@ai-agent-forge/agent-forge 0.86.4 → 0.86.5

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 (220) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/dist/bundle/.build-manifest.json +470 -404
  3. package/dist/bundle/chunks/anthropic-messages-ALDZBUKI.js +6 -0
  4. package/dist/bundle/chunks/anthropic.js +2 -2
  5. package/dist/bundle/chunks/{azure-openai-responses-WQCZWFAH.js → azure-openai-responses-A2WJWZFB.js} +1 -1
  6. package/dist/bundle/chunks/bedrock-converse-stream.js +1 -1
  7. package/dist/bundle/chunks/chunk-A7GUOX2H.js +141 -0
  8. package/dist/bundle/chunks/{chunk-WGLBM2BP.js → chunk-CIX3FSBK.js} +1 -1
  9. package/dist/bundle/chunks/{chunk-ZV3W36HK.js → chunk-EALJ5DDX.js} +99 -92
  10. package/dist/bundle/chunks/chunk-OO6DJ3CL.js +31 -0
  11. package/dist/bundle/chunks/{chunk-PE3XUHPT.js → chunk-SQFG22WN.js} +1 -1
  12. package/dist/bundle/chunks/{chunk-V46XUTK3.js → chunk-Y7HXTASS.js} +1 -1
  13. package/dist/bundle/chunks/{chunk-3WE3W52L.js → chunk-YJCQVXW5.js} +1 -1
  14. package/dist/bundle/chunks/github-copilot.js +1 -1
  15. package/dist/bundle/chunks/{google-generative-ai-LQ375GYC.js → google-generative-ai-NIB4WONV.js} +1 -1
  16. package/dist/bundle/chunks/{google-vertex-HXSRAKEZ.js → google-vertex-DCPYUEUO.js} +1 -1
  17. package/dist/bundle/chunks/{mistral-conversations-CSNMFR4J.js → mistral-conversations-OC6LA5XL.js} +1 -1
  18. package/dist/bundle/chunks/{openai-codex-responses-YDJSZOIH.js → openai-codex-responses-IO2X4Y7L.js} +1 -1
  19. package/dist/bundle/chunks/openai-codex.js +2 -2
  20. package/dist/bundle/chunks/{openai-completions-UPRWTQPT.js → openai-completions-XYQQHETU.js} +1 -1
  21. package/dist/bundle/chunks/{openai-responses-O63W6HQ3.js → openai-responses-DLIRN3CI.js} +1 -1
  22. package/dist/bundle/chunks/{openrouter-images-G3GT5BVT.js → openrouter-images-G4GQRUSG.js} +1 -1
  23. package/dist/bundle/chunks/openrouter.js +2 -2
  24. package/dist/bundle/chunks/{pi-messages-SLF355GF.js → pi-messages-E6RRYBO7.js} +1 -1
  25. package/dist/bundle/chunks/radius.js +2 -2
  26. package/dist/bundle/chunks/{virtual-modules-O72ICTMQ.js → virtual-modules-3IZ4MYSQ.js} +1 -1
  27. package/dist/bundle/cli.js +1 -1
  28. package/dist/bundle/index.js +1 -1
  29. package/dist/bundle/rpc-entry.js +1 -1
  30. package/dist/capabilities/builtin.d.ts +4 -2
  31. package/dist/capabilities/builtin.d.ts.map +1 -1
  32. package/dist/capabilities/builtin.js +5 -1
  33. package/dist/capabilities/builtin.js.map +1 -1
  34. package/dist/cli/plugin-command.d.ts.map +1 -1
  35. package/dist/cli/plugin-command.js +51 -5
  36. package/dist/cli/plugin-command.js.map +1 -1
  37. package/dist/core/agent-session-compaction.d.ts.map +1 -1
  38. package/dist/core/agent-session-compaction.js +13 -5
  39. package/dist/core/agent-session-compaction.js.map +1 -1
  40. package/dist/core/agent-session-internal.d.ts +2 -4
  41. package/dist/core/agent-session-internal.d.ts.map +1 -1
  42. package/dist/core/agent-session-internal.js.map +1 -1
  43. package/dist/core/agent-session-paths.d.ts +2 -0
  44. package/dist/core/agent-session-paths.d.ts.map +1 -1
  45. package/dist/core/agent-session-paths.js +2 -1
  46. package/dist/core/agent-session-paths.js.map +1 -1
  47. package/dist/core/agent-session-projection.d.ts +10 -4
  48. package/dist/core/agent-session-projection.d.ts.map +1 -1
  49. package/dist/core/agent-session-projection.js +17 -4
  50. package/dist/core/agent-session-projection.js.map +1 -1
  51. package/dist/core/agent-session.d.ts +19 -5
  52. package/dist/core/agent-session.d.ts.map +1 -1
  53. package/dist/core/agent-session.js +30 -4
  54. package/dist/core/agent-session.js.map +1 -1
  55. package/dist/core/extensions/bootstrap-lifecycle.d.ts +1 -1
  56. package/dist/core/extensions/bootstrap-lifecycle.d.ts.map +1 -1
  57. package/dist/core/extensions/bootstrap-lifecycle.js +5 -2
  58. package/dist/core/extensions/bootstrap-lifecycle.js.map +1 -1
  59. package/dist/core/extensions/capability-runtime-store.d.ts.map +1 -1
  60. package/dist/core/extensions/capability-runtime-store.js +1 -0
  61. package/dist/core/extensions/capability-runtime-store.js.map +1 -1
  62. package/dist/core/extensions/capability-runtime-types.d.ts +16 -1
  63. package/dist/core/extensions/capability-runtime-types.d.ts.map +1 -1
  64. package/dist/core/extensions/capability-runtime-types.js.map +1 -1
  65. package/dist/core/extensions/capability-runtime.d.ts.map +1 -1
  66. package/dist/core/extensions/capability-runtime.js +38 -2
  67. package/dist/core/extensions/capability-runtime.js.map +1 -1
  68. package/dist/core/extensions/index.d.ts +1 -1
  69. package/dist/core/extensions/index.d.ts.map +1 -1
  70. package/dist/core/extensions/index.js.map +1 -1
  71. package/dist/core/extensions/lifecycle-catalog.d.ts +46 -0
  72. package/dist/core/extensions/lifecycle-catalog.d.ts.map +1 -1
  73. package/dist/core/extensions/lifecycle-catalog.js +101 -0
  74. package/dist/core/extensions/lifecycle-catalog.js.map +1 -1
  75. package/dist/core/extensions/provider-failover.d.ts +106 -0
  76. package/dist/core/extensions/provider-failover.d.ts.map +1 -0
  77. package/dist/core/extensions/provider-failover.js +692 -0
  78. package/dist/core/extensions/provider-failover.js.map +1 -0
  79. package/dist/core/facade/coding-agent-facade.d.ts +13 -6
  80. package/dist/core/facade/coding-agent-facade.d.ts.map +1 -1
  81. package/dist/core/facade/coding-agent-facade.js +3 -1
  82. package/dist/core/facade/coding-agent-facade.js.map +1 -1
  83. package/dist/core/keybindings.d.ts +6 -6
  84. package/dist/core/keybindings.d.ts.map +1 -1
  85. package/dist/core/keybindings.js +23 -6
  86. package/dist/core/keybindings.js.map +1 -1
  87. package/dist/core/model-config.d.ts +102 -0
  88. package/dist/core/model-config.d.ts.map +1 -1
  89. package/dist/core/model-config.js +46 -14
  90. package/dist/core/model-config.js.map +1 -1
  91. package/dist/core/model-resolver.d.ts.map +1 -1
  92. package/dist/core/model-resolver.js +1 -1
  93. package/dist/core/model-resolver.js.map +1 -1
  94. package/dist/core/model-runtime.d.ts +15 -0
  95. package/dist/core/model-runtime.d.ts.map +1 -1
  96. package/dist/core/model-runtime.js +30 -18
  97. package/dist/core/model-runtime.js.map +1 -1
  98. package/dist/core/remote-catalog-provider.d.ts.map +1 -1
  99. package/dist/core/remote-catalog-provider.js +4 -9
  100. package/dist/core/remote-catalog-provider.js.map +1 -1
  101. package/dist/core/sdk.d.ts.map +1 -1
  102. package/dist/core/sdk.js +107 -24
  103. package/dist/core/sdk.js.map +1 -1
  104. package/dist/core/session-manager.d.ts +2 -0
  105. package/dist/core/session-manager.d.ts.map +1 -1
  106. package/dist/core/session-manager.js +10 -5
  107. package/dist/core/session-manager.js.map +1 -1
  108. package/dist/core/settings-manager.d.ts +71 -5
  109. package/dist/core/settings-manager.d.ts.map +1 -1
  110. package/dist/core/settings-manager.js +138 -9
  111. package/dist/core/settings-manager.js.map +1 -1
  112. package/dist/core/slash-commands.d.ts.map +1 -1
  113. package/dist/core/slash-commands.js +17 -2
  114. package/dist/core/slash-commands.js.map +1 -1
  115. package/dist/core/tools/render-utils.d.ts +6 -0
  116. package/dist/core/tools/render-utils.d.ts.map +1 -1
  117. package/dist/core/tools/render-utils.js +26 -0
  118. package/dist/core/tools/render-utils.js.map +1 -1
  119. package/dist/core/tools/tool-definition.d.ts +21 -2
  120. package/dist/core/tools/tool-definition.d.ts.map +1 -1
  121. package/dist/core/tools/tool-definition.js.map +1 -1
  122. package/dist/main.d.ts.map +1 -1
  123. package/dist/main.js +3 -6
  124. package/dist/main.js.map +1 -1
  125. package/dist/modes/interactive/components/agents-view.d.ts +57 -0
  126. package/dist/modes/interactive/components/agents-view.d.ts.map +1 -0
  127. package/dist/modes/interactive/components/agents-view.js +260 -0
  128. package/dist/modes/interactive/components/agents-view.js.map +1 -0
  129. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  130. package/dist/modes/interactive/components/custom-editor.js +2 -2
  131. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  132. package/dist/modes/interactive/components/footer.d.ts +7 -0
  133. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  134. package/dist/modes/interactive/components/footer.js +51 -6
  135. package/dist/modes/interactive/components/footer.js.map +1 -1
  136. package/dist/modes/interactive/components/scoped-models-selector.d.ts +1 -1
  137. package/dist/modes/interactive/components/scoped-models-selector.d.ts.map +1 -1
  138. package/dist/modes/interactive/components/scoped-models-selector.js +1 -1
  139. package/dist/modes/interactive/components/scoped-models-selector.js.map +1 -1
  140. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  141. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  142. package/dist/modes/interactive/components/settings-selector.js +12 -2
  143. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  144. package/dist/modes/interactive/components/thinking-selector.d.ts.map +1 -1
  145. package/dist/modes/interactive/components/thinking-selector.js +1 -1
  146. package/dist/modes/interactive/components/thinking-selector.js.map +1 -1
  147. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  148. package/dist/modes/interactive/components/tool-execution.js +89 -10
  149. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  150. package/dist/modes/interactive/components/user-message-selector.d.ts +3 -0
  151. package/dist/modes/interactive/components/user-message-selector.d.ts.map +1 -1
  152. package/dist/modes/interactive/components/user-message-selector.js +9 -3
  153. package/dist/modes/interactive/components/user-message-selector.js.map +1 -1
  154. package/dist/modes/interactive/components/workflow-view.d.ts +119 -0
  155. package/dist/modes/interactive/components/workflow-view.d.ts.map +1 -0
  156. package/dist/modes/interactive/components/workflow-view.js +638 -0
  157. package/dist/modes/interactive/components/workflow-view.js.map +1 -0
  158. package/dist/modes/interactive/interactive-commands.d.ts +22 -0
  159. package/dist/modes/interactive/interactive-commands.d.ts.map +1 -1
  160. package/dist/modes/interactive/interactive-commands.js +56 -0
  161. package/dist/modes/interactive/interactive-commands.js.map +1 -1
  162. package/dist/modes/interactive/interactive-mode.d.ts +51 -1
  163. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  164. package/dist/modes/interactive/interactive-mode.js +218 -37
  165. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  166. package/dist/modes/interactive/interactive-selectors.d.ts +2 -4
  167. package/dist/modes/interactive/interactive-selectors.d.ts.map +1 -1
  168. package/dist/modes/interactive/interactive-selectors.js +10 -1
  169. package/dist/modes/interactive/interactive-selectors.js.map +1 -1
  170. package/dist/modes/print-mode.d.ts.map +1 -1
  171. package/dist/modes/print-mode.js +5 -0
  172. package/dist/modes/print-mode.js.map +1 -1
  173. package/dist/modes/rpc/rpc-client.d.ts +3 -1
  174. package/dist/modes/rpc/rpc-client.d.ts.map +1 -1
  175. package/dist/modes/rpc/rpc-client.js +4 -2
  176. package/dist/modes/rpc/rpc-client.js.map +1 -1
  177. package/dist/modes/rpc/rpc-types.d.ts +1 -0
  178. package/dist/modes/rpc/rpc-types.d.ts.map +1 -1
  179. package/dist/modes/rpc/rpc-types.js.map +1 -1
  180. package/dist/plugins/ecosystem/bootstrap-factory-manifest.d.ts.map +1 -1
  181. package/dist/plugins/ecosystem/bootstrap-factory-manifest.js +7 -0
  182. package/dist/plugins/ecosystem/bootstrap-factory-manifest.js.map +1 -1
  183. package/dist/plugins/ecosystem/cli.d.ts.map +1 -1
  184. package/dist/plugins/ecosystem/cli.js +1 -1
  185. package/dist/plugins/ecosystem/cli.js.map +1 -1
  186. package/dist/plugins/ecosystem/install-store-paths.d.ts +15 -0
  187. package/dist/plugins/ecosystem/install-store-paths.d.ts.map +1 -0
  188. package/dist/plugins/ecosystem/install-store-paths.js +58 -0
  189. package/dist/plugins/ecosystem/install-store-paths.js.map +1 -0
  190. package/dist/plugins/ecosystem/node-disk-registry-source.d.ts.map +1 -1
  191. package/dist/plugins/ecosystem/node-disk-registry-source.js +3 -8
  192. package/dist/plugins/ecosystem/node-disk-registry-source.js.map +1 -1
  193. package/dist/plugins/ecosystem/node-package-install-host.d.ts.map +1 -1
  194. package/dist/plugins/ecosystem/node-package-install-host.js +9 -1
  195. package/dist/plugins/ecosystem/node-package-install-host.js.map +1 -1
  196. package/dist/plugins/ecosystem/node-package-install-persistence.d.ts.map +1 -1
  197. package/dist/plugins/ecosystem/node-package-install-persistence.js +3 -8
  198. package/dist/plugins/ecosystem/node-package-install-persistence.js.map +1 -1
  199. package/dist/profile/plugin-profiles.d.ts +2 -0
  200. package/dist/profile/plugin-profiles.d.ts.map +1 -1
  201. package/dist/profile/plugin-profiles.js +4 -0
  202. package/dist/profile/plugin-profiles.js.map +1 -1
  203. package/dist/profiles/builtin-suites.d.ts +19 -2
  204. package/dist/profiles/builtin-suites.d.ts.map +1 -1
  205. package/dist/profiles/builtin-suites.js +20 -2
  206. package/dist/profiles/builtin-suites.js.map +1 -1
  207. package/dist/profiles/suite-loader.d.ts.map +1 -1
  208. package/dist/profiles/suite-loader.js +4 -1
  209. package/dist/profiles/suite-loader.js.map +1 -1
  210. package/dist/utils/clipboard.d.ts.map +1 -1
  211. package/dist/utils/clipboard.js +10 -10
  212. package/dist/utils/clipboard.js.map +1 -1
  213. package/docs/keybindings.md +8 -8
  214. package/docs/models.md +1 -1
  215. package/docs/rpc.md +3 -1
  216. package/docs/settings.md +2 -1
  217. package/package.json +4 -4
  218. package/dist/bundle/chunks/anthropic-messages-EVFQ6MLR.js +0 -6
  219. package/dist/bundle/chunks/chunk-F6SBZUJG.js +0 -141
  220. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
@@ -104,6 +104,20 @@ const OpenAIResponsesCompatSchema = Type.Object({
104
104
  supportsToolSearch: Type.Optional(Type.Boolean()),
105
105
  supportsMaxOutputTokens: Type.Optional(Type.Boolean()),
106
106
  });
107
+ const ModelCostRatesSchema = {
108
+ input: Type.Number(),
109
+ output: Type.Number(),
110
+ cacheRead: Type.Number(),
111
+ cacheWrite: Type.Number(),
112
+ };
113
+ const ModelCostTierSchema = Type.Object({
114
+ inputTokensAbove: Type.Number(),
115
+ ...ModelCostRatesSchema,
116
+ });
117
+ const ModelCostSchema = Type.Object({
118
+ ...ModelCostRatesSchema,
119
+ tiers: Type.Optional(Type.Array(ModelCostTierSchema)),
120
+ });
107
121
  const AnthropicMessagesCompatSchema = Type.Object({
108
122
  supportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),
109
123
  supportsLongCacheRetention: Type.Optional(Type.Boolean()),
@@ -115,26 +129,17 @@ const AnthropicMessagesCompatSchema = Type.Object({
115
129
  supportsStrictTools: Type.Optional(Type.Boolean()),
116
130
  supportsMidConvoEffort: Type.Optional(Type.Boolean()),
117
131
  supportsToolReferences: Type.Optional(Type.Boolean()),
132
+ allowedFallbackModels: Type.Optional(Type.Array(Type.Object({
133
+ provider: Type.String({ minLength: 1 }),
134
+ model: Type.String({ minLength: 1 }),
135
+ cost: ModelCostSchema,
136
+ }), { maxItems: 3 })),
118
137
  });
119
138
  const ProviderCompatSchema = Type.Union([
120
139
  OpenAICompletionsCompatSchema,
121
140
  OpenAIResponsesCompatSchema,
122
141
  AnthropicMessagesCompatSchema,
123
142
  ]);
124
- const ModelCostRatesSchema = {
125
- input: Type.Number(),
126
- output: Type.Number(),
127
- cacheRead: Type.Number(),
128
- cacheWrite: Type.Number(),
129
- };
130
- const ModelCostTierSchema = Type.Object({
131
- inputTokensAbove: Type.Number(),
132
- ...ModelCostRatesSchema,
133
- });
134
- const ModelCostSchema = Type.Object({
135
- ...ModelCostRatesSchema,
136
- tiers: Type.Optional(Type.Array(ModelCostTierSchema)),
137
- });
138
143
  const ModelDefinitionSchema = Type.Object({
139
144
  id: Type.String({ minLength: 1 }),
140
145
  name: Type.Optional(Type.String({ minLength: 1 })),
@@ -143,6 +148,10 @@ const ModelDefinitionSchema = Type.Object({
143
148
  reasoning: Type.Optional(Type.Boolean()),
144
149
  thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
145
150
  input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
151
+ // 供应商能力槽位(设计 §3.1):语义与既有 ImagesModel.output 对齐,缺省 =
152
+ // 纯文本(undefined 视为 ["text"])。生图供应商在 models.json 登记
153
+ // "output": ["image"] 的模型即进入宿主注入的生图模型目录快照。
154
+ output: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
146
155
  cost: Type.Optional(ModelCostSchema),
147
156
  contextWindow: Type.Optional(Type.Number()),
148
157
  maxTokens: Type.Optional(Type.Number()),
@@ -155,6 +164,7 @@ const ModelOverrideSchema = Type.Object({
155
164
  reasoning: Type.Optional(Type.Boolean()),
156
165
  thinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),
157
166
  input: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
167
+ output: Type.Optional(Type.Array(Type.Union([Type.Literal("text"), Type.Literal("image")]))),
158
168
  cost: Type.Optional(Type.Object({
159
169
  input: Type.Optional(Type.Number()),
160
170
  output: Type.Optional(Type.Number()),
@@ -254,5 +264,27 @@ export class ModelConfig {
254
264
  getError() {
255
265
  return this.error;
256
266
  }
267
+ /**
268
+ * 生图模型目录快照(供应商能力槽位设计 §3.2 推断供料):models.json 中
269
+ * `output` 含 `image` 的模型按 provider 分组,供宿主在装配期经
270
+ * `configOverride` 注入 image-generation 插件(注入键 `imageModelCatalog`)。
271
+ * 快照为装配期静态数据;插件运行期按会话当前 provider 动态查询。内建
272
+ * 聊天目录不参与——内建 images 目录走 chat modalities 协议,与插件消费的
273
+ * `/images/generations` 端点协议不互通(设计 §3.2 第 4 层)。保持
274
+ * models.json 登记顺序(确定性来源);无生图模型的 provider 不出现在键集中。
275
+ */
276
+ getImageModelCatalog() {
277
+ const catalog = {};
278
+ for (const [providerId, provider] of this.providers) {
279
+ const imageModels = (provider.models ?? []).filter((model) => Array.isArray(model.output) && model.output.includes("image"));
280
+ if (imageModels.length === 0)
281
+ continue;
282
+ catalog[providerId] = imageModels.map((model) => ({
283
+ id: model.id,
284
+ ...(model.name === undefined ? {} : { name: model.name }),
285
+ }));
286
+ }
287
+ return deepFreeze(catalog);
288
+ }
257
289
  }
258
290
  //# sourceMappingURL=model-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"model-config.js","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"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","sourcesContent":["/** Immutable, credential-blind models.json snapshot. */\n\nimport { readFile } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { Compile } from \"typebox/compile\";\nimport type { TLocalizedValidationError } from \"typebox/error\";\nimport { stripJsonComments } from \"../utils/json.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport { stripBom } from \"../utils/text.ts\";\n\nconst PercentileCutoffsSchema = Type.Object({\n\tp50: Type.Optional(Type.Number()),\n\tp75: Type.Optional(Type.Number()),\n\tp90: Type.Optional(Type.Number()),\n\tp99: Type.Optional(Type.Number()),\n});\n\nconst OpenRouterRoutingSchema = Type.Object({\n\tallow_fallbacks: Type.Optional(Type.Boolean()),\n\trequire_parameters: Type.Optional(Type.Boolean()),\n\tdata_collection: Type.Optional(Type.Union([Type.Literal(\"deny\"), Type.Literal(\"allow\")])),\n\tzdr: Type.Optional(Type.Boolean()),\n\tenforce_distillable_text: Type.Optional(Type.Boolean()),\n\torder: Type.Optional(Type.Array(Type.String())),\n\tonly: Type.Optional(Type.Array(Type.String())),\n\tignore: Type.Optional(Type.Array(Type.String())),\n\tquantizations: Type.Optional(Type.Array(Type.String())),\n\tsort: Type.Optional(\n\t\tType.Union([\n\t\t\tType.String(),\n\t\t\tType.Object({\n\t\t\t\tby: Type.Optional(Type.String()),\n\t\t\t\tpartition: Type.Optional(Type.Union([Type.String(), Type.Null()])),\n\t\t\t}),\n\t\t]),\n\t),\n\tmax_price: Type.Optional(\n\t\tType.Object({\n\t\t\tprompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\tcompletion: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\timage: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\taudio: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\trequest: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t}),\n\t),\n\tpreferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n\tpreferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n});\n\nconst VercelGatewayRoutingSchema = Type.Object({\n\tonly: Type.Optional(Type.Array(Type.String())),\n\torder: Type.Optional(Type.Array(Type.String())),\n});\n\nconst ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);\nconst ThinkingLevelMapSchema = Type.Object({\n\toff: Type.Optional(ThinkingLevelMapValueSchema),\n\tminimal: Type.Optional(ThinkingLevelMapValueSchema),\n\tlow: Type.Optional(ThinkingLevelMapValueSchema),\n\tmedium: Type.Optional(ThinkingLevelMapValueSchema),\n\thigh: Type.Optional(ThinkingLevelMapValueSchema),\n\txhigh: Type.Optional(ThinkingLevelMapValueSchema),\n\tmax: Type.Optional(ThinkingLevelMapValueSchema),\n});\n\nconst ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]);\nconst ChatTemplateKwargVariableSchema = Type.Object({\n\t$var: Type.Union([Type.Literal(\"thinking.enabled\"), Type.Literal(\"thinking.effort\")]),\n\tomitWhenOff: Type.Optional(Type.Boolean()),\n});\nconst ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);\n\nconst OpenAICompletionsCompatSchema = Type.Object({\n\tsupportsStore: Type.Optional(Type.Boolean()),\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsupportsReasoningEffort: Type.Optional(Type.Boolean()),\n\tsupportsUsageInStreaming: Type.Optional(Type.Boolean()),\n\tsupportsFinishReason: Type.Optional(Type.Boolean()),\n\tmaxTokensField: Type.Optional(Type.Union([Type.Literal(\"max_completion_tokens\"), Type.Literal(\"max_tokens\")])),\n\trequiresToolResultName: Type.Optional(Type.Boolean()),\n\trequiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),\n\trequiresThinkingAsText: Type.Optional(Type.Boolean()),\n\trequiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),\n\tthinkingFormat: Type.Optional(\n\t\tType.Union([\n\t\t\tType.Literal(\"openai\"),\n\t\t\tType.Literal(\"openrouter\"),\n\t\t\tType.Literal(\"together\"),\n\t\t\tType.Literal(\"baseten\"),\n\t\t\tType.Literal(\"deepseek\"),\n\t\t\tType.Literal(\"zai\"),\n\t\t\tType.Literal(\"qwen\"),\n\t\t\tType.Literal(\"chat-template\"),\n\t\t\tType.Literal(\"qwen-chat-template\"),\n\t\t\tType.Literal(\"string-thinking\"),\n\t\t\tType.Literal(\"ant-ling\"),\n\t\t]),\n\t),\n\tchatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tchatTemplateArgs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tcacheControlFormat: Type.Optional(Type.Literal(\"anthropic\")),\n\topenRouterRouting: Type.Optional(OpenRouterRoutingSchema),\n\tvercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tdeferredToolsMode: Type.Optional(Type.Literal(\"kimi\")),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n});\n\nconst OpenAIResponsesCompatSchema = Type.Object({\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsAdditionalTools: Type.Optional(Type.Boolean()),\n\tsupportsToolSearch: Type.Optional(Type.Boolean()),\n\tsupportsMaxOutputTokens: Type.Optional(Type.Boolean()),\n});\n\nconst AnthropicMessagesCompatSchema = Type.Object({\n\tsupportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tsupportsCacheControlOnTools: Type.Optional(Type.Boolean()),\n\tsupportsTemperature: Type.Optional(Type.Boolean()),\n\tforceAdaptiveThinking: Type.Optional(Type.Boolean()),\n\tallowEmptySignature: Type.Optional(Type.Boolean()),\n\tsupportsStrictTools: Type.Optional(Type.Boolean()),\n\tsupportsMidConvoEffort: Type.Optional(Type.Boolean()),\n\tsupportsToolReferences: Type.Optional(Type.Boolean()),\n});\n\nconst ProviderCompatSchema = Type.Union([\n\tOpenAICompletionsCompatSchema,\n\tOpenAIResponsesCompatSchema,\n\tAnthropicMessagesCompatSchema,\n]);\n\nconst ModelCostRatesSchema = {\n\tinput: Type.Number(),\n\toutput: Type.Number(),\n\tcacheRead: Type.Number(),\n\tcacheWrite: Type.Number(),\n};\nconst ModelCostTierSchema = Type.Object({\n\tinputTokensAbove: Type.Number(),\n\t...ModelCostRatesSchema,\n});\nconst ModelCostSchema = Type.Object({\n\t...ModelCostRatesSchema,\n\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n});\n\nconst ModelDefinitionSchema = Type.Object({\n\tid: Type.String({ minLength: 1 }),\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(ModelCostSchema),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ModelOverrideSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(\n\t\tType.Object({\n\t\t\tinput: Type.Optional(Type.Number()),\n\t\t\toutput: Type.Optional(Type.Number()),\n\t\t\tcacheRead: Type.Optional(Type.Number()),\n\t\t\tcacheWrite: Type.Optional(Type.Number()),\n\t\t\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n\t\t}),\n\t),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ProviderConfigSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\tapiKey: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\toauth: Type.Optional(Type.Literal(\"radius\")),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n\tauthHeader: Type.Optional(Type.Boolean()),\n\tmodels: Type.Optional(Type.Array(ModelDefinitionSchema)),\n\tmodelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema)),\n});\n\nconst ModelsConfigSchema = Type.Object({\n\tproviders: Type.Record(Type.String(), ProviderConfigSchema),\n});\nconst validateModelsConfig = Compile(ModelsConfigSchema);\n\nexport type ModelsJsonModel = Static<typeof ModelDefinitionSchema>;\nexport type ModelsJsonModelOverride = Static<typeof ModelOverrideSchema>;\nexport type ModelsJsonProvider = Static<typeof ProviderConfigSchema>;\ntype ModelsJson = Static<typeof ModelsConfigSchema>;\n\nfunction formatValidationPath(error: TLocalizedValidationError): string {\n\tif (error.keyword === \"required\") {\n\t\tconst requiredProperties = (error.params as { requiredProperties?: string[] }).requiredProperties;\n\t\tconst requiredProperty = requiredProperties?.[0];\n\t\tif (requiredProperty) {\n\t\t\tconst basePath = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\t\t\treturn basePath ? `${basePath}.${requiredProperty}` : requiredProperty;\n\t\t}\n\t}\n\tconst path = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\treturn path || \"root\";\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** One immutable load of models.json. */\nexport class ModelConfig {\n\tprivate readonly providers: ReadonlyMap<string, ModelsJsonProvider>;\n\tprivate readonly error: string | undefined;\n\n\tprivate constructor(providers: ReadonlyMap<string, ModelsJsonProvider>, error?: string) {\n\t\tthis.providers = providers;\n\t\tthis.error = error;\n\t}\n\n\tstatic async load(modelsJsonPath: string | undefined): Promise<ModelConfig> {\n\t\tif (!modelsJsonPath) return new ModelConfig(new Map());\n\t\tconst path = normalizePath(modelsJsonPath);\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = await readFile(path, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return new ModelConfig(new Map());\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to load models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(stripJsonComments(stripBom(content)));\n\t\t} catch (error) {\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to parse models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tif (!validateModelsConfig.Check(parsed)) {\n\t\t\tconst errors =\n\t\t\t\tvalidateModelsConfig\n\t\t\t\t\t.Errors(parsed)\n\t\t\t\t\t.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)\n\t\t\t\t\t.join(\"\\n\") || \"Unknown schema error\";\n\t\t\treturn new ModelConfig(new Map(), `Invalid models.json schema:\\n${errors}\\n\\nFile: ${path}`);\n\t\t}\n\n\t\tconst config = parsed as ModelsJson;\n\t\tconst providers = new Map<string, ModelsJsonProvider>();\n\t\tfor (const [providerId, provider] of Object.entries(config.providers)) {\n\t\t\tproviders.set(providerId, deepFreeze(structuredClone(provider)));\n\t\t}\n\t\treturn new ModelConfig(providers);\n\t}\n\n\tgetProvider(providerId: string): ModelsJsonProvider | undefined {\n\t\treturn this.providers.get(providerId);\n\t}\n\n\tgetProviderIds(): readonly string[] {\n\t\treturn [...this.providers.keys()];\n\t}\n\n\tgetError(): string | undefined {\n\t\treturn this.error;\n\t}\n}\n"]}
1
+ {"version":3,"file":"model-config.js","sourceRoot":"","sources":["../../src/core/model-config.ts"],"names":[],"mappings":"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","sourcesContent":["/** Immutable, credential-blind models.json snapshot. */\n\nimport { readFile } from \"node:fs/promises\";\nimport { type Static, Type } from \"typebox\";\nimport { Compile } from \"typebox/compile\";\nimport type { TLocalizedValidationError } from \"typebox/error\";\nimport { stripJsonComments } from \"../utils/json.ts\";\nimport { normalizePath } from \"../utils/paths.ts\";\nimport { stripBom } from \"../utils/text.ts\";\n\nconst PercentileCutoffsSchema = Type.Object({\n\tp50: Type.Optional(Type.Number()),\n\tp75: Type.Optional(Type.Number()),\n\tp90: Type.Optional(Type.Number()),\n\tp99: Type.Optional(Type.Number()),\n});\n\nconst OpenRouterRoutingSchema = Type.Object({\n\tallow_fallbacks: Type.Optional(Type.Boolean()),\n\trequire_parameters: Type.Optional(Type.Boolean()),\n\tdata_collection: Type.Optional(Type.Union([Type.Literal(\"deny\"), Type.Literal(\"allow\")])),\n\tzdr: Type.Optional(Type.Boolean()),\n\tenforce_distillable_text: Type.Optional(Type.Boolean()),\n\torder: Type.Optional(Type.Array(Type.String())),\n\tonly: Type.Optional(Type.Array(Type.String())),\n\tignore: Type.Optional(Type.Array(Type.String())),\n\tquantizations: Type.Optional(Type.Array(Type.String())),\n\tsort: Type.Optional(\n\t\tType.Union([\n\t\t\tType.String(),\n\t\t\tType.Object({\n\t\t\t\tby: Type.Optional(Type.String()),\n\t\t\t\tpartition: Type.Optional(Type.Union([Type.String(), Type.Null()])),\n\t\t\t}),\n\t\t]),\n\t),\n\tmax_price: Type.Optional(\n\t\tType.Object({\n\t\t\tprompt: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\tcompletion: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\timage: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\taudio: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t\trequest: Type.Optional(Type.Union([Type.Number(), Type.String()])),\n\t\t}),\n\t),\n\tpreferred_min_throughput: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n\tpreferred_max_latency: Type.Optional(Type.Union([Type.Number(), PercentileCutoffsSchema])),\n});\n\nconst VercelGatewayRoutingSchema = Type.Object({\n\tonly: Type.Optional(Type.Array(Type.String())),\n\torder: Type.Optional(Type.Array(Type.String())),\n});\n\nconst ThinkingLevelMapValueSchema = Type.Union([Type.String(), Type.Null()]);\nconst ThinkingLevelMapSchema = Type.Object({\n\toff: Type.Optional(ThinkingLevelMapValueSchema),\n\tminimal: Type.Optional(ThinkingLevelMapValueSchema),\n\tlow: Type.Optional(ThinkingLevelMapValueSchema),\n\tmedium: Type.Optional(ThinkingLevelMapValueSchema),\n\thigh: Type.Optional(ThinkingLevelMapValueSchema),\n\txhigh: Type.Optional(ThinkingLevelMapValueSchema),\n\tmax: Type.Optional(ThinkingLevelMapValueSchema),\n});\n\nconst ChatTemplateKwargScalarSchema = Type.Union([Type.String(), Type.Number(), Type.Boolean(), Type.Null()]);\nconst ChatTemplateKwargVariableSchema = Type.Object({\n\t$var: Type.Union([Type.Literal(\"thinking.enabled\"), Type.Literal(\"thinking.effort\")]),\n\tomitWhenOff: Type.Optional(Type.Boolean()),\n});\nconst ChatTemplateKwargSchema = Type.Union([ChatTemplateKwargScalarSchema, ChatTemplateKwargVariableSchema]);\n\nconst OpenAICompletionsCompatSchema = Type.Object({\n\tsupportsStore: Type.Optional(Type.Boolean()),\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsupportsReasoningEffort: Type.Optional(Type.Boolean()),\n\tsupportsUsageInStreaming: Type.Optional(Type.Boolean()),\n\tsupportsFinishReason: Type.Optional(Type.Boolean()),\n\tmaxTokensField: Type.Optional(Type.Union([Type.Literal(\"max_completion_tokens\"), Type.Literal(\"max_tokens\")])),\n\trequiresToolResultName: Type.Optional(Type.Boolean()),\n\trequiresAssistantAfterToolResult: Type.Optional(Type.Boolean()),\n\trequiresThinkingAsText: Type.Optional(Type.Boolean()),\n\trequiresReasoningContentOnAssistantMessages: Type.Optional(Type.Boolean()),\n\tthinkingFormat: Type.Optional(\n\t\tType.Union([\n\t\t\tType.Literal(\"openai\"),\n\t\t\tType.Literal(\"openrouter\"),\n\t\t\tType.Literal(\"together\"),\n\t\t\tType.Literal(\"baseten\"),\n\t\t\tType.Literal(\"deepseek\"),\n\t\t\tType.Literal(\"zai\"),\n\t\t\tType.Literal(\"qwen\"),\n\t\t\tType.Literal(\"chat-template\"),\n\t\t\tType.Literal(\"qwen-chat-template\"),\n\t\t\tType.Literal(\"string-thinking\"),\n\t\t\tType.Literal(\"ant-ling\"),\n\t\t]),\n\t),\n\tchatTemplateKwargs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tchatTemplateArgs: Type.Optional(Type.Record(Type.String(), ChatTemplateKwargSchema)),\n\tcacheControlFormat: Type.Optional(Type.Literal(\"anthropic\")),\n\topenRouterRouting: Type.Optional(OpenRouterRoutingSchema),\n\tvercelGatewayRouting: Type.Optional(VercelGatewayRoutingSchema),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tdeferredToolsMode: Type.Optional(Type.Literal(\"kimi\")),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n});\n\nconst OpenAIResponsesCompatSchema = Type.Object({\n\tsupportsDeveloperRole: Type.Optional(Type.Boolean()),\n\tsessionAffinityFormat: Type.Optional(\n\t\tType.Union([Type.Literal(\"openai\"), Type.Literal(\"openai-nosession\"), Type.Literal(\"openrouter\")]),\n\t),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsupportsStrictMode: Type.Optional(Type.Boolean()),\n\tsupportsOpenAIGrammarTools: Type.Optional(Type.Boolean()),\n\tsupportsAdditionalTools: Type.Optional(Type.Boolean()),\n\tsupportsToolSearch: Type.Optional(Type.Boolean()),\n\tsupportsMaxOutputTokens: Type.Optional(Type.Boolean()),\n});\n\nconst ModelCostRatesSchema = {\n\tinput: Type.Number(),\n\toutput: Type.Number(),\n\tcacheRead: Type.Number(),\n\tcacheWrite: Type.Number(),\n};\nconst ModelCostTierSchema = Type.Object({\n\tinputTokensAbove: Type.Number(),\n\t...ModelCostRatesSchema,\n});\nconst ModelCostSchema = Type.Object({\n\t...ModelCostRatesSchema,\n\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n});\n\nconst AnthropicMessagesCompatSchema = Type.Object({\n\tsupportsEagerToolInputStreaming: Type.Optional(Type.Boolean()),\n\tsupportsLongCacheRetention: Type.Optional(Type.Boolean()),\n\tsendSessionAffinityHeaders: Type.Optional(Type.Boolean()),\n\tsupportsCacheControlOnTools: Type.Optional(Type.Boolean()),\n\tsupportsTemperature: Type.Optional(Type.Boolean()),\n\tforceAdaptiveThinking: Type.Optional(Type.Boolean()),\n\tallowEmptySignature: Type.Optional(Type.Boolean()),\n\tsupportsStrictTools: Type.Optional(Type.Boolean()),\n\tsupportsMidConvoEffort: Type.Optional(Type.Boolean()),\n\tsupportsToolReferences: Type.Optional(Type.Boolean()),\n\tallowedFallbackModels: Type.Optional(\n\t\tType.Array(\n\t\t\tType.Object({\n\t\t\t\tprovider: Type.String({ minLength: 1 }),\n\t\t\t\tmodel: Type.String({ minLength: 1 }),\n\t\t\t\tcost: ModelCostSchema,\n\t\t\t}),\n\t\t\t{ maxItems: 3 },\n\t\t),\n\t),\n});\n\nconst ProviderCompatSchema = Type.Union([\n\tOpenAICompletionsCompatSchema,\n\tOpenAIResponsesCompatSchema,\n\tAnthropicMessagesCompatSchema,\n]);\n\nconst ModelDefinitionSchema = Type.Object({\n\tid: Type.String({ minLength: 1 }),\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\t// 供应商能力槽位(设计 §3.1):语义与既有 ImagesModel.output 对齐,缺省 =\n\t// 纯文本(undefined 视为 [\"text\"])。生图供应商在 models.json 登记\n\t// \"output\": [\"image\"] 的模型即进入宿主注入的生图模型目录快照。\n\toutput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(ModelCostSchema),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ModelOverrideSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\treasoning: Type.Optional(Type.Boolean()),\n\tthinkingLevelMap: Type.Optional(ThinkingLevelMapSchema),\n\tinput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\toutput: Type.Optional(Type.Array(Type.Union([Type.Literal(\"text\"), Type.Literal(\"image\")]))),\n\tcost: Type.Optional(\n\t\tType.Object({\n\t\t\tinput: Type.Optional(Type.Number()),\n\t\t\toutput: Type.Optional(Type.Number()),\n\t\t\tcacheRead: Type.Optional(Type.Number()),\n\t\t\tcacheWrite: Type.Optional(Type.Number()),\n\t\t\ttiers: Type.Optional(Type.Array(ModelCostTierSchema)),\n\t\t}),\n\t),\n\tcontextWindow: Type.Optional(Type.Number()),\n\tmaxTokens: Type.Optional(Type.Number()),\n\tsamplingParams: Type.Optional(Type.Record(Type.String(), Type.Unknown())),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n});\n\nconst ProviderConfigSchema = Type.Object({\n\tname: Type.Optional(Type.String({ minLength: 1 })),\n\tbaseUrl: Type.Optional(Type.String({ minLength: 1 })),\n\tapiKey: Type.Optional(Type.String({ minLength: 1 })),\n\tapi: Type.Optional(Type.String({ minLength: 1 })),\n\toauth: Type.Optional(Type.Literal(\"radius\")),\n\theaders: Type.Optional(Type.Record(Type.String(), Type.String())),\n\tcompat: Type.Optional(ProviderCompatSchema),\n\tauthHeader: Type.Optional(Type.Boolean()),\n\tmodels: Type.Optional(Type.Array(ModelDefinitionSchema)),\n\tmodelOverrides: Type.Optional(Type.Record(Type.String(), ModelOverrideSchema)),\n});\n\nconst ModelsConfigSchema = Type.Object({\n\tproviders: Type.Record(Type.String(), ProviderConfigSchema),\n});\nconst validateModelsConfig = Compile(ModelsConfigSchema);\n\nexport type ModelsJsonModel = Static<typeof ModelDefinitionSchema>;\nexport type ModelsJsonModelOverride = Static<typeof ModelOverrideSchema>;\nexport type ModelsJsonProvider = Static<typeof ProviderConfigSchema>;\ntype ModelsJson = Static<typeof ModelsConfigSchema>;\n\nfunction formatValidationPath(error: TLocalizedValidationError): string {\n\tif (error.keyword === \"required\") {\n\t\tconst requiredProperties = (error.params as { requiredProperties?: string[] }).requiredProperties;\n\t\tconst requiredProperty = requiredProperties?.[0];\n\t\tif (requiredProperty) {\n\t\t\tconst basePath = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\t\t\treturn basePath ? `${basePath}.${requiredProperty}` : requiredProperty;\n\t\t}\n\t}\n\tconst path = error.instancePath.replace(/^\\//, \"\").replace(/\\//g, \".\");\n\treturn path || \"root\";\n}\n\nfunction deepFreeze<T>(value: T): T {\n\tif (typeof value !== \"object\" || value === null || Object.isFrozen(value)) return value;\n\tfor (const child of Object.values(value)) deepFreeze(child);\n\treturn Object.freeze(value);\n}\n\n/** One immutable load of models.json. */\nexport class ModelConfig {\n\tprivate readonly providers: ReadonlyMap<string, ModelsJsonProvider>;\n\tprivate readonly error: string | undefined;\n\n\tprivate constructor(providers: ReadonlyMap<string, ModelsJsonProvider>, error?: string) {\n\t\tthis.providers = providers;\n\t\tthis.error = error;\n\t}\n\n\tstatic async load(modelsJsonPath: string | undefined): Promise<ModelConfig> {\n\t\tif (!modelsJsonPath) return new ModelConfig(new Map());\n\t\tconst path = normalizePath(modelsJsonPath);\n\t\tlet content: string;\n\t\ttry {\n\t\t\tcontent = await readFile(path, \"utf-8\");\n\t\t} catch (error) {\n\t\t\tif ((error as NodeJS.ErrnoException).code === \"ENOENT\") return new ModelConfig(new Map());\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to load models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tlet parsed: unknown;\n\t\ttry {\n\t\t\tparsed = JSON.parse(stripJsonComments(stripBom(content)));\n\t\t} catch (error) {\n\t\t\treturn new ModelConfig(\n\t\t\t\tnew Map(),\n\t\t\t\t`Failed to parse models.json: ${error instanceof Error ? error.message : error}\\n\\nFile: ${path}`,\n\t\t\t);\n\t\t}\n\n\t\tif (!validateModelsConfig.Check(parsed)) {\n\t\t\tconst errors =\n\t\t\t\tvalidateModelsConfig\n\t\t\t\t\t.Errors(parsed)\n\t\t\t\t\t.map((error) => ` - ${formatValidationPath(error)}: ${error.message}`)\n\t\t\t\t\t.join(\"\\n\") || \"Unknown schema error\";\n\t\t\treturn new ModelConfig(new Map(), `Invalid models.json schema:\\n${errors}\\n\\nFile: ${path}`);\n\t\t}\n\n\t\tconst config = parsed as ModelsJson;\n\t\tconst providers = new Map<string, ModelsJsonProvider>();\n\t\tfor (const [providerId, provider] of Object.entries(config.providers)) {\n\t\t\tproviders.set(providerId, deepFreeze(structuredClone(provider)));\n\t\t}\n\t\treturn new ModelConfig(providers);\n\t}\n\n\tgetProvider(providerId: string): ModelsJsonProvider | undefined {\n\t\treturn this.providers.get(providerId);\n\t}\n\n\tgetProviderIds(): readonly string[] {\n\t\treturn [...this.providers.keys()];\n\t}\n\n\tgetError(): string | undefined {\n\t\treturn this.error;\n\t}\n\n\t/**\n\t * 生图模型目录快照(供应商能力槽位设计 §3.2 推断供料):models.json 中\n\t * `output` 含 `image` 的模型按 provider 分组,供宿主在装配期经\n\t * `configOverride` 注入 image-generation 插件(注入键 `imageModelCatalog`)。\n\t * 快照为装配期静态数据;插件运行期按会话当前 provider 动态查询。内建\n\t * 聊天目录不参与——内建 images 目录走 chat modalities 协议,与插件消费的\n\t * `/images/generations` 端点协议不互通(设计 §3.2 第 4 层)。保持\n\t * models.json 登记顺序(确定性来源);无生图模型的 provider 不出现在键集中。\n\t */\n\tgetImageModelCatalog(): Readonly<Record<string, ReadonlyArray<{ id: string; name?: string }>>> {\n\t\tconst catalog: Record<string, Array<{ id: string; name?: string }>> = {};\n\t\tfor (const [providerId, provider] of this.providers) {\n\t\t\tconst imageModels = (provider.models ?? []).filter(\n\t\t\t\t(model) => Array.isArray(model.output) && model.output.includes(\"image\"),\n\t\t\t);\n\t\t\tif (imageModels.length === 0) continue;\n\t\t\tcatalog[providerId] = imageModels.map((model) => ({\n\t\t\t\tid: model.id,\n\t\t\t\t...(model.name === undefined ? {} : { name: model.name }),\n\t\t\t}));\n\t\t}\n\t\treturn deepFreeze(catalog);\n\t}\n}\n"]}
@@ -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-5.5\",\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 { 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"]}
@@ -13,7 +13,7 @@ export const defaultModelPerProvider = {
13
13
  anthropic: "claude-opus-4-8",
14
14
  openai: "gpt-5.5",
15
15
  "azure-openai-responses": "gpt-5.4",
16
- "openai-codex": "gpt-5.5",
16
+ "openai-codex": "gpt-6.1-sol",
17
17
  radius: "auto",
18
18
  nvidia: "nvidia/nemotron-3-super-120b-a12b",
19
19
  deepseek: "deepseek-v4-pro",