1- // Shared building blocks for the Agent security commands (bl security *).
1+ // Shared building blocks for the Agent security commands (bl agents security *).
22//
33// AgentStudio uses the same per-workspace host scheme as the knowledge admin
44// plane, so the --workspace-id flag and its three-level resolver are reused
77import {
88 agentStudioHost ,
99 isDashScopeGateway ,
10+ type LocalizedText ,
1011 type SecurityAlert ,
1112 type SecurityOverview ,
1213 type SecurityToggle ,
@@ -36,33 +37,66 @@ export function resolveSecurityHost(ctx: {
3637 return agentStudioHost ( resolveWorkspaceId ( ctx ) ) ;
3738}
3839
39- // The API returns codes only — display names live here to match the console.
40- export const CAPABILITY_LABELS : Record < string , string > = {
41- agent_identity : "Agent 身份签发" ,
42- content_safety : "内容安全" ,
43- supply_chain_scan : "供应链静态扫描" ,
44- credential_isolation : "凭证隔离" ,
45- session_lifecycle : "session 生命周期治理" ,
40+ /** Locale selector supplied by the command context (`ctx.localize`). */
41+ export type Localize = ( text : LocalizedText ) => string ;
42+
43+ // The API returns codes only — display names live here to match the console,
44+ // localized to en-US / zh-CN per the resolved language.
45+ export const CAPABILITY_LABELS : Record < string , LocalizedText > = {
46+ agent_identity : { "en-US" : "Agent identity issuance" , "zh-CN" : "Agent 身份签发" } ,
47+ content_safety : { "en-US" : "Content safety" , "zh-CN" : "内容安全" } ,
48+ supply_chain_scan : { "en-US" : "Supply-chain static scan" , "zh-CN" : "供应链静态扫描" } ,
49+ credential_isolation : { "en-US" : "Credential isolation" , "zh-CN" : "凭证隔离" } ,
50+ session_lifecycle : { "en-US" : "Session lifecycle governance" , "zh-CN" : "session 生命周期治理" } ,
4651} ;
4752
4853// Protection entries are keyed by asset type; the doc lists only the codes, so
4954// the display names are maintained here.
50- export const PROTECTION_LABELS : Record < string , string > = {
51- flow_agent : " Flow Agent",
52- managed_agent : " Managed Agents",
53- knowledge_base : " RAG",
54- memory : " Memory",
55- mcp : " Store",
56- external_agent : " BYOA 托管",
55+ export const PROTECTION_LABELS : Record < string , LocalizedText > = {
56+ flow_agent : { "en-US" : " Flow Agent", "zh-CN" : "Flow Agent" } ,
57+ managed_agent : { "en-US" : " Managed Agents", "zh-CN" : "Managed Agents" } ,
58+ knowledge_base : { "en-US" : " RAG", "zh-CN" : "RAG" } ,
59+ memory : { "en-US" : " Memory", "zh-CN" : "Memory" } ,
60+ mcp : { "en-US" : " Store", "zh-CN" : "Store" } ,
61+ external_agent : { "en-US" : " BYOA hosting" , "zh-CN" : "BYOA 托管" } ,
5762} ;
5863
5964/** Detection cards summed into the overview banner: label + snake_case (REST) / camelCase (gateway) keys. */
60- export const SCAN_CARDS : Array < { label : string ; keys : Array < keyof SecurityOverview > } > = [
61- { label : "内容安全" , keys : [ "content_safety" , "contentSafety" ] } ,
62- { label : "文件扫描" , keys : [ "file_scan" , "fileScan" ] } ,
63- { label : "技能扫描" , keys : [ "skill_scan" , "skillScan" ] } ,
65+ export const SCAN_CARDS : Array < { label : LocalizedText ; keys : Array < keyof SecurityOverview > } > = [
66+ {
67+ label : { "en-US" : "Content safety" , "zh-CN" : "内容安全" } ,
68+ keys : [ "content_safety" , "contentSafety" ] ,
69+ } ,
70+ { label : { "en-US" : "File scan" , "zh-CN" : "文件扫描" } , keys : [ "file_scan" , "fileScan" ] } ,
71+ { label : { "en-US" : "Skill scan" , "zh-CN" : "技能扫描" } , keys : [ "skill_scan" , "skillScan" ] } ,
6472] ;
6573
74+ /** User-facing strings shared by the security commands, localized en-US / zh-CN. */
75+ export const SECURITY_UI = {
76+ unavailable : { "en-US" : "(unavailable)" , "zh-CN" : "(不可用)" } ,
77+ on : { "en-US" : "on" , "zh-CN" : "开启" } ,
78+ off : { "en-US" : "off" , "zh-CN" : "关闭" } ,
79+ scannedLabel : { "en-US" : "Scanned" , "zh-CN" : "扫描" } ,
80+ risksLabel : { "en-US" : "Risks" , "zh-CN" : "风险" } ,
81+ capabilities : { "en-US" : "Capabilities" , "zh-CN" : "能力项" } ,
82+ protection : { "en-US" : "Protection" , "zh-CN" : "防护项" } ,
83+ detections : { "en-US" : "Detections" , "zh-CN" : "检测项" } ,
84+ overviewUnavailable : { "en-US" : "Overview unavailable." , "zh-CN" : "总览不可用。" } ,
85+ hit : { "en-US" : "hit" , "zh-CN" : "命中" } ,
86+ scanned : { "en-US" : "scanned" , "zh-CN" : "扫描" } ,
87+ total : { "en-US" : "Total" , "zh-CN" : "总计" } ,
88+ high : { "en-US" : "high" , "zh-CN" : "高" } ,
89+ medium : { "en-US" : "medium" , "zh-CN" : "中" } ,
90+ low : { "en-US" : "low" , "zh-CN" : "低" } ,
91+ noAlerts : { "en-US" : "No alerts found." , "zh-CN" : "未找到告警。" } ,
92+ nextPageCursor : { "en-US" : "Next page cursor" , "zh-CN" : "下一页游标" } ,
93+ app : { "en-US" : "app" , "zh-CN" : "应用" } ,
94+ asset : { "en-US" : "asset" , "zh-CN" : "资产" } ,
95+ status : { "en-US" : "status" , "zh-CN" : "状态" } ,
96+ source : { "en-US" : "source" , "zh-CN" : "来源" } ,
97+ checked : { "en-US" : "checked" , "zh-CN" : "检测时间" } ,
98+ } satisfies Record < string , LocalizedText > ;
99+
66100/** Append a query param only when present; arrays append each item (repeatable). */
67101export function setSecurityParam (
68102 params : URLSearchParams ,
@@ -77,20 +111,23 @@ export function setSecurityParam(
77111 params . set ( key , String ( value ) ) ;
78112}
79113
80- /** Render a capability / protection toggle group; codes map to display names. */
114+ /** Render a capability / protection toggle group; codes map to localized display names. */
81115export function renderToggles (
82- title : string ,
116+ localize : Localize ,
117+ title : LocalizedText ,
83118 toggles : SecurityToggle [ ] | null | undefined ,
84- labels : Record < string , string > ,
119+ labels : Record < string , LocalizedText > ,
85120) : void {
86- emitBare ( `\n${ title } ` ) ;
121+ emitBare ( `\n${ localize ( title ) } ` ) ;
87122 if ( ! toggles || toggles . length === 0 ) {
88- emitBare ( " ( unavailable)" ) ;
123+ emitBare ( ` ${ localize ( SECURITY_UI . unavailable ) } ` ) ;
89124 return ;
90125 }
91126 for ( const toggle of toggles ) {
92127 const count = typeof toggle . count === "number" ? ` (${ toggle . count } )` : "" ;
93- emitBare ( ` ${ toggle . enabled ? "on " : "off" } ${ labels [ toggle . key ] ?? toggle . key } ${ count } ` ) ;
128+ const state = localize ( toggle . enabled ? SECURITY_UI . on : SECURITY_UI . off ) ;
129+ const label = labels [ toggle . key ] ? localize ( labels [ toggle . key ] ) : toggle . key ;
130+ emitBare ( ` ${ state } ${ label } ${ count } ` ) ;
94131 }
95132}
96133
@@ -102,15 +139,15 @@ export function formatSecurityTime(value: string | null | undefined): string {
102139 return new Date ( millis ) . toISOString ( ) . replace ( "T" , " " ) . slice ( 0 , 19 ) ;
103140}
104141
105- /** Render one alert row in text mode. */
106- export function renderAlert ( alert : SecurityAlert ) : void {
142+ /** Render one alert row in text mode; field labels are localized . */
143+ export function renderAlert ( localize : Localize , alert : SecurityAlert ) : void {
107144 const level = ( alert . risk_level ?? "unknown" ) . toUpperCase ( ) ;
108145 emitBare ( `[${ level } ] ${ alert . risk_name ?? "-" } (${ alert . alert_id } )` ) ;
109146 emitBare (
110- ` app: ${ alert . app_name ?? "-" } asset: ${ alert . asset_name ?? "-" } (${ alert . asset_type ?? "-" } )` ,
147+ ` ${ localize ( SECURITY_UI . app ) } : ${ alert . app_name ?? "-" } ${ localize ( SECURITY_UI . asset ) } : ${ alert . asset_name ?? "-" } (${ alert . asset_type ?? "-" } )` ,
111148 ) ;
112149 emitBare (
113- ` status: ${ alert . status ?? "-" } source: ${ alert . source ?? "-" } checked: ${ formatSecurityTime ( alert . check_time ) } ` ,
150+ ` ${ localize ( SECURITY_UI . status ) } : ${ alert . status ?? "-" } ${ localize ( SECURITY_UI . source ) } : ${ alert . source ?? "-" } ${ localize ( SECURITY_UI . checked ) } : ${ formatSecurityTime ( alert . check_time ) } ` ,
114151 ) ;
115152 if ( alert . risk_desc ) emitBare ( ` ${ alert . risk_desc } ` ) ;
116153 emitBare ( "" ) ;
0 commit comments