@ai-agent-forge/agent-forge 0.88.1 → 0.88.3

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 (518) hide show
  1. package/CHANGELOG.md +71 -0
  2. package/README.md +1 -1
  3. package/bundled-plugins/agent-loop-policy/agent-forge.json +1 -1
  4. package/bundled-plugins/agent-loop-policy/plugin.json +1 -1
  5. package/bundled-plugins/coding-tools/agent-forge.json +1 -1
  6. package/bundled-plugins/coding-tools/plugin.json +1 -1
  7. package/bundled-plugins/compaction-policy/agent-forge.json +1 -1
  8. package/bundled-plugins/compaction-policy/plugin.json +1 -1
  9. package/bundled-plugins/overflow-policy/agent-forge.json +1 -1
  10. package/bundled-plugins/overflow-policy/plugin.json +1 -1
  11. package/bundled-plugins/provider-failover/agent-forge.json +1 -1
  12. package/bundled-plugins/provider-failover/plugin.json +1 -1
  13. package/bundled-plugins/retry-policy/agent-forge.json +1 -1
  14. package/bundled-plugins/retry-policy/plugin.json +1 -1
  15. package/dist/artifacts/paged-read.d.ts +6 -1
  16. package/dist/artifacts/paged-read.d.ts.map +1 -1
  17. package/dist/artifacts/paged-read.js.map +1 -1
  18. package/dist/bundle/.build-manifest.json +283 -263
  19. package/dist/bundle/chunks/{anthropic-messages-PLAKXR73.js → anthropic-messages-3FJHRAJL.js} +2 -2
  20. package/dist/bundle/chunks/anthropic.js +1 -1
  21. package/dist/bundle/chunks/{azure-openai-responses-OUWQ2AZD.js → azure-openai-responses-GCL47IDS.js} +1 -1
  22. package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
  23. package/dist/bundle/chunks/{chunk-Z72JWUZ4.js → chunk-32YDZI4J.js} +1 -1
  24. package/dist/bundle/chunks/{chunk-AQLNTW2B.js → chunk-755VNWIF.js} +17 -16
  25. package/dist/bundle/chunks/{chunk-LZOEQITZ.js → chunk-B42Y2VME.js} +120 -104
  26. package/dist/bundle/chunks/{chunk-DRQDKNXA.js → chunk-BVVSHK6W.js} +1 -1
  27. package/dist/bundle/chunks/{chunk-6R7UI4IY.js → chunk-QDLOMKF6.js} +1 -1
  28. package/dist/bundle/chunks/{chunk-D3ARGZFR.js → chunk-V3ACW7VD.js} +3 -3
  29. package/dist/bundle/chunks/{google-generative-ai-DLII6DAT.js → google-generative-ai-6BMXWA44.js} +1 -1
  30. package/dist/bundle/chunks/{google-vertex-G7BZL7GM.js → google-vertex-6H7NLRTK.js} +1 -1
  31. package/dist/bundle/chunks/image-resize-worker.js +3 -3
  32. package/dist/bundle/chunks/{mistral-conversations-JXUK24ID.js → mistral-conversations-IXUHSFSJ.js} +1 -1
  33. package/dist/bundle/chunks/{openai-codex-responses-5GSGFIPG.js → openai-codex-responses-YHUAEVCM.js} +1 -1
  34. package/dist/bundle/chunks/openai-codex.js +1 -1
  35. package/dist/bundle/chunks/{openai-completions-EI2I6DTG.js → openai-completions-ULQCFC72.js} +1 -1
  36. package/dist/bundle/chunks/openai-responses-NLLAJDPS.js +2 -0
  37. package/dist/bundle/chunks/{openrouter-images-G4GQRUSG.js → openrouter-images-GZZQZXMS.js} +1 -1
  38. package/dist/bundle/chunks/openrouter.js +1 -1
  39. package/dist/bundle/chunks/{pi-messages-PWU2VJMR.js → pi-messages-EJTI2EJ3.js} +1 -1
  40. package/dist/bundle/chunks/virtual-modules-TQWEGNNZ.js +5 -0
  41. package/dist/bundle/cli.js +1 -1
  42. package/dist/bundle/client.js +1 -1
  43. package/dist/bundle/index.js +1 -1
  44. package/dist/bundle/rpc-entry.js +1 -1
  45. package/dist/cli/args.d.ts +0 -1
  46. package/dist/cli/args.d.ts.map +1 -1
  47. package/dist/cli/args.js +1 -4
  48. package/dist/cli/args.js.map +1 -1
  49. package/dist/cli/config-selector.d.ts.map +1 -1
  50. package/dist/cli/config-selector.js +1 -1
  51. package/dist/cli/config-selector.js.map +1 -1
  52. package/dist/cli/experimental/cli.d.ts +3 -3
  53. package/dist/cli/experimental/cli.d.ts.map +1 -1
  54. package/dist/cli/experimental/cli.js +2 -2
  55. package/dist/cli/experimental/cli.js.map +1 -1
  56. package/dist/cli/experimental/commands/agent-forge.d.ts +15 -0
  57. package/dist/cli/experimental/commands/agent-forge.d.ts.map +1 -0
  58. package/dist/cli/experimental/commands/{pi.js → agent-forge.js} +4 -4
  59. package/dist/cli/experimental/commands/agent-forge.js.map +1 -0
  60. package/dist/cli/plugin-command.d.ts.map +1 -1
  61. package/dist/cli/plugin-command.js +8 -2
  62. package/dist/cli/plugin-command.js.map +1 -1
  63. package/dist/cli/startup-ui.d.ts.map +1 -1
  64. package/dist/cli/startup-ui.js +1 -1
  65. package/dist/cli/startup-ui.js.map +1 -1
  66. package/dist/config.d.ts +4 -4
  67. package/dist/config.d.ts.map +1 -1
  68. package/dist/config.js +7 -7
  69. package/dist/config.js.map +1 -1
  70. package/dist/core/agent-forge-manifest.d.ts +7 -0
  71. package/dist/core/agent-forge-manifest.d.ts.map +1 -0
  72. package/dist/core/{pi-manifest.js → agent-forge-manifest.js} +4 -4
  73. package/dist/core/agent-forge-manifest.js.map +1 -0
  74. package/dist/core/agent-session-compaction.d.ts +1 -1
  75. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  76. package/dist/core/agent-session-compaction.js +3 -3
  77. package/dist/core/agent-session-compaction.js.map +1 -1
  78. package/dist/core/agent-session-internal.d.ts +2 -0
  79. package/dist/core/agent-session-internal.d.ts.map +1 -1
  80. package/dist/core/agent-session-internal.js.map +1 -1
  81. package/dist/core/agent-session-lifecycle.d.ts.map +1 -1
  82. package/dist/core/agent-session-lifecycle.js +12 -1
  83. package/dist/core/agent-session-lifecycle.js.map +1 -1
  84. package/dist/core/agent-session-projection.d.ts.map +1 -1
  85. package/dist/core/agent-session-projection.js +3 -3
  86. package/dist/core/agent-session-projection.js.map +1 -1
  87. package/dist/core/agent-session-services.d.ts +3 -1
  88. package/dist/core/agent-session-services.d.ts.map +1 -1
  89. package/dist/core/agent-session-services.js +2 -1
  90. package/dist/core/agent-session-services.js.map +1 -1
  91. package/dist/core/agent-session-store.d.ts.map +1 -1
  92. package/dist/core/agent-session-store.js +6 -1
  93. package/dist/core/agent-session-store.js.map +1 -1
  94. package/dist/core/agent-session-tools.d.ts.map +1 -1
  95. package/dist/core/agent-session-tools.js +13 -0
  96. package/dist/core/agent-session-tools.js.map +1 -1
  97. package/dist/core/agent-session.d.ts +24 -0
  98. package/dist/core/agent-session.d.ts.map +1 -1
  99. package/dist/core/agent-session.js +58 -4
  100. package/dist/core/agent-session.js.map +1 -1
  101. package/dist/core/compaction/branch-summarization.d.ts.map +1 -1
  102. package/dist/core/compaction/branch-summarization.js +1 -1
  103. package/dist/core/compaction/branch-summarization.js.map +1 -1
  104. package/dist/core/experimental.d.ts.map +1 -1
  105. package/dist/core/experimental.js +1 -3
  106. package/dist/core/experimental.js.map +1 -1
  107. package/dist/core/extensions/capability-runtime-store.d.ts +20 -1
  108. package/dist/core/extensions/capability-runtime-store.d.ts.map +1 -1
  109. package/dist/core/extensions/capability-runtime-store.js +67 -0
  110. package/dist/core/extensions/capability-runtime-store.js.map +1 -1
  111. package/dist/core/extensions/capability-runtime-types.d.ts +14 -0
  112. package/dist/core/extensions/capability-runtime-types.d.ts.map +1 -1
  113. package/dist/core/extensions/capability-runtime-types.js +7 -1
  114. package/dist/core/extensions/capability-runtime-types.js.map +1 -1
  115. package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
  116. package/dist/core/extensions/capability-runtime.js +144 -42
  117. package/dist/core/extensions/capability-runtime.js.map +1 -1
  118. package/dist/core/extensions/virtual-modules.d.ts.map +1 -1
  119. package/dist/core/extensions/virtual-modules.js +6 -1
  120. package/dist/core/extensions/virtual-modules.js.map +1 -1
  121. package/dist/core/facade/coding-agent-facade.d.ts +1 -1
  122. package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
  123. package/dist/core/facade/coding-agent-facade.js +1 -1
  124. package/dist/core/facade/coding-agent-facade.js.map +1 -1
  125. package/dist/core/i18n/locales/zh-cn/cli.d.ts.map +1 -1
  126. package/dist/core/i18n/locales/zh-cn/cli.js +2 -0
  127. package/dist/core/i18n/locales/zh-cn/cli.js.map +1 -1
  128. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts +1 -1
  129. package/dist/core/i18n/locales/zh-cn/core-contract-final.d.ts.map +1 -1
  130. package/dist/core/i18n/locales/zh-cn/core-contract-final.js +3 -3
  131. package/dist/core/i18n/locales/zh-cn/core-contract-final.js.map +1 -1
  132. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.d.ts.map +1 -1
  133. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js +1 -1
  134. package/dist/core/i18n/locales/zh-cn/core-contract-plugins.js.map +1 -1
  135. package/dist/core/i18n/locales/zh-cn/core-errors.d.ts.map +1 -1
  136. package/dist/core/i18n/locales/zh-cn/core-errors.js +1 -1
  137. package/dist/core/i18n/locales/zh-cn/core-errors.js.map +1 -1
  138. package/dist/core/i18n/locales/zh-cn/index.d.ts.map +1 -1
  139. package/dist/core/i18n/locales/zh-cn/index.js +2 -0
  140. package/dist/core/i18n/locales/zh-cn/index.js.map +1 -1
  141. package/dist/core/i18n/locales/zh-cn/interactive-mode.d.ts.map +1 -1
  142. package/dist/core/i18n/locales/zh-cn/interactive-mode.js +5 -0
  143. package/dist/core/i18n/locales/zh-cn/interactive-mode.js.map +1 -1
  144. package/dist/core/i18n/locales/zh-cn/session-cleanup.d.ts +7 -0
  145. package/dist/core/i18n/locales/zh-cn/session-cleanup.d.ts.map +1 -0
  146. package/dist/core/i18n/locales/zh-cn/session-cleanup.js +15 -0
  147. package/dist/core/i18n/locales/zh-cn/session-cleanup.js.map +1 -0
  148. package/dist/core/i18n/locales/zh-cn/slash-commands.d.ts.map +1 -1
  149. package/dist/core/i18n/locales/zh-cn/slash-commands.js +1 -0
  150. package/dist/core/i18n/locales/zh-cn/slash-commands.js.map +1 -1
  151. package/dist/core/i18n/locales/zh-cn/tui-components-misc.d.ts.map +1 -1
  152. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js +2 -0
  153. package/dist/core/i18n/locales/zh-cn/tui-components-misc.js.map +1 -1
  154. package/dist/core/model-resolver.d.ts +2 -0
  155. package/dist/core/model-resolver.d.ts.map +1 -1
  156. package/dist/core/model-resolver.js +4 -1
  157. package/dist/core/model-resolver.js.map +1 -1
  158. package/dist/core/package-resource-collection.d.ts.map +1 -1
  159. package/dist/core/package-resource-collection.js +5 -5
  160. package/dist/core/package-resource-collection.js.map +1 -1
  161. package/dist/core/provider-composer.d.ts.map +1 -1
  162. package/dist/core/provider-composer.js +3 -3
  163. package/dist/core/provider-composer.js.map +1 -1
  164. package/dist/core/resource-loader.d.ts.map +1 -1
  165. package/dist/core/resource-loader.js +1 -1
  166. package/dist/core/resource-loader.js.map +1 -1
  167. package/dist/core/sdk.d.ts +1 -1
  168. package/dist/core/sdk.d.ts.map +1 -1
  169. package/dist/core/sdk.js +30 -8
  170. package/dist/core/sdk.js.map +1 -1
  171. package/dist/core/session-cleanup.d.ts +49 -0
  172. package/dist/core/session-cleanup.d.ts.map +1 -0
  173. package/dist/core/session-cleanup.js +159 -0
  174. package/dist/core/session-cleanup.js.map +1 -0
  175. package/dist/core/session-index.d.ts +75 -0
  176. package/dist/core/session-index.d.ts.map +1 -0
  177. package/dist/core/session-index.js +455 -0
  178. package/dist/core/session-index.js.map +1 -0
  179. package/dist/core/session-manager.d.ts +9 -0
  180. package/dist/core/session-manager.d.ts.map +1 -1
  181. package/dist/core/session-manager.js +206 -51
  182. package/dist/core/session-manager.js.map +1 -1
  183. package/dist/core/settings-manager.d.ts.map +1 -1
  184. package/dist/core/settings-manager.js +5 -10
  185. package/dist/core/settings-manager.js.map +1 -1
  186. package/dist/core/slash-commands.d.ts.map +1 -1
  187. package/dist/core/slash-commands.js +5 -0
  188. package/dist/core/slash-commands.js.map +1 -1
  189. package/dist/core/system-prompt.d.ts.map +1 -1
  190. package/dist/core/system-prompt.js +12 -1
  191. package/dist/core/system-prompt.js.map +1 -1
  192. package/dist/core/timings.d.ts.map +1 -1
  193. package/dist/core/timings.js +1 -3
  194. package/dist/core/timings.js.map +1 -1
  195. package/dist/core/tools/capability-mount.d.ts +40 -0
  196. package/dist/core/tools/capability-mount.d.ts.map +1 -0
  197. package/dist/core/tools/capability-mount.js +112 -0
  198. package/dist/core/tools/capability-mount.js.map +1 -0
  199. package/dist/core/tools/render-utils.d.ts +1 -1
  200. package/dist/core/tools/render-utils.d.ts.map +1 -1
  201. package/dist/core/tools/render-utils.js.map +1 -1
  202. package/dist/core/tools/tool-definition.d.ts +1 -1
  203. package/dist/core/tools/tool-definition.d.ts.map +1 -1
  204. package/dist/core/tools/tool-definition.js.map +1 -1
  205. package/dist/core/trace-retention.d.ts +16 -1
  206. package/dist/core/trace-retention.d.ts.map +1 -1
  207. package/dist/core/trace-retention.js +43 -20
  208. package/dist/core/trace-retention.js.map +1 -1
  209. package/dist/export-html/ansi-to-html.d.ts.map +1 -0
  210. package/dist/export-html/ansi-to-html.js.map +1 -0
  211. package/dist/{core/export-html → export-html}/index.d.ts +1 -1
  212. package/dist/export-html/index.d.ts.map +1 -0
  213. package/dist/{core/export-html → export-html}/index.js +5 -5
  214. package/dist/export-html/index.js.map +1 -0
  215. package/dist/{core/export-html → export-html}/tool-renderer.d.ts +2 -2
  216. package/dist/export-html/tool-renderer.d.ts.map +1 -0
  217. package/dist/export-html/tool-renderer.js.map +1 -0
  218. package/dist/{modes/interactive → host}/model-catalog-refresh.d.ts +1 -1
  219. package/dist/host/model-catalog-refresh.d.ts.map +1 -0
  220. package/dist/{modes/interactive → host}/model-catalog-refresh.js +1 -1
  221. package/dist/host/model-catalog-refresh.js.map +1 -0
  222. package/dist/index.d.ts +5 -5
  223. package/dist/index.d.ts.map +1 -1
  224. package/dist/index.js +12 -12
  225. package/dist/index.js.map +1 -1
  226. package/dist/main.d.ts.map +1 -1
  227. package/dist/main.js +26 -14
  228. package/dist/main.js.map +1 -1
  229. package/dist/modes/interactive/components/agents-view.d.ts.map +1 -1
  230. package/dist/modes/interactive/components/agents-view.js +1 -1
  231. package/dist/modes/interactive/components/agents-view.js.map +1 -1
  232. package/dist/modes/interactive/components/armin.d.ts.map +1 -1
  233. package/dist/modes/interactive/components/armin.js +1 -1
  234. package/dist/modes/interactive/components/armin.js.map +1 -1
  235. package/dist/modes/interactive/components/assistant-message.d.ts +6 -0
  236. package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
  237. package/dist/modes/interactive/components/assistant-message.js +108 -27
  238. package/dist/modes/interactive/components/assistant-message.js.map +1 -1
  239. package/dist/modes/interactive/components/bash-execution.d.ts.map +1 -1
  240. package/dist/modes/interactive/components/bash-execution.js +1 -1
  241. package/dist/modes/interactive/components/bash-execution.js.map +1 -1
  242. package/dist/modes/interactive/components/bordered-loader.d.ts +1 -1
  243. package/dist/modes/interactive/components/bordered-loader.d.ts.map +1 -1
  244. package/dist/modes/interactive/components/bordered-loader.js.map +1 -1
  245. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  246. package/dist/modes/interactive/components/branch-summary-message.js +1 -1
  247. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  248. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  249. package/dist/modes/interactive/components/compaction-summary-message.js +1 -1
  250. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  251. package/dist/modes/interactive/components/config-selector.d.ts.map +1 -1
  252. package/dist/modes/interactive/components/config-selector.js +1 -1
  253. package/dist/modes/interactive/components/config-selector.js.map +1 -1
  254. package/dist/modes/interactive/components/custom-entry.d.ts.map +1 -1
  255. package/dist/modes/interactive/components/custom-entry.js +1 -1
  256. package/dist/modes/interactive/components/custom-entry.js.map +1 -1
  257. package/dist/modes/interactive/components/custom-message.d.ts.map +1 -1
  258. package/dist/modes/interactive/components/custom-message.js +1 -1
  259. package/dist/modes/interactive/components/custom-message.js.map +1 -1
  260. package/dist/modes/interactive/components/daxnuts.d.ts.map +1 -1
  261. package/dist/modes/interactive/components/daxnuts.js +1 -1
  262. package/dist/modes/interactive/components/daxnuts.js.map +1 -1
  263. package/dist/modes/interactive/components/dialog-editor.d.ts.map +1 -1
  264. package/dist/modes/interactive/components/dialog-editor.js +1 -1
  265. package/dist/modes/interactive/components/dialog-editor.js.map +1 -1
  266. package/dist/modes/interactive/components/dialog-input.d.ts.map +1 -1
  267. package/dist/modes/interactive/components/dialog-input.js +1 -1
  268. package/dist/modes/interactive/components/dialog-input.js.map +1 -1
  269. package/dist/modes/interactive/components/dialog-selector.d.ts.map +1 -1
  270. package/dist/modes/interactive/components/dialog-selector.js +1 -1
  271. package/dist/modes/interactive/components/dialog-selector.js.map +1 -1
  272. package/dist/modes/interactive/components/diff.d.ts.map +1 -1
  273. package/dist/modes/interactive/components/diff.js +1 -1
  274. package/dist/modes/interactive/components/diff.js.map +1 -1
  275. package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
  276. package/dist/modes/interactive/components/dynamic-border.js +1 -1
  277. package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
  278. package/dist/modes/interactive/components/first-time-setup.d.ts +1 -1
  279. package/dist/modes/interactive/components/first-time-setup.d.ts.map +1 -1
  280. package/dist/modes/interactive/components/first-time-setup.js +1 -1
  281. package/dist/modes/interactive/components/first-time-setup.js.map +1 -1
  282. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  283. package/dist/modes/interactive/components/footer.js +1 -1
  284. package/dist/modes/interactive/components/footer.js.map +1 -1
  285. package/dist/modes/interactive/components/keybinding-hints.d.ts.map +1 -1
  286. package/dist/modes/interactive/components/keybinding-hints.js +1 -1
  287. package/dist/modes/interactive/components/keybinding-hints.js.map +1 -1
  288. package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
  289. package/dist/modes/interactive/components/login-dialog.js +1 -1
  290. package/dist/modes/interactive/components/login-dialog.js.map +1 -1
  291. package/dist/modes/interactive/components/mermaid.d.ts +1 -1
  292. package/dist/modes/interactive/components/mermaid.d.ts.map +1 -1
  293. package/dist/modes/interactive/components/mermaid.js.map +1 -1
  294. package/dist/modes/interactive/components/model-selector.d.ts.map +1 -1
  295. package/dist/modes/interactive/components/model-selector.js +2 -2
  296. package/dist/modes/interactive/components/model-selector.js.map +1 -1
  297. package/dist/modes/interactive/components/oauth-selector.d.ts.map +1 -1
  298. package/dist/modes/interactive/components/oauth-selector.js +1 -1
  299. package/dist/modes/interactive/components/oauth-selector.js.map +1 -1
  300. package/dist/modes/interactive/components/plugin-manager-entry.d.ts.map +1 -1
  301. package/dist/modes/interactive/components/plugin-manager-entry.js +1 -1
  302. package/dist/modes/interactive/components/plugin-manager-entry.js.map +1 -1
  303. package/dist/modes/interactive/components/plugin-selection-entry.d.ts.map +1 -1
  304. package/dist/modes/interactive/components/plugin-selection-entry.js +1 -1
  305. package/dist/modes/interactive/components/plugin-selection-entry.js.map +1 -1
  306. package/dist/modes/interactive/components/queue-manager-selector.d.ts.map +1 -1
  307. package/dist/modes/interactive/components/queue-manager-selector.js +1 -1
  308. package/dist/modes/interactive/components/queue-manager-selector.js.map +1 -1
  309. package/dist/modes/interactive/components/render-types.d.ts +1 -1
  310. package/dist/modes/interactive/components/render-types.d.ts.map +1 -1
  311. package/dist/modes/interactive/components/render-types.js.map +1 -1
  312. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  313. package/dist/modes/interactive/components/scoped-models-selector.js +1 -1
  314. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  315. package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
  316. package/dist/modes/interactive/components/session-selector-search.js +5 -1
  317. package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
  318. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  319. package/dist/modes/interactive/components/session-selector.js +11 -2
  320. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  321. package/dist/modes/interactive/components/settings-selector.d.ts +1 -1
  322. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  323. package/dist/modes/interactive/components/settings-selector.js +1 -1
  324. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  325. package/dist/modes/interactive/components/settings-submenu.d.ts.map +1 -1
  326. package/dist/modes/interactive/components/settings-submenu.js +1 -1
  327. package/dist/modes/interactive/components/settings-submenu.js.map +1 -1
  328. package/dist/modes/interactive/components/show-images-selector.d.ts.map +1 -1
  329. package/dist/modes/interactive/components/show-images-selector.js +1 -1
  330. package/dist/modes/interactive/components/show-images-selector.js.map +1 -1
  331. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  332. package/dist/modes/interactive/components/skill-invocation-message.js +1 -1
  333. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  334. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  335. package/dist/modes/interactive/components/status-indicator.js +1 -1
  336. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  337. package/dist/modes/interactive/components/theme-selector.d.ts.map +1 -1
  338. package/dist/modes/interactive/components/theme-selector.js +1 -1
  339. package/dist/modes/interactive/components/theme-selector.js.map +1 -1
  340. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  341. package/dist/modes/interactive/components/thinking-selector.js +1 -1
  342. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  343. package/dist/modes/interactive/components/tool-execution.d.ts +19 -0
  344. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  345. package/dist/modes/interactive/components/tool-execution.js +139 -4
  346. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  347. package/dist/modes/interactive/components/tool-run-group.d.ts +44 -0
  348. package/dist/modes/interactive/components/tool-run-group.d.ts.map +1 -0
  349. package/dist/modes/interactive/components/tool-run-group.js +121 -0
  350. package/dist/modes/interactive/components/tool-run-group.js.map +1 -0
  351. package/dist/modes/interactive/components/tree-list.d.ts.map +1 -1
  352. package/dist/modes/interactive/components/tree-list.js +1 -1
  353. package/dist/modes/interactive/components/tree-list.js.map +1 -1
  354. package/dist/modes/interactive/components/tree-render.d.ts.map +1 -1
  355. package/dist/modes/interactive/components/tree-render.js +1 -1
  356. package/dist/modes/interactive/components/tree-render.js.map +1 -1
  357. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  358. package/dist/modes/interactive/components/tree-selector.js +1 -1
  359. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  360. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  361. package/dist/modes/interactive/components/user-message-selector.js +1 -1
  362. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  363. package/dist/modes/interactive/components/user-message.d.ts.map +1 -1
  364. package/dist/modes/interactive/components/user-message.js +1 -1
  365. package/dist/modes/interactive/components/user-message.js.map +1 -1
  366. package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -1
  367. package/dist/modes/interactive/components/workflow-view.js +1 -1
  368. package/dist/modes/interactive/components/workflow-view.js.map +1 -1
  369. package/dist/modes/interactive/interactive-auth.d.ts +1 -1
  370. package/dist/modes/interactive/interactive-auth.d.ts.map +1 -1
  371. package/dist/modes/interactive/interactive-auth.js +1 -1
  372. package/dist/modes/interactive/interactive-auth.js.map +1 -1
  373. package/dist/modes/interactive/interactive-commands.d.ts +125 -6
  374. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  375. package/dist/modes/interactive/interactive-commands.js +698 -4
  376. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  377. package/dist/modes/interactive/interactive-events.d.ts +174 -0
  378. package/dist/modes/interactive/interactive-events.d.ts.map +1 -0
  379. package/dist/modes/interactive/interactive-events.js +704 -0
  380. package/dist/modes/interactive/interactive-events.js.map +1 -0
  381. package/dist/modes/interactive/interactive-format.d.ts.map +1 -1
  382. package/dist/modes/interactive/interactive-format.js +1 -1
  383. package/dist/modes/interactive/interactive-format.js.map +1 -1
  384. package/dist/modes/interactive/interactive-lifecycle.d.ts +94 -0
  385. package/dist/modes/interactive/interactive-lifecycle.d.ts.map +1 -0
  386. package/dist/modes/interactive/interactive-lifecycle.js +177 -0
  387. package/dist/modes/interactive/interactive-lifecycle.js.map +1 -0
  388. package/dist/modes/interactive/interactive-mode.d.ts +254 -129
  389. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  390. package/dist/modes/interactive/interactive-mode.js +275 -2101
  391. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  392. package/dist/modes/interactive/interactive-queues.d.ts +96 -0
  393. package/dist/modes/interactive/interactive-queues.d.ts.map +1 -0
  394. package/dist/modes/interactive/interactive-queues.js +183 -0
  395. package/dist/modes/interactive/interactive-queues.js.map +1 -0
  396. package/dist/modes/interactive/interactive-selectors.d.ts +95 -5
  397. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  398. package/dist/modes/interactive/interactive-selectors.js +517 -6
  399. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  400. package/dist/modes/interactive/startup-services.d.ts +31 -0
  401. package/dist/modes/interactive/startup-services.d.ts.map +1 -0
  402. package/dist/modes/interactive/startup-services.js +123 -0
  403. package/dist/modes/interactive/startup-services.js.map +1 -0
  404. package/dist/modes/memory-preheat.d.ts +11 -0
  405. package/dist/modes/memory-preheat.d.ts.map +1 -0
  406. package/dist/modes/memory-preheat.js +20 -0
  407. package/dist/modes/memory-preheat.js.map +1 -0
  408. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  409. package/dist/modes/rpc/rpc-mode.js +3 -1
  410. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  411. package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
  412. package/dist/plugins/ecosystem/cli.js +6 -3
  413. package/dist/plugins/ecosystem/cli.js.map +1 -1
  414. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts +7 -1
  415. package/dist/plugins/ecosystem/node-plugin-bootstrap.d.ts.map +1 -1
  416. package/dist/plugins/ecosystem/node-plugin-bootstrap.js +50 -3
  417. package/dist/plugins/ecosystem/node-plugin-bootstrap.js.map +1 -1
  418. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts +28 -16
  419. package/dist/plugins/ecosystem/plugin-bootstrap.d.ts.map +1 -1
  420. package/dist/plugins/ecosystem/plugin-bootstrap.js +35 -33
  421. package/dist/plugins/ecosystem/plugin-bootstrap.js.map +1 -1
  422. package/dist/profile/plugin-profiles.d.ts +1 -1
  423. package/dist/profile/plugin-profiles.d.ts.map +1 -1
  424. package/dist/profile/plugin-profiles.js +18 -0
  425. package/dist/profile/plugin-profiles.js.map +1 -1
  426. package/dist/remote/server-assembly.d.ts.map +1 -1
  427. package/dist/remote/server-assembly.js +7 -2
  428. package/dist/remote/server-assembly.js.map +1 -1
  429. package/dist/{profiles → suites}/builtin-suites.d.ts +14 -4
  430. package/dist/suites/builtin-suites.d.ts.map +1 -0
  431. package/dist/{profiles → suites}/builtin-suites.js +20 -5
  432. package/dist/suites/builtin-suites.js.map +1 -0
  433. package/dist/suites/resolved-agent-profile.d.ts.map +1 -0
  434. package/dist/suites/resolved-agent-profile.js.map +1 -0
  435. package/dist/suites/suite-lifecycle.d.ts.map +1 -0
  436. package/dist/suites/suite-lifecycle.js.map +1 -0
  437. package/dist/suites/suite-loader.d.ts.map +1 -0
  438. package/dist/suites/suite-loader.js.map +1 -0
  439. package/dist/{modes/interactive/theme → theme}/dark.json +1 -1
  440. package/dist/{modes/interactive/theme → theme}/light.json +1 -1
  441. package/dist/{modes/interactive/theme → theme}/theme-controller.d.ts +1 -1
  442. package/dist/theme/theme-controller.d.ts.map +1 -0
  443. package/dist/{modes/interactive/theme → theme}/theme-controller.js +1 -1
  444. package/dist/theme/theme-controller.js.map +1 -0
  445. package/dist/{modes/interactive/theme → theme}/theme.d.ts +1 -1
  446. package/dist/theme/theme.d.ts.map +1 -0
  447. package/dist/{modes/interactive/theme → theme}/theme.js +5 -5
  448. package/dist/theme/theme.js.map +1 -0
  449. package/docs/compaction.md +7 -7
  450. package/docs/environment-variables.md +10 -4
  451. package/docs/keybindings.md +3 -3
  452. package/docs/models.md +17 -17
  453. package/docs/packages.md +1 -1
  454. package/docs/prompt-templates.md +1 -1
  455. package/docs/rpc.md +2 -2
  456. package/docs/sdk.md +5 -5
  457. package/docs/session-format.md +3 -3
  458. package/docs/settings.md +368 -354
  459. package/docs/shell-aliases.md +1 -1
  460. package/docs/skills.md +1 -1
  461. package/docs/terminal-setup.md +17 -17
  462. package/docs/themes.md +5 -5
  463. package/docs/tmux.md +4 -4
  464. package/docs/tui.md +1 -1
  465. package/docs/windows.md +1 -1
  466. package/examples/extensions/bash-spawn-hook/index.ts +1 -1
  467. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  468. package/examples/extensions/with-deps/package-lock.json +2 -2
  469. package/examples/extensions/with-deps/package.json +1 -6
  470. package/examples/extensions/with-deps/plugin.json +1 -1
  471. package/package.json +2 -2
  472. package/dist/bundle/chunks/openai-responses-AUJQ3NWT.js +0 -2
  473. package/dist/bundle/chunks/virtual-modules-WF6WRHP7.js +0 -5
  474. package/dist/cli/experimental/commands/pi.d.ts +0 -15
  475. package/dist/cli/experimental/commands/pi.d.ts.map +0 -1
  476. package/dist/cli/experimental/commands/pi.js.map +0 -1
  477. package/dist/core/export-html/ansi-to-html.d.ts.map +0 -1
  478. package/dist/core/export-html/ansi-to-html.js.map +0 -1
  479. package/dist/core/export-html/index.d.ts.map +0 -1
  480. package/dist/core/export-html/index.js.map +0 -1
  481. package/dist/core/export-html/tool-renderer.d.ts.map +0 -1
  482. package/dist/core/export-html/tool-renderer.js.map +0 -1
  483. package/dist/core/pi-manifest.d.ts +0 -7
  484. package/dist/core/pi-manifest.d.ts.map +0 -1
  485. package/dist/core/pi-manifest.js.map +0 -1
  486. package/dist/modes/interactive/model-catalog-refresh.d.ts.map +0 -1
  487. package/dist/modes/interactive/model-catalog-refresh.js.map +0 -1
  488. package/dist/modes/interactive/theme/theme-controller.d.ts.map +0 -1
  489. package/dist/modes/interactive/theme/theme-controller.js.map +0 -1
  490. package/dist/modes/interactive/theme/theme.d.ts.map +0 -1
  491. package/dist/modes/interactive/theme/theme.js.map +0 -1
  492. package/dist/profiles/builtin-suites.d.ts.map +0 -1
  493. package/dist/profiles/builtin-suites.js.map +0 -1
  494. package/dist/profiles/resolved-agent-profile.d.ts.map +0 -1
  495. package/dist/profiles/resolved-agent-profile.js.map +0 -1
  496. package/dist/profiles/suite-lifecycle.d.ts.map +0 -1
  497. package/dist/profiles/suite-lifecycle.js.map +0 -1
  498. package/dist/profiles/suite-loader.d.ts.map +0 -1
  499. package/dist/profiles/suite-loader.js.map +0 -1
  500. package/dist/utils/deprecation.d.ts +0 -4
  501. package/dist/utils/deprecation.d.ts.map +0 -1
  502. package/dist/utils/deprecation.js +0 -13
  503. package/dist/utils/deprecation.js.map +0 -1
  504. /package/dist/{core/export-html → export-html}/ansi-to-html.d.ts +0 -0
  505. /package/dist/{core/export-html → export-html}/ansi-to-html.js +0 -0
  506. /package/dist/{core/export-html → export-html}/template.css +0 -0
  507. /package/dist/{core/export-html → export-html}/template.html +0 -0
  508. /package/dist/{core/export-html → export-html}/template.js +0 -0
  509. /package/dist/{core/export-html → export-html}/tool-renderer.js +0 -0
  510. /package/dist/{core/export-html → export-html}/vendor/highlight.min.js +0 -0
  511. /package/dist/{core/export-html → export-html}/vendor/marked.min.js +0 -0
  512. /package/dist/{profiles → suites}/resolved-agent-profile.d.ts +0 -0
  513. /package/dist/{profiles → suites}/resolved-agent-profile.js +0 -0
  514. /package/dist/{profiles → suites}/suite-lifecycle.d.ts +0 -0
  515. /package/dist/{profiles → suites}/suite-lifecycle.js +0 -0
  516. /package/dist/{profiles → suites}/suite-loader.d.ts +0 -0
  517. /package/dist/{profiles → suites}/suite-loader.js +0 -0
  518. /package/dist/{modes/interactive/theme → theme}/theme-schema.json +0 -0
@@ -0,0 +1,15 @@
1
+ /**
2
+ * 会话清理命令域词典:`core/session-cleanup.ts` 中 `t()` 调用点的英文原文 →
3
+ * zh-CN 译文。占位符 `{name}` 原样保留(coverage-i18n 测试校验 key 与译文
4
+ * 占位符集合一致);命令名(/clean-sessions)与大小单位(MB)不译。
5
+ */
6
+ export const sessionCleanup = {
7
+ "Usage: /clean-sessions [days] - days must be a positive integer (default 7)": "用法:/clean-sessions [days] - days 必须为正整数(默认 7)",
8
+ "No sessions untouched for {days} days - nothing to clean": "没有连续 {days} 天无变动的会话 - 无可清理",
9
+ "{count} sessions ({size}) untouched since {cutoff} - confirm to delete": "{count} 个会话({size})自 {cutoff} 起无变动 - 确认后删除",
10
+ "Clean old sessions": "清理旧会话",
11
+ "Permanently delete {count} sessions ({size}) untouched for {days} days? This cannot be undone.": "永久删除 {count} 个连续 {days} 天无变动的会话({size})?此操作不可撤销。",
12
+ "Clean-sessions cancelled": "已取消会话清理",
13
+ "Deleted {count} sessions, freed {size}": "已删除 {count} 个会话,释放 {size}",
14
+ };
15
+ //# sourceMappingURL=session-cleanup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"session-cleanup.js","sourceRoot":"","sources":["../../../../../src/core/i18n/locales/zh-cn/session-cleanup.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAA2B;IACrD,6EAA6E,EAC5E,yEAA+C;IAChD,0DAA0D,EAAE,0DAA4B;IACxF,wEAAwE,EACvE,0EAA4C;IAC7C,oBAAoB,EAAE,iBAAO;IAC7B,gGAAgG,EAC/F,oGAAkD;IACnD,0BAA0B,EAAE,uBAAS;IACrC,wCAAwC,EAAE,6CAA2B;CACrE,CAAC","sourcesContent":["/**\n * 会话清理命令域词典:`core/session-cleanup.ts` 中 `t()` 调用点的英文原文 →\n * zh-CN 译文。占位符 `{name}` 原样保留(coverage-i18n 测试校验 key 与译文\n * 占位符集合一致);命令名(/clean-sessions)与大小单位(MB)不译。\n */\nexport const sessionCleanup: Record<string, string> = {\n\t\"Usage: /clean-sessions [days] - days must be a positive integer (default 7)\":\n\t\t\"用法:/clean-sessions [days] - days 必须为正整数(默认 7)\",\n\t\"No sessions untouched for {days} days - nothing to clean\": \"没有连续 {days} 天无变动的会话 - 无可清理\",\n\t\"{count} sessions ({size}) untouched since {cutoff} - confirm to delete\":\n\t\t\"{count} 个会话({size})自 {cutoff} 起无变动 - 确认后删除\",\n\t\"Clean old sessions\": \"清理旧会话\",\n\t\"Permanently delete {count} sessions ({size}) untouched for {days} days? This cannot be undone.\":\n\t\t\"永久删除 {count} 个连续 {days} 天无变动的会话({size})?此操作不可撤销。\",\n\t\"Clean-sessions cancelled\": \"已取消会话清理\",\n\t\"Deleted {count} sessions, freed {size}\": \"已删除 {count} 个会话,释放 {size}\",\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"slash-commands.d.ts","sourceRoot":"","sources":["../../../../../src/core/i18n/locales/zh-cn/slash-commands.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAmChD,CAAC","sourcesContent":["/**\n * slash 命令域词典:`core/slash-commands.ts` 中 BUILTIN_SLASH_COMMANDS 的\n * description 文案;argumentHint(`<provider/model>`、`[id]` 等)为纯语法\n * 占位形状,zh-CN 保持原形回退,不设词条。\n */\nexport const slashCommands: Record<string, string> = {\n\t\"Open settings menu\": \"打开设置菜单\",\n\t\"Select model (opens selector UI)\": \"选择模型(打开选择器界面)\",\n\t\"Navigate session tree (switch branches)\": \"浏览会话树(切换分支)\",\n\t\"Set thinking level\": \"设置思考等级\",\n\t\"Set the active suite (takes effect in new sessions)\": \"设置当前 suite(对新会话生效)\",\n\t\"Enable/disable models in the /model cycling scope\": \"启用/禁用 /model 轮换范围内的模型\",\n\t\"Export session (HTML default, or specify path: .html/.jsonl)\": \"导出会话(默认 HTML,或指定路径:.html/.jsonl)\",\n\t\"Import and resume a session from a JSONL file\": \"从 JSONL 文件导入并恢复会话\",\n\t\"Copy last agent message to clipboard\": \"复制上一条 agent 消息到剪贴板\",\n\t\"Set session display name\": \"设置会话显示名称\",\n\t\"Show session info and stats\": \"显示会话信息与统计\",\n\t\"Show product metrics (turns, tools, memory recall)\": \"显示产品指标(轮次、工具、记忆召回)\",\n\t\"Show changelog entries\": \"显示更新日志条目\",\n\t\"Show available commands\": \"显示可用命令\",\n\t\"Show all keyboard shortcuts\": \"显示全部键盘快捷键\",\n\t\"Return to any earlier prompt and continue from there (the original path stays as a branch)\":\n\t\t\"回到任意较早的提示词并从该处继续(原路径保留为分支)\",\n\t\"Duplicate the current session at the current position\": \"在当前位置复制当前会话\",\n\t\"Configure provider authentication\": \"配置 provider 认证\",\n\t\"Remove provider authentication\": \"移除 provider 认证\",\n\t\"Start a new session\": \"开始新会话\",\n\t\"Terminate all background subagents (Esc never touches them)\": \"终止所有后台子代理(Esc 不会触及它们)\",\n\t\"Manually compact the session context\": \"手动压缩会话上下文\",\n\t\"Resume a different session\": \"恢复另一个会话\",\n\t\"Queue a message for after the current run\": \"为当前运行结束后排队一条消息\",\n\t\"Restore queued messages back to the editor\": \"将排队的消息恢复到编辑器\",\n\t\"Open the queued messages manager\": \"打开排队消息管理器\",\n\t\"Edit the current input in an external editor\": \"在外部编辑器中编辑当前输入\",\n\t\"Browse this session's subagent sessions (read-only)\": \"浏览本会话的子代理会话(只读)\",\n\t\"Reload keybindings, extensions, skills, prompts, themes, and context files\":\n\t\t\"重新加载键位绑定、扩展、skill、提示模板、主题与上下文文件\",\n\t\"Promote a memory preference to user-default (visible in every suite)\":\n\t\t\"将一条记忆偏好提升为用户默认(在每个 suite 可见)\",\n\t\"Quit {app}\": \"退出 {app}\",\n};\n"]}
1
+ {"version":3,"file":"slash-commands.d.ts","sourceRoot":"","sources":["../../../../../src/core/i18n/locales/zh-cn/slash-commands.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,eAAO,MAAM,aAAa,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAoChD,CAAC","sourcesContent":["/**\n * slash 命令域词典:`core/slash-commands.ts` 中 BUILTIN_SLASH_COMMANDS 的\n * description 文案;argumentHint(`<provider/model>`、`[id]` 等)为纯语法\n * 占位形状,zh-CN 保持原形回退,不设词条。\n */\nexport const slashCommands: Record<string, string> = {\n\t\"Open settings menu\": \"打开设置菜单\",\n\t\"Select model (opens selector UI)\": \"选择模型(打开选择器界面)\",\n\t\"Navigate session tree (switch branches)\": \"浏览会话树(切换分支)\",\n\t\"Set thinking level\": \"设置思考等级\",\n\t\"Set the active suite (takes effect in new sessions)\": \"设置当前 suite(对新会话生效)\",\n\t\"Enable/disable models in the /model cycling scope\": \"启用/禁用 /model 轮换范围内的模型\",\n\t\"Export session (HTML default, or specify path: .html/.jsonl)\": \"导出会话(默认 HTML,或指定路径:.html/.jsonl)\",\n\t\"Import and resume a session from a JSONL file\": \"从 JSONL 文件导入并恢复会话\",\n\t\"Copy last agent message to clipboard\": \"复制上一条 agent 消息到剪贴板\",\n\t\"Set session display name\": \"设置会话显示名称\",\n\t\"Show session info and stats\": \"显示会话信息与统计\",\n\t\"Show product metrics (turns, tools, memory recall)\": \"显示产品指标(轮次、工具、记忆召回)\",\n\t\"Show changelog entries\": \"显示更新日志条目\",\n\t\"Show available commands\": \"显示可用命令\",\n\t\"Show all keyboard shortcuts\": \"显示全部键盘快捷键\",\n\t\"Return to any earlier prompt and continue from there (the original path stays as a branch)\":\n\t\t\"回到任意较早的提示词并从该处继续(原路径保留为分支)\",\n\t\"Duplicate the current session at the current position\": \"在当前位置复制当前会话\",\n\t\"Configure provider authentication\": \"配置 provider 认证\",\n\t\"Remove provider authentication\": \"移除 provider 认证\",\n\t\"Start a new session\": \"开始新会话\",\n\t\"Terminate all background subagents (Esc never touches them)\": \"终止所有后台子代理(Esc 不会触及它们)\",\n\t\"Manually compact the session context\": \"手动压缩会话上下文\",\n\t\"Resume a different session\": \"恢复另一个会话\",\n\t\"Delete session files untouched for N days to free disk space\": \"删除超过 N 天无变动的会话文件以释放磁盘空间\",\n\t\"Queue a message for after the current run\": \"为当前运行结束后排队一条消息\",\n\t\"Restore queued messages back to the editor\": \"将排队的消息恢复到编辑器\",\n\t\"Open the queued messages manager\": \"打开排队消息管理器\",\n\t\"Edit the current input in an external editor\": \"在外部编辑器中编辑当前输入\",\n\t\"Browse this session's subagent sessions (read-only)\": \"浏览本会话的子代理会话(只读)\",\n\t\"Reload keybindings, extensions, skills, prompts, themes, and context files\":\n\t\t\"重新加载键位绑定、扩展、skill、提示模板、主题与上下文文件\",\n\t\"Promote a memory preference to user-default (visible in every suite)\":\n\t\t\"将一条记忆偏好提升为用户默认(在每个 suite 可见)\",\n\t\"Quit {app}\": \"退出 {app}\",\n};\n"]}
@@ -27,6 +27,7 @@ export const slashCommands = {
27
27
  "Terminate all background subagents (Esc never touches them)": "终止所有后台子代理(Esc 不会触及它们)",
28
28
  "Manually compact the session context": "手动压缩会话上下文",
29
29
  "Resume a different session": "恢复另一个会话",
30
+ "Delete session files untouched for N days to free disk space": "删除超过 N 天无变动的会话文件以释放磁盘空间",
30
31
  "Queue a message for after the current run": "为当前运行结束后排队一条消息",
31
32
  "Restore queued messages back to the editor": "将排队的消息恢复到编辑器",
32
33
  "Open the queued messages manager": "打开排队消息管理器",
@@ -1 +1 @@
1
- {"version":3,"file":"slash-commands.js","sourceRoot":"","sources":["../../../../../src/core/i18n/locales/zh-cn/slash-commands.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAA2B;IACpD,oBAAoB,EAAE,oBAAQ;IAC9B,kCAAkC,EAAE,yCAAe;IACnD,yCAAyC,EAAE,mCAAa;IACxD,oBAAoB,EAAE,oBAAQ;IAC9B,qDAAqD,EAAE,4CAAoB;IAC3E,mDAAmD,EAAE,+CAAuB;IAC5E,8DAA8D,EAAE,gEAAkC;IAClG,+CAA+C,EAAE,uCAAmB;IACpE,sCAAsC,EAAE,0CAAoB;IAC5D,0BAA0B,EAAE,0BAAU;IACtC,6BAA6B,EAAE,6BAAW;IAC1C,oDAAoD,EAAE,wDAAoB;IAC1E,wBAAwB,EAAE,0BAAU;IACpC,yBAAyB,EAAE,oBAAQ;IACnC,6BAA6B,EAAE,6BAAW;IAC1C,4FAA4F,EAC3F,gFAA4B;IAC7B,uDAAuD,EAAE,mCAAa;IACtE,mCAAmC,EAAE,wBAAgB;IACrD,gCAAgC,EAAE,wBAAgB;IAClD,qBAAqB,EAAE,iBAAO;IAC9B,6DAA6D,EAAE,yDAAuB;IACtF,sCAAsC,EAAE,6BAAW;IACnD,4BAA4B,EAAE,uBAAS;IACvC,2CAA2C,EAAE,4CAAgB;IAC7D,4CAA4C,EAAE,sCAAc;IAC5D,kCAAkC,EAAE,6BAAW;IAC/C,8CAA8C,EAAE,yCAAe;IAC/D,qDAAqD,EAAE,+CAAiB;IACxE,4EAA4E,EAC3E,qFAAiC;IAClC,sEAAsE,EACrE,wEAA8B;IAC/B,YAAY,EAAE,cAAU;CACxB,CAAC","sourcesContent":["/**\n * slash 命令域词典:`core/slash-commands.ts` 中 BUILTIN_SLASH_COMMANDS 的\n * description 文案;argumentHint(`<provider/model>`、`[id]` 等)为纯语法\n * 占位形状,zh-CN 保持原形回退,不设词条。\n */\nexport const slashCommands: Record<string, string> = {\n\t\"Open settings menu\": \"打开设置菜单\",\n\t\"Select model (opens selector UI)\": \"选择模型(打开选择器界面)\",\n\t\"Navigate session tree (switch branches)\": \"浏览会话树(切换分支)\",\n\t\"Set thinking level\": \"设置思考等级\",\n\t\"Set the active suite (takes effect in new sessions)\": \"设置当前 suite(对新会话生效)\",\n\t\"Enable/disable models in the /model cycling scope\": \"启用/禁用 /model 轮换范围内的模型\",\n\t\"Export session (HTML default, or specify path: .html/.jsonl)\": \"导出会话(默认 HTML,或指定路径:.html/.jsonl)\",\n\t\"Import and resume a session from a JSONL file\": \"从 JSONL 文件导入并恢复会话\",\n\t\"Copy last agent message to clipboard\": \"复制上一条 agent 消息到剪贴板\",\n\t\"Set session display name\": \"设置会话显示名称\",\n\t\"Show session info and stats\": \"显示会话信息与统计\",\n\t\"Show product metrics (turns, tools, memory recall)\": \"显示产品指标(轮次、工具、记忆召回)\",\n\t\"Show changelog entries\": \"显示更新日志条目\",\n\t\"Show available commands\": \"显示可用命令\",\n\t\"Show all keyboard shortcuts\": \"显示全部键盘快捷键\",\n\t\"Return to any earlier prompt and continue from there (the original path stays as a branch)\":\n\t\t\"回到任意较早的提示词并从该处继续(原路径保留为分支)\",\n\t\"Duplicate the current session at the current position\": \"在当前位置复制当前会话\",\n\t\"Configure provider authentication\": \"配置 provider 认证\",\n\t\"Remove provider authentication\": \"移除 provider 认证\",\n\t\"Start a new session\": \"开始新会话\",\n\t\"Terminate all background subagents (Esc never touches them)\": \"终止所有后台子代理(Esc 不会触及它们)\",\n\t\"Manually compact the session context\": \"手动压缩会话上下文\",\n\t\"Resume a different session\": \"恢复另一个会话\",\n\t\"Queue a message for after the current run\": \"为当前运行结束后排队一条消息\",\n\t\"Restore queued messages back to the editor\": \"将排队的消息恢复到编辑器\",\n\t\"Open the queued messages manager\": \"打开排队消息管理器\",\n\t\"Edit the current input in an external editor\": \"在外部编辑器中编辑当前输入\",\n\t\"Browse this session's subagent sessions (read-only)\": \"浏览本会话的子代理会话(只读)\",\n\t\"Reload keybindings, extensions, skills, prompts, themes, and context files\":\n\t\t\"重新加载键位绑定、扩展、skill、提示模板、主题与上下文文件\",\n\t\"Promote a memory preference to user-default (visible in every suite)\":\n\t\t\"将一条记忆偏好提升为用户默认(在每个 suite 可见)\",\n\t\"Quit {app}\": \"退出 {app}\",\n};\n"]}
1
+ {"version":3,"file":"slash-commands.js","sourceRoot":"","sources":["../../../../../src/core/i18n/locales/zh-cn/slash-commands.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAA2B;IACpD,oBAAoB,EAAE,oBAAQ;IAC9B,kCAAkC,EAAE,yCAAe;IACnD,yCAAyC,EAAE,mCAAa;IACxD,oBAAoB,EAAE,oBAAQ;IAC9B,qDAAqD,EAAE,4CAAoB;IAC3E,mDAAmD,EAAE,+CAAuB;IAC5E,8DAA8D,EAAE,gEAAkC;IAClG,+CAA+C,EAAE,uCAAmB;IACpE,sCAAsC,EAAE,0CAAoB;IAC5D,0BAA0B,EAAE,0BAAU;IACtC,6BAA6B,EAAE,6BAAW;IAC1C,oDAAoD,EAAE,wDAAoB;IAC1E,wBAAwB,EAAE,0BAAU;IACpC,yBAAyB,EAAE,oBAAQ;IACnC,6BAA6B,EAAE,6BAAW;IAC1C,4FAA4F,EAC3F,gFAA4B;IAC7B,uDAAuD,EAAE,mCAAa;IACtE,mCAAmC,EAAE,wBAAgB;IACrD,gCAAgC,EAAE,wBAAgB;IAClD,qBAAqB,EAAE,iBAAO;IAC9B,6DAA6D,EAAE,yDAAuB;IACtF,sCAAsC,EAAE,6BAAW;IACnD,4BAA4B,EAAE,uBAAS;IACvC,8DAA8D,EAAE,iEAAyB;IACzF,2CAA2C,EAAE,4CAAgB;IAC7D,4CAA4C,EAAE,sCAAc;IAC5D,kCAAkC,EAAE,6BAAW;IAC/C,8CAA8C,EAAE,yCAAe;IAC/D,qDAAqD,EAAE,+CAAiB;IACxE,4EAA4E,EAC3E,qFAAiC;IAClC,sEAAsE,EACrE,wEAA8B;IAC/B,YAAY,EAAE,cAAU;CACxB,CAAC","sourcesContent":["/**\n * slash 命令域词典:`core/slash-commands.ts` 中 BUILTIN_SLASH_COMMANDS 的\n * description 文案;argumentHint(`<provider/model>`、`[id]` 等)为纯语法\n * 占位形状,zh-CN 保持原形回退,不设词条。\n */\nexport const slashCommands: Record<string, string> = {\n\t\"Open settings menu\": \"打开设置菜单\",\n\t\"Select model (opens selector UI)\": \"选择模型(打开选择器界面)\",\n\t\"Navigate session tree (switch branches)\": \"浏览会话树(切换分支)\",\n\t\"Set thinking level\": \"设置思考等级\",\n\t\"Set the active suite (takes effect in new sessions)\": \"设置当前 suite(对新会话生效)\",\n\t\"Enable/disable models in the /model cycling scope\": \"启用/禁用 /model 轮换范围内的模型\",\n\t\"Export session (HTML default, or specify path: .html/.jsonl)\": \"导出会话(默认 HTML,或指定路径:.html/.jsonl)\",\n\t\"Import and resume a session from a JSONL file\": \"从 JSONL 文件导入并恢复会话\",\n\t\"Copy last agent message to clipboard\": \"复制上一条 agent 消息到剪贴板\",\n\t\"Set session display name\": \"设置会话显示名称\",\n\t\"Show session info and stats\": \"显示会话信息与统计\",\n\t\"Show product metrics (turns, tools, memory recall)\": \"显示产品指标(轮次、工具、记忆召回)\",\n\t\"Show changelog entries\": \"显示更新日志条目\",\n\t\"Show available commands\": \"显示可用命令\",\n\t\"Show all keyboard shortcuts\": \"显示全部键盘快捷键\",\n\t\"Return to any earlier prompt and continue from there (the original path stays as a branch)\":\n\t\t\"回到任意较早的提示词并从该处继续(原路径保留为分支)\",\n\t\"Duplicate the current session at the current position\": \"在当前位置复制当前会话\",\n\t\"Configure provider authentication\": \"配置 provider 认证\",\n\t\"Remove provider authentication\": \"移除 provider 认证\",\n\t\"Start a new session\": \"开始新会话\",\n\t\"Terminate all background subagents (Esc never touches them)\": \"终止所有后台子代理(Esc 不会触及它们)\",\n\t\"Manually compact the session context\": \"手动压缩会话上下文\",\n\t\"Resume a different session\": \"恢复另一个会话\",\n\t\"Delete session files untouched for N days to free disk space\": \"删除超过 N 天无变动的会话文件以释放磁盘空间\",\n\t\"Queue a message for after the current run\": \"为当前运行结束后排队一条消息\",\n\t\"Restore queued messages back to the editor\": \"将排队的消息恢复到编辑器\",\n\t\"Open the queued messages manager\": \"打开排队消息管理器\",\n\t\"Edit the current input in an external editor\": \"在外部编辑器中编辑当前输入\",\n\t\"Browse this session's subagent sessions (read-only)\": \"浏览本会话的子代理会话(只读)\",\n\t\"Reload keybindings, extensions, skills, prompts, themes, and context files\":\n\t\t\"重新加载键位绑定、扩展、skill、提示模板、主题与上下文文件\",\n\t\"Promote a memory preference to user-default (visible in every suite)\":\n\t\t\"将一条记忆偏好提升为用户默认(在每个 suite 可见)\",\n\t\"Quit {app}\": \"退出 {app}\",\n};\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"tui-components-misc.d.ts","sourceRoot":"","sources":["../../../../../src/core/i18n/locales/zh-cn/tui-components-misc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA0GpD,CAAC","sourcesContent":["/**\n * 批次④ misc 域词典(docs/design/国际化与本地化.md §词典结构):\n * 覆盖 components/ 下的 footer、status-indicator、bash-execution、\n * assistant-message、user-message-selector、tree-render、branch-summary、\n * compaction-summary、skill-invocation、show-images、dialog-editor、dialog-input、\n * dialog-selector、mermaid、custom-entry、custom-message、tool-execution、\n * theme-selector、bordered-loader、settings-submenu。key 为英文原文(与调用点\n * 逐字一致;`t()` 会 trim key,调用点的前导/尾随空白在 `t()` 外拼接),\n * value 为简体中文译文,`{占位符}` 原样保留。数据值与纯格式(token 缩写、\n * 计数、时间戳)不入词典;skill 等术语保留原文(回退 key)。\n */\nexport const tuiComponentsMisc: Record<string, string> = {\n\t// ---- footer ----\n\t\"(sub)\": \"(订阅)\",\n\t\"(auto)\": \"(自动)\",\n\t\"no-model\": \"无模型\",\n\t\"{model} • thinking off\": \"{model} • 思考关闭\",\n\n\t// ---- status-indicator ----\n\t\"Retrying ({attempt}/{max}) in {seconds}s... ({key} to cancel)\":\n\t\t\"第 {attempt}/{max} 次重试,{seconds} 秒后...({key} 取消)\",\n\t\"Compacting context... ({key} to cancel)\": \"正在压缩上下文...({key} 取消)\",\n\t\"Context overflow detected, Auto-compacting... ({key} to cancel)\": \"检测到上下文溢出,自动压缩中...({key} 取消)\",\n\t\"Auto-compacting... ({key} to cancel)\": \"自动压缩中...({key} 取消)\",\n\t\"Summarizing branch... ({key} to cancel)\": \"正在生成分支摘要...({key} 取消)\",\n\n\t// ---- bash-execution ----\n\t\"Running... ({key} to cancel)\": \"运行中...({key} 取消)\",\n\t\"({key} to collapse)\": \"({key} 折叠)\",\n\t\"... {count} more lines ({key} to expand)\": \"... 还有 {count} 行({key} 展开)\",\n\t\"(cancelled)\": \"(已取消)\",\n\t\"(exit {code})\": \"(退出码 {code})\",\n\t\"Output truncated. Full output: {path}\": \"输出已截断。完整输出:{path}\",\n\n\t// ---- assistant-message ----\n\t\"Thinking...\": \"思考中...\",\n\t\"Response was truncated before completion.\": \"响应在完成前被截断。\",\n\t\"Operation aborted\": \"操作已中止\",\n\t\"Error: {message}\": \"错误:{message}\",\n\n\t// ---- user-message-selector ----\n\t\"No user messages found\": \"未找到用户消息\",\n\t\"Message {position} of {total}\": \"第 {position} 条,共 {total} 条\",\n\t\"Fork from Message\": \"从消息分叉\",\n\t\"Select a user message to copy the active path up to that point into a new session\":\n\t\t\"选择一条用户消息,将截至该点的当前路径复制到新会话\",\n\n\t// ---- queue-manager-selector(/queue-list 管理器)----\n\t\"Queued Messages\": \"排队消息\",\n\tSteering: \"转向\",\n\t\"Follow-up\": \"后续\",\n\t\"alt+up/alt+down move · delete remove · enter restore · esc close\":\n\t\t\"alt+up/alt+down 移动 · delete 移除 · enter 取回编辑器 · esc 关闭\",\n\n\t// ---- tree-render(/tree 高密度行,译文极短)----\n\t\"user:\": \"用户:\",\n\t\"assistant:\": \"助手:\",\n\t\"(aborted)\": \"(已中止)\",\n\t\"(no content)\": \"(无内容)\",\n\ttool: \"工具\",\n\t\"[bash]: {command}\": \"[bash]: {command}\",\n\t\"[compaction: {tokens}k tokens]\": \"[压缩: {tokens}k tokens]\",\n\t\"[branch summary]:\": \"[分支摘要]:\",\n\t\"[model: {model}]\": \"[模型: {model}]\",\n\t\"[thinking: {level}]\": \"[思考: {level}]\",\n\t\"[custom: {type}]\": \"[自定义: {type}]\",\n\t\"[label: {label}]\": \"[标签: {label}]\",\n\t\"(cleared)\": \"(已清除)\",\n\t\"[title: {name}]\": \"[标题: {name}]\",\n\tempty: \"空\",\n\t\"[read: {display}]\": \"[读取: {display}]\",\n\t\"[write: {path}]\": \"[写入: {path}]\",\n\t\"[edit: {path}]\": \"[编辑: {path}]\",\n\t\"[bash: {cmd}]\": \"[bash: {cmd}]\",\n\t\"[grep: /{pattern}/ in {path}]\": \"[搜索: /{pattern}/ 于 {path}]\",\n\t\"[find: {pattern} in {path}]\": \"[查找: {pattern} 于 {path}]\",\n\t\"[ls: {path}]\": \"[列目录: {path}]\",\n\t\"[{name}: {args}]\": \"[{name}: {args}]\",\n\n\t// ---- branch-summary / compaction-summary / skill-invocation ----\n\t\"[branch]\": \"[分支]\",\n\t\"**Branch Summary**\": \"**分支摘要**\",\n\t\"Branch summary ({key} to expand)\": \"分支摘要({key} 展开)\",\n\t\"[compaction]\": \"[压缩]\",\n\t\"**Compacted from {tokens} tokens**\": \"**已从 {tokens} tokens 压缩**\",\n\t\"Compacted from {tokens} tokens ({key} to expand)\": \"已从 {tokens} tokens 压缩({key} 展开)\",\n\t\"({key} to expand)\": \"({key} 展开)\",\n\n\t// ---- show-images-selector ----\n\tYes: \"是\",\n\tNo: \"否\",\n\t\"Show images inline in terminal\": \"在终端内联显示图片\",\n\t\"Show text placeholder instead\": \"改为显示文本占位符\",\n\n\t// ---- dialog-editor / dialog-input / dialog-selector / bordered-loader ----\n\tsubmit: \"提交\",\n\tnewline: \"换行\",\n\t\"external editor\": \"外部编辑器\",\n\tselect: \"选择\",\n\n\t// ---- mermaid ----\n\t\"Mermaid diagram not rendered: {warning}{suffix}\": \"Mermaid 图表未渲染:{warning}{suffix}\",\n\t\"+{count} more\": \"还有 {count} 条\",\n\n\t// ---- custom-entry ----\n\t\"[{type}] renderer failed: {message}\": \"[{type}] 渲染器失败:{message}\",\n\n\t// ---- tool-execution ----\n\t\"... ({count} more lines, {key} to expand)\": \"...(还有 {count} 行,{key} 展开)\",\n\n\t// ---- theme-selector ----\n\t\"(current)\": \"(当前)\",\n\n\t// ---- settings-submenu ----\n\t\"Type to filter · Enter to select · Esc to go back\": \"输入以过滤 · Enter 选择 · Esc 返回\",\n\t\"Enter to select · Esc to go back\": \"Enter 选择 · Esc 返回\",\n\t\"Step {index}/{total}\": \"第 {index}/{total} 步\",\n};\n"]}
1
+ {"version":3,"file":"tui-components-misc.d.ts","sourceRoot":"","sources":["../../../../../src/core/i18n/locales/zh-cn/tui-components-misc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CA4GpD,CAAC","sourcesContent":["/**\n * 批次④ misc 域词典(docs/design/国际化与本地化.md §词典结构):\n * 覆盖 components/ 下的 footer、status-indicator、bash-execution、\n * assistant-message、user-message-selector、tree-render、branch-summary、\n * compaction-summary、skill-invocation、show-images、dialog-editor、dialog-input、\n * dialog-selector、mermaid、custom-entry、custom-message、tool-execution、\n * theme-selector、bordered-loader、settings-submenu。key 为英文原文(与调用点\n * 逐字一致;`t()` 会 trim key,调用点的前导/尾随空白在 `t()` 外拼接),\n * value 为简体中文译文,`{占位符}` 原样保留。数据值与纯格式(token 缩写、\n * 计数、时间戳)不入词典;skill 等术语保留原文(回退 key)。\n */\nexport const tuiComponentsMisc: Record<string, string> = {\n\t// ---- footer ----\n\t\"(sub)\": \"(订阅)\",\n\t\"(auto)\": \"(自动)\",\n\t\"no-model\": \"无模型\",\n\t\"{model} • thinking off\": \"{model} • 思考关闭\",\n\n\t// ---- status-indicator ----\n\t\"Retrying ({attempt}/{max}) in {seconds}s... ({key} to cancel)\":\n\t\t\"第 {attempt}/{max} 次重试,{seconds} 秒后...({key} 取消)\",\n\t\"Compacting context... ({key} to cancel)\": \"正在压缩上下文...({key} 取消)\",\n\t\"Context overflow detected, Auto-compacting... ({key} to cancel)\": \"检测到上下文溢出,自动压缩中...({key} 取消)\",\n\t\"Auto-compacting... ({key} to cancel)\": \"自动压缩中...({key} 取消)\",\n\t\"Summarizing branch... ({key} to cancel)\": \"正在生成分支摘要...({key} 取消)\",\n\n\t// ---- bash-execution ----\n\t\"Running... ({key} to cancel)\": \"运行中...({key} 取消)\",\n\t\"({key} to collapse)\": \"({key} 折叠)\",\n\t\"... {count} more lines ({key} to expand)\": \"... 还有 {count} 行({key} 展开)\",\n\t\"(cancelled)\": \"(已取消)\",\n\t\"(exit {code})\": \"(退出码 {code})\",\n\t\"Output truncated. Full output: {path}\": \"输出已截断。完整输出:{path}\",\n\n\t// ---- assistant-message ----\n\t\"Thinking...\": \"思考中...\",\n\t\"Response was truncated before completion.\": \"响应在完成前被截断。\",\n\t\"Operation aborted\": \"操作已中止\",\n\t\"Error: {message}\": \"错误:{message}\",\n\n\t// ---- user-message-selector ----\n\t\"No user messages found\": \"未找到用户消息\",\n\t\"Message {position} of {total}\": \"第 {position} 条,共 {total} 条\",\n\t\"Fork from Message\": \"从消息分叉\",\n\t\"Select a user message to copy the active path up to that point into a new session\":\n\t\t\"选择一条用户消息,将截至该点的当前路径复制到新会话\",\n\n\t// ---- queue-manager-selector(/queue-list 管理器)----\n\t\"Queued Messages\": \"排队消息\",\n\tSteering: \"转向\",\n\t\"Follow-up\": \"后续\",\n\t\"alt+up/alt+down move · delete remove · enter restore · esc close\":\n\t\t\"alt+up/alt+down 移动 · delete 移除 · enter 取回编辑器 · esc 关闭\",\n\n\t// ---- tree-render(/tree 高密度行,译文极短)----\n\t\"user:\": \"用户:\",\n\t\"assistant:\": \"助手:\",\n\t\"(aborted)\": \"(已中止)\",\n\t\"(no content)\": \"(无内容)\",\n\ttool: \"工具\",\n\t\"[bash]: {command}\": \"[bash]: {command}\",\n\t\"[compaction: {tokens}k tokens]\": \"[压缩: {tokens}k tokens]\",\n\t\"[branch summary]:\": \"[分支摘要]:\",\n\t\"[model: {model}]\": \"[模型: {model}]\",\n\t\"[thinking: {level}]\": \"[思考: {level}]\",\n\t\"[custom: {type}]\": \"[自定义: {type}]\",\n\t\"[label: {label}]\": \"[标签: {label}]\",\n\t\"(cleared)\": \"(已清除)\",\n\t\"[title: {name}]\": \"[标题: {name}]\",\n\tempty: \"空\",\n\t\"[read: {display}]\": \"[读取: {display}]\",\n\t\"[write: {path}]\": \"[写入: {path}]\",\n\t\"[edit: {path}]\": \"[编辑: {path}]\",\n\t\"[bash: {cmd}]\": \"[bash: {cmd}]\",\n\t\"[grep: /{pattern}/ in {path}]\": \"[搜索: /{pattern}/ 于 {path}]\",\n\t\"[find: {pattern} in {path}]\": \"[查找: {pattern} 于 {path}]\",\n\t\"[ls: {path}]\": \"[列目录: {path}]\",\n\t\"[{name}: {args}]\": \"[{name}: {args}]\",\n\n\t// ---- branch-summary / compaction-summary / skill-invocation ----\n\t\"[branch]\": \"[分支]\",\n\t\"**Branch Summary**\": \"**分支摘要**\",\n\t\"Branch summary ({key} to expand)\": \"分支摘要({key} 展开)\",\n\t\"[compaction]\": \"[压缩]\",\n\t\"**Compacted from {tokens} tokens**\": \"**已从 {tokens} tokens 压缩**\",\n\t\"Compacted from {tokens} tokens ({key} to expand)\": \"已从 {tokens} tokens 压缩({key} 展开)\",\n\t\"({key} to expand)\": \"({key} 展开)\",\n\n\t// ---- show-images-selector ----\n\tYes: \"是\",\n\tNo: \"否\",\n\t\"Show images inline in terminal\": \"在终端内联显示图片\",\n\t\"Show text placeholder instead\": \"改为显示文本占位符\",\n\n\t// ---- dialog-editor / dialog-input / dialog-selector / bordered-loader ----\n\tsubmit: \"提交\",\n\tnewline: \"换行\",\n\t\"external editor\": \"外部编辑器\",\n\tselect: \"选择\",\n\n\t// ---- mermaid ----\n\t\"Mermaid diagram not rendered: {warning}{suffix}\": \"Mermaid 图表未渲染:{warning}{suffix}\",\n\t\"+{count} more\": \"还有 {count} 条\",\n\n\t// ---- custom-entry ----\n\t\"[{type}] renderer failed: {message}\": \"[{type}] 渲染器失败:{message}\",\n\n\t// ---- tool-execution ----\n\t\"... ({count} more lines, {key} to expand)\": \"...(还有 {count} 行,{key} 展开)\",\n\t\"... ({count} lines truncated)\": \"...(已截断 {count} 行)\",\n\t\"... ({count} lines truncated; full output: {path})\": \"...(已截断 {count} 行;完整输出: {path})\",\n\n\t// ---- theme-selector ----\n\t\"(current)\": \"(当前)\",\n\n\t// ---- settings-submenu ----\n\t\"Type to filter · Enter to select · Esc to go back\": \"输入以过滤 · Enter 选择 · Esc 返回\",\n\t\"Enter to select · Esc to go back\": \"Enter 选择 · Esc 返回\",\n\t\"Step {index}/{total}\": \"第 {index}/{total} 步\",\n};\n"]}
@@ -92,6 +92,8 @@ export const tuiComponentsMisc = {
92
92
  "[{type}] renderer failed: {message}": "[{type}] 渲染器失败:{message}",
93
93
  // ---- tool-execution ----
94
94
  "... ({count} more lines, {key} to expand)": "...(还有 {count} 行,{key} 展开)",
95
+ "... ({count} lines truncated)": "...(已截断 {count} 行)",
96
+ "... ({count} lines truncated; full output: {path})": "...(已截断 {count} 行;完整输出: {path})",
95
97
  // ---- theme-selector ----
96
98
  "(current)": "(当前)",
97
99
  // ---- settings-submenu ----
@@ -1 +1 @@
1
- {"version":3,"file":"tui-components-misc.js","sourceRoot":"","sources":["../../../../../src/core/i18n/locales/zh-cn/tui-components-misc.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,iBAAiB,GAA2B;IACxD,mBAAmB;IACnB,OAAO,EAAE,cAAM;IACf,QAAQ,EAAE,cAAM;IAChB,UAAU,EAAE,WAAK;IACjB,0BAAwB,EAAE,0BAAgB;IAE1C,6BAA6B;IAC7B,+DAA+D,EAC9D,uEAAiD;IAClD,yCAAyC,EAAE,4CAAsB;IACjE,iEAAiE,EAAE,iEAA6B;IAChG,sCAAsC,EAAE,sCAAoB;IAC5D,yCAAyC,EAAE,+CAAuB;IAElE,2BAA2B;IAC3B,8BAA8B,EAAE,gCAAkB;IAClD,qBAAqB,EAAE,oBAAY;IACnC,0CAA0C,EAAE,0CAA4B;IACxE,aAAa,EAAE,iBAAO;IACtB,eAAe,EAAE,wBAAc;IAC/B,uCAAuC,EAAE,yCAAmB;IAE5D,8BAA8B;IAC9B,aAAa,EAAE,cAAQ;IACvB,2CAA2C,EAAE,gCAAY;IACzD,mBAAmB,EAAE,iBAAO;IAC5B,kBAAkB,EAAE,oBAAc;IAElC,kCAAkC;IAClC,wBAAwB,EAAE,uBAAS;IACnC,+BAA+B,EAAE,sCAA4B;IAC7D,mBAAmB,EAAE,iBAAO;IAC5B,mFAAmF,EAClF,6EAA2B;IAE5B,6DAAmD;IACnD,iBAAiB,EAAE,cAAM;IACzB,QAAQ,EAAE,QAAI;IACd,WAAW,EAAE,QAAI;IACjB,qEAAkE,EACjE,gFAAuD;IAExD,8DAAwC;IACxC,OAAO,EAAE,SAAK;IACd,YAAY,EAAE,SAAK;IACnB,WAAW,EAAE,iBAAO;IACpB,cAAc,EAAE,iBAAO;IACvB,IAAI,EAAE,QAAI;IACV,mBAAmB,EAAE,mBAAmB;IACxC,gCAAgC,EAAE,4BAAwB;IAC1D,mBAAmB,EAAE,iBAAS;IAC9B,kBAAkB,EAAE,mBAAe;IACnC,qBAAqB,EAAE,mBAAe;IACtC,kBAAkB,EAAE,qBAAe;IACnC,kBAAkB,EAAE,mBAAe;IACnC,WAAW,EAAE,iBAAO;IACpB,iBAAiB,EAAE,kBAAc;IACjC,KAAK,EAAE,KAAG;IACV,mBAAmB,EAAE,qBAAiB;IACtC,iBAAiB,EAAE,kBAAc;IACjC,gBAAgB,EAAE,kBAAc;IAChC,eAAe,EAAE,eAAe;IAChC,+BAA+B,EAAE,kCAA4B;IAC7D,6BAA6B,EAAE,gCAA0B;IACzD,cAAc,EAAE,qBAAe;IAC/B,kBAAkB,EAAE,kBAAkB;IAEtC,mEAAmE;IACnE,UAAU,EAAE,UAAM;IAClB,oBAAoB,EAAE,kBAAU;IAChC,kCAAkC,EAAE,gCAAgB;IACpD,cAAc,EAAE,UAAM;IACtB,oCAAoC,EAAE,mCAA2B;IACjE,kDAAkD,EAAE,iDAAiC;IACrF,mBAAmB,EAAE,oBAAY;IAEjC,iCAAiC;IACjC,GAAG,EAAE,KAAG;IACR,EAAE,EAAE,KAAG;IACP,gCAAgC,EAAE,6BAAW;IAC7C,+BAA+B,EAAE,6BAAW;IAE5C,6EAA6E;IAC7E,MAAM,EAAE,QAAI;IACZ,OAAO,EAAE,QAAI;IACb,iBAAiB,EAAE,iBAAO;IAC1B,MAAM,EAAE,QAAI;IAEZ,oBAAoB;IACpB,iDAAiD,EAAE,6CAAiC;IACpF,eAAe,EAAE,oBAAc;IAE/B,yBAAyB;IACzB,qCAAqC,EAAE,sCAA0B;IAEjE,2BAA2B;IAC3B,2CAA2C,EAAE,4CAA4B;IAEzE,2BAA2B;IAC3B,WAAW,EAAE,cAAM;IAEnB,6BAA6B;IAC7B,qDAAmD,EAAE,+CAA2B;IAChF,mCAAkC,EAAE,4BAAmB;IACvD,sBAAsB,EAAE,yBAAqB;CAC7C,CAAC","sourcesContent":["/**\n * 批次④ misc 域词典(docs/design/国际化与本地化.md §词典结构):\n * 覆盖 components/ 下的 footer、status-indicator、bash-execution、\n * assistant-message、user-message-selector、tree-render、branch-summary、\n * compaction-summary、skill-invocation、show-images、dialog-editor、dialog-input、\n * dialog-selector、mermaid、custom-entry、custom-message、tool-execution、\n * theme-selector、bordered-loader、settings-submenu。key 为英文原文(与调用点\n * 逐字一致;`t()` 会 trim key,调用点的前导/尾随空白在 `t()` 外拼接),\n * value 为简体中文译文,`{占位符}` 原样保留。数据值与纯格式(token 缩写、\n * 计数、时间戳)不入词典;skill 等术语保留原文(回退 key)。\n */\nexport const tuiComponentsMisc: Record<string, string> = {\n\t// ---- footer ----\n\t\"(sub)\": \"(订阅)\",\n\t\"(auto)\": \"(自动)\",\n\t\"no-model\": \"无模型\",\n\t\"{model} • thinking off\": \"{model} • 思考关闭\",\n\n\t// ---- status-indicator ----\n\t\"Retrying ({attempt}/{max}) in {seconds}s... ({key} to cancel)\":\n\t\t\"第 {attempt}/{max} 次重试,{seconds} 秒后...({key} 取消)\",\n\t\"Compacting context... ({key} to cancel)\": \"正在压缩上下文...({key} 取消)\",\n\t\"Context overflow detected, Auto-compacting... ({key} to cancel)\": \"检测到上下文溢出,自动压缩中...({key} 取消)\",\n\t\"Auto-compacting... ({key} to cancel)\": \"自动压缩中...({key} 取消)\",\n\t\"Summarizing branch... ({key} to cancel)\": \"正在生成分支摘要...({key} 取消)\",\n\n\t// ---- bash-execution ----\n\t\"Running... ({key} to cancel)\": \"运行中...({key} 取消)\",\n\t\"({key} to collapse)\": \"({key} 折叠)\",\n\t\"... {count} more lines ({key} to expand)\": \"... 还有 {count} 行({key} 展开)\",\n\t\"(cancelled)\": \"(已取消)\",\n\t\"(exit {code})\": \"(退出码 {code})\",\n\t\"Output truncated. Full output: {path}\": \"输出已截断。完整输出:{path}\",\n\n\t// ---- assistant-message ----\n\t\"Thinking...\": \"思考中...\",\n\t\"Response was truncated before completion.\": \"响应在完成前被截断。\",\n\t\"Operation aborted\": \"操作已中止\",\n\t\"Error: {message}\": \"错误:{message}\",\n\n\t// ---- user-message-selector ----\n\t\"No user messages found\": \"未找到用户消息\",\n\t\"Message {position} of {total}\": \"第 {position} 条,共 {total} 条\",\n\t\"Fork from Message\": \"从消息分叉\",\n\t\"Select a user message to copy the active path up to that point into a new session\":\n\t\t\"选择一条用户消息,将截至该点的当前路径复制到新会话\",\n\n\t// ---- queue-manager-selector(/queue-list 管理器)----\n\t\"Queued Messages\": \"排队消息\",\n\tSteering: \"转向\",\n\t\"Follow-up\": \"后续\",\n\t\"alt+up/alt+down move · delete remove · enter restore · esc close\":\n\t\t\"alt+up/alt+down 移动 · delete 移除 · enter 取回编辑器 · esc 关闭\",\n\n\t// ---- tree-render(/tree 高密度行,译文极短)----\n\t\"user:\": \"用户:\",\n\t\"assistant:\": \"助手:\",\n\t\"(aborted)\": \"(已中止)\",\n\t\"(no content)\": \"(无内容)\",\n\ttool: \"工具\",\n\t\"[bash]: {command}\": \"[bash]: {command}\",\n\t\"[compaction: {tokens}k tokens]\": \"[压缩: {tokens}k tokens]\",\n\t\"[branch summary]:\": \"[分支摘要]:\",\n\t\"[model: {model}]\": \"[模型: {model}]\",\n\t\"[thinking: {level}]\": \"[思考: {level}]\",\n\t\"[custom: {type}]\": \"[自定义: {type}]\",\n\t\"[label: {label}]\": \"[标签: {label}]\",\n\t\"(cleared)\": \"(已清除)\",\n\t\"[title: {name}]\": \"[标题: {name}]\",\n\tempty: \"空\",\n\t\"[read: {display}]\": \"[读取: {display}]\",\n\t\"[write: {path}]\": \"[写入: {path}]\",\n\t\"[edit: {path}]\": \"[编辑: {path}]\",\n\t\"[bash: {cmd}]\": \"[bash: {cmd}]\",\n\t\"[grep: /{pattern}/ in {path}]\": \"[搜索: /{pattern}/ 于 {path}]\",\n\t\"[find: {pattern} in {path}]\": \"[查找: {pattern} 于 {path}]\",\n\t\"[ls: {path}]\": \"[列目录: {path}]\",\n\t\"[{name}: {args}]\": \"[{name}: {args}]\",\n\n\t// ---- branch-summary / compaction-summary / skill-invocation ----\n\t\"[branch]\": \"[分支]\",\n\t\"**Branch Summary**\": \"**分支摘要**\",\n\t\"Branch summary ({key} to expand)\": \"分支摘要({key} 展开)\",\n\t\"[compaction]\": \"[压缩]\",\n\t\"**Compacted from {tokens} tokens**\": \"**已从 {tokens} tokens 压缩**\",\n\t\"Compacted from {tokens} tokens ({key} to expand)\": \"已从 {tokens} tokens 压缩({key} 展开)\",\n\t\"({key} to expand)\": \"({key} 展开)\",\n\n\t// ---- show-images-selector ----\n\tYes: \"是\",\n\tNo: \"否\",\n\t\"Show images inline in terminal\": \"在终端内联显示图片\",\n\t\"Show text placeholder instead\": \"改为显示文本占位符\",\n\n\t// ---- dialog-editor / dialog-input / dialog-selector / bordered-loader ----\n\tsubmit: \"提交\",\n\tnewline: \"换行\",\n\t\"external editor\": \"外部编辑器\",\n\tselect: \"选择\",\n\n\t// ---- mermaid ----\n\t\"Mermaid diagram not rendered: {warning}{suffix}\": \"Mermaid 图表未渲染:{warning}{suffix}\",\n\t\"+{count} more\": \"还有 {count} 条\",\n\n\t// ---- custom-entry ----\n\t\"[{type}] renderer failed: {message}\": \"[{type}] 渲染器失败:{message}\",\n\n\t// ---- tool-execution ----\n\t\"... ({count} more lines, {key} to expand)\": \"...(还有 {count} 行,{key} 展开)\",\n\n\t// ---- theme-selector ----\n\t\"(current)\": \"(当前)\",\n\n\t// ---- settings-submenu ----\n\t\"Type to filter · Enter to select · Esc to go back\": \"输入以过滤 · Enter 选择 · Esc 返回\",\n\t\"Enter to select · Esc to go back\": \"Enter 选择 · Esc 返回\",\n\t\"Step {index}/{total}\": \"第 {index}/{total} 步\",\n};\n"]}
1
+ {"version":3,"file":"tui-components-misc.js","sourceRoot":"","sources":["../../../../../src/core/i18n/locales/zh-cn/tui-components-misc.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * 批次④ misc 域词典(docs/design/国际化与本地化.md §词典结构):\n * 覆盖 components/ 下的 footer、status-indicator、bash-execution、\n * assistant-message、user-message-selector、tree-render、branch-summary、\n * compaction-summary、skill-invocation、show-images、dialog-editor、dialog-input、\n * dialog-selector、mermaid、custom-entry、custom-message、tool-execution、\n * theme-selector、bordered-loader、settings-submenu。key 为英文原文(与调用点\n * 逐字一致;`t()` 会 trim key,调用点的前导/尾随空白在 `t()` 外拼接),\n * value 为简体中文译文,`{占位符}` 原样保留。数据值与纯格式(token 缩写、\n * 计数、时间戳)不入词典;skill 等术语保留原文(回退 key)。\n */\nexport const tuiComponentsMisc: Record<string, string> = {\n\t// ---- footer ----\n\t\"(sub)\": \"(订阅)\",\n\t\"(auto)\": \"(自动)\",\n\t\"no-model\": \"无模型\",\n\t\"{model} • thinking off\": \"{model} • 思考关闭\",\n\n\t// ---- status-indicator ----\n\t\"Retrying ({attempt}/{max}) in {seconds}s... ({key} to cancel)\":\n\t\t\"第 {attempt}/{max} 次重试,{seconds} 秒后...({key} 取消)\",\n\t\"Compacting context... ({key} to cancel)\": \"正在压缩上下文...({key} 取消)\",\n\t\"Context overflow detected, Auto-compacting... ({key} to cancel)\": \"检测到上下文溢出,自动压缩中...({key} 取消)\",\n\t\"Auto-compacting... ({key} to cancel)\": \"自动压缩中...({key} 取消)\",\n\t\"Summarizing branch... ({key} to cancel)\": \"正在生成分支摘要...({key} 取消)\",\n\n\t// ---- bash-execution ----\n\t\"Running... ({key} to cancel)\": \"运行中...({key} 取消)\",\n\t\"({key} to collapse)\": \"({key} 折叠)\",\n\t\"... {count} more lines ({key} to expand)\": \"... 还有 {count} 行({key} 展开)\",\n\t\"(cancelled)\": \"(已取消)\",\n\t\"(exit {code})\": \"(退出码 {code})\",\n\t\"Output truncated. Full output: {path}\": \"输出已截断。完整输出:{path}\",\n\n\t// ---- assistant-message ----\n\t\"Thinking...\": \"思考中...\",\n\t\"Response was truncated before completion.\": \"响应在完成前被截断。\",\n\t\"Operation aborted\": \"操作已中止\",\n\t\"Error: {message}\": \"错误:{message}\",\n\n\t// ---- user-message-selector ----\n\t\"No user messages found\": \"未找到用户消息\",\n\t\"Message {position} of {total}\": \"第 {position} 条,共 {total} 条\",\n\t\"Fork from Message\": \"从消息分叉\",\n\t\"Select a user message to copy the active path up to that point into a new session\":\n\t\t\"选择一条用户消息,将截至该点的当前路径复制到新会话\",\n\n\t// ---- queue-manager-selector(/queue-list 管理器)----\n\t\"Queued Messages\": \"排队消息\",\n\tSteering: \"转向\",\n\t\"Follow-up\": \"后续\",\n\t\"alt+up/alt+down move · delete remove · enter restore · esc close\":\n\t\t\"alt+up/alt+down 移动 · delete 移除 · enter 取回编辑器 · esc 关闭\",\n\n\t// ---- tree-render(/tree 高密度行,译文极短)----\n\t\"user:\": \"用户:\",\n\t\"assistant:\": \"助手:\",\n\t\"(aborted)\": \"(已中止)\",\n\t\"(no content)\": \"(无内容)\",\n\ttool: \"工具\",\n\t\"[bash]: {command}\": \"[bash]: {command}\",\n\t\"[compaction: {tokens}k tokens]\": \"[压缩: {tokens}k tokens]\",\n\t\"[branch summary]:\": \"[分支摘要]:\",\n\t\"[model: {model}]\": \"[模型: {model}]\",\n\t\"[thinking: {level}]\": \"[思考: {level}]\",\n\t\"[custom: {type}]\": \"[自定义: {type}]\",\n\t\"[label: {label}]\": \"[标签: {label}]\",\n\t\"(cleared)\": \"(已清除)\",\n\t\"[title: {name}]\": \"[标题: {name}]\",\n\tempty: \"空\",\n\t\"[read: {display}]\": \"[读取: {display}]\",\n\t\"[write: {path}]\": \"[写入: {path}]\",\n\t\"[edit: {path}]\": \"[编辑: {path}]\",\n\t\"[bash: {cmd}]\": \"[bash: {cmd}]\",\n\t\"[grep: /{pattern}/ in {path}]\": \"[搜索: /{pattern}/ 于 {path}]\",\n\t\"[find: {pattern} in {path}]\": \"[查找: {pattern} 于 {path}]\",\n\t\"[ls: {path}]\": \"[列目录: {path}]\",\n\t\"[{name}: {args}]\": \"[{name}: {args}]\",\n\n\t// ---- branch-summary / compaction-summary / skill-invocation ----\n\t\"[branch]\": \"[分支]\",\n\t\"**Branch Summary**\": \"**分支摘要**\",\n\t\"Branch summary ({key} to expand)\": \"分支摘要({key} 展开)\",\n\t\"[compaction]\": \"[压缩]\",\n\t\"**Compacted from {tokens} tokens**\": \"**已从 {tokens} tokens 压缩**\",\n\t\"Compacted from {tokens} tokens ({key} to expand)\": \"已从 {tokens} tokens 压缩({key} 展开)\",\n\t\"({key} to expand)\": \"({key} 展开)\",\n\n\t// ---- show-images-selector ----\n\tYes: \"是\",\n\tNo: \"否\",\n\t\"Show images inline in terminal\": \"在终端内联显示图片\",\n\t\"Show text placeholder instead\": \"改为显示文本占位符\",\n\n\t// ---- dialog-editor / dialog-input / dialog-selector / bordered-loader ----\n\tsubmit: \"提交\",\n\tnewline: \"换行\",\n\t\"external editor\": \"外部编辑器\",\n\tselect: \"选择\",\n\n\t// ---- mermaid ----\n\t\"Mermaid diagram not rendered: {warning}{suffix}\": \"Mermaid 图表未渲染:{warning}{suffix}\",\n\t\"+{count} more\": \"还有 {count} 条\",\n\n\t// ---- custom-entry ----\n\t\"[{type}] renderer failed: {message}\": \"[{type}] 渲染器失败:{message}\",\n\n\t// ---- tool-execution ----\n\t\"... ({count} more lines, {key} to expand)\": \"...(还有 {count} 行,{key} 展开)\",\n\t\"... ({count} lines truncated)\": \"...(已截断 {count} 行)\",\n\t\"... ({count} lines truncated; full output: {path})\": \"...(已截断 {count} 行;完整输出: {path})\",\n\n\t// ---- theme-selector ----\n\t\"(current)\": \"(当前)\",\n\n\t// ---- settings-submenu ----\n\t\"Type to filter · Enter to select · Esc to go back\": \"输入以过滤 · Enter 选择 · Esc 返回\",\n\t\"Enter to select · Esc to go back\": \"Enter 选择 · Esc 返回\",\n\t\"Step {index}/{total}\": \"第 {index}/{total} 步\",\n};\n"]}
@@ -4,6 +4,8 @@
4
4
  import type { ThinkingLevel } from "@agent-forge/agent-core";
5
5
  import { type Api, type AuthOperationOptions, type KnownProvider, type Model } from "@agent-forge/ai";
6
6
  import type { ModelRuntime } from "./model-runtime.ts";
7
+ export declare const VALID_THINKING_LEVELS: readonly ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
8
+ export declare function isValidThinkingLevel(level: string): level is ThinkingLevel;
7
9
  /** Default model IDs for each known provider */
8
10
  export declare const defaultModelPerProvider: Record<KnownProvider, string>;
9
11
  export interface ScopedModel {
@@ -1 +1 @@
1
- {"version":3,"file":"model-resolver.d.ts","sourceRoot":"","sources":["../../src/core/model-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model resolution, scoping, and initial selection\n */\n\nimport type { ThinkingLevel } from \"@agent-forge/agent-core\";\nimport { type Api, type AuthOperationOptions, type KnownProvider, type Model, modelsAreEqual } from \"@agent-forge/ai\";\nimport chalk from \"chalk\";\nimport { minimatch } from \"minimatch\";\nimport { isValidThinkingLevel } from \"../cli/args.ts\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport type { ModelRuntime } from \"./model-runtime.ts\";\n\n/** Default model IDs for each known provider */\nexport const defaultModelPerProvider: Record<KnownProvider, string> = {\n\t\"amazon-bedrock\": \"us.anthropic.claude-opus-4-6-v1\",\n\t\"ant-ling\": \"Ring-2.6-1T\",\n\tanthropic: \"claude-opus-4-8\",\n\topenai: \"gpt-5.5\",\n\t\"azure-openai-responses\": \"gpt-5.4\",\n\t\"openai-codex\": \"gpt-6.1-sol\",\n\tradius: \"auto\",\n\tnvidia: \"nvidia/nemotron-3-super-120b-a12b\",\n\tdeepseek: \"deepseek-v4-pro\",\n\tgoogle: \"gemini-3.1-pro-preview\",\n\t\"google-vertex\": \"gemini-3.1-pro-preview\",\n\t\"github-copilot\": \"gpt-5.4\",\n\topenrouter: \"moonshotai/kimi-k2.6\",\n\t\"vercel-ai-gateway\": \"zai/glm-5.1\",\n\txai: \"grok-4.6\",\n\tgroq: \"openai/gpt-oss-120b\",\n\tcerebras: \"gpt-oss-120b\",\n\tzai: \"glm-5.3\",\n\t\"zai-coding-cn\": \"glm-5.3\",\n\tmistral: \"devstral-medium-latest\",\n\tminimax: \"MiniMax-M2.7\",\n\t\"minimax-cn\": \"MiniMax-M2.7\",\n\tmoonshotai: \"kimi-k2.6\",\n\t\"moonshotai-cn\": \"kimi-k2.6\",\n\thuggingface: \"moonshotai/Kimi-K2.6\",\n\tfireworks: \"accounts/fireworks/models/kimi-k3\",\n\ttogether: \"moonshotai/Kimi-K3\",\n\tbaseten: \"zai-org/GLM-5.2\",\n\topencode: \"kimi-k2.6\",\n\t\"opencode-go\": \"kimi-k3\",\n\t\"kimi-coding\": \"kimi-for-coding\",\n\t\"cloudflare-workers-ai\": \"@cf/moonshotai/kimi-k2.6\",\n\t\"cloudflare-ai-gateway\": \"workers-ai/@cf/moonshotai/kimi-k2.6\",\n\t\"qwen-token-plan\": \"qwen3.7-max\",\n\t\"qwen-token-plan-cn\": \"qwen3.7-max\",\n\t\"qwen-token-plan-individual\": \"qwen3.8-max\",\n\txiaomi: \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-cn\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-ams\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-sgp\": \"mimo-v2.5-pro\",\n};\n\nexport interface ScopedModel {\n\tmodel: Model<Api>;\n\t/** Thinking level if explicitly specified in pattern (e.g., \"model:high\"), undefined otherwise */\n\tthinkingLevel?: ThinkingLevel;\n}\n\n/**\n * Helper to check if a model ID looks like an alias (no date suffix)\n * Dates are typically in format: -20241022 or -20250929\n */\nfunction isAlias(id: string): boolean {\n\t// Check if ID ends with -latest\n\tif (id.endsWith(\"-latest\")) return true;\n\n\t// Check if ID ends with a date pattern (-YYYYMMDD)\n\tconst datePattern = /-\\d{8}$/;\n\treturn !datePattern.test(id);\n}\n\n/**\n * Find an exact model reference match.\n * Supports either a bare model id or a canonical provider/modelId reference.\n * When matching by bare id, ambiguous matches across providers are rejected.\n */\nexport function findExactModelReferenceMatch(\n\tmodelReference: string,\n\tavailableModels: Model<Api>[],\n): Model<Api> | undefined {\n\tconst trimmedReference = modelReference.trim();\n\tif (!trimmedReference) {\n\t\treturn undefined;\n\t}\n\n\tconst normalizedReference = trimmedReference.toLowerCase();\n\n\tconst canonicalMatches = availableModels.filter(\n\t\t(model) => `${model.provider}/${model.id}`.toLowerCase() === normalizedReference,\n\t);\n\tif (canonicalMatches.length === 1) {\n\t\treturn canonicalMatches[0];\n\t}\n\tif (canonicalMatches.length > 1) {\n\t\treturn undefined;\n\t}\n\n\tconst slashIndex = trimmedReference.indexOf(\"/\");\n\tif (slashIndex !== -1) {\n\t\tconst provider = trimmedReference.substring(0, slashIndex).trim();\n\t\tconst modelId = trimmedReference.substring(slashIndex + 1).trim();\n\t\tif (provider && modelId) {\n\t\t\tconst providerMatches = availableModels.filter(\n\t\t\t\t(model) =>\n\t\t\t\t\tmodel.provider.toLowerCase() === provider.toLowerCase() &&\n\t\t\t\t\tmodel.id.toLowerCase() === modelId.toLowerCase(),\n\t\t\t);\n\t\t\tif (providerMatches.length === 1) {\n\t\t\t\treturn providerMatches[0];\n\t\t\t}\n\t\t\tif (providerMatches.length > 1) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst idMatches = availableModels.filter((model) => model.id.toLowerCase() === normalizedReference);\n\treturn idMatches.length === 1 ? idMatches[0] : undefined;\n}\n\n/**\n * Try to match a pattern to a model from the available models list.\n * Returns the matched model or undefined if no match found.\n */\nfunction tryMatchModel(modelPattern: string, availableModels: Model<Api>[]): Model<Api> | undefined {\n\tconst exactMatch = findExactModelReferenceMatch(modelPattern, availableModels);\n\tif (exactMatch) {\n\t\treturn exactMatch;\n\t}\n\n\t// No exact match - fall back to partial matching\n\tconst matches = availableModels.filter(\n\t\t(m) =>\n\t\t\tm.id.toLowerCase().includes(modelPattern.toLowerCase()) ||\n\t\t\tm.name?.toLowerCase().includes(modelPattern.toLowerCase()),\n\t);\n\n\tif (matches.length === 0) {\n\t\treturn undefined;\n\t}\n\n\t// Separate into aliases and dated versions\n\tconst aliases = matches.filter((m) => isAlias(m.id));\n\tconst datedVersions = matches.filter((m) => !isAlias(m.id));\n\n\tif (aliases.length > 0) {\n\t\t// Prefer alias - if multiple aliases, pick the one that sorts highest\n\t\taliases.sort((a, b) => b.id.localeCompare(a.id));\n\t\treturn aliases[0];\n\t} else {\n\t\t// No alias found, pick latest dated version\n\t\tdatedVersions.sort((a, b) => b.id.localeCompare(a.id));\n\t\treturn datedVersions[0];\n\t}\n}\n\nexport interface ParsedModelResult {\n\tmodel: Model<Api> | undefined;\n\t/** Thinking level if explicitly specified in pattern, undefined otherwise */\n\tthinkingLevel?: ThinkingLevel;\n\twarning: string | undefined;\n}\n\nfunction buildFallbackModel(provider: string, modelId: string, availableModels: Model<Api>[]): Model<Api> | undefined {\n\tconst providerModels = availableModels.filter((m) => m.provider === provider);\n\tif (providerModels.length === 0) return undefined;\n\n\tconst defaultId = defaultModelPerProvider[provider as KnownProvider];\n\tconst baseModel = defaultId\n\t\t? (providerModels.find((m) => m.id === defaultId) ?? providerModels[0])\n\t\t: providerModels[0];\n\n\treturn {\n\t\t...baseModel,\n\t\tid: modelId,\n\t\tname: modelId,\n\t};\n}\n\n/**\n * Parse a pattern to extract model and thinking level.\n * Handles models with colons in their IDs (e.g., OpenRouter's :exacto suffix).\n *\n * Algorithm:\n * 1. Try to match full pattern as a model\n * 2. If found, return it with \"off\" thinking level\n * 3. If not found and has colons, split on last colon:\n * - If suffix is valid thinking level, use it and recurse on prefix\n * - If suffix is invalid, warn and recurse on prefix with \"off\"\n *\n * @internal Exported for testing\n */\nexport function parseModelPattern(\n\tpattern: string,\n\tavailableModels: Model<Api>[],\n\toptions?: { allowInvalidThinkingLevelFallback?: boolean },\n): ParsedModelResult {\n\t// Try exact match first\n\tconst exactMatch = tryMatchModel(pattern, availableModels);\n\tif (exactMatch) {\n\t\treturn { model: exactMatch, thinkingLevel: undefined, warning: undefined };\n\t}\n\n\t// No match - try splitting on last colon if present\n\tconst lastColonIndex = pattern.lastIndexOf(\":\");\n\tif (lastColonIndex === -1) {\n\t\t// No colons, pattern simply doesn't match any model\n\t\treturn { model: undefined, thinkingLevel: undefined, warning: undefined };\n\t}\n\n\tconst prefix = pattern.substring(0, lastColonIndex);\n\tconst suffix = pattern.substring(lastColonIndex + 1);\n\n\tif (isValidThinkingLevel(suffix)) {\n\t\t// Valid thinking level - recurse on prefix and use this level\n\t\tconst result = parseModelPattern(prefix, availableModels, options);\n\t\tif (result.model) {\n\t\t\t// Only use this thinking level if no warning from inner recursion\n\t\t\treturn {\n\t\t\t\tmodel: result.model,\n\t\t\t\tthinkingLevel: result.warning ? undefined : suffix,\n\t\t\t\twarning: result.warning,\n\t\t\t};\n\t\t}\n\t\treturn result;\n\t} else {\n\t\t// Invalid suffix\n\t\tconst allowFallback = options?.allowInvalidThinkingLevelFallback ?? true;\n\t\tif (!allowFallback) {\n\t\t\t// In strict mode (CLI --model parsing), treat it as part of the model id and fail.\n\t\t\t// This avoids accidentally resolving to a different model.\n\t\t\treturn { model: undefined, thinkingLevel: undefined, warning: undefined };\n\t\t}\n\n\t\t// Scope mode: recurse on prefix and warn\n\t\tconst result = parseModelPattern(prefix, availableModels, options);\n\t\tif (result.model) {\n\t\t\treturn {\n\t\t\t\tmodel: result.model,\n\t\t\t\tthinkingLevel: undefined,\n\t\t\t\twarning: `Invalid thinking level \"${suffix}\" in pattern \"${pattern}\". Using default instead.`,\n\t\t\t};\n\t\t}\n\t\treturn result;\n\t}\n}\n\n/**\n * Resolve model patterns to actual Model objects with optional thinking levels\n * Format: \"pattern:level\" where :level is optional\n * For each pattern, finds all matching models and picks the best version:\n * 1. Prefer alias (e.g., claude-sonnet-4-5) over dated versions (claude-sonnet-4-5-20250929)\n * 2. If no alias, pick the latest dated version\n *\n * Supports models with colons in their IDs (e.g., OpenRouter's model:exacto).\n * The algorithm tries to match the full pattern first, then progressively\n * strips colon-suffixes to find a match.\n */\nexport interface ModelScopeDiagnostic {\n\ttype: \"warning\";\n\tcode: \"no-match\" | \"invalid-thinking-level\";\n\tmessage: string;\n\tpattern: string;\n}\n\nexport interface ResolveModelScopeResult {\n\tscopedModels: ScopedModel[];\n\tdiagnostics: ModelScopeDiagnostic[];\n}\n\nexport function resolveModelScopeFromModels(\n\tpatterns: string[],\n\tmodels: readonly Model<Api>[],\n): ResolveModelScopeResult {\n\tconst availableModels = [...models];\n\tconst scopedModels: ScopedModel[] = [];\n\tconst diagnostics: ModelScopeDiagnostic[] = [];\n\n\tfor (const pattern of patterns) {\n\t\t// Check if pattern contains glob characters\n\t\tif (pattern.includes(\"*\") || pattern.includes(\"?\") || pattern.includes(\"[\")) {\n\t\t\t// Extract optional thinking level suffix (e.g., \"provider/*:high\")\n\t\t\tconst colonIdx = pattern.lastIndexOf(\":\");\n\t\t\tlet globPattern = pattern;\n\t\t\tlet thinkingLevel: ThinkingLevel | undefined;\n\n\t\t\tif (colonIdx !== -1) {\n\t\t\t\tconst suffix = pattern.substring(colonIdx + 1);\n\t\t\t\tif (isValidThinkingLevel(suffix)) {\n\t\t\t\t\tthinkingLevel = suffix;\n\t\t\t\t\tglobPattern = pattern.substring(0, colonIdx);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst exactMatch = findExactModelReferenceMatch(globPattern, availableModels);\n\t\t\tif (exactMatch) {\n\t\t\t\tif (!scopedModels.find((sm) => modelsAreEqual(sm.model, exactMatch))) {\n\t\t\t\t\tscopedModels.push({ model: exactMatch, thinkingLevel });\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Match against \"provider/modelId\" format OR just model ID\n\t\t\t// This allows \"*sonnet*\" to match without requiring \"anthropic/*sonnet*\"\n\t\t\tconst matchingModels = availableModels.filter((m) => {\n\t\t\t\tconst fullId = `${m.provider}/${m.id}`;\n\t\t\t\treturn minimatch(fullId, globPattern, { nocase: true }) || minimatch(m.id, globPattern, { nocase: true });\n\t\t\t});\n\n\t\t\tif (matchingModels.length === 0) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tcode: \"no-match\",\n\t\t\t\t\tmessage: `No models match pattern \"${pattern}\"`,\n\t\t\t\t\tpattern,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor (const model of matchingModels) {\n\t\t\t\tif (!scopedModels.find((sm) => modelsAreEqual(sm.model, model))) {\n\t\t\t\t\tscopedModels.push({ model, thinkingLevel });\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { model, thinkingLevel, warning } = parseModelPattern(pattern, availableModels);\n\n\t\tif (warning) {\n\t\t\tdiagnostics.push({ type: \"warning\", code: \"invalid-thinking-level\", message: warning, pattern });\n\t\t}\n\n\t\tif (!model) {\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"warning\",\n\t\t\t\tcode: \"no-match\",\n\t\t\t\tmessage: `No models match pattern \"${pattern}\"`,\n\t\t\t\tpattern,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Avoid duplicates\n\t\tif (!scopedModels.find((sm) => modelsAreEqual(sm.model, model))) {\n\t\t\tscopedModels.push({ model, thinkingLevel });\n\t\t}\n\t}\n\n\treturn { scopedModels, diagnostics };\n}\n\nexport async function resolveModelScopeWithDiagnostics(\n\tpatterns: string[],\n\tmodelRuntime: ModelRuntime,\n\toptions?: AuthOperationOptions,\n): Promise<ResolveModelScopeResult> {\n\treturn resolveModelScopeFromModels(patterns, await modelRuntime.getAvailable(undefined, options));\n}\n\nexport async function resolveModelScope(\n\tpatterns: string[],\n\tmodelRuntime: ModelRuntime,\n\toptions?: AuthOperationOptions,\n): Promise<ScopedModel[]> {\n\tconst { scopedModels, diagnostics } = await resolveModelScopeWithDiagnostics(patterns, modelRuntime, options);\n\tfor (const diagnostic of diagnostics) {\n\t\tconsole.warn(chalk.yellow(`Warning: ${diagnostic.message}`));\n\t}\n\treturn scopedModels;\n}\n\nexport interface ResolveCliModelResult {\n\tmodel: Model<Api> | undefined;\n\tthinkingLevel?: ThinkingLevel;\n\twarning: string | undefined;\n\t/**\n\t * Error message suitable for CLI display.\n\t * When set, model will be undefined.\n\t */\n\terror: string | undefined;\n}\n\n/**\n * Resolve a single model from CLI flags.\n *\n * Supports:\n * - --provider <provider> --model <pattern>\n * - --model <provider>/<pattern>\n * - Fuzzy matching (same rules as model scoping: exact id, then partial id/name)\n *\n * Note: This does not apply the thinking level by itself, but it may *parse* and\n * return a thinking level from \"<pattern>:<thinking>\" so the caller can apply it.\n */\nexport function resolveCliModel(options: {\n\tcliProvider?: string;\n\tcliModel?: string;\n\tcliThinking?: ThinkingLevel;\n\tmodelRuntime: ModelRuntime;\n}): ResolveCliModelResult {\n\tconst { cliProvider, cliModel, cliThinking, modelRuntime } = options;\n\n\tif (!cliModel) {\n\t\treturn { model: undefined, warning: undefined, error: undefined };\n\t}\n\n\t// Important: use *all* models here, not just models with pre-configured auth.\n\t// This allows \"--api-key\" to be used for first-time setup.\n\tconst availableModels = [...modelRuntime.getModels()];\n\tif (availableModels.length === 0) {\n\t\treturn {\n\t\t\tmodel: undefined,\n\t\t\twarning: undefined,\n\t\t\terror: \"No models available. Check your installation or add models to models.json.\",\n\t\t};\n\t}\n\n\t// Build canonical provider lookup (case-insensitive)\n\tconst providerMap = new Map<string, string>();\n\tfor (const m of availableModels) {\n\t\tproviderMap.set(m.provider.toLowerCase(), m.provider);\n\t}\n\n\tlet provider = cliProvider ? providerMap.get(cliProvider.toLowerCase()) : undefined;\n\tif (cliProvider && !provider) {\n\t\treturn {\n\t\t\tmodel: undefined,\n\t\t\twarning: undefined,\n\t\t\terror: `Unknown provider \"${cliProvider}\". Use --list-models to see available providers/models.`,\n\t\t};\n\t}\n\n\t// If no explicit --provider, try to interpret \"provider/model\" format first.\n\t// When the prefix before the first slash matches a known provider, prefer that\n\t// interpretation over matching models whose IDs literally contain slashes\n\t// (e.g. \"zai/glm-5\" should resolve to provider=zai, model=glm-5, not to a\n\t// vercel-ai-gateway model with id \"zai/glm-5\").\n\tlet pattern = cliModel;\n\tlet inferredProvider = false;\n\n\tif (!provider) {\n\t\tconst slashIndex = cliModel.indexOf(\"/\");\n\t\tif (slashIndex !== -1) {\n\t\t\tconst maybeProvider = cliModel.substring(0, slashIndex);\n\t\t\tconst canonical = providerMap.get(maybeProvider.toLowerCase());\n\t\t\tif (canonical) {\n\t\t\t\tprovider = canonical;\n\t\t\t\tpattern = cliModel.substring(slashIndex + 1);\n\t\t\t\tinferredProvider = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If no provider was inferred from the slash, try exact matches without provider inference.\n\t// This handles models whose IDs naturally contain slashes (e.g. OpenRouter-style IDs).\n\t// Bare exact IDs can exist in multiple providers, so do not choose by catalog order.\n\t// Prefer the sole authenticated provider when there is one; otherwise require an\n\t// explicit provider to avoid silently selecting an unusable provider.\n\tif (!provider) {\n\t\tconst lower = cliModel.toLowerCase();\n\t\tconst exactMatches = availableModels.filter(\n\t\t\t(m) => m.id.toLowerCase() === lower || `${m.provider}/${m.id}`.toLowerCase() === lower,\n\t\t);\n\t\tif (exactMatches.length === 1) {\n\t\t\treturn { model: exactMatches[0], warning: undefined, thinkingLevel: undefined, error: undefined };\n\t\t}\n\t\tif (exactMatches.length > 1) {\n\t\t\tconst authenticatedExactMatches = exactMatches.filter((m) => modelRuntime.hasConfiguredAuth(m.provider));\n\t\t\tif (authenticatedExactMatches.length === 1) {\n\t\t\t\treturn {\n\t\t\t\t\tmodel: authenticatedExactMatches[0],\n\t\t\t\t\twarning: undefined,\n\t\t\t\t\tthinkingLevel: undefined,\n\t\t\t\t\terror: undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst matches = exactMatches\n\t\t\t\t.map((m) => `${m.provider}/${m.id}`)\n\t\t\t\t.sort((a, b) => a.localeCompare(b))\n\t\t\t\t.join(\", \");\n\t\t\tconst authHint =\n\t\t\t\tauthenticatedExactMatches.length === 0\n\t\t\t\t\t? \"No matching provider is authenticated.\"\n\t\t\t\t\t: \"More than one matching provider is authenticated.\";\n\t\t\treturn {\n\t\t\t\tmodel: undefined,\n\t\t\t\twarning: undefined,\n\t\t\t\tthinkingLevel: undefined,\n\t\t\t\terror: `Model \"${cliModel}\" is ambiguous across providers: ${matches}. ${authHint} Use --provider or provider/model.`,\n\t\t\t};\n\t\t}\n\t}\n\n\tif (cliProvider && provider) {\n\t\t// If both were provided, tolerate --model <provider>/<pattern> by stripping the provider prefix\n\t\tconst prefix = `${provider}/`;\n\t\tif (cliModel.toLowerCase().startsWith(prefix.toLowerCase())) {\n\t\t\tpattern = cliModel.substring(prefix.length);\n\t\t}\n\t}\n\n\tconst candidates = provider ? availableModels.filter((m) => m.provider === provider) : availableModels;\n\tconst { model, thinkingLevel, warning } = parseModelPattern(pattern, candidates, {\n\t\tallowInvalidThinkingLevelFallback: false,\n\t});\n\n\tif (model) {\n\t\t// If provider inference matched an unauthenticated provider/model pair, prefer\n\t\t// one exact raw model-id match that is authenticated. This keeps\n\t\t// \"provider/model\" syntax preferred when usable, but handles models whose\n\t\t// literal id starts with a known provider name (for example\n\t\t// commandcode model id \"xiaomi/mimo-v2.5-pro\").\n\t\tif (inferredProvider) {\n\t\t\tconst rawExactMatches = availableModels.filter(\n\t\t\t\t(m) => m.id.toLowerCase() === cliModel.toLowerCase() && !modelsAreEqual(m, model),\n\t\t\t);\n\t\t\tif (rawExactMatches.length > 0 && !modelRuntime.hasConfiguredAuth(model.provider)) {\n\t\t\t\tconst authenticatedRawMatches = rawExactMatches.filter((m) => modelRuntime.hasConfiguredAuth(m.provider));\n\t\t\t\tif (authenticatedRawMatches.length === 1) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tmodel: authenticatedRawMatches[0],\n\t\t\t\t\t\tthinkingLevel: undefined,\n\t\t\t\t\t\twarning: undefined,\n\t\t\t\t\t\terror: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn { model, thinkingLevel, warning, error: undefined };\n\t}\n\n\t// If we inferred a provider from the slash but found no match within that provider,\n\t// fall back to matching the full input as a raw model id across all models.\n\t// This handles OpenRouter-style IDs like \"openai/gpt-4o:extended\" where \"openai\"\n\t// looks like a provider but the full string is actually a model id on openrouter.\n\tif (inferredProvider) {\n\t\tconst lower = cliModel.toLowerCase();\n\t\tconst exact = availableModels.find(\n\t\t\t(m) => m.id.toLowerCase() === lower || `${m.provider}/${m.id}`.toLowerCase() === lower,\n\t\t);\n\t\tif (exact) {\n\t\t\treturn { model: exact, warning: undefined, thinkingLevel: undefined, error: undefined };\n\t\t}\n\t\t// Also try parseModelPattern on the full input against all models\n\t\tconst fallback = parseModelPattern(cliModel, availableModels, {\n\t\t\tallowInvalidThinkingLevelFallback: false,\n\t\t});\n\t\tif (fallback.model) {\n\t\t\treturn {\n\t\t\t\tmodel: fallback.model,\n\t\t\t\tthinkingLevel: fallback.thinkingLevel,\n\t\t\t\twarning: fallback.warning,\n\t\t\t\terror: undefined,\n\t\t\t};\n\t\t}\n\t}\n\n\tif (provider) {\n\t\t// Parse thinking level suffix from the pattern before building the fallback model,\n\t\t// but only when --thinking is not explicitly provided.\n\t\t// e.g. \"zai-org/GLM-5.1-FP8:high\" → modelId=\"zai-org/GLM-5.1-FP8\", fallbackThinking=\"high\"\n\t\tlet fallbackPattern = pattern;\n\t\tlet fallbackThinking: ThinkingLevel | undefined;\n\t\tif (!cliThinking) {\n\t\t\tconst lastColon = pattern.lastIndexOf(\":\");\n\t\t\tif (lastColon !== -1) {\n\t\t\t\tconst suffix = pattern.substring(lastColon + 1);\n\t\t\t\tif (isValidThinkingLevel(suffix)) {\n\t\t\t\t\tfallbackPattern = pattern.substring(0, lastColon);\n\t\t\t\t\tfallbackThinking = suffix;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst fallbackModel = buildFallbackModel(provider, fallbackPattern, availableModels);\n\t\tif (fallbackModel) {\n\t\t\tconst requestedThinking = cliThinking ?? fallbackThinking;\n\t\t\tconst model =\n\t\t\t\trequestedThinking && requestedThinking !== \"off\" ? { ...fallbackModel, reasoning: true } : fallbackModel;\n\t\t\tconst fallbackWarning = warning\n\t\t\t\t? `${warning} Model \"${fallbackPattern}\" not found for provider \"${provider}\". Using custom model id.`\n\t\t\t\t: `Model \"${fallbackPattern}\" not found for provider \"${provider}\". Using custom model id.`;\n\t\t\treturn { model, thinkingLevel: fallbackThinking, warning: fallbackWarning, error: undefined };\n\t\t}\n\t}\n\n\tconst display = provider ? `${provider}/${pattern}` : cliModel;\n\treturn {\n\t\tmodel: undefined,\n\t\tthinkingLevel: undefined,\n\t\twarning,\n\t\terror: `Model \"${display}\" not found. Use --list-models to see available models.`,\n\t};\n}\n\nexport interface InitialModelResult {\n\tmodel: Model<Api> | undefined;\n\tthinkingLevel: ThinkingLevel;\n\tfallbackMessage: string | undefined;\n}\n\n/**\n * Find the initial model to use based on priority:\n * 1. CLI args (provider + model)\n * 2. First model from scoped models (if not continuing/resuming)\n * 3. Restored from session (if continuing/resuming)\n * 4. Saved default from settings\n * 5. First available model with valid API key\n */\nexport async function findInitialModel(options: {\n\tcliProvider?: string;\n\tcliModel?: string;\n\tscopedModels: ScopedModel[];\n\tisContinuing: boolean;\n\tdefaultProvider?: string;\n\tdefaultModelId?: string;\n\tdefaultThinkingLevel?: ThinkingLevel;\n\tmodelThinkingLevels?: Record<string, ThinkingLevel>;\n\tmodelRuntime: ModelRuntime;\n}): Promise<InitialModelResult> {\n\tconst {\n\t\tcliProvider,\n\t\tcliModel,\n\t\tscopedModels,\n\t\tisContinuing,\n\t\tdefaultProvider,\n\t\tdefaultModelId,\n\t\tdefaultThinkingLevel,\n\t\tmodelThinkingLevels,\n\t\tmodelRuntime,\n\t} = options;\n\n\tlet model: Model<Api> | undefined;\n\tlet thinkingLevel: ThinkingLevel = DEFAULT_THINKING_LEVEL;\n\n\t// 1. CLI args take priority\n\tif (cliProvider && cliModel) {\n\t\tconst resolved = resolveCliModel({\n\t\t\tcliProvider,\n\t\t\tcliModel,\n\t\t\tmodelRuntime,\n\t\t});\n\t\t// v8 ignore next -- CLI 模型解析失败即退出进程,测试无法安全触达 process.exit(1)\n\t\tif (resolved.error) {\n\t\t\tconsole.error(chalk.red(resolved.error));\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tif (resolved.model) {\n\t\t\treturn { model: resolved.model, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n\t\t}\n\t}\n\n\t// 2. Use first model from scoped models (skip if continuing/resuming)\n\tif (scopedModels.length > 0 && !isContinuing) {\n\t\tconst scopedModel = scopedModels[0];\n\t\tconst perModel = modelThinkingLevels?.[`${scopedModel.model.provider}/${scopedModel.model.id}`];\n\t\treturn {\n\t\t\tmodel: scopedModel.model,\n\t\t\tthinkingLevel: scopedModel.thinkingLevel ?? perModel ?? defaultThinkingLevel ?? DEFAULT_THINKING_LEVEL,\n\t\t\tfallbackMessage: undefined,\n\t\t};\n\t}\n\n\t// 3. Try saved default from settings if auth is configured.\n\tif (defaultProvider && defaultModelId) {\n\t\tconst found = modelRuntime.getModel(defaultProvider, defaultModelId);\n\t\tif (found && modelRuntime.hasConfiguredAuth(found.provider)) {\n\t\t\tmodel = found;\n\t\t\tconst perModel = modelThinkingLevels?.[`${defaultProvider}/${defaultModelId}`];\n\t\t\tif (perModel) {\n\t\t\t\tthinkingLevel = perModel;\n\t\t\t} else if (defaultThinkingLevel) {\n\t\t\t\tthinkingLevel = defaultThinkingLevel;\n\t\t\t}\n\t\t\treturn { model, thinkingLevel, fallbackMessage: undefined };\n\t\t}\n\t}\n\n\t// 4. Try first available model with valid API key\n\tconst availableModels = [...modelRuntime.getAvailableSnapshot()];\n\n\tif (availableModels.length > 0) {\n\t\t// Try to find a default model from known providers\n\t\tfor (const provider of Object.keys(defaultModelPerProvider) as KnownProvider[]) {\n\t\t\tconst defaultId = defaultModelPerProvider[provider];\n\t\t\tconst match = availableModels.find((m) => m.provider === provider && m.id === defaultId);\n\t\t\tif (match) {\n\t\t\t\treturn { model: match, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n\t\t\t}\n\t\t}\n\n\t\t// If no default found, use first available\n\t\treturn { model: availableModels[0], thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n\t}\n\n\t// 5. No model found\n\treturn { model: undefined, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n}\n\n/**\n * Restore model from session, with fallback to available models\n */\nexport async function restoreModelFromSession(\n\tsavedProvider: string,\n\tsavedModelId: string,\n\tcurrentModel: Model<Api> | undefined,\n\tshouldPrintMessages: boolean,\n\tmodelRuntime: ModelRuntime,\n): Promise<{ model: Model<Api> | undefined; fallbackMessage: string | undefined }> {\n\tconst restoredModel = modelRuntime.getModel(savedProvider, savedModelId);\n\n\t// Check if restored model exists and still has auth configured\n\tconst hasConfiguredAuth = restoredModel ? modelRuntime.hasConfiguredAuth(restoredModel.provider) : false;\n\n\tif (restoredModel && hasConfiguredAuth) {\n\t\tif (shouldPrintMessages) {\n\t\t\tconsole.log(chalk.dim(`Restored model: ${savedProvider}/${savedModelId}`));\n\t\t}\n\t\treturn { model: restoredModel, fallbackMessage: undefined };\n\t}\n\n\t// Model not found or no API key - fall back\n\tconst reason = !restoredModel ? \"model no longer exists\" : \"no auth configured\";\n\n\tif (shouldPrintMessages) {\n\t\tconsole.error(chalk.yellow(`Warning: Could not restore model ${savedProvider}/${savedModelId} (${reason}).`));\n\t}\n\n\t// If we already have a model, use it as fallback\n\tif (currentModel) {\n\t\tif (shouldPrintMessages) {\n\t\t\tconsole.log(chalk.dim(`Falling back to: ${currentModel.provider}/${currentModel.id}`));\n\t\t}\n\t\treturn {\n\t\t\tmodel: currentModel,\n\t\t\tfallbackMessage: `Could not restore model ${savedProvider}/${savedModelId} (${reason}). Using ${currentModel.provider}/${currentModel.id}.`,\n\t\t};\n\t}\n\n\t// Try to find any available model\n\tconst availableModels = [...modelRuntime.getAvailableSnapshot()];\n\n\tif (availableModels.length > 0) {\n\t\t// Try to find a default model from known providers\n\t\tlet fallbackModel: Model<Api> | undefined;\n\t\tfor (const provider of Object.keys(defaultModelPerProvider) as KnownProvider[]) {\n\t\t\tconst defaultId = defaultModelPerProvider[provider];\n\t\t\tconst match = availableModels.find((m) => m.provider === provider && m.id === defaultId);\n\t\t\tif (match) {\n\t\t\t\tfallbackModel = match;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// If no default found, use first available\n\t\tif (!fallbackModel) {\n\t\t\tfallbackModel = availableModels[0];\n\t\t}\n\n\t\tif (shouldPrintMessages) {\n\t\t\tconsole.log(chalk.dim(`Falling back to: ${fallbackModel.provider}/${fallbackModel.id}`));\n\t\t}\n\n\t\treturn {\n\t\t\tmodel: fallbackModel,\n\t\t\tfallbackMessage: `Could not restore model ${savedProvider}/${savedModelId} (${reason}). Using ${fallbackModel.provider}/${fallbackModel.id}.`,\n\t\t};\n\t}\n\n\t// No models available\n\treturn { model: undefined, fallbackMessage: undefined };\n}\n"]}
1
+ {"version":3,"file":"model-resolver.d.ts","sourceRoot":"","sources":["../../src/core/model-resolver.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Model resolution, scoping, and initial selection\n */\n\nimport type { ThinkingLevel } from \"@agent-forge/agent-core\";\nimport { type Api, type AuthOperationOptions, type KnownProvider, type Model, modelsAreEqual } from \"@agent-forge/ai\";\nimport chalk from \"chalk\";\nimport { minimatch } from \"minimatch\";\nimport { DEFAULT_THINKING_LEVEL } from \"./defaults.ts\";\nimport type { ModelRuntime } from \"./model-runtime.ts\";\n\nexport const VALID_THINKING_LEVELS = [\"off\", \"minimal\", \"low\", \"medium\", \"high\", \"xhigh\", \"max\"] as const;\n\nexport function isValidThinkingLevel(level: string): level is ThinkingLevel {\n\treturn VALID_THINKING_LEVELS.includes(level as ThinkingLevel);\n}\n\n/** Default model IDs for each known provider */\nexport const defaultModelPerProvider: Record<KnownProvider, string> = {\n\t\"amazon-bedrock\": \"us.anthropic.claude-opus-4-6-v1\",\n\t\"ant-ling\": \"Ring-2.6-1T\",\n\tanthropic: \"claude-opus-4-8\",\n\topenai: \"gpt-5.5\",\n\t\"azure-openai-responses\": \"gpt-5.4\",\n\t\"openai-codex\": \"gpt-6.1-sol\",\n\tradius: \"auto\",\n\tnvidia: \"nvidia/nemotron-3-super-120b-a12b\",\n\tdeepseek: \"deepseek-v4-pro\",\n\tgoogle: \"gemini-3.1-pro-preview\",\n\t\"google-vertex\": \"gemini-3.1-pro-preview\",\n\t\"github-copilot\": \"gpt-5.4\",\n\topenrouter: \"moonshotai/kimi-k2.6\",\n\t\"vercel-ai-gateway\": \"zai/glm-5.1\",\n\txai: \"grok-4.6\",\n\tgroq: \"openai/gpt-oss-120b\",\n\tcerebras: \"gpt-oss-120b\",\n\tzai: \"glm-5.3\",\n\t\"zai-coding-cn\": \"glm-5.3\",\n\tmistral: \"devstral-medium-latest\",\n\tminimax: \"MiniMax-M2.7\",\n\t\"minimax-cn\": \"MiniMax-M2.7\",\n\tmoonshotai: \"kimi-k2.6\",\n\t\"moonshotai-cn\": \"kimi-k2.6\",\n\thuggingface: \"moonshotai/Kimi-K2.6\",\n\tfireworks: \"accounts/fireworks/models/kimi-k3\",\n\ttogether: \"moonshotai/Kimi-K3\",\n\tbaseten: \"zai-org/GLM-5.2\",\n\topencode: \"kimi-k2.6\",\n\t\"opencode-go\": \"kimi-k3\",\n\t\"kimi-coding\": \"kimi-for-coding\",\n\t\"cloudflare-workers-ai\": \"@cf/moonshotai/kimi-k2.6\",\n\t\"cloudflare-ai-gateway\": \"workers-ai/@cf/moonshotai/kimi-k2.6\",\n\t\"qwen-token-plan\": \"qwen3.7-max\",\n\t\"qwen-token-plan-cn\": \"qwen3.7-max\",\n\t\"qwen-token-plan-individual\": \"qwen3.8-max\",\n\txiaomi: \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-cn\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-ams\": \"mimo-v2.5-pro\",\n\t\"xiaomi-token-plan-sgp\": \"mimo-v2.5-pro\",\n};\n\nexport interface ScopedModel {\n\tmodel: Model<Api>;\n\t/** Thinking level if explicitly specified in pattern (e.g., \"model:high\"), undefined otherwise */\n\tthinkingLevel?: ThinkingLevel;\n}\n\n/**\n * Helper to check if a model ID looks like an alias (no date suffix)\n * Dates are typically in format: -20241022 or -20250929\n */\nfunction isAlias(id: string): boolean {\n\t// Check if ID ends with -latest\n\tif (id.endsWith(\"-latest\")) return true;\n\n\t// Check if ID ends with a date pattern (-YYYYMMDD)\n\tconst datePattern = /-\\d{8}$/;\n\treturn !datePattern.test(id);\n}\n\n/**\n * Find an exact model reference match.\n * Supports either a bare model id or a canonical provider/modelId reference.\n * When matching by bare id, ambiguous matches across providers are rejected.\n */\nexport function findExactModelReferenceMatch(\n\tmodelReference: string,\n\tavailableModels: Model<Api>[],\n): Model<Api> | undefined {\n\tconst trimmedReference = modelReference.trim();\n\tif (!trimmedReference) {\n\t\treturn undefined;\n\t}\n\n\tconst normalizedReference = trimmedReference.toLowerCase();\n\n\tconst canonicalMatches = availableModels.filter(\n\t\t(model) => `${model.provider}/${model.id}`.toLowerCase() === normalizedReference,\n\t);\n\tif (canonicalMatches.length === 1) {\n\t\treturn canonicalMatches[0];\n\t}\n\tif (canonicalMatches.length > 1) {\n\t\treturn undefined;\n\t}\n\n\tconst slashIndex = trimmedReference.indexOf(\"/\");\n\tif (slashIndex !== -1) {\n\t\tconst provider = trimmedReference.substring(0, slashIndex).trim();\n\t\tconst modelId = trimmedReference.substring(slashIndex + 1).trim();\n\t\tif (provider && modelId) {\n\t\t\tconst providerMatches = availableModels.filter(\n\t\t\t\t(model) =>\n\t\t\t\t\tmodel.provider.toLowerCase() === provider.toLowerCase() &&\n\t\t\t\t\tmodel.id.toLowerCase() === modelId.toLowerCase(),\n\t\t\t);\n\t\t\tif (providerMatches.length === 1) {\n\t\t\t\treturn providerMatches[0];\n\t\t\t}\n\t\t\tif (providerMatches.length > 1) {\n\t\t\t\treturn undefined;\n\t\t\t}\n\t\t}\n\t}\n\n\tconst idMatches = availableModels.filter((model) => model.id.toLowerCase() === normalizedReference);\n\treturn idMatches.length === 1 ? idMatches[0] : undefined;\n}\n\n/**\n * Try to match a pattern to a model from the available models list.\n * Returns the matched model or undefined if no match found.\n */\nfunction tryMatchModel(modelPattern: string, availableModels: Model<Api>[]): Model<Api> | undefined {\n\tconst exactMatch = findExactModelReferenceMatch(modelPattern, availableModels);\n\tif (exactMatch) {\n\t\treturn exactMatch;\n\t}\n\n\t// No exact match - fall back to partial matching\n\tconst matches = availableModels.filter(\n\t\t(m) =>\n\t\t\tm.id.toLowerCase().includes(modelPattern.toLowerCase()) ||\n\t\t\tm.name?.toLowerCase().includes(modelPattern.toLowerCase()),\n\t);\n\n\tif (matches.length === 0) {\n\t\treturn undefined;\n\t}\n\n\t// Separate into aliases and dated versions\n\tconst aliases = matches.filter((m) => isAlias(m.id));\n\tconst datedVersions = matches.filter((m) => !isAlias(m.id));\n\n\tif (aliases.length > 0) {\n\t\t// Prefer alias - if multiple aliases, pick the one that sorts highest\n\t\taliases.sort((a, b) => b.id.localeCompare(a.id));\n\t\treturn aliases[0];\n\t} else {\n\t\t// No alias found, pick latest dated version\n\t\tdatedVersions.sort((a, b) => b.id.localeCompare(a.id));\n\t\treturn datedVersions[0];\n\t}\n}\n\nexport interface ParsedModelResult {\n\tmodel: Model<Api> | undefined;\n\t/** Thinking level if explicitly specified in pattern, undefined otherwise */\n\tthinkingLevel?: ThinkingLevel;\n\twarning: string | undefined;\n}\n\nfunction buildFallbackModel(provider: string, modelId: string, availableModels: Model<Api>[]): Model<Api> | undefined {\n\tconst providerModels = availableModels.filter((m) => m.provider === provider);\n\tif (providerModels.length === 0) return undefined;\n\n\tconst defaultId = defaultModelPerProvider[provider as KnownProvider];\n\tconst baseModel = defaultId\n\t\t? (providerModels.find((m) => m.id === defaultId) ?? providerModels[0])\n\t\t: providerModels[0];\n\n\treturn {\n\t\t...baseModel,\n\t\tid: modelId,\n\t\tname: modelId,\n\t};\n}\n\n/**\n * Parse a pattern to extract model and thinking level.\n * Handles models with colons in their IDs (e.g., OpenRouter's :exacto suffix).\n *\n * Algorithm:\n * 1. Try to match full pattern as a model\n * 2. If found, return it with \"off\" thinking level\n * 3. If not found and has colons, split on last colon:\n * - If suffix is valid thinking level, use it and recurse on prefix\n * - If suffix is invalid, warn and recurse on prefix with \"off\"\n *\n * @internal Exported for testing\n */\nexport function parseModelPattern(\n\tpattern: string,\n\tavailableModels: Model<Api>[],\n\toptions?: { allowInvalidThinkingLevelFallback?: boolean },\n): ParsedModelResult {\n\t// Try exact match first\n\tconst exactMatch = tryMatchModel(pattern, availableModels);\n\tif (exactMatch) {\n\t\treturn { model: exactMatch, thinkingLevel: undefined, warning: undefined };\n\t}\n\n\t// No match - try splitting on last colon if present\n\tconst lastColonIndex = pattern.lastIndexOf(\":\");\n\tif (lastColonIndex === -1) {\n\t\t// No colons, pattern simply doesn't match any model\n\t\treturn { model: undefined, thinkingLevel: undefined, warning: undefined };\n\t}\n\n\tconst prefix = pattern.substring(0, lastColonIndex);\n\tconst suffix = pattern.substring(lastColonIndex + 1);\n\n\tif (isValidThinkingLevel(suffix)) {\n\t\t// Valid thinking level - recurse on prefix and use this level\n\t\tconst result = parseModelPattern(prefix, availableModels, options);\n\t\tif (result.model) {\n\t\t\t// Only use this thinking level if no warning from inner recursion\n\t\t\treturn {\n\t\t\t\tmodel: result.model,\n\t\t\t\tthinkingLevel: result.warning ? undefined : suffix,\n\t\t\t\twarning: result.warning,\n\t\t\t};\n\t\t}\n\t\treturn result;\n\t} else {\n\t\t// Invalid suffix\n\t\tconst allowFallback = options?.allowInvalidThinkingLevelFallback ?? true;\n\t\tif (!allowFallback) {\n\t\t\t// In strict mode (CLI --model parsing), treat it as part of the model id and fail.\n\t\t\t// This avoids accidentally resolving to a different model.\n\t\t\treturn { model: undefined, thinkingLevel: undefined, warning: undefined };\n\t\t}\n\n\t\t// Scope mode: recurse on prefix and warn\n\t\tconst result = parseModelPattern(prefix, availableModels, options);\n\t\tif (result.model) {\n\t\t\treturn {\n\t\t\t\tmodel: result.model,\n\t\t\t\tthinkingLevel: undefined,\n\t\t\t\twarning: `Invalid thinking level \"${suffix}\" in pattern \"${pattern}\". Using default instead.`,\n\t\t\t};\n\t\t}\n\t\treturn result;\n\t}\n}\n\n/**\n * Resolve model patterns to actual Model objects with optional thinking levels\n * Format: \"pattern:level\" where :level is optional\n * For each pattern, finds all matching models and picks the best version:\n * 1. Prefer alias (e.g., claude-sonnet-4-5) over dated versions (claude-sonnet-4-5-20250929)\n * 2. If no alias, pick the latest dated version\n *\n * Supports models with colons in their IDs (e.g., OpenRouter's model:exacto).\n * The algorithm tries to match the full pattern first, then progressively\n * strips colon-suffixes to find a match.\n */\nexport interface ModelScopeDiagnostic {\n\ttype: \"warning\";\n\tcode: \"no-match\" | \"invalid-thinking-level\";\n\tmessage: string;\n\tpattern: string;\n}\n\nexport interface ResolveModelScopeResult {\n\tscopedModels: ScopedModel[];\n\tdiagnostics: ModelScopeDiagnostic[];\n}\n\nexport function resolveModelScopeFromModels(\n\tpatterns: string[],\n\tmodels: readonly Model<Api>[],\n): ResolveModelScopeResult {\n\tconst availableModels = [...models];\n\tconst scopedModels: ScopedModel[] = [];\n\tconst diagnostics: ModelScopeDiagnostic[] = [];\n\n\tfor (const pattern of patterns) {\n\t\t// Check if pattern contains glob characters\n\t\tif (pattern.includes(\"*\") || pattern.includes(\"?\") || pattern.includes(\"[\")) {\n\t\t\t// Extract optional thinking level suffix (e.g., \"provider/*:high\")\n\t\t\tconst colonIdx = pattern.lastIndexOf(\":\");\n\t\t\tlet globPattern = pattern;\n\t\t\tlet thinkingLevel: ThinkingLevel | undefined;\n\n\t\t\tif (colonIdx !== -1) {\n\t\t\t\tconst suffix = pattern.substring(colonIdx + 1);\n\t\t\t\tif (isValidThinkingLevel(suffix)) {\n\t\t\t\t\tthinkingLevel = suffix;\n\t\t\t\t\tglobPattern = pattern.substring(0, colonIdx);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tconst exactMatch = findExactModelReferenceMatch(globPattern, availableModels);\n\t\t\tif (exactMatch) {\n\t\t\t\tif (!scopedModels.find((sm) => modelsAreEqual(sm.model, exactMatch))) {\n\t\t\t\t\tscopedModels.push({ model: exactMatch, thinkingLevel });\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Match against \"provider/modelId\" format OR just model ID\n\t\t\t// This allows \"*sonnet*\" to match without requiring \"anthropic/*sonnet*\"\n\t\t\tconst matchingModels = availableModels.filter((m) => {\n\t\t\t\tconst fullId = `${m.provider}/${m.id}`;\n\t\t\t\treturn minimatch(fullId, globPattern, { nocase: true }) || minimatch(m.id, globPattern, { nocase: true });\n\t\t\t});\n\n\t\t\tif (matchingModels.length === 0) {\n\t\t\t\tdiagnostics.push({\n\t\t\t\t\ttype: \"warning\",\n\t\t\t\t\tcode: \"no-match\",\n\t\t\t\t\tmessage: `No models match pattern \"${pattern}\"`,\n\t\t\t\t\tpattern,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tfor (const model of matchingModels) {\n\t\t\t\tif (!scopedModels.find((sm) => modelsAreEqual(sm.model, model))) {\n\t\t\t\t\tscopedModels.push({ model, thinkingLevel });\n\t\t\t\t}\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst { model, thinkingLevel, warning } = parseModelPattern(pattern, availableModels);\n\n\t\tif (warning) {\n\t\t\tdiagnostics.push({ type: \"warning\", code: \"invalid-thinking-level\", message: warning, pattern });\n\t\t}\n\n\t\tif (!model) {\n\t\t\tdiagnostics.push({\n\t\t\t\ttype: \"warning\",\n\t\t\t\tcode: \"no-match\",\n\t\t\t\tmessage: `No models match pattern \"${pattern}\"`,\n\t\t\t\tpattern,\n\t\t\t});\n\t\t\tcontinue;\n\t\t}\n\n\t\t// Avoid duplicates\n\t\tif (!scopedModels.find((sm) => modelsAreEqual(sm.model, model))) {\n\t\t\tscopedModels.push({ model, thinkingLevel });\n\t\t}\n\t}\n\n\treturn { scopedModels, diagnostics };\n}\n\nexport async function resolveModelScopeWithDiagnostics(\n\tpatterns: string[],\n\tmodelRuntime: ModelRuntime,\n\toptions?: AuthOperationOptions,\n): Promise<ResolveModelScopeResult> {\n\treturn resolveModelScopeFromModels(patterns, await modelRuntime.getAvailable(undefined, options));\n}\n\nexport async function resolveModelScope(\n\tpatterns: string[],\n\tmodelRuntime: ModelRuntime,\n\toptions?: AuthOperationOptions,\n): Promise<ScopedModel[]> {\n\tconst { scopedModels, diagnostics } = await resolveModelScopeWithDiagnostics(patterns, modelRuntime, options);\n\tfor (const diagnostic of diagnostics) {\n\t\tconsole.warn(chalk.yellow(`Warning: ${diagnostic.message}`));\n\t}\n\treturn scopedModels;\n}\n\nexport interface ResolveCliModelResult {\n\tmodel: Model<Api> | undefined;\n\tthinkingLevel?: ThinkingLevel;\n\twarning: string | undefined;\n\t/**\n\t * Error message suitable for CLI display.\n\t * When set, model will be undefined.\n\t */\n\terror: string | undefined;\n}\n\n/**\n * Resolve a single model from CLI flags.\n *\n * Supports:\n * - --provider <provider> --model <pattern>\n * - --model <provider>/<pattern>\n * - Fuzzy matching (same rules as model scoping: exact id, then partial id/name)\n *\n * Note: This does not apply the thinking level by itself, but it may *parse* and\n * return a thinking level from \"<pattern>:<thinking>\" so the caller can apply it.\n */\nexport function resolveCliModel(options: {\n\tcliProvider?: string;\n\tcliModel?: string;\n\tcliThinking?: ThinkingLevel;\n\tmodelRuntime: ModelRuntime;\n}): ResolveCliModelResult {\n\tconst { cliProvider, cliModel, cliThinking, modelRuntime } = options;\n\n\tif (!cliModel) {\n\t\treturn { model: undefined, warning: undefined, error: undefined };\n\t}\n\n\t// Important: use *all* models here, not just models with pre-configured auth.\n\t// This allows \"--api-key\" to be used for first-time setup.\n\tconst availableModels = [...modelRuntime.getModels()];\n\tif (availableModels.length === 0) {\n\t\treturn {\n\t\t\tmodel: undefined,\n\t\t\twarning: undefined,\n\t\t\terror: \"No models available. Check your installation or add models to models.json.\",\n\t\t};\n\t}\n\n\t// Build canonical provider lookup (case-insensitive)\n\tconst providerMap = new Map<string, string>();\n\tfor (const m of availableModels) {\n\t\tproviderMap.set(m.provider.toLowerCase(), m.provider);\n\t}\n\n\tlet provider = cliProvider ? providerMap.get(cliProvider.toLowerCase()) : undefined;\n\tif (cliProvider && !provider) {\n\t\treturn {\n\t\t\tmodel: undefined,\n\t\t\twarning: undefined,\n\t\t\terror: `Unknown provider \"${cliProvider}\". Use --list-models to see available providers/models.`,\n\t\t};\n\t}\n\n\t// If no explicit --provider, try to interpret \"provider/model\" format first.\n\t// When the prefix before the first slash matches a known provider, prefer that\n\t// interpretation over matching models whose IDs literally contain slashes\n\t// (e.g. \"zai/glm-5\" should resolve to provider=zai, model=glm-5, not to a\n\t// vercel-ai-gateway model with id \"zai/glm-5\").\n\tlet pattern = cliModel;\n\tlet inferredProvider = false;\n\n\tif (!provider) {\n\t\tconst slashIndex = cliModel.indexOf(\"/\");\n\t\tif (slashIndex !== -1) {\n\t\t\tconst maybeProvider = cliModel.substring(0, slashIndex);\n\t\t\tconst canonical = providerMap.get(maybeProvider.toLowerCase());\n\t\t\tif (canonical) {\n\t\t\t\tprovider = canonical;\n\t\t\t\tpattern = cliModel.substring(slashIndex + 1);\n\t\t\t\tinferredProvider = true;\n\t\t\t}\n\t\t}\n\t}\n\n\t// If no provider was inferred from the slash, try exact matches without provider inference.\n\t// This handles models whose IDs naturally contain slashes (e.g. OpenRouter-style IDs).\n\t// Bare exact IDs can exist in multiple providers, so do not choose by catalog order.\n\t// Prefer the sole authenticated provider when there is one; otherwise require an\n\t// explicit provider to avoid silently selecting an unusable provider.\n\tif (!provider) {\n\t\tconst lower = cliModel.toLowerCase();\n\t\tconst exactMatches = availableModels.filter(\n\t\t\t(m) => m.id.toLowerCase() === lower || `${m.provider}/${m.id}`.toLowerCase() === lower,\n\t\t);\n\t\tif (exactMatches.length === 1) {\n\t\t\treturn { model: exactMatches[0], warning: undefined, thinkingLevel: undefined, error: undefined };\n\t\t}\n\t\tif (exactMatches.length > 1) {\n\t\t\tconst authenticatedExactMatches = exactMatches.filter((m) => modelRuntime.hasConfiguredAuth(m.provider));\n\t\t\tif (authenticatedExactMatches.length === 1) {\n\t\t\t\treturn {\n\t\t\t\t\tmodel: authenticatedExactMatches[0],\n\t\t\t\t\twarning: undefined,\n\t\t\t\t\tthinkingLevel: undefined,\n\t\t\t\t\terror: undefined,\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tconst matches = exactMatches\n\t\t\t\t.map((m) => `${m.provider}/${m.id}`)\n\t\t\t\t.sort((a, b) => a.localeCompare(b))\n\t\t\t\t.join(\", \");\n\t\t\tconst authHint =\n\t\t\t\tauthenticatedExactMatches.length === 0\n\t\t\t\t\t? \"No matching provider is authenticated.\"\n\t\t\t\t\t: \"More than one matching provider is authenticated.\";\n\t\t\treturn {\n\t\t\t\tmodel: undefined,\n\t\t\t\twarning: undefined,\n\t\t\t\tthinkingLevel: undefined,\n\t\t\t\terror: `Model \"${cliModel}\" is ambiguous across providers: ${matches}. ${authHint} Use --provider or provider/model.`,\n\t\t\t};\n\t\t}\n\t}\n\n\tif (cliProvider && provider) {\n\t\t// If both were provided, tolerate --model <provider>/<pattern> by stripping the provider prefix\n\t\tconst prefix = `${provider}/`;\n\t\tif (cliModel.toLowerCase().startsWith(prefix.toLowerCase())) {\n\t\t\tpattern = cliModel.substring(prefix.length);\n\t\t}\n\t}\n\n\tconst candidates = provider ? availableModels.filter((m) => m.provider === provider) : availableModels;\n\tconst { model, thinkingLevel, warning } = parseModelPattern(pattern, candidates, {\n\t\tallowInvalidThinkingLevelFallback: false,\n\t});\n\n\tif (model) {\n\t\t// If provider inference matched an unauthenticated provider/model pair, prefer\n\t\t// one exact raw model-id match that is authenticated. This keeps\n\t\t// \"provider/model\" syntax preferred when usable, but handles models whose\n\t\t// literal id starts with a known provider name (for example\n\t\t// commandcode model id \"xiaomi/mimo-v2.5-pro\").\n\t\tif (inferredProvider) {\n\t\t\tconst rawExactMatches = availableModels.filter(\n\t\t\t\t(m) => m.id.toLowerCase() === cliModel.toLowerCase() && !modelsAreEqual(m, model),\n\t\t\t);\n\t\t\tif (rawExactMatches.length > 0 && !modelRuntime.hasConfiguredAuth(model.provider)) {\n\t\t\t\tconst authenticatedRawMatches = rawExactMatches.filter((m) => modelRuntime.hasConfiguredAuth(m.provider));\n\t\t\t\tif (authenticatedRawMatches.length === 1) {\n\t\t\t\t\treturn {\n\t\t\t\t\t\tmodel: authenticatedRawMatches[0],\n\t\t\t\t\t\tthinkingLevel: undefined,\n\t\t\t\t\t\twarning: undefined,\n\t\t\t\t\t\terror: undefined,\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn { model, thinkingLevel, warning, error: undefined };\n\t}\n\n\t// If we inferred a provider from the slash but found no match within that provider,\n\t// fall back to matching the full input as a raw model id across all models.\n\t// This handles OpenRouter-style IDs like \"openai/gpt-4o:extended\" where \"openai\"\n\t// looks like a provider but the full string is actually a model id on openrouter.\n\tif (inferredProvider) {\n\t\tconst lower = cliModel.toLowerCase();\n\t\tconst exact = availableModels.find(\n\t\t\t(m) => m.id.toLowerCase() === lower || `${m.provider}/${m.id}`.toLowerCase() === lower,\n\t\t);\n\t\tif (exact) {\n\t\t\treturn { model: exact, warning: undefined, thinkingLevel: undefined, error: undefined };\n\t\t}\n\t\t// Also try parseModelPattern on the full input against all models\n\t\tconst fallback = parseModelPattern(cliModel, availableModels, {\n\t\t\tallowInvalidThinkingLevelFallback: false,\n\t\t});\n\t\tif (fallback.model) {\n\t\t\treturn {\n\t\t\t\tmodel: fallback.model,\n\t\t\t\tthinkingLevel: fallback.thinkingLevel,\n\t\t\t\twarning: fallback.warning,\n\t\t\t\terror: undefined,\n\t\t\t};\n\t\t}\n\t}\n\n\tif (provider) {\n\t\t// Parse thinking level suffix from the pattern before building the fallback model,\n\t\t// but only when --thinking is not explicitly provided.\n\t\t// e.g. \"zai-org/GLM-5.1-FP8:high\" → modelId=\"zai-org/GLM-5.1-FP8\", fallbackThinking=\"high\"\n\t\tlet fallbackPattern = pattern;\n\t\tlet fallbackThinking: ThinkingLevel | undefined;\n\t\tif (!cliThinking) {\n\t\t\tconst lastColon = pattern.lastIndexOf(\":\");\n\t\t\tif (lastColon !== -1) {\n\t\t\t\tconst suffix = pattern.substring(lastColon + 1);\n\t\t\t\tif (isValidThinkingLevel(suffix)) {\n\t\t\t\t\tfallbackPattern = pattern.substring(0, lastColon);\n\t\t\t\t\tfallbackThinking = suffix;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tconst fallbackModel = buildFallbackModel(provider, fallbackPattern, availableModels);\n\t\tif (fallbackModel) {\n\t\t\tconst requestedThinking = cliThinking ?? fallbackThinking;\n\t\t\tconst model =\n\t\t\t\trequestedThinking && requestedThinking !== \"off\" ? { ...fallbackModel, reasoning: true } : fallbackModel;\n\t\t\tconst fallbackWarning = warning\n\t\t\t\t? `${warning} Model \"${fallbackPattern}\" not found for provider \"${provider}\". Using custom model id.`\n\t\t\t\t: `Model \"${fallbackPattern}\" not found for provider \"${provider}\". Using custom model id.`;\n\t\t\treturn { model, thinkingLevel: fallbackThinking, warning: fallbackWarning, error: undefined };\n\t\t}\n\t}\n\n\tconst display = provider ? `${provider}/${pattern}` : cliModel;\n\treturn {\n\t\tmodel: undefined,\n\t\tthinkingLevel: undefined,\n\t\twarning,\n\t\terror: `Model \"${display}\" not found. Use --list-models to see available models.`,\n\t};\n}\n\nexport interface InitialModelResult {\n\tmodel: Model<Api> | undefined;\n\tthinkingLevel: ThinkingLevel;\n\tfallbackMessage: string | undefined;\n}\n\n/**\n * Find the initial model to use based on priority:\n * 1. CLI args (provider + model)\n * 2. First model from scoped models (if not continuing/resuming)\n * 3. Restored from session (if continuing/resuming)\n * 4. Saved default from settings\n * 5. First available model with valid API key\n */\nexport async function findInitialModel(options: {\n\tcliProvider?: string;\n\tcliModel?: string;\n\tscopedModels: ScopedModel[];\n\tisContinuing: boolean;\n\tdefaultProvider?: string;\n\tdefaultModelId?: string;\n\tdefaultThinkingLevel?: ThinkingLevel;\n\tmodelThinkingLevels?: Record<string, ThinkingLevel>;\n\tmodelRuntime: ModelRuntime;\n}): Promise<InitialModelResult> {\n\tconst {\n\t\tcliProvider,\n\t\tcliModel,\n\t\tscopedModels,\n\t\tisContinuing,\n\t\tdefaultProvider,\n\t\tdefaultModelId,\n\t\tdefaultThinkingLevel,\n\t\tmodelThinkingLevels,\n\t\tmodelRuntime,\n\t} = options;\n\n\tlet model: Model<Api> | undefined;\n\tlet thinkingLevel: ThinkingLevel = DEFAULT_THINKING_LEVEL;\n\n\t// 1. CLI args take priority\n\tif (cliProvider && cliModel) {\n\t\tconst resolved = resolveCliModel({\n\t\t\tcliProvider,\n\t\t\tcliModel,\n\t\t\tmodelRuntime,\n\t\t});\n\t\t// v8 ignore next -- CLI 模型解析失败即退出进程,测试无法安全触达 process.exit(1)\n\t\tif (resolved.error) {\n\t\t\tconsole.error(chalk.red(resolved.error));\n\t\t\tprocess.exit(1);\n\t\t}\n\t\tif (resolved.model) {\n\t\t\treturn { model: resolved.model, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n\t\t}\n\t}\n\n\t// 2. Use first model from scoped models (skip if continuing/resuming)\n\tif (scopedModels.length > 0 && !isContinuing) {\n\t\tconst scopedModel = scopedModels[0];\n\t\tconst perModel = modelThinkingLevels?.[`${scopedModel.model.provider}/${scopedModel.model.id}`];\n\t\treturn {\n\t\t\tmodel: scopedModel.model,\n\t\t\tthinkingLevel: scopedModel.thinkingLevel ?? perModel ?? defaultThinkingLevel ?? DEFAULT_THINKING_LEVEL,\n\t\t\tfallbackMessage: undefined,\n\t\t};\n\t}\n\n\t// 3. Try saved default from settings if auth is configured.\n\tif (defaultProvider && defaultModelId) {\n\t\tconst found = modelRuntime.getModel(defaultProvider, defaultModelId);\n\t\tif (found && modelRuntime.hasConfiguredAuth(found.provider)) {\n\t\t\tmodel = found;\n\t\t\tconst perModel = modelThinkingLevels?.[`${defaultProvider}/${defaultModelId}`];\n\t\t\tif (perModel) {\n\t\t\t\tthinkingLevel = perModel;\n\t\t\t} else if (defaultThinkingLevel) {\n\t\t\t\tthinkingLevel = defaultThinkingLevel;\n\t\t\t}\n\t\t\treturn { model, thinkingLevel, fallbackMessage: undefined };\n\t\t}\n\t}\n\n\t// 4. Try first available model with valid API key\n\tconst availableModels = [...modelRuntime.getAvailableSnapshot()];\n\n\tif (availableModels.length > 0) {\n\t\t// Try to find a default model from known providers\n\t\tfor (const provider of Object.keys(defaultModelPerProvider) as KnownProvider[]) {\n\t\t\tconst defaultId = defaultModelPerProvider[provider];\n\t\t\tconst match = availableModels.find((m) => m.provider === provider && m.id === defaultId);\n\t\t\tif (match) {\n\t\t\t\treturn { model: match, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n\t\t\t}\n\t\t}\n\n\t\t// If no default found, use first available\n\t\treturn { model: availableModels[0], thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n\t}\n\n\t// 5. No model found\n\treturn { model: undefined, thinkingLevel: DEFAULT_THINKING_LEVEL, fallbackMessage: undefined };\n}\n\n/**\n * Restore model from session, with fallback to available models\n */\nexport async function restoreModelFromSession(\n\tsavedProvider: string,\n\tsavedModelId: string,\n\tcurrentModel: Model<Api> | undefined,\n\tshouldPrintMessages: boolean,\n\tmodelRuntime: ModelRuntime,\n): Promise<{ model: Model<Api> | undefined; fallbackMessage: string | undefined }> {\n\tconst restoredModel = modelRuntime.getModel(savedProvider, savedModelId);\n\n\t// Check if restored model exists and still has auth configured\n\tconst hasConfiguredAuth = restoredModel ? modelRuntime.hasConfiguredAuth(restoredModel.provider) : false;\n\n\tif (restoredModel && hasConfiguredAuth) {\n\t\tif (shouldPrintMessages) {\n\t\t\tconsole.log(chalk.dim(`Restored model: ${savedProvider}/${savedModelId}`));\n\t\t}\n\t\treturn { model: restoredModel, fallbackMessage: undefined };\n\t}\n\n\t// Model not found or no API key - fall back\n\tconst reason = !restoredModel ? \"model no longer exists\" : \"no auth configured\";\n\n\tif (shouldPrintMessages) {\n\t\tconsole.error(chalk.yellow(`Warning: Could not restore model ${savedProvider}/${savedModelId} (${reason}).`));\n\t}\n\n\t// If we already have a model, use it as fallback\n\tif (currentModel) {\n\t\tif (shouldPrintMessages) {\n\t\t\tconsole.log(chalk.dim(`Falling back to: ${currentModel.provider}/${currentModel.id}`));\n\t\t}\n\t\treturn {\n\t\t\tmodel: currentModel,\n\t\t\tfallbackMessage: `Could not restore model ${savedProvider}/${savedModelId} (${reason}). Using ${currentModel.provider}/${currentModel.id}.`,\n\t\t};\n\t}\n\n\t// Try to find any available model\n\tconst availableModels = [...modelRuntime.getAvailableSnapshot()];\n\n\tif (availableModels.length > 0) {\n\t\t// Try to find a default model from known providers\n\t\tlet fallbackModel: Model<Api> | undefined;\n\t\tfor (const provider of Object.keys(defaultModelPerProvider) as KnownProvider[]) {\n\t\t\tconst defaultId = defaultModelPerProvider[provider];\n\t\t\tconst match = availableModels.find((m) => m.provider === provider && m.id === defaultId);\n\t\t\tif (match) {\n\t\t\t\tfallbackModel = match;\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\t// If no default found, use first available\n\t\tif (!fallbackModel) {\n\t\t\tfallbackModel = availableModels[0];\n\t\t}\n\n\t\tif (shouldPrintMessages) {\n\t\t\tconsole.log(chalk.dim(`Falling back to: ${fallbackModel.provider}/${fallbackModel.id}`));\n\t\t}\n\n\t\treturn {\n\t\t\tmodel: fallbackModel,\n\t\t\tfallbackMessage: `Could not restore model ${savedProvider}/${savedModelId} (${reason}). Using ${fallbackModel.provider}/${fallbackModel.id}.`,\n\t\t};\n\t}\n\n\t// No models available\n\treturn { model: undefined, fallbackMessage: undefined };\n}\n"]}
@@ -4,8 +4,11 @@
4
4
  import { modelsAreEqual } from "@agent-forge/ai";
5
5
  import chalk from "chalk";
6
6
  import { minimatch } from "minimatch";
7
- import { isValidThinkingLevel } from "../cli/args.js";
8
7
  import { DEFAULT_THINKING_LEVEL } from "./defaults.js";
8
+ export const VALID_THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
9
+ export function isValidThinkingLevel(level) {
10
+ return VALID_THINKING_LEVELS.includes(level);
11
+ }
9
12
  /** Default model IDs for each known provider */
10
13
  export const defaultModelPerProvider = {
11
14
  "amazon-bedrock": "us.anthropic.claude-opus-4-6-v1",