@ai-zen/cli 1.0.0-alpha.2 → 1.0.0-alpha.22

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (311) hide show
  1. package/CHANGELOG.md +514 -0
  2. package/README.md +136 -39
  3. package/README.zh.md +136 -39
  4. package/dist/agent-creator.d.ts +11 -0
  5. package/dist/agent-creator.d.ts.map +1 -1
  6. package/dist/agent-creator.js +52 -21
  7. package/dist/agent-creator.js.map +1 -1
  8. package/dist/agent-switch.d.ts +61 -0
  9. package/dist/agent-switch.d.ts.map +1 -0
  10. package/dist/agent-switch.js +83 -0
  11. package/dist/agent-switch.js.map +1 -0
  12. package/dist/agents-store.d.ts +6 -1
  13. package/dist/agents-store.d.ts.map +1 -1
  14. package/dist/agents-store.js +46 -4
  15. package/dist/agents-store.js.map +1 -1
  16. package/dist/auto-migrate-confirm.d.ts +43 -0
  17. package/dist/auto-migrate-confirm.d.ts.map +1 -0
  18. package/dist/auto-migrate-confirm.js +47 -0
  19. package/dist/auto-migrate-confirm.js.map +1 -0
  20. package/dist/config-editor.d.ts +13 -5
  21. package/dist/config-editor.d.ts.map +1 -1
  22. package/dist/config-editor.js +36 -27
  23. package/dist/config-editor.js.map +1 -1
  24. package/dist/config.d.ts +24 -3
  25. package/dist/config.d.ts.map +1 -1
  26. package/dist/config.js +55 -15
  27. package/dist/config.js.map +1 -1
  28. package/dist/conversation-commands/registry.d.ts +123 -4
  29. package/dist/conversation-commands/registry.d.ts.map +1 -1
  30. package/dist/conversation-commands/registry.js +92 -14
  31. package/dist/conversation-commands/registry.js.map +1 -1
  32. package/dist/conversation-persist-plugin.d.ts +0 -1
  33. package/dist/conversation-persist-plugin.d.ts.map +1 -1
  34. package/dist/conversation-persist-plugin.js +7 -16
  35. package/dist/conversation-persist-plugin.js.map +1 -1
  36. package/dist/conversation-repository.d.ts +71 -13
  37. package/dist/conversation-repository.d.ts.map +1 -1
  38. package/dist/conversation-repository.js +81 -24
  39. package/dist/conversation-repository.js.map +1 -1
  40. package/dist/cwd-tracker-plugin.d.ts.map +1 -1
  41. package/dist/cwd-tracker-plugin.js +6 -2
  42. package/dist/cwd-tracker-plugin.js.map +1 -1
  43. package/dist/format-time.d.ts +17 -6
  44. package/dist/format-time.d.ts.map +1 -1
  45. package/dist/format-time.js +32 -14
  46. package/dist/format-time.js.map +1 -1
  47. package/dist/handoff-service.d.ts +19 -0
  48. package/dist/handoff-service.d.ts.map +1 -0
  49. package/dist/handoff-service.js +89 -0
  50. package/dist/handoff-service.js.map +1 -0
  51. package/dist/hook.d.ts.map +1 -1
  52. package/dist/hook.js +69 -15
  53. package/dist/hook.js.map +1 -1
  54. package/dist/i18n/en-wizard.d.ts +8 -0
  55. package/dist/i18n/en-wizard.d.ts.map +1 -0
  56. package/dist/i18n/en-wizard.js +290 -0
  57. package/dist/i18n/en-wizard.js.map +1 -0
  58. package/dist/i18n/en.d.ts +7 -0
  59. package/dist/i18n/en.d.ts.map +1 -0
  60. package/dist/i18n/en.js +224 -0
  61. package/dist/i18n/en.js.map +1 -0
  62. package/dist/i18n/index.d.ts +57 -0
  63. package/dist/i18n/index.d.ts.map +1 -0
  64. package/dist/i18n/index.js +109 -0
  65. package/dist/i18n/index.js.map +1 -0
  66. package/dist/i18n/preferences.d.ts +34 -0
  67. package/dist/i18n/preferences.d.ts.map +1 -0
  68. package/dist/i18n/preferences.js +69 -0
  69. package/dist/i18n/preferences.js.map +1 -0
  70. package/dist/i18n/zh-wizard.d.ts +11 -0
  71. package/dist/i18n/zh-wizard.d.ts.map +1 -0
  72. package/dist/i18n/zh-wizard.js +293 -0
  73. package/dist/i18n/zh-wizard.js.map +1 -0
  74. package/dist/i18n/zh.d.ts +10 -0
  75. package/dist/i18n/zh.d.ts.map +1 -0
  76. package/dist/i18n/zh.js +228 -0
  77. package/dist/i18n/zh.js.map +1 -0
  78. package/dist/index.js +61 -25
  79. package/dist/index.js.map +1 -1
  80. package/dist/mcp-command.d.ts +32 -0
  81. package/dist/mcp-command.d.ts.map +1 -0
  82. package/dist/mcp-command.js +37 -0
  83. package/dist/mcp-command.js.map +1 -0
  84. package/dist/mode.d.ts +31 -4
  85. package/dist/mode.d.ts.map +1 -1
  86. package/dist/mode.js +42 -7
  87. package/dist/mode.js.map +1 -1
  88. package/dist/model-switch.d.ts +58 -0
  89. package/dist/model-switch.d.ts.map +1 -0
  90. package/dist/model-switch.js +62 -0
  91. package/dist/model-switch.js.map +1 -0
  92. package/dist/reasoning-effort.d.ts +96 -0
  93. package/dist/reasoning-effort.d.ts.map +1 -0
  94. package/dist/reasoning-effort.js +164 -0
  95. package/dist/reasoning-effort.js.map +1 -0
  96. package/dist/reasoning-presets.d.ts +34 -0
  97. package/dist/reasoning-presets.d.ts.map +1 -0
  98. package/dist/reasoning-presets.js +85 -0
  99. package/dist/reasoning-presets.js.map +1 -0
  100. package/dist/sdk-log.d.ts +55 -0
  101. package/dist/sdk-log.d.ts.map +1 -0
  102. package/dist/sdk-log.js +91 -0
  103. package/dist/sdk-log.js.map +1 -0
  104. package/dist/session-pointer.d.ts +22 -9
  105. package/dist/session-pointer.d.ts.map +1 -1
  106. package/dist/session-pointer.js +55 -23
  107. package/dist/session-pointer.js.map +1 -1
  108. package/dist/stdio-runner.d.ts.map +1 -1
  109. package/dist/stdio-runner.js +32 -30
  110. package/dist/stdio-runner.js.map +1 -1
  111. package/dist/sub-agent-guard-plugin.d.ts +5 -5
  112. package/dist/sub-agent-guard-plugin.d.ts.map +1 -1
  113. package/dist/sub-agent-guard-plugin.js +7 -7
  114. package/dist/sub-agent-guard-plugin.js.map +1 -1
  115. package/dist/tui/chat-session.d.ts +110 -59
  116. package/dist/tui/chat-session.d.ts.map +1 -1
  117. package/dist/tui/chat-session.js +268 -120
  118. package/dist/tui/chat-session.js.map +1 -1
  119. package/dist/tui/components.d.ts +48 -2
  120. package/dist/tui/components.d.ts.map +1 -1
  121. package/dist/tui/components.js +96 -3
  122. package/dist/tui/components.js.map +1 -1
  123. package/dist/tui/config-wizard/detail.d.ts +12 -6
  124. package/dist/tui/config-wizard/detail.d.ts.map +1 -1
  125. package/dist/tui/config-wizard/detail.js +33 -32
  126. package/dist/tui/config-wizard/detail.js.map +1 -1
  127. package/dist/tui/config-wizard/engine.d.ts.map +1 -1
  128. package/dist/tui/config-wizard/engine.js +27 -21
  129. package/dist/tui/config-wizard/engine.js.map +1 -1
  130. package/dist/tui/config-wizard/fields.d.ts +3 -1
  131. package/dist/tui/config-wizard/fields.d.ts.map +1 -1
  132. package/dist/tui/config-wizard/fields.js +216 -152
  133. package/dist/tui/config-wizard/fields.js.map +1 -1
  134. package/dist/tui/config-wizard/kv-editor.d.ts.map +1 -1
  135. package/dist/tui/config-wizard/kv-editor.js +9 -5
  136. package/dist/tui/config-wizard/kv-editor.js.map +1 -1
  137. package/dist/tui/config-wizard/list.d.ts.map +1 -1
  138. package/dist/tui/config-wizard/list.js +2 -1
  139. package/dist/tui/config-wizard/list.js.map +1 -1
  140. package/dist/tui/config-wizard/mcp-helpers.d.ts.map +1 -1
  141. package/dist/tui/config-wizard/mcp-helpers.js +4 -3
  142. package/dist/tui/config-wizard/mcp-helpers.js.map +1 -1
  143. package/dist/tui/config-wizard/menu.d.ts.map +1 -1
  144. package/dist/tui/config-wizard/menu.js +33 -21
  145. package/dist/tui/config-wizard/menu.js.map +1 -1
  146. package/dist/tui/config-wizard/prompt-editor.d.ts.map +1 -1
  147. package/dist/tui/config-wizard/prompt-editor.js +4 -3
  148. package/dist/tui/config-wizard/prompt-editor.js.map +1 -1
  149. package/dist/tui/config-wizard/prompt.d.ts.map +1 -1
  150. package/dist/tui/config-wizard/prompt.js +8 -7
  151. package/dist/tui/config-wizard/prompt.js.map +1 -1
  152. package/dist/tui/config-wizard/step-agents.d.ts.map +1 -1
  153. package/dist/tui/config-wizard/step-agents.js +29 -20
  154. package/dist/tui/config-wizard/step-agents.js.map +1 -1
  155. package/dist/tui/config-wizard/step-defaults.d.ts.map +1 -1
  156. package/dist/tui/config-wizard/step-defaults.js +24 -27
  157. package/dist/tui/config-wizard/step-defaults.js.map +1 -1
  158. package/dist/tui/config-wizard/step-endpoints.d.ts.map +1 -1
  159. package/dist/tui/config-wizard/step-endpoints.js +16 -6
  160. package/dist/tui/config-wizard/step-endpoints.js.map +1 -1
  161. package/dist/tui/config-wizard/step-mcp.d.ts.map +1 -1
  162. package/dist/tui/config-wizard/step-mcp.js +17 -19
  163. package/dist/tui/config-wizard/step-mcp.js.map +1 -1
  164. package/dist/tui/config-wizard/step-models.d.ts.map +1 -1
  165. package/dist/tui/config-wizard/step-models.js +41 -26
  166. package/dist/tui/config-wizard/step-models.js.map +1 -1
  167. package/dist/tui/config-wizard/step-new-endpoint.d.ts.map +1 -1
  168. package/dist/tui/config-wizard/step-new-endpoint.js +16 -12
  169. package/dist/tui/config-wizard/step-new-endpoint.js.map +1 -1
  170. package/dist/tui/config-wizard/step-simple.d.ts.map +1 -1
  171. package/dist/tui/config-wizard/step-simple.js +18 -17
  172. package/dist/tui/config-wizard/step-simple.js.map +1 -1
  173. package/dist/tui/config-wizard/types.d.ts +18 -3
  174. package/dist/tui/config-wizard/types.d.ts.map +1 -1
  175. package/dist/tui/config-wizard/wizard.d.ts.map +1 -1
  176. package/dist/tui/config-wizard/wizard.js +4 -3
  177. package/dist/tui/config-wizard/wizard.js.map +1 -1
  178. package/dist/tui/highlight.d.ts +3 -2
  179. package/dist/tui/highlight.d.ts.map +1 -1
  180. package/dist/tui/highlight.js +3 -2
  181. package/dist/tui/highlight.js.map +1 -1
  182. package/dist/tui/index.d.ts +18 -1
  183. package/dist/tui/index.d.ts.map +1 -1
  184. package/dist/tui/index.js +107 -49
  185. package/dist/tui/index.js.map +1 -1
  186. package/dist/tui/input-editing.d.ts +52 -0
  187. package/dist/tui/input-editing.d.ts.map +1 -0
  188. package/dist/tui/input-editing.js +91 -0
  189. package/dist/tui/input-editing.js.map +1 -0
  190. package/dist/tui/key-debug.d.ts +62 -0
  191. package/dist/tui/key-debug.d.ts.map +1 -0
  192. package/dist/tui/key-debug.js +92 -0
  193. package/dist/tui/key-debug.js.map +1 -0
  194. package/dist/tui/mouse.d.ts +55 -0
  195. package/dist/tui/mouse.d.ts.map +1 -0
  196. package/dist/tui/mouse.js +74 -0
  197. package/dist/tui/mouse.js.map +1 -0
  198. package/dist/tui/phase.d.ts +64 -0
  199. package/dist/tui/phase.d.ts.map +1 -0
  200. package/dist/tui/phase.js +112 -0
  201. package/dist/tui/phase.js.map +1 -0
  202. package/dist/tui/screens/chat-commands.d.ts +64 -3
  203. package/dist/tui/screens/chat-commands.d.ts.map +1 -1
  204. package/dist/tui/screens/chat-commands.js +483 -157
  205. package/dist/tui/screens/chat-commands.js.map +1 -1
  206. package/dist/tui/screens/chat.d.ts +10 -5
  207. package/dist/tui/screens/chat.d.ts.map +1 -1
  208. package/dist/tui/screens/chat.js +464 -301
  209. package/dist/tui/screens/chat.js.map +1 -1
  210. package/dist/tui/screens/common-keys.d.ts +36 -0
  211. package/dist/tui/screens/common-keys.d.ts.map +1 -0
  212. package/dist/tui/screens/common-keys.js +67 -0
  213. package/dist/tui/screens/common-keys.js.map +1 -0
  214. package/dist/tui/screens/frame-buffer.d.ts +47 -0
  215. package/dist/tui/screens/frame-buffer.d.ts.map +1 -0
  216. package/dist/tui/screens/frame-buffer.js +78 -0
  217. package/dist/tui/screens/frame-buffer.js.map +1 -0
  218. package/dist/tui/screens/handoff-choice.d.ts +37 -0
  219. package/dist/tui/screens/handoff-choice.d.ts.map +1 -0
  220. package/dist/tui/screens/handoff-choice.js +42 -0
  221. package/dist/tui/screens/handoff-choice.js.map +1 -0
  222. package/dist/tui/screens/index.d.ts +8 -8
  223. package/dist/tui/screens/index.d.ts.map +1 -1
  224. package/dist/tui/screens/index.js +7 -7
  225. package/dist/tui/screens/index.js.map +1 -1
  226. package/dist/tui/screens/input-row.d.ts +64 -0
  227. package/dist/tui/screens/input-row.d.ts.map +1 -0
  228. package/dist/tui/screens/input-row.js +67 -0
  229. package/dist/tui/screens/input-row.js.map +1 -0
  230. package/dist/tui/screens/input.d.ts +46 -1
  231. package/dist/tui/screens/input.d.ts.map +1 -1
  232. package/dist/tui/screens/input.js +83 -8
  233. package/dist/tui/screens/input.js.map +1 -1
  234. package/dist/tui/screens/layout.d.ts +21 -3
  235. package/dist/tui/screens/layout.d.ts.map +1 -1
  236. package/dist/tui/screens/layout.js +20 -9
  237. package/dist/tui/screens/layout.js.map +1 -1
  238. package/dist/tui/screens/lines.d.ts +12 -41
  239. package/dist/tui/screens/lines.d.ts.map +1 -1
  240. package/dist/tui/screens/lines.js +90 -98
  241. package/dist/tui/screens/lines.js.map +1 -1
  242. package/dist/tui/screens/messages-view.d.ts +10 -0
  243. package/dist/tui/screens/messages-view.d.ts.map +1 -0
  244. package/dist/tui/screens/messages-view.js +116 -0
  245. package/dist/tui/screens/messages-view.js.map +1 -0
  246. package/dist/tui/screens/notice-bar.d.ts +5 -0
  247. package/dist/tui/screens/notice-bar.d.ts.map +1 -0
  248. package/dist/tui/screens/notice-bar.js +15 -0
  249. package/dist/tui/screens/notice-bar.js.map +1 -0
  250. package/dist/tui/screens/notice.d.ts +64 -0
  251. package/dist/tui/screens/notice.d.ts.map +1 -0
  252. package/dist/tui/screens/notice.js +106 -0
  253. package/dist/tui/screens/notice.js.map +1 -0
  254. package/dist/tui/screens/overlays.d.ts.map +1 -1
  255. package/dist/tui/screens/overlays.js +3 -2
  256. package/dist/tui/screens/overlays.js.map +1 -1
  257. package/dist/tui/screens/render.d.ts +2 -4
  258. package/dist/tui/screens/render.d.ts.map +1 -1
  259. package/dist/tui/screens/render.js +7 -43
  260. package/dist/tui/screens/render.js.map +1 -1
  261. package/dist/tui/screens/splash.d.ts +1 -1
  262. package/dist/tui/screens/splash.d.ts.map +1 -1
  263. package/dist/tui/screens/splash.js +12 -3
  264. package/dist/tui/screens/splash.js.map +1 -1
  265. package/dist/tui/screens/use-chat-viewport.d.ts +22 -0
  266. package/dist/tui/screens/use-chat-viewport.d.ts.map +1 -0
  267. package/dist/tui/screens/use-chat-viewport.js +50 -0
  268. package/dist/tui/screens/use-chat-viewport.js.map +1 -0
  269. package/dist/tui/screens/use-input-editing.d.ts +44 -0
  270. package/dist/tui/screens/use-input-editing.d.ts.map +1 -0
  271. package/dist/tui/screens/use-input-editing.js +192 -0
  272. package/dist/tui/screens/use-input-editing.js.map +1 -0
  273. package/dist/tui/screens/use-overlays.d.ts +25 -0
  274. package/dist/tui/screens/use-overlays.d.ts.map +1 -0
  275. package/dist/tui/screens/use-overlays.js +32 -0
  276. package/dist/tui/screens/use-overlays.js.map +1 -0
  277. package/dist/tui/screens/use-wizard-host.d.ts +35 -0
  278. package/dist/tui/screens/use-wizard-host.d.ts.map +1 -0
  279. package/dist/tui/screens/use-wizard-host.js +103 -0
  280. package/dist/tui/screens/use-wizard-host.js.map +1 -0
  281. package/dist/tui/status-segments.d.ts +37 -0
  282. package/dist/tui/status-segments.d.ts.map +1 -0
  283. package/dist/tui/status-segments.js +166 -0
  284. package/dist/tui/status-segments.js.map +1 -0
  285. package/dist/tui/text.d.ts +20 -7
  286. package/dist/tui/text.d.ts.map +1 -1
  287. package/dist/tui/text.js +111 -37
  288. package/dist/tui/text.js.map +1 -1
  289. package/dist/tui/theme.d.ts +7 -1
  290. package/dist/tui/theme.d.ts.map +1 -1
  291. package/dist/tui/theme.js +15 -3
  292. package/dist/tui/theme.js.map +1 -1
  293. package/dist/tui/token-rate.d.ts +83 -0
  294. package/dist/tui/token-rate.d.ts.map +1 -0
  295. package/dist/tui/token-rate.js +195 -0
  296. package/dist/tui/token-rate.js.map +1 -0
  297. package/dist/types.d.ts +7 -8
  298. package/dist/types.d.ts.map +1 -1
  299. package/package.json +4 -3
  300. package/dist/auto-migrate-confirm-plugin.d.ts +0 -58
  301. package/dist/auto-migrate-confirm-plugin.d.ts.map +0 -1
  302. package/dist/auto-migrate-confirm-plugin.js +0 -61
  303. package/dist/auto-migrate-confirm-plugin.js.map +0 -1
  304. package/dist/migration-service.d.ts +0 -15
  305. package/dist/migration-service.d.ts.map +0 -1
  306. package/dist/migration-service.js +0 -59
  307. package/dist/migration-service.js.map +0 -1
  308. package/dist/tui/screens/state.d.ts +0 -13
  309. package/dist/tui/screens/state.d.ts.map +0 -1
  310. package/dist/tui/screens/state.js +0 -75
  311. package/dist/tui/screens/state.js.map +0 -1
@@ -1,38 +1,78 @@
1
1
  import { agentKindLabel, agentList } from "../../agents-store.js";
2
- import { findEndpoint, findModel, formatAgentPermission, formatArgs, getAgentPrompt, kvSummary, maskApiKey, mcpServerIdTaken, parseArgs, parsePermission, PERMISSION_DIMENSIONS, renameMcpServer, setAgentPermission, summarizePermissions, updateAgentDefinition, updateAgentFunction, updateEndpoint, updateImageModel, updateMcpServer, updateModel } from "../../config-editor.js";
2
+ import { findEndpoint, findModel, formatAgentPermission, formatArgs, getAgentPrompt, kvSummary, maskApiKey, mcpServerIdTaken, mergeTokenThresholds, parseArgs, parsePermission, PERMISSION_DIMENSIONS, renameMcpServer, setAgentPermission, summarizePermissions, updateAgentDefinition, updateAgentFunction, updateEndpoint, updateImageModel, updateMcpServer, updateModel } from "../../config-editor.js";
3
+ import { t } from "../../i18n/index.js";
3
4
  import { scopeLabel } from "./mcp-helpers.js";
5
+ /**
6
+ * 权限四维的显示名。
7
+ *
8
+ * 维度名(`tools` / `skills` / …)是配置里的键,直接上屏等于把内部标识暴露给用户;
9
+ * 这里映射到词条,`Record<PermissionDimension, …>` 保证四个维度都有对应文案。
10
+ */
11
+ const PERMISSION_DIMENSION_LABEL_KEY = {
12
+ tools: "perm.tools",
13
+ skills: "perm.skills",
14
+ mcps: "perm.mcps",
15
+ subagents: "perm.subagents",
16
+ };
4
17
  // 由 src/tui/config-wizard.tsx 拆分而来 —— 详情屏字段构造器(工厂)
5
18
  /** 多行文本在详情屏的**单行摘要**(避免换行撑破吸底布局);内容一律走外部编辑器编辑 */
6
19
  function summarizeMultiline(text) {
7
20
  const body = text.replace(/\r\n/g, "\n").trim();
8
21
  if (!body)
9
- return "(空)· Enter 打开编辑器";
22
+ return t("common.emptyWithEditor");
10
23
  const lines = body.split("\n");
11
- return lines.length > 1 ? `${lines.length} 行 · Enter 打开编辑器` : `${body} · Enter 打开编辑器`;
24
+ return lines.length > 1
25
+ ? t("common.linesWithEditor", { n: lines.length })
26
+ : t("common.bodyWithEditor", { text: body });
12
27
  }
13
28
  export function createFieldBuilders(context) {
14
- const { config, mcp, store, persist, persistMcp, saveAgent, removeAgentQuiet, go } = context;
15
- // ---------- 字段构造器 ----------
29
+ const { config, mcp, store, reasoningPresets, persist, persistMcp, saveAgent, removeAgentQuiet, go } = context;
30
+ // ---------- 共享字段 ----------
31
+ /**
32
+ * 「名称」字段:端点 / 模型 / 图片模型三处的形状逐字相同,只有写回目标不同。
33
+ * 空名称一律拦下 —— 名称会进提示语与列表,写空等于把这一条「弄丢」。
34
+ */
35
+ const nameField = (current, save) => ({
36
+ key: "name",
37
+ label: t("field.name"),
38
+ kind: "text",
39
+ value: current.name || current.id,
40
+ initial: current.name,
41
+ commit: (raw) => (raw.trim() ? save({ name: raw.trim() }, t("field.name")) : t("err.nameRequired")),
42
+ });
43
+ /** 「绑定端点」字段:模型 / 图片模型共用,选项是全局端点表 */
44
+ const endpointIdField = (currentEndpointId, save) => ({
45
+ key: "endpointId",
46
+ label: t("field.endpoint"),
47
+ kind: "enum",
48
+ value: findEndpoint(config, currentEndpointId)?.name ?? currentEndpointId,
49
+ options: config.endpoints.map((endpoint) => ({ label: endpoint.name || endpoint.id, value: endpoint.id })),
50
+ // 选回原端点不算改动:否则会白白写盘一次
51
+ commit: (raw) => (raw === currentEndpointId ? null : save({ endpointId: raw }, t("field.endpoint"))),
52
+ });
53
+ /**
54
+ * 出厂托管条目的改动标记。
55
+ *
56
+ * 托管条目由 SDK 同步维护,**任何本地改动都必须打成 `custom: true`**,否则下次
57
+ * 同步会把改动覆盖掉。提示语后缀同步告知用户这一后果。
58
+ */
59
+ const customPatch = (entity, patch) => entity.custom ? patch : { ...patch, custom: true };
60
+ /** 同上,用于「整份定义」写回(如 Agent 定义):返回完整对象 */
61
+ const markCustom = (entity) => entity.custom ? entity : { ...entity, custom: true };
62
+ const customNote = (managed) => (managed ? t("common.customOnlyNote") : "");
16
63
  /** 端点详情字段(editable:名称 / Base URL / API Key / 描述) */
17
64
  const endpointFields = (endpoint) => {
18
65
  const name = endpoint.name || endpoint.id;
19
- const save = (patch, label) => persist(updateEndpoint(config, endpoint.id, patch), `端点 ${name} 的 ${label} 已更新`, [endpoint.id]);
66
+ const save = (patch, label) => persist(updateEndpoint(config, endpoint.id, patch), t("wiz.endpointUpdated", { name, label }), [endpoint.id]);
20
67
  return [
21
- {
22
- key: "name",
23
- label: "名称",
24
- kind: "text",
25
- value: name,
26
- initial: endpoint.name,
27
- commit: (raw) => (raw.trim() ? save({ name: raw.trim() }, "名称") : Promise.resolve("名称不能为空")),
28
- },
68
+ nameField(endpoint, save),
29
69
  {
30
70
  key: "baseUrl",
31
71
  label: "Base URL",
32
72
  kind: "text",
33
73
  value: endpoint.baseUrl,
34
74
  initial: endpoint.baseUrl,
35
- commit: (raw) => /^https?:\/\//i.test(raw) ? save({ baseUrl: raw }, "Base URL") : Promise.resolve("Base URL 需以 http:// 或 https:// 开头"),
75
+ commit: (raw) => /^https?:\/\//i.test(raw) ? save({ baseUrl: raw }, "Base URL") : t("err.baseUrlScheme"),
36
76
  },
37
77
  {
38
78
  key: "apiKey",
@@ -40,165 +80,189 @@ export function createFieldBuilders(context) {
40
80
  kind: "secret",
41
81
  value: maskApiKey(endpoint.apiKey),
42
82
  initial: endpoint.apiKey ?? "",
43
- commit: (raw) => (raw ? save({ apiKey: raw }, "API Key") : Promise.resolve("API Key 不能为空")),
83
+ commit: (raw) => (raw ? save({ apiKey: raw }, "API Key") : t("err.apiKeyRequired")),
44
84
  },
45
85
  {
46
86
  key: "description",
47
- label: "描述",
87
+ label: t("field.description"),
48
88
  kind: "text",
49
- value: endpoint.description ?? "(空)",
89
+ value: endpoint.description ?? t("common.empty"),
50
90
  initial: endpoint.description ?? "",
51
- commit: (raw) => save({ description: raw || undefined }, "描述"),
91
+ commit: (raw) => save({ description: raw || undefined }, t("field.description")),
52
92
  },
53
93
  ];
54
94
  };
95
+ /** 模型详情页「思考策略」的展示文案:附上该策略的档位,免得用户还得去翻 JSON */
96
+ const describePreset = (name) => {
97
+ if (!name)
98
+ return t("common.notAdjustable");
99
+ const preset = Object.prototype.hasOwnProperty.call(reasoningPresets, name)
100
+ ? reasoningPresets[name]
101
+ : undefined;
102
+ const levels = Object.keys(preset?.levels ?? {});
103
+ return levels.length
104
+ ? t("wiz.presetLevels", { name, levels: levels.join(" / ") })
105
+ : t("wiz.presetMissingName", { name });
106
+ };
55
107
  /** 模型详情字段;编辑「出厂托管」模型时自动标记 `custom: true`(否则改动会被 SDK 同步覆盖) */
56
108
  const modelFields = (model) => {
57
109
  const managed = !model.custom;
58
- const save = (patch, label) => {
59
- const next = updateModel(config, model.id, managed ? { ...patch, custom: true } : patch);
60
- const suffix = managed ? "(已标记为自定义,改动才会保留)" : "";
61
- return persist(next, `模型 ${model.name || model.id} 的 ${label} 已更新${suffix}`, [model.endpointId]);
62
- };
110
+ const save = (patch, label) => persist(updateModel(config, model.id, customPatch(model, patch)), t("wiz.modelUpdated", { name: model.name || model.id, label, suffix: customNote(managed) }), [model.endpointId]);
63
111
  return [
112
+ nameField(model, save),
113
+ endpointIdField(model.endpointId, save),
64
114
  {
65
- key: "name",
66
- label: "名称",
115
+ key: "modelName",
116
+ label: t("field.modelName"),
67
117
  kind: "text",
68
- value: model.name || model.id,
69
- initial: model.name,
70
- commit: (raw) => (raw.trim() ? save({ name: raw.trim() }, "名称") : Promise.resolve("名称不能为空")),
118
+ value: model.modelName ?? t("common.sameAsId"),
119
+ initial: model.modelName ?? "",
120
+ commit: (raw) => save({ modelName: raw || undefined }, t("field.modelName")),
71
121
  },
72
122
  {
73
- key: "endpointId",
74
- label: "端点",
75
- kind: "enum",
76
- value: findEndpoint(config, model.endpointId)?.name ?? model.endpointId,
77
- options: config.endpoints.map((endpoint) => ({ label: endpoint.name || endpoint.id, value: endpoint.id })),
78
- commit: (raw) => (raw === model.endpointId ? Promise.resolve(null) : save({ endpointId: raw }, "端点")),
123
+ key: "reasoningPreset",
124
+ label: t("field.reasoningPreset"),
125
+ kind: "text",
126
+ value: describePreset(model.reasoningPreset),
127
+ initial: model.reasoningPreset ?? "",
128
+ commit: (raw) => {
129
+ const name = raw.trim();
130
+ if (!name)
131
+ return save({ reasoningPreset: undefined }, t("field.reasoningPreset"));
132
+ // 名字写错等于静默失去调档能力,当场拦住
133
+ if (!Object.prototype.hasOwnProperty.call(reasoningPresets, name)) {
134
+ const available = Object.keys(reasoningPresets);
135
+ return available.length
136
+ ? t("err.presetNotFound", { name, options: available.join(" / ") })
137
+ : t("err.presetTableEmpty", { name });
138
+ }
139
+ return save({ reasoningPreset: name }, t("field.reasoningPreset"));
140
+ },
79
141
  },
80
142
  {
81
- key: "modelName",
82
- label: "模型名",
83
- kind: "text",
84
- value: model.modelName ?? "(同 id)",
85
- initial: model.modelName ?? "",
86
- commit: (raw) => save({ modelName: raw || undefined }, "模型名"),
143
+ key: "handoffTokens",
144
+ label: t("field.handoffThreshold"),
145
+ kind: "number",
146
+ value: String(model.tokenThresholds?.handoff ?? 0),
147
+ initial: String(model.tokenThresholds?.handoff ?? 0),
148
+ commit: (raw) => {
149
+ const n = Number(raw.trim());
150
+ if (!Number.isFinite(n) || n <= 0)
151
+ return t("err.handoffPositive");
152
+ const guard = model.tokenThresholds?.guard ?? 0;
153
+ // 软线不得越过硬线,否则一启动就被阻断
154
+ if (guard > 0 && Math.floor(n) >= guard)
155
+ return t("err.handoffLessThanGuard");
156
+ return save({ tokenThresholds: mergeTokenThresholds(model.tokenThresholds, { handoff: Math.floor(n) }) }, t("field.handoffThreshold"));
157
+ },
87
158
  },
88
159
  {
89
- key: "maxContextTokens",
90
- label: "迁移阈值",
160
+ key: "guardTokens",
161
+ label: t("field.guardThreshold"),
91
162
  kind: "number",
92
- value: String(model.maxContextTokens ?? 0),
93
- initial: String(model.maxContextTokens ?? 0),
163
+ value: String(model.tokenThresholds?.guard ?? 0),
164
+ initial: String(model.tokenThresholds?.guard ?? 0),
94
165
  commit: (raw) => {
95
166
  const n = Number(raw.trim());
96
- return Number.isFinite(n) && n > 0 ? save({ maxContextTokens: Math.floor(n) }, "迁移阈值") : Promise.resolve("迁移阈值需为正整数");
167
+ if (!Number.isFinite(n) || n <= 0)
168
+ return t("err.guardPositive");
169
+ const handoff = model.tokenThresholds?.handoff ?? 0;
170
+ if (Math.floor(n) <= handoff)
171
+ return t("err.guardGreaterThanHandoff");
172
+ return save({ tokenThresholds: mergeTokenThresholds(model.tokenThresholds, { guard: Math.floor(n) }) }, t("field.guardThreshold"));
97
173
  },
98
174
  },
99
175
  {
100
176
  key: "vision",
101
- label: "视觉",
177
+ label: t("field.vision"),
102
178
  kind: "bool",
103
- value: model.vision ? "是" : "否",
104
- toggle: () => save({ vision: !model.vision }, "视觉"),
179
+ value: model.vision ? t("common.yes") : t("common.no"),
180
+ toggle: () => save({ vision: !model.vision }, t("field.vision")),
105
181
  },
106
182
  {
107
183
  key: "description",
108
- label: "描述",
184
+ label: t("field.description"),
109
185
  kind: "text",
110
- value: model.description ?? "(空)",
186
+ value: model.description ?? t("common.empty"),
111
187
  initial: model.description ?? "",
112
- commit: (raw) => save({ description: raw || undefined }, "描述"),
188
+ commit: (raw) => save({ description: raw || undefined }, t("field.description")),
113
189
  },
114
190
  {
115
191
  key: "custom",
116
- label: "自定义",
192
+ label: t("field.custom"),
117
193
  kind: "bool",
118
- value: model.custom ? "是" : "否(出厂托管)",
119
- toggle: () => persist(updateModel(config, model.id, { custom: !model.custom }), `模型 ${model.name || model.id} 的「自定义」已设为 ${!model.custom ? "是" : "否"}`, [model.endpointId]),
194
+ value: model.custom ? t("common.yes") : t("common.factoryManaged"),
195
+ toggle: () => persist(updateModel(config, model.id, { custom: !model.custom }), t("wiz.modelCustomSet", {
196
+ name: model.name || model.id,
197
+ value: !model.custom ? t("common.yes") : t("common.no"),
198
+ }), [model.endpointId]),
120
199
  },
121
200
  ];
122
201
  };
123
202
  /** 图片模型详情字段(同样对托管条目自动标记 `custom: true`) */
124
203
  const imageModelFields = (model) => {
125
204
  const managed = !model.custom;
126
- const save = (patch, label) => {
127
- const next = updateImageModel(config, model.id, managed ? { ...patch, custom: true } : patch);
128
- const suffix = managed ? "(已标记为自定义,改动才会保留)" : "";
129
- return persist(next, `图片模型 ${model.name || model.id} 的 ${label} 已更新${suffix}`, [model.endpointId]);
130
- };
205
+ const save = (patch, label) => persist(updateImageModel(config, model.id, customPatch(model, patch)), t("wiz.imageModelUpdated", { name: model.name || model.id, label, suffix: customNote(managed) }), [model.endpointId]);
131
206
  return [
132
- {
133
- key: "name",
134
- label: "名称",
135
- kind: "text",
136
- value: model.name || model.id,
137
- initial: model.name,
138
- commit: (raw) => (raw.trim() ? save({ name: raw.trim() }, "名称") : Promise.resolve("名称不能为空")),
139
- },
140
- {
141
- key: "endpointId",
142
- label: "端点",
143
- kind: "enum",
144
- value: findEndpoint(config, model.endpointId)?.name ?? model.endpointId,
145
- options: config.endpoints.map((endpoint) => ({ label: endpoint.name || endpoint.id, value: endpoint.id })),
146
- commit: (raw) => (raw === model.endpointId ? Promise.resolve(null) : save({ endpointId: raw }, "端点")),
147
- },
207
+ nameField(model, save),
208
+ endpointIdField(model.endpointId, save),
148
209
  {
149
210
  key: "modelName",
150
- label: "模型名",
211
+ label: t("field.modelName"),
151
212
  kind: "text",
152
213
  value: model.modelName,
153
214
  initial: model.modelName,
154
- commit: (raw) => (raw.trim() ? save({ modelName: raw.trim() }, "模型名") : Promise.resolve("模型名不能为空")),
215
+ commit: (raw) => (raw.trim() ? save({ modelName: raw.trim() }, t("field.modelName")) : t("err.modelNameRequired")),
155
216
  },
156
217
  {
157
218
  key: "defaultSize",
158
- label: "尺寸",
219
+ label: t("field.size"),
159
220
  kind: "text",
160
- value: model.defaultSize ?? "(默认)",
221
+ value: model.defaultSize ?? t("common.defaultInParens"),
161
222
  initial: model.defaultSize ?? "",
162
- commit: (raw) => save({ defaultSize: raw || undefined }, "尺寸"),
223
+ commit: (raw) => save({ defaultSize: raw || undefined }, t("field.size")),
163
224
  },
164
225
  {
165
226
  key: "defaultQuality",
166
- label: "质量",
227
+ label: t("field.quality"),
167
228
  kind: "text",
168
- value: model.defaultQuality ?? "(默认)",
229
+ value: model.defaultQuality ?? t("common.defaultInParens"),
169
230
  initial: model.defaultQuality ?? "",
170
- commit: (raw) => save({ defaultQuality: raw || undefined }, "质量"),
231
+ commit: (raw) => save({ defaultQuality: raw || undefined }, t("field.quality")),
171
232
  },
172
233
  {
173
234
  key: "custom",
174
- label: "自定义",
235
+ label: t("field.custom"),
175
236
  kind: "bool",
176
- value: model.custom ? "是" : "否(出厂托管)",
177
- toggle: () => persist(updateImageModel(config, model.id, { custom: !model.custom }), `图片模型 ${model.name || model.id} 的「自定义」已设为 ${!model.custom ? "是" : "否"}`, [model.endpointId]),
237
+ value: model.custom ? t("common.yes") : t("common.factoryManaged"),
238
+ toggle: () => persist(updateImageModel(config, model.id, { custom: !model.custom }), t("wiz.imageModelCustomSet", {
239
+ name: model.name || model.id,
240
+ value: !model.custom ? t("common.yes") : t("common.no"),
241
+ }), [model.endpointId]),
178
242
  },
179
243
  ];
180
244
  };
181
245
  /** MCP 服务器详情字段(依 transport 呈现 stdio 或 http/sse 字段) */
182
246
  const mcpServerFields = (scope, id, entry) => {
183
247
  const scopeName = scopeLabel(scope);
184
- const save = (patch, label) => persistMcp(scope, updateMcpServer(mcp[scope], id, patch), `MCP ${id} 的${label}已更新(${scopeName})`);
248
+ const save = (patch, label) => persistMcp(scope, updateMcpServer(mcp[scope], id, patch), t("wiz.mcpFieldUpdated", { id, label, scope: scopeName }));
185
249
  const type = entry.type ?? "stdio";
186
250
  const fields = [
187
251
  {
188
252
  key: "id",
189
- label: "名称",
253
+ label: t("field.name"),
190
254
  kind: "text",
191
255
  value: id,
192
256
  initial: id,
193
257
  commit: (raw) => {
194
258
  const name = raw.trim();
195
259
  if (!name)
196
- return Promise.resolve("名称不能为空");
260
+ return t("err.nameRequired");
197
261
  if (name === id)
198
- return Promise.resolve(null);
262
+ return null;
199
263
  if (mcpServerIdTaken(mcp[scope], name, id))
200
- return Promise.resolve(`已存在名为 ${name} 的服务器`);
201
- return persistMcp(scope, renameMcpServer(mcp[scope], id, name), `MCP ${id} 已重命名为 ${name}(${scopeName})`).then((failure) => {
264
+ return t("err.mcpNameTaken", { name });
265
+ return persistMcp(scope, renameMcpServer(mcp[scope], id, name), t("wiz.mcpRenamed", { id, name, scope: scopeName })).then((failure) => {
202
266
  if (!failure)
203
267
  go({ kind: "mcp-server", scope, serverId: name });
204
268
  return failure;
@@ -207,54 +271,54 @@ export function createFieldBuilders(context) {
207
271
  },
208
272
  {
209
273
  key: "type",
210
- label: "传输",
274
+ label: t("field.transport"),
211
275
  kind: "enum",
212
276
  value: type,
213
277
  options: [
214
- { label: "stdio(本地子进程)", value: "stdio" },
215
- { label: "http(Streamable HTTP)", value: "http" },
216
- { label: "sse(Server-Sent Events)", value: "sse" },
278
+ { label: t("common.transportStdio"), value: "stdio" },
279
+ { label: t("common.transportHttp"), value: "http" },
280
+ { label: t("common.transportSse"), value: "sse" },
217
281
  ],
218
- commit: (raw) => raw === type ? Promise.resolve(null) : save({ type: raw }, "传输方式"),
282
+ commit: (raw) => raw === type ? null : save({ type: raw }, t("common.transportMode")),
219
283
  },
220
284
  {
221
285
  key: "enabled",
222
- label: "启用",
286
+ label: t("field.enabled"),
223
287
  kind: "bool",
224
- value: entry.disabled === true ? "否(已禁用)" : "是",
225
- toggle: () => save({ disabled: entry.disabled === true ? undefined : true }, "启用状态"),
288
+ value: entry.disabled === true ? t("common.disabledInParens") : t("common.yes"),
289
+ toggle: () => save({ disabled: entry.disabled === true ? undefined : true }, t("common.enabledState")),
226
290
  },
227
291
  {
228
292
  key: "description",
229
- label: "描述",
293
+ label: t("field.description"),
230
294
  kind: "text",
231
- value: entry.description ?? "(空)",
295
+ value: entry.description ?? t("common.empty"),
232
296
  initial: entry.description ?? "",
233
- commit: (raw) => save({ description: raw.trim() || undefined }, "描述"),
297
+ commit: (raw) => save({ description: raw.trim() || undefined }, t("field.description")),
234
298
  },
235
299
  ];
236
300
  if (type === "stdio") {
237
301
  fields.push({
238
302
  key: "command",
239
- label: "命令",
303
+ label: t("field.command"),
240
304
  kind: "text",
241
- value: entry.command ?? "(空)",
305
+ value: entry.command ?? t("common.empty"),
242
306
  initial: entry.command ?? "",
243
- commit: (raw) => save({ command: raw.trim() || undefined }, "命令"),
307
+ commit: (raw) => save({ command: raw.trim() || undefined }, t("field.command")),
244
308
  }, {
245
309
  key: "args",
246
- label: "参数",
310
+ label: t("field.args"),
247
311
  kind: "text",
248
- value: formatArgs(entry.args) || "(空)",
312
+ value: formatArgs(entry.args) || t("common.empty"),
249
313
  initial: formatArgs(entry.args),
250
314
  commit: (raw) => {
251
315
  const args = parseArgs(raw.trim());
252
- return save({ args: args.length ? args : undefined }, "参数");
316
+ return save({ args: args.length ? args : undefined }, t("field.args"));
253
317
  },
254
318
  }, {
255
319
  key: "env",
256
- label: "环境变量",
257
- kind: "map",
320
+ label: t("field.env"),
321
+ kind: "open",
258
322
  value: kvSummary(entry.env),
259
323
  open: () => go({ kind: "mcp-kv", scope, serverId: id, field: "env" }),
260
324
  });
@@ -264,13 +328,13 @@ export function createFieldBuilders(context) {
264
328
  key: "url",
265
329
  label: "URL",
266
330
  kind: "text",
267
- value: entry.url ?? "(空)",
331
+ value: entry.url ?? t("common.empty"),
268
332
  initial: entry.url ?? "",
269
333
  commit: (raw) => save({ url: raw.trim() || undefined }, "URL"),
270
334
  }, {
271
335
  key: "headers",
272
- label: "请求头",
273
- kind: "map",
336
+ label: t("field.headers"),
337
+ kind: "open",
274
338
  value: kvSummary(entry.headers),
275
339
  open: () => go({ kind: "mcp-kv", scope, serverId: id, field: "headers" }),
276
340
  });
@@ -282,37 +346,37 @@ export function createFieldBuilders(context) {
282
346
  const kindName = agentKindLabel(kind);
283
347
  const managed = kind === "agent" && !def.custom;
284
348
  const save = (nextDef, label) => {
285
- const marked = managed ? { ...nextDef, custom: true } : nextDef;
286
- const suffix = managed ? "(已标记为自定义,改动才会保留)" : "";
287
- return saveAgent(kind, marked, `${kindName} ${def.id} 的 ${label} 已更新${suffix}`);
349
+ const marked = markCustom(nextDef);
350
+ const suffix = customNote(managed);
351
+ return saveAgent(kind, marked, t("wiz.agentFieldUpdated", { kind: kindName, id: def.id, label, suffix }));
288
352
  };
289
353
  const fields = [
290
354
  {
291
355
  key: "name",
292
- label: "名称",
356
+ label: t("field.name"),
293
357
  kind: "text",
294
358
  value: def.name || def.id,
295
359
  initial: def.name,
296
360
  commit: (raw) => raw.trim()
297
- ? save(updateAgentDefinition(def, { name: raw.trim() }), "名称")
298
- : Promise.resolve("名称不能为空"),
361
+ ? save(updateAgentDefinition(def, { name: raw.trim() }), t("field.name"))
362
+ : t("err.nameRequired"),
299
363
  },
300
364
  {
301
365
  key: "id",
302
- label: "标识",
366
+ label: t("field.id"),
303
367
  kind: "text",
304
368
  value: def.id,
305
369
  initial: def.id,
306
370
  commit: (raw) => {
307
371
  const name = raw.trim();
308
372
  if (!name)
309
- return Promise.resolve("标识不能为空");
373
+ return t("err.idRequired");
310
374
  if (name === def.id)
311
- return Promise.resolve(null);
375
+ return null;
312
376
  if (agentList(store, kind).some((item) => item.id === name))
313
- return Promise.resolve(`已存在标识 ${name} 的定义`);
377
+ return t("err.agentIdTaken", { name });
314
378
  return (async () => {
315
- const failure = await saveAgent(kind, { ...def, id: name }, `${kindName} ${def.id} 已重命名为 ${name}`);
379
+ const failure = await saveAgent(kind, { ...def, id: name }, t("wiz.agentRenamed", { kind: kindName, id: def.id, name }));
316
380
  if (failure)
317
381
  return failure;
318
382
  await removeAgentQuiet(kind, def.id);
@@ -323,34 +387,34 @@ export function createFieldBuilders(context) {
323
387
  },
324
388
  {
325
389
  key: "description",
326
- label: "描述",
390
+ label: t("field.description"),
327
391
  kind: "text",
328
- value: def.description ?? "(空)",
392
+ value: def.description ?? t("common.empty"),
329
393
  initial: def.description ?? "",
330
- commit: (raw) => save(updateAgentDefinition(def, { description: raw.trim() || undefined }), "描述"),
394
+ commit: (raw) => save(updateAgentDefinition(def, { description: raw.trim() || undefined }), t("field.description")),
331
395
  },
332
396
  {
333
397
  key: "modelId",
334
- label: "模型",
398
+ label: t("field.model"),
335
399
  kind: "enum",
336
- value: findModel(config, def.modelId)?.name ?? def.modelId ?? "(未设置)",
400
+ value: findModel(config, def.modelId)?.name ?? def.modelId ?? t("common.unset"),
337
401
  options: [
338
402
  ...config.models.map((model) => ({ label: model.name || model.id, value: model.id })),
339
- { label: "(未设置)", value: "" },
403
+ { label: t("common.unset"), value: "" },
340
404
  ],
341
- commit: (raw) => save(updateAgentDefinition(def, { modelId: raw || undefined }), "模型"),
405
+ commit: (raw) => save(updateAgentDefinition(def, { modelId: raw || undefined }), t("field.model")),
342
406
  },
343
407
  {
344
408
  key: "prompt",
345
- label: "提示词",
346
- kind: "map",
409
+ label: t("field.prompt"),
410
+ kind: "open",
347
411
  value: summarizeMultiline(getAgentPrompt(def)),
348
412
  open: () => go({ kind: "agent-text", agentKind: kind, agentId: def.id, field: "prompt" }),
349
413
  },
350
414
  {
351
415
  key: "permissions",
352
- label: "权限",
353
- kind: "map",
416
+ label: t("field.permissions"),
417
+ kind: "open",
354
418
  value: summarizePermissions(def.permissions),
355
419
  open: () => go({ kind: "agent-perms", agentKind: kind, agentId: def.id }),
356
420
  },
@@ -358,32 +422,32 @@ export function createFieldBuilders(context) {
358
422
  if (kind === "agent") {
359
423
  fields.push({
360
424
  key: "custom",
361
- label: "自定义",
425
+ label: t("field.custom"),
362
426
  kind: "bool",
363
- value: def.custom ? "是" : "否(出厂托管)",
364
- toggle: () => save(updateAgentDefinition(def, { custom: !def.custom }), "「自定义」"),
427
+ value: def.custom ? t("common.yes") : t("common.factoryManaged"),
428
+ toggle: () => save(updateAgentDefinition(def, { custom: !def.custom }), t("common.customQuoted")),
365
429
  });
366
430
  }
367
431
  else {
368
432
  fields.push({
369
433
  key: "fnName",
370
- label: "函数名",
434
+ label: t("field.functionName"),
371
435
  kind: "text",
372
- value: def.function?.name ?? "(空)",
436
+ value: def.function?.name ?? t("common.empty"),
373
437
  initial: def.function?.name ?? "",
374
438
  commit: (raw) => raw.trim()
375
- ? save(updateAgentFunction(def, { name: raw.trim() }), "函数名")
376
- : Promise.resolve("函数名不能为空"),
439
+ ? save(updateAgentFunction(def, { name: raw.trim() }), t("field.functionName"))
440
+ : t("err.functionNameRequired"),
377
441
  }, {
378
442
  key: "fnDesc",
379
- label: "函数说明",
380
- kind: "map",
443
+ label: t("field.functionDescription"),
444
+ kind: "open",
381
445
  value: summarizeMultiline(def.function?.description ?? ""),
382
446
  open: () => go({ kind: "agent-text", agentKind: kind, agentId: def.id, field: "fnDesc" }),
383
447
  }, {
384
448
  key: "fnParams",
385
- label: "参数 schema",
386
- kind: "map",
449
+ label: t("field.paramsSchema"),
450
+ kind: "open",
387
451
  value: summarizeMultiline(JSON.stringify(def.function?.parameters ?? {}, null, 2)),
388
452
  open: () => go({ kind: "agent-text", agentKind: kind, agentId: def.id, field: "fnParams" }),
389
453
  });
@@ -393,17 +457,17 @@ export function createFieldBuilders(context) {
393
457
  /** 四维权限子屏字段(`allow: a, b` / `deny: x`;留空清除该维) */
394
458
  const agentPermFields = (kind, def) => PERMISSION_DIMENSIONS.map((dim) => ({
395
459
  key: dim,
396
- label: dim,
460
+ label: t(PERMISSION_DIMENSION_LABEL_KEY[dim]),
397
461
  kind: "text",
398
- value: formatAgentPermission(def.permissions, dim) || "(未设置)",
462
+ value: formatAgentPermission(def.permissions, dim) || t("common.unset"),
399
463
  initial: formatAgentPermission(def.permissions, dim),
400
464
  commit: (raw) => {
401
465
  const parsed = parsePermission(raw);
402
466
  if (typeof parsed === "string")
403
- return Promise.resolve(parsed);
467
+ return parsed;
404
468
  const managed = kind === "agent" && !def.custom;
405
469
  const next = setAgentPermission(managed ? { ...def, custom: true } : def, dim, parsed);
406
- return saveAgent(kind, next, `${agentKindLabel(kind)} ${def.id} 的 ${dim} 权限已更新`);
470
+ return saveAgent(kind, next, t("wiz.agentPermissionUpdated", { kind: agentKindLabel(kind), id: def.id, dim }));
407
471
  },
408
472
  }));
409
473
  return { endpointFields, modelFields, imageModelFields, mcpServerFields, agentFields, agentPermFields };