@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
@@ -41,7 +41,7 @@ var AMA_VERSION;
41
41
  var init_version = __esm({
42
42
  "src/version.ts"() {
43
43
  "use strict";
44
- AMA_VERSION = true ? "0.6.0" : readPackageVersion();
44
+ AMA_VERSION = true ? "0.6.1" : readPackageVersion();
45
45
  }
46
46
  });
47
47
 
@@ -117,7 +117,7 @@ function agentEntry(agents, agentId) {
117
117
  const entry = agents[agentId];
118
118
  return typeof entry === "object" && !Array.isArray(entry) ? entry : void 0;
119
119
  }
120
- var STATUS_LINE_MODES, IMAGE_RESIZE_MODES, PLAN_BASH_MODES_STRICT_FIRST, PLAN_UNATTENDED_MODES, AGENTS_RESERVED_KEYS;
120
+ var STATUS_LINE_MODES, IMAGE_RESIZE_MODES, PLAN_BASH_MODES_STRICT_FIRST, PLAN_UNATTENDED_MODES, AGENTS_RESERVED_KEYS, MODELS_ENABLED_REF;
121
121
  var init_types_w5 = __esm({
122
122
  "src/config/types-w5.ts"() {
123
123
  "use strict";
@@ -126,6 +126,7 @@ var init_types_w5 = __esm({
126
126
  PLAN_BASH_MODES_STRICT_FIRST = ["deny", "readonly", "ask"];
127
127
  PLAN_UNATTENDED_MODES = ["stop", "approve"];
128
128
  AGENTS_RESERVED_KEYS = ["maxConcurrent", "sessionBudgetUsd", "dirs"];
129
+ MODELS_ENABLED_REF = /^[^/\s]+\/\S+$/;
129
130
  }
130
131
  });
131
132
 
@@ -267,6 +268,8 @@ Subcommands
267
268
  Timeline of turns, requests, tools and subagents (text / HTML / JSON)
268
269
  ama models list [--provider <id>] List models (with source and key status)
269
270
  ama models check <provider/id> Send one minimal request to check availability
271
+ ama models enable|disable <provider/model|provider/*>…
272
+ Edit the /model list (models.enabled); list --enabled shows it
270
273
  ama models discover <provider> [--probe] [--write] [--limit N]
271
274
  List models from a relay's /v1/models, probe protocols, write the config
272
275
  ama models refresh [--provider <id>] Refresh models.dev metadata into the data directory (startup stays
@@ -382,6 +385,8 @@ Exit codes: 0 ok · 1 runtime error · 2 usage error · 3 config error · 4 no u
382
385
  回合、请求、工具与子 Agent 的时间线(文本 / HTML / JSON)
383
386
  ama models list [--provider <id>] 列出模型(含来源与 key 状态)
384
387
  ama models check <provider/id> 发一次最小请求检查可用性
388
+ ama models enable|disable <provider/model|provider/*>…
389
+ 编辑 /model 的模型清单(models.enabled);list --enabled 查看
385
390
  ama models discover <provider> [--probe] [--write] [--limit N]
386
391
  从中转 /v1/models 列出模型,探测协议并写入配置
387
392
  ama models refresh [--provider <id>] 联网刷新 models.dev 元数据到数据目录(启动不联网;
@@ -902,6 +907,8 @@ Probing protocols: ${plural(count2, "model")} (${order}), at most ${plural(reque
902
907
  `,
903
908
  unavailable: "unavailable (all three protocols failed)",
904
909
  probeStopped: (reason) => `ama: probing stopped early (${reason})
910
+ `,
911
+ cached: (path) => `Model list cached at ${path}; /model shows these models
905
912
  `
906
913
  }
907
914
  };
@@ -973,21 +980,79 @@ Probing protocols: ${plural(count2, "model")} (${order}), at most ${plural(reque
973
980
  `,
974
981
  unavailable: "不可用(三种协议均失败)",
975
982
  probeStopped: (reason) => `ama: 探测提前停止(${reason})
983
+ `,
984
+ cached: (path) => `模型列表已缓存到 ${path},/model 里会列出这些模型
976
985
  `
977
986
  }
978
987
  };
979
988
  }
980
989
  });
981
990
 
982
- // src/i18n/messages/subcommands.ts
991
+ // src/i18n/messages/subcommands-models.ts
983
992
  var en5, zh5;
993
+ var init_subcommands_models = __esm({
994
+ "src/i18n/messages/subcommands-models.ts"() {
995
+ "use strict";
996
+ en5 = {
997
+ modelsEnabled: {
998
+ badRef: (ref) => `ama: ${ref} is not provider/model[@channel] or provider/*
999
+ `,
1000
+ unknownModel: (ref) => `ama: warning: ${ref} is not in the model table; written anyway (relays accept any id)
1001
+ `,
1002
+ added: (refs, path) => `Added to models.enabled: ${refs} → ${path}
1003
+ `,
1004
+ alreadyListed: (refs) => `Already in models.enabled: ${refs}
1005
+ `,
1006
+ removed: (refs, path) => `Removed from models.enabled: ${refs} → ${path}
1007
+ `,
1008
+ notListed: (refs) => `Not in models.enabled: ${refs}
1009
+ `,
1010
+ cleared: (path) => `models.enabled is empty and was removed; /model shows every configured model again → ${path}
1011
+ `,
1012
+ listHeader: (path) => `models.enabled (${path}):
1013
+ `,
1014
+ listUnset: "models.enabled is not set; /model shows the models of configured providers:\n",
1015
+ notInTable: "not in the model table",
1016
+ nothing: " (none)\n"
1017
+ }
1018
+ };
1019
+ zh5 = {
1020
+ modelsEnabled: {
1021
+ badRef: (ref) => `ama: ${ref} 不是 provider/model[@channel] 或 provider/*
1022
+ `,
1023
+ unknownModel: (ref) => `ama: 警告:${ref} 不在模型表里,照样写入(中转站接受任意 id)
1024
+ `,
1025
+ added: (refs, path) => `已加入 models.enabled:${refs} → ${path}
1026
+ `,
1027
+ alreadyListed: (refs) => `已在 models.enabled 里:${refs}
1028
+ `,
1029
+ removed: (refs, path) => `已移出 models.enabled:${refs} → ${path}
1030
+ `,
1031
+ notListed: (refs) => `不在 models.enabled 里:${refs}
1032
+ `,
1033
+ cleared: (path) => `models.enabled 已清空并删除,/model 恢复显示全部已配置的模型 → ${path}
1034
+ `,
1035
+ listHeader: (path) => `models.enabled(${path}):
1036
+ `,
1037
+ listUnset: "未设置 models.enabled;/model 显示已配置供应商的模型:\n",
1038
+ notInTable: "不在模型表里",
1039
+ nothing: " (无)\n"
1040
+ }
1041
+ };
1042
+ }
1043
+ });
1044
+
1045
+ // src/i18n/messages/subcommands.ts
1046
+ var en6, zh6;
984
1047
  var init_subcommands = __esm({
985
1048
  "src/i18n/messages/subcommands.ts"() {
986
1049
  "use strict";
987
1050
  init_format();
988
1051
  init_subcommands_config();
989
- en5 = {
1052
+ init_subcommands_models();
1053
+ en6 = {
990
1054
  ...en4,
1055
+ ...en5,
991
1056
  /** 多个子命令共用。 */
992
1057
  common: {
993
1058
  warning: (text) => `ama: warning: ${text}
@@ -1238,8 +1303,9 @@ Estimated cost: ${estimate} (2 × ${tokens} tokens × catalog price)
1238
1303
  `
1239
1304
  }
1240
1305
  };
1241
- zh5 = {
1306
+ zh6 = {
1242
1307
  ...zh4,
1308
+ ...zh5,
1243
1309
  common: {
1244
1310
  warning: (text) => `ama: 警告:${text}
1245
1311
  `,
@@ -1505,12 +1571,12 @@ function zhWhy(why) {
1505
1571
  if (why.kind === "hook") return `(${why.reason})`;
1506
1572
  return `(Auto ${why.layer}:${why.reason})`;
1507
1573
  }
1508
- var en6, zh6;
1574
+ var en7, zh7;
1509
1575
  var init_interactive_line = __esm({
1510
1576
  "src/i18n/messages/interactive-line.ts"() {
1511
1577
  "use strict";
1512
1578
  init_format();
1513
- en6 = {
1579
+ en7 = {
1514
1580
  approvalOrigin: (task, title, where) => `${task}Allow ${title}${where !== void 0 ? ` ${where}` : ""}? [y allow / a allow all this session / N deny] `,
1515
1581
  approvalFirstRun: (task, note) => `${task}${note} Allow? [y allow / N deny] `,
1516
1582
  approvalTool: (task, tool, summary2, why) => `${task}Allow ${tool}${summary2 !== "" ? ` ${summary2}` : ""}${enWhy(why)}? [y allow / a allow all this session / N deny] `,
@@ -1532,7 +1598,7 @@ var init_interactive_line = __esm({
1532
1598
  steer: (text) => `↳ steer: ${text}`,
1533
1599
  pasteMarker: (id, lines2) => `[paste #${id} +${plural(lines2, "line")}]`
1534
1600
  };
1535
- zh6 = {
1601
+ zh7 = {
1536
1602
  approvalOrigin: (task, title, where) => `${task}允许 ${title}${where !== void 0 ? ` ${where}` : ""}?[y 允许 / a 本会话都允许 / N 拒绝] `,
1537
1603
  approvalFirstRun: (task, note) => `${task}${note} 允许?[y 允许 / N 拒绝] `,
1538
1604
  approvalTool: (task, tool, summary2, why) => `${task}允许 ${tool}${summary2 !== "" ? ` ${summary2}` : ""}${zhWhy(why)}?[y 允许 / a 本会话都允许 / N 拒绝] `,
@@ -1558,12 +1624,12 @@ var init_interactive_line = __esm({
1558
1624
  });
1559
1625
 
1560
1626
  // src/i18n/messages/interactive-startup.ts
1561
- var en7, zh7;
1627
+ var en8, zh8;
1562
1628
  var init_interactive_startup = __esm({
1563
1629
  "src/i18n/messages/interactive-startup.ts"() {
1564
1630
  "use strict";
1565
1631
  init_format();
1566
- en7 = {
1632
+ en8 = {
1567
1633
  header: {
1568
1634
  trusted: "trusted",
1569
1635
  untrusted: "untrusted",
@@ -1588,8 +1654,6 @@ var init_interactive_startup = __esm({
1588
1654
  hintFilter: (arrows) => `type to filter · ${arrows} select · Enter confirm · Esc cancel`,
1589
1655
  hintNumbers: (arrows, n) => `${arrows} select · Enter confirm · 1-${n} pick · Esc cancel`,
1590
1656
  hint: (arrows) => `${arrows} select · Enter confirm · Esc cancel`,
1591
- local: "local",
1592
- noKey: "no key",
1593
1657
  justNow: "just now",
1594
1658
  minutesAgo: (n) => `${n}m ago`,
1595
1659
  hoursAgo: (n) => `${n}h ago`,
@@ -1611,7 +1675,7 @@ var init_interactive_startup = __esm({
1611
1675
  cwdNotDir: (path) => `Not a directory: ${path}`
1612
1676
  }
1613
1677
  };
1614
- zh7 = {
1678
+ zh8 = {
1615
1679
  header: {
1616
1680
  trusted: "已信任",
1617
1681
  untrusted: "未信任",
@@ -1636,8 +1700,6 @@ var init_interactive_startup = __esm({
1636
1700
  hintFilter: (arrows) => `输入过滤 · ${arrows} 选择 · Enter 确认 · Esc 取消`,
1637
1701
  hintNumbers: (arrows, n) => `${arrows} 选择 · Enter 确认 · 1-${n} 直接选 · Esc 取消`,
1638
1702
  hint: (arrows) => `${arrows} 选择 · Enter 确认 · Esc 取消`,
1639
- local: "本地",
1640
- noKey: "无 key",
1641
1703
  justNow: "刚刚",
1642
1704
  minutesAgo: (n) => `${n} 分钟前`,
1643
1705
  hoursAgo: (n) => `${n} 小时前`,
@@ -1663,12 +1725,12 @@ var init_interactive_startup = __esm({
1663
1725
  });
1664
1726
 
1665
1727
  // src/i18n/messages/interactive-view.ts
1666
- var en8, zh8;
1728
+ var en9, zh9;
1667
1729
  var init_interactive_view = __esm({
1668
1730
  "src/i18n/messages/interactive-view.ts"() {
1669
1731
  "use strict";
1670
1732
  init_format();
1671
- en8 = {
1733
+ en9 = {
1672
1734
  message: {
1673
1735
  /** 退出摘要的时长:不足 1 分钟按秒,否则按分钟。 */
1674
1736
  duration: (seconds2) => seconds2 < 60 ? `${seconds2}s` : `${Math.round(seconds2 / 60)} min`,
@@ -1735,7 +1797,7 @@ var init_interactive_view = __esm({
1735
1797
  earlierCalls: (ellipsis, n) => `${ellipsis} ${plural(n, "earlier call")}`
1736
1798
  }
1737
1799
  };
1738
- zh8 = {
1800
+ zh9 = {
1739
1801
  message: {
1740
1802
  duration: (seconds2) => seconds2 < 60 ? `${seconds2} 秒` : `${Math.round(seconds2 / 60)} 分钟`,
1741
1803
  sessionPrefix: (rule) => `${rule} 会话 `,
@@ -1805,7 +1867,7 @@ var init_interactive_view = __esm({
1805
1867
  });
1806
1868
 
1807
1869
  // src/i18n/messages/interactive.ts
1808
- var en9, zh9;
1870
+ var en10, zh10;
1809
1871
  var init_interactive = __esm({
1810
1872
  "src/i18n/messages/interactive.ts"() {
1811
1873
  "use strict";
@@ -1813,7 +1875,7 @@ var init_interactive = __esm({
1813
1875
  init_interactive_line();
1814
1876
  init_interactive_startup();
1815
1877
  init_interactive_view();
1816
- en9 = {
1878
+ en10 = {
1817
1879
  commands: {
1818
1880
  /** [W6-C0] 第六波命令登记了但本构建还没有实现。 */
1819
1881
  unavailable: (name) => `/${name} is not available in this build yet`,
@@ -1929,11 +1991,11 @@ var init_interactive = __esm({
1929
1991
  editor: {
1930
1992
  completionFooter: "Tab accept · Esc close"
1931
1993
  },
1932
- view: en8,
1933
- startup: en7,
1934
- line: en6
1994
+ view: en9,
1995
+ startup: en8,
1996
+ line: en7
1935
1997
  };
1936
- zh9 = {
1998
+ zh10 = {
1937
1999
  commands: {
1938
2000
  unavailable: (name) => `/${name} 当前版本尚未提供`,
1939
2001
  treeDescription: "浏览会话树,回到某条消息之前重写",
@@ -2044,20 +2106,20 @@ var init_interactive = __esm({
2044
2106
  editor: {
2045
2107
  completionFooter: "Tab 接受 · Esc 关闭"
2046
2108
  },
2047
- view: zh8,
2048
- startup: zh7,
2049
- line: zh6
2109
+ view: zh9,
2110
+ startup: zh8,
2111
+ line: zh7
2050
2112
  };
2051
2113
  }
2052
2114
  });
2053
2115
 
2054
2116
  // src/i18n/messages/approval.ts
2055
- var en10, zh10;
2117
+ var en11, zh11;
2056
2118
  var init_approval = __esm({
2057
2119
  "src/i18n/messages/approval.ts"() {
2058
2120
  "use strict";
2059
2121
  init_format();
2060
- en10 = {
2122
+ en11 = {
2061
2123
  /** 外部 Agent 来源标注:`[claude · session abc12345]`。 */
2062
2124
  originLabel: (agent, sessionId) => `[${agent} · session ${sessionId}]`,
2063
2125
  /** 标题里的原因。 */
@@ -2105,7 +2167,7 @@ var init_approval = __esm({
2105
2167
  /** 通用确认框的按键行。 */
2106
2168
  choiceHint: (arrows, n) => `${arrows} select · Enter confirm · 1-${n} pick · Esc cancel`
2107
2169
  };
2108
- zh10 = {
2170
+ zh11 = {
2109
2171
  originLabel: (agent, sessionId) => `[${agent} · 会话 ${sessionId}]`,
2110
2172
  title: {
2111
2173
  firstRun: "首次运行外部 Agent",
@@ -2152,12 +2214,12 @@ var init_approval = __esm({
2152
2214
  });
2153
2215
 
2154
2216
  // src/i18n/messages/plan.ts
2155
- var en11, zh11;
2217
+ var en12, zh12;
2156
2218
  var init_plan = __esm({
2157
2219
  "src/i18n/messages/plan.ts"() {
2158
2220
  "use strict";
2159
2221
  init_format();
2160
- en11 = {
2222
+ en12 = {
2161
2223
  usage: "Usage: /plan [goal] | /plan approve [mode|fresh] | /plan reject",
2162
2224
  status: {
2163
2225
  proposed: "awaiting approval",
@@ -2214,7 +2276,7 @@ var init_plan = __esm({
2214
2276
  rejectedStay: (version) => `Rejected plan v${version} (still in Plan mode; /plan to view)`
2215
2277
  }
2216
2278
  };
2217
- zh11 = {
2279
+ zh12 = {
2218
2280
  usage: "用法:/plan [目标] | /plan approve [模式|fresh] | /plan reject",
2219
2281
  status: {
2220
2282
  proposed: "待审批",
@@ -2275,7 +2337,7 @@ var init_plan = __esm({
2275
2337
  });
2276
2338
 
2277
2339
  // src/i18n/messages/rewind.ts
2278
- var EN_SKIP, ZH_SKIP, en12, zh12;
2340
+ var EN_SKIP, ZH_SKIP, en13, zh13;
2279
2341
  var init_rewind = __esm({
2280
2342
  "src/i18n/messages/rewind.ts"() {
2281
2343
  "use strict";
@@ -2300,7 +2362,7 @@ var init_rewind = __esm({
2300
2362
  conflict: "冲突",
2301
2363
  failed: "失败"
2302
2364
  };
2303
- en12 = {
2365
+ en13 = {
2304
2366
  skip: {
2305
2367
  reason: (code) => EN_SKIP[code],
2306
2368
  failed: (message) => `failed: ${message}`,
@@ -2395,7 +2457,7 @@ var init_rewind = __esm({
2395
2457
  fileReason: (reason) => `: ${reason}`
2396
2458
  }
2397
2459
  };
2398
- zh12 = {
2460
+ zh13 = {
2399
2461
  skip: {
2400
2462
  reason: (code) => ZH_SKIP[code],
2401
2463
  failed: (message) => `失败:${message}`,
@@ -2492,12 +2554,12 @@ var init_rewind = __esm({
2492
2554
  });
2493
2555
 
2494
2556
  // src/i18n/messages/panels.ts
2495
- var en13, zh13;
2557
+ var en14, zh14;
2496
2558
  var init_panels = __esm({
2497
2559
  "src/i18n/messages/panels.ts"() {
2498
2560
  "use strict";
2499
2561
  init_format();
2500
- en13 = {
2562
+ en14 = {
2501
2563
  session: {
2502
2564
  title: (id) => `Session ${id}`,
2503
2565
  notSaved: "not saved",
@@ -2539,6 +2601,28 @@ var init_panels = __esm({
2539
2601
  thinkingUnsupported: "The current model does not support thinking",
2540
2602
  emptyText: "(empty)"
2541
2603
  },
2604
+ /** 模型选择器(`/model`、启动选择器、`/config` 的模型项)。 */
2605
+ model: {
2606
+ local: "local",
2607
+ key: "key ✓",
2608
+ oauth: "signed in ✓",
2609
+ needsLogin: "sign in again",
2610
+ noKey: "no key configured",
2611
+ current: "current",
2612
+ listed: "listed",
2613
+ otherChannels: (names) => `also ${names}`,
2614
+ discoverHint: (provider) => `Run ama models discover ${provider} to list its models`,
2615
+ loginHint: (provider) => `Run ama auth login ${provider} to sign in`,
2616
+ footerConfigured: "Tab all · Space list · @ channels · Enter switch · Esc cancel",
2617
+ footerAll: "Tab configured · Space list · @ channels · Enter switch · Esc cancel",
2618
+ emptyConfigured: "(no configured models; Tab shows all)",
2619
+ added: (ref) => `Added ${ref} to models.enabled`,
2620
+ addedFirst: (ref) => `Added ${ref} to models.enabled; /model now shows only listed models (Tab shows all)`,
2621
+ removed: (ref) => `Removed ${ref} from models.enabled`,
2622
+ wildcard: (ref, pattern) => `${ref} is listed through ${pattern}; remove it with ama models disable ${pattern}`,
2623
+ noKeyHint: (provider) => `${provider} has no key: run ama auth set ${provider} (custom providers: ama providers add)`,
2624
+ needsLoginHint: (provider) => `${provider} needs a new sign-in: run ama auth login ${provider}`
2625
+ },
2542
2626
  plan: {
2543
2627
  title: "Plan",
2544
2628
  titleVersion: (version) => `Plan v${version}`,
@@ -2586,7 +2670,7 @@ var init_panels = __esm({
2586
2670
  title: (id) => `Task ${id}`
2587
2671
  }
2588
2672
  };
2589
- zh13 = {
2673
+ zh14 = {
2590
2674
  session: {
2591
2675
  title: (id) => `会话 ${id}`,
2592
2676
  notSaved: "未落盘",
@@ -2628,6 +2712,27 @@ var init_panels = __esm({
2628
2712
  thinkingUnsupported: "当前模型不支持思考",
2629
2713
  emptyText: "(空)"
2630
2714
  },
2715
+ model: {
2716
+ local: "本地",
2717
+ key: "key ✓",
2718
+ oauth: "已登录 ✓",
2719
+ needsLogin: "需重新登录",
2720
+ noKey: "未配置 key",
2721
+ current: "当前",
2722
+ listed: "清单内",
2723
+ otherChannels: (names) => `另有 ${names}`,
2724
+ discoverHint: (provider) => `运行 ama models discover ${provider} 获取模型`,
2725
+ loginHint: (provider) => `运行 ama auth login ${provider} 登录`,
2726
+ footerConfigured: "Tab 全部 · Space 清单 · @ 渠道 · Enter 切换 · Esc 取消",
2727
+ footerAll: "Tab 已配置 · Space 清单 · @ 渠道 · Enter 切换 · Esc 取消",
2728
+ emptyConfigured: "(没有已配置的模型,Tab 看全部)",
2729
+ added: (ref) => `已把 ${ref} 加入 models.enabled`,
2730
+ addedFirst: (ref) => `已把 ${ref} 加入 models.enabled;/model 之后只显示清单内的模型(Tab 看全部)`,
2731
+ removed: (ref) => `已把 ${ref} 移出 models.enabled`,
2732
+ wildcard: (ref, pattern) => `${ref} 经 ${pattern} 列入清单;用 ama models disable ${pattern} 移除`,
2733
+ noKeyHint: (provider) => `${provider} 未配置 key:运行 ama auth set ${provider}(自定义供应商用 ama providers add)`,
2734
+ needsLoginHint: (provider) => `${provider} 需要重新登录:运行 ama auth login ${provider}`
2735
+ },
2631
2736
  plan: {
2632
2737
  title: "计划",
2633
2738
  titleVersion: (version) => `计划 v${version}`,
@@ -2679,7 +2784,7 @@ var init_panels = __esm({
2679
2784
  });
2680
2785
 
2681
2786
  // src/i18n/messages/permissions.ts
2682
- var EN_VERB, ZH_VERB, EN_NOTE, ZH_NOTE, en14, zh14;
2787
+ var EN_VERB, ZH_VERB, EN_NOTE, ZH_NOTE, en15, zh15;
2683
2788
  var init_permissions = __esm({
2684
2789
  "src/i18n/messages/permissions.ts"() {
2685
2790
  "use strict";
@@ -2712,7 +2817,7 @@ var init_permissions = __esm({
2712
2817
  overwritten: "(已存在,将被覆盖)",
2713
2818
  gitCleanTracked: "(计数含已跟踪文件,实际只删未跟踪的)"
2714
2819
  };
2715
- en14 = {
2820
+ en15 = {
2716
2821
  /** 六种权限模式的一行说明(`permissions/modes.ts`)。 */
2717
2822
  modeDescription: {
2718
2823
  default: "Ask before writing files or running commands",
@@ -2770,7 +2875,7 @@ var init_permissions = __esm({
2770
2875
  moreLines: (n) => `… ${plural(n, "more line")}`
2771
2876
  }
2772
2877
  };
2773
- zh14 = {
2878
+ zh15 = {
2774
2879
  modeDescription: {
2775
2880
  default: "写文件、执行命令前询问",
2776
2881
  autoEdit: "自动接受文件编辑,执行命令仍询问",
@@ -2830,12 +2935,12 @@ var init_permissions = __esm({
2830
2935
  });
2831
2936
 
2832
2937
  // src/i18n/messages/report.ts
2833
- var en15, zh15;
2938
+ var en16, zh16;
2834
2939
  var init_report = __esm({
2835
2940
  "src/i18n/messages/report.ts"() {
2836
2941
  "use strict";
2837
2942
  init_format();
2838
- en15 = {
2943
+ en16 = {
2839
2944
  /** 内置斜杠命令:`args` 只写需要翻译的占位,说明整句。 */
2840
2945
  commands: {
2841
2946
  help: "List commands",
@@ -3075,7 +3180,7 @@ Available: ${inactive.join(", ")}` : ""}`,
3075
3180
  userHooks: (path) => `User hooks.json: ${path}`
3076
3181
  }
3077
3182
  };
3078
- zh15 = {
3183
+ zh16 = {
3079
3184
  commands: {
3080
3185
  help: "列出命令",
3081
3186
  new: "新建会话",
@@ -3310,12 +3415,12 @@ Available: ${inactive.join(", ")}` : ""}`,
3310
3415
  });
3311
3416
 
3312
3417
  // src/i18n/messages/print.ts
3313
- var en16, zh16;
3418
+ var en17, zh17;
3314
3419
  var init_print = __esm({
3315
3420
  "src/i18n/messages/print.ts"() {
3316
3421
  "use strict";
3317
3422
  init_format();
3318
- en16 = {
3423
+ en17 = {
3319
3424
  /** `ama -p` 的 stderr。 */
3320
3425
  print: {
3321
3426
  stdinIgnored: (wait) => `ama: no piped input within ${wait}, ignored; to wait for it, end the arguments with -
@@ -3358,7 +3463,7 @@ var init_print = __esm({
3358
3463
  truncated: (length) => `…(truncated, ${plural(length, "character")} in total)`
3359
3464
  }
3360
3465
  };
3361
- zh16 = {
3466
+ zh17 = {
3362
3467
  print: {
3363
3468
  stdinIgnored: (wait) => `ama: 未在 ${wait}内收到管道输入,已忽略;需要等待请在末尾加 -
3364
3469
  `,
@@ -3402,7 +3507,7 @@ var init_print = __esm({
3402
3507
  });
3403
3508
 
3404
3509
  // src/i18n/messages/config-keys.ts
3405
- var dynamicDefaultsEn, dynamicDefaultsZh, keysEn, keysZh, en17, zh17;
3510
+ var dynamicDefaultsEn, dynamicDefaultsZh, keysEn, keysZh, en18, zh18;
3406
3511
  var init_config_keys = __esm({
3407
3512
  "src/i18n/messages/config-keys.ts"() {
3408
3513
  "use strict";
@@ -3420,6 +3525,7 @@ var init_config_keys = __esm({
3420
3525
  "subagents.defaultModel": "unset: inherit the parent session model",
3421
3526
  "models.aliases.fast": "unset: fast is treated as inherit",
3422
3527
  "models.aliases.strong": "unset: strong is treated as inherit",
3528
+ "models.enabled": "unset: /model shows every model of configured providers",
3423
3529
  fallbackModel: "unset: no fallback",
3424
3530
  "limits.maxTurns": "unset: unlimited",
3425
3531
  "limits.maxCostUsd": "unset: unlimited",
@@ -3442,6 +3548,7 @@ var init_config_keys = __esm({
3442
3548
  "subagents.defaultModel": "不设:继承父会话模型",
3443
3549
  "models.aliases.fast": "不设:fast 按 inherit 处理",
3444
3550
  "models.aliases.strong": "不设:strong 按 inherit 处理",
3551
+ "models.enabled": "不设:/model 显示已配置供应商的全部模型",
3445
3552
  fallbackModel: "不设:不回退",
3446
3553
  "limits.maxTurns": "不设:不限",
3447
3554
  "limits.maxCostUsd": "不设:不限",
@@ -3551,10 +3658,11 @@ var init_config_keys = __esm({
3551
3658
  "subagents.maxConcurrent": "Sub-sessions running at the same time",
3552
3659
  "subagents.maxPending": "Queue limit; task fails beyond it",
3553
3660
  "subagents.defaultModel": "Default sub-session model provider/model[@channel]",
3554
- models: "Model aliases; user level only (effective from wave 5 W5-G)",
3661
+ models: "Model aliases and the model picker list; user level only (effective from wave 5 W5-G)",
3555
3662
  "models.aliases": "Models that model: fast / strong in sub-agent definitions point to",
3556
3663
  "models.aliases.fast": "Model for the fast alias provider/model[@channel]",
3557
3664
  "models.aliases.strong": "Model for the strong alias provider/model[@channel]",
3665
+ "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",
3558
3666
  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)",
3559
3667
  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)",
3560
3668
  "limits.maxTurns": "Maximum turns per run",
@@ -3668,10 +3776,11 @@ var init_config_keys = __esm({
3668
3776
  "subagents.maxConcurrent": "同时运行的子会话数",
3669
3777
  "subagents.maxPending": "排队上限,超出时 task 报错",
3670
3778
  "subagents.defaultModel": "子会话缺省模型 provider/model[@channel]",
3671
- models: "模型别名;只认用户级(第五波 W5-G 起生效)",
3779
+ models: "模型别名与模型选择器清单;只认用户级(第五波 W5-G 起生效)",
3672
3780
  "models.aliases": "子 Agent 定义里 model: fast / strong 指向的模型",
3673
3781
  "models.aliases.fast": "fast 别名的模型 provider/model[@channel]",
3674
3782
  "models.aliases.strong": "strong 别名的模型 provider/model[@channel]",
3783
+ "models.enabled": "/model 显示的模型(provider/model[@channel],provider/* 表示整个供应商);不设:已配置 key、已登录或本地可达的供应商的全部模型",
3675
3784
  fallbackModel: "回退模型 provider/model[@channel]:可重试错误用尽或过载时切换重试一次,下一回合回主模型;只认用户级(第五波 W5-H2 起生效)",
3676
3785
  limits: "会话预算,到限结束本次运行(-p 退出码 8);--max-turns / --max-cost 覆盖;只认用户级(第五波 W5-H2 起生效)",
3677
3786
  "limits.maxTurns": "一次运行最多回合数",
@@ -3684,8 +3793,8 @@ var init_config_keys = __esm({
3684
3793
  todo: "todo 工具;只认用户级(第五波 W5-F / W5-H2 起生效)",
3685
3794
  "todo.reminder": "连续 N 回合未更新且有未完成项时提醒复述;0 关闭"
3686
3795
  };
3687
- en17 = { keys: keysEn, dynamicDefaults: dynamicDefaultsEn };
3688
- zh17 = {
3796
+ en18 = { keys: keysEn, dynamicDefaults: dynamicDefaultsEn };
3797
+ zh18 = {
3689
3798
  keys: keysZh,
3690
3799
  dynamicDefaults: dynamicDefaultsZh
3691
3800
  };
@@ -3693,12 +3802,12 @@ var init_config_keys = __esm({
3693
3802
  });
3694
3803
 
3695
3804
  // src/i18n/messages/config.ts
3696
- var en18, zh18;
3805
+ var en19, zh19;
3697
3806
  var init_config = __esm({
3698
3807
  "src/i18n/messages/config.ts"() {
3699
3808
  "use strict";
3700
3809
  init_config_keys();
3701
- en18 = {
3810
+ en19 = {
3702
3811
  /** 配置校验诊断(checker.ts、schema.ts、schema-w5.ts、schema-w6.ts)。 */
3703
3812
  schema: {
3704
3813
  enumArray: (choices) => `should be an array of ${choices.join(" | ")}`,
@@ -3717,6 +3826,7 @@ var init_config = __esm({
3717
3826
  stringArray: "should be an array of strings",
3718
3827
  array: "should be an array",
3719
3828
  modelsDev: `should be "provider/model" or false`,
3829
+ modelsEnabled: `should be "provider/model[@channel]" or "provider/*"`,
3720
3830
  noChannels: "the provider has no channels",
3721
3831
  unknownChannelOf: (name, available) => `channel "${name}" does not exist (available: ${available.join(", ")})`,
3722
3832
  modelInput: `should be ("text" | "image")[]`,
@@ -3818,9 +3928,9 @@ var init_config = __esm({
3818
3928
  models: "Custom models (an entry with the same id replaces the whole model)",
3819
3929
  modelOverrides: "Only changes metadata of existing models"
3820
3930
  },
3821
- ...en17
3931
+ ...en18
3822
3932
  };
3823
- zh18 = {
3933
+ zh19 = {
3824
3934
  schema: {
3825
3935
  enumArray: (choices) => `应为 ${choices.join(" | ")} 组成的数组`,
3826
3936
  ports: "应为端口号数组(0–65535;0 = 任意空闲端口)",
@@ -3838,6 +3948,7 @@ var init_config = __esm({
3838
3948
  stringArray: "应为字符串数组",
3839
3949
  array: "应为数组",
3840
3950
  modelsDev: `应为 "provider/model" 或 false`,
3951
+ modelsEnabled: `应为 "provider/model[@channel]" 或 "provider/*"`,
3841
3952
  noChannels: "供应商没有 channels",
3842
3953
  unknownChannelOf: (name, available) => `渠道 "${name}" 不存在(可用:${available.join(", ")})`,
3843
3954
  modelInput: `应为 ("text" | "image")[]`,
@@ -3931,18 +4042,18 @@ var init_config = __esm({
3931
4042
  models: "自定义模型(同 id 整条替换)",
3932
4043
  modelOverrides: "只改已有模型的元数据"
3933
4044
  },
3934
- ...zh17
4045
+ ...zh18
3935
4046
  };
3936
4047
  }
3937
4048
  });
3938
4049
 
3939
4050
  // src/i18n/messages/drivers.ts
3940
- var en19, zh19;
4051
+ var en20, zh20;
3941
4052
  var init_drivers = __esm({
3942
4053
  "src/i18n/messages/drivers.ts"() {
3943
4054
  "use strict";
3944
4055
  init_format();
3945
- en19 = {
4056
+ en20 = {
3946
4057
  /** 外部 Agent 的 notice 与日志。 */
3947
4058
  agent: {
3948
4059
  reapedOrphans: (pids) => `cleaned up external agent processes left over from last time: ${pids}`,
@@ -4002,7 +4113,7 @@ var init_drivers = __esm({
4002
4113
  noId: (label2) => `${label2}: the adapter returned by create() has no id`
4003
4114
  }
4004
4115
  };
4005
- zh19 = {
4116
+ zh20 = {
4006
4117
  agent: {
4007
4118
  reapedOrphans: (pids) => `清理了上次遗留的外部 Agent 进程:${pids}`,
4008
4119
  unverifiedVersion: (program, version, verified) => `${program} ${version} 不在已验证区间 ${verified},协议可能有变化`,
@@ -4063,12 +4174,12 @@ var init_drivers = __esm({
4063
4174
  });
4064
4175
 
4065
4176
  // src/i18n/messages/session.ts
4066
- var en20, zh20;
4177
+ var en21, zh21;
4067
4178
  var init_session = __esm({
4068
4179
  "src/i18n/messages/session.ts"() {
4069
4180
  "use strict";
4070
4181
  init_format();
4071
- en20 = {
4182
+ en21 = {
4072
4183
  /** `ama sessions list / show / prune`(search / export / trace 各有自己的文案)。 */
4073
4184
  cli: {
4074
4185
  usage: `Usage: ama sessions list [--all] [--session-dir <dir>]
@@ -4204,7 +4315,7 @@ var init_session = __esm({
4204
4315
  }
4205
4316
  }
4206
4317
  };
4207
- zh20 = {
4318
+ zh21 = {
4208
4319
  cli: {
4209
4320
  usage: `用法:ama sessions list [--all] [--session-dir <目录>]
4210
4321
  ama sessions show <id> [--session-dir <目录>]
@@ -4337,7 +4448,7 @@ var init_session = __esm({
4337
4448
  });
4338
4449
 
4339
4450
  // src/i18n/messages/errors.ts
4340
- var EN_HINT, ZH_HINT, en21, zh21;
4451
+ var EN_HINT, ZH_HINT, en22, zh22;
4341
4452
  var init_errors2 = __esm({
4342
4453
  "src/i18n/messages/errors.ts"() {
4343
4454
  "use strict";
@@ -4352,7 +4463,7 @@ var init_errors2 = __esm({
4352
4463
  no_tool: "(没找到缩放工具:装 ImageMagick,macOS 自带 sips)",
4353
4464
  still_too_large: "(缩放后仍超限)"
4354
4465
  };
4355
- en21 = {
4466
+ en22 = {
4356
4467
  /** [W6-I3] 图片附件:当前模型不收图片(`--image` / `@路径`)。 */
4357
4468
  imageUnsupported: (model) => `${model ?? "The current model"} does not accept image input (the model's input has no image); switch to a model that supports images (marked "image" in ama models list, or give the model "input": ["text", "image"] in the config)`,
4358
4469
  /** [W6-I3] SDK(`createRuntime` / `createAgentSession`)。 */
@@ -4424,7 +4535,7 @@ var init_errors2 = __esm({
4424
4535
  }
4425
4536
  }
4426
4537
  };
4427
- zh21 = {
4538
+ zh22 = {
4428
4539
  imageUnsupported: (model) => `${model ?? "当前模型"} 不接受图片输入(模型 input 没有 image);换一个支持图像的模型再试(ama models list 里标「图片」的,或在配置里给该模型写 "input": ["text", "image"])`,
4429
4540
  cacheParamsStripped: (key, field2, suggestion) => `${key}:该端点不支持 ${field2},已自动去掉缓存参数重发;可在 config 里设 ${suggestion ?? "相应的 compat 开关"}`,
4430
4541
  sdk: {
@@ -4495,12 +4606,12 @@ var init_errors2 = __esm({
4495
4606
  });
4496
4607
 
4497
4608
  // src/i18n/messages/agents.ts
4498
- var en22, zh22;
4609
+ var en23, zh23;
4499
4610
  var init_agents = __esm({
4500
4611
  "src/i18n/messages/agents.ts"() {
4501
4612
  "use strict";
4502
4613
  init_format();
4503
- en22 = {
4614
+ en23 = {
4504
4615
  status: {
4505
4616
  queued: "queued",
4506
4617
  running: "running",
@@ -4538,7 +4649,7 @@ var init_agents = __esm({
4538
4649
  externalNoSession: (runner) => `Live output is kept only in memory; ${runner} did not report a session to resume.`
4539
4650
  }
4540
4651
  };
4541
- zh22 = {
4652
+ zh23 = {
4542
4653
  status: {
4543
4654
  queued: "排队",
4544
4655
  running: "运行中",
@@ -4580,12 +4691,12 @@ var init_agents = __esm({
4580
4691
  });
4581
4692
 
4582
4693
  // src/i18n/messages/trace.ts
4583
- var en23, zh23;
4694
+ var en24, zh24;
4584
4695
  var init_trace = __esm({
4585
4696
  "src/i18n/messages/trace.ts"() {
4586
4697
  "use strict";
4587
4698
  init_format();
4588
- en23 = {
4699
+ en24 = {
4589
4700
  title: "Trace",
4590
4701
  /** 顶部汇总行。 */
4591
4702
  summary: (turns, requests, tools) => `${plural(turns, "turn")} · ${plural(requests, "request")} · ${plural(tools, "tool call")}`,
@@ -4704,7 +4815,7 @@ var init_trace = __esm({
4704
4815
  badNow: (raw) => `--now expects epoch milliseconds (got ${raw})`
4705
4816
  }
4706
4817
  };
4707
- zh23 = {
4818
+ zh24 = {
4708
4819
  title: "轨迹",
4709
4820
  summary: (turns, requests, tools) => `${turns} 回合 · ${requests} 请求 · ${tools} 次工具`,
4710
4821
  cache: (percent2) => `缓存 ${percent2}`,
@@ -4823,12 +4934,12 @@ var init_trace = __esm({
4823
4934
  });
4824
4935
 
4825
4936
  // src/i18n/messages/memory.ts
4826
- var en24, zh24;
4937
+ var en25, zh25;
4827
4938
  var init_memory = __esm({
4828
4939
  "src/i18n/messages/memory.ts"() {
4829
4940
  "use strict";
4830
4941
  init_format();
4831
- en24 = {
4942
+ en25 = {
4832
4943
  scope: { user: "user", project: "project", workspace: "workspace" },
4833
4944
  panel: {
4834
4945
  title: "Memory",
@@ -4888,7 +4999,7 @@ var init_memory = __esm({
4888
4999
  untrusted: (cwd) => `Project scope skipped: ${cwd} is not trusted (run ama --trust there once).`
4889
5000
  }
4890
5001
  };
4891
- zh24 = {
5002
+ zh25 = {
4892
5003
  scope: { user: "用户", project: "项目", workspace: "工作空间" },
4893
5004
  panel: {
4894
5005
  title: "记忆",
@@ -4952,11 +5063,11 @@ var init_memory = __esm({
4952
5063
  });
4953
5064
 
4954
5065
  // src/i18n/messages/auth.ts
4955
- var en25, zh25;
5066
+ var en26, zh26;
4956
5067
  var init_auth = __esm({
4957
5068
  "src/i18n/messages/auth.ts"() {
4958
5069
  "use strict";
4959
- en25 = {
5070
+ en26 = {
4960
5071
  usage: `Usage: ama auth set <provider> [--auth-file <file>] read the key from stdin
4961
5072
  ama auth list [--auth-file <file>]
4962
5073
  ama auth remove <provider> [--auth-file <file>]
@@ -5002,12 +5113,16 @@ Then paste the full URL from the address bar (http://127.0.0.1:…/auth/callback
5002
5113
  loggedIn: (flavor, plan2, email, path) => `Signed in to ChatGPT (${flavor}${plan2 !== void 0 ? ` · ${plan2}` : ""}${email !== void 0 ? ` · ${email}` : ""}) → ${path} (0600)`,
5003
5114
  siwcLimitHint: "Tip: set a weekly limit for ama in ChatGPT → Settings → Usage → App limits. For personal use only; never share one sign-in between several people.",
5004
5115
  freePlanHint: (plan2) => `Note: the "${plan2}" plan may not include subscription usage for ama.`,
5005
- modelHint: "Use it with --model chatgpt/<model>; list the models your account can use with ama models discover chatgpt."
5116
+ modelHint: "Use it with --model chatgpt/<model>; list the models your account can use with ama models discover chatgpt.",
5117
+ modelsCached: (count2) => `Your account can use ${count2} model(s); pick one with /model or --model chatgpt/<model>.`
5006
5118
  },
5007
5119
  errors: {
5008
5120
  portsBusy: (ports, codex) => `callback port ${ports} is in use: finish the other sign-in first, or use --paste${codex ? " / --device" : ""}`,
5009
5121
  timeout: "sign-in timed out; run the command again",
5010
- denied: (error2) => `sign-in was not authorized (${error2})`,
5122
+ denied: (error2, codexFallback) => `sign-in was not authorized (${error2}). Possible causes:
5123
+ 1. The authorization page was cancelled, or using your ChatGPT plan was not checked: run ama auth login chatgpt again and keep that option checked
5124
+ 2. The account or plan is not eligible: plan usage is shared with Plus / Pro only; Team / Enterprise workspaces may not offer it; the browser may be signed in to another account
5125
+ 3. Your region is not supported` + (codexFallback ? "\nYou can also try the fallback: ama auth login chatgpt --flavor codex" : ""),
5011
5126
  stateMismatch: "the pasted URL does not belong to this sign-in (state mismatch); start again",
5012
5127
  noCode: "the pasted URL has no code; copy the whole address after the browser redirects",
5013
5128
  invalidToken: (reason) => `id_token failed verification (${reason}); sign-in rejected`,
@@ -5053,7 +5168,7 @@ Then paste the full URL from the address bar (http://127.0.0.1:…/auth/callback
5053
5168
  relogin: (provider) => `${provider}: sign-in expired, run ama auth login ${provider}`
5054
5169
  }
5055
5170
  };
5056
- zh25 = {
5171
+ zh26 = {
5057
5172
  usage: `用法:ama auth set <provider> [--auth-file <文件>] 从 stdin 读取 key
5058
5173
  ama auth list [--auth-file <文件>]
5059
5174
  ama auth remove <provider> [--auth-file <文件>]
@@ -5099,12 +5214,16 @@ Then paste the full URL from the address bar (http://127.0.0.1:…/auth/callback
5099
5214
  loggedIn: (flavor, plan2, email, path) => `已登录 ChatGPT(${flavor}${plan2 !== void 0 ? ` · ${plan2}` : ""}${email !== void 0 ? ` · ${email}` : ""})→ ${path}(0600)`,
5100
5215
  siwcLimitHint: "提示:可在 ChatGPT → 设置 → Usage → App limits 给 ama 设周上限。仅限本人使用,不要让多人共用一个登录。",
5101
5216
  freePlanHint: (plan2) => `注意:「${plan2}」计划可能不含给 ama 用的订阅额度。`,
5102
- modelHint: "用 --model chatgpt/<模型> 使用;账户可用的模型用 ama models discover chatgpt 查看。"
5217
+ modelHint: "用 --model chatgpt/<模型> 使用;账户可用的模型用 ama models discover chatgpt 查看。",
5218
+ modelsCached: (count2) => `账户可用 ${count2} 个模型,用 /model 或 --model chatgpt/<模型> 选择。`
5103
5219
  },
5104
5220
  errors: {
5105
5221
  portsBusy: (ports, codex) => `回调端口 ${ports} 被占用:请先结束其它登录,或用 --paste${codex ? " / --device" : ""}`,
5106
5222
  timeout: "登录超时,请重新运行命令",
5107
- denied: (error2) => `授权未通过(${error2})`,
5223
+ denied: (error2, codexFallback) => `授权未通过(${error2})。可能的原因:
5224
+ 1. 在授权页取消了,或没有勾选使用 ChatGPT 套餐额度:重新运行 ama auth login chatgpt 并确认勾选
5225
+ 2. 账户或套餐不符合:额度共享只对 Plus / Pro 开放;Team / Enterprise 工作空间可能未开放;浏览器可能登录了别的账户
5226
+ 3. 所在地区受限` + (codexFallback ? "\n也可以改用备用方式:ama auth login chatgpt --flavor codex" : ""),
5108
5227
  stateMismatch: "粘贴的 URL 不属于这次登录(state 不符),请重新开始",
5109
5228
  noCode: "粘贴的 URL 里没有 code;请在浏览器跳转后复制完整地址",
5110
5229
  invalidToken: (reason) => `id_token 校验失败(${reason}),已拒绝这次登录`,
@@ -5154,11 +5273,11 @@ Then paste the full URL from the address bar (http://127.0.0.1:…/auth/callback
5154
5273
  });
5155
5274
 
5156
5275
  // src/i18n/messages/settings.ts
5157
- var en26, zh26;
5276
+ var en27, zh27;
5158
5277
  var init_settings = __esm({
5159
5278
  "src/i18n/messages/settings.ts"() {
5160
5279
  "use strict";
5161
- en26 = {
5280
+ en27 = {
5162
5281
  groups: {
5163
5282
  ui: "Interface",
5164
5283
  model: "Model",
@@ -5278,6 +5397,9 @@ var init_settings = __esm({
5278
5397
  setDone: (key, value, scope) => `${key} = ${value} (${scope})`,
5279
5398
  unsetDone: (key, value, scope) => `${key} reset (${scope}); now ${value}`,
5280
5399
  stillOverridden: (key, source) => `${key} is still overridden by ${source}; the saved value applies once that is removed`,
5400
+ /** `ama config set` when a higher layer hides the write: first line = what was written. */
5401
+ writtenTo: (key, value, scope) => `${key} = ${value} (written to ${scope})`,
5402
+ overriddenNow: (source, effective) => `Still overridden by ${source} (${effective}); the effective value is ${effective}`,
5281
5403
  slashUsage: "Usage: /config [key=value | key value]",
5282
5404
  errors: {
5283
5405
  unknownKey: (key) => `${key} isn't a /config setting. Run /config to see what's available.`,
@@ -5305,7 +5427,8 @@ var init_settings = __esm({
5305
5427
  sandboxWritable: "ama config set sandbox.writable --json-value",
5306
5428
  agents: "agents.<id>: ama config edit",
5307
5429
  hooks: "hooks.json · /hooks",
5308
- auth: "ama auth"
5430
+ auth: "ama auth",
5431
+ modelsEnabled: "/model (Space) · ama models enable / disable"
5309
5432
  },
5310
5433
  cli: {
5311
5434
  usage: `Usage: ama config get <key> [--json]
@@ -5323,7 +5446,7 @@ var init_settings = __esm({
5323
5446
  missingValue: "missing <value>"
5324
5447
  }
5325
5448
  };
5326
- zh26 = {
5449
+ zh27 = {
5327
5450
  groups: {
5328
5451
  ui: "界面",
5329
5452
  model: "模型",
@@ -5442,6 +5565,8 @@ var init_settings = __esm({
5442
5565
  setDone: (key, value, scope) => `${key} = ${value}(${scope})`,
5443
5566
  unsetDone: (key, value, scope) => `已恢复 ${key}(${scope}),现为 ${value}`,
5444
5567
  stillOverridden: (key, source) => `${key} 仍被 ${source} 覆盖,撤掉后写入的值才生效`,
5568
+ writtenTo: (key, value, scope) => `${key} = ${value}(已写入${scope})`,
5569
+ overriddenNow: (source, effective) => `当前仍被 ${source}(${effective})覆盖,生效值为 ${effective}`,
5445
5570
  slashUsage: "用法:/config [key=value | key value]",
5446
5571
  errors: {
5447
5572
  unknownKey: (key) => `${key} 不是可设置项,用 /config 查看`,
@@ -5469,7 +5594,8 @@ var init_settings = __esm({
5469
5594
  sandboxWritable: "ama config set sandbox.writable --json-value",
5470
5595
  agents: "agents.<id>:ama config edit",
5471
5596
  hooks: "hooks.json · /hooks",
5472
- auth: "ama auth"
5597
+ auth: "ama auth",
5598
+ modelsEnabled: "/model(Space)· ama models enable / disable"
5473
5599
  },
5474
5600
  cli: {
5475
5601
  usage: `用法:ama config get <key> [--json]
@@ -5491,7 +5617,7 @@ var init_settings = __esm({
5491
5617
  });
5492
5618
 
5493
5619
  // src/i18n/catalog.ts
5494
- var en27, zh27, CATALOGS, MESSAGE_DOMAINS;
5620
+ var en28, zh28, CATALOGS, MESSAGE_DOMAINS;
5495
5621
  var init_catalog = __esm({
5496
5622
  "src/i18n/catalog.ts"() {
5497
5623
  "use strict";
@@ -5514,50 +5640,50 @@ var init_catalog = __esm({
5514
5640
  init_memory();
5515
5641
  init_auth();
5516
5642
  init_settings();
5517
- en27 = {
5643
+ en28 = {
5518
5644
  cli: en3,
5519
- subcommands: en5,
5520
- interactive: en9,
5521
- approval: en10,
5522
- plan: en11,
5523
- rewind: en12,
5524
- panels: en13,
5525
- permissions: en14,
5526
- report: en15,
5527
- print: en16,
5528
- config: en18,
5529
- drivers: en19,
5530
- session: en20,
5531
- errors: en21,
5532
- agents: en22,
5533
- trace: en23,
5534
- memory: en24,
5535
- auth: en25,
5536
- settings: en26
5537
- };
5538
- zh27 = {
5645
+ subcommands: en6,
5646
+ interactive: en10,
5647
+ approval: en11,
5648
+ plan: en12,
5649
+ rewind: en13,
5650
+ panels: en14,
5651
+ permissions: en15,
5652
+ report: en16,
5653
+ print: en17,
5654
+ config: en19,
5655
+ drivers: en20,
5656
+ session: en21,
5657
+ errors: en22,
5658
+ agents: en23,
5659
+ trace: en24,
5660
+ memory: en25,
5661
+ auth: en26,
5662
+ settings: en27
5663
+ };
5664
+ zh28 = {
5539
5665
  cli: zh3,
5540
- subcommands: zh5,
5541
- interactive: zh9,
5542
- approval: zh10,
5543
- plan: zh11,
5544
- rewind: zh12,
5545
- panels: zh13,
5546
- permissions: zh14,
5547
- report: zh15,
5548
- print: zh16,
5549
- config: zh18,
5550
- drivers: zh19,
5551
- session: zh20,
5552
- errors: zh21,
5553
- agents: zh22,
5554
- trace: zh23,
5555
- memory: zh24,
5556
- auth: zh25,
5557
- settings: zh26
5558
- };
5559
- CATALOGS = { en: en27, zh: zh27 };
5560
- MESSAGE_DOMAINS = Object.keys(en27);
5666
+ subcommands: zh6,
5667
+ interactive: zh10,
5668
+ approval: zh11,
5669
+ plan: zh12,
5670
+ rewind: zh13,
5671
+ panels: zh14,
5672
+ permissions: zh15,
5673
+ report: zh16,
5674
+ print: zh17,
5675
+ config: zh19,
5676
+ drivers: zh20,
5677
+ session: zh21,
5678
+ errors: zh22,
5679
+ agents: zh23,
5680
+ trace: zh24,
5681
+ memory: zh25,
5682
+ auth: zh26,
5683
+ settings: zh27
5684
+ };
5685
+ CATALOGS = { en: en28, zh: zh28 };
5686
+ MESSAGE_DOMAINS = Object.keys(en28);
5561
5687
  }
5562
5688
  });
5563
5689
 
@@ -6192,7 +6318,14 @@ function validateConfigW5(c, config) {
6192
6318
  c.number(s2, "maxPending", p, 0, 1024);
6193
6319
  c.string(s2, "defaultModel", p);
6194
6320
  });
6195
- checkSection(c, config, "models", ["aliases"], (s2, p) => {
6321
+ checkSection(c, config, "models", ["aliases", "enabled"], (s2, p) => {
6322
+ c.stringArray(s2, "enabled", p);
6323
+ const enabled = s2["enabled"];
6324
+ if (Array.isArray(enabled))
6325
+ enabled.forEach((ref, i) => {
6326
+ if (typeof ref === "string" && !MODELS_ENABLED_REF.test(ref))
6327
+ c.error(join(join(p, "enabled"), i), msg().config.schema.modelsEnabled);
6328
+ });
6196
6329
  const aliases = s2["aliases"];
6197
6330
  const ap = join(p, "aliases");
6198
6331
  if (aliases === void 0 || !c.object(aliases, ap)) return;
@@ -9185,12 +9318,12 @@ function editDistance(a, b) {
9185
9318
  if (b.length === 0) return a.length;
9186
9319
  let prev = Array.from({ length: b.length + 1 }, (_, i) => i);
9187
9320
  for (let i = 1; i <= a.length; i++) {
9188
- const row2 = [i];
9321
+ const row3 = [i];
9189
9322
  for (let j = 1; j <= b.length; j++) {
9190
9323
  const cost2 = a[i - 1] === b[j - 1] ? 0 : 1;
9191
- row2[j] = Math.min((prev[j] ?? 0) + 1, (row2[j - 1] ?? 0) + 1, (prev[j - 1] ?? 0) + cost2);
9324
+ row3[j] = Math.min((prev[j] ?? 0) + 1, (row3[j - 1] ?? 0) + 1, (prev[j - 1] ?? 0) + cost2);
9192
9325
  }
9193
- prev = row2;
9326
+ prev = row3;
9194
9327
  }
9195
9328
  return prev[b.length] ?? 0;
9196
9329
  }
@@ -20550,11 +20683,11 @@ function addSubscription(stats, provider, usage) {
20550
20683
  if (usage.billing !== "subscription") return;
20551
20684
  const sub = stats.subscription ??= { requests: 0, byProvider: {} };
20552
20685
  sub.requests++;
20553
- const row2 = sub.byProvider[provider] ??= { requests: 0, input: 0, output: 0, cacheRead: 0 };
20554
- row2.requests++;
20555
- row2.input += usage.input;
20556
- row2.output += usage.output;
20557
- row2.cacheRead += usage.cacheRead;
20686
+ const row3 = sub.byProvider[provider] ??= { requests: 0, input: 0, output: 0, cacheRead: 0 };
20687
+ row3.requests++;
20688
+ row3.input += usage.input;
20689
+ row3.output += usage.output;
20690
+ row3.cacheRead += usage.cacheRead;
20558
20691
  }
20559
20692
  function computeStats(input2) {
20560
20693
  const tokens = { input: 0, output: 0, cacheRead: 0, cacheWrite: 0, total: 0 };
@@ -32643,14 +32776,14 @@ function aggregateExternal(entries) {
32643
32776
  const byAgent = {};
32644
32777
  for (const u of usage) {
32645
32778
  if (typeof u.agent !== "string" || typeof u.amount !== "number") continue;
32646
- const row2 = byAgent[u.agent] ??= { runs: 0, unit: u.unit, amount: 0 };
32647
- row2.runs += 1;
32648
- if (row2.unit !== u.unit) {
32649
- row2.unit = u.unit;
32650
- row2.amount = 0;
32779
+ const row3 = byAgent[u.agent] ??= { runs: 0, unit: u.unit, amount: 0 };
32780
+ row3.runs += 1;
32781
+ if (row3.unit !== u.unit) {
32782
+ row3.unit = u.unit;
32783
+ row3.amount = 0;
32651
32784
  }
32652
- row2.amount += u.amount;
32653
- if (typeof u.tokens === "number") row2.tokens = (row2.tokens ?? 0) + u.tokens;
32785
+ row3.amount += u.amount;
32786
+ if (typeof u.tokens === "number") row3.tokens = (row3.tokens ?? 0) + u.tokens;
32654
32787
  }
32655
32788
  return { byAgent };
32656
32789
  }
@@ -34162,6 +34295,90 @@ var init_token_store = __esm({
34162
34295
  }
34163
34296
  });
34164
34297
 
34298
+ // src/ai/providers/discovered-cache.ts
34299
+ function discoveredCachePath(dataDir, provider) {
34300
+ return (0, import_node_path66.join)(dataDir, "models", "discovered", `${provider}.json`);
34301
+ }
34302
+ function isEntry(value) {
34303
+ if (typeof value !== "object" || value === null) return false;
34304
+ const { id, name } = value;
34305
+ return typeof id === "string" && id !== "" && (name === void 0 || typeof name === "string");
34306
+ }
34307
+ function readDiscoveredCache(dataDir, provider) {
34308
+ let parsed;
34309
+ try {
34310
+ parsed = JSON.parse((0, import_node_fs44.readFileSync)(discoveredCachePath(dataDir, provider), "utf8"));
34311
+ } catch {
34312
+ return void 0;
34313
+ }
34314
+ if (typeof parsed !== "object" || parsed === null) return void 0;
34315
+ const file = parsed;
34316
+ if (file.provider !== provider || !Array.isArray(file.models)) return void 0;
34317
+ return {
34318
+ version: typeof file.version === "number" ? file.version : DISCOVERED_CACHE_VERSION,
34319
+ provider,
34320
+ fetchedAt: typeof file.fetchedAt === "string" ? file.fetchedAt : "",
34321
+ ...typeof file.flavor === "string" ? { flavor: file.flavor } : {},
34322
+ models: file.models.filter(isEntry).map((m) => m.name ? { id: m.id, name: m.name } : { id: m.id })
34323
+ };
34324
+ }
34325
+ function writeDiscoveredCache(dataDir, provider, input2, now = Date.now()) {
34326
+ const path = discoveredCachePath(dataDir, provider);
34327
+ const file = {
34328
+ version: DISCOVERED_CACHE_VERSION,
34329
+ provider,
34330
+ fetchedAt: new Date(now).toISOString(),
34331
+ ...input2.flavor !== void 0 ? { flavor: input2.flavor } : {},
34332
+ models: input2.models.map((m) => m.name ? { id: m.id, name: m.name } : { id: m.id })
34333
+ };
34334
+ (0, import_node_fs44.mkdirSync)((0, import_node_path66.dirname)(path), { recursive: true, mode: 448 });
34335
+ const tmp = `${path}.${process.pid}.tmp`;
34336
+ (0, import_node_fs44.writeFileSync)(tmp, `${JSON.stringify(file, null, 2)}
34337
+ `);
34338
+ (0, import_node_fs44.renameSync)(tmp, path);
34339
+ return path;
34340
+ }
34341
+ function clearDiscoveredCache(dataDir, provider) {
34342
+ const path = discoveredCachePath(dataDir, provider);
34343
+ if (!(0, import_node_fs44.existsSync)(path)) return false;
34344
+ (0, import_node_fs44.rmSync)(path, { force: true });
34345
+ return true;
34346
+ }
34347
+ function discoveredModels(file, provider, modelsDev) {
34348
+ return file.models.map((m) => {
34349
+ const { entry } = enrichEntry(m.name ? { id: m.id, name: m.name } : { id: m.id }, modelsDev);
34350
+ const model = withCustomDefaults(entry, provider.id, provider.api);
34351
+ const names = (provider.channels ?? []).map((c) => c.name);
34352
+ if (names.length > 0) {
34353
+ const own = file.flavor !== void 0 && names.includes(file.flavor) ? file.flavor : void 0;
34354
+ model.channels = [own ?? provider.defaultChannel ?? names[0]];
34355
+ }
34356
+ return model;
34357
+ });
34358
+ }
34359
+ function mergeDiscoveredModels(registry2, dataDir, modelsDev) {
34360
+ const merged = [];
34361
+ for (const provider of registry2.list()) {
34362
+ if (provider.models.length > 0 || !provider.requiresApiKey) continue;
34363
+ const file = readDiscoveredCache(dataDir, provider.id);
34364
+ if (file === void 0 || file.models.length === 0) continue;
34365
+ registry2.addModels(provider.id, discoveredModels(file, provider, modelsDev), "discovered");
34366
+ merged.push(provider.id);
34367
+ }
34368
+ return merged;
34369
+ }
34370
+ var import_node_fs44, import_node_path66, DISCOVERED_CACHE_VERSION;
34371
+ var init_discovered_cache = __esm({
34372
+ "src/ai/providers/discovered-cache.ts"() {
34373
+ "use strict";
34374
+ import_node_fs44 = require("node:fs");
34375
+ import_node_path66 = require("node:path");
34376
+ init_catalog2();
34377
+ init_enrich();
34378
+ DISCOVERED_CACHE_VERSION = 1;
34379
+ }
34380
+ });
34381
+
34165
34382
  // src/ai/apis/chatgpt-rate-limits.ts
34166
34383
  function num(value) {
34167
34384
  const n = typeof value === "string" && value.trim() !== "" ? Number(value) : value;
@@ -34660,7 +34877,7 @@ var init_key_docs = __esm({
34660
34877
 
34661
34878
  // src/ai/providers/models-dev-cache.ts
34662
34879
  function modelsDevCachePath(dataDir) {
34663
- return (0, import_node_path68.join)(dataDir, MODELS_DEV_FILE);
34880
+ return (0, import_node_path69.join)(dataDir, MODELS_DEV_FILE);
34664
34881
  }
34665
34882
  function modelsDevUrl(env = process.env) {
34666
34883
  const custom = env[MODELS_DEV_URL_ENV]?.trim();
@@ -34668,7 +34885,7 @@ function modelsDevUrl(env = process.env) {
34668
34885
  }
34669
34886
  function readModelsDevCache(dataDir) {
34670
34887
  try {
34671
- const value = JSON.parse((0, import_node_fs45.readFileSync)(modelsDevCachePath(dataDir), "utf8"));
34888
+ const value = JSON.parse((0, import_node_fs46.readFileSync)(modelsDevCachePath(dataDir), "utf8"));
34672
34889
  if (typeof value !== "object" || value === null) return void 0;
34673
34890
  const file = value;
34674
34891
  if (file.version !== 2 || typeof file.fetchedAt !== "string") return void 0;
@@ -34681,10 +34898,10 @@ function readModelsDevCache(dataDir) {
34681
34898
  }
34682
34899
  function writeModelsDevCache(dataDir, file) {
34683
34900
  const path = modelsDevCachePath(dataDir);
34684
- (0, import_node_fs45.mkdirSync)((0, import_node_path68.dirname)(path), { recursive: true, mode: 448 });
34901
+ (0, import_node_fs46.mkdirSync)((0, import_node_path69.dirname)(path), { recursive: true, mode: 448 });
34685
34902
  const tmp = `${path}.${process.pid}.tmp`;
34686
- (0, import_node_fs45.writeFileSync)(tmp, JSON.stringify(file));
34687
- (0, import_node_fs45.renameSync)(tmp, path);
34903
+ (0, import_node_fs46.writeFileSync)(tmp, JSON.stringify(file));
34904
+ (0, import_node_fs46.renameSync)(tmp, path);
34688
34905
  memo = void 0;
34689
34906
  }
34690
34907
  function overrideApplies(file) {
@@ -34694,7 +34911,7 @@ function loadModelsDevIndex(dataDir) {
34694
34911
  const path = modelsDevCachePath(dataDir);
34695
34912
  let key;
34696
34913
  try {
34697
- const stat16 = (0, import_node_fs45.statSync)(path);
34914
+ const stat16 = (0, import_node_fs46.statSync)(path);
34698
34915
  key = `${path}\0${stat16.mtimeMs}\0${stat16.size}`;
34699
34916
  } catch {
34700
34917
  return builtinSnapshotIndex();
@@ -34779,12 +34996,12 @@ function describeRefresh(result, limit = 20) {
34779
34996
  }
34780
34997
  return lines2.join("\n");
34781
34998
  }
34782
- var import_node_fs45, import_node_path68, MODELS_DEV_URL, MODELS_DEV_URL_ENV, MODELS_DEV_FILE, MODELS_DEV_TIMEOUT_MS, memo;
34999
+ var import_node_fs46, import_node_path69, MODELS_DEV_URL, MODELS_DEV_URL_ENV, MODELS_DEV_FILE, MODELS_DEV_TIMEOUT_MS, memo;
34783
35000
  var init_models_dev_cache = __esm({
34784
35001
  "src/ai/providers/models-dev-cache.ts"() {
34785
35002
  "use strict";
34786
- import_node_fs45 = require("node:fs");
34787
- import_node_path68 = require("node:path");
35003
+ import_node_fs46 = require("node:fs");
35004
+ import_node_path69 = require("node:path");
34788
35005
  init_models_dev();
34789
35006
  init_models_dev_snapshot();
34790
35007
  init_i18n();
@@ -34901,7 +35118,7 @@ function w5Sections() {
34901
35118
  }
34902
35119
  ),
34903
35120
  subagents: object({ maxConcurrent: num2(1, 64), maxPending: num2(0, 1024), defaultModel: str3() }),
34904
- models: object({ aliases: object({ fast: str3(), strong: str3() }) }),
35121
+ models: object({ aliases: object({ fast: str3(), strong: str3() }), enabled: strings2 }),
34905
35122
  fallbackModel: str3(),
34906
35123
  limits: object({ maxTurns: num2(1), maxCostUsd: num2(0) }),
34907
35124
  reminders: object({
@@ -35111,40 +35328,40 @@ function minimalConfig() {
35111
35328
  }
35112
35329
  function writeAtomic2(path, text, mode) {
35113
35330
  const tmp = `${path}.${process.pid}.tmp`;
35114
- (0, import_node_fs46.writeFileSync)(tmp, text, { mode });
35115
- (0, import_node_fs46.renameSync)(tmp, path);
35331
+ (0, import_node_fs47.writeFileSync)(tmp, text, { mode });
35332
+ (0, import_node_fs47.renameSync)(tmp, path);
35116
35333
  }
35117
35334
  function initConfigDir(dir, options = {}) {
35118
- const dirCreated = !(0, import_node_fs46.existsSync)(dir);
35119
- (0, import_node_fs46.mkdirSync)(dir, { recursive: true, mode: 448 });
35120
- if (dirCreated && process.platform !== "win32") (0, import_node_fs46.chmodSync)(dir, 448);
35335
+ const dirCreated = !(0, import_node_fs47.existsSync)(dir);
35336
+ (0, import_node_fs47.mkdirSync)(dir, { recursive: true, mode: 448 });
35337
+ if (dirCreated && process.platform !== "win32") (0, import_node_fs47.chmodSync)(dir, 448);
35121
35338
  const files = [];
35122
- const config = (0, import_node_path69.join)(dir, CONFIG_FILE);
35339
+ const config = (0, import_node_path70.join)(dir, CONFIG_FILE);
35123
35340
  const text = `${JSON.stringify(minimalConfig(), null, 2)}
35124
35341
  `;
35125
- if (!(0, import_node_fs46.existsSync)(config)) {
35342
+ if (!(0, import_node_fs47.existsSync)(config)) {
35126
35343
  writeAtomic2(config, text, 420);
35127
35344
  files.push({ path: config, status: "created" });
35128
35345
  } else if (options.force) {
35129
- (0, import_node_fs46.copyFileSync)(config, `${config}.bak`);
35346
+ (0, import_node_fs47.copyFileSync)(config, `${config}.bak`);
35130
35347
  writeAtomic2(config, text, 420);
35131
35348
  files.push({ path: config, status: "overwritten" });
35132
35349
  } else files.push({ path: config, status: "exists" });
35133
- const schema = (0, import_node_path69.join)(dir, CONFIG_SCHEMA_FILE);
35350
+ const schema = (0, import_node_path70.join)(dir, CONFIG_SCHEMA_FILE);
35134
35351
  const schemaText = configSchemaText();
35135
- if (!(0, import_node_fs46.existsSync)(schema)) {
35352
+ if (!(0, import_node_fs47.existsSync)(schema)) {
35136
35353
  writeAtomic2(schema, schemaText, 420);
35137
35354
  files.push({ path: schema, status: "created" });
35138
- } else if ((0, import_node_fs46.readFileSync)(schema, "utf8") !== schemaText) {
35355
+ } else if ((0, import_node_fs47.readFileSync)(schema, "utf8") !== schemaText) {
35139
35356
  writeAtomic2(schema, schemaText, 420);
35140
35357
  files.push({ path: schema, status: "updated" });
35141
35358
  } else files.push({ path: schema, status: "unchanged" });
35142
- const auth = (0, import_node_path69.join)(dir, AUTH_FILE);
35143
- if ((0, import_node_fs46.existsSync)(auth)) files.push({ path: auth, status: "exists" });
35359
+ const auth = (0, import_node_path70.join)(dir, AUTH_FILE);
35360
+ if ((0, import_node_fs47.existsSync)(auth)) files.push({ path: auth, status: "exists" });
35144
35361
  return { dir, dirCreated, files };
35145
35362
  }
35146
35363
  function autoInitConfigDir(dir, env) {
35147
- if (env[NO_INIT_ENV] === "1" || (0, import_node_fs46.existsSync)(dir)) return false;
35364
+ if (env[NO_INIT_ENV] === "1" || (0, import_node_fs47.existsSync)(dir)) return false;
35148
35365
  try {
35149
35366
  initConfigDir(dir);
35150
35367
  return true;
@@ -35162,12 +35379,12 @@ function describeInit(result) {
35162
35379
  return `${lines2.join("\n")}
35163
35380
  `;
35164
35381
  }
35165
- var import_node_fs46, import_node_path69, NO_INIT_ENV;
35382
+ var import_node_fs47, import_node_path70, NO_INIT_ENV;
35166
35383
  var init_init = __esm({
35167
35384
  "src/config/init.ts"() {
35168
35385
  "use strict";
35169
- import_node_fs46 = require("node:fs");
35170
- import_node_path69 = require("node:path");
35386
+ import_node_fs47 = require("node:fs");
35387
+ import_node_path70 = require("node:path");
35171
35388
  init_i18n();
35172
35389
  init_json_schema();
35173
35390
  init_paths();
@@ -37937,14 +38154,14 @@ var init_api = __esm({
37937
38154
  // src/ai/providers/auth.ts
37938
38155
  function defaultConfigDir(env = process.env) {
37939
38156
  if (env["AMA_CONFIG_DIR"]) return env["AMA_CONFIG_DIR"];
37940
- if (process.platform === "win32" && env["APPDATA"]) return (0, import_node_path70.join)(env["APPDATA"], "ama");
37941
- if (env["XDG_CONFIG_HOME"]) return (0, import_node_path70.join)(env["XDG_CONFIG_HOME"], "ama");
37942
- return (0, import_node_path70.join)(env["HOME"] ?? (0, import_node_os11.homedir)(), ".config", "ama");
38157
+ if (process.platform === "win32" && env["APPDATA"]) return (0, import_node_path71.join)(env["APPDATA"], "ama");
38158
+ if (env["XDG_CONFIG_HOME"]) return (0, import_node_path71.join)(env["XDG_CONFIG_HOME"], "ama");
38159
+ return (0, import_node_path71.join)(env["HOME"] ?? (0, import_node_os11.homedir)(), ".config", "ama");
37943
38160
  }
37944
38161
  function readAuthFile2(path, onWarning) {
37945
38162
  let raw;
37946
38163
  try {
37947
- raw = (0, import_node_fs47.readFileSync)(path, "utf8");
38164
+ raw = (0, import_node_fs48.readFileSync)(path, "utf8");
37948
38165
  } catch (error2) {
37949
38166
  const code = error2.code;
37950
38167
  if (code !== "ENOENT") onWarning?.(`cannot read auth file ${path}`);
@@ -37952,7 +38169,7 @@ function readAuthFile2(path, onWarning) {
37952
38169
  }
37953
38170
  if (process.platform !== "win32") {
37954
38171
  try {
37955
- const mode = (0, import_node_fs47.statSync)(path).mode & 511;
38172
+ const mode = (0, import_node_fs48.statSync)(path).mode & 511;
37956
38173
  if ((mode & 63) !== 0) {
37957
38174
  onWarning?.(
37958
38175
  `auth file ${path} has permissions ${mode.toString(8).padStart(4, "0")}; expected 0600`
@@ -37986,14 +38203,14 @@ function expandEnvRefs(value, env) {
37986
38203
  );
37987
38204
  return missing || out.length === 0 ? void 0 : out;
37988
38205
  }
37989
- var import_node_child_process13, import_node_fs47, import_node_os11, import_node_path70, ApiKeyResolver;
38206
+ var import_node_child_process13, import_node_fs48, import_node_os11, import_node_path71, ApiKeyResolver;
37990
38207
  var init_auth2 = __esm({
37991
38208
  "src/ai/providers/auth.ts"() {
37992
38209
  "use strict";
37993
38210
  import_node_child_process13 = require("node:child_process");
37994
- import_node_fs47 = require("node:fs");
38211
+ import_node_fs48 = require("node:fs");
37995
38212
  import_node_os11 = require("node:os");
37996
- import_node_path70 = require("node:path");
38213
+ import_node_path71 = require("node:path");
37997
38214
  init_live();
37998
38215
  init_refresh();
37999
38216
  init_token_store();
@@ -38013,7 +38230,7 @@ var init_auth2 = __esm({
38013
38230
  authFiles() {
38014
38231
  const files = [];
38015
38232
  if (this.options.authFile) files.push(this.options.authFile);
38016
- const user = this.options.userAuthFile === void 0 ? (0, import_node_path70.join)(defaultConfigDir(this.env), "auth.json") : this.options.userAuthFile;
38233
+ const user = this.options.userAuthFile === void 0 ? (0, import_node_path71.join)(defaultConfigDir(this.env), "auth.json") : this.options.userAuthFile;
38017
38234
  if (user && !files.includes(user)) files.push(user);
38018
38235
  return files;
38019
38236
  }
@@ -38214,6 +38431,8 @@ var init_registry2 = __esm({
38214
38431
  envBaseUrls = /* @__PURE__ */ new Map();
38215
38432
  /** baseUrl 指向非官方主机的内置供应商:接受目录外的 model id。 */
38216
38433
  relayed = /* @__PURE__ */ new Set();
38434
+ /** 模型表只来自发现缓存的供应商:表外的 id 照样合成(与空表相同)。 */
38435
+ openTables = /* @__PURE__ */ new Set();
38217
38436
  /** config 里写了自己 `channels` 的供应商(内置渠道不因改 baseUrl 作废)。 */
38218
38437
  userChannels = /* @__PURE__ */ new Set();
38219
38438
  /** config 里写了供应商级 `api` 的供应商(单渠道回落时目录模型跟它走)。 */
@@ -38484,6 +38703,8 @@ var init_registry2 = __esm({
38484
38703
  addModels(providerId, models, source = "discovered") {
38485
38704
  const provider = this.providers.get(providerId);
38486
38705
  if (!provider) return;
38706
+ if (source === "discovered" && provider.models.length === 0 && provider.requiresApiKey)
38707
+ this.openTables.add(providerId);
38487
38708
  for (const raw of models) {
38488
38709
  this.raw.delete(`${providerId}/${raw.id}`);
38489
38710
  const model = this.materialize(provider, { ...raw, provider: providerId });
@@ -38539,7 +38760,8 @@ var init_registry2 = __esm({
38539
38760
  const id = trimmed.slice(slash + 1);
38540
38761
  const model = provider.models.find((m) => m.id === id);
38541
38762
  if (model) return { ok: true, model, provider };
38542
- const relayed = provider.models.length === 0 || this.relayed.has(provider.id);
38763
+ const open2 = this.relayed.has(provider.id) || this.openTables.has(provider.id);
38764
+ const relayed = provider.models.length === 0 || open2;
38543
38765
  if (synthesize && relayed && id.length > 0) {
38544
38766
  const synthesized = this.synthesize(provider, id);
38545
38767
  if (channel !== void 0 && provider.channels?.some((c) => c.name === channel))
@@ -39115,33 +39337,34 @@ var init_settings_registry = __esm({
39115
39337
  { key: "sandbox.writable", hint: "sandboxWritable" },
39116
39338
  { key: "agents.<id>", hint: "agents" },
39117
39339
  { key: "hooks", hint: "hooks" },
39118
- { key: "auth.chatgpt", hint: "auth" }
39340
+ { key: "auth.chatgpt", hint: "auth" },
39341
+ { key: "models.enabled", hint: "modelsEnabled" }
39119
39342
  ];
39120
39343
  }
39121
39344
  });
39122
39345
 
39123
39346
  // src/config/write.ts
39124
39347
  function writeConfigFile(path, config, options = {}) {
39125
- (0, import_node_fs48.mkdirSync)((0, import_node_path72.dirname)(path), { recursive: true });
39348
+ (0, import_node_fs49.mkdirSync)((0, import_node_path73.dirname)(path), { recursive: true });
39126
39349
  let mode;
39127
39350
  try {
39128
- mode = (0, import_node_fs48.statSync)(path).mode & 511;
39351
+ mode = (0, import_node_fs49.statSync)(path).mode & 511;
39129
39352
  } catch {
39130
39353
  mode = void 0;
39131
39354
  }
39132
- if (mode !== void 0 && options.backup !== false) (0, import_node_fs48.copyFileSync)(path, `${path}.bak`);
39355
+ if (mode !== void 0 && options.backup !== false) (0, import_node_fs49.copyFileSync)(path, `${path}.bak`);
39133
39356
  const tmp = `${path}.${process.pid}.tmp`;
39134
- (0, import_node_fs48.writeFileSync)(tmp, `${JSON.stringify(config, null, 2)}
39357
+ (0, import_node_fs49.writeFileSync)(tmp, `${JSON.stringify(config, null, 2)}
39135
39358
  `, { mode: mode ?? 420 });
39136
- if (mode !== void 0) (0, import_node_fs48.chmodSync)(tmp, mode);
39137
- (0, import_node_fs48.renameSync)(tmp, path);
39359
+ if (mode !== void 0) (0, import_node_fs49.chmodSync)(tmp, mode);
39360
+ (0, import_node_fs49.renameSync)(tmp, path);
39138
39361
  }
39139
- var import_node_fs48, import_node_path72;
39362
+ var import_node_fs49, import_node_path73;
39140
39363
  var init_write2 = __esm({
39141
39364
  "src/config/write.ts"() {
39142
39365
  "use strict";
39143
- import_node_fs48 = require("node:fs");
39144
- import_node_path72 = require("node:path");
39366
+ import_node_fs49 = require("node:fs");
39367
+ import_node_path73 = require("node:path");
39145
39368
  }
39146
39369
  });
39147
39370
 
@@ -39339,7 +39562,7 @@ function parseEnum(key, text, options) {
39339
39562
  function readTarget(path, scope) {
39340
39563
  let text;
39341
39564
  try {
39342
- text = (0, import_node_fs49.readFileSync)(path, "utf8");
39565
+ text = (0, import_node_fs50.readFileSync)(path, "utf8");
39343
39566
  } catch (error2) {
39344
39567
  if (error2.code === "ENOENT")
39345
39568
  return scope === "user" ? minimalConfig() : { version: CONFIG_FILE_VERSION };
@@ -39421,11 +39644,11 @@ function formatSettingValue(value) {
39421
39644
  if (typeof value === "string") return value;
39422
39645
  return JSON.stringify(value);
39423
39646
  }
39424
- var import_node_fs49, ConfigEditError, same, ABOVE, TRUE, FALSE, UNSET;
39647
+ var import_node_fs50, ConfigEditError, same, ABOVE, TRUE, FALSE, UNSET;
39425
39648
  var init_edit2 = __esm({
39426
39649
  "src/config/edit.ts"() {
39427
39650
  "use strict";
39428
- import_node_fs49 = require("node:fs");
39651
+ import_node_fs50 = require("node:fs");
39429
39652
  init_errors();
39430
39653
  init_i18n();
39431
39654
  init_init();
@@ -39538,8 +39761,8 @@ function compositeOne(lines2, layer, width2, height) {
39538
39761
  const startRow = anchor === "bottom" ? result.length - oh : viewportTop + Math.max(0, Math.floor((visible - oh) / 2));
39539
39762
  const col = anchor === "bottom" && ow === width2 ? 0 : Math.floor((width2 - ow) / 2);
39540
39763
  for (let i = 0; i < oh; i++) {
39541
- const row2 = startRow + i;
39542
- result[row2] = spliceLine(result[row2] ?? "", body[i] ?? "", col, ow, width2);
39764
+ const row3 = startRow + i;
39765
+ result[row3] = spliceLine(result[row3] ?? "", body[i] ?? "", col, ow, width2);
39543
39766
  }
39544
39767
  return result;
39545
39768
  }
@@ -40245,21 +40468,21 @@ var init_tui = __esm({
40245
40468
  return Math.max(this.topLimit, this.bufferRows - height);
40246
40469
  }
40247
40470
  /** 从 hwRow 移到内容行 row 的行首;越过已有行时用换行(会滚屏)。 */
40248
- moveTo(row2) {
40471
+ moveTo(row3) {
40249
40472
  let seq = "";
40250
- if (row2 < this.hwRow) {
40251
- seq += `\x1B[${this.hwRow - row2}A`;
40252
- } else if (row2 > this.hwRow) {
40473
+ if (row3 < this.hwRow) {
40474
+ seq += `\x1B[${this.hwRow - row3}A`;
40475
+ } else if (row3 > this.hwRow) {
40253
40476
  const lastExisting = Math.max(this.hwRow, this.bufferRows - 1);
40254
- const down = Math.min(row2, lastExisting) - this.hwRow;
40477
+ const down = Math.min(row3, lastExisting) - this.hwRow;
40255
40478
  if (down > 0) seq += `\x1B[${down}B`;
40256
- const extra = row2 - lastExisting;
40479
+ const extra = row3 - lastExisting;
40257
40480
  if (extra > 0) {
40258
40481
  seq += "\r\n".repeat(extra);
40259
- this.bufferRows = row2 + 1;
40482
+ this.bufferRows = row3 + 1;
40260
40483
  }
40261
40484
  }
40262
- this.hwRow = row2;
40485
+ this.hwRow = row3;
40263
40486
  return seq + "\r";
40264
40487
  }
40265
40488
  doRender() {
@@ -40740,7 +40963,7 @@ function parseKeybindings(value) {
40740
40963
  function loadKeybindingsFile(path) {
40741
40964
  let text;
40742
40965
  try {
40743
- text = (0, import_node_fs50.readFileSync)(path, "utf8");
40966
+ text = (0, import_node_fs51.readFileSync)(path, "utf8");
40744
40967
  } catch (error2) {
40745
40968
  if (error2.code === "ENOENT") return { overrides: {}, warnings: [] };
40746
40969
  return {
@@ -40757,12 +40980,12 @@ function loadKeybindingsFile(path) {
40757
40980
  };
40758
40981
  }
40759
40982
  }
40760
- var import_node_fs50, DEFAULT_KEYBINDINGS, Keybindings, defaultKeybindings;
40983
+ var import_node_fs51, DEFAULT_KEYBINDINGS, Keybindings, defaultKeybindings;
40761
40984
  var init_keybindings = __esm({
40762
40985
  "src/tui/keybindings.ts"() {
40763
40986
  "use strict";
40764
40987
  init_i18n();
40765
- import_node_fs50 = require("node:fs");
40988
+ import_node_fs51 = require("node:fs");
40766
40989
  init_keys();
40767
40990
  DEFAULT_KEYBINDINGS = {
40768
40991
  "tui.editor.submit": ["enter"],
@@ -40945,9 +41168,9 @@ function parseBlock(lines2, i, blocks) {
40945
41168
  if (TABLE_RE.test(line2)) {
40946
41169
  const rows = [];
40947
41170
  while (i < lines2.length && TABLE_RE.test(lines2[i])) {
40948
- const row2 = lines2[i++];
40949
- if (TABLE_SEP_RE.test(row2)) continue;
40950
- rows.push(splitTableRow(row2));
41171
+ const row3 = lines2[i++];
41172
+ if (TABLE_SEP_RE.test(row3)) continue;
41173
+ rows.push(splitTableRow(row3));
40951
41174
  }
40952
41175
  blocks.push({ kind: "table", rows, source: lines2.slice(start, i).join("\n") });
40953
41176
  return i;
@@ -41016,8 +41239,8 @@ function joinSoftBreaks(lines2) {
41016
41239
  });
41017
41240
  return out.trimEnd();
41018
41241
  }
41019
- function splitTableRow(row2) {
41020
- const trimmed = row2.trim().replace(/^\|/, "").replace(/\|$/, "");
41242
+ function splitTableRow(row3) {
41243
+ const trimmed = row3.trim().replace(/^\|/, "").replace(/\|$/, "");
41021
41244
  return trimmed.split(/(?<!\\)\|/).map((cell) => cell.trim().replace(/\\\|/g, "|"));
41022
41245
  }
41023
41246
  function renderInline(text, theme) {
@@ -41184,13 +41407,13 @@ function wrapCode(line2, width2) {
41184
41407
  function renderTable(rows, width2, theme) {
41185
41408
  const cols = Math.max(0, ...rows.map((r) => r.length));
41186
41409
  const widths = new Array(cols).fill(0);
41187
- const rendered = rows.map((row2) => row2.map((cell) => renderInline(cell, theme)));
41188
- for (const row2 of rendered) {
41189
- row2.forEach((cell, c) => widths[c] = Math.max(widths[c], visibleWidth(cell)));
41410
+ const rendered = rows.map((row3) => row3.map((cell) => renderInline(cell, theme)));
41411
+ for (const row3 of rendered) {
41412
+ row3.forEach((cell, c) => widths[c] = Math.max(widths[c], visibleWidth(cell)));
41190
41413
  }
41191
41414
  const lines2 = [];
41192
- rendered.forEach((row2, r) => {
41193
- const cells = widths.map((w, c) => padToWidth(row2[c] ?? "", w));
41415
+ rendered.forEach((row3, r) => {
41416
+ const cells = widths.map((w, c) => padToWidth(row3[c] ?? "", w));
41194
41417
  const line2 = cells.join(" ").replace(/\s+$/, "");
41195
41418
  const header = r === 0 && rows.length > 1;
41196
41419
  lines2.push(truncateToWidth(header ? theme.bold(line2) : line2, width2));
@@ -41586,7 +41809,7 @@ var init_editor_buffer = __esm({
41586
41809
  function loadHistoryFile(path, limit = 500) {
41587
41810
  let text;
41588
41811
  try {
41589
- text = (0, import_node_fs51.readFileSync)(path, "utf8");
41812
+ text = (0, import_node_fs52.readFileSync)(path, "utf8");
41590
41813
  } catch {
41591
41814
  return [];
41592
41815
  }
@@ -41603,11 +41826,11 @@ function loadHistoryFile(path, limit = 500) {
41603
41826
  }
41604
41827
  function appendHistoryFile(path, entry, limit) {
41605
41828
  try {
41606
- (0, import_node_fs51.mkdirSync)((0, import_node_path73.dirname)(path), { recursive: true });
41607
- (0, import_node_fs51.appendFileSync)(path, JSON.stringify(entry) + "\n", { mode: 384 });
41829
+ (0, import_node_fs52.mkdirSync)((0, import_node_path74.dirname)(path), { recursive: true });
41830
+ (0, import_node_fs52.appendFileSync)(path, JSON.stringify(entry) + "\n", { mode: 384 });
41608
41831
  const all = loadHistoryFile(path, Number.MAX_SAFE_INTEGER);
41609
41832
  if (all.length > limit * 2) {
41610
- (0, import_node_fs51.writeFileSync)(
41833
+ (0, import_node_fs52.writeFileSync)(
41611
41834
  path,
41612
41835
  all.slice(-limit).map((e) => JSON.stringify(e) + "\n").join("")
41613
41836
  );
@@ -41615,12 +41838,12 @@ function appendHistoryFile(path, entry, limit) {
41615
41838
  } catch {
41616
41839
  }
41617
41840
  }
41618
- var import_node_fs51, import_node_path73;
41841
+ var import_node_fs52, import_node_path74;
41619
41842
  var init_editor_history = __esm({
41620
41843
  "src/tui/components/editor-history.ts"() {
41621
41844
  "use strict";
41622
- import_node_fs51 = require("node:fs");
41623
- import_node_path73 = require("node:path");
41845
+ import_node_fs52 = require("node:fs");
41846
+ import_node_path74 = require("node:path");
41624
41847
  }
41625
41848
  });
41626
41849
 
@@ -41727,6 +41950,11 @@ var init_select_list = __esm({
41727
41950
  getItems() {
41728
41951
  return this.filtered;
41729
41952
  }
41953
+ /** 换列表下的按键提示(选择器切视图时)。 */
41954
+ setFooter(footer) {
41955
+ if (footer === void 0) delete this.options.footer;
41956
+ else this.options.footer = footer;
41957
+ }
41730
41958
  getFilter() {
41731
41959
  return this.filter;
41732
41960
  }
@@ -42110,9 +42338,9 @@ var init_editor = __esm({
42110
42338
  else this.buffer.moveLineEnd();
42111
42339
  return;
42112
42340
  }
42113
- const row2 = rows[at];
42114
- const line2 = this.buffer.getLines()[row2.line];
42115
- const col = this.preferredCol ?? visibleWidth(line2.slice(row2.start, this.buffer.cursor.col));
42341
+ const row3 = rows[at];
42342
+ const line2 = this.buffer.getLines()[row3.line];
42343
+ const col = this.preferredCol ?? visibleWidth(line2.slice(row3.start, this.buffer.cursor.col));
42116
42344
  this.preferredCol = col;
42117
42345
  const target = rows[at + direction];
42118
42346
  this.buffer.setCursor({ line: target.line, col: this.colAtWidth(target, col) });
@@ -42135,17 +42363,17 @@ var init_editor = __esm({
42135
42363
  this.preferredCol = null;
42136
42364
  this.options.onChange?.(this.buffer.getText());
42137
42365
  }
42138
- colAtWidth(row2, targetWidth) {
42139
- const line2 = this.buffer.getLines()[row2.line];
42140
- let col = row2.start;
42366
+ colAtWidth(row3, targetWidth) {
42367
+ const line2 = this.buffer.getLines()[row3.line];
42368
+ let col = row3.start;
42141
42369
  let width2 = 0;
42142
- for (const { segment, index: index2 } of segmenter4.segment(line2.slice(row2.start, row2.end))) {
42370
+ for (const { segment, index: index2 } of segmenter4.segment(line2.slice(row3.start, row3.end))) {
42143
42371
  const w = visibleWidth(segment);
42144
42372
  if (width2 + w > targetWidth) break;
42145
42373
  width2 += w;
42146
- col = row2.start + index2 + segment.length;
42374
+ col = row3.start + index2 + segment.length;
42147
42375
  }
42148
- if (!row2.last && col >= row2.end) col = this.prevGrapheme(line2, row2.end);
42376
+ if (!row3.last && col >= row3.end) col = this.prevGrapheme(line2, row3.end);
42149
42377
  return col;
42150
42378
  }
42151
42379
  prevGrapheme(line2, col) {
@@ -42277,28 +42505,28 @@ var init_editor = __esm({
42277
42505
  }
42278
42506
  return rows.length - 1;
42279
42507
  }
42280
- renderRow(row2, withCursor) {
42281
- const text = this.buffer.getLines()[row2.line];
42508
+ renderRow(row3, withCursor) {
42509
+ const text = this.buffer.getLines()[row3.line];
42282
42510
  const atomic = this.pastes.ranges(text);
42283
42511
  const cursorCol = withCursor ? this.buffer.cursor.col : -1;
42284
42512
  let out = "";
42285
- let pos = row2.start;
42286
- while (pos < row2.end || pos === cursorCol) {
42513
+ let pos = row3.start;
42514
+ while (pos < row3.end || pos === cursorCol) {
42287
42515
  if (pos === cursorCol) {
42288
- const g = pos < row2.end ? nextGrapheme(text, pos) : " ";
42516
+ const g = pos < row3.end ? nextGrapheme(text, pos) : " ";
42289
42517
  out += CURSOR_MARKER + `\x1B[7m${g}\x1B[27m`;
42290
- if (pos >= row2.end) break;
42518
+ if (pos >= row3.end) break;
42291
42519
  pos += g.length;
42292
42520
  continue;
42293
42521
  }
42294
42522
  const range = atomic.find(([s2, e]) => pos >= s2 && pos < e);
42295
42523
  if (range) {
42296
- const end2 = Math.min(range[1], row2.end, cursorCol > pos ? cursorCol : Infinity);
42524
+ const end2 = Math.min(range[1], row3.end, cursorCol > pos ? cursorCol : Infinity);
42297
42525
  out += this.theme.fg("accent", text.slice(pos, end2));
42298
42526
  pos = end2;
42299
42527
  continue;
42300
42528
  }
42301
- let end = row2.end;
42529
+ let end = row3.end;
42302
42530
  if (cursorCol > pos && cursorCol < end) end = cursorCol;
42303
42531
  const nextAtomic = atomic.find(([s2]) => s2 > pos && s2 < end);
42304
42532
  if (nextAtomic) end = nextAtomic[0];
@@ -42398,7 +42626,7 @@ var init_box = __esm({
42398
42626
  for (let i = 0; i < padY; i++) rows.push(emptyRow);
42399
42627
  if (!border) return rows;
42400
42628
  const lines2 = [this.topBorder(width2, color)];
42401
- for (const row2 of rows) lines2.push(color(g.vertical) + row2 + color(g.vertical));
42629
+ for (const row3 of rows) lines2.push(color(g.vertical) + row3 + color(g.vertical));
42402
42630
  lines2.push(color(g.bottomLeft + g.horizontal.repeat(width2 - 2) + g.bottomRight));
42403
42631
  return lines2;
42404
42632
  }
@@ -42755,7 +42983,7 @@ var init_settings_list = __esm({
42755
42983
  return this.shown;
42756
42984
  }
42757
42985
  selectId(id) {
42758
- const index2 = this.shown.findIndex((row2) => row2.id === id);
42986
+ const index2 = this.shown.findIndex((row3) => row3.id === id);
42759
42987
  if (index2 === -1) return false;
42760
42988
  this.selected = index2;
42761
42989
  return true;
@@ -42769,7 +42997,7 @@ var init_settings_list = __esm({
42769
42997
  refilter() {
42770
42998
  const q = this.filter.trim().toLowerCase();
42771
42999
  this.shown = q === "" ? [...this.rows] : this.rows.filter(
42772
- (row2) => [row2.id, row2.label, row2.value, row2.search ?? ""].some(
43000
+ (row3) => [row3.id, row3.label, row3.value, row3.search ?? ""].some(
42773
43001
  (t) => t.toLowerCase().includes(q)
42774
43002
  )
42775
43003
  );
@@ -42778,12 +43006,12 @@ var init_settings_list = __esm({
42778
43006
  lines() {
42779
43007
  const out = [];
42780
43008
  let group;
42781
- this.shown.forEach((row2, index2) => {
42782
- if (row2.group !== group) {
42783
- group = row2.group;
42784
- out.push({ kind: "group", text: row2.group });
43009
+ this.shown.forEach((row3, index2) => {
43010
+ if (row3.group !== group) {
43011
+ group = row3.group;
43012
+ out.push({ kind: "group", text: row3.group });
42785
43013
  }
42786
- out.push({ kind: "row", row: row2, index: index2 });
43014
+ out.push({ kind: "row", row: row3, index: index2 });
42787
43015
  });
42788
43016
  return out;
42789
43017
  }
@@ -42809,18 +43037,18 @@ var init_settings_list = __esm({
42809
43037
  (line2) => line2.kind === "group" ? truncateToWidth(theme.fg("muted", theme.bold(line2.text)), width2) : this.rowLine(line2.row, line2.index === this.selected, width2, labelW, valueW, tagW)
42810
43038
  );
42811
43039
  }
42812
- rowLine(row2, selected, width2, labelW, valueW, tagW) {
43040
+ rowLine(row3, selected, width2, labelW, valueW, tagW) {
42813
43041
  const { theme } = this.options;
42814
43042
  const pointer = selected ? theme.glyphs.prompt : " ";
42815
- const label2 = padToWidth(truncateToWidth(row2.label, labelW), labelW);
42816
- const valueText = padToWidth(truncateToWidth(row2.value, valueW), valueW);
42817
- const value = row2.valueColor !== void 0 ? theme.fg(row2.valueColor, valueText) : valueText;
43043
+ const label2 = padToWidth(truncateToWidth(row3.label, labelW), labelW);
43044
+ const valueText = padToWidth(truncateToWidth(row3.value, valueW), valueW);
43045
+ const value = row3.valueColor !== void 0 ? theme.fg(row3.valueColor, valueText) : valueText;
42818
43046
  let line2 = `${pointer} ${selected ? theme.fg("accent", theme.bold(label2)) : label2} ${value}`;
42819
- if (width2 >= 48 && tagW > 0) line2 += ` ${theme.fg("dim", padToWidth(row2.tag ?? "", tagW))}`;
42820
- if (width2 >= 60 && row2.note !== void 0 && row2.note !== "")
42821
- line2 += ` ${theme.fg(row2.noteColor ?? "dim", row2.note)}`;
43047
+ if (width2 >= 48 && tagW > 0) line2 += ` ${theme.fg("dim", padToWidth(row3.tag ?? "", tagW))}`;
43048
+ if (width2 >= 60 && row3.note !== void 0 && row3.note !== "")
43049
+ line2 += ` ${theme.fg(row3.noteColor ?? "dim", row3.note)}`;
42822
43050
  let out = truncateToWidth(line2, width2);
42823
- if (row2.dim === true && !selected) out = theme.dim(out);
43051
+ if (row3.dim === true && !selected) out = theme.dim(out);
42824
43052
  return selected ? theme.bg("selection", padToWidth(out, width2)) : out;
42825
43053
  }
42826
43054
  invalidate() {
@@ -42979,6 +43207,54 @@ var init_choice_prompt = __esm({
42979
43207
  }
42980
43208
  });
42981
43209
 
43210
+ // src/ai/providers/model-visibility.ts
43211
+ async function providerAccess(registry2, provider) {
43212
+ if (!provider.requiresApiKey) return "local";
43213
+ const key = await registry2.resolveApiKey(provider.id).catch(() => ({ apiKey: void 0, source: "none" }));
43214
+ if (key.apiKey === void 0) return "none";
43215
+ if (key.source !== "oauth") return "key";
43216
+ return liveToken(key.apiKey)?.needsLogin === true ? "needsLogin" : "oauth";
43217
+ }
43218
+ function accessReady(access) {
43219
+ return access === "local" || access === "key" || access === "oauth";
43220
+ }
43221
+ function splitEnabledRef(ref) {
43222
+ const slash = ref.indexOf("/");
43223
+ if (slash <= 0 || slash === ref.length - 1) return void 0;
43224
+ const provider = ref.slice(0, slash);
43225
+ const rest = ref.slice(slash + 1);
43226
+ const at = rest.lastIndexOf("@");
43227
+ if (at > 0) return { provider, model: rest.slice(0, at), channel: rest.slice(at + 1) };
43228
+ return { provider, model: rest };
43229
+ }
43230
+ function enabledMatch(list5, ref) {
43231
+ if (list5.includes(ref)) return { kind: "exact", pattern: ref };
43232
+ const parts = splitEnabledRef(ref);
43233
+ if (parts === void 0) return void 0;
43234
+ const wildcard = `${parts.provider}/*`;
43235
+ return list5.includes(wildcard) ? { kind: "wildcard", pattern: wildcard } : void 0;
43236
+ }
43237
+ function addEnabled(list5, refs) {
43238
+ const out = [...list5 ?? []];
43239
+ for (const ref of refs) if (!out.includes(ref)) out.push(ref);
43240
+ return out;
43241
+ }
43242
+ function removeEnabled(list5, refs) {
43243
+ const out = (list5 ?? []).filter((ref) => !refs.includes(ref));
43244
+ return out.length > 0 ? out : void 0;
43245
+ }
43246
+ function enabledList(value) {
43247
+ if (!Array.isArray(value)) return void 0;
43248
+ const list5 = value.filter((x) => typeof x === "string");
43249
+ return list5.length > 0 ? list5 : void 0;
43250
+ }
43251
+ var init_model_visibility = __esm({
43252
+ "src/ai/providers/model-visibility.ts"() {
43253
+ "use strict";
43254
+ init_live();
43255
+ }
43256
+ });
43257
+
42982
43258
  // src/tools/clipboard-image.ts
42983
43259
  function attempts(platform, file, env) {
42984
43260
  if (platform === "darwin") {
@@ -43026,11 +43302,11 @@ async function readClipboardImage(dataDir, deps = {}) {
43026
43302
  const platform = deps.platform ?? process.platform;
43027
43303
  const env = deps.env ?? process.env;
43028
43304
  const run7 = deps.run ?? runCommand;
43029
- const dir = (0, import_node_path76.join)(dataDir, CLIPBOARD_DIR);
43305
+ const dir = (0, import_node_path77.join)(dataDir, CLIPBOARD_DIR);
43030
43306
  await (0, import_promises21.mkdir)(dir, { recursive: true });
43031
43307
  const stamp = new Date((deps.now ?? Date.now)()).toISOString().replace(/[:.]/g, "-");
43032
- let file = (0, import_node_path76.join)(dir, `${stamp}.png`);
43033
- for (let n = 1; (0, import_node_fs57.existsSync)(file); n++) file = (0, import_node_path76.join)(dir, `${stamp}-${n}.png`);
43308
+ let file = (0, import_node_path77.join)(dir, `${stamp}.png`);
43309
+ for (let n = 1; (0, import_node_fs58.existsSync)(file); n++) file = (0, import_node_path77.join)(dir, `${stamp}-${n}.png`);
43034
43310
  let anyTool = false;
43035
43311
  for (const attempt of attempts(platform, file, env)) {
43036
43312
  const options = attempt.via === "file" && attempt.env !== void 0 ? { env: attempt.env } : {};
@@ -43049,7 +43325,7 @@ async function readClipboardImage(dataDir, deps = {}) {
43049
43325
  return { ok: false, reason: anyTool ? "no_image" : "no_tool" };
43050
43326
  }
43051
43327
  async function gcClipboardImages(dataDir, options = {}) {
43052
- const dir = (0, import_node_path76.join)(dataDir, CLIPBOARD_DIR);
43328
+ const dir = (0, import_node_path77.join)(dataDir, CLIPBOARD_DIR);
43053
43329
  let names;
43054
43330
  try {
43055
43331
  names = await (0, import_promises21.readdir)(dir);
@@ -43059,7 +43335,7 @@ async function gcClipboardImages(dataDir, options = {}) {
43059
43335
  const cutoff = (options.now ?? Date.now()) - (options.maxAgeDays ?? CLIPBOARD_MAX_AGE_DAYS) * 864e5;
43060
43336
  const removed = [];
43061
43337
  for (const name of names) {
43062
- const file = (0, import_node_path76.join)(dir, name);
43338
+ const file = (0, import_node_path77.join)(dir, name);
43063
43339
  try {
43064
43340
  const info2 = await (0, import_promises21.stat)(file);
43065
43341
  if (!info2.isFile() || info2.mtimeMs >= cutoff) continue;
@@ -43070,13 +43346,13 @@ async function gcClipboardImages(dataDir, options = {}) {
43070
43346
  }
43071
43347
  return removed;
43072
43348
  }
43073
- var import_node_fs57, import_promises21, import_node_path76, CLIPBOARD_DIR, CLIPBOARD_MAX_AGE_DAYS, OSASCRIPT, POWERSHELL;
43349
+ var import_node_fs58, import_promises21, import_node_path77, CLIPBOARD_DIR, CLIPBOARD_MAX_AGE_DAYS, OSASCRIPT, POWERSHELL;
43074
43350
  var init_clipboard_image = __esm({
43075
43351
  "src/tools/clipboard-image.ts"() {
43076
43352
  "use strict";
43077
- import_node_fs57 = require("node:fs");
43353
+ import_node_fs58 = require("node:fs");
43078
43354
  import_promises21 = require("node:fs/promises");
43079
- import_node_path76 = require("node:path");
43355
+ import_node_path77 = require("node:path");
43080
43356
  init_image_file();
43081
43357
  init_image_resize();
43082
43358
  CLIPBOARD_DIR = "clipboard";
@@ -44192,7 +44468,7 @@ function statusCost(stats) {
44192
44468
  function layoutRow(parts, width2, theme, style = {}) {
44193
44469
  const sep5 = style.sep ?? " · ";
44194
44470
  const dim = (text) => text === "" ? "" : theme.fg("dim", text);
44195
- const join65 = (list5) => {
44471
+ const join66 = (list5) => {
44196
44472
  let out = "";
44197
44473
  let size = 0;
44198
44474
  const add3 = (text, measured = visibleWidth(text)) => {
@@ -44221,9 +44497,9 @@ function layoutRow(parts, width2, theme, style = {}) {
44221
44497
  let kept = [...parts];
44222
44498
  const zone = (z) => kept.filter((p) => p.zone === z);
44223
44499
  const fits = () => {
44224
- const l2 = join65(zone("left"))[1];
44500
+ const l2 = join66(zone("left"))[1];
44225
44501
  const right = zone("right");
44226
- return l2 + (right.length === 0 ? 0 : sep5.length + join65(right)[1]) <= width2;
44502
+ return l2 + (right.length === 0 ? 0 : sep5.length + join66(right)[1]) <= width2;
44227
44503
  };
44228
44504
  while (!fits()) {
44229
44505
  const droppable = kept.filter((p) => p.priority !== void 0);
@@ -44231,8 +44507,8 @@ function layoutRow(parts, width2, theme, style = {}) {
44231
44507
  const drop = droppable.reduce((worst, p) => p.priority > worst.priority ? p : worst);
44232
44508
  kept = kept.filter((p) => p !== drop);
44233
44509
  }
44234
- const l = join65(zone("left"))[0];
44235
- const r = join65(zone("right"))[0];
44510
+ const l = join66(zone("left"))[0];
44511
+ const r = join66(zone("right"))[0];
44236
44512
  const gap = width2 - visibleWidth(l) - visibleWidth(r);
44237
44513
  const line2 = r === "" ? l : gap >= MIN_GAP ? l + " ".repeat(gap) + r : l + dim(sep5) + r;
44238
44514
  return truncateToWidth(line2, width2);
@@ -44449,9 +44725,9 @@ function flat(text, max = 120) {
44449
44725
  return one.length > max ? `${one.slice(0, max - 1)}…` : one;
44450
44726
  }
44451
44727
  function displayPath2(path, cwd) {
44452
- if (cwd === void 0 || !(0, import_node_path81.isAbsolute)(path)) return path;
44453
- const rel = (0, import_node_path81.relative)(cwd, path);
44454
- return rel === "" ? "." : rel.startsWith("..") || (0, import_node_path81.isAbsolute)(rel) ? path : rel;
44728
+ if (cwd === void 0 || !(0, import_node_path82.isAbsolute)(path)) return path;
44729
+ const rel = (0, import_node_path82.relative)(cwd, path);
44730
+ return rel === "" ? "." : rel.startsWith("..") || (0, import_node_path82.isAbsolute)(rel) ? path : rel;
44455
44731
  }
44456
44732
  function toolSummary(name, args, cwd) {
44457
44733
  if (typeof args !== "object" || args === null) return "";
@@ -44605,12 +44881,12 @@ function resultSummary(input2, theme) {
44605
44881
  return muted(count2 === 0 ? m.done : m.outputLines(count2));
44606
44882
  }
44607
44883
  }
44608
- var import_node_path81;
44884
+ var import_node_path82;
44609
44885
  var init_tool_summary = __esm({
44610
44886
  "src/modes/interactive/tool-summary.ts"() {
44611
44887
  "use strict";
44612
44888
  init_i18n();
44613
- import_node_path81 = require("node:path");
44889
+ import_node_path82 = require("node:path");
44614
44890
  init_tui2();
44615
44891
  init_status_bar();
44616
44892
  }
@@ -44675,9 +44951,9 @@ function walk3(w, node, prefix, depth, turn, span) {
44675
44951
  const key = rowKey(prefix, node);
44676
44952
  const expandable = isExpandable(node);
44677
44953
  const expanded = expandable && (w.expanded.get(key) ?? defaultExpanded(node));
44678
- const row2 = { key, depth, node, turn, expandable, expanded };
44679
- if (span !== void 0) row2.span = span;
44680
- w.rows.push(row2);
44954
+ const row3 = { key, depth, node, turn, expandable, expanded };
44955
+ if (span !== void 0) row3.span = span;
44956
+ w.rows.push(row3);
44681
44957
  if (!expanded) return;
44682
44958
  const childPrefix = `${key}/`;
44683
44959
  if (node.kind === "subagent") {
@@ -44723,7 +44999,7 @@ function flattenNode(node, opts = {}) {
44723
44999
  return w.rows;
44724
45000
  }
44725
45001
  function rowIndex(rows, key) {
44726
- return rows.findIndex((row2) => row2.key === key);
45002
+ return rows.findIndex((row3) => row3.key === key);
44727
45003
  }
44728
45004
  var KEY_CODE;
44729
45005
  var init_flatten = __esm({
@@ -44804,9 +45080,9 @@ function auxLabel(purpose) {
44804
45080
  const aux = msg().trace.row.aux;
44805
45081
  return purpose === "cache_warm" ? aux.cache_warm : purpose === "permission_classify" ? aux.permission_classify : purpose === "compaction" ? msg().trace.row.compactionPlain : purpose;
44806
45082
  }
44807
- function rowLabel(row2, ctx) {
45083
+ function rowLabel(row3, ctx) {
44808
45084
  const m = msg().trace.row;
44809
- const node = row2.node;
45085
+ const node = row3.node;
44810
45086
  const described = ctx.describe?.(node);
44811
45087
  switch (node.kind) {
44812
45088
  case "more":
@@ -44816,7 +45092,7 @@ function rowLabel(row2, ctx) {
44816
45092
  case "turn": {
44817
45093
  const text = described ?? "";
44818
45094
  const origin = node.origin;
44819
- return origin === void 0 || origin === "followUp" ? m.turn(row2.turn, text).trimEnd() : m.turnOrigin(row2.turn, origin, text).trimEnd();
45095
+ return origin === void 0 || origin === "followUp" ? m.turn(row3.turn, text).trimEnd() : m.turnOrigin(row3.turn, origin, text).trimEnd();
44820
45096
  }
44821
45097
  case "step": {
44822
45098
  const base4 = node.attempt > 1 ? m.stepAttempt(node.model, node.attempt) : m.step(node.model);
@@ -44880,12 +45156,12 @@ function pushSegments(node, out, deep) {
44880
45156
  }
44881
45157
  }
44882
45158
  }
44883
- function barText(row2, width2, theme) {
45159
+ function barText(row3, width2, theme) {
44884
45160
  const plain = plainBars(theme);
44885
45161
  const cells = Math.max(1, width2 - 2);
44886
45162
  const ranks = new Array(cells).fill(0);
44887
- const span = row2.span;
44888
- const node = row2.node;
45163
+ const span = row3.span;
45164
+ const node = row3.node;
44889
45165
  if (span !== void 0 && node.kind !== "more" && node.kind !== "aux_group") {
44890
45166
  const segs = [];
44891
45167
  pushSegments(node, segs, true);
@@ -44908,31 +45184,31 @@ function barText(row2, width2, theme) {
44908
45184
  const [open2, close] = plain ? ["[", "]"] : ["▕", "▏"];
44909
45185
  return theme.fg("border", open2) + body + theme.fg("border", close);
44910
45186
  }
44911
- function labelPart(row2, ctx) {
45187
+ function labelPart(row3, ctx) {
44912
45188
  const g = ctx.theme.glyphs;
44913
- const indent2 = " ".repeat(Math.min(row2.depth * 2, MAX_INDENT));
44914
- const fold = row2.expandable ? row2.expanded ? g.collapse : g.expand : " ";
44915
- const mark = statusMark(row2.node, ctx.theme);
44916
- const label2 = rowLabel(row2, ctx);
44917
- const styled = row2.node.kind === "turn" ? ctx.theme.bold(label2) : row2.node.kind === "more" || row2.node.kind === "aux_group" ? ctx.theme.dim(label2) : label2;
45189
+ const indent2 = " ".repeat(Math.min(row3.depth * 2, MAX_INDENT));
45190
+ const fold = row3.expandable ? row3.expanded ? g.collapse : g.expand : " ";
45191
+ const mark = statusMark(row3.node, ctx.theme);
45192
+ const label2 = rowLabel(row3, ctx);
45193
+ const styled = row3.node.kind === "turn" ? ctx.theme.bold(label2) : row3.node.kind === "more" || row3.node.kind === "aux_group" ? ctx.theme.dim(label2) : label2;
44918
45194
  return `${indent2}${ctx.theme.fg("dim", fold)} ${mark === "" ? "" : `${mark} `}${styled}`;
44919
45195
  }
44920
- function formatRow(row2, width2, ctx, selected = false) {
45196
+ function formatRow(row3, width2, ctx, selected = false) {
44921
45197
  const theme = ctx.theme;
44922
45198
  const cursor = selected ? theme.fg("accent", theme.glyphs.prompt) : " ";
44923
45199
  const inner = Math.max(1, width2 - 1);
44924
- const duration = durationText(row2.node, theme).padStart(DURATION_WIDTH);
45200
+ const duration = durationText(row3.node, theme).padStart(DURATION_WIDTH);
44925
45201
  let right;
44926
45202
  if (width2 < NARROW_WIDTH) right = ` ${duration}`;
44927
45203
  else {
44928
- const bar = barText(row2, barWidth(width2), theme);
44929
- const tokens = padToWidth(tokensText(row2.node, theme), TOKENS_WIDTH);
44930
- const cache3 = cacheText2(row2.node).padStart(CACHE_WIDTH);
45204
+ const bar = barText(row3, barWidth(width2), theme);
45205
+ const tokens = padToWidth(tokensText(row3.node, theme), TOKENS_WIDTH);
45206
+ const cache3 = cacheText2(row3.node).padStart(CACHE_WIDTH);
44931
45207
  right = ` ${duration} ${bar} ${tokens} ${cache3}`;
44932
45208
  }
44933
45209
  const labelWidth = Math.max(1, inner - visibleWidth(right));
44934
45210
  const label2 = padToWidth(
44935
- truncateToWidth(labelPart(row2, ctx), labelWidth, theme.glyphs.ellipsis),
45211
+ truncateToWidth(labelPart(row3, ctx), labelWidth, theme.glyphs.ellipsis),
44936
45212
  labelWidth
44937
45213
  );
44938
45214
  const line2 = `${cursor}${label2}${theme.fg("muted", right)}`;
@@ -44961,9 +45237,9 @@ function expandAll(rows) {
44961
45237
  const expanded = /* @__PURE__ */ new Map();
44962
45238
  for (let guard2 = 0; guard2 < 8; guard2++) {
44963
45239
  let changed = false;
44964
- for (const row2 of rows(expanded))
44965
- if (row2.expandable && !row2.expanded && row2.node.kind !== "more") {
44966
- expanded.set(row2.key, true);
45240
+ for (const row3 of rows(expanded))
45241
+ if (row3.expandable && !row3.expanded && row3.node.kind !== "more") {
45242
+ expanded.set(row3.key, true);
44967
45243
  changed = true;
44968
45244
  }
44969
45245
  if (!changed) break;
@@ -44974,11 +45250,11 @@ function formatTraceText(trace, ctx, rows = expandAll((expanded) => flattenTrace
44974
45250
  const theme = ctx.theme;
44975
45251
  const lines2 = [title];
44976
45252
  if (rows.length === 0) lines2.push(msg().trace.empty);
44977
- for (const row2 of rows) {
44978
- const indent2 = " ".repeat(row2.depth);
44979
- const mark = statusMark(row2.node, theme);
44980
- const cols = [durationText(row2.node, theme), tokensText(row2.node, theme), cacheText2(row2.node)].filter((c) => c !== "").join(" ");
44981
- const label2 = `${indent2}${mark === "" ? "" : `${mark} `}${rowLabel(row2, ctx)}`;
45253
+ for (const row3 of rows) {
45254
+ const indent2 = " ".repeat(row3.depth);
45255
+ const mark = statusMark(row3.node, theme);
45256
+ const cols = [durationText(row3.node, theme), tokensText(row3.node, theme), cacheText2(row3.node)].filter((c) => c !== "").join(" ");
45257
+ const label2 = `${indent2}${mark === "" ? "" : `${mark} `}${rowLabel(row3, ctx)}`;
44982
45258
  lines2.push(cols === "" ? label2 : `${label2} ${cols}`);
44983
45259
  }
44984
45260
  return `${lines2.join("\n")}
@@ -45427,7 +45703,7 @@ function childLoader(read2 = readTraceInput) {
45427
45703
  const load2 = ((file) => {
45428
45704
  let stamp = "";
45429
45705
  try {
45430
- const st = (0, import_node_fs60.statSync)(file);
45706
+ const st = (0, import_node_fs61.statSync)(file);
45431
45707
  stamp = `${st.mtimeMs}:${st.size}`;
45432
45708
  } catch {
45433
45709
  stamp = "missing";
@@ -45471,11 +45747,11 @@ function traceText(session, taskId) {
45471
45747
  `${msg().trace.taskTitle(node.taskId, node.agent)}${summary2}`
45472
45748
  );
45473
45749
  }
45474
- var import_node_fs60, LiveTracker, lineTraceCommand;
45750
+ var import_node_fs61, LiveTracker, lineTraceCommand;
45475
45751
  var init_session3 = __esm({
45476
45752
  "src/trace/session.ts"() {
45477
45753
  "use strict";
45478
- import_node_fs60 = require("node:fs");
45754
+ import_node_fs61 = require("node:fs");
45479
45755
  init_session2();
45480
45756
  init_i18n();
45481
45757
  init_scan();
@@ -45549,10 +45825,10 @@ var init_session3 = __esm({
45549
45825
 
45550
45826
  // src/skills/builtin.ts
45551
45827
  function builtinSkillPath(dataDir, name) {
45552
- return (0, import_node_path84.join)(dataDir, BUILTIN_SKILLS_DIR, `${name}.md`);
45828
+ return (0, import_node_path85.join)(dataDir, BUILTIN_SKILLS_DIR, `${name}.md`);
45553
45829
  }
45554
45830
  function isBuiltinSkill(skill) {
45555
- return BUILTIN_SKILLS.some((b) => b.name === skill.name) && skill.location.endsWith((0, import_node_path84.join)(BUILTIN_SKILLS_DIR, `${skill.name}.md`));
45831
+ return BUILTIN_SKILLS.some((b) => b.name === skill.name) && skill.location.endsWith((0, import_node_path85.join)(BUILTIN_SKILLS_DIR, `${skill.name}.md`));
45556
45832
  }
45557
45833
  function builtinSkillText(skill) {
45558
45834
  return `---
@@ -45567,7 +45843,7 @@ async function ensureFile(path, text) {
45567
45843
  if (await (0, import_promises22.readFile)(path, "utf8") === text) return;
45568
45844
  } catch {
45569
45845
  }
45570
- await (0, import_promises22.mkdir)((0, import_node_path84.dirname)(path), { recursive: true });
45846
+ await (0, import_promises22.mkdir)((0, import_node_path85.dirname)(path), { recursive: true });
45571
45847
  await (0, import_promises22.writeFile)(path, text, "utf8");
45572
45848
  }
45573
45849
  async function withBuiltinSkills(skills, dataDir, builtins = BUILTIN_SKILLS) {
@@ -45576,7 +45852,7 @@ async function withBuiltinSkills(skills, dataDir, builtins = BUILTIN_SKILLS) {
45576
45852
  const taken = new Set(skills.map((skill) => skill.name));
45577
45853
  for (const builtin2 of builtins) {
45578
45854
  if (taken.has(builtin2.name)) continue;
45579
- const baseDir = (0, import_node_path84.join)(dataDir, BUILTIN_SKILLS_DIR);
45855
+ const baseDir = (0, import_node_path85.join)(dataDir, BUILTIN_SKILLS_DIR);
45580
45856
  const location = builtinSkillPath(dataDir, builtin2.name);
45581
45857
  try {
45582
45858
  await ensureFile(location, builtinSkillText(builtin2));
@@ -45597,12 +45873,12 @@ async function withBuiltinSkills(skills, dataDir, builtins = BUILTIN_SKILLS) {
45597
45873
  }
45598
45874
  return { skills: out, warnings };
45599
45875
  }
45600
- var import_promises22, import_node_path84, BUILTIN_SKILLS_DIR, AMA_DOCS_BODY, BUILTIN_SKILLS;
45876
+ var import_promises22, import_node_path85, BUILTIN_SKILLS_DIR, AMA_DOCS_BODY, BUILTIN_SKILLS;
45601
45877
  var init_builtin3 = __esm({
45602
45878
  "src/skills/builtin.ts"() {
45603
45879
  "use strict";
45604
45880
  import_promises22 = require("node:fs/promises");
45605
- import_node_path84 = require("node:path");
45881
+ import_node_path85 = require("node:path");
45606
45882
  BUILTIN_SKILLS_DIR = "builtin";
45607
45883
  AMA_DOCS_BODY = `# ama quick reference
45608
45884
 
@@ -45655,33 +45931,33 @@ Skills: \`<dir>/<name>/SKILL.md\` with \`name\` and \`description\` frontmatter
45655
45931
  // src/skills/discover.ts
45656
45932
  function ancestorDirs(cwd) {
45657
45933
  const out = [];
45658
- let dir = (0, import_node_path85.resolve)(cwd);
45934
+ let dir = (0, import_node_path86.resolve)(cwd);
45659
45935
  for (; ; ) {
45660
45936
  out.push(dir);
45661
- if ((0, import_node_fs62.existsSync)((0, import_node_path85.join)(dir, ".git"))) return out;
45662
- const parent = (0, import_node_path85.dirname)(dir);
45937
+ if ((0, import_node_fs63.existsSync)((0, import_node_path86.join)(dir, ".git"))) return out;
45938
+ const parent = (0, import_node_path86.dirname)(dir);
45663
45939
  if (parent === dir) return out;
45664
45940
  dir = parent;
45665
45941
  }
45666
45942
  }
45667
45943
  function skillSources(options) {
45668
45944
  const sources = [];
45669
- const add3 = (dir, scope, requiresTrust) => sources.push({ dir: (0, import_node_path85.resolve)(options.cwd, dir), scope, requiresTrust });
45945
+ const add3 = (dir, scope, requiresTrust) => sources.push({ dir: (0, import_node_path86.resolve)(options.cwd, dir), scope, requiresTrust });
45670
45946
  for (const d of options.cliDirs ?? []) add3(d, "cli", false);
45671
45947
  for (const d of options.profileDirs ?? []) add3(d, "profile", false);
45672
45948
  for (const d of options.configDirs ?? []) add3(d, "config", false);
45673
- add3((0, import_node_path85.join)(options.configDir, "skills"), "user", false);
45674
- add3((0, import_node_path85.join)(options.cwd, ".ama", "skills"), "project", true);
45675
- for (const d of ancestorDirs(options.cwd)) add3((0, import_node_path85.join)(d, ".agents", "skills"), "ancestor", true);
45949
+ add3((0, import_node_path86.join)(options.configDir, "skills"), "user", false);
45950
+ add3((0, import_node_path86.join)(options.cwd, ".ama", "skills"), "project", true);
45951
+ for (const d of ancestorDirs(options.cwd)) add3((0, import_node_path86.join)(d, ".agents", "skills"), "ancestor", true);
45676
45952
  return sources;
45677
45953
  }
45678
45954
  function parseSkill(text, location, scope) {
45679
45955
  const warnings = [];
45680
45956
  const fm = parseFrontmatter(text);
45681
45957
  for (const e of fm.errors) warnings.push(`${location}: ${e}`);
45682
- const baseDir = (0, import_node_path85.dirname)(location);
45958
+ const baseDir = (0, import_node_path86.dirname)(location);
45683
45959
  const rawName = fm.data["name"];
45684
- const name = typeof rawName === "string" && rawName !== "" ? rawName : (0, import_node_path85.basename)(baseDir);
45960
+ const name = typeof rawName === "string" && rawName !== "" ? rawName : (0, import_node_path86.basename)(baseDir);
45685
45961
  if (name.length > MAX_SKILL_NAME || !SKILL_NAME_RE.test(name)) {
45686
45962
  warnings.push(`${location}: invalid skill name "${name}" (lowercase letters, digits, -)`);
45687
45963
  return { warnings };
@@ -45719,8 +45995,8 @@ async function isDir3(path) {
45719
45995
  }
45720
45996
  async function findSkillFiles(dir, depth = 0) {
45721
45997
  if (depth > MAX_DEPTH2) return [];
45722
- const own = (0, import_node_path85.join)(dir, SKILL_FILE);
45723
- if ((0, import_node_fs62.existsSync)(own)) return [own];
45998
+ const own = (0, import_node_path86.join)(dir, SKILL_FILE);
45999
+ if ((0, import_node_fs63.existsSync)(own)) return [own];
45724
46000
  let names;
45725
46001
  try {
45726
46002
  names = await (0, import_promises23.readdir)(dir);
@@ -45731,7 +46007,7 @@ async function findSkillFiles(dir, depth = 0) {
45731
46007
  const out = [];
45732
46008
  for (const name of names) {
45733
46009
  if (SKIP_DIRS.has(name)) continue;
45734
- const child = (0, import_node_path85.join)(dir, name);
46010
+ const child = (0, import_node_path86.join)(dir, name);
45735
46011
  if (await isDir3(child)) out.push(...await findSkillFiles(child, depth + 1));
45736
46012
  }
45737
46013
  return out;
@@ -45772,13 +46048,13 @@ async function discoverSkills(sources, options) {
45772
46048
  }
45773
46049
  return result;
45774
46050
  }
45775
- var import_node_fs62, import_promises23, import_node_path85, SKILL_FILE, SKILL_NAME_RE, MAX_SKILL_NAME, MAX_SKILL_DESCRIPTION, MAX_DEPTH2, SKIP_DIRS;
46051
+ var import_node_fs63, import_promises23, import_node_path86, SKILL_FILE, SKILL_NAME_RE, MAX_SKILL_NAME, MAX_SKILL_DESCRIPTION, MAX_DEPTH2, SKIP_DIRS;
45776
46052
  var init_discover2 = __esm({
45777
46053
  "src/skills/discover.ts"() {
45778
46054
  "use strict";
45779
- import_node_fs62 = require("node:fs");
46055
+ import_node_fs63 = require("node:fs");
45780
46056
  import_promises23 = require("node:fs/promises");
45781
- import_node_path85 = require("node:path");
46057
+ import_node_path86 = require("node:path");
45782
46058
  init_frontmatter2();
45783
46059
  SKILL_FILE = "SKILL.md";
45784
46060
  SKILL_NAME_RE = /^[a-z0-9-]+$/;
@@ -45893,14 +46169,14 @@ var init_protocol = __esm({
45893
46169
 
45894
46170
  // src/codemode/host-side.ts
45895
46171
  function resolveSandboxEntry(moduleUrl = __ama_import_meta_url) {
45896
- const here = (0, import_node_path86.dirname)((0, import_node_url2.fileURLToPath)(moduleUrl));
46172
+ const here = (0, import_node_path87.dirname)((0, import_node_url2.fileURLToPath)(moduleUrl));
45897
46173
  const candidates2 = [];
45898
46174
  if (true)
45899
- candidates2.push((0, import_node_path86.join)(here, "ama-sandbox.cjs"));
45900
- candidates2.push((0, import_node_path86.join)(here, "sandbox-entry.js"));
45901
- candidates2.push((0, import_node_path86.join)(here, "sandbox-entry.ts"));
46175
+ candidates2.push((0, import_node_path87.join)(here, "ama-sandbox.cjs"));
46176
+ candidates2.push((0, import_node_path87.join)(here, "sandbox-entry.js"));
46177
+ candidates2.push((0, import_node_path87.join)(here, "sandbox-entry.ts"));
45902
46178
  for (const candidate of candidates2) {
45903
- if ((0, import_node_fs63.existsSync)(candidate)) return (0, import_node_fs63.realpathSync)(candidate);
46179
+ if ((0, import_node_fs64.existsSync)(candidate)) return (0, import_node_fs64.realpathSync)(candidate);
45904
46180
  }
45905
46181
  return void 0;
45906
46182
  }
@@ -46119,13 +46395,13 @@ async function runSandbox(request) {
46119
46395
  child.stdin.end();
46120
46396
  return result;
46121
46397
  }
46122
- var import_node_child_process16, import_node_fs63, import_node_path86, import_node_url2, MAX_COLLECTED_OUTPUT_CHARS, ABORT_GRACE_MS, CODEMODE_OS_POLICY;
46398
+ var import_node_child_process16, import_node_fs64, import_node_path87, import_node_url2, MAX_COLLECTED_OUTPUT_CHARS, ABORT_GRACE_MS, CODEMODE_OS_POLICY;
46123
46399
  var init_host_side = __esm({
46124
46400
  "src/codemode/host-side.ts"() {
46125
46401
  "use strict";
46126
46402
  import_node_child_process16 = require("node:child_process");
46127
- import_node_fs63 = require("node:fs");
46128
- import_node_path86 = require("node:path");
46403
+ import_node_fs64 = require("node:fs");
46404
+ import_node_path87 = require("node:path");
46129
46405
  import_node_url2 = require("node:url");
46130
46406
  init_detect();
46131
46407
  init_wrap();
@@ -46288,10 +46564,10 @@ ${output.slice(-half)}`;
46288
46564
  }
46289
46565
  function saveFullOutput(ctx, text) {
46290
46566
  try {
46291
- const dir = ctx.outputDir ?? (0, import_node_path87.join)((0, import_node_os13.tmpdir)(), "ama-codemode");
46292
- (0, import_node_fs64.mkdirSync)(dir, { recursive: true });
46293
- const file = (0, import_node_path87.join)(dir, `${ctx.toolCallId.replace(/[^A-Za-z0-9_-]/g, "_")}.txt`);
46294
- (0, import_node_fs64.writeFileSync)(file, text, "utf8");
46567
+ const dir = ctx.outputDir ?? (0, import_node_path88.join)((0, import_node_os13.tmpdir)(), "ama-codemode");
46568
+ (0, import_node_fs65.mkdirSync)(dir, { recursive: true });
46569
+ const file = (0, import_node_path88.join)(dir, `${ctx.toolCallId.replace(/[^A-Za-z0-9_-]/g, "_")}.txt`);
46570
+ (0, import_node_fs65.writeFileSync)(file, text, "utf8");
46295
46571
  return file;
46296
46572
  } catch {
46297
46573
  return void 0;
@@ -46440,13 +46716,13 @@ function codemodeToolFactory(overrides = {}) {
46440
46716
  return createCodemodeTool(options);
46441
46717
  };
46442
46718
  }
46443
- var import_node_fs64, import_node_os13, import_node_path87, CODEMODE_TOOL_NAME2, DEFAULT_MAX_TOOL_RESULT_CHARS2, CODEMODE_EXAMPLE, SCRIPT_ONLY_GLOBALS, TAIL_CHARS, CODEMODE_ONLY_GUIDELINE;
46719
+ var import_node_fs65, import_node_os13, import_node_path88, CODEMODE_TOOL_NAME2, DEFAULT_MAX_TOOL_RESULT_CHARS2, CODEMODE_EXAMPLE, SCRIPT_ONLY_GLOBALS, TAIL_CHARS, CODEMODE_ONLY_GUIDELINE;
46444
46720
  var init_tool = __esm({
46445
46721
  "src/codemode/tool.ts"() {
46446
46722
  "use strict";
46447
- import_node_fs64 = require("node:fs");
46723
+ import_node_fs65 = require("node:fs");
46448
46724
  import_node_os13 = require("node:os");
46449
- import_node_path87 = require("node:path");
46725
+ import_node_path88 = require("node:path");
46450
46726
  init_presets();
46451
46727
  init_capability();
46452
46728
  init_declarations();
@@ -46558,7 +46834,7 @@ var init_tool2 = __esm({
46558
46834
  // src/cli/codemode-notice.ts
46559
46835
  function readNotices(path) {
46560
46836
  try {
46561
- const value = JSON.parse((0, import_node_fs65.readFileSync)(path, "utf8"));
46837
+ const value = JSON.parse((0, import_node_fs66.readFileSync)(path, "utf8"));
46562
46838
  if (typeof value === "object" && value !== null && !Array.isArray(value)) {
46563
46839
  const shown2 = value[KEY];
46564
46840
  return {
@@ -46577,26 +46853,26 @@ function takeCodemodeNotice(input2) {
46577
46853
  const resolved = resolveCodemodeMode(input2.config, input2.capability.strict);
46578
46854
  if (resolved.source !== "preset" || resolved.preset !== "default" || input2.capability.strict)
46579
46855
  return void 0;
46580
- const path = (0, import_node_path88.join)(input2.dataDir, NOTICES_FILE);
46856
+ const path = (0, import_node_path89.join)(input2.dataDir, NOTICES_FILE);
46581
46857
  const notices = readNotices(path);
46582
46858
  const shown2 = notices[KEY] ?? [];
46583
46859
  if (shown2.includes(input2.configDir)) return void 0;
46584
46860
  try {
46585
- (0, import_node_fs65.mkdirSync)(input2.dataDir, { recursive: true });
46861
+ (0, import_node_fs66.mkdirSync)(input2.dataDir, { recursive: true });
46586
46862
  const tmp = `${path}.${process.pid}.tmp`;
46587
- (0, import_node_fs65.writeFileSync)(tmp, `${JSON.stringify({ ...notices, [KEY]: [...shown2, input2.configDir] })}
46863
+ (0, import_node_fs66.writeFileSync)(tmp, `${JSON.stringify({ ...notices, [KEY]: [...shown2, input2.configDir] })}
46588
46864
  `);
46589
- (0, import_node_fs65.renameSync)(tmp, path);
46865
+ (0, import_node_fs66.renameSync)(tmp, path);
46590
46866
  } catch {
46591
46867
  }
46592
46868
  return codemodeNoticeText(input2.capability);
46593
46869
  }
46594
- var import_node_fs65, import_node_path88, NOTICES_FILE, KEY;
46870
+ var import_node_fs66, import_node_path89, NOTICES_FILE, KEY;
46595
46871
  var init_codemode_notice = __esm({
46596
46872
  "src/cli/codemode-notice.ts"() {
46597
46873
  "use strict";
46598
- import_node_fs65 = require("node:fs");
46599
- import_node_path88 = require("node:path");
46874
+ import_node_fs66 = require("node:fs");
46875
+ import_node_path89 = require("node:path");
46600
46876
  init_presets();
46601
46877
  init_i18n();
46602
46878
  NOTICES_FILE = "notices.json";
@@ -46683,6 +46959,12 @@ async function buildProviderRegistry(input2, options = {}) {
46683
46959
  }
46684
46960
  if (provider !== void 0) registry2 = make({ provider, apiKey: cli.apiKey });
46685
46961
  }
46962
+ if (dataDir !== void 0)
46963
+ mergeDiscoveredModels(
46964
+ registry2,
46965
+ dataDir,
46966
+ lazyIndex(() => loadModelsDevIndex(dataDir))
46967
+ );
46686
46968
  const probe = options.probeLocal ?? env[NO_LOCAL_PROBE_ENV] !== "1";
46687
46969
  if (probe && config.defaultModel === void 0 && !anyKeyConfigured(registry2)) {
46688
46970
  await probeLocalProviders(registry2, options.probeTimeoutMs ?? LOCAL_PROBE_TIMEOUT_MS);
@@ -46714,6 +46996,8 @@ var init_compose_providers = __esm({
46714
46996
  "use strict";
46715
46997
  init_models_dev_cache();
46716
46998
  init_registry2();
46999
+ init_discovered_cache();
47000
+ init_enrich();
46717
47001
  init_token_store();
46718
47002
  init_presets2();
46719
47003
  LOCAL_PROBE_TIMEOUT_MS = 300;
@@ -46724,7 +47008,7 @@ var init_compose_providers = __esm({
46724
47008
  // src/modes/image-input.ts
46725
47009
  function expand(path, cwd) {
46726
47010
  const home = path === "~" || path.startsWith("~/") ? (0, import_node_os14.homedir)() + path.slice(1) : path;
46727
- return (0, import_node_path89.resolve)(cwd, home);
47011
+ return (0, import_node_path90.resolve)(cwd, home);
46728
47012
  }
46729
47013
  function findImageRefs(text, cwd) {
46730
47014
  const out = [];
@@ -46736,7 +47020,7 @@ function findImageRefs(text, cwd) {
46736
47020
  token = token.replace(/\\ /g, " ").replace(/[,\uFF0C\u3002;\uFF1B)\uFF09]+$/, "");
46737
47021
  if (token === "" || imageMimeFromPath(token) === void 0) continue;
46738
47022
  const path = expand(token, cwd);
46739
- if (!explicit && !(0, import_node_fs66.existsSync)(path)) continue;
47023
+ if (!explicit && !(0, import_node_fs67.existsSync)(path)) continue;
46740
47024
  if (seen.has(path)) continue;
46741
47025
  seen.add(path);
46742
47026
  out.push({ path, explicit });
@@ -46795,13 +47079,13 @@ async function loadLocalized(path, options) {
46795
47079
  throw error2;
46796
47080
  }
46797
47081
  }
46798
- var import_node_fs66, import_node_os14, import_node_path89, TOKEN;
47082
+ var import_node_fs67, import_node_os14, import_node_path90, TOKEN;
46799
47083
  var init_image_input = __esm({
46800
47084
  "src/modes/image-input.ts"() {
46801
47085
  "use strict";
46802
- import_node_fs66 = require("node:fs");
47086
+ import_node_fs67 = require("node:fs");
46803
47087
  import_node_os14 = require("node:os");
46804
- import_node_path89 = require("node:path");
47088
+ import_node_path90 = require("node:path");
46805
47089
  init_channels();
46806
47090
  init_errors();
46807
47091
  init_image_limits();
@@ -47353,6 +47637,116 @@ var init_rewind_text = __esm({
47353
47637
  }
47354
47638
  });
47355
47639
 
47640
+ // src/modes/interactive/model-items.ts
47641
+ function isHintValue(value) {
47642
+ return value.startsWith(HINT_PREFIX);
47643
+ }
47644
+ function modelDescription(model) {
47645
+ const ctx = model.contextWindow;
47646
+ const parts = [
47647
+ model.name !== "" && model.name !== model.id ? model.name : void 0,
47648
+ ctx === void 0 ? void 0 : ctx >= 1e6 ? `${Math.round(ctx / 1e5) / 10}M` : `${Math.round(ctx / 1e3)}k`,
47649
+ model.input.includes("image") ? "img" : void 0
47650
+ ].filter((x) => x !== void 0);
47651
+ return parts.length > 0 ? parts.join(" · ") : void 0;
47652
+ }
47653
+ async function loadModelCatalog(registry2) {
47654
+ const providers = [];
47655
+ for (const provider of registry2.list())
47656
+ providers.push({ provider, access: await providerAccess(registry2, provider) });
47657
+ return { providers };
47658
+ }
47659
+ function accessLabel(access) {
47660
+ const m = msg().panels.model;
47661
+ return access === "none" ? m.noKey : m[access];
47662
+ }
47663
+ function otherChannels(model) {
47664
+ return (model.channels ?? []).filter((c) => c !== "" && c !== model.channel);
47665
+ }
47666
+ function row2(model, group, channel) {
47667
+ const suffix = channel === void 0 ? "" : `@${channel}`;
47668
+ const item = {
47669
+ value: `${model.provider}/${model.id}${suffix}`,
47670
+ label: `${model.id}${suffix}`,
47671
+ group
47672
+ };
47673
+ const others = channel === void 0 ? otherChannels(model) : [];
47674
+ const parts = [
47675
+ modelDescription(model),
47676
+ others.length > 0 ? msg().panels.model.otherChannels(others.map((c) => `@${c}`).join(" ")) : void 0
47677
+ ].filter((x) => x !== void 0);
47678
+ if (parts.length > 0) item.description = parts.join(" · ");
47679
+ return item;
47680
+ }
47681
+ function hintRow(entry, group) {
47682
+ const { provider, access } = entry;
47683
+ if (provider.models.length > 0 || !provider.requiresApiKey) return void 0;
47684
+ const m = msg().panels.model;
47685
+ if (access === "key" || access === "oauth")
47686
+ return { value: `${HINT_PREFIX}${provider.id}`, label: m.discoverHint(provider.id), group };
47687
+ if (provider.id === CHATGPT_PROVIDER_ID)
47688
+ return { value: `${HINT_PREFIX}${provider.id}`, label: m.loginHint(provider.id), group };
47689
+ return void 0;
47690
+ }
47691
+ function catalogItems(catalog, options = {}) {
47692
+ const all = options.view === "all";
47693
+ const list5 = options.enabled !== void 0 && options.enabled.length > 0 ? options.enabled : void 0;
47694
+ const ready = [];
47695
+ const rest = [];
47696
+ for (const entry of catalog.providers) {
47697
+ const { provider, access } = entry;
47698
+ const isReady = accessReady(access);
47699
+ const group = `${provider.id} · ${accessLabel(access)}`;
47700
+ const items = [];
47701
+ const listedProvider = list5?.includes(`${provider.id}/*`) === true;
47702
+ for (const model of provider.models) {
47703
+ const main2 = row2(model, group);
47704
+ const listed2 = list5 !== void 0 && enabledMatch(list5, main2.value) !== void 0;
47705
+ const shown2 = all || (list5 !== void 0 ? listed2 : isReady);
47706
+ if (shown2) {
47707
+ if (all && listed2) main2.badge = msg().panels.model.listed;
47708
+ if (all && listed2) main2.badgeColor = "dim";
47709
+ items.push(main2);
47710
+ }
47711
+ for (const channel of otherChannels(model)) {
47712
+ const extra = row2(model, group, channel);
47713
+ const exact = list5?.includes(extra.value) === true;
47714
+ if (exact || shown2 && options.channels === true) items.push(extra);
47715
+ }
47716
+ }
47717
+ const hint = options.hints === false ? void 0 : hintRow(entry, group);
47718
+ if (hint !== void 0 && (all || (list5 !== void 0 ? listedProvider : isReady)))
47719
+ items.push(hint);
47720
+ (isReady ? ready : rest).push(...items);
47721
+ }
47722
+ return pinCurrent(catalog, [...ready, ...rest], options.current);
47723
+ }
47724
+ function pinCurrent(catalog, items, current3) {
47725
+ if (current3 === void 0 || current3 === "" || items.some((i) => i.value === current3))
47726
+ return items;
47727
+ const slash = current3.indexOf("/");
47728
+ const at = current3.lastIndexOf("@");
47729
+ const base4 = at > slash ? current3.slice(0, at) : current3;
47730
+ const model = catalog.providers.find((p) => p.provider.id === current3.slice(0, slash))?.provider.models.find((m) => `${m.provider}/${m.id}` === base4);
47731
+ const item = { value: current3, label: current3, group: msg().panels.model.current };
47732
+ const description = model === void 0 ? void 0 : modelDescription(model);
47733
+ if (description !== void 0) item.description = description;
47734
+ return [item, ...items];
47735
+ }
47736
+ async function modelItems(registry2, options = {}) {
47737
+ return catalogItems(await loadModelCatalog(registry2), options);
47738
+ }
47739
+ var HINT_PREFIX;
47740
+ var init_model_items = __esm({
47741
+ "src/modes/interactive/model-items.ts"() {
47742
+ "use strict";
47743
+ init_model_visibility();
47744
+ init_presets2();
47745
+ init_i18n();
47746
+ HINT_PREFIX = "ama:hint:";
47747
+ }
47748
+ });
47749
+
47356
47750
  // src/modes/interactive/startup-ui.ts
47357
47751
  var startup_ui_exports = {};
47358
47752
  __export(startup_ui_exports, {
@@ -47456,54 +47850,6 @@ function askText(r, prompt) {
47456
47850
  tui.setFocus(editor);
47457
47851
  });
47458
47852
  }
47459
- function modelDescription(model) {
47460
- const ctx = model.contextWindow;
47461
- const parts = [
47462
- model.name !== "" && model.name !== model.id ? model.name : void 0,
47463
- ctx === void 0 ? void 0 : ctx >= 1e6 ? `${Math.round(ctx / 1e5) / 10}M` : `${Math.round(ctx / 1e3)}k`,
47464
- model.input.includes("image") ? "img" : void 0
47465
- ].filter((x) => x !== void 0);
47466
- return parts.length > 0 ? parts.join(" · ") : void 0;
47467
- }
47468
- async function modelItems(providers) {
47469
- const groups = [];
47470
- for (const provider of providers.list()) {
47471
- if (provider.models.length === 0) continue;
47472
- let status;
47473
- let ready = true;
47474
- if (!provider.requiresApiKey) status = msg().interactive.startup.ui.local;
47475
- else {
47476
- const key = await providers.resolveApiKey(provider.id).catch(() => ({ apiKey: void 0 }));
47477
- ready = key.apiKey !== void 0;
47478
- status = ready ? "key ✓" : msg().interactive.startup.ui.noKey;
47479
- }
47480
- const item = (model, group, channel) => {
47481
- const suffix = channel !== void 0 && channel !== model.channel ? `@${channel}` : "";
47482
- const out = {
47483
- value: `${provider.id}/${model.id}${suffix}`,
47484
- label: `${model.id}${suffix}`,
47485
- group
47486
- };
47487
- const description = modelDescription(model);
47488
- if (description !== void 0) out.description = description;
47489
- return out;
47490
- };
47491
- if (provider.channels === void 0) {
47492
- const group = `${provider.id} · ${status}`;
47493
- groups.push({ ready, items: provider.models.map((model) => item(model, group)) });
47494
- continue;
47495
- }
47496
- for (const channel of provider.channels) {
47497
- const group = `${provider.id} · ${channel.name} · ${status}`;
47498
- const models = provider.models.filter((m) => m.channels?.includes(channel.name));
47499
- if (models.length > 0)
47500
- groups.push({ ready, items: models.map((model) => item(model, group, channel.name)) });
47501
- }
47502
- }
47503
- return [...groups.filter((g) => g.ready), ...groups.filter((g) => !g.ready)].flatMap(
47504
- (g) => g.items
47505
- );
47506
- }
47507
47853
  function relativeTime(iso, now) {
47508
47854
  const at = Date.parse(iso);
47509
47855
  if (!Number.isFinite(at)) return "";
@@ -47539,7 +47885,7 @@ function trustChoices() {
47539
47885
  }
47540
47886
  function isDirectory2(path) {
47541
47887
  try {
47542
- return (0, import_node_fs67.statSync)(path).isDirectory();
47888
+ return (0, import_node_fs68.statSync)(path).isDirectory();
47543
47889
  } catch {
47544
47890
  return false;
47545
47891
  }
@@ -47573,7 +47919,9 @@ function createStartupUi(options = {}) {
47573
47919
  return picked?.value;
47574
47920
  },
47575
47921
  async pickModel(providers, reason) {
47576
- const items = await modelItems(providers);
47922
+ const catalog = await loadModelCatalog(providers);
47923
+ let items = catalogItems(catalog, { hints: false });
47924
+ if (items.length === 0) items = catalogItems(catalog, { view: "all", hints: false });
47577
47925
  if (items.length === 0) return void 0;
47578
47926
  const picked = await askSelect(r, {
47579
47927
  title: msg().interactive.startup.ui.modelTitle,
@@ -47591,8 +47939,8 @@ function createStartupUi(options = {}) {
47591
47939
  placeholder: m.cwdPlaceholder,
47592
47940
  validate: (text) => {
47593
47941
  if (text === "") return m.cwdEmpty;
47594
- const abs = (0, import_node_path90.resolve)(text);
47595
- if (!(0, import_node_fs67.existsSync)(abs)) return m.cwdMissing(abs);
47942
+ const abs = (0, import_node_path91.resolve)(text);
47943
+ if (!(0, import_node_fs68.existsSync)(abs)) return m.cwdMissing(abs);
47596
47944
  if (!isDirectory2(abs)) return m.cwdNotDir(abs);
47597
47945
  return void 0;
47598
47946
  }
@@ -47600,14 +47948,16 @@ function createStartupUi(options = {}) {
47600
47948
  }
47601
47949
  };
47602
47950
  }
47603
- var import_node_fs67, import_node_path90;
47951
+ var import_node_fs68, import_node_path91;
47604
47952
  var init_startup_ui = __esm({
47605
47953
  "src/modes/interactive/startup-ui.ts"() {
47606
47954
  "use strict";
47607
47955
  init_i18n();
47608
- import_node_fs67 = require("node:fs");
47609
- import_node_path90 = require("node:path");
47956
+ import_node_fs68 = require("node:fs");
47957
+ import_node_path91 = require("node:path");
47610
47958
  init_tui2();
47959
+ init_model_items();
47960
+ init_model_items();
47611
47961
  }
47612
47962
  });
47613
47963
 
@@ -48585,7 +48935,7 @@ function startupInfo(runtime, home) {
48585
48935
  permissionMode: runtime.session.state.permissionMode,
48586
48936
  preset: runtime.config.tools?.preset ?? "default",
48587
48937
  codemode: effectiveCodemodeMode(runtime.config),
48588
- contextFiles: resources.contextFiles.map((f) => (0, import_node_path91.basename)(f.path)),
48938
+ contextFiles: resources.contextFiles.map((f) => (0, import_node_path92.basename)(f.path)),
48589
48939
  skills: resources.skills.filter((s2) => !isBuiltinSkill(s2)).length,
48590
48940
  prompts: resources.prompts.length,
48591
48941
  hooks: runtime.hooks.list().length,
@@ -48594,12 +48944,12 @@ function startupInfo(runtime, home) {
48594
48944
  if (runtime.host !== void 0) info2.host = runtime.host.adapter.id;
48595
48945
  return info2;
48596
48946
  }
48597
- var import_node_path91;
48947
+ var import_node_path92;
48598
48948
  var init_startup_screen = __esm({
48599
48949
  "src/cli/startup-screen.ts"() {
48600
48950
  "use strict";
48601
48951
  init_builtin3();
48602
- import_node_path91 = require("node:path");
48952
+ import_node_path92 = require("node:path");
48603
48953
  init_channels();
48604
48954
  init_presets();
48605
48955
  init_i18n();
@@ -48644,7 +48994,7 @@ function settingRows(snapshot2, scope, theme) {
48644
48994
  noteColor = "warning";
48645
48995
  } else if (scope === "project" && spec2.project !== "any") note = s2.projectNote[spec2.project];
48646
48996
  else if (value.source !== "default") note = s2.source(value.source);
48647
- const row2 = {
48997
+ const row3 = {
48648
48998
  id: spec2.key,
48649
48999
  group: s2.groups[spec2.group],
48650
49000
  label: labels[spec2.key] ?? spec2.key,
@@ -48652,11 +49002,11 @@ function settingRows(snapshot2, scope, theme) {
48652
49002
  tag,
48653
49003
  search: [...spec2.options ?? [], settingDoc(spec2.key) ?? ""].join(" ")
48654
49004
  };
48655
- if (value.value === void 0) row2.valueColor = "dim";
48656
- if (note !== void 0) row2.note = note;
48657
- if (noteColor !== void 0) row2.noteColor = noteColor;
48658
- if (scope === "project" && spec2.project === "deny") row2.dim = true;
48659
- return row2;
49005
+ if (value.value === void 0) row3.valueColor = "dim";
49006
+ if (note !== void 0) row3.note = note;
49007
+ if (noteColor !== void 0) row3.noteColor = noteColor;
49008
+ if (scope === "project" && spec2.project === "deny") row3.dim = true;
49009
+ return row3;
48660
49010
  });
48661
49011
  for (const hint of SETTING_HINTS) {
48662
49012
  rows.push({
@@ -48738,7 +49088,7 @@ var init_config_panel = __esm({
48738
49088
  if (this.busy) return;
48739
49089
  const keys = this.deps.keybindings ?? defaultKeybindings;
48740
49090
  if (this.edit !== void 0) return this.editInput(data2);
48741
- const row2 = this.list.selectedRow;
49091
+ const row3 = this.list.selectedRow;
48742
49092
  const unsetKey = matchesKey(data2, "backspace") || matchesKey(data2, "delete");
48743
49093
  if (!unsetKey || this.searching) this.pendingUnset = void 0;
48744
49094
  if (keys.matches(data2, "tui.select.up")) return this.move(-1);
@@ -48758,8 +49108,8 @@ var init_config_panel = __esm({
48758
49108
  return;
48759
49109
  }
48760
49110
  if (this.searching) {
48761
- if (matchesKey(data2, "enter") && row2 !== void 0)
48762
- return this.run(this.deps.activate(row2.id, this.scope));
49111
+ if (matchesKey(data2, "enter") && row3 !== void 0)
49112
+ return this.run(this.deps.activate(row3.id, this.scope));
48763
49113
  if (matchesKey(data2, "backspace"))
48764
49114
  return this.list.setQuery([...this.list.query].slice(0, -1).join(""));
48765
49115
  const text = isPasteData(data2) ? unwrapPaste(data2) : isPrintableText(data2) ? data2 : "";
@@ -48770,20 +49120,20 @@ var init_config_panel = __esm({
48770
49120
  this.searching = true;
48771
49121
  return;
48772
49122
  }
48773
- if (row2 === void 0) return;
49123
+ if (row3 === void 0) return;
48774
49124
  if (matchesKey(data2, "enter") || matchesKey(data2, "space")) {
48775
49125
  this.notice = void 0;
48776
- const hint = hintOf(row2.id);
49126
+ const hint = hintOf(row3.id);
48777
49127
  if (hint !== void 0) return this.setNotice(hint);
48778
- return this.run(this.deps.activate(row2.id, this.scope));
49128
+ return this.run(this.deps.activate(row3.id, this.scope));
48779
49129
  }
48780
- if (unsetKey && hintOf(row2.id) === void 0) {
48781
- if (this.pendingUnset === row2.id) {
49130
+ if (unsetKey && hintOf(row3.id) === void 0) {
49131
+ if (this.pendingUnset === row3.id) {
48782
49132
  this.pendingUnset = void 0;
48783
- return this.run(this.deps.unset(row2.id, this.scope));
49133
+ return this.run(this.deps.unset(row3.id, this.scope));
48784
49134
  }
48785
- this.pendingUnset = row2.id;
48786
- this.setNotice(msg().settings.confirmUnset(row2.id), "warning");
49135
+ this.pendingUnset = row3.id;
49136
+ this.setNotice(msg().settings.confirmUnset(row3.id), "warning");
48787
49137
  }
48788
49138
  }
48789
49139
  move(delta) {
@@ -48862,13 +49212,13 @@ var init_config_panel = __esm({
48862
49212
  }
48863
49213
  description(width2) {
48864
49214
  const { theme } = this.deps;
48865
- const row2 = this.list.selectedRow;
48866
- if (row2 === void 0 || hintOf(row2.id) !== void 0) return [];
48867
- const doc = settingDoc(row2.id) ?? "";
48868
- const value = getConfigValue(this.snapshot, row2.id);
48869
- const dynamic = value.value === void 0 ? settingDynamicDefault(row2.id) : void 0;
49215
+ const row3 = this.list.selectedRow;
49216
+ if (row3 === void 0 || hintOf(row3.id) !== void 0) return [];
49217
+ const doc = settingDoc(row3.id) ?? "";
49218
+ const value = getConfigValue(this.snapshot, row3.id);
49219
+ const dynamic = value.value === void 0 ? settingDynamicDefault(row3.id) : void 0;
48870
49220
  const text = dynamic === void 0 ? doc : `${doc} · ${dynamic}`;
48871
- const spec2 = settingsRegistry().find((x) => x.key === row2.id);
49221
+ const spec2 = settingsRegistry().find((x) => x.key === row3.id);
48872
49222
  const blocked = spec2 === void 0 ? void 0 : blockedReason(spec2, value, this.scope);
48873
49223
  const lines2 = blocked === void 0 ? [] : [theme.fg("warning", truncateToWidth(blocked, width2))];
48874
49224
  if (text !== "") lines2.push(...wrapTextWithAnsi(theme.fg("dim", text), width2));
@@ -49944,7 +50294,8 @@ var init_config_ui = __esm({
49944
50294
  else if (spec2.kind === "model")
49945
50295
  items = [
49946
50296
  ...await modelItems(
49947
- hideFakeProvider(this.deps.runtime.providers, this.deps.context.io.env)
50297
+ hideFakeProvider(this.deps.runtime.providers, this.deps.context.io.env),
50298
+ { current: current3, enabled: this.deps.runtime.config.models?.enabled, hints: false }
49948
50299
  ),
49949
50300
  { value: "", label: s2.defaultChoice }
49950
50301
  ];
@@ -50197,29 +50548,29 @@ function runEditor(command3, file) {
50197
50548
  return result.status;
50198
50549
  }
50199
50550
  async function editExternally(text, name, deps) {
50200
- const dir = (0, import_node_fs68.mkdtempSync)((0, import_node_path92.join)((0, import_node_os15.tmpdir)(), "ama-edit-"));
50201
- const file = (0, import_node_path92.join)(dir, name);
50202
- (0, import_node_fs68.writeFileSync)(file, text);
50551
+ const dir = (0, import_node_fs69.mkdtempSync)((0, import_node_path93.join)((0, import_node_os15.tmpdir)(), "ama-edit-"));
50552
+ const file = (0, import_node_path93.join)(dir, name);
50553
+ (0, import_node_fs69.writeFileSync)(file, text);
50203
50554
  deps.suspend();
50204
50555
  try {
50205
50556
  const code = (deps.run ?? runEditor)(editorCommand(deps.env, deps.platform), file);
50206
50557
  if (code !== 0) return void 0;
50207
- return (0, import_node_fs68.readFileSync)(file, "utf8");
50558
+ return (0, import_node_fs69.readFileSync)(file, "utf8");
50208
50559
  } catch {
50209
50560
  return void 0;
50210
50561
  } finally {
50211
50562
  deps.resume();
50212
- (0, import_node_fs68.rmSync)(dir, { recursive: true, force: true });
50563
+ (0, import_node_fs69.rmSync)(dir, { recursive: true, force: true });
50213
50564
  }
50214
50565
  }
50215
- var import_node_child_process17, import_node_fs68, import_node_os15, import_node_path92;
50566
+ var import_node_child_process17, import_node_fs69, import_node_os15, import_node_path93;
50216
50567
  var init_external_editor = __esm({
50217
50568
  "src/modes/interactive/external-editor.ts"() {
50218
50569
  "use strict";
50219
50570
  import_node_child_process17 = require("node:child_process");
50220
- import_node_fs68 = require("node:fs");
50571
+ import_node_fs69 = require("node:fs");
50221
50572
  import_node_os15 = require("node:os");
50222
- import_node_path92 = require("node:path");
50573
+ import_node_path93 = require("node:path");
50223
50574
  }
50224
50575
  });
50225
50576
 
@@ -51016,10 +51367,10 @@ var init_tool_view = __esm({
51016
51367
  del: "error",
51017
51368
  ctx: "muted"
51018
51369
  };
51019
- const styled = shown2.map((row2) => {
51020
- if (!numbers || row2.kind === "hunk") return theme.fg(color[row2.kind], row2.text);
51021
- const no = theme.fg("dim", String(row2.num ?? "").padStart(numWidth));
51022
- return `${no} ${theme.fg(color[row2.kind], row2.text)}`;
51370
+ const styled = shown2.map((row3) => {
51371
+ if (!numbers || row3.kind === "hunk") return theme.fg(color[row3.kind], row3.text);
51372
+ const no = theme.fg("dim", String(row3.num ?? "").padStart(numWidth));
51373
+ return `${no} ${theme.fg(color[row3.kind], row3.text)}`;
51023
51374
  });
51024
51375
  const out = this.indent(styled, width2);
51025
51376
  if (rows.length > shown2.length) out.push(this.more(rows.length - shown2.length));
@@ -51939,7 +52290,7 @@ function taskNumber(taskId) {
51939
52290
  return n === null ? Number.MAX_SAFE_INTEGER : Number(n[1]);
51940
52291
  }
51941
52292
  function compareRows(a, b) {
51942
- const group = (row2) => ACTIVE.has(row2.status) ? 0 : 1;
52293
+ const group = (row3) => ACTIVE.has(row3.status) ? 0 : 1;
51943
52294
  return group(a) - group(b) || taskNumber(a.taskId) - taskNumber(b.taskId);
51944
52295
  }
51945
52296
  function statusLabel(status) {
@@ -51966,7 +52317,7 @@ function taskRow(info2, ctx) {
51966
52317
  else if (ctx.approvals.has(info2.taskId)) status = "approval";
51967
52318
  else if (ctx.queued) status = "queued";
51968
52319
  else status = "running";
51969
- const row2 = {
52320
+ const row3 = {
51970
52321
  taskId: info2.taskId,
51971
52322
  agent: info2.agent,
51972
52323
  runner: info2.runner,
@@ -51975,21 +52326,21 @@ function taskRow(info2, ctx) {
51975
52326
  turns: Math.max(state?.turns ?? 0, info2.turns ?? 0)
51976
52327
  };
51977
52328
  const tool = state?.tools.at(-1);
51978
- if (tool !== void 0 && status !== "queued") row2.tool = tool;
52329
+ if (tool !== void 0 && status !== "queued") row3.tool = tool;
51979
52330
  if (status !== "queued") {
51980
- if (state !== void 0) row2.elapsedMs = (state.endedAt ?? ctx.now) - state.startedAt;
51981
- else if (info2.endedAt !== void 0) row2.elapsedMs = info2.endedAt - info2.startedAt;
52331
+ if (state !== void 0) row3.elapsedMs = (state.endedAt ?? ctx.now) - state.startedAt;
52332
+ else if (info2.endedAt !== void 0) row3.elapsedMs = info2.endedAt - info2.startedAt;
51982
52333
  }
51983
- return row2;
52334
+ return row3;
51984
52335
  }
51985
- function agentLabel(row2) {
51986
- return row2.runner !== "ama" && row2.runner !== row2.agent ? `${row2.agent}(${row2.runner})` : row2.agent;
52336
+ function agentLabel(row3) {
52337
+ return row3.runner !== "ama" && row3.runner !== row3.agent ? `${row3.agent}(${row3.runner})` : row3.agent;
51987
52338
  }
51988
- function rowFacts(row2, withTool = true) {
51989
- const facts = [statusLabel(row2.status)];
51990
- if (row2.elapsedMs !== void 0) facts[0] += ` ${formatElapsed(row2.elapsedMs)}`;
51991
- if (row2.turns > 0) facts.push(msg().agents.turns(row2.turns));
51992
- if (withTool && row2.tool !== void 0 && row2.status === "running") facts.push(row2.tool);
52339
+ function rowFacts(row3, withTool = true) {
52340
+ const facts = [statusLabel(row3.status)];
52341
+ if (row3.elapsedMs !== void 0) facts[0] += ` ${formatElapsed(row3.elapsedMs)}`;
52342
+ if (row3.turns > 0) facts.push(msg().agents.turns(row3.turns));
52343
+ if (withTool && row3.tool !== void 0 && row3.status === "running") facts.push(row3.tool);
51993
52344
  return facts.join(" · ");
51994
52345
  }
51995
52346
  var BAR_ROWS, BAR_RETAIN_MS, ACTIVE, AgentBar;
@@ -52028,11 +52379,11 @@ var init_agent_bar = __esm({
52028
52379
  visibleRows() {
52029
52380
  if (!this.deps.enabled()) return [];
52030
52381
  const now = this.deps.now();
52031
- return this.all().filter((row2) => {
52032
- if (ACTIVE.has(row2.status)) return true;
52033
- if (this.deps.tracker.get(row2.taskId) === void 0 || this.viewed.has(row2.taskId))
52382
+ return this.all().filter((row3) => {
52383
+ if (ACTIVE.has(row3.status)) return true;
52384
+ if (this.deps.tracker.get(row3.taskId) === void 0 || this.viewed.has(row3.taskId))
52034
52385
  return false;
52035
- const seen = this.endedSeen.get(row2.taskId);
52386
+ const seen = this.endedSeen.get(row3.taskId);
52036
52387
  return seen !== void 0 && now - seen < BAR_RETAIN_MS;
52037
52388
  });
52038
52389
  }
@@ -52067,7 +52418,7 @@ var init_agent_bar = __esm({
52067
52418
  /** 聚焦时选中某任务。 */
52068
52419
  select(taskId) {
52069
52420
  if (this.index === void 0) return;
52070
- const at = this.all().findIndex((row2) => row2.taskId === taskId);
52421
+ const at = this.all().findIndex((row3) => row3.taskId === taskId);
52071
52422
  if (at >= 0) this.index = at;
52072
52423
  }
52073
52424
  /** 查看过(视图里看到了结束后的状态):不再留在栏里。 */
@@ -52081,17 +52432,17 @@ var init_agent_bar = __esm({
52081
52432
  this.viewed.clear();
52082
52433
  }
52083
52434
  row(info2, approvals, now) {
52084
- const row2 = taskRow(info2, {
52435
+ const row3 = taskRow(info2, {
52085
52436
  tracker: this.deps.tracker,
52086
52437
  approvals,
52087
52438
  queued: this.deps.registry()?.live(info2.taskId)?.queued === true,
52088
52439
  now
52089
52440
  });
52090
- if (ACTIVE.has(row2.status)) {
52441
+ if (ACTIVE.has(row3.status)) {
52091
52442
  this.endedSeen.delete(info2.taskId);
52092
52443
  this.viewed.delete(info2.taskId);
52093
52444
  } else if (!this.endedSeen.has(info2.taskId)) this.endedSeen.set(info2.taskId, now);
52094
- return row2;
52445
+ return row3;
52095
52446
  }
52096
52447
  render(width2) {
52097
52448
  const focused = this.index !== void 0;
@@ -52108,7 +52459,7 @@ var init_agent_bar = __esm({
52108
52459
  start = this.top;
52109
52460
  }
52110
52461
  const shown2 = rows.slice(start, start + BAR_ROWS);
52111
- const out = shown2.map((row2, i) => this.line(row2, width2, focused, start + i === this.index));
52462
+ const out = shown2.map((row3, i) => this.line(row3, width2, focused, start + i === this.index));
52112
52463
  const hidden = rows.length - shown2.length;
52113
52464
  const tail = [];
52114
52465
  if (hidden > 0) tail.push(m.bar.more(hidden));
@@ -52117,15 +52468,15 @@ var init_agent_bar = __esm({
52117
52468
  out.push(truncateToWidth(t.fg("dim", tail.join(" · ")), width2, t.glyphs.ellipsis));
52118
52469
  return out;
52119
52470
  }
52120
- line(row2, width2, focused, selected) {
52471
+ line(row3, width2, focused, selected) {
52121
52472
  const t = this.deps.theme;
52122
52473
  const g = t.glyphs;
52123
- const agent = agentLabel(row2);
52474
+ const agent = agentLabel(row3);
52124
52475
  const lead = focused ? (selected ? t.fg("accent", g.prompt) : " ") + " " : "";
52125
- const marker = t.fg(statusColor(row2.status), g.tool);
52126
- const id = selected ? t.bold(row2.taskId) : row2.taskId;
52127
- const description = row2.description.replace(/\s+/g, " ").trim();
52128
- const text = `${lead}${marker} ${id} ${t.fg("tool", agent)}` + t.fg("dim", " · ") + t.fg(row2.status === "approval" ? "warning" : "muted", rowFacts(row2)) + (description === "" ? "" : ` ${t.fg("dim", description)}`);
52476
+ const marker = t.fg(statusColor(row3.status), g.tool);
52477
+ const id = selected ? t.bold(row3.taskId) : row3.taskId;
52478
+ const description = row3.description.replace(/\s+/g, " ").trim();
52479
+ const text = `${lead}${marker} ${id} ${t.fg("tool", agent)}` + t.fg("dim", " · ") + t.fg(row3.status === "approval" ? "warning" : "muted", rowFacts(row3)) + (description === "" ? "" : ` ${t.fg("dim", description)}`);
52129
52480
  return truncateToWidth(text, width2, g.ellipsis);
52130
52481
  }
52131
52482
  invalidate() {
@@ -52500,7 +52851,7 @@ var init_agent_view = __esm({
52500
52851
  const registry2 = this.deps.registry();
52501
52852
  const info2 = registry2?.get(this.taskId);
52502
52853
  if (info2 === void 0) return truncateToWidth(t.bold(this.taskId), width2);
52503
- const row2 = taskRow(info2, {
52854
+ const row3 = taskRow(info2, {
52504
52855
  tracker: this.deps.tracker,
52505
52856
  approvals: this.deps.approvals(),
52506
52857
  queued: registry2?.live(this.taskId)?.queued === true,
@@ -52511,9 +52862,9 @@ var init_agent_view = __esm({
52511
52862
  const tokens = usage !== void 0 && usage.input + usage.output + usage.cacheRead > 0 ? `${g.arrowUp}${formatTokenCount(usage.input + usage.cacheRead + usage.cacheWrite)} ${g.arrowDown}${formatTokenCount(usage.output)}` : void 0;
52512
52863
  const stop = info2.status === "running" ? m.stopHint(this.taskId) : void 0;
52513
52864
  const compose = (withTokens, withStop) => {
52514
- const facts = [rowFacts(row2, false), ...withTokens && tokens ? [tokens] : []];
52865
+ const facts = [rowFacts(row3, false), ...withTokens && tokens ? [tokens] : []];
52515
52866
  const hints = [m.back, ...withStop && stop ? [stop] : []];
52516
- return t.bold(`${this.taskId} ${agentLabel(row2)}`) + t.fg("dim", " · ") + t.fg(statusColor(row2.status), facts.join(" · ")) + t.fg("dim", ` · ${hints.join(" · ")}`);
52867
+ return t.bold(`${this.taskId} ${agentLabel(row3)}`) + t.fg("dim", " · ") + t.fg(statusColor(row3.status), facts.join(" · ")) + t.fg("dim", ` · ${hints.join(" · ")}`);
52517
52868
  };
52518
52869
  for (const [withTokens, withStop] of [
52519
52870
  [true, true],
@@ -53532,7 +53883,7 @@ var init_agent_ui = __esm({
53532
53883
  now: () => this.deps.now(),
53533
53884
  rows: () => this.deps.tui.terminal.rows,
53534
53885
  render: () => this.deps.render(),
53535
- siblings: () => this.bar.all().map((row2) => row2.taskId),
53886
+ siblings: () => this.bar.all().map((row3) => row3.taskId),
53536
53887
  close: () => this.closeView(),
53537
53888
  stop: (id) => stopTask(this.deps.session().state.sessionId, id),
53538
53889
  messages: {
@@ -53706,18 +54057,21 @@ async function handlePick(what, ui) {
53706
54057
  case "model": {
53707
54058
  const current3 = session.state.model;
53708
54059
  const ref = current3 === void 0 ? void 0 : `${current3.provider}/${current3.id}`;
53709
- const picked = await ui.pick({
54060
+ const providers = ui.env === void 0 ? ui.runtime.providers : hideFakeProvider(ui.runtime.providers, ui.env);
54061
+ const picked = ui.pickModel !== void 0 ? await ui.pickModel(providers, ref) : (await ui.pick({
53710
54062
  title: m.modelTitle,
53711
- items: await modelItems(
53712
- ui.env === void 0 ? ui.runtime.providers : hideFakeProvider(ui.runtime.providers, ui.env)
53713
- ),
54063
+ items: await modelItems(providers, {
54064
+ current: ref,
54065
+ enabled: ui.runtime.config.models?.enabled,
54066
+ hints: false
54067
+ }),
53714
54068
  filterable: true,
53715
54069
  showCount: true,
53716
54070
  ...ref !== void 0 ? { selected: ref, currentValue: ref } : {}
53717
- });
54071
+ }))?.value;
53718
54072
  if (picked === void 0) return;
53719
- await session.setModel(picked.value);
53720
- ui.notice("info", m.modelSet(picked.value));
54073
+ await session.setModel(picked);
54074
+ ui.notice("info", m.modelSet(picked));
53721
54075
  return;
53722
54076
  }
53723
54077
  case "session": {
@@ -54098,17 +54452,17 @@ async function readHead2(cwd) {
54098
54452
  }
54099
54453
  const gitDir = await findGitDir(cwd);
54100
54454
  if (gitDir === void 0) return void 0;
54101
- const text = await (0, import_promises24.readFile)((0, import_node_path93.join)(gitDir, "HEAD"), "utf8").catch(() => void 0);
54455
+ const text = await (0, import_promises24.readFile)((0, import_node_path94.join)(gitDir, "HEAD"), "utf8").catch(() => void 0);
54102
54456
  const match = /^ref:\s*refs\/heads\/(\S+)\s*$/.exec(text ?? "");
54103
54457
  return match?.[1] !== void 0 ? { branch: match[1] } : void 0;
54104
54458
  }
54105
- var import_node_child_process18, import_promises24, import_node_path93, GIT_NUMSTAT_INTERVAL_MS, GIT_NUMSTAT_TIMEOUT_MS, sameInfo, GitInfoWatcher;
54459
+ var import_node_child_process18, import_promises24, import_node_path94, GIT_NUMSTAT_INTERVAL_MS, GIT_NUMSTAT_TIMEOUT_MS, sameInfo, GitInfoWatcher;
54106
54460
  var init_info = __esm({
54107
54461
  "src/git/info.ts"() {
54108
54462
  "use strict";
54109
54463
  import_node_child_process18 = require("node:child_process");
54110
54464
  import_promises24 = require("node:fs/promises");
54111
- import_node_path93 = require("node:path");
54465
+ import_node_path94 = require("node:path");
54112
54466
  init_git_head();
54113
54467
  GIT_NUMSTAT_INTERVAL_MS = 1e4;
54114
54468
  GIT_NUMSTAT_TIMEOUT_MS = 2e3;
@@ -54358,12 +54712,12 @@ function statusLineText(mode) {
54358
54712
  const m = msg().interactive.statusLine;
54359
54713
  return mode === "full" ? m.full : m.compact;
54360
54714
  }
54361
- var import_node_path94, WRITE_TOOLS3, HintLine, StatusArea;
54715
+ var import_node_path95, WRITE_TOOLS3, HintLine, StatusArea;
54362
54716
  var init_status_area = __esm({
54363
54717
  "src/modes/interactive/status-area.ts"() {
54364
54718
  "use strict";
54365
54719
  init_i18n();
54366
- import_node_path94 = require("node:path");
54720
+ import_node_path95 = require("node:path");
54367
54721
  init_capability();
54368
54722
  init_channels();
54369
54723
  init_info();
@@ -54497,7 +54851,7 @@ var init_status_area = __esm({
54497
54851
  gitView() {
54498
54852
  const cwd = this.gitCwd;
54499
54853
  if (cwd === void 0) return void 0;
54500
- return { dir: (0, import_node_path94.basename)(cwd), info: this.git?.current() };
54854
+ return { dir: (0, import_node_path95.basename)(cwd), info: this.git?.current() };
54501
54855
  }
54502
54856
  watchGit() {
54503
54857
  const cwd = this.deps.session().state.cwd;
@@ -54669,6 +55023,184 @@ var init_key_dispatch = __esm({
54669
55023
  }
54670
55024
  });
54671
55025
 
55026
+ // src/modes/interactive/model-picker.ts
55027
+ async function openModelPicker(host, options) {
55028
+ const catalog = await loadModelCatalog(options.providers);
55029
+ return new Promise((resolve38) => {
55030
+ let handle;
55031
+ const view = new ModelPickerView(host, catalog, options, (ref) => {
55032
+ handle?.hide();
55033
+ resolve38(ref);
55034
+ });
55035
+ const width2 = Math.max(20, Math.min(host.columns() - 2, 72));
55036
+ handle = host.showOverlay(new Box(view, { title: options.title, theme: host.theme }), {
55037
+ anchor: "center",
55038
+ width: width2
55039
+ });
55040
+ });
55041
+ }
55042
+ function modelPickerFor(host, runtime, context) {
55043
+ return (providers, current3) => openModelPicker(host, {
55044
+ title: msg().interactive.commands.modelTitle,
55045
+ providers,
55046
+ current: current3,
55047
+ enabled: runtime.config.models?.enabled,
55048
+ saveEnabled: (next) => {
55049
+ const result = setConfigValue({
55050
+ ...layerInputFor(runtime, context),
55051
+ scope: "user",
55052
+ key: "models.enabled",
55053
+ value: next
55054
+ });
55055
+ runtime.replaceConfig?.(result.snapshot.config);
55056
+ }
55057
+ });
55058
+ }
55059
+ var ModelPickerView;
55060
+ var init_model_picker = __esm({
55061
+ "src/modes/interactive/model-picker.ts"() {
55062
+ "use strict";
55063
+ init_model_visibility();
55064
+ init_edit2();
55065
+ init_i18n();
55066
+ init_tui2();
55067
+ init_config_ui();
55068
+ init_model_items();
55069
+ ModelPickerView = class {
55070
+ constructor(host, catalog, options, done) {
55071
+ this.host = host;
55072
+ this.catalog = catalog;
55073
+ this.options = options;
55074
+ this.done = done;
55075
+ this.enabled = enabledList(options.enabled);
55076
+ this.list = new SelectList([], {
55077
+ theme: host.theme,
55078
+ maxVisible: 12,
55079
+ filterable: true,
55080
+ showCount: true,
55081
+ ...host.keybindings !== void 0 ? { keybindings: host.keybindings } : {},
55082
+ ...options.current !== void 0 ? { currentValue: options.current } : {},
55083
+ emptyText: msg().panels.model.emptyConfigured,
55084
+ onSelect: (item) => this.select(item),
55085
+ onCancel: () => this.done(void 0)
55086
+ });
55087
+ this.rebuild();
55088
+ if (options.current !== void 0) this.list.selectValue(options.current);
55089
+ }
55090
+ host;
55091
+ catalog;
55092
+ options;
55093
+ done;
55094
+ view = "configured";
55095
+ enabled;
55096
+ notice;
55097
+ channels = false;
55098
+ list;
55099
+ get focused() {
55100
+ return this.list.focused;
55101
+ }
55102
+ set focused(value) {
55103
+ this.list.focused = value;
55104
+ }
55105
+ get currentView() {
55106
+ return this.view;
55107
+ }
55108
+ rebuild() {
55109
+ const m = msg().panels.model;
55110
+ this.list.setFooter(this.view === "all" ? m.footerAll : m.footerConfigured);
55111
+ this.list.setItems(
55112
+ catalogItems(this.catalog, {
55113
+ view: this.view,
55114
+ enabled: this.enabled,
55115
+ current: this.options.current,
55116
+ channels: this.channels
55117
+ })
55118
+ );
55119
+ }
55120
+ handleInput(data2) {
55121
+ if (matchesKey(data2, "tab")) {
55122
+ this.view = this.view === "all" ? "configured" : "all";
55123
+ this.notice = void 0;
55124
+ this.rebuild();
55125
+ return;
55126
+ }
55127
+ if (data2 === " ") {
55128
+ this.toggle();
55129
+ return;
55130
+ }
55131
+ this.list.handleInput(data2);
55132
+ const channels = this.list.getFilter().includes("@");
55133
+ if (channels !== this.channels) {
55134
+ this.channels = channels;
55135
+ this.rebuild();
55136
+ }
55137
+ }
55138
+ providerOf(value) {
55139
+ const id = value.slice(0, value.indexOf("/"));
55140
+ return this.catalog.providers.find((p) => p.provider.id === id);
55141
+ }
55142
+ save(next) {
55143
+ try {
55144
+ this.options.saveEnabled(next);
55145
+ this.enabled = next;
55146
+ return true;
55147
+ } catch (error2) {
55148
+ this.notice = {
55149
+ text: error2 instanceof Error ? error2.message : String(error2),
55150
+ level: "error"
55151
+ };
55152
+ return false;
55153
+ }
55154
+ }
55155
+ toggle() {
55156
+ const item = this.list.getSelected();
55157
+ if (item === void 0 || isHintValue(item.value)) return;
55158
+ const m = msg().panels.model;
55159
+ const ref = item.value;
55160
+ const match = this.enabled === void 0 ? void 0 : enabledMatch(this.enabled, ref);
55161
+ if (match?.kind === "wildcard") {
55162
+ this.notice = { text: m.wildcard(ref, match.pattern), level: "warning" };
55163
+ } else if (match !== void 0) {
55164
+ if (this.save(removeEnabled(this.enabled, [ref])))
55165
+ this.notice = { text: m.removed(ref), level: "info" };
55166
+ } else {
55167
+ const first = this.enabled === void 0;
55168
+ if (this.save(addEnabled(this.enabled, [ref])))
55169
+ this.notice = { text: first ? m.addedFirst(ref) : m.added(ref), level: "info" };
55170
+ }
55171
+ this.rebuild();
55172
+ }
55173
+ select(item) {
55174
+ const m = msg().panels.model;
55175
+ const id = item.value.slice(0, item.value.indexOf("/"));
55176
+ if (isHintValue(item.value)) {
55177
+ this.notice = { text: item.label, level: "info" };
55178
+ return;
55179
+ }
55180
+ const entry = this.providerOf(item.value);
55181
+ if (item.value !== this.options.current && entry !== void 0 && !accessReady(entry.access)) {
55182
+ const text = entry.access === "needsLogin" ? m.needsLoginHint(id) : m.noKeyHint(id);
55183
+ this.notice = { text, level: "warning" };
55184
+ return;
55185
+ }
55186
+ if (this.enabled !== void 0 && item.value !== this.options.current && enabledMatch(this.enabled, item.value) === void 0 && !this.save(addEnabled(this.enabled, [item.value])))
55187
+ return;
55188
+ this.done(item.value);
55189
+ }
55190
+ render(width2) {
55191
+ const lines2 = this.list.render(width2);
55192
+ if (this.notice === void 0) return lines2;
55193
+ const theme = this.host.theme;
55194
+ const color = this.notice.level === "info" ? "dim" : this.notice.level;
55195
+ return [...lines2, ...wrapTextWithAnsi(theme.fg(color, this.notice.text), width2)];
55196
+ }
55197
+ invalidate() {
55198
+ this.list.invalidate();
55199
+ }
55200
+ };
55201
+ }
55202
+ });
55203
+
54672
55204
  // src/modes/interactive/rewind-list.ts
54673
55205
  function rewindListItems(points, cache3, highlighted, now, ascii = false) {
54674
55206
  return points.map((point) => {
@@ -55384,33 +55916,33 @@ var init_trace_view = __esm({
55384
55916
  this.cursor = Math.max(0, at - 1);
55385
55917
  }
55386
55918
  expand() {
55387
- const row2 = this.selected;
55388
- if (row2 === void 0) return;
55389
- if (!row2.expandable) return;
55390
- if (!row2.expanded) {
55391
- if (needsChild(row2.node)) {
55392
- this.loaded.add(row2.node.taskId);
55393
- loadSubagentTrace(row2.node, this.loadChild);
55919
+ const row3 = this.selected;
55920
+ if (row3 === void 0) return;
55921
+ if (!row3.expandable) return;
55922
+ if (!row3.expanded) {
55923
+ if (needsChild(row3.node)) {
55924
+ this.loaded.add(row3.node.taskId);
55925
+ loadSubagentTrace(row3.node, this.loadChild);
55394
55926
  this.rebuild();
55395
55927
  }
55396
- this.expanded.set(row2.key, true);
55928
+ this.expanded.set(row3.key, true);
55397
55929
  this.reflow();
55398
55930
  return;
55399
55931
  }
55400
- if (this.rows[this.cursor + 1]?.depth === row2.depth + 1) this.cursor++;
55932
+ if (this.rows[this.cursor + 1]?.depth === row3.depth + 1) this.cursor++;
55401
55933
  }
55402
55934
  collapse() {
55403
- const row2 = this.selected;
55404
- if (row2 === void 0) return;
55935
+ const row3 = this.selected;
55936
+ if (row3 === void 0) return;
55405
55937
  this.follow = false;
55406
- if (row2.expanded) {
55407
- this.expanded.set(row2.key, false);
55938
+ if (row3.expanded) {
55939
+ this.expanded.set(row3.key, false);
55408
55940
  this.reflow();
55409
55941
  return;
55410
55942
  }
55411
- const slash = row2.key.lastIndexOf("/");
55943
+ const slash = row3.key.lastIndexOf("/");
55412
55944
  if (slash < 0) return;
55413
- const parent = rowIndex(this.rows, row2.key.slice(0, slash));
55945
+ const parent = rowIndex(this.rows, row3.key.slice(0, slash));
55414
55946
  if (parent >= 0) this.cursor = parent;
55415
55947
  }
55416
55948
  handleInput(data2) {
@@ -55430,9 +55962,9 @@ var init_trace_view = __esm({
55430
55962
  } else if (matchesKey(data2, "right")) this.expand();
55431
55963
  else if (matchesKey(data2, "left")) this.collapse();
55432
55964
  else if (matchesKey(data2, "enter")) {
55433
- const row2 = this.selected;
55434
- if (row2?.node.kind === "more") this.loadEarlier();
55435
- else if (row2 !== void 0 && row2.node.kind !== "aux_group") this.detail = { row: row2, scroll: 0 };
55965
+ const row3 = this.selected;
55966
+ if (row3?.node.kind === "more") this.loadEarlier();
55967
+ else if (row3 !== void 0 && row3.node.kind !== "aux_group") this.detail = { row: row3, scroll: 0 };
55436
55968
  } else if (data2 === "f") {
55437
55969
  this.follow = !this.follow;
55438
55970
  if (this.follow) this.cursor = Math.max(0, this.rows.length - 1);
@@ -55476,10 +56008,10 @@ var init_trace_view = __esm({
55476
56008
  const height = this.bodyHeight();
55477
56009
  const lines2 = [this.headerLine(width2)];
55478
56010
  if (this.detail !== void 0) {
55479
- const { row: row2 } = this.detail;
56011
+ const { row: row3 } = this.detail;
55480
56012
  const body = [
55481
- theme.bold(rowLabel(row2, this.ctx())),
55482
- ...detailLines(row2.node, this.lookup, Math.max(8, width2 - 2), theme, this.trace.startedAt)
56013
+ theme.bold(rowLabel(row3, this.ctx())),
56014
+ ...detailLines(row3.node, this.lookup, Math.max(8, width2 - 2), theme, this.trace.startedAt)
55483
56015
  ].map((l) => ` ${l}`);
55484
56016
  const max = Math.max(0, body.length - height);
55485
56017
  this.detail.scroll = Math.min(this.detail.scroll, max);
@@ -55641,7 +56173,7 @@ var init_startup_header = __esm({
55641
56173
  if (info2.warnings > 0) {
55642
56174
  rows.push({ key: m.keyWarnings, value: t.fg("warning", m.warningsValue(info2.warnings)) });
55643
56175
  }
55644
- const padded = rows.map((row2) => ({ ...row2, key: padToWidth(row2.key, keyWidth) }));
56176
+ const padded = rows.map((row3) => ({ ...row3, key: padToWidth(row3.key, keyWidth) }));
55645
56177
  const kv = new KeyValue(padded, { theme: t, gap: 1, maxKeyRatio: 1 });
55646
56178
  const body = {
55647
56179
  render: (inner) => [this.title(), "", ...kv.render(inner), "", t.fg("dim", m.hint)],
@@ -55811,10 +56343,10 @@ var init_run_indicator = __esm({
55811
56343
  theme;
55812
56344
  setQueue(steering, followUp) {
55813
56345
  const t = this.theme;
55814
- const row2 = (origin, text) => ` ${t.fg("dim", `${t.glyphs.queued} ${originLabel(origin)}`)} ${t.fg("muted", oneLine8(text))}`;
56346
+ const row3 = (origin, text) => ` ${t.fg("dim", `${t.glyphs.queued} ${originLabel(origin)}`)} ${t.fg("muted", oneLine8(text))}`;
55815
56347
  const rows = [
55816
- ...steering.map((text) => row2("steer", text)),
55817
- ...followUp.map((text) => row2("followUp", text))
56348
+ ...steering.map((text) => row3("steer", text)),
56349
+ ...followUp.map((text) => row3("followUp", text))
55818
56350
  ];
55819
56351
  const shown2 = rows.slice(-QUEUE_PREVIEW);
55820
56352
  if (rows.length > shown2.length) {
@@ -55938,15 +56470,15 @@ function processTerminal() {
55938
56470
  return new ProcessTerminal();
55939
56471
  }
55940
56472
  function loadKeys(runtime, warn2) {
55941
- const parsed = loadKeybindingsFile((0, import_node_path95.join)(runtime.paths.configDir, KEYBINDINGS_FILE));
56473
+ const parsed = loadKeybindingsFile((0, import_node_path96.join)(runtime.paths.configDir, KEYBINDINGS_FILE));
55942
56474
  for (const w of parsed.warnings) warn2(msg().interactive.app.keybindingsWarning(w));
55943
56475
  return new Keybindings(parsed.overrides);
55944
56476
  }
55945
- var import_node_path95;
56477
+ var import_node_path96;
55946
56478
  var init_terminal_setup = __esm({
55947
56479
  "src/modes/interactive/terminal-setup.ts"() {
55948
56480
  "use strict";
55949
- import_node_path95 = require("node:path");
56481
+ import_node_path96 = require("node:path");
55950
56482
  init_paths();
55951
56483
  init_errors();
55952
56484
  init_i18n();
@@ -56009,7 +56541,7 @@ function runInteractiveMode(runtime, context, options = {}) {
56009
56541
  ...options.statusLine !== void 0 ? { layout: options.statusLine } : {}
56010
56542
  });
56011
56543
  const { hint, bar: status } = area;
56012
- const historyFile = options.historyFile === false ? void 0 : options.historyFile ?? (0, import_node_path96.join)(runtime.paths.dataDir, "history");
56544
+ const historyFile = options.historyFile === false ? void 0 : options.historyFile ?? (0, import_node_path97.join)(runtime.paths.dataDir, "history");
56013
56545
  const completion = new InteractiveCompletion({
56014
56546
  commands: () => ALL_COMMANDS,
56015
56547
  prompts: () => runtime.resources.prompts,
@@ -56186,6 +56718,7 @@ function runInteractiveMode(runtime, context, options = {}) {
56186
56718
  return next;
56187
56719
  },
56188
56720
  pick: (spec2) => openPicker(pickerHost, spec2),
56721
+ pickModel: modelPickerFor(pickerHost, runtime, context),
56189
56722
  confirmMode,
56190
56723
  rewind: () => rewind.open(),
56191
56724
  setDraft,
@@ -56374,12 +56907,12 @@ function runInteractiveMode(runtime, context, options = {}) {
56374
56907
  }
56375
56908
  });
56376
56909
  }
56377
- var import_node_path96, HINT_MS;
56910
+ var import_node_path97, HINT_MS;
56378
56911
  var init_interactive_mode = __esm({
56379
56912
  "src/modes/interactive/interactive-mode.ts"() {
56380
56913
  "use strict";
56381
56914
  init_image_input();
56382
- import_node_path96 = require("node:path");
56915
+ import_node_path97 = require("node:path");
56383
56916
  init_session2();
56384
56917
  init_subagent_registry();
56385
56918
  init_compose_session();
@@ -56400,6 +56933,7 @@ var init_interactive_mode = __esm({
56400
56933
  init_key_dispatch();
56401
56934
  init_message_view();
56402
56935
  init_pickers();
56936
+ init_model_picker();
56403
56937
  init_rewind_flow();
56404
56938
  init_trace_view();
56405
56939
  init_startup_header();
@@ -56452,7 +56986,7 @@ function choose(answer, values) {
56452
56986
  }
56453
56987
  function isDirectory3(path) {
56454
56988
  try {
56455
- return (0, import_node_fs69.statSync)(path).isDirectory();
56989
+ return (0, import_node_fs70.statSync)(path).isDirectory();
56456
56990
  } catch {
56457
56991
  return false;
56458
56992
  }
@@ -56496,8 +57030,8 @@ function createTextStartupUi(io) {
56496
57030
  const m = msg().report.startup;
56497
57031
  const answer = (await ask([m.cwdMissing(missing)], m.cwdAnswer))?.trim();
56498
57032
  if (answer === void 0 || answer === "") return void 0;
56499
- const abs = (0, import_node_path97.resolve)(answer);
56500
- if (!(0, import_node_fs69.existsSync)(abs) || !isDirectory3(abs)) {
57033
+ const abs = (0, import_node_path98.resolve)(answer);
57034
+ if (!(0, import_node_fs70.existsSync)(abs) || !isDirectory3(abs)) {
56501
57035
  io.write(m.notDirectory(abs));
56502
57036
  return void 0;
56503
57037
  }
@@ -56505,12 +57039,12 @@ function createTextStartupUi(io) {
56505
57039
  }
56506
57040
  };
56507
57041
  }
56508
- var import_node_fs69, import_node_path97;
57042
+ var import_node_fs70, import_node_path98;
56509
57043
  var init_startup_ui_text = __esm({
56510
57044
  "src/modes/startup-ui-text.ts"() {
56511
57045
  "use strict";
56512
- import_node_fs69 = require("node:fs");
56513
- import_node_path97 = require("node:path");
57046
+ import_node_fs70 = require("node:fs");
57047
+ import_node_path98 = require("node:path");
56514
57048
  init_i18n();
56515
57049
  }
56516
57050
  });
@@ -56535,7 +57069,7 @@ function createTools(input2, options, state) {
56535
57069
  const osStatus = configureOsSandbox(input2.config.sandbox?.enabled);
56536
57070
  const bashSandbox = options.bashSandbox ?? resolveBashSandbox(input2.config.sandbox, {
56537
57071
  status: osStatus,
56538
- ...input2.paths === void 0 ? {} : { hidden: [(0, import_node_path98.join)(input2.paths.configDir, AUTH_FILE)] }
57072
+ ...input2.paths === void 0 ? {} : { hidden: [(0, import_node_path99.join)(input2.paths.configDir, AUTH_FILE)] }
56539
57073
  });
56540
57074
  state.bashSandbox = bashSandbox;
56541
57075
  const capability = options.sandboxCapability ?? sandboxCapabilityFor(input2.config);
@@ -56720,7 +57254,7 @@ function createRuntimeDeps(options = {}) {
56720
57254
  if (ui !== void 0) deps.ui = ui;
56721
57255
  return deps;
56722
57256
  }
56723
- var import_node_path98, DEFAULT_TOOL_FACTORIES, DEFAULT_MODES;
57257
+ var import_node_path99, DEFAULT_TOOL_FACTORIES, DEFAULT_MODES;
56724
57258
  var init_compose2 = __esm({
56725
57259
  "src/cli/compose.ts"() {
56726
57260
  "use strict";
@@ -56735,7 +57269,7 @@ var init_compose2 = __esm({
56735
57269
  init_tool();
56736
57270
  init_detect();
56737
57271
  init_bash();
56738
- import_node_path98 = require("node:path");
57272
+ import_node_path99 = require("node:path");
56739
57273
  init_paths();
56740
57274
  init_presets();
56741
57275
  init_registry();
@@ -56950,8 +57484,8 @@ var init_memory3 = __esm({
56950
57484
  });
56951
57485
 
56952
57486
  // src/cli/main.ts
56953
- var import_node_fs70 = require("node:fs");
56954
- var import_node_path99 = require("node:path");
57487
+ var import_node_fs71 = require("node:fs");
57488
+ var import_node_path100 = require("node:path");
56955
57489
  var import_node_url3 = require("node:url");
56956
57490
  init_version();
56957
57491
  init_args();
@@ -58239,7 +58773,7 @@ function reportError(error2, io, fallback = ExitCode.RuntimeError) {
58239
58773
  init_exit_codes();
58240
58774
 
58241
58775
  // src/cli/subcommands/auth.ts
58242
- var import_node_path67 = require("node:path");
58776
+ var import_node_path68 = require("node:path");
58243
58777
 
58244
58778
  // src/auth/chatgpt/cli.ts
58245
58779
  init_errors();
@@ -58273,6 +58807,7 @@ var openBrowser = (url) => new Promise((resolve38) => {
58273
58807
 
58274
58808
  // src/auth/chatgpt/cli.ts
58275
58809
  init_token_store();
58810
+ init_discovered_cache();
58276
58811
 
58277
58812
  // src/auth/chatgpt/backend-client.ts
58278
58813
  init_chatgpt_rate_limits();
@@ -58742,23 +59277,23 @@ init_token_client();
58742
59277
 
58743
59278
  // src/auth/chatgpt/host-id.ts
58744
59279
  var import_node_crypto17 = require("node:crypto");
58745
- var import_node_fs44 = require("node:fs");
58746
- var import_node_path66 = require("node:path");
59280
+ var import_node_fs45 = require("node:fs");
59281
+ var import_node_path67 = require("node:path");
58747
59282
  var HOST_ID_FILE = "chatgpt-host.json";
58748
59283
  function hostIdPath(dataDir) {
58749
- return (0, import_node_path66.join)(dataDir, HOST_ID_FILE);
59284
+ return (0, import_node_path67.join)(dataDir, HOST_ID_FILE);
58750
59285
  }
58751
59286
  function readOrCreateHostId(dataDir) {
58752
59287
  const path = hostIdPath(dataDir);
58753
59288
  try {
58754
- const value = JSON.parse((0, import_node_fs44.readFileSync)(path, "utf8"));
59289
+ const value = JSON.parse((0, import_node_fs45.readFileSync)(path, "utf8"));
58755
59290
  if (typeof value.hostId === "string" && /^urn:uuid:[0-9a-f-]{36}$/i.test(value.hostId))
58756
59291
  return value.hostId;
58757
59292
  } catch {
58758
59293
  }
58759
59294
  const hostId = `urn:uuid:${(0, import_node_crypto17.randomUUID)()}`;
58760
- (0, import_node_fs44.mkdirSync)((0, import_node_path66.dirname)(path), { recursive: true, mode: 448 });
58761
- (0, import_node_fs44.writeFileSync)(path, `${JSON.stringify({ version: 1, hostId }, null, 2)}
59295
+ (0, import_node_fs45.mkdirSync)((0, import_node_path67.dirname)(path), { recursive: true, mode: 448 });
59296
+ (0, import_node_fs45.writeFileSync)(path, `${JSON.stringify({ version: 1, hostId }, null, 2)}
58762
59297
  `, { mode: 384 });
58763
59298
  return hostId;
58764
59299
  }
@@ -58906,7 +59441,7 @@ function loginErrorText(error2, flavor) {
58906
59441
  case "oauth_timeout":
58907
59442
  return m.timeout;
58908
59443
  case "oauth_denied":
58909
- return m.denied(detail.error ?? "error");
59444
+ return m.denied(detail.error ?? "error", flavor === "siwc");
58910
59445
  case "oauth_state_mismatch":
58911
59446
  return m.stateMismatch;
58912
59447
  case "oauth_no_code":
@@ -59030,10 +59565,31 @@ async function runLogin(args, io, deps = {}) {
59030
59565
  `);
59031
59566
  if (flavor === "siwc") io.stdout(`${m.siwcLimitHint}
59032
59567
  `);
59033
- io.stdout(`${m.modelHint}
59568
+ const count2 = await cacheModels(io, entry, config, deps);
59569
+ io.stdout(`${count2 === void 0 ? m.modelHint : m.modelsCached(count2)}
59034
59570
  `);
59035
59571
  return ExitCode.Ok;
59036
59572
  }
59573
+ async function cacheModels(io, entry, config, deps) {
59574
+ try {
59575
+ const models = await listChatGptModels(
59576
+ deps.fetch ?? fetch,
59577
+ chatgptBaseUrl(entry.flavor, io.env),
59578
+ {
59579
+ flavor: entry.flavor,
59580
+ accessToken: entry.accessToken,
59581
+ accountId: entry.accountId,
59582
+ originator: config?.originator
59583
+ }
59584
+ );
59585
+ if (models.length === 0) return void 0;
59586
+ const dataDir = resolveDataDir({ env: io.env });
59587
+ writeDiscoveredCache(dataDir, CHATGPT_PROVIDER_ID, { models, flavor: entry.flavor });
59588
+ return models.length;
59589
+ } catch {
59590
+ return void 0;
59591
+ }
59592
+ }
59037
59593
  async function runLogout(args, io, deps = {}) {
59038
59594
  const m = msg().auth.logout;
59039
59595
  const provider = providerOf(args, "logout");
@@ -59051,6 +59607,7 @@ async function runLogout(args, io, deps = {}) {
59051
59607
  `);
59052
59608
  return ExitCode.RuntimeError;
59053
59609
  }
59610
+ clearDiscoveredCache(resolveDataDir({ env: io.env }), provider);
59054
59611
  const text = revoked === void 0 ? m.local(provider, args.path) : revoked ? m.revoked(provider, args.path) : m.notRevoked(provider, args.path);
59055
59612
  io.stdout(`${text}
59056
59613
  `);
@@ -59152,7 +59709,7 @@ async function runAuth(argv, io, deps = {}) {
59152
59709
  return flags2.has("help") ? ExitCode.Ok : ExitCode.Usage;
59153
59710
  }
59154
59711
  const explicit = values.get("auth-file");
59155
- const path = explicit !== void 0 ? (0, import_node_path67.resolve)(io.cwd, explicit) : defaultAuthFilePath(resolveConfigDir({ env: io.env }));
59712
+ const path = explicit !== void 0 ? (0, import_node_path68.resolve)(io.cwd, explicit) : defaultAuthFilePath(resolveConfigDir({ env: io.env }));
59156
59713
  const loginOnly = ["flavor", "port"].filter((name) => values.has(name));
59157
59714
  const loginFlags = ["paste", "device", "no-browser", "yes"].filter((name) => flags2.has(name));
59158
59715
  if (action !== "login" && [...loginOnly, ...loginFlags].length > 0)
@@ -59224,8 +59781,8 @@ init_merge();
59224
59781
  init_key_docs();
59225
59782
  init_paths();
59226
59783
  var import_node_child_process14 = require("node:child_process");
59227
- var import_node_fs53 = require("node:fs");
59228
- var import_node_path75 = require("node:path");
59784
+ var import_node_fs54 = require("node:fs");
59785
+ var import_node_path76 = require("node:path");
59229
59786
  init_models_dev_cache();
59230
59787
  init_init();
59231
59788
  init_json_schema();
@@ -59240,7 +59797,7 @@ init_default_model();
59240
59797
  init_exit_codes();
59241
59798
 
59242
59799
  // src/cli/subcommands/context.ts
59243
- var import_node_path71 = require("node:path");
59800
+ var import_node_path72 = require("node:path");
59244
59801
  init_auth_file();
59245
59802
  init_load();
59246
59803
  init_merge();
@@ -59261,7 +59818,7 @@ function loadUserLevel(io, options = {}) {
59261
59818
  profile: profile?.config,
59262
59819
  hasProfile: profile !== void 0
59263
59820
  });
59264
- const authFile = options.authFile !== void 0 ? (0, import_node_path71.resolve)(io.cwd, options.authFile) : profile?.authFile ?? defaultAuthFilePath(configDir);
59821
+ const authFile = options.authFile !== void 0 ? (0, import_node_path72.resolve)(io.cwd, options.authFile) : profile?.authFile ?? defaultAuthFilePath(configDir);
59265
59822
  const result = { configDir, dataDir, merged, userConfigPath, authFile, warnings };
59266
59823
  if (profile !== void 0) result.profile = profile;
59267
59824
  return result;
@@ -59286,8 +59843,8 @@ init_ansi();
59286
59843
  // src/cli/subcommands/config-set.ts
59287
59844
  init_i18n();
59288
59845
  init_edit2();
59289
- var import_node_fs52 = require("node:fs");
59290
- var import_node_path74 = require("node:path");
59846
+ var import_node_fs53 = require("node:fs");
59847
+ var import_node_path75 = require("node:path");
59291
59848
  init_init();
59292
59849
  init_paths();
59293
59850
  init_profile();
@@ -59339,18 +59896,22 @@ function textRow(value) {
59339
59896
  function scopeLabel(scope) {
59340
59897
  return msg().settings.scope[scope];
59341
59898
  }
59342
- function report(io, result, unset) {
59899
+ function report(io, result, written) {
59343
59900
  const s2 = msg().settings;
59344
- const value = formatSettingValue(result.after.value);
59901
+ const effective = formatSettingValue(result.after.value);
59902
+ const scope = scopeLabel(result.scope);
59903
+ const by = result.after.envName ?? result.overriddenBy;
59904
+ if (written === void 0) io.stdout(`${s2.unsetDone(result.key, effective, scope)}
59905
+ `);
59906
+ else if (by === void 0) io.stdout(`${s2.setDone(result.key, effective, scope)}
59907
+ `);
59908
+ else io.stdout(`${s2.writtenTo(result.key, formatSettingValue(written), scope)}
59909
+ `);
59910
+ if (by === void 0) return;
59345
59911
  io.stdout(
59346
- `${unset ? s2.unsetDone(result.key, value, scopeLabel(result.scope)) : s2.setDone(result.key, value, scopeLabel(result.scope))}
59912
+ `${written === void 0 ? s2.stillOverridden(result.key, by) : s2.overriddenNow(by, effective)}
59347
59913
  `
59348
59914
  );
59349
- if (result.overriddenBy !== void 0) {
59350
- const by = result.after.envName ?? result.overriddenBy;
59351
- io.stdout(`${s2.stillOverridden(result.key, by)}
59352
- `);
59353
- }
59354
59915
  }
59355
59916
  async function confirmBypass(io, yes, deps) {
59356
59917
  const s2 = msg().settings.cli;
@@ -59403,7 +59964,7 @@ async function runConfigEdit(action, argv, io, deps = {}) {
59403
59964
  return ExitCode.Ok;
59404
59965
  }
59405
59966
  if (action === "unset") {
59406
- report(io, setConfigValue({ ...input2, scope, key, value: void 0 }), true);
59967
+ report(io, setConfigValue({ ...input2, scope, key, value: void 0 }), void 0);
59407
59968
  return ExitCode.Ok;
59408
59969
  }
59409
59970
  const raw = positionals.slice(1).join(" ");
@@ -59412,9 +59973,9 @@ async function runConfigEdit(action, argv, io, deps = {}) {
59412
59973
  if (key === "permission.mode" && value === "full-auto" && scope === "user") {
59413
59974
  if (!await confirmBypass(io, flags2.has("yes"), deps)) return ExitCode.Config;
59414
59975
  }
59415
- if (scope === "user" && !(0, import_node_fs52.existsSync)((0, import_node_path74.join)(input2.configDir, CONFIG_FILE)))
59976
+ if (scope === "user" && !(0, import_node_fs53.existsSync)((0, import_node_path75.join)(input2.configDir, CONFIG_FILE)))
59416
59977
  initConfigDir(input2.configDir);
59417
- report(io, setConfigValue({ ...input2, scope, key, value }), value === void 0);
59978
+ report(io, setConfigValue({ ...input2, scope, key, value }), value);
59418
59979
  return ExitCode.Ok;
59419
59980
  }
59420
59981
 
@@ -59425,17 +59986,17 @@ function showPaths(io) {
59425
59986
  const configDir = resolveConfigDir({ env: io.env });
59426
59987
  const dataDir = resolveDataDir({ env: io.env });
59427
59988
  const m = msg().subcommands.configShow;
59428
- const mark = (path) => `${path}${(0, import_node_fs53.existsSync)(path) ? "" : m.missing}`;
59989
+ const mark = (path) => `${path}${(0, import_node_fs54.existsSync)(path) ? "" : m.missing}`;
59429
59990
  const width2 = Math.max(...[m.configDir, m.dataDir, m.projectLevel].map(visibleWidth)) + 2;
59430
59991
  const label2 = (text) => padToWidth(text, width2);
59431
59992
  const lines2 = [
59432
59993
  `${label2(m.configDir)}${mark(configDir)}`,
59433
- ` config.json ${mark((0, import_node_path75.join)(configDir, CONFIG_FILE))}`,
59434
- ` config.schema.json ${mark((0, import_node_path75.join)(configDir, CONFIG_SCHEMA_FILE))}`,
59435
- ` auth.json ${mark((0, import_node_path75.join)(configDir, AUTH_FILE))}`,
59436
- ` hooks.json ${mark((0, import_node_path75.join)(configDir, HOOKS_FILE))}`,
59994
+ ` config.json ${mark((0, import_node_path76.join)(configDir, CONFIG_FILE))}`,
59995
+ ` config.schema.json ${mark((0, import_node_path76.join)(configDir, CONFIG_SCHEMA_FILE))}`,
59996
+ ` auth.json ${mark((0, import_node_path76.join)(configDir, AUTH_FILE))}`,
59997
+ ` hooks.json ${mark((0, import_node_path76.join)(configDir, HOOKS_FILE))}`,
59437
59998
  `${label2(m.dataDir)}${mark(dataDir)}`,
59438
- ` sessions/ ${mark((0, import_node_path75.join)(dataDir, "sessions"))}`,
59999
+ ` sessions/ ${mark((0, import_node_path76.join)(dataDir, "sessions"))}`,
59439
60000
  ` models-dev.json ${mark(modelsDevCachePath(dataDir))}`,
59440
60001
  `${label2(m.projectLevel)}${mark(projectFile(io.cwd, CONFIG_FILE))}`
59441
60002
  ];
@@ -59445,8 +60006,8 @@ function showPaths(io) {
59445
60006
  }
59446
60007
  function editConfig(io) {
59447
60008
  const configDir = resolveConfigDir({ env: io.env });
59448
- const path = (0, import_node_path75.join)(configDir, CONFIG_FILE);
59449
- if (!(0, import_node_fs53.existsSync)(path)) initConfigDir(configDir);
60009
+ const path = (0, import_node_path76.join)(configDir, CONFIG_FILE);
60010
+ if (!(0, import_node_fs54.existsSync)(path)) initConfigDir(configDir);
59450
60011
  const editor = (io.env["VISUAL"] ?? io.env["EDITOR"] ?? "").trim();
59451
60012
  if (editor === "") {
59452
60013
  io.stdout(msg().subcommands.configShow.noEditor(path));
@@ -59719,7 +60280,7 @@ async function runConfig(argv, io, deps) {
59719
60280
  const lines2 = [m.heading];
59720
60281
  for (const layer of layers.slice(1)) lines2.push(m.layerLine(layer.name, layer.label));
59721
60282
  lines2.push("");
59722
- const texts2 = rows.map((row2) => [`${row2.path} = ${display(row2.path, row2.value)}`, row2.source]);
60283
+ const texts2 = rows.map((row3) => [`${row3.path} = ${display(row3.path, row3.value)}`, row3.source]);
59723
60284
  const width2 = Math.min(60, Math.max(...texts2.map(([text]) => (text ?? "").length)));
59724
60285
  for (const [text, source] of texts2) lines2.push(` ${(text ?? "").padEnd(width2)} ${source}`);
59725
60286
  lines2.push(...providerLines(providers));
@@ -59738,7 +60299,7 @@ async function runConfig(argv, io, deps) {
59738
60299
  }
59739
60300
 
59740
60301
  // src/cli/subcommands/doctor.ts
59741
- var import_node_fs54 = require("node:fs");
60302
+ var import_node_fs55 = require("node:fs");
59742
60303
  init_blobs();
59743
60304
  init_shadow_git();
59744
60305
  init_gc();
@@ -60109,7 +60670,7 @@ async function runDoctor(argv, io, deps) {
60109
60670
  const m = msg().report.doctor;
60110
60671
  report2.section(m.dirsTitle);
60111
60672
  report2.item(m.configDir(level.configDir));
60112
- report2.item(m.dataDir(level.dataDir, (0, import_node_fs54.existsSync)(level.dataDir)));
60673
+ report2.item(m.dataDir(level.dataDir, (0, import_node_fs55.existsSync)(level.dataDir)));
60113
60674
  await fileHistoryLine(report2, level.dataDir);
60114
60675
  report2.section(m.layersTitle);
60115
60676
  report2.item(m.builtinDefaults);
@@ -60333,10 +60894,11 @@ init_http();
60333
60894
  init_presets2();
60334
60895
  init_live();
60335
60896
  init_registry2();
60897
+ init_discovered_cache();
60336
60898
  init_catalog2();
60337
60899
  init_models_dev_cache();
60338
60900
  init_models_dev();
60339
- var import_node_fs55 = require("node:fs");
60901
+ var import_node_fs56 = require("node:fs");
60340
60902
  init_load();
60341
60903
  init_write2();
60342
60904
  init_args();
@@ -60692,7 +61254,7 @@ function writeEntries(ctx, provider, entries, notes) {
60692
61254
  return 0;
60693
61255
  }
60694
61256
  models.push(...added);
60695
- const backup = (0, import_node_fs55.existsSync)(path);
61257
+ const backup = (0, import_node_fs56.existsSync)(path);
60696
61258
  writeConfigFile(path, config, { backup: true });
60697
61259
  io.stdout(m.written(path, provider.id, added.length, kept, backup));
60698
61260
  if (notes.noTools.size > 0) io.stdout(m.skippedNoTools([...notes.noTools].join(", ")));
@@ -60724,6 +61286,7 @@ async function run6(ctx) {
60724
61286
  }
60725
61287
  const configured2 = new Map(provider.models.map((m2) => [m2.id, m2]));
60726
61288
  io.stdout(m.found(provider.id, found.length, modelsUrl(provider)));
61289
+ if (provider.id === CHATGPT_PROVIDER_ID) cacheChatGpt(ctx, found, key.apiKey);
60727
61290
  const mdIndex = loadModelsDevIndex(ctx.level.dataDir);
60728
61291
  io.stdout(`${describeModelsDev(ctx.level.dataDir)}
60729
61292
  `);
@@ -60782,6 +61345,17 @@ async function run6(ctx) {
60782
61345
  }
60783
61346
  return ExitCode.Ok;
60784
61347
  }
61348
+ function cacheChatGpt(ctx, found, apiKey) {
61349
+ try {
61350
+ const flavor = liveToken(apiKey)?.flavor;
61351
+ const models = found.map((m) => ({ id: m.id, ...m.name !== m.id ? { name: m.name } : {} }));
61352
+ const path = writeDiscoveredCache(ctx.level.dataDir, CHATGPT_PROVIDER_ID, { models, flavor });
61353
+ ctx.io.stdout(msg().subcommands.discover.cached(path));
61354
+ } catch (error2) {
61355
+ ctx.io.stderr(`ama: ${error2.message}
61356
+ `);
61357
+ }
61358
+ }
60785
61359
  var DISCOVER_ACTION = {
60786
61360
  usage: "ama models discover <provider> [--probe] [--write] [--limit <n>] [--concurrency <n>] [--probe-timeout <ms>]",
60787
61361
  required: "<provider>",
@@ -60790,6 +61364,132 @@ var DISCOVER_ACTION = {
60790
61364
  run: run6
60791
61365
  };
60792
61366
 
61367
+ // src/cli/subcommands/models-enable.ts
61368
+ init_model_visibility();
61369
+ init_edit2();
61370
+ init_types_w5();
61371
+ init_i18n();
61372
+ init_args();
61373
+ init_exit_codes();
61374
+ function layerInput2(ctx) {
61375
+ const input2 = {
61376
+ configDir: ctx.level.configDir,
61377
+ cwd: ctx.io.cwd,
61378
+ env: ctx.io.env
61379
+ };
61380
+ if (ctx.level.profile !== void 0) {
61381
+ input2.profile = { config: ctx.level.profile.config };
61382
+ input2.hasProfile = true;
61383
+ }
61384
+ return input2;
61385
+ }
61386
+ function checkRefs(ctx, refs) {
61387
+ const m = msg().subcommands.modelsEnabled;
61388
+ for (const ref of refs) {
61389
+ const parts = splitEnabledRef(ref);
61390
+ if (!MODELS_ENABLED_REF.test(ref) || parts === void 0) throw new UsageError(m.badRef(ref));
61391
+ const provider = ctx.registry.get(parts.provider);
61392
+ if (provider === void 0) {
61393
+ ctx.io.stderr(msg().subcommands.common.providerNotFound(parts.provider));
61394
+ return ExitCode.NoModel;
61395
+ }
61396
+ if (parts.model !== "*" && provider.models.length > 0 && !provider.models.some((model) => model.id === parts.model))
61397
+ ctx.io.stderr(m.unknownModel(ref));
61398
+ }
61399
+ return void 0;
61400
+ }
61401
+ function userList(input2) {
61402
+ return enabledList(readSnapshot(input2).user?.models?.enabled);
61403
+ }
61404
+ async function enable(ctx) {
61405
+ const m = msg().subcommands.modelsEnabled;
61406
+ const refs = [...new Set(ctx.args)];
61407
+ const bad = checkRefs(ctx, refs);
61408
+ if (bad !== void 0) return bad;
61409
+ const input2 = layerInput2(ctx);
61410
+ const current3 = userList(input2);
61411
+ const fresh = refs.filter((ref) => !(current3 ?? []).includes(ref));
61412
+ if (fresh.length === 0) {
61413
+ ctx.io.stdout(m.alreadyListed(refs.join(", ")));
61414
+ return ExitCode.Ok;
61415
+ }
61416
+ const result = setConfigValue({
61417
+ ...input2,
61418
+ scope: "user",
61419
+ key: "models.enabled",
61420
+ value: addEnabled(current3, fresh)
61421
+ });
61422
+ ctx.io.stdout(m.added(fresh.join(", "), result.path));
61423
+ return ExitCode.Ok;
61424
+ }
61425
+ async function disable(ctx) {
61426
+ const m = msg().subcommands.modelsEnabled;
61427
+ const refs = [...new Set(ctx.args)];
61428
+ for (const ref of refs) if (!MODELS_ENABLED_REF.test(ref)) throw new UsageError(m.badRef(ref));
61429
+ const input2 = layerInput2(ctx);
61430
+ const current3 = userList(input2) ?? [];
61431
+ const listed2 = refs.filter((ref) => current3.includes(ref));
61432
+ const missing = refs.filter((ref) => !current3.includes(ref));
61433
+ if (missing.length > 0) ctx.io.stderr(m.notListed(missing.join(", ")));
61434
+ if (listed2.length === 0) return missing.length > 0 ? ExitCode.RuntimeError : ExitCode.Ok;
61435
+ const next = removeEnabled(current3, listed2);
61436
+ const result = setConfigValue({ ...input2, scope: "user", key: "models.enabled", value: next });
61437
+ ctx.io.stdout(
61438
+ next === void 0 ? m.cleared(result.path) : m.removed(listed2.join(", "), result.path)
61439
+ );
61440
+ return ExitCode.Ok;
61441
+ }
61442
+ async function listEnabled(ctx) {
61443
+ const m = msg().subcommands.modelsEnabled;
61444
+ const labels = msg().panels.model;
61445
+ const list5 = enabledList(ctx.level.merged.config.models?.enabled);
61446
+ const status = async (providerId) => {
61447
+ const provider = ctx.registry.get(providerId);
61448
+ if (provider === void 0) return "?";
61449
+ const access = await providerAccess(ctx.registry, provider);
61450
+ return access === "none" ? labels.noKey : labels[access];
61451
+ };
61452
+ if (list5 !== void 0) {
61453
+ ctx.io.stdout(m.listHeader(ctx.level.userConfigPath));
61454
+ for (const ref of list5) {
61455
+ const parts = splitEnabledRef(ref);
61456
+ const provider = parts === void 0 ? void 0 : ctx.registry.get(parts.provider);
61457
+ const known = parts === void 0 || parts.model === "*" || provider === void 0 || provider.models.length === 0 || provider.models.some((model) => model.id === parts.model);
61458
+ const notes = [
61459
+ parts === void 0 ? "?" : await status(parts.provider),
61460
+ ...known ? [] : [m.notInTable]
61461
+ ];
61462
+ ctx.io.stdout(` ${ref} ${notes.join(" · ")}
61463
+ `);
61464
+ }
61465
+ return ExitCode.Ok;
61466
+ }
61467
+ ctx.io.stdout(m.listUnset);
61468
+ let shown2 = 0;
61469
+ for (const provider of ctx.registry.list()) {
61470
+ const access = await providerAccess(ctx.registry, provider);
61471
+ if (!accessReady(access)) continue;
61472
+ const label2 = access === "none" ? labels.noKey : labels[access];
61473
+ for (const model of provider.models) {
61474
+ ctx.io.stdout(` ${provider.id}/${model.id} ${label2}
61475
+ `);
61476
+ shown2++;
61477
+ }
61478
+ }
61479
+ if (shown2 === 0) ctx.io.stdout(m.nothing);
61480
+ return ExitCode.Ok;
61481
+ }
61482
+ var ENABLE_ACTION = {
61483
+ usage: "ama models enable <provider/model[@channel]|provider/*>…",
61484
+ required: "<provider/model>",
61485
+ run: enable
61486
+ };
61487
+ var DISABLE_ACTION = {
61488
+ usage: "ama models disable <provider/model[@channel]|provider/*>…",
61489
+ required: "<provider/model>",
61490
+ run: disable
61491
+ };
61492
+
60793
61493
  // src/cli/subcommands/models.ts
60794
61494
  init_model_meta();
60795
61495
  init_i18n();
@@ -60887,9 +61587,10 @@ var REFRESH_ACTION = {
60887
61587
  };
60888
61588
  var MODELS_ACTIONS = Object.freeze({
60889
61589
  list: {
60890
- usage: "ama models list [--provider <id>]",
61590
+ usage: "ama models list [--provider <id>] [--enabled]",
60891
61591
  valueOptions: ["provider"],
60892
- run: (ctx) => list3(ctx.io, ctx.registry, ctx.values.get("provider"))
61592
+ flagOptions: ["enabled"],
61593
+ run: (ctx) => ctx.flags.has("enabled") ? listEnabled(ctx) : list3(ctx.io, ctx.registry, ctx.values.get("provider"))
60893
61594
  },
60894
61595
  check: {
60895
61596
  usage: "ama models check <provider/id>",
@@ -60905,7 +61606,9 @@ var MODELS_ACTIONS = Object.freeze({
60905
61606
  get usage() {
60906
61607
  return msg().subcommands.models.refreshCatalogUsage;
60907
61608
  }
60908
- }
61609
+ },
61610
+ enable: ENABLE_ACTION,
61611
+ disable: DISABLE_ACTION
60909
61612
  });
60910
61613
  function modelsUsage() {
60911
61614
  return msg().subcommands.models.usage(Object.values(MODELS_ACTIONS).map((a) => a.usage));
@@ -60953,7 +61656,7 @@ async function runModels(argv, io, deps) {
60953
61656
  }
60954
61657
 
60955
61658
  // src/cli/subcommands/providers.ts
60956
- var import_node_fs56 = require("node:fs");
61659
+ var import_node_fs57 = require("node:fs");
60957
61660
  init_models_dev_cache();
60958
61661
  init_models_dev();
60959
61662
  init_auth_file();
@@ -61610,7 +62313,7 @@ ${renderTable2(result.plans)}`);
61610
62313
  const providers = config.providers ??= {};
61611
62314
  providers[id] = merged.config;
61612
62315
  if (defaultPick !== void 0) config.defaultModel = `${id}/${defaultPick.id}`;
61613
- const backup = (0, import_node_fs56.existsSync)(level.userConfigPath);
62316
+ const backup = (0, import_node_fs57.existsSync)(level.userConfigPath);
61614
62317
  writeConfigFile(level.userConfigPath, config, { backup: true });
61615
62318
  if (key.store !== void 0) setAuthKey(level.authFile, id, key.store);
61616
62319
  io.stdout(m.written(level.userConfigPath, backup));
@@ -61726,7 +62429,7 @@ init_init();
61726
62429
  init_paths();
61727
62430
 
61728
62431
  // src/cli/subcommands/sessions.ts
61729
- var import_node_path83 = require("node:path");
62432
+ var import_node_path84 = require("node:path");
61730
62433
  init_gc();
61731
62434
  init_paths();
61732
62435
  init_args();
@@ -61735,8 +62438,8 @@ init_reuse();
61735
62438
  init_clipboard_image();
61736
62439
 
61737
62440
  // src/cli/subcommands/sessions-export.ts
61738
- var import_node_fs58 = require("node:fs");
61739
- var import_node_path77 = require("node:path");
62441
+ var import_node_fs59 = require("node:fs");
62442
+ var import_node_path78 = require("node:path");
61740
62443
  init_paths();
61741
62444
 
61742
62445
  // src/session/export.ts
@@ -61958,7 +62661,7 @@ async function runSessionsExport(argv, io) {
61958
62661
  throw new UsageError(msg().subcommands.common.invalidChoice("--branch", BRANCHES, branch));
61959
62662
  }
61960
62663
  const dirFlag = values.get("session-dir");
61961
- const root = dirFlag !== void 0 ? (0, import_node_path77.resolve)(io.cwd, expandHome(dirFlag, { env: io.env })) : (0, import_node_path77.join)(resolveDataDir({ env: io.env }), "sessions");
62664
+ const root = dirFlag !== void 0 ? (0, import_node_path78.resolve)(io.cwd, expandHome(dirFlag, { env: io.env })) : (0, import_node_path78.join)(resolveDataDir({ env: io.env }), "sessions");
61962
62665
  const session = readSessionReadOnly(findSessionFileReadOnly(root, id, io.cwd));
61963
62666
  const text = renderExport(session, format, branch);
61964
62667
  const output = values.get("output");
@@ -61966,14 +62669,14 @@ async function runSessionsExport(argv, io) {
61966
62669
  io.stdout(text);
61967
62670
  return ExitCode.Ok;
61968
62671
  }
61969
- const target = (0, import_node_path77.resolve)(io.cwd, expandHome(output, { env: io.env }));
61970
- (0, import_node_fs58.writeFileSync)(target, text, { mode: 384 });
62672
+ const target = (0, import_node_path78.resolve)(io.cwd, expandHome(output, { env: io.env }));
62673
+ (0, import_node_fs59.writeFileSync)(target, text, { mode: 384 });
61971
62674
  io.stderr(msg().subcommands.sessionsExport.exported(target));
61972
62675
  return ExitCode.Ok;
61973
62676
  }
61974
62677
 
61975
62678
  // src/cli/subcommands/sessions-search.ts
61976
- var import_node_path80 = require("node:path");
62679
+ var import_node_path81 = require("node:path");
61977
62680
  init_paths();
61978
62681
  init_scan();
61979
62682
 
@@ -62151,7 +62854,7 @@ init_args();
62151
62854
  init_exit_codes();
62152
62855
 
62153
62856
  // src/cli/subcommands/stats.ts
62154
- var import_node_path79 = require("node:path");
62857
+ var import_node_path80 = require("node:path");
62155
62858
  init_paths();
62156
62859
  init_scan();
62157
62860
 
@@ -62299,8 +63002,8 @@ function aggregateStats(summaries, options = {}) {
62299
63002
  }
62300
63003
 
62301
63004
  // src/session/stats-index.ts
62302
- var import_node_fs59 = require("node:fs");
62303
- var import_node_path78 = require("node:path");
63005
+ var import_node_fs60 = require("node:fs");
63006
+ var import_node_path79 = require("node:path");
62304
63007
 
62305
63008
  // src/session/stats-scan.ts
62306
63009
  init_scan();
@@ -62513,7 +63216,7 @@ function collectSummaries(files, options = {}) {
62513
63216
  let index2 = { version: INDEX_VERSION, zone, files: {} };
62514
63217
  if (options.indexFile !== void 0) {
62515
63218
  try {
62516
- const loaded = JSON.parse((0, import_node_fs59.readFileSync)(options.indexFile, "utf8"));
63219
+ const loaded = JSON.parse((0, import_node_fs60.readFileSync)(options.indexFile, "utf8"));
62517
63220
  if (loaded.version === INDEX_VERSION && loaded.zone === zone && typeof loaded.files === "object")
62518
63221
  index2 = loaded;
62519
63222
  } catch {
@@ -62524,7 +63227,7 @@ function collectSummaries(files, options = {}) {
62524
63227
  for (const file of files) {
62525
63228
  let stat16;
62526
63229
  try {
62527
- stat16 = (0, import_node_fs59.statSync)(file);
63230
+ stat16 = (0, import_node_fs60.statSync)(file);
62528
63231
  } catch {
62529
63232
  result.invalid++;
62530
63233
  continue;
@@ -62554,10 +63257,10 @@ function collectSummaries(files, options = {}) {
62554
63257
  }
62555
63258
  if (dirty && options.indexFile !== void 0) {
62556
63259
  try {
62557
- (0, import_node_fs59.mkdirSync)((0, import_node_path78.dirname)(options.indexFile), { recursive: true, mode: 448 });
63260
+ (0, import_node_fs60.mkdirSync)((0, import_node_path79.dirname)(options.indexFile), { recursive: true, mode: 448 });
62558
63261
  const tmp = `${options.indexFile}.${process.pid}.tmp`;
62559
- (0, import_node_fs59.writeFileSync)(tmp, JSON.stringify(index2), { mode: 384 });
62560
- (0, import_node_fs59.renameSync)(tmp, options.indexFile);
63262
+ (0, import_node_fs60.writeFileSync)(tmp, JSON.stringify(index2), { mode: 384 });
63263
+ (0, import_node_fs60.renameSync)(tmp, options.indexFile);
62561
63264
  } catch {
62562
63265
  }
62563
63266
  }
@@ -62607,10 +63310,10 @@ function width(text) {
62607
63310
  }
62608
63311
  function table(rows, rightAlign) {
62609
63312
  const widths = [];
62610
- for (const row2 of rows)
62611
- row2.forEach((cell, i) => widths[i] = Math.max(widths[i] ?? 0, width(cell)));
63313
+ for (const row3 of rows)
63314
+ row3.forEach((cell, i) => widths[i] = Math.max(widths[i] ?? 0, width(cell)));
62612
63315
  return rows.map(
62613
- (row2) => row2.map((cell, i) => {
63316
+ (row3) => row3.map((cell, i) => {
62614
63317
  const padding = " ".repeat((widths[i] ?? 0) - width(cell));
62615
63318
  return rightAlign(i) ? padding + cell : cell + padding;
62616
63319
  }).join(" ").trimEnd()
@@ -62718,13 +63421,13 @@ async function runStats(argv, io) {
62718
63421
  }
62719
63422
  const dataDir = resolveDataDir({ env: io.env });
62720
63423
  const dirFlag = values.get("session-dir");
62721
- const root = dirFlag !== void 0 ? (0, import_node_path79.resolve)(io.cwd, expandHome(dirFlag, { env: io.env })) : (0, import_node_path79.join)(dataDir, "sessions");
63424
+ const root = dirFlag !== void 0 ? (0, import_node_path80.resolve)(io.cwd, expandHome(dirFlag, { env: io.env })) : (0, import_node_path80.join)(dataDir, "sessions");
62722
63425
  const projectFlag = values.get("project");
62723
- const project = projectFlag !== void 0 ? (0, import_node_path79.resolve)(io.cwd, expandHome(projectFlag, { env: io.env })) : flags2.has("all") || by === "project" ? void 0 : io.cwd;
63426
+ const project = projectFlag !== void 0 ? (0, import_node_path80.resolve)(io.cwd, expandHome(projectFlag, { env: io.env })) : flags2.has("all") || by === "project" ? void 0 : io.cwd;
62724
63427
  const files = sessionFilesInScope(root, project);
62725
63428
  const useCache = !flags2.has("no-cache");
62726
63429
  const collected = collectSummaries(files, {
62727
- ...useCache ? { indexFile: (0, import_node_path79.join)(dataDir, STATS_INDEX_FILE) } : {},
63430
+ ...useCache ? { indexFile: (0, import_node_path80.join)(dataDir, STATS_INDEX_FILE) } : {},
62728
63431
  prune: project === void 0
62729
63432
  });
62730
63433
  const report2 = aggregateStats(collected.summaries, {
@@ -62819,7 +63522,7 @@ async function runSessionsSearch(argv, io) {
62819
63522
  const sinceRaw = values.get("since");
62820
63523
  const sinceIso = sinceRaw === void 0 ? void 0 : (/* @__PURE__ */ new Date(`${parseDaySpec("since", sinceRaw)}T00:00:00`)).toISOString();
62821
63524
  const dirFlag = values.get("session-dir");
62822
- const root = dirFlag !== void 0 ? (0, import_node_path80.resolve)(io.cwd, expandHome(dirFlag, { env: io.env })) : (0, import_node_path80.join)(resolveDataDir({ env: io.env }), "sessions");
63525
+ const root = dirFlag !== void 0 ? (0, import_node_path81.resolve)(io.cwd, expandHome(dirFlag, { env: io.env })) : (0, import_node_path81.join)(resolveDataDir({ env: io.env }), "sessions");
62823
63526
  const files = sessionFilesInScope(root, flags2.has("all") ? void 0 : io.cwd);
62824
63527
  const { hits, truncated } = searchSessions(files, query, {
62825
63528
  limit,
@@ -62843,9 +63546,9 @@ async function runSessionsSearch(argv, io) {
62843
63546
 
62844
63547
  // src/cli/subcommands/sessions-trace.ts
62845
63548
  var import_node_child_process15 = require("node:child_process");
62846
- var import_node_fs61 = require("node:fs");
63549
+ var import_node_fs62 = require("node:fs");
62847
63550
  var import_node_os12 = require("node:os");
62848
- var import_node_path82 = require("node:path");
63551
+ var import_node_path83 = require("node:path");
62849
63552
  init_paths();
62850
63553
  init_i18n();
62851
63554
  init_scan();
@@ -63061,8 +63764,8 @@ function mapTime(points, raw) {
63061
63764
  }
63062
63765
  return prev[1] + (raw - prev[0]);
63063
63766
  }
63064
- function segments2(row2, at) {
63065
- const node = row2.node;
63767
+ function segments2(row3, at) {
63768
+ const node = row3.node;
63066
63769
  if (node.kind === "more" || node.kind === "aux_group") return [];
63067
63770
  const out = [];
63068
63771
  const running = node.status === "running" && node.endedAt === void 0;
@@ -63131,20 +63834,20 @@ function traceHtmlData(source, opts) {
63131
63834
  const parents = [];
63132
63835
  const under = [];
63133
63836
  let span = axis.at(-1)?.[1] ?? 0;
63134
- flat2.forEach((row2, i) => {
63135
- parents.length = row2.depth;
63136
- const node = row2.node;
63837
+ flat2.forEach((row3, i) => {
63838
+ parents.length = row3.depth;
63839
+ const node = row3.node;
63137
63840
  const out = {
63138
- d: row2.depth,
63139
- p: row2.depth === 0 ? -1 : parents[row2.depth - 1] ?? -1,
63841
+ d: row3.depth,
63842
+ p: row3.depth === 0 ? -1 : parents[row3.depth - 1] ?? -1,
63140
63843
  k: node.kind,
63141
- l: redactSecrets(rowLabel(row2, describe4 === void 0 ? {} : { describe: describe4 })),
63844
+ l: redactSecrets(rowLabel(row3, describe4 === void 0 ? {} : { describe: describe4 })),
63142
63845
  kv: []
63143
63846
  };
63144
63847
  const parent = out.p < 0 ? void 0 : rows[out.p];
63145
- const inChild = row2.depth > 0 && ((under[row2.depth - 1] ?? false) || parent?.k === "subagent");
63146
- under[row2.depth] = inChild;
63147
- parents[row2.depth] = i;
63848
+ const inChild = row3.depth > 0 && ((under[row3.depth - 1] ?? false) || parent?.k === "subagent");
63849
+ under[row3.depth] = inChild;
63850
+ parents[row3.depth] = i;
63148
63851
  if (node.kind !== "more" && node.kind !== "aux_group") {
63149
63852
  if (node.status !== "ok") {
63150
63853
  out.s = m.status[node.status];
@@ -63157,7 +63860,7 @@ function traceHtmlData(source, opts) {
63157
63860
  const ca = cacheText2(node);
63158
63861
  if (ca !== "") out.ca = ca;
63159
63862
  out.kv = summaryRows(node, theme, t0).filter(([label2]) => opts.content || !dropKeys.has(label2)).map(([label2, value]) => [label2, redactSecrets(value)]);
63160
- const g = segments2(row2, at);
63863
+ const g = segments2(row3, at);
63161
63864
  if (g.length > 0) {
63162
63865
  out.g = g;
63163
63866
  for (const seg of g) span = Math.max(span, seg[1]);
@@ -63170,20 +63873,20 @@ function traceHtmlData(source, opts) {
63170
63873
  }
63171
63874
  }
63172
63875
  }
63173
- if (row2.expandable && defaultExpanded(node)) out.e = 1;
63174
- if (node.kind === "turn" && row2.depth === 0) out.t = row2.turn;
63876
+ if (row3.expandable && defaultExpanded(node)) out.e = 1;
63877
+ if (node.kind === "turn" && row3.depth === 0) out.t = row3.turn;
63175
63878
  rows.push(out);
63176
63879
  });
63177
63880
  let budget = opts.previewBudget ?? PREVIEW_BUDGET;
63178
63881
  for (let i = rows.length - 1; i >= 0; i--) {
63179
- const row2 = rows[i];
63180
- if (row2.pv === void 0) continue;
63181
- const size = row2.pv.reduce((n, [, text]) => n + text.length, 0);
63882
+ const row3 = rows[i];
63883
+ if (row3.pv === void 0) continue;
63884
+ const size = row3.pv.reduce((n, [, text]) => n + text.length, 0);
63182
63885
  if (size <= budget) budget -= size;
63183
63886
  else {
63184
63887
  budget = 0;
63185
- delete row2.pv;
63186
- row2.pd = 1;
63888
+ delete row3.pv;
63889
+ row3.pd = 1;
63187
63890
  }
63188
63891
  }
63189
63892
  const h = m.html;
@@ -63281,9 +63984,9 @@ function splitHtmlFlag(argv) {
63281
63984
  return { rest, html, ...file !== void 0 ? { file } : {} };
63282
63985
  }
63283
63986
  function locate(io, target, dirFlag) {
63284
- const asPath = (0, import_node_path82.resolve)(io.cwd, expandHome(target, { env: io.env }));
63285
- if (/[\\/]|\.jsonl$/.test(target) && (0, import_node_fs61.existsSync)(asPath)) return asPath;
63286
- const root = dirFlag !== void 0 ? (0, import_node_path82.resolve)(io.cwd, expandHome(dirFlag, { env: io.env })) : (0, import_node_path82.join)(resolveDataDir({ env: io.env }), "sessions");
63987
+ const asPath = (0, import_node_path83.resolve)(io.cwd, expandHome(target, { env: io.env }));
63988
+ if (/[\\/]|\.jsonl$/.test(target) && (0, import_node_fs62.existsSync)(asPath)) return asPath;
63989
+ const root = dirFlag !== void 0 ? (0, import_node_path83.resolve)(io.cwd, expandHome(dirFlag, { env: io.env })) : (0, import_node_path83.join)(resolveDataDir({ env: io.env }), "sessions");
63287
63990
  return findSessionFileReadOnly(root, target, io.cwd);
63288
63991
  }
63289
63992
  async function runSessionsTrace(argv, io, deps = {}) {
@@ -63348,14 +64051,14 @@ async function runSessionsTrace(argv, io, deps = {}) {
63348
64051
  }
63349
64052
  const outFlag = split.file ?? values.get("output");
63350
64053
  const open2 = flags2.has("open");
63351
- let outPath = outFlag === void 0 ? void 0 : (0, import_node_path82.resolve)(io.cwd, expandHome(outFlag, { env: io.env }));
64054
+ let outPath = outFlag === void 0 ? void 0 : (0, import_node_path83.resolve)(io.cwd, expandHome(outFlag, { env: io.env }));
63352
64055
  if (outPath === void 0 && open2)
63353
- outPath = (0, import_node_path82.join)((0, import_node_os12.tmpdir)(), `ama-trace-${read2.header.id}.${wantsJson ? "json" : "html"}`);
64056
+ outPath = (0, import_node_path83.join)((0, import_node_os12.tmpdir)(), `ama-trace-${read2.header.id}.${wantsJson ? "json" : "html"}`);
63354
64057
  if (outPath === void 0) {
63355
64058
  io.stdout(text);
63356
64059
  return ExitCode.Ok;
63357
64060
  }
63358
- (0, import_node_fs61.writeFileSync)(outPath, text, { mode: 384 });
64061
+ (0, import_node_fs62.writeFileSync)(outPath, text, { mode: 384 });
63359
64062
  io.stderr(m.wrote(outPath));
63360
64063
  if (open2) {
63361
64064
  try {
@@ -63396,7 +64099,7 @@ async function runSessions(argv, io, deps) {
63396
64099
  return flags2.has("help") ? ExitCode.Ok : ExitCode.Usage;
63397
64100
  }
63398
64101
  const dirFlag = values.get("session-dir");
63399
- const sessionDir = dirFlag !== void 0 ? (0, import_node_path83.resolve)(io.cwd, expandHome(dirFlag, { env: io.env })) : (0, import_node_path83.resolve)(resolveDataDir({ env: io.env }), "sessions");
64102
+ const sessionDir = dirFlag !== void 0 ? (0, import_node_path84.resolve)(io.cwd, expandHome(dirFlag, { env: io.env })) : (0, import_node_path84.resolve)(resolveDataDir({ env: io.env }), "sessions");
63400
64103
  const sessions = deps?.sessions;
63401
64104
  const scope = flags2.has("all") ? {} : { cwd: io.cwd };
63402
64105
  switch (action) {
@@ -63482,7 +64185,7 @@ async function pruneFileHistory(io, sessionDir, dryRun) {
63482
64185
  try {
63483
64186
  const result = await gcBlobs({
63484
64187
  dataDir,
63485
- sessionRoots: [sessionDir, (0, import_node_path83.join)(dataDir, "sessions")],
64188
+ sessionRoots: [sessionDir, (0, import_node_path84.join)(dataDir, "sessions")],
63486
64189
  dryRun
63487
64190
  });
63488
64191
  if (result.removed.length === 0) return;
@@ -63556,7 +64259,7 @@ function readStdinDefault() {
63556
64259
  }
63557
64260
  function stdinKindDefault() {
63558
64261
  try {
63559
- const stat16 = (0, import_node_fs70.fstatSync)(0);
64262
+ const stat16 = (0, import_node_fs71.fstatSync)(0);
63560
64263
  if (stat16.isFile()) return "file";
63561
64264
  if (stat16.isFIFO()) return "fifo";
63562
64265
  if (stat16.isSocket()) return "socket";
@@ -63616,7 +64319,7 @@ function defaultIo() {
63616
64319
  }
63617
64320
  function peekUserLanguage(env) {
63618
64321
  try {
63619
- const raw = (0, import_node_fs70.readFileSync)((0, import_node_path99.join)(resolveConfigDir({ env }), "config.json"), "utf8");
64322
+ const raw = (0, import_node_fs71.readFileSync)((0, import_node_path100.join)(resolveConfigDir({ env }), "config.json"), "utf8");
63620
64323
  const value = JSON.parse(raw).ui?.language;
63621
64324
  return value === "auto" || value === "zh" || value === "en" ? value : void 0;
63622
64325
  } catch {
@@ -63704,7 +64407,7 @@ function isDirectRun() {
63704
64407
  const entry = process.argv[1];
63705
64408
  if (entry === void 0) return false;
63706
64409
  try {
63707
- return (0, import_node_fs70.realpathSync)(entry) === (0, import_node_fs70.realpathSync)((0, import_node_url3.fileURLToPath)(__ama_import_meta_url));
64410
+ return (0, import_node_fs71.realpathSync)(entry) === (0, import_node_fs71.realpathSync)((0, import_node_url3.fileURLToPath)(__ama_import_meta_url));
63708
64411
  } catch {
63709
64412
  return false;
63710
64413
  }