@ai-zen/cli 1.0.0-alpha.9 → 1.0.0

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 (336) hide show
  1. package/CHANGELOG.md +1334 -275
  2. package/LICENSE +21 -0
  3. package/README.md +136 -31
  4. package/README.zh.md +136 -31
  5. package/dist/agent-creator.d.ts +11 -0
  6. package/dist/agent-creator.d.ts.map +1 -1
  7. package/dist/agent-creator.js +50 -20
  8. package/dist/agent-creator.js.map +1 -1
  9. package/dist/agent-switch.d.ts +61 -0
  10. package/dist/agent-switch.d.ts.map +1 -0
  11. package/dist/agent-switch.js +83 -0
  12. package/dist/agent-switch.js.map +1 -0
  13. package/dist/agents-store.d.ts +6 -1
  14. package/dist/agents-store.d.ts.map +1 -1
  15. package/dist/agents-store.js +46 -4
  16. package/dist/agents-store.js.map +1 -1
  17. package/dist/auto-migrate-confirm.d.ts +43 -0
  18. package/dist/auto-migrate-confirm.d.ts.map +1 -0
  19. package/dist/auto-migrate-confirm.js +47 -0
  20. package/dist/auto-migrate-confirm.js.map +1 -0
  21. package/dist/clipboard.d.ts +68 -0
  22. package/dist/clipboard.d.ts.map +1 -0
  23. package/dist/clipboard.js +177 -0
  24. package/dist/clipboard.js.map +1 -0
  25. package/dist/config-editor.d.ts +42 -5
  26. package/dist/config-editor.d.ts.map +1 -1
  27. package/dist/config-editor.js +80 -27
  28. package/dist/config-editor.js.map +1 -1
  29. package/dist/config.d.ts +76 -17
  30. package/dist/config.d.ts.map +1 -1
  31. package/dist/config.js +143 -39
  32. package/dist/config.js.map +1 -1
  33. package/dist/conversation-commands/registry.d.ts +127 -4
  34. package/dist/conversation-commands/registry.d.ts.map +1 -1
  35. package/dist/conversation-commands/registry.js +93 -14
  36. package/dist/conversation-commands/registry.js.map +1 -1
  37. package/dist/conversation-persist-plugin.d.ts +0 -1
  38. package/dist/conversation-persist-plugin.d.ts.map +1 -1
  39. package/dist/conversation-persist-plugin.js +7 -16
  40. package/dist/conversation-persist-plugin.js.map +1 -1
  41. package/dist/conversation-repository.d.ts +79 -18
  42. package/dist/conversation-repository.d.ts.map +1 -1
  43. package/dist/conversation-repository.js +96 -30
  44. package/dist/conversation-repository.js.map +1 -1
  45. package/dist/cwd-tracker-plugin.d.ts.map +1 -1
  46. package/dist/cwd-tracker-plugin.js +22 -7
  47. package/dist/cwd-tracker-plugin.js.map +1 -1
  48. package/dist/format-time.d.ts +17 -6
  49. package/dist/format-time.d.ts.map +1 -1
  50. package/dist/format-time.js +32 -14
  51. package/dist/format-time.js.map +1 -1
  52. package/dist/handoff-service.d.ts +19 -0
  53. package/dist/handoff-service.d.ts.map +1 -0
  54. package/dist/handoff-service.js +85 -0
  55. package/dist/handoff-service.js.map +1 -0
  56. package/dist/hook.d.ts.map +1 -1
  57. package/dist/hook.js +69 -15
  58. package/dist/hook.js.map +1 -1
  59. package/dist/i18n/en-wizard.d.ts +8 -0
  60. package/dist/i18n/en-wizard.d.ts.map +1 -0
  61. package/dist/i18n/en-wizard.js +303 -0
  62. package/dist/i18n/en-wizard.js.map +1 -0
  63. package/dist/i18n/en.d.ts +7 -0
  64. package/dist/i18n/en.d.ts.map +1 -0
  65. package/dist/i18n/en.js +245 -0
  66. package/dist/i18n/en.js.map +1 -0
  67. package/dist/i18n/index.d.ts +57 -0
  68. package/dist/i18n/index.d.ts.map +1 -0
  69. package/dist/i18n/index.js +109 -0
  70. package/dist/i18n/index.js.map +1 -0
  71. package/dist/i18n/preferences.d.ts +37 -0
  72. package/dist/i18n/preferences.d.ts.map +1 -0
  73. package/dist/i18n/preferences.js +73 -0
  74. package/dist/i18n/preferences.js.map +1 -0
  75. package/dist/i18n/zh-wizard.d.ts +11 -0
  76. package/dist/i18n/zh-wizard.d.ts.map +1 -0
  77. package/dist/i18n/zh-wizard.js +306 -0
  78. package/dist/i18n/zh-wizard.js.map +1 -0
  79. package/dist/i18n/zh.d.ts +10 -0
  80. package/dist/i18n/zh.d.ts.map +1 -0
  81. package/dist/i18n/zh.js +249 -0
  82. package/dist/i18n/zh.js.map +1 -0
  83. package/dist/index.js +52 -23
  84. package/dist/index.js.map +1 -1
  85. package/dist/mcp-command.d.ts +32 -0
  86. package/dist/mcp-command.d.ts.map +1 -0
  87. package/dist/mcp-command.js +37 -0
  88. package/dist/mcp-command.js.map +1 -0
  89. package/dist/mode.d.ts +31 -4
  90. package/dist/mode.d.ts.map +1 -1
  91. package/dist/mode.js +42 -7
  92. package/dist/mode.js.map +1 -1
  93. package/dist/model-switch.d.ts +58 -0
  94. package/dist/model-switch.d.ts.map +1 -0
  95. package/dist/model-switch.js +62 -0
  96. package/dist/model-switch.js.map +1 -0
  97. package/dist/reasoning-effort.d.ts +96 -0
  98. package/dist/reasoning-effort.d.ts.map +1 -0
  99. package/dist/reasoning-effort.js +164 -0
  100. package/dist/reasoning-effort.js.map +1 -0
  101. package/dist/reasoning-presets.d.ts +34 -0
  102. package/dist/reasoning-presets.d.ts.map +1 -0
  103. package/dist/reasoning-presets.js +85 -0
  104. package/dist/reasoning-presets.js.map +1 -0
  105. package/dist/sdk-log.d.ts +84 -0
  106. package/dist/sdk-log.d.ts.map +1 -0
  107. package/dist/sdk-log.js +167 -0
  108. package/dist/sdk-log.js.map +1 -0
  109. package/dist/session-pointer.d.ts.map +1 -1
  110. package/dist/session-pointer.js +10 -4
  111. package/dist/session-pointer.js.map +1 -1
  112. package/dist/stdio-runner.d.ts.map +1 -1
  113. package/dist/stdio-runner.js +32 -30
  114. package/dist/stdio-runner.js.map +1 -1
  115. package/dist/sub-agent-guard-plugin.d.ts +10 -7
  116. package/dist/sub-agent-guard-plugin.d.ts.map +1 -1
  117. package/dist/sub-agent-guard-plugin.js +12 -9
  118. package/dist/sub-agent-guard-plugin.js.map +1 -1
  119. package/dist/tui/chat-history.d.ts +29 -0
  120. package/dist/tui/chat-history.d.ts.map +1 -0
  121. package/dist/tui/chat-history.js +55 -0
  122. package/dist/tui/chat-history.js.map +1 -0
  123. package/dist/tui/chat-session.d.ts +144 -13
  124. package/dist/tui/chat-session.d.ts.map +1 -1
  125. package/dist/tui/chat-session.js +312 -73
  126. package/dist/tui/chat-session.js.map +1 -1
  127. package/dist/tui/components.d.ts +109 -6
  128. package/dist/tui/components.d.ts.map +1 -1
  129. package/dist/tui/components.js +177 -12
  130. package/dist/tui/components.js.map +1 -1
  131. package/dist/tui/config-wizard/detail.d.ts +18 -10
  132. package/dist/tui/config-wizard/detail.d.ts.map +1 -1
  133. package/dist/tui/config-wizard/detail.js +53 -46
  134. package/dist/tui/config-wizard/detail.js.map +1 -1
  135. package/dist/tui/config-wizard/engine.d.ts +2 -2
  136. package/dist/tui/config-wizard/engine.d.ts.map +1 -1
  137. package/dist/tui/config-wizard/engine.js +48 -26
  138. package/dist/tui/config-wizard/engine.js.map +1 -1
  139. package/dist/tui/config-wizard/fields.d.ts +3 -1
  140. package/dist/tui/config-wizard/fields.d.ts.map +1 -1
  141. package/dist/tui/config-wizard/fields.js +202 -167
  142. package/dist/tui/config-wizard/fields.js.map +1 -1
  143. package/dist/tui/config-wizard/frame.js +1 -1
  144. package/dist/tui/config-wizard/kv-editor.d.ts.map +1 -1
  145. package/dist/tui/config-wizard/kv-editor.js +13 -5
  146. package/dist/tui/config-wizard/kv-editor.js.map +1 -1
  147. package/dist/tui/config-wizard/list.d.ts +3 -1
  148. package/dist/tui/config-wizard/list.d.ts.map +1 -1
  149. package/dist/tui/config-wizard/list.js +4 -4
  150. package/dist/tui/config-wizard/list.js.map +1 -1
  151. package/dist/tui/config-wizard/mcp-helpers.d.ts.map +1 -1
  152. package/dist/tui/config-wizard/mcp-helpers.js +4 -3
  153. package/dist/tui/config-wizard/mcp-helpers.js.map +1 -1
  154. package/dist/tui/config-wizard/menu.d.ts.map +1 -1
  155. package/dist/tui/config-wizard/menu.js +33 -21
  156. package/dist/tui/config-wizard/menu.js.map +1 -1
  157. package/dist/tui/config-wizard/prompt-editor.d.ts +8 -1
  158. package/dist/tui/config-wizard/prompt-editor.d.ts.map +1 -1
  159. package/dist/tui/config-wizard/prompt-editor.js +11 -7
  160. package/dist/tui/config-wizard/prompt-editor.js.map +1 -1
  161. package/dist/tui/config-wizard/prompt.d.ts.map +1 -1
  162. package/dist/tui/config-wizard/prompt.js +8 -7
  163. package/dist/tui/config-wizard/prompt.js.map +1 -1
  164. package/dist/tui/config-wizard/step-agents.d.ts.map +1 -1
  165. package/dist/tui/config-wizard/step-agents.js +50 -29
  166. package/dist/tui/config-wizard/step-agents.js.map +1 -1
  167. package/dist/tui/config-wizard/step-defaults.d.ts.map +1 -1
  168. package/dist/tui/config-wizard/step-defaults.js +77 -27
  169. package/dist/tui/config-wizard/step-defaults.js.map +1 -1
  170. package/dist/tui/config-wizard/step-endpoints.d.ts.map +1 -1
  171. package/dist/tui/config-wizard/step-endpoints.js +27 -14
  172. package/dist/tui/config-wizard/step-endpoints.js.map +1 -1
  173. package/dist/tui/config-wizard/step-mcp.d.ts.map +1 -1
  174. package/dist/tui/config-wizard/step-mcp.js +29 -25
  175. package/dist/tui/config-wizard/step-mcp.js.map +1 -1
  176. package/dist/tui/config-wizard/step-models.d.ts.map +1 -1
  177. package/dist/tui/config-wizard/step-models.js +98 -43
  178. package/dist/tui/config-wizard/step-models.js.map +1 -1
  179. package/dist/tui/config-wizard/step-new-endpoint.d.ts.map +1 -1
  180. package/dist/tui/config-wizard/step-new-endpoint.js +16 -12
  181. package/dist/tui/config-wizard/step-new-endpoint.js.map +1 -1
  182. package/dist/tui/config-wizard/step-simple.d.ts.map +1 -1
  183. package/dist/tui/config-wizard/step-simple.js +18 -17
  184. package/dist/tui/config-wizard/step-simple.js.map +1 -1
  185. package/dist/tui/config-wizard/types.d.ts +31 -3
  186. package/dist/tui/config-wizard/types.d.ts.map +1 -1
  187. package/dist/tui/config-wizard/types.js.map +1 -1
  188. package/dist/tui/file-index.d.ts +38 -0
  189. package/dist/tui/file-index.d.ts.map +1 -0
  190. package/dist/tui/file-index.js +117 -0
  191. package/dist/tui/file-index.js.map +1 -0
  192. package/dist/tui/index.d.ts +17 -1
  193. package/dist/tui/index.d.ts.map +1 -1
  194. package/dist/tui/index.js +105 -49
  195. package/dist/tui/index.js.map +1 -1
  196. package/dist/tui/input-editing.d.ts +52 -0
  197. package/dist/tui/input-editing.d.ts.map +1 -0
  198. package/dist/tui/input-editing.js +91 -0
  199. package/dist/tui/input-editing.js.map +1 -0
  200. package/dist/tui/key-debug.d.ts +62 -0
  201. package/dist/tui/key-debug.d.ts.map +1 -0
  202. package/dist/tui/key-debug.js +92 -0
  203. package/dist/tui/key-debug.js.map +1 -0
  204. package/dist/tui/mention.d.ts +47 -0
  205. package/dist/tui/mention.d.ts.map +1 -0
  206. package/dist/tui/mention.js +152 -0
  207. package/dist/tui/mention.js.map +1 -0
  208. package/dist/tui/mouse.d.ts +55 -0
  209. package/dist/tui/mouse.d.ts.map +1 -0
  210. package/dist/tui/mouse.js +74 -0
  211. package/dist/tui/mouse.js.map +1 -0
  212. package/dist/tui/phase.d.ts +64 -0
  213. package/dist/tui/phase.d.ts.map +1 -0
  214. package/dist/tui/phase.js +112 -0
  215. package/dist/tui/phase.js.map +1 -0
  216. package/dist/tui/screens/agent-tabs.d.ts +53 -0
  217. package/dist/tui/screens/agent-tabs.d.ts.map +1 -0
  218. package/dist/tui/screens/agent-tabs.js +81 -0
  219. package/dist/tui/screens/agent-tabs.js.map +1 -0
  220. package/dist/tui/screens/chat-commands.d.ts +78 -1
  221. package/dist/tui/screens/chat-commands.d.ts.map +1 -1
  222. package/dist/tui/screens/chat-commands.js +688 -157
  223. package/dist/tui/screens/chat-commands.js.map +1 -1
  224. package/dist/tui/screens/chat.d.ts +57 -1
  225. package/dist/tui/screens/chat.d.ts.map +1 -1
  226. package/dist/tui/screens/chat.js +708 -261
  227. package/dist/tui/screens/chat.js.map +1 -1
  228. package/dist/tui/screens/common-keys.d.ts +36 -0
  229. package/dist/tui/screens/common-keys.d.ts.map +1 -0
  230. package/dist/tui/screens/common-keys.js +67 -0
  231. package/dist/tui/screens/common-keys.js.map +1 -0
  232. package/dist/tui/screens/frame-buffer.d.ts.map +1 -1
  233. package/dist/tui/screens/frame-buffer.js.map +1 -1
  234. package/dist/tui/screens/handoff-choice.d.ts +37 -0
  235. package/dist/tui/screens/handoff-choice.d.ts.map +1 -0
  236. package/dist/tui/screens/handoff-choice.js +42 -0
  237. package/dist/tui/screens/handoff-choice.js.map +1 -0
  238. package/dist/tui/screens/index.d.ts +7 -5
  239. package/dist/tui/screens/index.d.ts.map +1 -1
  240. package/dist/tui/screens/index.js +6 -5
  241. package/dist/tui/screens/index.js.map +1 -1
  242. package/dist/tui/screens/input-row.d.ts +64 -0
  243. package/dist/tui/screens/input-row.d.ts.map +1 -0
  244. package/dist/tui/screens/input-row.js +67 -0
  245. package/dist/tui/screens/input-row.js.map +1 -0
  246. package/dist/tui/screens/input.d.ts +77 -1
  247. package/dist/tui/screens/input.d.ts.map +1 -1
  248. package/dist/tui/screens/input.js +125 -8
  249. package/dist/tui/screens/input.js.map +1 -1
  250. package/dist/tui/screens/layout.d.ts +49 -0
  251. package/dist/tui/screens/layout.d.ts.map +1 -1
  252. package/dist/tui/screens/layout.js +45 -7
  253. package/dist/tui/screens/layout.js.map +1 -1
  254. package/dist/tui/screens/lines.d.ts +7 -0
  255. package/dist/tui/screens/lines.d.ts.map +1 -1
  256. package/dist/tui/screens/lines.js +6 -6
  257. package/dist/tui/screens/lines.js.map +1 -1
  258. package/dist/tui/screens/messages-view.d.ts +20 -1
  259. package/dist/tui/screens/messages-view.d.ts.map +1 -1
  260. package/dist/tui/screens/messages-view.js +55 -8
  261. package/dist/tui/screens/messages-view.js.map +1 -1
  262. package/dist/tui/screens/notice-bar.d.ts +5 -0
  263. package/dist/tui/screens/notice-bar.d.ts.map +1 -0
  264. package/dist/tui/screens/notice-bar.js +21 -0
  265. package/dist/tui/screens/notice-bar.js.map +1 -0
  266. package/dist/tui/screens/notice.d.ts +44 -10
  267. package/dist/tui/screens/notice.d.ts.map +1 -1
  268. package/dist/tui/screens/notice.js +75 -15
  269. package/dist/tui/screens/notice.js.map +1 -1
  270. package/dist/tui/screens/overlays.d.ts.map +1 -1
  271. package/dist/tui/screens/overlays.js +4 -3
  272. package/dist/tui/screens/overlays.js.map +1 -1
  273. package/dist/tui/screens/render.d.ts +1 -1
  274. package/dist/tui/screens/render.d.ts.map +1 -1
  275. package/dist/tui/screens/render.js +18 -11
  276. package/dist/tui/screens/render.js.map +1 -1
  277. package/dist/tui/screens/use-chat-viewport.d.ts +22 -0
  278. package/dist/tui/screens/use-chat-viewport.d.ts.map +1 -0
  279. package/dist/tui/screens/use-chat-viewport.js +50 -0
  280. package/dist/tui/screens/use-chat-viewport.js.map +1 -0
  281. package/dist/tui/screens/use-input-editing.d.ts +69 -0
  282. package/dist/tui/screens/use-input-editing.d.ts.map +1 -0
  283. package/dist/tui/screens/use-input-editing.js +220 -0
  284. package/dist/tui/screens/use-input-editing.js.map +1 -0
  285. package/dist/tui/screens/use-overlays.d.ts +25 -0
  286. package/dist/tui/screens/use-overlays.d.ts.map +1 -0
  287. package/dist/tui/screens/use-overlays.js +32 -0
  288. package/dist/tui/screens/use-overlays.js.map +1 -0
  289. package/dist/tui/screens/use-wizard-host.d.ts +46 -0
  290. package/dist/tui/screens/use-wizard-host.d.ts.map +1 -0
  291. package/dist/tui/screens/use-wizard-host.js +123 -0
  292. package/dist/tui/screens/use-wizard-host.js.map +1 -0
  293. package/dist/tui/screens/welcome.d.ts +12 -0
  294. package/dist/tui/screens/welcome.d.ts.map +1 -0
  295. package/dist/tui/screens/welcome.js +36 -0
  296. package/dist/tui/screens/welcome.js.map +1 -0
  297. package/dist/tui/status-segments.d.ts +37 -0
  298. package/dist/tui/status-segments.d.ts.map +1 -0
  299. package/dist/tui/status-segments.js +166 -0
  300. package/dist/tui/status-segments.js.map +1 -0
  301. package/dist/tui/text.d.ts +22 -7
  302. package/dist/tui/text.d.ts.map +1 -1
  303. package/dist/tui/text.js +110 -39
  304. package/dist/tui/text.js.map +1 -1
  305. package/dist/tui/theme.d.ts +2 -0
  306. package/dist/tui/theme.d.ts.map +1 -1
  307. package/dist/tui/theme.js +2 -0
  308. package/dist/tui/theme.js.map +1 -1
  309. package/dist/tui/token-rate.d.ts +83 -0
  310. package/dist/tui/token-rate.d.ts.map +1 -0
  311. package/dist/tui/token-rate.js +195 -0
  312. package/dist/tui/token-rate.js.map +1 -0
  313. package/dist/types.d.ts +7 -8
  314. package/dist/types.d.ts.map +1 -1
  315. package/dist/user-content.d.ts +41 -0
  316. package/dist/user-content.d.ts.map +1 -0
  317. package/dist/user-content.js +37 -0
  318. package/dist/user-content.js.map +1 -0
  319. package/dist/version-compare.d.ts +37 -0
  320. package/dist/version-compare.d.ts.map +1 -0
  321. package/dist/version-compare.js +105 -0
  322. package/dist/version-compare.js.map +1 -0
  323. package/dist/version.js.map +1 -1
  324. package/package.json +7 -5
  325. package/dist/auto-migrate-confirm-plugin.d.ts +0 -58
  326. package/dist/auto-migrate-confirm-plugin.d.ts.map +0 -1
  327. package/dist/auto-migrate-confirm-plugin.js +0 -61
  328. package/dist/auto-migrate-confirm-plugin.js.map +0 -1
  329. package/dist/migration-service.d.ts +0 -15
  330. package/dist/migration-service.d.ts.map +0 -1
  331. package/dist/migration-service.js +0 -66
  332. package/dist/migration-service.js.map +0 -1
  333. package/dist/tui/screens/splash.d.ts +0 -5
  334. package/dist/tui/screens/splash.d.ts.map +0 -1
  335. package/dist/tui/screens/splash.js +0 -51
  336. package/dist/tui/screens/splash.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,169 @@ 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 }, "描述"),
113
- },
114
- {
115
- key: "custom",
116
- label: "自定义",
117
- kind: "bool",
118
- value: model.custom ? "是" : "否(出厂托管)",
119
- toggle: () => persist(updateModel(config, model.id, { custom: !model.custom }), `模型 ${model.name || model.id} 的「自定义」已设为 ${!model.custom ? "是" : "否"}`, [model.endpointId]),
188
+ commit: (raw) => save({ description: raw || undefined }, t("field.description")),
120
189
  },
121
190
  ];
122
191
  };
123
192
  /** 图片模型详情字段(同样对托管条目自动标记 `custom: true`) */
124
193
  const imageModelFields = (model) => {
125
194
  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
- };
195
+ 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
196
  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
- },
197
+ nameField(model, save),
198
+ endpointIdField(model.endpointId, save),
148
199
  {
149
200
  key: "modelName",
150
- label: "模型名",
201
+ label: t("field.modelName"),
151
202
  kind: "text",
152
203
  value: model.modelName,
153
204
  initial: model.modelName,
154
- commit: (raw) => (raw.trim() ? save({ modelName: raw.trim() }, "模型名") : Promise.resolve("模型名不能为空")),
205
+ commit: (raw) => (raw.trim() ? save({ modelName: raw.trim() }, t("field.modelName")) : t("err.modelNameRequired")),
155
206
  },
156
207
  {
157
208
  key: "defaultSize",
158
- label: "尺寸",
209
+ label: t("field.size"),
159
210
  kind: "text",
160
- value: model.defaultSize ?? "(默认)",
211
+ value: model.defaultSize ?? t("common.defaultInParens"),
161
212
  initial: model.defaultSize ?? "",
162
- commit: (raw) => save({ defaultSize: raw || undefined }, "尺寸"),
213
+ commit: (raw) => save({ defaultSize: raw || undefined }, t("field.size")),
163
214
  },
164
215
  {
165
216
  key: "defaultQuality",
166
- label: "质量",
217
+ label: t("field.quality"),
167
218
  kind: "text",
168
- value: model.defaultQuality ?? "(默认)",
219
+ value: model.defaultQuality ?? t("common.defaultInParens"),
169
220
  initial: model.defaultQuality ?? "",
170
- commit: (raw) => save({ defaultQuality: raw || undefined }, "质量"),
171
- },
172
- {
173
- key: "custom",
174
- label: "自定义",
175
- kind: "bool",
176
- value: model.custom ? "是" : "否(出厂托管)",
177
- toggle: () => persist(updateImageModel(config, model.id, { custom: !model.custom }), `图片模型 ${model.name || model.id} 的「自定义」已设为 ${!model.custom ? "是" : "否"}`, [model.endpointId]),
221
+ commit: (raw) => save({ defaultQuality: raw || undefined }, t("field.quality")),
178
222
  },
179
223
  ];
180
224
  };
181
225
  /** MCP 服务器详情字段(依 transport 呈现 stdio 或 http/sse 字段) */
182
226
  const mcpServerFields = (scope, id, entry) => {
183
227
  const scopeName = scopeLabel(scope);
184
- const save = (patch, label) => persistMcp(scope, updateMcpServer(mcp[scope], id, patch), `MCP ${id} 的${label}已更新(${scopeName})`);
228
+ const save = (patch, label) => persistMcp(scope, updateMcpServer(mcp[scope], id, patch), t("wiz.mcpFieldUpdated", { id, label, scope: scopeName }));
185
229
  const type = entry.type ?? "stdio";
186
230
  const fields = [
187
231
  {
188
232
  key: "id",
189
- label: "名称",
233
+ label: t("field.name"),
190
234
  kind: "text",
191
235
  value: id,
192
236
  initial: id,
193
237
  commit: (raw) => {
194
238
  const name = raw.trim();
195
239
  if (!name)
196
- return Promise.resolve("名称不能为空");
240
+ return t("err.nameRequired");
197
241
  if (name === id)
198
- return Promise.resolve(null);
242
+ return null;
199
243
  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) => {
244
+ return t("err.mcpNameTaken", { name });
245
+ return persistMcp(scope, renameMcpServer(mcp[scope], id, name), t("wiz.mcpRenamed", { id, name, scope: scopeName })).then((failure) => {
202
246
  if (!failure)
203
247
  go({ kind: "mcp-server", scope, serverId: name });
204
248
  return failure;
@@ -207,54 +251,54 @@ export function createFieldBuilders(context) {
207
251
  },
208
252
  {
209
253
  key: "type",
210
- label: "传输",
254
+ label: t("field.transport"),
211
255
  kind: "enum",
212
256
  value: type,
213
257
  options: [
214
- { label: "stdio(本地子进程)", value: "stdio" },
215
- { label: "http(Streamable HTTP)", value: "http" },
216
- { label: "sse(Server-Sent Events)", value: "sse" },
258
+ { label: t("common.transportStdio"), value: "stdio" },
259
+ { label: t("common.transportHttp"), value: "http" },
260
+ { label: t("common.transportSse"), value: "sse" },
217
261
  ],
218
- commit: (raw) => raw === type ? Promise.resolve(null) : save({ type: raw }, "传输方式"),
262
+ commit: (raw) => raw === type ? null : save({ type: raw }, t("common.transportMode")),
219
263
  },
220
264
  {
221
265
  key: "enabled",
222
- label: "启用",
266
+ label: t("field.enabled"),
223
267
  kind: "bool",
224
- value: entry.disabled === true ? "否(已禁用)" : "是",
225
- toggle: () => save({ disabled: entry.disabled === true ? undefined : true }, "启用状态"),
268
+ value: entry.disabled === true ? t("common.disabledInParens") : t("common.yes"),
269
+ toggle: () => save({ disabled: entry.disabled === true ? undefined : true }, t("common.enabledState")),
226
270
  },
227
271
  {
228
272
  key: "description",
229
- label: "描述",
273
+ label: t("field.description"),
230
274
  kind: "text",
231
- value: entry.description ?? "(空)",
275
+ value: entry.description ?? t("common.empty"),
232
276
  initial: entry.description ?? "",
233
- commit: (raw) => save({ description: raw.trim() || undefined }, "描述"),
277
+ commit: (raw) => save({ description: raw.trim() || undefined }, t("field.description")),
234
278
  },
235
279
  ];
236
280
  if (type === "stdio") {
237
281
  fields.push({
238
282
  key: "command",
239
- label: "命令",
283
+ label: t("field.command"),
240
284
  kind: "text",
241
- value: entry.command ?? "(空)",
285
+ value: entry.command ?? t("common.empty"),
242
286
  initial: entry.command ?? "",
243
- commit: (raw) => save({ command: raw.trim() || undefined }, "命令"),
287
+ commit: (raw) => save({ command: raw.trim() || undefined }, t("field.command")),
244
288
  }, {
245
289
  key: "args",
246
- label: "参数",
290
+ label: t("field.args"),
247
291
  kind: "text",
248
- value: formatArgs(entry.args) || "(空)",
292
+ value: formatArgs(entry.args) || t("common.empty"),
249
293
  initial: formatArgs(entry.args),
250
294
  commit: (raw) => {
251
295
  const args = parseArgs(raw.trim());
252
- return save({ args: args.length ? args : undefined }, "参数");
296
+ return save({ args: args.length ? args : undefined }, t("field.args"));
253
297
  },
254
298
  }, {
255
299
  key: "env",
256
- label: "环境变量",
257
- kind: "map",
300
+ label: t("field.env"),
301
+ kind: "open",
258
302
  value: kvSummary(entry.env),
259
303
  open: () => go({ kind: "mcp-kv", scope, serverId: id, field: "env" }),
260
304
  });
@@ -264,13 +308,13 @@ export function createFieldBuilders(context) {
264
308
  key: "url",
265
309
  label: "URL",
266
310
  kind: "text",
267
- value: entry.url ?? "(空)",
311
+ value: entry.url ?? t("common.empty"),
268
312
  initial: entry.url ?? "",
269
313
  commit: (raw) => save({ url: raw.trim() || undefined }, "URL"),
270
314
  }, {
271
315
  key: "headers",
272
- label: "请求头",
273
- kind: "map",
316
+ label: t("field.headers"),
317
+ kind: "open",
274
318
  value: kvSummary(entry.headers),
275
319
  open: () => go({ kind: "mcp-kv", scope, serverId: id, field: "headers" }),
276
320
  });
@@ -282,37 +326,37 @@ export function createFieldBuilders(context) {
282
326
  const kindName = agentKindLabel(kind);
283
327
  const managed = kind === "agent" && !def.custom;
284
328
  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}`);
329
+ const marked = markCustom(nextDef);
330
+ const suffix = customNote(managed);
331
+ return saveAgent(kind, marked, t("wiz.agentFieldUpdated", { kind: kindName, id: def.id, label, suffix }));
288
332
  };
289
333
  const fields = [
290
334
  {
291
335
  key: "name",
292
- label: "名称",
336
+ label: t("field.name"),
293
337
  kind: "text",
294
338
  value: def.name || def.id,
295
339
  initial: def.name,
296
340
  commit: (raw) => raw.trim()
297
- ? save(updateAgentDefinition(def, { name: raw.trim() }), "名称")
298
- : Promise.resolve("名称不能为空"),
341
+ ? save(updateAgentDefinition(def, { name: raw.trim() }), t("field.name"))
342
+ : t("err.nameRequired"),
299
343
  },
300
344
  {
301
345
  key: "id",
302
- label: "标识",
346
+ label: t("field.id"),
303
347
  kind: "text",
304
348
  value: def.id,
305
349
  initial: def.id,
306
350
  commit: (raw) => {
307
351
  const name = raw.trim();
308
352
  if (!name)
309
- return Promise.resolve("标识不能为空");
353
+ return t("err.idRequired");
310
354
  if (name === def.id)
311
- return Promise.resolve(null);
355
+ return null;
312
356
  if (agentList(store, kind).some((item) => item.id === name))
313
- return Promise.resolve(`已存在标识 ${name} 的定义`);
357
+ return t("err.agentIdTaken", { name });
314
358
  return (async () => {
315
- const failure = await saveAgent(kind, { ...def, id: name }, `${kindName} ${def.id} 已重命名为 ${name}`);
359
+ const failure = await saveAgent(kind, { ...def, id: name }, t("wiz.agentRenamed", { kind: kindName, id: def.id, name }));
316
360
  if (failure)
317
361
  return failure;
318
362
  await removeAgentQuiet(kind, def.id);
@@ -323,67 +367,58 @@ export function createFieldBuilders(context) {
323
367
  },
324
368
  {
325
369
  key: "description",
326
- label: "描述",
370
+ label: t("field.description"),
327
371
  kind: "text",
328
- value: def.description ?? "(空)",
372
+ value: def.description ?? t("common.empty"),
329
373
  initial: def.description ?? "",
330
- commit: (raw) => save(updateAgentDefinition(def, { description: raw.trim() || undefined }), "描述"),
374
+ commit: (raw) => save(updateAgentDefinition(def, { description: raw.trim() || undefined }), t("field.description")),
331
375
  },
332
376
  {
333
377
  key: "modelId",
334
- label: "模型",
378
+ label: t("field.model"),
335
379
  kind: "enum",
336
- value: findModel(config, def.modelId)?.name ?? def.modelId ?? "(未设置)",
380
+ value: findModel(config, def.modelId)?.name ?? def.modelId ?? t("common.unset"),
337
381
  options: [
338
382
  ...config.models.map((model) => ({ label: model.name || model.id, value: model.id })),
339
- { label: "(未设置)", value: "" },
383
+ { label: t("common.unset"), value: "" },
340
384
  ],
341
- commit: (raw) => save(updateAgentDefinition(def, { modelId: raw || undefined }), "模型"),
385
+ commit: (raw) => save(updateAgentDefinition(def, { modelId: raw || undefined }), t("field.model")),
342
386
  },
343
387
  {
344
388
  key: "prompt",
345
- label: "提示词",
346
- kind: "map",
389
+ label: t("field.prompt"),
390
+ kind: "open",
347
391
  value: summarizeMultiline(getAgentPrompt(def)),
348
392
  open: () => go({ kind: "agent-text", agentKind: kind, agentId: def.id, field: "prompt" }),
349
393
  },
350
394
  {
351
395
  key: "permissions",
352
- label: "权限",
353
- kind: "map",
396
+ label: t("field.permissions"),
397
+ kind: "open",
354
398
  value: summarizePermissions(def.permissions),
355
399
  open: () => go({ kind: "agent-perms", agentKind: kind, agentId: def.id }),
356
400
  },
357
401
  ];
358
- if (kind === "agent") {
359
- fields.push({
360
- key: "custom",
361
- label: "自定义",
362
- kind: "bool",
363
- value: def.custom ? "是" : "否(出厂托管)",
364
- toggle: () => save(updateAgentDefinition(def, { custom: !def.custom }), "「自定义」"),
365
- });
366
- }
367
- else {
402
+ if (kind === "subagent") {
368
403
  fields.push({
369
404
  key: "fnName",
370
- label: "函数名",
405
+ label: t("field.functionName"),
371
406
  kind: "text",
372
- value: def.function?.name ?? "(空)",
407
+ value: def.function?.name ?? t("common.empty"),
373
408
  initial: def.function?.name ?? "",
374
409
  commit: (raw) => raw.trim()
375
- ? save(updateAgentFunction(def, { name: raw.trim() }), "函数名")
376
- : Promise.resolve("函数名不能为空"),
410
+ ? save(updateAgentFunction(def, { name: raw.trim() }), t("field.functionName"))
411
+ : t("err.functionNameRequired"),
377
412
  }, {
378
413
  key: "fnDesc",
379
- label: "函数说明",
380
- kind: "map",
414
+ label: t("field.functionDescription"),
415
+ kind: "open",
381
416
  value: summarizeMultiline(def.function?.description ?? ""),
382
417
  open: () => go({ kind: "agent-text", agentKind: kind, agentId: def.id, field: "fnDesc" }),
383
418
  }, {
384
419
  key: "fnParams",
385
- label: "参数 schema",
386
- kind: "map",
420
+ label: t("field.paramsSchema"),
421
+ kind: "open",
387
422
  value: summarizeMultiline(JSON.stringify(def.function?.parameters ?? {}, null, 2)),
388
423
  open: () => go({ kind: "agent-text", agentKind: kind, agentId: def.id, field: "fnParams" }),
389
424
  });
@@ -393,17 +428,17 @@ export function createFieldBuilders(context) {
393
428
  /** 四维权限子屏字段(`allow: a, b` / `deny: x`;留空清除该维) */
394
429
  const agentPermFields = (kind, def) => PERMISSION_DIMENSIONS.map((dim) => ({
395
430
  key: dim,
396
- label: dim,
431
+ label: t(PERMISSION_DIMENSION_LABEL_KEY[dim]),
397
432
  kind: "text",
398
- value: formatAgentPermission(def.permissions, dim) || "(未设置)",
433
+ value: formatAgentPermission(def.permissions, dim) || t("common.unset"),
399
434
  initial: formatAgentPermission(def.permissions, dim),
400
435
  commit: (raw) => {
401
436
  const parsed = parsePermission(raw);
402
437
  if (typeof parsed === "string")
403
- return Promise.resolve(parsed);
438
+ return parsed;
404
439
  const managed = kind === "agent" && !def.custom;
405
440
  const next = setAgentPermission(managed ? { ...def, custom: true } : def, dim, parsed);
406
- return saveAgent(kind, next, `${agentKindLabel(kind)} ${def.id} 的 ${dim} 权限已更新`);
441
+ return saveAgent(kind, next, t("wiz.agentPermissionUpdated", { kind: agentKindLabel(kind), id: def.id, dim }));
407
442
  },
408
443
  }));
409
444
  return { endpointFields, modelFields, imageModelFields, mcpServerFields, agentFields, agentPermFields };