@armadra/agent 0.6.0 → 0.6.1

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 (65) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/CHANGELOG.zh-CN.md +20 -0
  3. package/dist/ai/providers/discovered-cache.d.ts +48 -0
  4. package/dist/ai/providers/discovered-cache.js +102 -0
  5. package/dist/ai/providers/model-visibility.d.ts +33 -0
  6. package/dist/ai/providers/model-visibility.js +70 -0
  7. package/dist/ai/providers/registry.d.ts +2 -0
  8. package/dist/ai/providers/registry.js +6 -1
  9. package/dist/auth/chatgpt/cli.d.ts +3 -1
  10. package/dist/auth/chatgpt/cli.js +31 -4
  11. package/dist/bundle/ama.cjs +1343 -640
  12. package/dist/cli/compose-providers.d.ts +1 -0
  13. package/dist/cli/compose-providers.js +6 -0
  14. package/dist/cli/subcommands/config-set.js +19 -11
  15. package/dist/cli/subcommands/models-discover.d.ts +2 -1
  16. package/dist/cli/subcommands/models-discover.js +17 -1
  17. package/dist/cli/subcommands/models-enable.d.ts +13 -0
  18. package/dist/cli/subcommands/models-enable.js +145 -0
  19. package/dist/cli/subcommands/models.d.ts +2 -0
  20. package/dist/cli/subcommands/models.js +10 -2
  21. package/dist/config/json-schema.js +1 -1
  22. package/dist/config/schema-w5.js +9 -2
  23. package/dist/config/settings-registry.d.ts +3 -0
  24. package/dist/config/settings-registry.js +1 -0
  25. package/dist/config/types-w5.d.ts +7 -0
  26. package/dist/config/types-w5.js +2 -0
  27. package/dist/i18n/catalog.d.ts +43 -3
  28. package/dist/i18n/messages/auth.d.ts +4 -2
  29. package/dist/i18n/messages/auth.js +14 -2
  30. package/dist/i18n/messages/cli-help.js +4 -0
  31. package/dist/i18n/messages/config-keys.d.ts +4 -0
  32. package/dist/i18n/messages/config-keys.js +6 -2
  33. package/dist/i18n/messages/config.d.ts +6 -0
  34. package/dist/i18n/messages/config.js +2 -0
  35. package/dist/i18n/messages/errors.d.ts +1 -1
  36. package/dist/i18n/messages/interactive-startup.d.ts +0 -4
  37. package/dist/i18n/messages/interactive-startup.js +0 -4
  38. package/dist/i18n/messages/interactive.d.ts +0 -4
  39. package/dist/i18n/messages/panels.d.ts +43 -0
  40. package/dist/i18n/messages/panels.js +43 -0
  41. package/dist/i18n/messages/settings.d.ts +7 -0
  42. package/dist/i18n/messages/settings.js +7 -0
  43. package/dist/i18n/messages/subcommands-config.d.ts +2 -0
  44. package/dist/i18n/messages/subcommands-config.js +2 -0
  45. package/dist/i18n/messages/subcommands-models.d.ts +34 -0
  46. package/dist/i18n/messages/subcommands-models.js +34 -0
  47. package/dist/i18n/messages/subcommands.d.ts +28 -0
  48. package/dist/i18n/messages/subcommands.js +3 -0
  49. package/dist/modes/interactive/commands.d.ts +3 -0
  50. package/dist/modes/interactive/commands.js +18 -11
  51. package/dist/modes/interactive/config-ui.js +1 -1
  52. package/dist/modes/interactive/interactive-mode.js +2 -0
  53. package/dist/modes/interactive/model-items.d.ts +45 -0
  54. package/dist/modes/interactive/model-items.js +134 -0
  55. package/dist/modes/interactive/model-picker.d.ts +57 -0
  56. package/dist/modes/interactive/model-picker.js +191 -0
  57. package/dist/modes/interactive/startup-ui.d.ts +3 -9
  58. package/dist/modes/interactive/startup-ui.js +8 -60
  59. package/dist/tui/components/select-list.d.ts +2 -0
  60. package/dist/tui/components/select-list.js +7 -0
  61. package/docs/en/providers.md +2 -0
  62. package/docs/en/tui.md +8 -1
  63. package/docs/providers.md +6 -0
  64. package/docs/tui.md +8 -1
  65. package/package.json +1 -1
@@ -111,6 +111,7 @@ export declare const en: {
111
111
  "models.aliases": string;
112
112
  "models.aliases.fast": string;
113
113
  "models.aliases.strong": string;
114
+ "models.enabled": string;
114
115
  fallbackModel: string;
115
116
  limits: string;
116
117
  "limits.maxTurns": string;
@@ -137,6 +138,7 @@ export declare const en: {
137
138
  "subagents.defaultModel": string;
138
139
  "models.aliases.fast": string;
139
140
  "models.aliases.strong": string;
141
+ "models.enabled": string;
140
142
  fallbackModel: string;
141
143
  "limits.maxTurns": string;
142
144
  "limits.maxCostUsd": string;
@@ -252,6 +254,7 @@ export declare const zh: {
252
254
  "models.aliases": string;
253
255
  "models.aliases.fast": string;
254
256
  "models.aliases.strong": string;
257
+ "models.enabled": string;
255
258
  fallbackModel: string;
256
259
  limits: string;
257
260
  "limits.maxTurns": string;
@@ -278,6 +281,7 @@ export declare const zh: {
278
281
  "subagents.defaultModel": string;
279
282
  "models.aliases.fast": string;
280
283
  "models.aliases.strong": string;
284
+ "models.enabled": string;
281
285
  fallbackModel: string;
282
286
  "limits.maxTurns": string;
283
287
  "limits.maxCostUsd": string;
@@ -20,6 +20,7 @@ const dynamicDefaultsEn = {
20
20
  "subagents.defaultModel": "unset: inherit the parent session model",
21
21
  "models.aliases.fast": "unset: fast is treated as inherit",
22
22
  "models.aliases.strong": "unset: strong is treated as inherit",
23
+ "models.enabled": "unset: /model shows every model of configured providers",
23
24
  fallbackModel: "unset: no fallback",
24
25
  "limits.maxTurns": "unset: unlimited",
25
26
  "limits.maxCostUsd": "unset: unlimited",
@@ -42,6 +43,7 @@ const dynamicDefaultsZh = {
42
43
  "subagents.defaultModel": "不设:继承父会话模型",
43
44
  "models.aliases.fast": "不设:fast 按 inherit 处理",
44
45
  "models.aliases.strong": "不设:strong 按 inherit 处理",
46
+ "models.enabled": "不设:/model 显示已配置供应商的全部模型",
45
47
  fallbackModel: "不设:不回退",
46
48
  "limits.maxTurns": "不设:不限",
47
49
  "limits.maxCostUsd": "不设:不限",
@@ -152,10 +154,11 @@ const keysEn = {
152
154
  "subagents.maxConcurrent": "Sub-sessions running at the same time",
153
155
  "subagents.maxPending": "Queue limit; task fails beyond it",
154
156
  "subagents.defaultModel": "Default sub-session model provider/model[@channel]",
155
- models: "Model aliases; user level only (effective from wave 5 W5-G)",
157
+ models: "Model aliases and the model picker list; user level only (effective from wave 5 W5-G)",
156
158
  "models.aliases": "Models that model: fast / strong in sub-agent definitions point to",
157
159
  "models.aliases.fast": "Model for the fast alias provider/model[@channel]",
158
160
  "models.aliases.strong": "Model for the strong alias provider/model[@channel]",
161
+ "models.enabled": "Models shown by /model (provider/model[@channel], provider/* for a whole provider); unset: every model of providers with a key, a sign-in or a local server",
159
162
  fallbackModel: "Fallback model provider/model[@channel]: switch and retry once when retryable errors are exhausted or the model is overloaded; the next turn returns to the main model; user level only (effective from wave 5 W5-H2)",
160
163
  limits: "Session budget; the run ends when reached (-p exit code 8); --max-turns / --max-cost override; user level only (effective from wave 5 W5-H2)",
161
164
  "limits.maxTurns": "Maximum turns per run",
@@ -269,10 +272,11 @@ const keysZh = {
269
272
  "subagents.maxConcurrent": "同时运行的子会话数",
270
273
  "subagents.maxPending": "排队上限,超出时 task 报错",
271
274
  "subagents.defaultModel": "子会话缺省模型 provider/model[@channel]",
272
- models: "模型别名;只认用户级(第五波 W5-G 起生效)",
275
+ models: "模型别名与模型选择器清单;只认用户级(第五波 W5-G 起生效)",
273
276
  "models.aliases": "子 Agent 定义里 model: fast / strong 指向的模型",
274
277
  "models.aliases.fast": "fast 别名的模型 provider/model[@channel]",
275
278
  "models.aliases.strong": "strong 别名的模型 provider/model[@channel]",
279
+ "models.enabled": "/model 显示的模型(provider/model[@channel],provider/* 表示整个供应商);不设:已配置 key、已登录或本地可达的供应商的全部模型",
276
280
  fallbackModel: "回退模型 provider/model[@channel]:可重试错误用尽或过载时切换重试一次,下一回合回主模型;只认用户级(第五波 W5-H2 起生效)",
277
281
  limits: "会话预算,到限结束本次运行(-p 退出码 8);--max-turns / --max-cost 覆盖;只认用户级(第五波 W5-H2 起生效)",
278
282
  "limits.maxTurns": "一次运行最多回合数",
@@ -111,6 +111,7 @@ export declare const en: {
111
111
  "models.aliases": string;
112
112
  "models.aliases.fast": string;
113
113
  "models.aliases.strong": string;
114
+ "models.enabled": string;
114
115
  fallbackModel: string;
115
116
  limits: string;
116
117
  "limits.maxTurns": string;
@@ -137,6 +138,7 @@ export declare const en: {
137
138
  "subagents.defaultModel": string;
138
139
  "models.aliases.fast": string;
139
140
  "models.aliases.strong": string;
141
+ "models.enabled": string;
140
142
  fallbackModel: string;
141
143
  "limits.maxTurns": string;
142
144
  "limits.maxCostUsd": string;
@@ -163,6 +165,7 @@ export declare const en: {
163
165
  stringArray: string;
164
166
  array: string;
165
167
  modelsDev: string;
168
+ modelsEnabled: string;
166
169
  noChannels: string;
167
170
  unknownChannelOf: (name: string, available: readonly string[]) => string;
168
171
  modelInput: string;
@@ -363,6 +366,7 @@ export declare const zh: {
363
366
  "models.aliases": string;
364
367
  "models.aliases.fast": string;
365
368
  "models.aliases.strong": string;
369
+ "models.enabled": string;
366
370
  fallbackModel: string;
367
371
  limits: string;
368
372
  "limits.maxTurns": string;
@@ -389,6 +393,7 @@ export declare const zh: {
389
393
  "subagents.defaultModel": string;
390
394
  "models.aliases.fast": string;
391
395
  "models.aliases.strong": string;
396
+ "models.enabled": string;
392
397
  fallbackModel: string;
393
398
  "limits.maxTurns": string;
394
399
  "limits.maxCostUsd": string;
@@ -414,6 +419,7 @@ export declare const zh: {
414
419
  stringArray: string;
415
420
  array: string;
416
421
  modelsDev: string;
422
+ modelsEnabled: string;
417
423
  noChannels: string;
418
424
  unknownChannelOf: (name: string, available: readonly string[]) => string;
419
425
  modelInput: string;
@@ -25,6 +25,7 @@ export const en = {
25
25
  stringArray: "should be an array of strings",
26
26
  array: "should be an array",
27
27
  modelsDev: `should be "provider/model" or false`,
28
+ modelsEnabled: `should be "provider/model[@channel]" or "provider/*"`,
28
29
  noChannels: "the provider has no channels",
29
30
  unknownChannelOf: (name, available) => `channel "${name}" does not exist (available: ${available.join(", ")})`,
30
31
  modelInput: `should be ("text" | "image")[]`,
@@ -144,6 +145,7 @@ export const zh = {
144
145
  stringArray: "应为字符串数组",
145
146
  array: "应为数组",
146
147
  modelsDev: `应为 "provider/model" 或 false`,
148
+ modelsEnabled: `应为 "provider/model[@channel]" 或 "provider/*"`,
147
149
  noChannels: "供应商没有 channels",
148
150
  unknownChannelOf: (name, available) => `渠道 "${name}" 不存在(可用:${available.join(", ")})`,
149
151
  modelInput: `应为 ("text" | "image")[]`,
@@ -75,7 +75,7 @@ export declare const zh: {
75
75
  refreshFailed: (reason: string) => string;
76
76
  notListed: (unknown: string, choices: string) => string;
77
77
  refreshStatus: (status: "failed" | "unchanged" | "updated", providers: number, models: number, at: string | undefined) => string;
78
- section: (kind: "removed" | "added" | "changed", count: number) => string;
78
+ section: (kind: "added" | "removed" | "changed", count: number) => string;
79
79
  more: (count: number) => string;
80
80
  changed: (ref: string, parts: readonly string[]) => string;
81
81
  };
@@ -30,8 +30,6 @@ export declare const en: {
30
30
  hintFilter: (arrows: string) => string;
31
31
  hintNumbers: (arrows: string, n: number) => string;
32
32
  hint: (arrows: string) => string;
33
- local: string;
34
- noKey: string;
35
33
  justNow: string;
36
34
  minutesAgo: (n: number) => string;
37
35
  hoursAgo: (n: number) => string;
@@ -78,8 +76,6 @@ export declare const zh: {
78
76
  hintFilter: (arrows: string) => string;
79
77
  hintNumbers: (arrows: string, n: number) => string;
80
78
  hint: (arrows: string) => string;
81
- local: string;
82
- noKey: string;
83
79
  justNow: string;
84
80
  minutesAgo: (n: number) => string;
85
81
  hoursAgo: (n: number) => string;
@@ -31,8 +31,6 @@ export const en = {
31
31
  hintFilter: (arrows) => `type to filter · ${arrows} select · Enter confirm · Esc cancel`,
32
32
  hintNumbers: (arrows, n) => `${arrows} select · Enter confirm · 1-${n} pick · Esc cancel`,
33
33
  hint: (arrows) => `${arrows} select · Enter confirm · Esc cancel`,
34
- local: "local",
35
- noKey: "no key",
36
34
  justNow: "just now",
37
35
  minutesAgo: (n) => `${n}m ago`,
38
36
  hoursAgo: (n) => `${n}h ago`,
@@ -79,8 +77,6 @@ export const zh = {
79
77
  hintFilter: (arrows) => `输入过滤 · ${arrows} 选择 · Enter 确认 · Esc 取消`,
80
78
  hintNumbers: (arrows, n) => `${arrows} 选择 · Enter 确认 · 1-${n} 直接选 · Esc 取消`,
81
79
  hint: (arrows) => `${arrows} 选择 · Enter 确认 · Esc 取消`,
82
- local: "本地",
83
- noKey: "无 key",
84
80
  justNow: "刚刚",
85
81
  minutesAgo: (n) => `${n} 分钟前`,
86
82
  hoursAgo: (n) => `${n} 小时前`,
@@ -206,8 +206,6 @@ export declare const en: {
206
206
  hintFilter: (arrows: string) => string;
207
207
  hintNumbers: (arrows: string, n: number) => string;
208
208
  hint: (arrows: string) => string;
209
- local: string;
210
- noKey: string;
211
209
  justNow: string;
212
210
  minutesAgo: (n: number) => string;
213
211
  hoursAgo: (n: number) => string;
@@ -445,8 +443,6 @@ export declare const zh: {
445
443
  hintFilter: (arrows: string) => string;
446
444
  hintNumbers: (arrows: string, n: number) => string;
447
445
  hint: (arrows: string) => string;
448
- local: string;
449
- noKey: string;
450
446
  justNow: string;
451
447
  minutesAgo: (n: number) => string;
452
448
  hoursAgo: (n: number) => string;
@@ -51,6 +51,28 @@ export declare const en: {
51
51
  thinkingUnsupported: string;
52
52
  emptyText: string;
53
53
  };
54
+ /** 模型选择器(`/model`、启动选择器、`/config` 的模型项)。 */
55
+ model: {
56
+ local: string;
57
+ key: string;
58
+ oauth: string;
59
+ needsLogin: string;
60
+ noKey: string;
61
+ current: string;
62
+ listed: string;
63
+ otherChannels: (names: string) => string;
64
+ discoverHint: (provider: string) => string;
65
+ loginHint: (provider: string) => string;
66
+ footerConfigured: string;
67
+ footerAll: string;
68
+ emptyConfigured: string;
69
+ added: (ref: string) => string;
70
+ addedFirst: (ref: string) => string;
71
+ removed: (ref: string) => string;
72
+ wildcard: (ref: string, pattern: string) => string;
73
+ noKeyHint: (provider: string) => string;
74
+ needsLoginHint: (provider: string) => string;
75
+ };
54
76
  plan: {
55
77
  title: string;
56
78
  titleVersion: (version: number) => string;
@@ -140,6 +162,27 @@ export declare const zh: {
140
162
  thinkingUnsupported: string;
141
163
  emptyText: string;
142
164
  };
165
+ model: {
166
+ local: string;
167
+ key: string;
168
+ oauth: string;
169
+ needsLogin: string;
170
+ noKey: string;
171
+ current: string;
172
+ listed: string;
173
+ otherChannels: (names: string) => string;
174
+ discoverHint: (provider: string) => string;
175
+ loginHint: (provider: string) => string;
176
+ footerConfigured: string;
177
+ footerAll: string;
178
+ emptyConfigured: string;
179
+ added: (ref: string) => string;
180
+ addedFirst: (ref: string) => string;
181
+ removed: (ref: string) => string;
182
+ wildcard: (ref: string, pattern: string) => string;
183
+ noKeyHint: (provider: string) => string;
184
+ needsLoginHint: (provider: string) => string;
185
+ };
143
186
  plan: {
144
187
  title: string;
145
188
  titleVersion: (version: number) => string;
@@ -51,6 +51,28 @@ export const en = {
51
51
  thinkingUnsupported: "The current model does not support thinking",
52
52
  emptyText: "(empty)",
53
53
  },
54
+ /** 模型选择器(`/model`、启动选择器、`/config` 的模型项)。 */
55
+ model: {
56
+ local: "local",
57
+ key: "key ✓",
58
+ oauth: "signed in ✓",
59
+ needsLogin: "sign in again",
60
+ noKey: "no key configured",
61
+ current: "current",
62
+ listed: "listed",
63
+ otherChannels: (names) => `also ${names}`,
64
+ discoverHint: (provider) => `Run ama models discover ${provider} to list its models`,
65
+ loginHint: (provider) => `Run ama auth login ${provider} to sign in`,
66
+ footerConfigured: "Tab all · Space list · @ channels · Enter switch · Esc cancel",
67
+ footerAll: "Tab configured · Space list · @ channels · Enter switch · Esc cancel",
68
+ emptyConfigured: "(no configured models; Tab shows all)",
69
+ added: (ref) => `Added ${ref} to models.enabled`,
70
+ addedFirst: (ref) => `Added ${ref} to models.enabled; /model now shows only listed models (Tab shows all)`,
71
+ removed: (ref) => `Removed ${ref} from models.enabled`,
72
+ wildcard: (ref, pattern) => `${ref} is listed through ${pattern}; remove it with ama models disable ${pattern}`,
73
+ noKeyHint: (provider) => `${provider} has no key: run ama auth set ${provider} (custom providers: ama providers add)`,
74
+ needsLoginHint: (provider) => `${provider} needs a new sign-in: run ama auth login ${provider}`,
75
+ },
54
76
  plan: {
55
77
  title: "Plan",
56
78
  titleVersion: (version) => `Plan v${version}`,
@@ -140,6 +162,27 @@ export const zh = {
140
162
  thinkingUnsupported: "当前模型不支持思考",
141
163
  emptyText: "(空)",
142
164
  },
165
+ model: {
166
+ local: "本地",
167
+ key: "key ✓",
168
+ oauth: "已登录 ✓",
169
+ needsLogin: "需重新登录",
170
+ noKey: "未配置 key",
171
+ current: "当前",
172
+ listed: "清单内",
173
+ otherChannels: (names) => `另有 ${names}`,
174
+ discoverHint: (provider) => `运行 ama models discover ${provider} 获取模型`,
175
+ loginHint: (provider) => `运行 ama auth login ${provider} 登录`,
176
+ footerConfigured: "Tab 全部 · Space 清单 · @ 渠道 · Enter 切换 · Esc 取消",
177
+ footerAll: "Tab 已配置 · Space 清单 · @ 渠道 · Enter 切换 · Esc 取消",
178
+ emptyConfigured: "(没有已配置的模型,Tab 看全部)",
179
+ added: (ref) => `已把 ${ref} 加入 models.enabled`,
180
+ addedFirst: (ref) => `已把 ${ref} 加入 models.enabled;/model 之后只显示清单内的模型(Tab 看全部)`,
181
+ removed: (ref) => `已把 ${ref} 移出 models.enabled`,
182
+ wildcard: (ref, pattern) => `${ref} 经 ${pattern} 列入清单;用 ama models disable ${pattern} 移除`,
183
+ noKeyHint: (provider) => `${provider} 未配置 key:运行 ama auth set ${provider}(自定义供应商用 ama providers add)`,
184
+ needsLoginHint: (provider) => `${provider} 需要重新登录:运行 ama auth login ${provider}`,
185
+ },
143
186
  plan: {
144
187
  title: "计划",
145
188
  titleVersion: (version) => `计划 v${version}`,
@@ -135,6 +135,9 @@ export declare const en: {
135
135
  setDone: (key: string, value: string, scope: string) => string;
136
136
  unsetDone: (key: string, value: string, scope: string) => string;
137
137
  stillOverridden: (key: string, source: string) => string;
138
+ /** `ama config set` when a higher layer hides the write: first line = what was written. */
139
+ writtenTo: (key: string, value: string, scope: string) => string;
140
+ overriddenNow: (source: string, effective: string) => string;
138
141
  slashUsage: string;
139
142
  errors: {
140
143
  unknownKey: (key: string) => string;
@@ -163,6 +166,7 @@ export declare const en: {
163
166
  agents: string;
164
167
  hooks: string;
165
168
  auth: string;
169
+ modelsEnabled: string;
166
170
  };
167
171
  cli: {
168
172
  usage: string;
@@ -305,6 +309,8 @@ export declare const zh: {
305
309
  setDone: (key: string, value: string, scope: string) => string;
306
310
  unsetDone: (key: string, value: string, scope: string) => string;
307
311
  stillOverridden: (key: string, source: string) => string;
312
+ writtenTo: (key: string, value: string, scope: string) => string;
313
+ overriddenNow: (source: string, effective: string) => string;
308
314
  slashUsage: string;
309
315
  errors: {
310
316
  unknownKey: (key: string) => string;
@@ -333,6 +339,7 @@ export declare const zh: {
333
339
  agents: string;
334
340
  hooks: string;
335
341
  auth: string;
342
+ modelsEnabled: string;
336
343
  };
337
344
  cli: {
338
345
  usage: string;
@@ -125,6 +125,9 @@ export const en = {
125
125
  setDone: (key, value, scope) => `${key} = ${value} (${scope})`,
126
126
  unsetDone: (key, value, scope) => `${key} reset (${scope}); now ${value}`,
127
127
  stillOverridden: (key, source) => `${key} is still overridden by ${source}; the saved value applies once that is removed`,
128
+ /** `ama config set` when a higher layer hides the write: first line = what was written. */
129
+ writtenTo: (key, value, scope) => `${key} = ${value} (written to ${scope})`,
130
+ overriddenNow: (source, effective) => `Still overridden by ${source} (${effective}); the effective value is ${effective}`,
128
131
  slashUsage: "Usage: /config [key=value | key value]",
129
132
  errors: {
130
133
  unknownKey: (key) => `${key} isn't a /config setting. Run /config to see what's available.`,
@@ -153,6 +156,7 @@ export const en = {
153
156
  agents: "agents.<id>: ama config edit",
154
157
  hooks: "hooks.json · /hooks",
155
158
  auth: "ama auth",
159
+ modelsEnabled: "/model (Space) · ama models enable / disable",
156
160
  },
157
161
  cli: {
158
162
  usage: `Usage: ama config get <key> [--json]
@@ -289,6 +293,8 @@ export const zh = {
289
293
  setDone: (key, value, scope) => `${key} = ${value}(${scope})`,
290
294
  unsetDone: (key, value, scope) => `已恢复 ${key}(${scope}),现为 ${value}`,
291
295
  stillOverridden: (key, source) => `${key} 仍被 ${source} 覆盖,撤掉后写入的值才生效`,
296
+ writtenTo: (key, value, scope) => `${key} = ${value}(已写入${scope})`,
297
+ overriddenNow: (source, effective) => `当前仍被 ${source}(${effective})覆盖,生效值为 ${effective}`,
292
298
  slashUsage: "用法:/config [key=value | key value]",
293
299
  errors: {
294
300
  unknownKey: (key) => `${key} 不是可设置项,用 /config 查看`,
@@ -317,6 +323,7 @@ export const zh = {
317
323
  agents: "agents.<id>:ama config edit",
318
324
  hooks: "hooks.json · /hooks",
319
325
  auth: "ama auth",
326
+ modelsEnabled: "/model(Space)· ama models enable / disable",
320
327
  },
321
328
  cli: {
322
329
  usage: `用法:ama config get <key> [--json]
@@ -55,6 +55,7 @@ export declare const en: {
55
55
  probeHeader: (count: number, order: string, requests: number, extra: number, limit: number) => string;
56
56
  unavailable: string;
57
57
  probeStopped: (reason: string) => string;
58
+ cached: (path: string) => string;
58
59
  };
59
60
  };
60
61
  export declare const zh: {
@@ -107,5 +108,6 @@ export declare const zh: {
107
108
  probeHeader: (count: number, order: string, requests: number, extra: number, limit: number) => string;
108
109
  unavailable: string;
109
110
  probeStopped: (reason: string) => string;
111
+ cached: (path: string) => string;
110
112
  };
111
113
  };
@@ -64,6 +64,7 @@ export const en = {
64
64
  `${extra > 0 ? `; ${extra} more over --limit ${limit} are not probed` : ""}\n`,
65
65
  unavailable: "unavailable (all three protocols failed)",
66
66
  probeStopped: (reason) => `ama: probing stopped early (${reason})\n`,
67
+ cached: (path) => `Model list cached at ${path}; /model shows these models\n`,
67
68
  },
68
69
  };
69
70
  export const zh = {
@@ -123,5 +124,6 @@ export const zh = {
123
124
  `${extra > 0 ? `;另有 ${extra} 个超出 --limit ${limit},未探测` : ""}\n`,
124
125
  unavailable: "不可用(三种协议均失败)",
125
126
  probeStopped: (reason) => `ama: 探测提前停止(${reason})\n`,
127
+ cached: (path) => `模型列表已缓存到 ${path},/model 里会列出这些模型\n`,
126
128
  },
127
129
  };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 消息目录:subcommands 里 `ama models enable | disable | list --enabled`(`modelsEnabled`)。由
3
+ * messages/subcommands.ts 引用。
4
+ */
5
+ export declare const en: {
6
+ modelsEnabled: {
7
+ badRef: (ref: string) => string;
8
+ unknownModel: (ref: string) => string;
9
+ added: (refs: string, path: string) => string;
10
+ alreadyListed: (refs: string) => string;
11
+ removed: (refs: string, path: string) => string;
12
+ notListed: (refs: string) => string;
13
+ cleared: (path: string) => string;
14
+ listHeader: (path: string) => string;
15
+ listUnset: string;
16
+ notInTable: string;
17
+ nothing: string;
18
+ };
19
+ };
20
+ export declare const zh: {
21
+ modelsEnabled: {
22
+ badRef: (ref: string) => string;
23
+ unknownModel: (ref: string) => string;
24
+ added: (refs: string, path: string) => string;
25
+ alreadyListed: (refs: string) => string;
26
+ removed: (refs: string, path: string) => string;
27
+ notListed: (refs: string) => string;
28
+ cleared: (path: string) => string;
29
+ listHeader: (path: string) => string;
30
+ listUnset: string;
31
+ notInTable: string;
32
+ nothing: string;
33
+ };
34
+ };
@@ -0,0 +1,34 @@
1
+ /**
2
+ * 消息目录:subcommands 里 `ama models enable | disable | list --enabled`(`modelsEnabled`)。由
3
+ * messages/subcommands.ts 引用。
4
+ */
5
+ export const en = {
6
+ modelsEnabled: {
7
+ badRef: (ref) => `ama: ${ref} is not provider/model[@channel] or provider/*\n`,
8
+ unknownModel: (ref) => `ama: warning: ${ref} is not in the model table; written anyway (relays accept any id)\n`,
9
+ added: (refs, path) => `Added to models.enabled: ${refs} → ${path}\n`,
10
+ alreadyListed: (refs) => `Already in models.enabled: ${refs}\n`,
11
+ removed: (refs, path) => `Removed from models.enabled: ${refs} → ${path}\n`,
12
+ notListed: (refs) => `Not in models.enabled: ${refs}\n`,
13
+ cleared: (path) => `models.enabled is empty and was removed; /model shows every configured model again → ${path}\n`,
14
+ listHeader: (path) => `models.enabled (${path}):\n`,
15
+ listUnset: "models.enabled is not set; /model shows the models of configured providers:\n",
16
+ notInTable: "not in the model table",
17
+ nothing: " (none)\n",
18
+ },
19
+ };
20
+ export const zh = {
21
+ modelsEnabled: {
22
+ badRef: (ref) => `ama: ${ref} 不是 provider/model[@channel] 或 provider/*\n`,
23
+ unknownModel: (ref) => `ama: 警告:${ref} 不在模型表里,照样写入(中转站接受任意 id)\n`,
24
+ added: (refs, path) => `已加入 models.enabled:${refs} → ${path}\n`,
25
+ alreadyListed: (refs) => `已在 models.enabled 里:${refs}\n`,
26
+ removed: (refs, path) => `已移出 models.enabled:${refs} → ${path}\n`,
27
+ notListed: (refs) => `不在 models.enabled 里:${refs}\n`,
28
+ cleared: (path) => `models.enabled 已清空并删除,/model 恢复显示全部已配置的模型 → ${path}\n`,
29
+ listHeader: (path) => `models.enabled(${path}):\n`,
30
+ listUnset: "未设置 models.enabled;/model 显示已配置供应商的模型:\n",
31
+ notInTable: "不在模型表里",
32
+ nothing: " (无)\n",
33
+ },
34
+ };
@@ -225,6 +225,19 @@ export declare const en: {
225
225
  noHits: (all: boolean) => "No matches\n" | "No matches (only sessions of this directory; --all searches all)\n";
226
226
  truncated: (limit: number) => string;
227
227
  };
228
+ modelsEnabled: {
229
+ badRef: (ref: string) => string;
230
+ unknownModel: (ref: string) => string;
231
+ added: (refs: string, path: string) => string;
232
+ alreadyListed: (refs: string) => string;
233
+ removed: (refs: string, path: string) => string;
234
+ notListed: (refs: string) => string;
235
+ cleared: (path: string) => string;
236
+ listHeader: (path: string) => string;
237
+ listUnset: string;
238
+ notInTable: string;
239
+ nothing: string;
240
+ };
228
241
  configShow: {
229
242
  usage: string;
230
243
  unknownAction: (action: string) => string;
@@ -274,6 +287,7 @@ export declare const en: {
274
287
  probeHeader: (count: number, order: string, requests: number, extra: number, limit: number) => string;
275
288
  unavailable: string;
276
289
  probeStopped: (reason: string) => string;
290
+ cached: (path: string) => string;
277
291
  };
278
292
  };
279
293
  export declare const zh: {
@@ -495,6 +509,19 @@ export declare const zh: {
495
509
  noHits: (all: boolean) => "没有命中\n" | "没有命中(只搜了当前目录的会话,--all 搜全部)\n";
496
510
  truncated: (limit: number) => string;
497
511
  };
512
+ modelsEnabled: {
513
+ badRef: (ref: string) => string;
514
+ unknownModel: (ref: string) => string;
515
+ added: (refs: string, path: string) => string;
516
+ alreadyListed: (refs: string) => string;
517
+ removed: (refs: string, path: string) => string;
518
+ notListed: (refs: string) => string;
519
+ cleared: (path: string) => string;
520
+ listHeader: (path: string) => string;
521
+ listUnset: string;
522
+ notInTable: string;
523
+ nothing: string;
524
+ };
498
525
  configShow: {
499
526
  usage: string;
500
527
  unknownAction: (action: string) => string;
@@ -544,5 +571,6 @@ export declare const zh: {
544
571
  probeHeader: (count: number, order: string, requests: number, extra: number, limit: number) => string;
545
572
  unavailable: string;
546
573
  probeStopped: (reason: string) => string;
574
+ cached: (path: string) => string;
547
575
  };
548
576
  };
@@ -7,8 +7,10 @@
7
7
  */
8
8
  import { plural } from "../format.js";
9
9
  import * as configShow from "./subcommands-config.js";
10
+ import * as modelsEnabled from "./subcommands-models.js";
10
11
  export const en = {
11
12
  ...configShow.en,
13
+ ...modelsEnabled.en,
12
14
  /** 多个子命令共用。 */
13
15
  common: {
14
16
  warning: (text) => `ama: warning: ${text}\n`,
@@ -242,6 +244,7 @@ export const en = {
242
244
  };
243
245
  export const zh = {
244
246
  ...configShow.zh,
247
+ ...modelsEnabled.zh,
245
248
  common: {
246
249
  warning: (text) => `ama: 警告:${text}\n`,
247
250
  cancelled: "ama: 已取消\n",
@@ -15,6 +15,7 @@
15
15
  * 直接进子 Agent 视图(W6-A)。钩子没装时回落 commands-core(line 模式同一套文本)。
16
16
  */
17
17
  import type { AgentSession, RewindDraftText } from "../../agent/types.js";
18
+ import type { ProviderRegistryApi } from "../../ai/types.js";
18
19
  import type { SwitchRequest } from "../../cli/compose-session.js";
19
20
  import type { Runtime } from "../../cli/runtime.js";
20
21
  import type { PermissionMode } from "../../permissions/types.js";
@@ -67,6 +68,8 @@ export interface CommandUi {
67
68
  memoryPanel?(args: string): void | Promise<void>;
68
69
  /** [W6-C0] 设置面板(W6-S;`/config`,`/config key=value` 直接设一项)。 */
69
70
  configPanel?(args: string): void | Promise<void>;
71
+ /** `/model` 选择器(model-picker.ts:Tab 视图、Space 清单);没有时回落为 `pick` + `modelItems`。 */
72
+ pickModel?(providers: ProviderRegistryApi, current: string | undefined): Promise<string | undefined>;
70
73
  }
71
74
  /**
72
75
  * [W6-C0] 面板类命令 → `CommandUi` 钩子。钩子存在就调用并返回 true;不存在返回 false(回落 commands-core)。
@@ -156,19 +156,26 @@ async function handlePick(what, ui) {
156
156
  case "model": {
157
157
  const current = session.state.model;
158
158
  const ref = current === undefined ? undefined : `${current.provider}/${current.id}`;
159
- const picked = await ui.pick({
160
- title: m.modelTitle,
161
- items: await modelItems(ui.env === undefined
162
- ? ui.runtime.providers
163
- : hideFakeProvider(ui.runtime.providers, ui.env)),
164
- filterable: true,
165
- showCount: true,
166
- ...(ref !== undefined ? { selected: ref, currentValue: ref } : {}),
167
- });
159
+ const providers = ui.env === undefined
160
+ ? ui.runtime.providers
161
+ : hideFakeProvider(ui.runtime.providers, ui.env);
162
+ const picked = ui.pickModel !== undefined
163
+ ? await ui.pickModel(providers, ref)
164
+ : (await ui.pick({
165
+ title: m.modelTitle,
166
+ items: await modelItems(providers, {
167
+ current: ref,
168
+ enabled: ui.runtime.config.models?.enabled,
169
+ hints: false,
170
+ }),
171
+ filterable: true,
172
+ showCount: true,
173
+ ...(ref !== undefined ? { selected: ref, currentValue: ref } : {}),
174
+ }))?.value;
168
175
  if (picked === undefined)
169
176
  return;
170
- await session.setModel(picked.value);
171
- ui.notice("info", m.modelSet(picked.value));
177
+ await session.setModel(picked);
178
+ ui.notice("info", m.modelSet(picked));
172
179
  return;
173
180
  }
174
181
  case "session": {
@@ -232,7 +232,7 @@ export class ConfigUi {
232
232
  items = thinkingItems(true);
233
233
  else if (spec.kind === "model")
234
234
  items = [
235
- ...(await modelItems(hideFakeProvider(this.deps.runtime.providers, this.deps.context.io.env))),
235
+ ...(await modelItems(hideFakeProvider(this.deps.runtime.providers, this.deps.context.io.env), { current, enabled: this.deps.runtime.config.models?.enabled, hints: false })),
236
236
  { value: "", label: s.defaultChoice },
237
237
  ];
238
238
  else
@@ -41,6 +41,7 @@ import { configUiFor } from "./config-ui.js";
41
41
  import { createKeyDispatch } from "./key-dispatch.js";
42
42
  import { MessageView, exitSummaryLines } from "./message-view.js";
43
43
  import { openPicker } from "./pickers.js";
44
+ import { modelPickerFor } from "./model-picker.js";
44
45
  import { createRewindFlow } from "./rewind-flow.js";
45
46
  import { openTraceView } from "./trace-view.js";
46
47
  import { StartupHeader } from "./startup-header.js";
@@ -285,6 +286,7 @@ export function runInteractiveMode(runtime, context, options = {}) {
285
286
  return next;
286
287
  },
287
288
  pick: (spec) => openPicker(pickerHost, spec),
289
+ pickModel: modelPickerFor(pickerHost, runtime, context),
288
290
  confirmMode,
289
291
  rewind: () => rewind.open(),
290
292
  setDraft,