open-multi-agent-kit 0.96.0 → 0.96.2

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 (351) hide show
  1. package/CHANGELOG.md +81 -0
  2. package/README.md +34 -6
  3. package/dist/cli/args.d.ts.map +1 -1
  4. package/dist/cli/args.js +1 -0
  5. package/dist/cli/args.js.map +1 -1
  6. package/dist/commands/doctor-provider.d.ts.map +1 -1
  7. package/dist/commands/doctor-provider.js +15 -20
  8. package/dist/commands/doctor-provider.js.map +1 -1
  9. package/dist/commands/resource-doctor-cli.d.ts +22 -0
  10. package/dist/commands/resource-doctor-cli.d.ts.map +1 -0
  11. package/dist/commands/resource-doctor-cli.js +98 -0
  12. package/dist/commands/resource-doctor-cli.js.map +1 -0
  13. package/dist/commands/sdk-session-cli.d.ts +24 -0
  14. package/dist/commands/sdk-session-cli.d.ts.map +1 -0
  15. package/dist/commands/sdk-session-cli.js +225 -0
  16. package/dist/commands/sdk-session-cli.js.map +1 -0
  17. package/dist/core/advisory-judge-model.d.ts +18 -0
  18. package/dist/core/advisory-judge-model.d.ts.map +1 -0
  19. package/dist/core/advisory-judge-model.js +168 -0
  20. package/dist/core/advisory-judge-model.js.map +1 -0
  21. package/dist/core/advisory-judge-response.d.ts +8 -0
  22. package/dist/core/advisory-judge-response.d.ts.map +1 -0
  23. package/dist/core/advisory-judge-response.js +61 -0
  24. package/dist/core/advisory-judge-response.js.map +1 -0
  25. package/dist/core/advisory-judge-types.d.ts +53 -0
  26. package/dist/core/advisory-judge-types.d.ts.map +1 -0
  27. package/dist/core/advisory-judge-types.js +2 -0
  28. package/dist/core/advisory-judge-types.js.map +1 -0
  29. package/dist/core/advisory-judge.d.ts +8 -0
  30. package/dist/core/advisory-judge.d.ts.map +1 -0
  31. package/dist/core/advisory-judge.js +178 -0
  32. package/dist/core/advisory-judge.js.map +1 -0
  33. package/dist/core/agent-session-services.d.ts +1 -0
  34. package/dist/core/agent-session-services.d.ts.map +1 -1
  35. package/dist/core/agent-session-services.js +1 -0
  36. package/dist/core/agent-session-services.js.map +1 -1
  37. package/dist/core/agent-session.d.ts +41 -2
  38. package/dist/core/agent-session.d.ts.map +1 -1
  39. package/dist/core/agent-session.js +396 -179
  40. package/dist/core/agent-session.js.map +1 -1
  41. package/dist/core/auth-storage.d.ts.map +1 -1
  42. package/dist/core/auth-storage.js +28 -4
  43. package/dist/core/auth-storage.js.map +1 -1
  44. package/dist/core/compaction-gate.d.ts +28 -0
  45. package/dist/core/compaction-gate.d.ts.map +1 -0
  46. package/dist/core/compaction-gate.js +34 -0
  47. package/dist/core/compaction-gate.js.map +1 -0
  48. package/dist/core/completion-sound.d.ts +109 -0
  49. package/dist/core/completion-sound.d.ts.map +1 -0
  50. package/dist/core/completion-sound.js +165 -0
  51. package/dist/core/completion-sound.js.map +1 -0
  52. package/dist/core/context-budget-system-prompt-items.d.ts.map +1 -1
  53. package/dist/core/context-budget-system-prompt-items.js +5 -3
  54. package/dist/core/context-budget-system-prompt-items.js.map +1 -1
  55. package/dist/core/domain-loadouts.d.ts.map +1 -1
  56. package/dist/core/domain-loadouts.js +2 -2
  57. package/dist/core/domain-loadouts.js.map +1 -1
  58. package/dist/core/durable-goal-checkpoint.d.ts +6 -0
  59. package/dist/core/durable-goal-checkpoint.d.ts.map +1 -0
  60. package/dist/core/durable-goal-checkpoint.js +195 -0
  61. package/dist/core/durable-goal-checkpoint.js.map +1 -0
  62. package/dist/core/durable-goal-parse.d.ts +3 -0
  63. package/dist/core/durable-goal-parse.d.ts.map +1 -0
  64. package/dist/core/durable-goal-parse.js +86 -0
  65. package/dist/core/durable-goal-parse.js.map +1 -0
  66. package/dist/core/durable-goal-reducer.d.ts +3 -0
  67. package/dist/core/durable-goal-reducer.d.ts.map +1 -0
  68. package/dist/core/durable-goal-reducer.js +175 -0
  69. package/dist/core/durable-goal-reducer.js.map +1 -0
  70. package/dist/core/durable-goal-store.d.ts +19 -0
  71. package/dist/core/durable-goal-store.d.ts.map +1 -0
  72. package/dist/core/durable-goal-store.js +126 -0
  73. package/dist/core/durable-goal-store.js.map +1 -0
  74. package/dist/core/durable-goal.d.ts +92 -0
  75. package/dist/core/durable-goal.d.ts.map +1 -0
  76. package/dist/core/durable-goal.js +62 -0
  77. package/dist/core/durable-goal.js.map +1 -0
  78. package/dist/core/extensions/builtin/goal-controller.d.ts +3 -0
  79. package/dist/core/extensions/builtin/goal-controller.d.ts.map +1 -0
  80. package/dist/core/extensions/builtin/goal-controller.js +125 -0
  81. package/dist/core/extensions/builtin/goal-controller.js.map +1 -0
  82. package/dist/core/extensions/builtin/identical-loop.d.ts +3 -0
  83. package/dist/core/extensions/builtin/identical-loop.d.ts.map +1 -0
  84. package/dist/core/extensions/builtin/identical-loop.js +31 -0
  85. package/dist/core/extensions/builtin/identical-loop.js.map +1 -0
  86. package/dist/core/extensions/builtin/prompt-preset.d.ts +3 -0
  87. package/dist/core/extensions/builtin/prompt-preset.d.ts.map +1 -0
  88. package/dist/core/extensions/builtin/prompt-preset.js +13 -0
  89. package/dist/core/extensions/builtin/prompt-preset.js.map +1 -0
  90. package/dist/core/extensions/builtin/tool-pair-repair.d.ts +3 -0
  91. package/dist/core/extensions/builtin/tool-pair-repair.d.ts.map +1 -0
  92. package/dist/core/extensions/builtin/tool-pair-repair.js +12 -0
  93. package/dist/core/extensions/builtin/tool-pair-repair.js.map +1 -0
  94. package/dist/core/extensions/types.d.ts +6 -2
  95. package/dist/core/extensions/types.d.ts.map +1 -1
  96. package/dist/core/extensions/types.js.map +1 -1
  97. package/dist/core/goal-continuation.d.ts +13 -0
  98. package/dist/core/goal-continuation.d.ts.map +1 -0
  99. package/dist/core/goal-continuation.js +10 -0
  100. package/dist/core/goal-continuation.js.map +1 -0
  101. package/dist/core/grok-harness.d.ts +1 -1
  102. package/dist/core/grok-harness.d.ts.map +1 -1
  103. package/dist/core/grok-harness.js +1 -1
  104. package/dist/core/grok-harness.js.map +1 -1
  105. package/dist/core/grok-playbook.d.ts +1 -1
  106. package/dist/core/grok-playbook.d.ts.map +1 -1
  107. package/dist/core/grok-playbook.js +1 -1
  108. package/dist/core/grok-playbook.js.map +1 -1
  109. package/dist/core/host-resource-probe.d.ts +63 -0
  110. package/dist/core/host-resource-probe.d.ts.map +1 -0
  111. package/dist/core/host-resource-probe.js +126 -0
  112. package/dist/core/host-resource-probe.js.map +1 -0
  113. package/dist/core/host-resource-snapshot.d.ts +54 -0
  114. package/dist/core/host-resource-snapshot.d.ts.map +1 -0
  115. package/dist/core/host-resource-snapshot.js +139 -0
  116. package/dist/core/host-resource-snapshot.js.map +1 -0
  117. package/dist/core/identical-loop.d.ts +15 -0
  118. package/dist/core/identical-loop.d.ts.map +1 -0
  119. package/dist/core/identical-loop.js +34 -0
  120. package/dist/core/identical-loop.js.map +1 -0
  121. package/dist/core/index.d.ts +1 -1
  122. package/dist/core/index.d.ts.map +1 -1
  123. package/dist/core/index.js +1 -1
  124. package/dist/core/index.js.map +1 -1
  125. package/dist/core/model-prompt-policy.d.ts +11 -0
  126. package/dist/core/model-prompt-policy.d.ts.map +1 -0
  127. package/dist/core/model-prompt-policy.js +17 -0
  128. package/dist/core/model-prompt-policy.js.map +1 -0
  129. package/dist/core/model-registry.d.ts.map +1 -1
  130. package/dist/core/model-registry.js +16 -4
  131. package/dist/core/model-registry.js.map +1 -1
  132. package/dist/core/model-resolver.d.ts.map +1 -1
  133. package/dist/core/model-resolver.js +2 -2
  134. package/dist/core/model-resolver.js.map +1 -1
  135. package/dist/core/prompt-budget.d.ts +21 -0
  136. package/dist/core/prompt-budget.d.ts.map +1 -0
  137. package/dist/core/prompt-budget.js +51 -0
  138. package/dist/core/prompt-budget.js.map +1 -0
  139. package/dist/core/prompt-cache.d.ts +14 -0
  140. package/dist/core/prompt-cache.d.ts.map +1 -0
  141. package/dist/core/prompt-cache.js +16 -0
  142. package/dist/core/prompt-cache.js.map +1 -0
  143. package/dist/core/prompt-preset.d.ts +8 -0
  144. package/dist/core/prompt-preset.d.ts.map +1 -0
  145. package/dist/core/prompt-preset.js +56 -0
  146. package/dist/core/prompt-preset.js.map +1 -0
  147. package/dist/core/prompt-settlement.d.ts +81 -0
  148. package/dist/core/prompt-settlement.d.ts.map +1 -0
  149. package/dist/core/prompt-settlement.js +84 -0
  150. package/dist/core/prompt-settlement.js.map +1 -0
  151. package/dist/core/provider-resilience.d.ts +16 -0
  152. package/dist/core/provider-resilience.d.ts.map +1 -1
  153. package/dist/core/provider-resilience.js +24 -2
  154. package/dist/core/provider-resilience.js.map +1 -1
  155. package/dist/core/provider-retry.d.ts +36 -0
  156. package/dist/core/provider-retry.d.ts.map +1 -0
  157. package/dist/core/provider-retry.js +73 -0
  158. package/dist/core/provider-retry.js.map +1 -0
  159. package/dist/core/provider-usage.d.ts +16 -2
  160. package/dist/core/provider-usage.d.ts.map +1 -1
  161. package/dist/core/provider-usage.js +150 -8
  162. package/dist/core/provider-usage.js.map +1 -1
  163. package/dist/core/reasoning-router-resolver.d.ts.map +1 -1
  164. package/dist/core/reasoning-router-resolver.js +1 -1
  165. package/dist/core/reasoning-router-resolver.js.map +1 -1
  166. package/dist/core/resource-admission-config.d.ts +55 -0
  167. package/dist/core/resource-admission-config.d.ts.map +1 -0
  168. package/dist/core/resource-admission-config.js +97 -0
  169. package/dist/core/resource-admission-config.js.map +1 -0
  170. package/dist/core/resource-admission.d.ts +81 -0
  171. package/dist/core/resource-admission.d.ts.map +1 -0
  172. package/dist/core/resource-admission.js +128 -0
  173. package/dist/core/resource-admission.js.map +1 -0
  174. package/dist/core/resource-governor-format.d.ts +50 -0
  175. package/dist/core/resource-governor-format.d.ts.map +1 -0
  176. package/dist/core/resource-governor-format.js +113 -0
  177. package/dist/core/resource-governor-format.js.map +1 -0
  178. package/dist/core/resource-governor-settings.d.ts +56 -0
  179. package/dist/core/resource-governor-settings.d.ts.map +1 -0
  180. package/dist/core/resource-governor-settings.js +89 -0
  181. package/dist/core/resource-governor-settings.js.map +1 -0
  182. package/dist/core/resource-loader.d.ts.map +1 -1
  183. package/dist/core/resource-loader.js +32 -0
  184. package/dist/core/resource-loader.js.map +1 -1
  185. package/dist/core/resource-observation-journal.d.ts +74 -0
  186. package/dist/core/resource-observation-journal.d.ts.map +1 -0
  187. package/dist/core/resource-observation-journal.js +198 -0
  188. package/dist/core/resource-observation-journal.js.map +1 -0
  189. package/dist/core/resource-safety-gate.d.ts +54 -0
  190. package/dist/core/resource-safety-gate.d.ts.map +1 -0
  191. package/dist/core/resource-safety-gate.js +51 -0
  192. package/dist/core/resource-safety-gate.js.map +1 -0
  193. package/dist/core/run-journal.d.ts.map +1 -1
  194. package/dist/core/run-journal.js +13 -1
  195. package/dist/core/run-journal.js.map +1 -1
  196. package/dist/core/run-resource-lease.d.ts +73 -0
  197. package/dist/core/run-resource-lease.d.ts.map +1 -0
  198. package/dist/core/run-resource-lease.js +78 -0
  199. package/dist/core/run-resource-lease.js.map +1 -0
  200. package/dist/core/sandbox/backend.d.ts +12 -0
  201. package/dist/core/sandbox/backend.d.ts.map +1 -1
  202. package/dist/core/sandbox/backend.js +52 -42
  203. package/dist/core/sandbox/backend.js.map +1 -1
  204. package/dist/core/sandbox/policy.d.ts +2 -0
  205. package/dist/core/sandbox/policy.d.ts.map +1 -1
  206. package/dist/core/sandbox/policy.js +2 -1
  207. package/dist/core/sandbox/policy.js.map +1 -1
  208. package/dist/core/sdk.d.ts +2 -0
  209. package/dist/core/sdk.d.ts.map +1 -1
  210. package/dist/core/sdk.js +1 -0
  211. package/dist/core/sdk.js.map +1 -1
  212. package/dist/core/session-bash-service.d.ts +12 -0
  213. package/dist/core/session-bash-service.d.ts.map +1 -1
  214. package/dist/core/session-bash-service.js +14 -0
  215. package/dist/core/session-bash-service.js.map +1 -1
  216. package/dist/core/session-system-prompt.d.ts +30 -0
  217. package/dist/core/session-system-prompt.d.ts.map +1 -0
  218. package/dist/core/session-system-prompt.js +39 -0
  219. package/dist/core/session-system-prompt.js.map +1 -0
  220. package/dist/core/session-termination.d.ts +7 -2
  221. package/dist/core/session-termination.d.ts.map +1 -1
  222. package/dist/core/session-termination.js +29 -1
  223. package/dist/core/session-termination.js.map +1 -1
  224. package/dist/core/settings-manager.d.ts +12 -0
  225. package/dist/core/settings-manager.d.ts.map +1 -1
  226. package/dist/core/settings-manager.js +36 -0
  227. package/dist/core/settings-manager.js.map +1 -1
  228. package/dist/core/slash-commands.d.ts.map +1 -1
  229. package/dist/core/slash-commands.js +1 -0
  230. package/dist/core/slash-commands.js.map +1 -1
  231. package/dist/core/strict-record.d.ts +2 -0
  232. package/dist/core/strict-record.d.ts.map +1 -0
  233. package/dist/core/strict-record.js +9 -0
  234. package/dist/core/strict-record.js.map +1 -0
  235. package/dist/core/subagent-lane-launcher.d.ts +64 -0
  236. package/dist/core/subagent-lane-launcher.d.ts.map +1 -0
  237. package/dist/core/subagent-lane-launcher.js +107 -0
  238. package/dist/core/subagent-lane-launcher.js.map +1 -0
  239. package/dist/core/system-cpu-sampler.d.ts +45 -0
  240. package/dist/core/system-cpu-sampler.d.ts.map +1 -0
  241. package/dist/core/system-cpu-sampler.js +95 -0
  242. package/dist/core/system-cpu-sampler.js.map +1 -0
  243. package/dist/core/system-prompt.d.ts.map +1 -1
  244. package/dist/core/system-prompt.js +5 -8
  245. package/dist/core/system-prompt.js.map +1 -1
  246. package/dist/core/tool-pair-repair.d.ts +11 -0
  247. package/dist/core/tool-pair-repair.d.ts.map +1 -0
  248. package/dist/core/tool-pair-repair.js +38 -0
  249. package/dist/core/tool-pair-repair.js.map +1 -0
  250. package/dist/core/tools/artifact-spill.d.ts +13 -0
  251. package/dist/core/tools/artifact-spill.d.ts.map +1 -0
  252. package/dist/core/tools/artifact-spill.js +26 -0
  253. package/dist/core/tools/artifact-spill.js.map +1 -0
  254. package/dist/core/tools/bash.d.ts +7 -4
  255. package/dist/core/tools/bash.d.ts.map +1 -1
  256. package/dist/core/tools/bash.js +8 -7
  257. package/dist/core/tools/bash.js.map +1 -1
  258. package/dist/core/tools/index.d.ts +1 -1
  259. package/dist/core/tools/index.d.ts.map +1 -1
  260. package/dist/core/tools/index.js.map +1 -1
  261. package/dist/core/tools/read.d.ts +1 -0
  262. package/dist/core/tools/read.d.ts.map +1 -1
  263. package/dist/core/tools/read.js +10 -1
  264. package/dist/core/tools/read.js.map +1 -1
  265. package/dist/core/tools/tool-definition-wrapper.d.ts.map +1 -1
  266. package/dist/core/tools/tool-definition-wrapper.js +2 -0
  267. package/dist/core/tools/tool-definition-wrapper.js.map +1 -1
  268. package/dist/core/workload-classifier.d.ts +32 -0
  269. package/dist/core/workload-classifier.d.ts.map +1 -0
  270. package/dist/core/workload-classifier.js +66 -0
  271. package/dist/core/workload-classifier.js.map +1 -0
  272. package/dist/core/workload-family-matcher.d.ts +3 -0
  273. package/dist/core/workload-family-matcher.d.ts.map +1 -0
  274. package/dist/core/workload-family-matcher.js +126 -0
  275. package/dist/core/workload-family-matcher.js.map +1 -0
  276. package/dist/core/workload-permit-pool.d.ts +78 -0
  277. package/dist/core/workload-permit-pool.d.ts.map +1 -0
  278. package/dist/core/workload-permit-pool.js +138 -0
  279. package/dist/core/workload-permit-pool.js.map +1 -0
  280. package/dist/core/workload-shard-executor.d.ts +68 -0
  281. package/dist/core/workload-shard-executor.d.ts.map +1 -0
  282. package/dist/core/workload-shard-executor.js +156 -0
  283. package/dist/core/workload-shard-executor.js.map +1 -0
  284. package/dist/core/workload-shard-plan.d.ts +81 -0
  285. package/dist/core/workload-shard-plan.d.ts.map +1 -0
  286. package/dist/core/workload-shard-plan.js +183 -0
  287. package/dist/core/workload-shard-plan.js.map +1 -0
  288. package/dist/core/workload-shard-runner.d.ts +11 -0
  289. package/dist/core/workload-shard-runner.d.ts.map +1 -0
  290. package/dist/core/workload-shard-runner.js +98 -0
  291. package/dist/core/workload-shard-runner.js.map +1 -0
  292. package/dist/core/workload-shard-store.d.ts +44 -0
  293. package/dist/core/workload-shard-store.d.ts.map +1 -0
  294. package/dist/core/workload-shard-store.js +189 -0
  295. package/dist/core/workload-shard-store.js.map +1 -0
  296. package/dist/core/workload-sharders.d.ts +47 -0
  297. package/dist/core/workload-sharders.d.ts.map +1 -0
  298. package/dist/core/workload-sharders.js +162 -0
  299. package/dist/core/workload-sharders.js.map +1 -0
  300. package/dist/core/workload-shell-scan.d.ts +12 -0
  301. package/dist/core/workload-shell-scan.d.ts.map +1 -0
  302. package/dist/core/workload-shell-scan.js +79 -0
  303. package/dist/core/workload-shell-scan.js.map +1 -0
  304. package/dist/index.d.ts +18 -1
  305. package/dist/index.d.ts.map +1 -1
  306. package/dist/index.js +18 -0
  307. package/dist/index.js.map +1 -1
  308. package/dist/main.d.ts.map +1 -1
  309. package/dist/main.js +14 -0
  310. package/dist/main.js.map +1 -1
  311. package/dist/modes/interactive/interactive-mode.d.ts +4 -0
  312. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  313. package/dist/modes/interactive/interactive-mode.js +81 -0
  314. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  315. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  316. package/dist/modes/interactive/theme/theme.js +14 -3
  317. package/dist/modes/interactive/theme/theme.js.map +1 -1
  318. package/docs/adaptorch-preview-spec.md +1 -1
  319. package/docs/adaptorch-preview.md +2 -2
  320. package/docs/book-to-skill.md +1 -1
  321. package/docs/containerization.md +9 -0
  322. package/docs/docs.json +11 -3
  323. package/docs/environment-variables.md +11 -4
  324. package/docs/extensions.md +14 -1
  325. package/docs/grok-harness.md +35 -12
  326. package/docs/index.md +7 -6
  327. package/docs/loadout-domains/grok-harness.md +2 -2
  328. package/docs/models.md +10 -9
  329. package/docs/provider-resilience.md +9 -3
  330. package/docs/providers.md +9 -4
  331. package/docs/run-protocol.md +32 -0
  332. package/docs/sdk.md +100 -3
  333. package/docs/security.md +22 -32
  334. package/docs/sessions.md +14 -0
  335. package/docs/settings.md +64 -2
  336. package/docs/skills.md +16 -0
  337. package/docs/usage.md +37 -15
  338. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  339. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  340. package/examples/extensions/custom-provider-gitlab-duo/index.ts +6 -1
  341. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  342. package/examples/extensions/gondolin/package-lock.json +2 -2
  343. package/examples/extensions/gondolin/package.json +1 -1
  344. package/examples/extensions/sandbox/package-lock.json +2 -2
  345. package/examples/extensions/sandbox/package.json +1 -1
  346. package/examples/extensions/subagent/agent-capability-router.test.ts +7 -0
  347. package/examples/extensions/subagent/domain-profiles.ts +0 -1
  348. package/examples/extensions/with-deps/package-lock.json +2 -2
  349. package/examples/extensions/with-deps/package.json +1 -1
  350. package/npm-shrinkwrap.json +18 -18
  351. package/package.json +7 -9
@@ -1 +1 @@
1
- {"version":3,"file":"doctor-provider.d.ts","sourceRoot":"","sources":["../../src/commands/doctor-provider.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { BlockList, isIP } from \"node:net\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { type Api, findEnvKeys, getModels, getProviders, type KnownProvider, type Model } from \"omk-ai\";\nimport { getAgentDir as getConfiguredAgentDir } from \"../config.ts\";\nimport { isConfigValueConfigured, resolveConfigValueOrThrow } from \"../core/resolve-config-value.ts\";\nimport { stripJsonComments } from \"../utils/json.ts\";\n\nexport type ProviderOrigin = \"native\" | \"custom-openai-compatible\" | \"local-proxy\" | \"unknown\";\nexport type ProviderDoctorLevel = 0 | 1 | 2;\nexport type ProviderDoctorCheckStatus = \"ok\" | \"fail\" | \"skipped\" | \"unsupported\";\nexport type DoctorErrorCategory = \"network\" | \"auth\" | \"model\" | \"config\" | \"server\" | \"unknown\";\n\n/** Exact endpoint-probe category model from the v0.90.9 design (§10.4). */\nexport type EndpointProbeCategory = \"ok\" | \"network\" | \"auth\" | \"unsupported-endpoint\" | \"server\";\n\nexport type EndpointProbeResult = {\n\treachable: boolean;\n\tauthenticated?: boolean;\n\tmodelsSupported?: boolean;\n\tstatus?: number;\n\tcategory: EndpointProbeCategory;\n};\n\nexport type ProviderDoctorCode =\n\t| \"ok\"\n\t| \"provider-not-found\"\n\t| \"models-config-invalid\"\n\t| \"auth-config-invalid\"\n\t| \"kimi-config-invalid\"\n\t| \"unsupported-level\"\n\t| \"model-provider-mismatch\"\n\t| \"api-missing\"\n\t| \"api-unsupported\"\n\t| \"base-url-missing\"\n\t| \"base-url-invalid\"\n\t| \"url-scheme-unsupported\"\n\t| \"origin-unsupported\"\n\t| \"address-policy-blocked\"\n\t| \"auth-missing\"\n\t| \"auth-materialization-failed\"\n\t| \"transport-required\"\n\t| \"address-pinning-required\"\n\t| \"redirect-blocked\"\n\t| \"authentication-failed\"\n\t| \"endpoint-unsupported\"\n\t| \"request-aborted\"\n\t| \"request-timeout\"\n\t| \"network-failure\"\n\t| \"server-error\"\n\t| \"probe-model-required\"\n\t| \"probe-model-conflict\"\n\t| \"unexpected-response\";\n\nexport interface ProviderDoctorEndpoint {\n\tbaseUrl?: string;\n\tapi?: string;\n\tmodelIds?: readonly string[];\n\tmodelId?: string;\n}\n\nexport type ProviderDoctorHeaderFactory = () => Headers | Promise<Headers>;\n\nexport type ProviderDoctorAuthHeaderResolver = (target: ResolvedProviderTarget) => Headers | Promise<Headers>;\n\n/** Fixed-message marker used to classify auth resolution without exposing its cause. */\nexport class ProviderDoctorAuthMaterializationError extends Error {\n\tconstructor() {\n\t\tsuper(\"provider doctor authentication could not be materialized\");\n\t\tthis.name = \"ProviderDoctorAuthMaterializationError\";\n\t}\n}\n\nexport interface ProviderDoctorCredentialBinding {\n\torigin: ProviderOrigin;\n\tsource: string;\n\tbaseUrl: string;\n\tapi: string;\n\tmodelId: string;\n}\n\nexport interface ProviderDoctorAuth {\n\tpresent: boolean;\n\tsource?: string;\n\t/** Materialized by an injected transport at request time only. */\n\tcreateHeaders?: ProviderDoctorHeaderFactory;\n\t/** Exact endpoint provenance that authorizes createHeaders. */\n\tbinding?: ProviderDoctorCredentialBinding;\n}\n\nexport interface ResolvedProviderTarget {\n\tproviderId: string;\n\torigin: ProviderOrigin;\n\tsource: string;\n\tendpoint: ProviderDoctorEndpoint;\n\tauth: ProviderDoctorAuth;\n}\n\n/** Compatibility name for callers using the design-document terminology. */\nexport type ResolvedProviderConfig = ResolvedProviderTarget;\n\nexport type ProviderDoctorAddressPolicy =\n\t| { kind: \"public\"; requireAddressPinning: true }\n\t| { kind: \"loopback-only\"; requireAddressPinning: false };\n\nexport interface ProviderDoctorTransportRequest {\n\turl: URL;\n\tmethod: \"GET\" | \"POST\";\n\tredirect: \"manual\";\n\tsignal: AbortSignal;\n\taddressPolicy: ProviderDoctorAddressPolicy;\n\tcreateHeaders: ProviderDoctorHeaderFactory;\n\t/** Bounded JSON payload; present only for opt-in Level-2 POST model probes. */\n\tbody?: string;\n\tcontentType?: \"application/json\";\n}\n\nexport interface ProviderDoctorTransportResponse {\n\tstatus: number;\n}\n\nexport interface ProviderDoctorTransport {\n\t/** Public requests are rejected unless the transport enforces DNS/address pinning. */\n\tpinsResolvedAddress?: boolean;\n\trequest(request: ProviderDoctorTransportRequest): Promise<ProviderDoctorTransportResponse>;\n}\n\nexport interface ProviderDoctorDependencies {\n\ttransport?: ProviderDoctorTransport;\n\t/** Level-2 only. Called by the transport immediately before each request is dispatched. */\n\tresolveAuthHeaders?: ProviderDoctorAuthHeaderResolver;\n}\n\nexport interface ProviderDoctorOptions extends ProviderDoctorDependencies {\n\tlevel?: ProviderDoctorLevel;\n\tmodelId?: string;\n\t/** Level-2 opt-in only: the model probed with one minimal-token generative request. */\n\tprobeModelId?: string;\n\ttimeoutMs?: number;\n\tsignal?: AbortSignal;\n\tagentDir?: string;\n\t/** Path to the Kimi CLI config TOML consulted for the kimi-coding provider. Defaults to ~/.kimi/config.toml. */\n\tkimiConfigPath?: string;\n}\n\nexport interface ProviderDoctorCheck {\n\tname: string;\n\tstatus: ProviderDoctorCheckStatus;\n\tcode: ProviderDoctorCode;\n\tcategory?: DoctorErrorCategory;\n\tmessage?: string;\n\t/** Exact-category endpoint classification for network probe checks. */\n\tprobe?: EndpointProbeResult;\n}\n\nexport interface ProviderDoctorResult {\n\tprovider: string;\n\tstatus: \"ok\" | \"fail\";\n\tlevel: ProviderDoctorLevel;\n\torigin: ProviderOrigin;\n\tsource: string;\n\t/** Sanitized URL: userinfo, query, and fragment are always removed. */\n\ttargetUrl?: string;\n\t/** Backwards-compatible alias of targetUrl. */\n\tbaseUrl?: string;\n\tapi?: string;\n\tmodelId?: string;\n\tauthPresent: boolean;\n\t/** True only when an opt-in Level-2 model probe was dispatched; the request may incur provider costs. */\n\tcostWarning?: boolean;\n\tchecks: ProviderDoctorCheck[];\n\terror?: {\n\t\tcategory: DoctorErrorCategory;\n\t\tcode: ProviderDoctorCode;\n\t\tmessage: string;\n\t};\n}\n\ninterface ModelEndpointConfig {\n\tid: string;\n\tbaseUrl?: string;\n\tapi?: string;\n}\n\ninterface ProviderConfig {\n\tbaseUrl?: string;\n\tapiKey?: string;\n\tapi?: string;\n\theaders?: Record<string, string>;\n\tmodels?: ModelEndpointConfig[];\n}\n\ninterface ModelsConfig {\n\tproviders: Record<string, ProviderConfig>;\n}\n\ninterface AuthConfigEntry {\n\ttype: \"api_key\" | \"oauth\";\n}\n\ntype AuthConfig = Record<string, AuthConfigEntry>;\n\ntype LoadedConfig<T> = { kind: \"missing\" } | { kind: \"invalid\" } | { kind: \"ok\"; value: T };\n\ntype ProbeFailure = {\n\tcategory: DoctorErrorCategory;\n\tcode: ProviderDoctorCode;\n\tmessage: string;\n};\n\ninterface ProbeOutcome {\n\tcheck: ProviderDoctorCheck;\n\tfailure?: ProbeFailure;\n}\n\nconst DEFAULT_TIMEOUT_MS = 5_000;\nconst KNOWN_APIS = new Set<string>([\n\t\"openai-completions\",\n\t\"mistral-conversations\",\n\t\"openai-responses\",\n\t\"azure-openai-responses\",\n\t\"openai-codex-responses\",\n\t\"anthropic-messages\",\n\t\"bedrock-converse-stream\",\n\t\"google-generative-ai\",\n\t\"google-vertex\",\n]);\nconst OPENAI_COMPATIBLE_APIS = new Set<string>([\"openai-completions\", \"openai-responses\"]);\nconst ABORTED = Symbol(\"provider-doctor-aborted\");\n\n// Family-specific lists: node BlockList canonicalizes IPv4 checks to the v4-mapped v6 form,\n// so a combined list containing ::ffff:0:0/96 would block every IPv4 address.\nconst blockedPublicV4 = new BlockList();\nfor (const [address, prefix] of [\n\t[\"0.0.0.0\", 8],\n\t[\"10.0.0.0\", 8],\n\t[\"100.64.0.0\", 10],\n\t[\"127.0.0.0\", 8],\n\t[\"169.254.0.0\", 16],\n\t[\"172.16.0.0\", 12],\n\t[\"192.168.0.0\", 16],\n\t[\"224.0.0.0\", 4],\n\t[\"240.0.0.0\", 4],\n] as const) {\n\tblockedPublicV4.addSubnet(address, prefix, \"ipv4\");\n}\n// ::ffff:0:0/96 stays here on purpose: a v4-mapped IPv6 literal or DNS answer is anomalous\n// for a public origin and is rejected wholesale (fail closed), covering hex-form mappings too.\nconst blockedPublicV6 = new BlockList();\nfor (const [address, prefix] of [\n\t[\"::\", 128],\n\t[\"::1\", 128],\n\t[\"::ffff:0:0\", 96],\n\t[\"fc00::\", 7],\n\t[\"fe80::\", 10],\n\t[\"ff00::\", 8],\n] as const) {\n\tblockedPublicV6.addSubnet(address, prefix, \"ipv6\");\n}\n\nconst loopbackAddresses = new BlockList();\nloopbackAddresses.addSubnet(\"127.0.0.0\", 8, \"ipv4\");\nloopbackAddresses.addAddress(\"::1\", \"ipv6\");\nloopbackAddresses.addSubnet(\"::ffff:127.0.0.0\", 104, \"ipv6\");\n\n/** True when the literal IP address is a loopback address. Non-IP input is never loopback. */\nexport function isLoopbackAddress(address: string): boolean {\n\tconst family = isIP(address);\n\tif (family === 4) return loopbackAddresses.check(address, \"ipv4\");\n\tif (family === 6) return loopbackAddresses.check(address, \"ipv6\");\n\treturn false;\n}\n\n/** True when the literal IP address must not be dialed for a public origin. Non-IP input fails closed. */\nexport function isBlockedPublicAddress(address: string): boolean {\n\tconst family = isIP(address);\n\tif (family === 4) return blockedPublicV4.check(address, \"ipv4\");\n\tif (family === 6) return blockedPublicV6.check(address, \"ipv6\");\n\treturn true;\n}\n\nexport function getAgentDir(): string {\n\treturn getConfiguredAgentDir();\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isOptionalNonemptyString(value: unknown): value is string | undefined {\n\treturn value === undefined || (typeof value === \"string\" && value.length > 0);\n}\n\nfunction parseModelsConfig(value: unknown): ModelsConfig | undefined {\n\tif (!isRecord(value) || !isRecord(value.providers)) return undefined;\n\tconst providers: Record<string, ProviderConfig> = {};\n\n\tfor (const [providerId, rawProvider] of Object.entries(value.providers)) {\n\t\tif (!isRecord(rawProvider)) return undefined;\n\t\tif (\n\t\t\t!isOptionalNonemptyString(rawProvider.baseUrl) ||\n\t\t\t!isOptionalNonemptyString(rawProvider.apiKey) ||\n\t\t\t!isOptionalNonemptyString(rawProvider.api)\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tlet headers: Record<string, string> | undefined;\n\t\tif (rawProvider.headers !== undefined) {\n\t\t\tif (!isRecord(rawProvider.headers)) return undefined;\n\t\t\theaders = {};\n\t\t\tfor (const [name, headerValue] of Object.entries(rawProvider.headers)) {\n\t\t\t\tif (typeof headerValue !== \"string\") return undefined;\n\t\t\t\theaders[name] = headerValue;\n\t\t\t}\n\t\t}\n\n\t\tlet models: ModelEndpointConfig[] | undefined;\n\t\tif (rawProvider.models !== undefined) {\n\t\t\tif (!Array.isArray(rawProvider.models)) return undefined;\n\t\t\tmodels = [];\n\t\t\tfor (const rawModel of rawProvider.models) {\n\t\t\t\tif (\n\t\t\t\t\t!isRecord(rawModel) ||\n\t\t\t\t\ttypeof rawModel.id !== \"string\" ||\n\t\t\t\t\trawModel.id.length === 0 ||\n\t\t\t\t\t!isOptionalNonemptyString(rawModel.baseUrl) ||\n\t\t\t\t\t!isOptionalNonemptyString(rawModel.api)\n\t\t\t\t) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tmodels.push({ id: rawModel.id, baseUrl: rawModel.baseUrl, api: rawModel.api });\n\t\t\t}\n\t\t}\n\n\t\tproviders[providerId] = {\n\t\t\tbaseUrl: rawProvider.baseUrl,\n\t\t\tapiKey: rawProvider.apiKey,\n\t\t\tapi: rawProvider.api,\n\t\t\theaders,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\treturn { providers };\n}\n\nfunction parseAuthConfig(value: unknown): AuthConfig | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst auth: AuthConfig = {};\n\tfor (const [providerId, rawEntry] of Object.entries(value)) {\n\t\tif (!isRecord(rawEntry) || (rawEntry.type !== \"api_key\" && rawEntry.type !== \"oauth\")) return undefined;\n\t\tif (rawEntry.type === \"api_key\" && (typeof rawEntry.key !== \"string\" || rawEntry.key.length === 0)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tauth[providerId] = { type: rawEntry.type };\n\t}\n\treturn auth;\n}\n\nconst KIMI_PROVIDER_ID = \"kimi-coding\";\nconst TOML_BASIC_ESCAPES: Record<string, string> = {\n\t'\"': '\"',\n\t\"\\\\\": \"\\\\\",\n\tb: \"\\b\",\n\tf: \"\\f\",\n\tn: \"\\n\",\n\tr: \"\\r\",\n\tt: \"\\t\",\n};\n\ntype TomlQuote = \"basic\" | \"literal\" | \"multiline-basic\" | \"multiline-literal\";\n\ninterface TomlScanState {\n\tquote?: TomlQuote;\n\tcontainers: (\"[\" | \"{\")[];\n}\n\ninterface KimiTomlProviderEntry {\n\tname: string;\n\ttype?: string;\n\tbaseUrl?: string;\n\tmodelName?: string;\n\tapiKey?: string;\n}\n\ninterface KimiConfigValues {\n\tbaseUrl?: string;\n\tmodelName?: string;\n\tproviders: KimiTomlProviderEntry[];\n}\n\ntype KimiConfigLoad =\n\t| { kind: \"missing\" }\n\t| { kind: \"ok\"; value: KimiConfigValues }\n\t| { kind: \"invalid\"; line: number; reason: string };\n\nfunction findBasicStringEnd(text: string, start: number, multiline: boolean): number {\n\tfor (let index = start; index < text.length; index++) {\n\t\tif (text[index] === \"\\\\\") {\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (multiline ? text.startsWith('\"\"\"', index) : text[index] === '\"') return index;\n\t}\n\treturn -1;\n}\n\nfunction decodeTomlBasicString(body: string, multiline: boolean): { value: string } | { error: string } {\n\tlet value = \"\";\n\tfor (let index = 0; index < body.length; index++) {\n\t\tconst char = body[index];\n\t\tif (char !== \"\\\\\") {\n\t\t\tconst code = char.codePointAt(0) ?? 0;\n\t\t\tif (code < 0x20 && char !== \"\\t\" && !(multiline && (char === \"\\n\" || char === \"\\r\"))) {\n\t\t\t\treturn { error: \"invalid control character in string value\" };\n\t\t\t}\n\t\t\tvalue += char;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst escapeChar = body[index + 1];\n\t\tif (escapeChar === undefined) return { error: \"unterminated escape sequence\" };\n\t\tif (multiline && (escapeChar === \"\\n\" || escapeChar === \"\\r\")) {\n\t\t\tindex++;\n\t\t\twhile (index + 1 < body.length && /\\s/.test(body[index + 1])) index++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (escapeChar === \"u\" || escapeChar === \"U\") {\n\t\t\tconst width = escapeChar === \"u\" ? 4 : 8;\n\t\t\tconst hex = body.slice(index + 2, index + 2 + width);\n\t\t\tconst codePoint = /^[0-9a-fA-F]+$/.test(hex) && hex.length === width ? Number.parseInt(hex, 16) : -1;\n\t\t\tif (codePoint < 0 || codePoint > 0x10ffff || (codePoint >= 0xd800 && codePoint <= 0xdfff)) {\n\t\t\t\treturn { error: \"invalid unicode escape\" };\n\t\t\t}\n\t\t\tvalue += String.fromCodePoint(codePoint);\n\t\t\tindex += 1 + width;\n\t\t\tcontinue;\n\t\t}\n\t\tconst mapped = TOML_BASIC_ESCAPES[escapeChar];\n\t\tif (mapped === undefined) return { error: \"invalid escape sequence\" };\n\t\tvalue += mapped;\n\t\tindex++;\n\t}\n\treturn { value };\n}\n\n/** Parses one TOML string value. Errors are fixed and never include raw TOML content. */\nfunction parseTomlStringValue(raw: string, requireNonempty = true): { value: string } | { error: string } {\n\tconst text = raw.trim();\n\tconst multilineBasic = text.startsWith('\"\"\"');\n\tconst multilineLiteral = text.startsWith(\"'''\");\n\tconst basic = !multilineBasic && text.startsWith('\"');\n\tconst literal = !multilineLiteral && text.startsWith(\"'\");\n\tif (!multilineBasic && !multilineLiteral && !basic && !literal) {\n\t\treturn { error: \"value must be a quoted string\" };\n\t}\n\n\tconst delimiterWidth = multilineBasic || multilineLiteral ? 3 : 1;\n\tconst end =\n\t\tmultilineBasic || basic\n\t\t\t? findBasicStringEnd(text, delimiterWidth, multilineBasic)\n\t\t\t: text.indexOf(multilineLiteral ? \"'''\" : \"'\", delimiterWidth);\n\tif (end < 0) {\n\t\treturn {\n\t\t\terror:\n\t\t\t\tmultilineBasic || multilineLiteral ? \"unterminated multiline string value\" : \"unterminated string value\",\n\t\t};\n\t}\n\tif (text.slice(end + delimiterWidth).trim().length > 0) {\n\t\treturn { error: \"unexpected content after string value\" };\n\t}\n\n\tlet body = text.slice(delimiterWidth, end);\n\tif ((multilineBasic || multilineLiteral) && body.startsWith(\"\\n\")) body = body.slice(1);\n\tconst parsed =\n\t\tmultilineBasic || basic\n\t\t\t? decodeTomlBasicString(body, multilineBasic)\n\t\t\t: /[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f]/.test(body)\n\t\t\t\t? { error: \"invalid control character in string value\" as const }\n\t\t\t\t: { value: body };\n\tif (\"error\" in parsed) return parsed;\n\treturn requireNonempty && parsed.value.length === 0 ? { error: \"empty string value\" } : parsed;\n}\n\nfunction scanTomlLine(text: string, state: TomlScanState): { content: string; error?: string } {\n\tlet content = \"\";\n\tfor (let index = 0; index < text.length; index++) {\n\t\tconst char = text[index];\n\t\tif (state.quote === \"basic\") {\n\t\t\tcontent += char;\n\t\t\tif (char === \"\\\\\" && index + 1 < text.length) content += text[++index];\n\t\t\telse if (char === '\"') state.quote = undefined;\n\t\t\tcontinue;\n\t\t}\n\t\tif (state.quote === \"literal\") {\n\t\t\tcontent += char;\n\t\t\tif (char === \"'\") state.quote = undefined;\n\t\t\tcontinue;\n\t\t}\n\t\tif (state.quote === \"multiline-basic\") {\n\t\t\tif (text.startsWith('\"\"\"', index)) {\n\t\t\t\tcontent += '\"\"\"';\n\t\t\t\tindex += 2;\n\t\t\t\tstate.quote = undefined;\n\t\t\t} else {\n\t\t\t\tcontent += char;\n\t\t\t\tif (char === \"\\\\\" && index + 1 < text.length) content += text[++index];\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (state.quote === \"multiline-literal\") {\n\t\t\tif (text.startsWith(\"'''\", index)) {\n\t\t\t\tcontent += \"'''\";\n\t\t\t\tindex += 2;\n\t\t\t\tstate.quote = undefined;\n\t\t\t} else {\n\t\t\t\tcontent += char;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"#\") break;\n\t\tif (text.startsWith('\"\"\"', index)) {\n\t\t\tcontent += '\"\"\"';\n\t\t\tindex += 2;\n\t\t\tstate.quote = \"multiline-basic\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (text.startsWith(\"'''\", index)) {\n\t\t\tcontent += \"'''\";\n\t\t\tindex += 2;\n\t\t\tstate.quote = \"multiline-literal\";\n\t\t\tcontinue;\n\t\t}\n\t\tcontent += char;\n\t\tif (char === '\"') state.quote = \"basic\";\n\t\telse if (char === \"'\") state.quote = \"literal\";\n\t\telse if (char === \"[\" || char === \"{\") state.containers.push(char);\n\t\telse if (char === \"]\" || char === \"}\") {\n\t\t\tconst expected = char === \"]\" ? \"[\" : \"{\";\n\t\t\tif (state.containers.pop() !== expected) return { content, error: \"mismatched value delimiter\" };\n\t\t}\n\t}\n\tif (state.quote === \"basic\" || state.quote === \"literal\") {\n\t\treturn { content, error: \"unterminated string value\" };\n\t}\n\treturn { content };\n}\n\nfunction consumeTomlValue(\n\tlines: readonly string[],\n\tstartLine: number,\n\tinitial: string,\n): { value?: string; endLine: number; error?: string } {\n\tconst state: TomlScanState = { containers: [] };\n\tconst chunks: string[] = [];\n\tfor (let line = startLine; line < lines.length; line++) {\n\t\tconst scanned = scanTomlLine(line === startLine ? initial : lines[line], state);\n\t\tchunks.push(scanned.content);\n\t\tif (scanned.error) return { endLine: line, error: scanned.error };\n\t\tif (!state.quote && state.containers.length === 0) {\n\t\t\tconst value = chunks.join(\"\\n\").trim();\n\t\t\treturn value.length > 0\n\t\t\t\t? { value, endLine: line }\n\t\t\t\t: { endLine: startLine, error: \"assignment value is missing\" };\n\t\t}\n\t}\n\treturn {\n\t\tendLine: startLine,\n\t\terror: state.quote ? \"unterminated multiline string value\" : \"unterminated compound value\",\n\t};\n}\n\nfunction findTomlTopLevelCharacter(text: string, wanted: string): number {\n\tconst state: TomlScanState = { containers: [] };\n\tfor (let index = 0; index < text.length; index++) {\n\t\tconst char = text[index];\n\t\tif (state.quote === \"basic\" || state.quote === \"multiline-basic\") {\n\t\t\tif (char === \"\\\\\") index++;\n\t\t\telse if (state.quote === \"basic\" && char === '\"') state.quote = undefined;\n\t\t\telse if (state.quote === \"multiline-basic\" && text.startsWith('\"\"\"', index)) {\n\t\t\t\tstate.quote = undefined;\n\t\t\t\tindex += 2;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (state.quote === \"literal\" || state.quote === \"multiline-literal\") {\n\t\t\tconst delimiter = state.quote === \"literal\" ? \"'\" : \"'''\";\n\t\t\tif (text.startsWith(delimiter, index)) {\n\t\t\t\tstate.quote = undefined;\n\t\t\t\tindex += delimiter.length - 1;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"#\") return -1;\n\t\tif (text.startsWith('\"\"\"', index)) {\n\t\t\tstate.quote = \"multiline-basic\";\n\t\t\tindex += 2;\n\t\t} else if (text.startsWith(\"'''\", index)) {\n\t\t\tstate.quote = \"multiline-literal\";\n\t\t\tindex += 2;\n\t\t} else if (char === '\"') state.quote = \"basic\";\n\t\telse if (char === \"'\") state.quote = \"literal\";\n\t\telse if (char === \"[\" || char === \"{\") state.containers.push(char);\n\t\telse if (char === \"]\" || char === \"}\") state.containers.pop();\n\t\telse if (char === wanted && state.containers.length === 0) return index;\n\t}\n\treturn -1;\n}\n\nfunction parseTomlDottedKey(raw: string): string[] | undefined {\n\tconst components: string[] = [];\n\tlet index = 0;\n\twhile (index < raw.length) {\n\t\twhile (/\\s/.test(raw[index] ?? \"\")) index++;\n\t\tlet component: string | undefined;\n\t\tif (raw[index] === '\"') {\n\t\t\tconst end = findBasicStringEnd(raw, index + 1, false);\n\t\t\tif (end < 0) return undefined;\n\t\t\tconst parsed = parseTomlStringValue(raw.slice(index, end + 1), false);\n\t\t\tif (\"error\" in parsed) return undefined;\n\t\t\tcomponent = parsed.value;\n\t\t\tindex = end + 1;\n\t\t} else if (raw[index] === \"'\") {\n\t\t\tconst end = raw.indexOf(\"'\", index + 1);\n\t\t\tif (end < 0) return undefined;\n\t\t\tcomponent = raw.slice(index + 1, end);\n\t\t\tindex = end + 1;\n\t\t} else {\n\t\t\tconst match = /^[A-Za-z0-9_-]+/.exec(raw.slice(index));\n\t\t\tif (!match) return undefined;\n\t\t\tcomponent = match[0];\n\t\t\tindex += match[0].length;\n\t\t}\n\t\tcomponents.push(component);\n\t\twhile (/\\s/.test(raw[index] ?? \"\")) index++;\n\t\tif (index === raw.length) return components;\n\t\tif (raw[index] !== \".\") return undefined;\n\t\tindex++;\n\t\tif (index === raw.length) return undefined;\n\t}\n\treturn undefined;\n}\n\nfunction splitTomlTopLevel(raw: string): string[] {\n\tconst parts: string[] = [];\n\tlet start = 0;\n\tfor (let index = 0; index < raw.length; index++) {\n\t\tif (raw[index] !== \",\") continue;\n\t\tconst relative = findTomlTopLevelCharacter(raw.slice(start, index + 1), \",\");\n\t\tif (relative !== index - start) continue;\n\t\tparts.push(raw.slice(start, index).trim());\n\t\tstart = index + 1;\n\t}\n\tparts.push(raw.slice(start).trim());\n\treturn parts;\n}\n\nfunction isValidTomlScalar(raw: string): boolean {\n\treturn (\n\t\traw === \"true\" ||\n\t\traw === \"false\" ||\n\t\t/^[+-]?(?:0|[1-9](?:_?\\d)*)$/.test(raw) ||\n\t\t/^[+-]?0x[0-9A-Fa-f](?:_?[0-9A-Fa-f])*$/.test(raw) ||\n\t\t/^[+-]?0o[0-7](?:_?[0-7])*$/.test(raw) ||\n\t\t/^[+-]?0b[01](?:_?[01])*$/.test(raw) ||\n\t\t/^[+-]?(?:(?:0|[1-9](?:_?\\d)*)\\.(?:\\d(?:_?\\d)*)(?:[eE][+-]?\\d(?:_?\\d)*)?|(?:0|[1-9](?:_?\\d)*)[eE][+-]?\\d(?:_?\\d)*|inf|nan)$/.test(\n\t\t\traw,\n\t\t) ||\n\t\t/^\\d{4}-\\d{2}-\\d{2}(?:[Tt ]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:[Zz]|[+-]\\d{2}:\\d{2})?)?$/.test(raw) ||\n\t\t/^\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?$/.test(raw)\n\t);\n}\n\nfunction isValidTomlValue(raw: string): boolean {\n\tconst text = raw.trim();\n\tif (text.startsWith('\"') || text.startsWith(\"'\")) return !(\"error\" in parseTomlStringValue(text, false));\n\tif (text.startsWith(\"[\") && text.endsWith(\"]\")) {\n\t\tconst parts = splitTomlTopLevel(text.slice(1, -1));\n\t\tif (parts.at(-1) === \"\") parts.pop();\n\t\treturn parts.every((part) => part.length > 0 && isValidTomlValue(part));\n\t}\n\tif (text.startsWith(\"{\") && text.endsWith(\"}\")) {\n\t\tconst body = text.slice(1, -1).trim();\n\t\tif (body.length === 0) return true;\n\t\treturn splitTomlTopLevel(body).every((part) => {\n\t\t\tconst equals = findTomlTopLevelCharacter(part, \"=\");\n\t\t\treturn equals > 0 && !!parseTomlDottedKey(part.slice(0, equals)) && isValidTomlValue(part.slice(equals + 1));\n\t\t});\n\t}\n\treturn isValidTomlScalar(text);\n}\n\nfunction parseTomlTable(line: string): { components?: string[]; array?: boolean; error?: string } {\n\tconst state: TomlScanState = { containers: [] };\n\tconst scanned = scanTomlLine(line, state);\n\tif (scanned.error || state.quote || state.containers.length > 0) return { error: \"malformed table header\" };\n\tconst text = scanned.content.trim();\n\tconst array = text.startsWith(\"[[\");\n\tif (array ? !text.endsWith(\"]]\") : !text.endsWith(\"]\")) return { error: \"malformed table header\" };\n\tconst inner = text.slice(array ? 2 : 1, array ? -2 : -1).trim();\n\tconst components = parseTomlDottedKey(inner);\n\treturn components && components.length > 0 ? { components, array } : { error: \"malformed table header\" };\n}\n\n/**\n * Strict Kimi TOML subset reader. It validates every table/assignment and generic TOML value,\n * but extracts only root `base_url`/`model_name` and `[providers.<name>]` string fields. Fixed\n * line-number errors ensure credentials and other file content are never echoed.\n */\nfunction loadKimiConfig(path: string): KimiConfigLoad {\n\tif (!existsSync(path)) return { kind: \"missing\" };\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(path, \"utf-8\");\n\t} catch {\n\t\treturn { kind: \"invalid\", line: 0, reason: \"file is unreadable\" };\n\t}\n\tconst value: KimiConfigValues = { providers: [] };\n\tconst lines = content.split(/\\r?\\n/);\n\tconst assignments = new Set<string>();\n\tlet table: KimiTomlProviderEntry | \"root\" | \"other\" = \"root\";\n\tlet scope = \"root\";\n\tfor (let index = 0; index < lines.length; index++) {\n\t\tconst line = lines[index].trim();\n\t\tif (line.length === 0 || line.startsWith(\"#\")) continue;\n\t\tif (line.startsWith(\"[\")) {\n\t\t\tconst parsed = parseTomlTable(line);\n\t\t\tif (parsed.error || !parsed.components) {\n\t\t\t\treturn { kind: \"invalid\", line: index + 1, reason: parsed.error ?? \"malformed table header\" };\n\t\t\t}\n\t\t\tconst [first, name] = parsed.components;\n\t\t\tif (first === \"providers\" && parsed.array) {\n\t\t\t\treturn { kind: \"invalid\", line: index + 1, reason: \"provider table cannot be an array\" };\n\t\t\t}\n\t\t\tif (first === \"providers\" && parsed.components.length === 2 && name !== undefined && name.length > 0) {\n\t\t\t\tconst entry: KimiTomlProviderEntry = { name };\n\t\t\t\tvalue.providers.push(entry);\n\t\t\t\ttable = entry;\n\t\t\t} else {\n\t\t\t\ttable = \"other\";\n\t\t\t}\n\t\t\tscope = `${parsed.array ? \"array\" : \"table\"}:${JSON.stringify(parsed.components)}`;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst assignmentLine = index;\n\t\tconst equals = findTomlTopLevelCharacter(line, \"=\");\n\t\tconst key = equals > 0 ? parseTomlDottedKey(line.slice(0, equals)) : undefined;\n\t\tif (!key || key.length === 0) return { kind: \"invalid\", line: index + 1, reason: \"invalid assignment\" };\n\t\tconst consumed = consumeTomlValue(lines, index, line.slice(equals + 1));\n\t\tif (consumed.error || consumed.value === undefined) {\n\t\t\treturn { kind: \"invalid\", line: assignmentLine + 1, reason: consumed.error ?? \"invalid assignment value\" };\n\t\t}\n\t\tindex = consumed.endLine;\n\t\tif (!isValidTomlValue(consumed.value)) {\n\t\t\treturn { kind: \"invalid\", line: assignmentLine + 1, reason: \"invalid assignment value\" };\n\t\t}\n\t\tconst assignmentId = `${scope}:${JSON.stringify(key)}`;\n\t\tif (assignments.has(assignmentId)) {\n\t\t\treturn { kind: \"invalid\", line: assignmentLine + 1, reason: \"duplicate assignment\" };\n\t\t}\n\t\tassignments.add(assignmentId);\n\t\tif (key.length !== 1 || table === \"other\") continue;\n\n\t\tconst keyName = key[0];\n\t\tconst relevant =\n\t\t\ttable === \"root\"\n\t\t\t\t? keyName === \"base_url\" || keyName === \"model_name\"\n\t\t\t\t: keyName === \"base_url\" ||\n\t\t\t\t\tkeyName === \"model_name\" ||\n\t\t\t\t\tkeyName === \"model\" ||\n\t\t\t\t\tkeyName === \"type\" ||\n\t\t\t\t\tkeyName === \"api_key\";\n\t\tif (!relevant) continue;\n\t\tconst parsedValue = parseTomlStringValue(consumed.value);\n\t\tif (\"error\" in parsedValue) return { kind: \"invalid\", line: assignmentLine + 1, reason: parsedValue.error };\n\t\tif (table === \"root\") {\n\t\t\tif (keyName === \"base_url\") value.baseUrl = parsedValue.value;\n\t\t\telse value.modelName = parsedValue.value;\n\t\t} else {\n\t\t\tif (keyName === \"base_url\") table.baseUrl = parsedValue.value;\n\t\t\telse if (keyName === \"type\") table.type = parsedValue.value;\n\t\t\telse if (keyName === \"api_key\") table.apiKey = parsedValue.value;\n\t\t\telse table.modelName = parsedValue.value;\n\t\t}\n\t}\n\treturn { kind: \"ok\", value };\n}\n\nfunction nonemptyEnv(name: string): string | undefined {\n\tconst value = process.env[name];\n\treturn value && value.length > 0 ? value : undefined;\n}\n\ninterface KimiResolution {\n\tbaseUrl?: string;\n\tmodelName?: string;\n\tbaseUrlSource?: \"kimi-environment\" | \"kimi-config-toml\";\n\t/** First `[providers.<name>]` entry with `type = \"openai_legacy\"` and a base URL (§10.2). */\n\tcustomProvider?: { name: string; baseUrl: string; modelName?: string; apiKey?: string };\n\tfailure?: { line: number; reason: string };\n}\n\nfunction resolveKimiConfig(kimiConfigPath: string | undefined): KimiResolution {\n\tconst path = kimiConfigPath ?? join(homedir(), \".kimi\", \"config.toml\");\n\tconst loaded = loadKimiConfig(path);\n\tif (loaded.kind === \"invalid\") return { failure: { line: loaded.line, reason: loaded.reason } };\n\tconst fileValues: KimiConfigValues = loaded.kind === \"ok\" ? loaded.value : { providers: [] };\n\tconst envBaseUrl = nonemptyEnv(\"KIMI_BASE_URL\");\n\tconst envModelName = nonemptyEnv(\"KIMI_MODEL_NAME\");\n\tconst custom = fileValues.providers.find((entry) => entry.type === \"openai_legacy\" && entry.baseUrl);\n\treturn {\n\t\tbaseUrl: envBaseUrl ?? fileValues.baseUrl,\n\t\tmodelName: envModelName ?? fileValues.modelName,\n\t\tbaseUrlSource: envBaseUrl ? \"kimi-environment\" : fileValues.baseUrl ? \"kimi-config-toml\" : undefined,\n\t\tcustomProvider: custom\n\t\t\t? { name: custom.name, baseUrl: custom.baseUrl as string, modelName: custom.modelName, apiKey: custom.apiKey }\n\t\t\t: undefined,\n\t};\n}\n\nfunction loadConfig<T>(path: string, parse: (value: unknown) => T | undefined, allowComments = false): LoadedConfig<T> {\n\tif (!existsSync(path)) return { kind: \"missing\" };\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst parsed = JSON.parse(allowComments ? stripJsonComments(content) : content) as unknown;\n\t\tconst value = parse(parsed);\n\t\treturn value ? { kind: \"ok\", value } : { kind: \"invalid\" };\n\t} catch {\n\t\treturn { kind: \"invalid\" };\n\t}\n}\n\nexport function normalizedUrlHostname(url: URL): string {\n\treturn normalizedHostname(url);\n}\n\nfunction normalizedHostname(url: URL): string {\n\tconst hostname = url.hostname.toLowerCase();\n\tconst unwrapped = hostname.startsWith(\"[\") && hostname.endsWith(\"]\") ? hostname.slice(1, -1) : hostname;\n\treturn unwrapped.endsWith(\".\") ? unwrapped.slice(0, -1) : unwrapped;\n}\n\nfunction isLiteralLoopback(hostname: string): boolean {\n\tif (hostname === \"localhost\" || hostname === \"::1\") return true;\n\tif (isIP(hostname) !== 4) return false;\n\treturn Number(hostname.split(\".\")[0]) === 127;\n}\n\nfunction isBlockedPublicHost(hostname: string): boolean {\n\tif (hostname === \"localhost\" || hostname.endsWith(\".localhost\")) return true;\n\tif (isIP(hostname) === 0) return false;\n\treturn isBlockedPublicAddress(hostname);\n}\n\nfunction sanitizeUrl(rawUrl: string): URL | undefined {\n\ttry {\n\t\tconst url = new URL(rawUrl);\n\t\turl.username = \"\";\n\t\turl.password = \"\";\n\t\turl.search = \"\";\n\t\turl.hash = \"\";\n\t\treturn url;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function canonicalProviderEndpointUrl(rawUrl: string | undefined): string | undefined {\n\tif (!rawUrl) return undefined;\n\tconst url = sanitizeUrl(rawUrl);\n\tif (!url) return undefined;\n\tconst hostname = normalizedHostname(url);\n\tconst host = isIP(hostname) === 6 ? `[${hostname}]` : hostname;\n\tconst pathname = url.pathname.replace(/\\/+$/, \"\") || \"/\";\n\treturn `${url.protocol}//${host}${url.port ? `:${url.port}` : \"\"}${pathname}`;\n}\n\nfunction credentialBindingMatchesTarget(\n\tbinding: ProviderDoctorCredentialBinding,\n\ttarget: ResolvedProviderTarget,\n): boolean {\n\treturn (\n\t\tbinding.origin === target.origin &&\n\t\tbinding.source === target.source &&\n\t\tbinding.baseUrl === canonicalProviderEndpointUrl(target.endpoint.baseUrl) &&\n\t\tbinding.api === target.endpoint.api &&\n\t\tbinding.modelId === target.endpoint.modelId\n\t);\n}\n\nfunction appendPath(url: URL, segment: string): URL {\n\tconst next = new URL(url.href);\n\tnext.pathname = `${next.pathname.replace(/\\/$/, \"\")}/${segment}`;\n\treturn next;\n}\n\nfunction makeRootProbeUrl(url: URL, origin: ProviderOrigin): URL {\n\tif (origin !== \"local-proxy\") return new URL(url.href);\n\tconst health = new URL(url.href);\n\thealth.pathname = \"/health\";\n\treturn health;\n}\n\nfunction publicResult(\n\ttarget: ResolvedProviderTarget,\n\tlevel: ProviderDoctorLevel,\n\tchecks: ProviderDoctorCheck[],\n\turl: URL | undefined,\n\tfailure?: ProbeFailure,\n\tcostWarning?: boolean,\n): ProviderDoctorResult {\n\tconst targetUrl = url?.href;\n\treturn {\n\t\tprovider: target.providerId,\n\t\tstatus: failure ? \"fail\" : \"ok\",\n\t\tlevel,\n\t\torigin: target.origin,\n\t\tsource: target.source,\n\t\ttargetUrl,\n\t\tbaseUrl: targetUrl,\n\t\tapi: target.endpoint.api,\n\t\tmodelId: target.endpoint.modelId,\n\t\tauthPresent: target.auth.present,\n\t\t...(costWarning ? { costWarning: true } : {}),\n\t\tchecks,\n\t\terror: failure,\n\t};\n}\n\nfunction unresolvedFailure(\n\tproviderId: string,\n\tlevel: ProviderDoctorLevel,\n\tcode: ProviderDoctorCode,\n\tmessage: string,\n): ProviderDoctorResult {\n\tconst check: ProviderDoctorCheck = { name: \"config\", status: \"fail\", category: \"config\", code, message };\n\treturn {\n\t\tprovider: providerId,\n\t\tstatus: \"fail\",\n\t\tlevel,\n\t\torigin: \"unknown\",\n\t\tsource: \"unresolved\",\n\t\tauthPresent: false,\n\t\tchecks: [check],\n\t\terror: { category: \"config\", code, message },\n\t};\n}\n\nfunction staticChecks(target: ResolvedProviderTarget): {\n\tchecks: ProviderDoctorCheck[];\n\turl?: URL;\n\tfailure?: ProbeFailure;\n} {\n\tconst checks: ProviderDoctorCheck[] = [\n\t\t{ name: \"config-present\", status: \"ok\", code: \"ok\", message: \"Provider configuration resolved\" },\n\t];\n\tif (target.origin === \"custom-openai-compatible\") {\n\t\tchecks.push({\n\t\t\tname: \"native-provider-checks\",\n\t\t\tstatus: \"skipped\",\n\t\t\tcode: \"ok\",\n\t\t\tmessage: \"Custom OpenAI-compatible endpoint; native-only provider checks skipped\",\n\t\t});\n\t}\n\tlet failure: ProbeFailure | undefined;\n\tconst recordFailure = (next: ProbeFailure): void => {\n\t\tfailure ??= next;\n\t};\n\n\tconst requestedModel = target.endpoint.modelId;\n\tconst modelIds = target.endpoint.modelIds ?? [];\n\tif (!requestedModel) {\n\t\tchecks.push({ name: \"model-provider-relation\", status: \"skipped\", code: \"ok\", message: \"No model selected\" });\n\t} else if (!modelIds.includes(requestedModel)) {\n\t\tconst next: ProbeFailure = {\n\t\t\tcategory: \"model\",\n\t\t\tcode: \"model-provider-mismatch\",\n\t\t\tmessage: \"Selected model does not belong to the provider\",\n\t\t};\n\t\tchecks.push({ name: \"model-provider-relation\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t} else {\n\t\tchecks.push({ name: \"model-provider-relation\", status: \"ok\", code: \"ok\", message: \"Model belongs to provider\" });\n\t}\n\n\tconst api = target.endpoint.api;\n\tif (!api) {\n\t\tconst next: ProbeFailure = { category: \"config\", code: \"api-missing\", message: \"Provider API type is missing\" };\n\t\tchecks.push({ name: \"api\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t} else if (\n\t\t!KNOWN_APIS.has(api) ||\n\t\t(target.origin === \"custom-openai-compatible\" && !OPENAI_COMPATIBLE_APIS.has(api))\n\t) {\n\t\tconst next: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"api-unsupported\",\n\t\t\tmessage: \"Provider API type is unsupported\",\n\t\t};\n\t\tchecks.push({ name: \"api\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t} else {\n\t\tchecks.push({ name: \"api\", status: \"ok\", code: \"ok\", message: \"Provider API type is supported\" });\n\t}\n\n\tlet url: URL | undefined;\n\tif (!target.endpoint.baseUrl) {\n\t\tconst next: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"base-url-missing\",\n\t\t\tmessage: \"Provider base URL is missing\",\n\t\t};\n\t\tchecks.push({ name: \"base-url\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t} else {\n\t\turl = sanitizeUrl(target.endpoint.baseUrl);\n\t\tif (!url) {\n\t\t\tconst next: ProbeFailure = {\n\t\t\t\tcategory: \"config\",\n\t\t\t\tcode: \"base-url-invalid\",\n\t\t\t\tmessage: \"Provider base URL is invalid\",\n\t\t\t};\n\t\t\tchecks.push({ name: \"base-url\", status: \"fail\", ...next });\n\t\t\trecordFailure(next);\n\t\t} else {\n\t\t\tconst allowedScheme =\n\t\t\t\ttarget.origin === \"local-proxy\"\n\t\t\t\t\t? url.protocol === \"http:\" || url.protocol === \"https:\"\n\t\t\t\t\t: url.protocol === \"https:\";\n\t\t\tif (!allowedScheme) {\n\t\t\t\tconst next: ProbeFailure = {\n\t\t\t\t\tcategory: \"config\",\n\t\t\t\t\tcode: \"url-scheme-unsupported\",\n\t\t\t\t\tmessage: \"Provider URL scheme is not allowed\",\n\t\t\t\t};\n\t\t\t\tchecks.push({ name: \"base-url\", status: \"fail\", ...next });\n\t\t\t\trecordFailure(next);\n\t\t\t} else {\n\t\t\t\tchecks.push({ name: \"base-url\", status: \"ok\", code: \"ok\", message: \"Provider base URL is valid\" });\n\t\t\t}\n\t\t}\n\t}\n\n\tif (target.origin === \"unknown\") {\n\t\tconst next: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"origin-unsupported\",\n\t\t\tmessage: \"Provider origin is unsupported\",\n\t\t};\n\t\tchecks.push({ name: \"origin-policy\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t} else if (url) {\n\t\tconst hostname = normalizedHostname(url);\n\t\tconst blocked = target.origin === \"local-proxy\" ? !isLiteralLoopback(hostname) : isBlockedPublicHost(hostname);\n\t\tif (blocked) {\n\t\t\tconst next: ProbeFailure = {\n\t\t\t\tcategory: \"config\",\n\t\t\t\tcode: \"address-policy-blocked\",\n\t\t\t\tmessage: \"Provider address is blocked by origin policy\",\n\t\t\t};\n\t\t\tchecks.push({ name: \"origin-policy\", status: \"fail\", ...next });\n\t\t\trecordFailure(next);\n\t\t} else {\n\t\t\tchecks.push({ name: \"origin-policy\", status: \"ok\", code: \"ok\", message: \"Provider origin policy passed\" });\n\t\t}\n\t} else {\n\t\tchecks.push({ name: \"origin-policy\", status: \"skipped\", code: \"ok\", message: \"No valid URL to inspect\" });\n\t}\n\n\tif (target.auth.present) {\n\t\tchecks.push({ name: \"auth-present\", status: \"ok\", code: \"ok\", message: \"Authentication is configured\" });\n\t} else if (target.origin === \"custom-openai-compatible\" || target.origin === \"local-proxy\") {\n\t\t// Native login checks do not apply: custom/local OpenAI-compatible endpoints may be keyless.\n\t\tchecks.push({\n\t\t\tname: \"auth-present\",\n\t\t\tstatus: \"skipped\",\n\t\t\tcode: \"ok\",\n\t\t\tmessage: \"No credential configured; custom endpoints may be keyless\",\n\t\t});\n\t} else {\n\t\tconst next: ProbeFailure = {\n\t\t\tcategory: \"auth\",\n\t\t\tcode: \"auth-missing\",\n\t\t\tmessage: \"Authentication is not configured\",\n\t\t};\n\t\tchecks.push({ name: \"auth-present\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t}\n\n\treturn { checks, url, failure };\n}\n\ntype ProbeEndpointKind = \"root\" | \"models\" | \"model-probe\";\n\nfunction classifyProbe(name: string, kind: ProbeEndpointKind, status: number): ProbeOutcome {\n\tconst forModels = kind === \"models\";\n\tif (Number.isInteger(status) && status >= 200 && status < 300) {\n\t\tconst probe: EndpointProbeResult = { reachable: true, authenticated: true, status, category: \"ok\" };\n\t\tif (forModels) probe.modelsSupported = true;\n\t\treturn { check: { name, status: \"ok\", code: \"ok\", message: `HTTP ${status}`, probe } };\n\t}\n\tif (status >= 300 && status < 400) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"redirect-blocked\",\n\t\t\tmessage: \"Provider probe returned a blocked redirect\",\n\t\t};\n\t\treturn { check: { name, status: \"fail\", ...failure }, failure };\n\t}\n\tif (status === 401 || status === 403) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"auth\",\n\t\t\tcode: \"authentication-failed\",\n\t\t\tmessage: \"Provider rejected authentication\",\n\t\t};\n\t\tconst probe: EndpointProbeResult = { reachable: true, authenticated: false, status, category: \"auth\" };\n\t\treturn { check: { name, status: \"fail\", ...failure, probe }, failure };\n\t}\n\tif (status === 404 || status === 405 || status === 501) {\n\t\t// A root or /models 404 is neutral: OpenAI-compatible servers may not expose these paths.\n\t\tconst probe: EndpointProbeResult = { reachable: true, status, category: \"unsupported-endpoint\" };\n\t\tif (forModels) probe.modelsSupported = false;\n\t\treturn {\n\t\t\tcheck: {\n\t\t\t\tname,\n\t\t\t\tstatus: \"unsupported\",\n\t\t\t\tcode: \"endpoint-unsupported\",\n\t\t\t\tmessage: `HTTP ${status}; endpoint is not required`,\n\t\t\t\tprobe,\n\t\t\t},\n\t\t};\n\t}\n\tif (status >= 500 && status <= 599) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"server\",\n\t\t\tcode: \"server-error\",\n\t\t\tmessage: \"Provider endpoint returned a server error\",\n\t\t};\n\t\tconst probe: EndpointProbeResult = { reachable: true, status, category: \"server\" };\n\t\treturn { check: { name, status: \"fail\", ...failure, probe }, failure };\n\t}\n\tif (status === 408 || status === 429) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"network\",\n\t\t\tcode: \"network-failure\",\n\t\t\tmessage: \"Provider probe failed at the network boundary\",\n\t\t};\n\t\tconst probe: EndpointProbeResult = { reachable: true, status, category: \"network\" };\n\t\treturn { check: { name, status: \"fail\", ...failure, probe }, failure };\n\t}\n\n\tconst failure: ProbeFailure = {\n\t\tcategory: \"config\",\n\t\tcode: \"unexpected-response\",\n\t\tmessage: \"Provider probe returned an unexpected response\",\n\t};\n\treturn { check: { name, status: \"fail\", ...failure }, failure };\n}\n\nfunction createComposedController(\n\tsignal: AbortSignal | undefined,\n\ttimeoutMs: number,\n): {\n\tcontroller: AbortController;\n\tabortKind: () => \"aborted\" | \"timeout\" | undefined;\n\tdispose: () => void;\n} {\n\tconst controller = new AbortController();\n\tlet kind: \"aborted\" | \"timeout\" | undefined;\n\tconst abortFromCaller = (): void => {\n\t\tkind ??= \"aborted\";\n\t\tcontroller.abort();\n\t};\n\tif (signal?.aborted) abortFromCaller();\n\telse signal?.addEventListener(\"abort\", abortFromCaller, { once: true });\n\tconst timeout = setTimeout(() => {\n\t\tkind ??= \"timeout\";\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\n\treturn {\n\t\tcontroller,\n\t\tabortKind: () => kind,\n\t\tdispose: () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tsignal?.removeEventListener(\"abort\", abortFromCaller);\n\t\t},\n\t};\n}\n\nfunction requestWithAbort(\n\ttransport: ProviderDoctorTransport,\n\trequest: ProviderDoctorTransportRequest,\n): Promise<ProviderDoctorTransportResponse> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (request.signal.aborted) {\n\t\t\treject(ABORTED);\n\t\t\treturn;\n\t\t}\n\t\tconst onAbort = (): void => reject(ABORTED);\n\t\trequest.signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\tlet pending: Promise<ProviderDoctorTransportResponse>;\n\t\ttry {\n\t\t\tpending = transport.request(request);\n\t\t} catch (error) {\n\t\t\trequest.signal.removeEventListener(\"abort\", onAbort);\n\t\t\treject(error instanceof ProviderDoctorAuthMaterializationError ? error : undefined);\n\t\t\treturn;\n\t\t}\n\t\tvoid pending.then(\n\t\t\t(response) => {\n\t\t\t\trequest.signal.removeEventListener(\"abort\", onAbort);\n\t\t\t\tresolve(response);\n\t\t\t},\n\t\t\t(error: unknown) => {\n\t\t\t\trequest.signal.removeEventListener(\"abort\", onAbort);\n\t\t\t\treject(error instanceof ProviderDoctorAuthMaterializationError ? error : undefined);\n\t\t\t},\n\t\t);\n\t});\n}\n\ninterface ProbePayload {\n\tbody: string;\n\tcontentType: \"application/json\";\n}\n\nasync function runProbe(\n\tname: string,\n\tkind: ProbeEndpointKind,\n\turl: URL,\n\ttransport: ProviderDoctorTransport,\n\taddressPolicy: ProviderDoctorAddressPolicy,\n\tcreateHeaders: ProviderDoctorHeaderFactory,\n\tcontroller: ReturnType<typeof createComposedController>,\n\tpayload?: ProbePayload,\n): Promise<ProbeOutcome> {\n\ttry {\n\t\tconst response = await requestWithAbort(transport, {\n\t\t\turl,\n\t\t\tmethod: payload ? \"POST\" : \"GET\",\n\t\t\tredirect: \"manual\",\n\t\t\tsignal: controller.controller.signal,\n\t\t\taddressPolicy,\n\t\t\tcreateHeaders,\n\t\t\tbody: payload?.body,\n\t\t\tcontentType: payload?.contentType,\n\t\t});\n\t\treturn classifyProbe(name, kind, response.status);\n\t} catch (error) {\n\t\tif (error instanceof ProviderDoctorAuthMaterializationError) {\n\t\t\tconst failure: ProbeFailure = {\n\t\t\t\tcategory: \"auth\",\n\t\t\t\tcode: \"auth-materialization-failed\",\n\t\t\t\tmessage: \"Configured authentication could not be materialized; verify auth and config references\",\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tcheck: {\n\t\t\t\t\tname,\n\t\t\t\t\tstatus: \"fail\",\n\t\t\t\t\t...failure,\n\t\t\t\t\tprobe: { reachable: false, authenticated: false, category: \"auth\" },\n\t\t\t\t},\n\t\t\t\tfailure,\n\t\t\t};\n\t\t}\n\t\tconst abortKind = controller.abortKind();\n\t\tconst failure: ProbeFailure = abortKind\n\t\t\t? {\n\t\t\t\t\tcategory: \"network\",\n\t\t\t\t\tcode: abortKind === \"timeout\" ? \"request-timeout\" : \"request-aborted\",\n\t\t\t\t\tmessage: abortKind === \"timeout\" ? \"Provider probe timed out\" : \"Provider probe was aborted\",\n\t\t\t\t}\n\t\t\t: { category: \"network\", code: \"network-failure\", message: \"Provider transport failed\" };\n\t\treturn {\n\t\t\tcheck: { name, status: \"fail\", ...failure, probe: { reachable: false, category: \"network\" } },\n\t\t\tfailure,\n\t\t};\n\t}\n}\n\n/** Minimal-token generative probe payload; never includes tools (no tool-call probe). */\nfunction modelProbeSpec(api: string, modelId: string): { path: string; payload: ProbePayload } | undefined {\n\tif (api === \"openai-completions\") {\n\t\treturn {\n\t\t\tpath: \"chat/completions\",\n\t\t\tpayload: {\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel: modelId,\n\t\t\t\t\tmessages: [{ role: \"user\", content: \"ping\" }],\n\t\t\t\t\tmax_tokens: 1,\n\t\t\t\t\tstream: false,\n\t\t\t\t}),\n\t\t\t\tcontentType: \"application/json\",\n\t\t\t},\n\t\t};\n\t}\n\tif (api === \"openai-responses\") {\n\t\treturn {\n\t\t\tpath: \"responses\",\n\t\t\tpayload: {\n\t\t\t\t// The responses API rejects max_output_tokens below 16; still the minimal request.\n\t\t\t\tbody: JSON.stringify({ model: modelId, input: \"ping\", max_output_tokens: 16, stream: false }),\n\t\t\t\tcontentType: \"application/json\",\n\t\t\t},\n\t\t};\n\t}\n\treturn undefined;\n}\n\nfunction classifyOrigin(\n\tproviderId: string,\n\tbaseUrl: string | undefined,\n\tapi: string | undefined,\n\tisNative: boolean,\n): ProviderOrigin {\n\tconst url = baseUrl ? sanitizeUrl(baseUrl) : undefined;\n\tif (providerId === \"grok-oauth-proxy\" || (url && isLiteralLoopback(normalizedHostname(url)))) {\n\t\treturn \"local-proxy\";\n\t}\n\tif (isNative) return \"native\";\n\tif (api && OPENAI_COMPATIBLE_APIS.has(api)) return \"custom-openai-compatible\";\n\treturn \"unknown\";\n}\n\nfunction resolveProviderTarget(\n\tproviderId: string,\n\toptions: ProviderDoctorOptions,\n): { target?: ResolvedProviderTarget; failure?: ProviderDoctorResult } {\n\tconst level = options.level ?? 0;\n\tconst agentDir = options.agentDir ?? getConfiguredAgentDir();\n\tconst modelsConfig = loadConfig(join(agentDir, \"models.json\"), parseModelsConfig, true);\n\tif (modelsConfig.kind === \"invalid\") {\n\t\treturn {\n\t\t\tfailure: unresolvedFailure(providerId, level, \"models-config-invalid\", \"models.json is invalid\"),\n\t\t};\n\t}\n\tconst authConfig = loadConfig(join(agentDir, \"auth.json\"), parseAuthConfig);\n\tif (authConfig.kind === \"invalid\") {\n\t\treturn { failure: unresolvedFailure(providerId, level, \"auth-config-invalid\", \"auth.json is invalid\") };\n\t}\n\n\tconst kimi = providerId === KIMI_PROVIDER_ID ? resolveKimiConfig(options.kimiConfigPath) : {};\n\tif (kimi.failure) {\n\t\treturn {\n\t\t\tfailure: unresolvedFailure(\n\t\t\t\tproviderId,\n\t\t\t\tlevel,\n\t\t\t\t\"kimi-config-invalid\",\n\t\t\t\t`Kimi config TOML is invalid (line ${kimi.failure.line}: ${kimi.failure.reason}); fix the Kimi config or set KIMI_BASE_URL/KIMI_MODEL_NAME`,\n\t\t\t),\n\t\t};\n\t}\n\n\tconst configured = modelsConfig.kind === \"ok\" ? modelsConfig.value.providers[providerId] : undefined;\n\tconst nativeProviders = getProviders();\n\tconst isNative = nativeProviders.includes(providerId as KnownProvider);\n\tconst nativeModels = isNative ? (getModels(providerId as KnownProvider) as Model<Api>[]) : [];\n\tconst configuredModels = configured?.models ?? [];\n\t// At Level 2 the probe model is the paid target and therefore drives endpoint resolution.\n\tconst requestedModel = level === 2 ? (options.probeModelId ?? options.modelId) : options.modelId;\n\tconst configuredModel = requestedModel\n\t\t? configuredModels.find((model) => model.id === requestedModel)\n\t\t: configuredModels[0];\n\n\t// §10.2: with no higher-precedence endpoint (models.json > KIMI_BASE_URL > root TOML), a\n\t// `[providers.<name>]` entry with `type = \"openai_legacy\"` selects a custom OpenAI-compatible\n\t// endpoint, so native-only checks and native credential/model inheritance are skipped downstream.\n\tconst kimiCustomSelected =\n\t\t!(configuredModel?.baseUrl ?? configured?.baseUrl) && !kimi.baseUrl && kimi.customProvider !== undefined;\n\tconst kimiModelName = kimi.modelName ?? (kimiCustomSelected ? kimi.customProvider?.modelName : undefined);\n\tconst endpointModelId = requestedModel ?? kimiModelName;\n\tconst modelIds = kimiCustomSelected\n\t\t? kimiModelName\n\t\t\t? [kimiModelName]\n\t\t\t: []\n\t\t: Array.from(\n\t\t\t\tnew Set([\n\t\t\t\t\t...nativeModels.map((model) => model.id),\n\t\t\t\t\t...configuredModels.map((model) => model.id),\n\t\t\t\t\t...(kimiModelName ? [kimiModelName] : []),\n\t\t\t\t]),\n\t\t\t);\n\tlet nativeModel = kimiCustomSelected\n\t\t? undefined\n\t\t: requestedModel\n\t\t\t? nativeModels.find((model) => model.id === requestedModel)\n\t\t\t: nativeModels[0];\n\tif (!nativeModel && !kimiCustomSelected && requestedModel !== undefined && requestedModel === kimiModelName) {\n\t\t// A native Kimi TOML/env model rides on the provider defaults for endpoint metadata.\n\t\tnativeModel = nativeModels[0];\n\t}\n\n\tlet baseUrl = configuredModel?.baseUrl ?? configured?.baseUrl;\n\tlet api = configuredModel?.api ?? configured?.api ?? nativeModel?.api;\n\tlet source = configured ? \"models.json\" : isNative ? \"built-in-model-registry\" : \"unresolved\";\n\tif (!baseUrl && kimi.baseUrl) {\n\t\tbaseUrl = kimi.baseUrl;\n\t\tsource = kimi.baseUrlSource ?? source;\n\t} else if (kimiCustomSelected && kimi.customProvider) {\n\t\tbaseUrl = kimi.customProvider.baseUrl;\n\t\tapi = \"openai-completions\";\n\t\tsource = `kimi-config-toml:providers.${kimi.customProvider.name}`;\n\t} else {\n\t\tbaseUrl = baseUrl ?? nativeModel?.baseUrl;\n\t}\n\tlet builtInAuth = false;\n\tif (providerId === \"grok-oauth-proxy\" && !baseUrl) {\n\t\tbaseUrl = \"http://127.0.0.1:9996/v1\";\n\t\tapi = \"openai-completions\";\n\t\tsource = \"built-in-grok-oauth-proxy-defaults\";\n\t\tbuiltInAuth = true;\n\t}\n\n\tconst storedAuth = authConfig.kind === \"ok\" && authConfig.value[providerId] !== undefined;\n\tconst environmentAuth = findEnvKeys(providerId) !== undefined;\n\tconst configuredAuth = configured?.apiKey ? isConfigValueConfigured(configured.apiKey) : false;\n\tconst headerAuth = configured?.headers !== undefined && Object.keys(configured.headers).length > 0;\n\tconst customApiKey = kimiCustomSelected ? kimi.customProvider?.apiKey : undefined;\n\tconst customAuthPresent = customApiKey !== undefined && isConfigValueConfigured(customApiKey);\n\tconst authPresent = kimiCustomSelected\n\t\t? customAuthPresent\n\t\t: storedAuth || environmentAuth || configuredAuth || headerAuth || builtInAuth;\n\tconst authSource = kimiCustomSelected\n\t\t? customAuthPresent\n\t\t\t? source\n\t\t\t: undefined\n\t\t: storedAuth\n\t\t\t? \"auth.json\"\n\t\t\t: environmentAuth\n\t\t\t\t? \"environment\"\n\t\t\t\t: configuredAuth || headerAuth\n\t\t\t\t\t? \"models.json\"\n\t\t\t\t\t: builtInAuth\n\t\t\t\t\t\t? \"built-in\"\n\t\t\t\t\t\t: undefined;\n\n\tif (!configured && !isNative && !storedAuth && !environmentAuth && providerId !== \"grok-oauth-proxy\") {\n\t\treturn { failure: unresolvedFailure(providerId, level, \"provider-not-found\", \"Provider was not found\") };\n\t}\n\n\tconst origin = classifyOrigin(providerId, baseUrl, api, isNative && !kimiCustomSelected);\n\tconst canonicalBaseUrl = canonicalProviderEndpointUrl(baseUrl);\n\tconst binding =\n\t\tcanonicalBaseUrl && api && endpointModelId\n\t\t\t? { origin, source, baseUrl: canonicalBaseUrl, api, modelId: endpointModelId }\n\t\t\t: undefined;\n\tconst createHeaders: ProviderDoctorHeaderFactory | undefined =\n\t\tkimiCustomSelected && binding\n\t\t\t? () => {\n\t\t\t\t\tconst headers = new Headers();\n\t\t\t\t\tif (customApiKey) {\n\t\t\t\t\t\theaders.set(\n\t\t\t\t\t\t\t\"Authorization\",\n\t\t\t\t\t\t\t`Bearer ${resolveConfigValueOrThrow(customApiKey, \"API key for custom Kimi endpoint\")}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn headers;\n\t\t\t\t}\n\t\t\t: undefined;\n\n\treturn {\n\t\ttarget: {\n\t\t\tproviderId,\n\t\t\torigin,\n\t\t\tsource,\n\t\t\tendpoint: { baseUrl, api, modelIds, modelId: endpointModelId },\n\t\t\tauth: { present: authPresent, source: authSource, createHeaders, binding },\n\t\t},\n\t};\n}\n\nexport async function diagnoseResolvedProvider(\n\ttarget: ResolvedProviderTarget,\n\toptions: ProviderDoctorOptions = {},\n\tdependencies: ProviderDoctorDependencies = {},\n): Promise<ProviderDoctorResult> {\n\tconst requestedLevel = options.level ?? 0;\n\tif (requestedLevel !== 0 && requestedLevel !== 1 && requestedLevel !== 2) {\n\t\treturn unresolvedFailure(target.providerId, 0, \"unsupported-level\", \"Provider doctor level is unsupported\");\n\t}\n\tconst level: ProviderDoctorLevel = requestedLevel;\n\t// Level 2 is opt-in only: probeModelId is ignored at levels 0/1, which stay GET-only.\n\tconst probeModelId = level === 2 ? options.probeModelId : undefined;\n\tconst effectiveModelId = probeModelId ?? options.modelId;\n\tconst resolvedTarget = effectiveModelId\n\t\t? { ...target, endpoint: { ...target.endpoint, modelId: effectiveModelId } }\n\t\t: target;\n\tif (level === 2 && options.modelId && probeModelId && options.modelId !== probeModelId) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"model\",\n\t\t\tcode: \"probe-model-conflict\",\n\t\t\tmessage: \"Validation model and paid probe model must match\",\n\t\t};\n\t\treturn publicResult(\n\t\t\tresolvedTarget,\n\t\t\tlevel,\n\t\t\t[{ name: \"model-probe\", status: \"fail\", ...failure }],\n\t\t\tundefined,\n\t\t\tfailure,\n\t\t);\n\t}\n\tif (level === 2 && !probeModelId) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"probe-model-required\",\n\t\t\tmessage: \"Level 2 requires an explicit probe model (--probe-model)\",\n\t\t};\n\t\treturn publicResult(\n\t\t\tresolvedTarget,\n\t\t\tlevel,\n\t\t\t[{ name: \"model-probe\", status: \"fail\", ...failure }],\n\t\t\tundefined,\n\t\t\tfailure,\n\t\t);\n\t}\n\tconst validation = staticChecks(resolvedTarget);\n\tif (validation.failure || level === 0) {\n\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, validation.failure);\n\t}\n\n\tconst transport = dependencies.transport ?? options.transport;\n\tif (!transport) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"transport-required\",\n\t\t\tmessage: \"Level 1 requires an injected provider transport\",\n\t\t};\n\t\tvalidation.checks.push({ name: \"transport\", status: \"fail\", ...failure });\n\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, failure);\n\t}\n\tif (resolvedTarget.origin !== \"local-proxy\" && transport.pinsResolvedAddress !== true) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"address-pinning-required\",\n\t\t\tmessage: \"Public provider transport must pin resolved addresses\",\n\t\t};\n\t\tvalidation.checks.push({ name: \"transport\", status: \"fail\", ...failure });\n\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, failure);\n\t}\n\n\tconst timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tif (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"unexpected-response\",\n\t\t\tmessage: \"Provider probe timeout is invalid\",\n\t\t};\n\t\tvalidation.checks.push({ name: \"transport\", status: \"fail\", ...failure });\n\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, failure);\n\t}\n\n\tconst addressPolicy: ProviderDoctorAddressPolicy =\n\t\tresolvedTarget.origin === \"local-proxy\"\n\t\t\t? { kind: \"loopback-only\", requireAddressPinning: false }\n\t\t\t: { kind: \"public\", requireAddressPinning: true };\n\tconst resolveAuthHeaders = dependencies.resolveAuthHeaders ?? options.resolveAuthHeaders;\n\tconst credentialBinding = resolvedTarget.auth.binding;\n\tconst boundHeaderFactory = resolvedTarget.auth.createHeaders;\n\tconst endpointBoundHeaders: ProviderDoctorHeaderFactory | undefined =\n\t\tcredentialBinding && boundHeaderFactory\n\t\t\t? async () => {\n\t\t\t\t\tif (!credentialBindingMatchesTarget(credentialBinding, resolvedTarget)) {\n\t\t\t\t\t\tthrow new ProviderDoctorAuthMaterializationError();\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn await boundHeaderFactory();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthrow new ProviderDoctorAuthMaterializationError();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t: undefined;\n\tconst createHeaders: ProviderDoctorHeaderFactory = endpointBoundHeaders\n\t\t? endpointBoundHeaders\n\t\t: level === 2 && resolveAuthHeaders\n\t\t\t? async () => {\n\t\t\t\t\tif (credentialBinding && !credentialBindingMatchesTarget(credentialBinding, resolvedTarget)) {\n\t\t\t\t\t\tthrow new ProviderDoctorAuthMaterializationError();\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn await resolveAuthHeaders(resolvedTarget);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthrow new ProviderDoctorAuthMaterializationError();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t: (resolvedTarget.auth.createHeaders ?? (() => new Headers()));\n\tconst controller = createComposedController(options.signal, timeoutMs);\n\ttry {\n\t\tconst root = await runProbe(\n\t\t\t\"root-endpoint\",\n\t\t\t\"root\",\n\t\t\tmakeRootProbeUrl(validation.url!, resolvedTarget.origin),\n\t\t\ttransport,\n\t\t\taddressPolicy,\n\t\t\tcreateHeaders,\n\t\t\tcontroller,\n\t\t);\n\t\tvalidation.checks.push(root.check);\n\t\tif (root.failure) {\n\t\t\tvalidation.checks.push({\n\t\t\t\tname: \"models-endpoint\",\n\t\t\t\tstatus: \"skipped\",\n\t\t\t\tcode: \"ok\",\n\t\t\t\tmessage: \"Capability probe skipped after root failure\",\n\t\t\t});\n\t\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, root.failure);\n\t\t}\n\n\t\tconst models = await runProbe(\n\t\t\t\"models-endpoint\",\n\t\t\t\"models\",\n\t\t\tappendPath(validation.url!, \"models\"),\n\t\t\ttransport,\n\t\t\taddressPolicy,\n\t\t\tcreateHeaders,\n\t\t\tcontroller,\n\t\t);\n\t\tvalidation.checks.push(models.check);\n\t\tif (level !== 2 || models.failure) {\n\t\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, models.failure);\n\t\t}\n\n\t\tconst spec = modelProbeSpec(resolvedTarget.endpoint.api ?? \"\", probeModelId as string);\n\t\tif (!spec) {\n\t\t\tconst failure: ProbeFailure = {\n\t\t\t\tcategory: \"config\",\n\t\t\t\tcode: \"api-unsupported\",\n\t\t\t\tmessage: \"Model probe supports only OpenAI-compatible APIs\",\n\t\t\t};\n\t\t\tvalidation.checks.push({ name: \"model-probe\", status: \"fail\", ...failure });\n\t\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, failure);\n\t\t}\n\t\tconst probe = await runProbe(\n\t\t\t\"model-probe\",\n\t\t\t\"model-probe\",\n\t\t\tappendPath(validation.url!, spec.path),\n\t\t\ttransport,\n\t\t\taddressPolicy,\n\t\t\tcreateHeaders,\n\t\t\tcontroller,\n\t\t\tspec.payload,\n\t\t);\n\t\tconst dispatched = probe.failure?.code !== \"auth-materialization-failed\";\n\t\tif (dispatched) {\n\t\t\tprobe.check.message = `${probe.check.message}; minimal-token generative probe (may incur provider costs)`;\n\t\t}\n\t\tvalidation.checks.push(probe.check);\n\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, probe.failure, dispatched);\n\t} finally {\n\t\tcontroller.dispose();\n\t}\n}\n\nexport async function diagnoseProvider(\n\tproviderId: string,\n\toptions: ProviderDoctorOptions = {},\n): Promise<ProviderDoctorResult> {\n\tconst requestedLevel = options.level ?? 0;\n\tif (requestedLevel !== 0 && requestedLevel !== 1 && requestedLevel !== 2) {\n\t\treturn unresolvedFailure(providerId, 0, \"unsupported-level\", \"Provider doctor level is unsupported\");\n\t}\n\tconst resolved = resolveProviderTarget(providerId, options);\n\tif (resolved.failure) return resolved.failure;\n\treturn diagnoseResolvedProvider(resolved.target!, options);\n}\n"]}
1
+ {"version":3,"file":"doctor-provider.d.ts","sourceRoot":"","sources":["../../src/commands/doctor-provider.ts"],"names":[],"mappings":"AASA,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,0BAA0B,GAAG,aAAa,GAAG,SAAS,CAAC;AAC/F,MAAM,MAAM,mBAAmB,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAC5C,MAAM,MAAM,yBAAyB,GAAG,IAAI,GAAG,MAAM,GAAG,SAAS,GAAG,aAAa,CAAC;AAClF,MAAM,MAAM,mBAAmB,GAAG,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,CAAC;AAEjG,4EAA2E;AAC3E,MAAM,MAAM,qBAAqB,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,sBAAsB,GAAG,QAAQ,CAAC;AAElG,MAAM,MAAM,mBAAmB,GAAG;IACjC,SAAS,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,qBAAqB,CAAC;CAChC,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAC3B,IAAI,GACJ,oBAAoB,GACpB,uBAAuB,GACvB,qBAAqB,GACrB,qBAAqB,GACrB,mBAAmB,GACnB,yBAAyB,GACzB,aAAa,GACb,iBAAiB,GACjB,kBAAkB,GAClB,kBAAkB,GAClB,wBAAwB,GACxB,oBAAoB,GACpB,wBAAwB,GACxB,cAAc,GACd,6BAA6B,GAC7B,oBAAoB,GACpB,0BAA0B,GAC1B,kBAAkB,GAClB,uBAAuB,GACvB,sBAAsB,GACtB,iBAAiB,GACjB,iBAAiB,GACjB,iBAAiB,GACjB,cAAc,GACd,sBAAsB,GACtB,sBAAsB,GACtB,qBAAqB,CAAC;AAEzB,MAAM,WAAW,sBAAsB;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,QAAQ,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,OAAO,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,MAAM,2BAA2B,GAAG,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE3E,MAAM,MAAM,gCAAgC,GAAG,CAAC,MAAM,EAAE,sBAAsB,KAAK,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAE9G,wFAAwF;AACxF,qBAAa,sCAAuC,SAAQ,KAAK;IAChE,cAGC;CACD;AAED,MAAM,WAAW,+BAA+B;IAC/C,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB,GAAG,EAAE,MAAM,CAAC;IACZ,OAAO,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,WAAW,kBAAkB;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,kEAAkE;IAClE,aAAa,CAAC,EAAE,2BAA2B,CAAC;IAC5C,+DAA+D;IAC/D,OAAO,CAAC,EAAE,+BAA+B,CAAC;CAC1C;AAED,MAAM,WAAW,sBAAsB;IACtC,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,sBAAsB,CAAC;IACjC,IAAI,EAAE,kBAAkB,CAAC;CACzB;AAED,4EAA4E;AAC5E,MAAM,MAAM,sBAAsB,GAAG,sBAAsB,CAAC;AAE5D,MAAM,MAAM,2BAA2B,GACpC;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,qBAAqB,EAAE,IAAI,CAAA;CAAE,GAC/C;IAAE,IAAI,EAAE,eAAe,CAAC;IAAC,qBAAqB,EAAE,KAAK,CAAA;CAAE,CAAC;AAE3D,MAAM,WAAW,8BAA8B;IAC9C,GAAG,EAAE,GAAG,CAAC;IACT,MAAM,EAAE,KAAK,GAAG,MAAM,CAAC;IACvB,QAAQ,EAAE,QAAQ,CAAC;IACnB,MAAM,EAAE,WAAW,CAAC;IACpB,aAAa,EAAE,2BAA2B,CAAC;IAC3C,aAAa,EAAE,2BAA2B,CAAC;IAC3C,+EAA+E;IAC/E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,kBAAkB,CAAC;CACjC;AAED,MAAM,WAAW,+BAA+B;IAC/C,MAAM,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,uBAAuB;IACvC,sFAAsF;IACtF,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,OAAO,CAAC,OAAO,EAAE,8BAA8B,GAAG,OAAO,CAAC,+BAA+B,CAAC,CAAC;CAC3F;AAED,MAAM,WAAW,0BAA0B;IAC1C,SAAS,CAAC,EAAE,uBAAuB,CAAC;IACpC,2FAA2F;IAC3F,kBAAkB,CAAC,EAAE,gCAAgC,CAAC;CACtD;AAED,MAAM,WAAW,qBAAsB,SAAQ,0BAA0B;IACxE,KAAK,CAAC,EAAE,mBAAmB,CAAC;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uFAAuF;IACvF,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gHAAgH;IAChH,cAAc,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,MAAM,WAAW,mBAAmB;IACnC,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,yBAAyB,CAAC;IAClC,IAAI,EAAE,kBAAkB,CAAC;IACzB,QAAQ,CAAC,EAAE,mBAAmB,CAAC;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE,mBAAmB,CAAC;CAC5B;AAED,MAAM,WAAW,oBAAoB;IACpC,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,IAAI,GAAG,MAAM,CAAC;IACtB,KAAK,EAAE,mBAAmB,CAAC;IAC3B,MAAM,EAAE,cAAc,CAAC;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,+CAA+C;IAC/C,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,WAAW,EAAE,OAAO,CAAC;IACrB,yGAAyG;IACzG,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,MAAM,EAAE,mBAAmB,EAAE,CAAC;IAC9B,KAAK,CAAC,EAAE;QACP,QAAQ,EAAE,mBAAmB,CAAC;QAC9B,IAAI,EAAE,kBAAkB,CAAC;QACzB,OAAO,EAAE,MAAM,CAAC;KAChB,CAAC;CACF;AAyFD,8FAA8F;AAC9F,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAK1D;AAED,0GAA0G;AAC1G,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAK/D;AAED,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAwiBD,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,GAAG,GAAG,MAAM,CAEtD;AAiCD,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,SAAS,CAQ3F;AAykBD,wBAAsB,wBAAwB,CAC7C,MAAM,EAAE,sBAAsB,EAC9B,OAAO,GAAE,qBAA0B,EACnC,YAAY,GAAE,0BAA+B,GAC3C,OAAO,CAAC,oBAAoB,CAAC,CA+K/B;AAED,wBAAsB,gBAAgB,CACrC,UAAU,EAAE,MAAM,EAClB,OAAO,GAAE,qBAA0B,GACjC,OAAO,CAAC,oBAAoB,CAAC,CAQ/B","sourcesContent":["import { existsSync, readFileSync } from \"node:fs\";\nimport { BlockList, isIP } from \"node:net\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { type Api, findEnvKeys, getModels, getProviders, type KnownProvider, type Model } from \"omk-ai\";\nimport { getAgentDir as getConfiguredAgentDir } from \"../config.ts\";\nimport { isConfigValueConfigured, resolveConfigValueOrThrow } from \"../core/resolve-config-value.ts\";\nimport { stripJsonComments } from \"../utils/json.ts\";\n\nexport type ProviderOrigin = \"native\" | \"custom-openai-compatible\" | \"local-proxy\" | \"unknown\";\nexport type ProviderDoctorLevel = 0 | 1 | 2;\nexport type ProviderDoctorCheckStatus = \"ok\" | \"fail\" | \"skipped\" | \"unsupported\";\nexport type DoctorErrorCategory = \"network\" | \"auth\" | \"model\" | \"config\" | \"server\" | \"unknown\";\n\n/** Exact endpoint-probe category model from the v0.90.9 design (§10.4). */\nexport type EndpointProbeCategory = \"ok\" | \"network\" | \"auth\" | \"unsupported-endpoint\" | \"server\";\n\nexport type EndpointProbeResult = {\n\treachable: boolean;\n\tauthenticated?: boolean;\n\tmodelsSupported?: boolean;\n\tstatus?: number;\n\tcategory: EndpointProbeCategory;\n};\n\nexport type ProviderDoctorCode =\n\t| \"ok\"\n\t| \"provider-not-found\"\n\t| \"models-config-invalid\"\n\t| \"auth-config-invalid\"\n\t| \"kimi-config-invalid\"\n\t| \"unsupported-level\"\n\t| \"model-provider-mismatch\"\n\t| \"api-missing\"\n\t| \"api-unsupported\"\n\t| \"base-url-missing\"\n\t| \"base-url-invalid\"\n\t| \"url-scheme-unsupported\"\n\t| \"origin-unsupported\"\n\t| \"address-policy-blocked\"\n\t| \"auth-missing\"\n\t| \"auth-materialization-failed\"\n\t| \"transport-required\"\n\t| \"address-pinning-required\"\n\t| \"redirect-blocked\"\n\t| \"authentication-failed\"\n\t| \"endpoint-unsupported\"\n\t| \"request-aborted\"\n\t| \"request-timeout\"\n\t| \"network-failure\"\n\t| \"server-error\"\n\t| \"probe-model-required\"\n\t| \"probe-model-conflict\"\n\t| \"unexpected-response\";\n\nexport interface ProviderDoctorEndpoint {\n\tbaseUrl?: string;\n\tapi?: string;\n\tmodelIds?: readonly string[];\n\tmodelId?: string;\n}\n\nexport type ProviderDoctorHeaderFactory = () => Headers | Promise<Headers>;\n\nexport type ProviderDoctorAuthHeaderResolver = (target: ResolvedProviderTarget) => Headers | Promise<Headers>;\n\n/** Fixed-message marker used to classify auth resolution without exposing its cause. */\nexport class ProviderDoctorAuthMaterializationError extends Error {\n\tconstructor() {\n\t\tsuper(\"provider doctor authentication could not be materialized\");\n\t\tthis.name = \"ProviderDoctorAuthMaterializationError\";\n\t}\n}\n\nexport interface ProviderDoctorCredentialBinding {\n\torigin: ProviderOrigin;\n\tsource: string;\n\tbaseUrl: string;\n\tapi: string;\n\tmodelId: string;\n}\n\nexport interface ProviderDoctorAuth {\n\tpresent: boolean;\n\tsource?: string;\n\t/** Materialized by an injected transport at request time only. */\n\tcreateHeaders?: ProviderDoctorHeaderFactory;\n\t/** Exact endpoint provenance that authorizes createHeaders. */\n\tbinding?: ProviderDoctorCredentialBinding;\n}\n\nexport interface ResolvedProviderTarget {\n\tproviderId: string;\n\torigin: ProviderOrigin;\n\tsource: string;\n\tendpoint: ProviderDoctorEndpoint;\n\tauth: ProviderDoctorAuth;\n}\n\n/** Compatibility name for callers using the design-document terminology. */\nexport type ResolvedProviderConfig = ResolvedProviderTarget;\n\nexport type ProviderDoctorAddressPolicy =\n\t| { kind: \"public\"; requireAddressPinning: true }\n\t| { kind: \"loopback-only\"; requireAddressPinning: false };\n\nexport interface ProviderDoctorTransportRequest {\n\turl: URL;\n\tmethod: \"GET\" | \"POST\";\n\tredirect: \"manual\";\n\tsignal: AbortSignal;\n\taddressPolicy: ProviderDoctorAddressPolicy;\n\tcreateHeaders: ProviderDoctorHeaderFactory;\n\t/** Bounded JSON payload; present only for opt-in Level-2 POST model probes. */\n\tbody?: string;\n\tcontentType?: \"application/json\";\n}\n\nexport interface ProviderDoctorTransportResponse {\n\tstatus: number;\n}\n\nexport interface ProviderDoctorTransport {\n\t/** Public requests are rejected unless the transport enforces DNS/address pinning. */\n\tpinsResolvedAddress?: boolean;\n\trequest(request: ProviderDoctorTransportRequest): Promise<ProviderDoctorTransportResponse>;\n}\n\nexport interface ProviderDoctorDependencies {\n\ttransport?: ProviderDoctorTransport;\n\t/** Level-2 only. Called by the transport immediately before each request is dispatched. */\n\tresolveAuthHeaders?: ProviderDoctorAuthHeaderResolver;\n}\n\nexport interface ProviderDoctorOptions extends ProviderDoctorDependencies {\n\tlevel?: ProviderDoctorLevel;\n\tmodelId?: string;\n\t/** Level-2 opt-in only: the model probed with one minimal-token generative request. */\n\tprobeModelId?: string;\n\ttimeoutMs?: number;\n\tsignal?: AbortSignal;\n\tagentDir?: string;\n\t/** Path to the Kimi CLI config TOML consulted for the kimi-coding provider. Defaults to ~/.kimi/config.toml. */\n\tkimiConfigPath?: string;\n}\n\nexport interface ProviderDoctorCheck {\n\tname: string;\n\tstatus: ProviderDoctorCheckStatus;\n\tcode: ProviderDoctorCode;\n\tcategory?: DoctorErrorCategory;\n\tmessage?: string;\n\t/** Exact-category endpoint classification for network probe checks. */\n\tprobe?: EndpointProbeResult;\n}\n\nexport interface ProviderDoctorResult {\n\tprovider: string;\n\tstatus: \"ok\" | \"fail\";\n\tlevel: ProviderDoctorLevel;\n\torigin: ProviderOrigin;\n\tsource: string;\n\t/** Sanitized URL: userinfo, query, and fragment are always removed. */\n\ttargetUrl?: string;\n\t/** Backwards-compatible alias of targetUrl. */\n\tbaseUrl?: string;\n\tapi?: string;\n\tmodelId?: string;\n\tauthPresent: boolean;\n\t/** True only when an opt-in Level-2 model probe was dispatched; the request may incur provider costs. */\n\tcostWarning?: boolean;\n\tchecks: ProviderDoctorCheck[];\n\terror?: {\n\t\tcategory: DoctorErrorCategory;\n\t\tcode: ProviderDoctorCode;\n\t\tmessage: string;\n\t};\n}\n\ninterface ModelEndpointConfig {\n\tid: string;\n\tbaseUrl?: string;\n\tapi?: string;\n}\n\ninterface ProviderConfig {\n\tbaseUrl?: string;\n\tapiKey?: string;\n\tapi?: string;\n\theaders?: Record<string, string>;\n\tmodels?: ModelEndpointConfig[];\n}\n\ninterface ModelsConfig {\n\tproviders: Record<string, ProviderConfig>;\n}\n\ninterface AuthConfigEntry {\n\ttype: \"api_key\" | \"oauth\";\n}\n\ntype AuthConfig = Record<string, AuthConfigEntry>;\n\ntype LoadedConfig<T> = { kind: \"missing\" } | { kind: \"invalid\" } | { kind: \"ok\"; value: T };\n\ntype ProbeFailure = {\n\tcategory: DoctorErrorCategory;\n\tcode: ProviderDoctorCode;\n\tmessage: string;\n};\n\ninterface ProbeOutcome {\n\tcheck: ProviderDoctorCheck;\n\tfailure?: ProbeFailure;\n}\n\nconst DEFAULT_TIMEOUT_MS = 5_000;\nconst KNOWN_APIS = new Set<string>([\n\t\"openai-completions\",\n\t\"mistral-conversations\",\n\t\"openai-responses\",\n\t\"azure-openai-responses\",\n\t\"openai-codex-responses\",\n\t\"anthropic-messages\",\n\t\"bedrock-converse-stream\",\n\t\"google-generative-ai\",\n\t\"google-vertex\",\n]);\nconst OPENAI_COMPATIBLE_APIS = new Set<string>([\"openai-completions\", \"openai-responses\"]);\nconst ABORTED = Symbol(\"provider-doctor-aborted\");\n\n// Family-specific lists: node BlockList canonicalizes IPv4 checks to the v4-mapped v6 form,\n// so a combined list containing ::ffff:0:0/96 would block every IPv4 address.\nconst blockedPublicV4 = new BlockList();\nfor (const [address, prefix] of [\n\t[\"0.0.0.0\", 8],\n\t[\"10.0.0.0\", 8],\n\t[\"100.64.0.0\", 10],\n\t[\"127.0.0.0\", 8],\n\t[\"169.254.0.0\", 16],\n\t[\"172.16.0.0\", 12],\n\t[\"192.168.0.0\", 16],\n\t[\"224.0.0.0\", 4],\n\t[\"240.0.0.0\", 4],\n] as const) {\n\tblockedPublicV4.addSubnet(address, prefix, \"ipv4\");\n}\n// ::ffff:0:0/96 stays here on purpose: a v4-mapped IPv6 literal or DNS answer is anomalous\n// for a public origin and is rejected wholesale (fail closed), covering hex-form mappings too.\nconst blockedPublicV6 = new BlockList();\nfor (const [address, prefix] of [\n\t[\"::\", 128],\n\t[\"::1\", 128],\n\t[\"::ffff:0:0\", 96],\n\t[\"fc00::\", 7],\n\t[\"fe80::\", 10],\n\t[\"ff00::\", 8],\n] as const) {\n\tblockedPublicV6.addSubnet(address, prefix, \"ipv6\");\n}\n\nconst loopbackAddresses = new BlockList();\nloopbackAddresses.addSubnet(\"127.0.0.0\", 8, \"ipv4\");\nloopbackAddresses.addAddress(\"::1\", \"ipv6\");\nloopbackAddresses.addSubnet(\"::ffff:127.0.0.0\", 104, \"ipv6\");\n\n/** True when the literal IP address is a loopback address. Non-IP input is never loopback. */\nexport function isLoopbackAddress(address: string): boolean {\n\tconst family = isIP(address);\n\tif (family === 4) return loopbackAddresses.check(address, \"ipv4\");\n\tif (family === 6) return loopbackAddresses.check(address, \"ipv6\");\n\treturn false;\n}\n\n/** True when the literal IP address must not be dialed for a public origin. Non-IP input fails closed. */\nexport function isBlockedPublicAddress(address: string): boolean {\n\tconst family = isIP(address);\n\tif (family === 4) return blockedPublicV4.check(address, \"ipv4\");\n\tif (family === 6) return blockedPublicV6.check(address, \"ipv6\");\n\treturn true;\n}\n\nexport function getAgentDir(): string {\n\treturn getConfiguredAgentDir();\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction isOptionalNonemptyString(value: unknown): value is string | undefined {\n\treturn value === undefined || (typeof value === \"string\" && value.length > 0);\n}\n\nfunction parseModelsConfig(value: unknown): ModelsConfig | undefined {\n\tif (!isRecord(value) || !isRecord(value.providers)) return undefined;\n\tconst providers: Record<string, ProviderConfig> = {};\n\n\tfor (const [providerId, rawProvider] of Object.entries(value.providers)) {\n\t\tif (!isRecord(rawProvider)) return undefined;\n\t\tif (\n\t\t\t!isOptionalNonemptyString(rawProvider.baseUrl) ||\n\t\t\t!isOptionalNonemptyString(rawProvider.apiKey) ||\n\t\t\t!isOptionalNonemptyString(rawProvider.api)\n\t\t) {\n\t\t\treturn undefined;\n\t\t}\n\n\t\tlet headers: Record<string, string> | undefined;\n\t\tif (rawProvider.headers !== undefined) {\n\t\t\tif (!isRecord(rawProvider.headers)) return undefined;\n\t\t\theaders = {};\n\t\t\tfor (const [name, headerValue] of Object.entries(rawProvider.headers)) {\n\t\t\t\tif (typeof headerValue !== \"string\") return undefined;\n\t\t\t\theaders[name] = headerValue;\n\t\t\t}\n\t\t}\n\n\t\tlet models: ModelEndpointConfig[] | undefined;\n\t\tif (rawProvider.models !== undefined) {\n\t\t\tif (!Array.isArray(rawProvider.models)) return undefined;\n\t\t\tmodels = [];\n\t\t\tfor (const rawModel of rawProvider.models) {\n\t\t\t\tif (\n\t\t\t\t\t!isRecord(rawModel) ||\n\t\t\t\t\ttypeof rawModel.id !== \"string\" ||\n\t\t\t\t\trawModel.id.length === 0 ||\n\t\t\t\t\t!isOptionalNonemptyString(rawModel.baseUrl) ||\n\t\t\t\t\t!isOptionalNonemptyString(rawModel.api)\n\t\t\t\t) {\n\t\t\t\t\treturn undefined;\n\t\t\t\t}\n\t\t\t\tmodels.push({ id: rawModel.id, baseUrl: rawModel.baseUrl, api: rawModel.api });\n\t\t\t}\n\t\t}\n\n\t\tproviders[providerId] = {\n\t\t\tbaseUrl: rawProvider.baseUrl,\n\t\t\tapiKey: rawProvider.apiKey,\n\t\t\tapi: rawProvider.api,\n\t\t\theaders,\n\t\t\tmodels,\n\t\t};\n\t}\n\n\treturn { providers };\n}\n\nfunction parseAuthConfig(value: unknown): AuthConfig | undefined {\n\tif (!isRecord(value)) return undefined;\n\tconst auth: AuthConfig = {};\n\tfor (const [providerId, rawEntry] of Object.entries(value)) {\n\t\tif (!isRecord(rawEntry) || (rawEntry.type !== \"api_key\" && rawEntry.type !== \"oauth\")) return undefined;\n\t\tif (rawEntry.type === \"api_key\" && (typeof rawEntry.key !== \"string\" || rawEntry.key.length === 0)) {\n\t\t\treturn undefined;\n\t\t}\n\t\tauth[providerId] = { type: rawEntry.type };\n\t}\n\treturn auth;\n}\n\nconst KIMI_PROVIDER_ID = \"kimi-coding\";\nconst TOML_BASIC_ESCAPES: Record<string, string> = {\n\t'\"': '\"',\n\t\"\\\\\": \"\\\\\",\n\tb: \"\\b\",\n\tf: \"\\f\",\n\tn: \"\\n\",\n\tr: \"\\r\",\n\tt: \"\\t\",\n};\n\ntype TomlQuote = \"basic\" | \"literal\" | \"multiline-basic\" | \"multiline-literal\";\n\ninterface TomlScanState {\n\tquote?: TomlQuote;\n\tcontainers: (\"[\" | \"{\")[];\n}\n\ninterface KimiTomlProviderEntry {\n\tname: string;\n\ttype?: string;\n\tbaseUrl?: string;\n\tmodelName?: string;\n\tapiKey?: string;\n}\n\ninterface KimiConfigValues {\n\tbaseUrl?: string;\n\tmodelName?: string;\n\tproviders: KimiTomlProviderEntry[];\n}\n\ntype KimiConfigLoad =\n\t| { kind: \"missing\" }\n\t| { kind: \"ok\"; value: KimiConfigValues }\n\t| { kind: \"invalid\"; line: number; reason: string };\n\nfunction findBasicStringEnd(text: string, start: number, multiline: boolean): number {\n\tfor (let index = start; index < text.length; index++) {\n\t\tif (text[index] === \"\\\\\") {\n\t\t\tindex++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (multiline ? text.startsWith('\"\"\"', index) : text[index] === '\"') return index;\n\t}\n\treturn -1;\n}\n\nfunction decodeTomlBasicString(body: string, multiline: boolean): { value: string } | { error: string } {\n\tlet value = \"\";\n\tfor (let index = 0; index < body.length; index++) {\n\t\tconst char = body[index];\n\t\tif (char !== \"\\\\\") {\n\t\t\tconst code = char.codePointAt(0) ?? 0;\n\t\t\tif (code < 0x20 && char !== \"\\t\" && !(multiline && (char === \"\\n\" || char === \"\\r\"))) {\n\t\t\t\treturn { error: \"invalid control character in string value\" };\n\t\t\t}\n\t\t\tvalue += char;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst escapeChar = body[index + 1];\n\t\tif (escapeChar === undefined) return { error: \"unterminated escape sequence\" };\n\t\tif (multiline && (escapeChar === \"\\n\" || escapeChar === \"\\r\")) {\n\t\t\tindex++;\n\t\t\twhile (index + 1 < body.length && /\\s/.test(body[index + 1])) index++;\n\t\t\tcontinue;\n\t\t}\n\t\tif (escapeChar === \"u\" || escapeChar === \"U\") {\n\t\t\tconst width = escapeChar === \"u\" ? 4 : 8;\n\t\t\tconst hex = body.slice(index + 2, index + 2 + width);\n\t\t\tconst codePoint = /^[0-9a-fA-F]+$/.test(hex) && hex.length === width ? Number.parseInt(hex, 16) : -1;\n\t\t\tif (codePoint < 0 || codePoint > 0x10ffff || (codePoint >= 0xd800 && codePoint <= 0xdfff)) {\n\t\t\t\treturn { error: \"invalid unicode escape\" };\n\t\t\t}\n\t\t\tvalue += String.fromCodePoint(codePoint);\n\t\t\tindex += 1 + width;\n\t\t\tcontinue;\n\t\t}\n\t\tconst mapped = TOML_BASIC_ESCAPES[escapeChar];\n\t\tif (mapped === undefined) return { error: \"invalid escape sequence\" };\n\t\tvalue += mapped;\n\t\tindex++;\n\t}\n\treturn { value };\n}\n\n/** Parses one TOML string value. Errors are fixed and never include raw TOML content. */\nfunction parseTomlStringValue(raw: string, requireNonempty = true): { value: string } | { error: string } {\n\tconst text = raw.trim();\n\tconst multilineBasic = text.startsWith('\"\"\"');\n\tconst multilineLiteral = text.startsWith(\"'''\");\n\tconst basic = !multilineBasic && text.startsWith('\"');\n\tconst literal = !multilineLiteral && text.startsWith(\"'\");\n\tif (!multilineBasic && !multilineLiteral && !basic && !literal) {\n\t\treturn { error: \"value must be a quoted string\" };\n\t}\n\n\tconst delimiterWidth = multilineBasic || multilineLiteral ? 3 : 1;\n\tconst end =\n\t\tmultilineBasic || basic\n\t\t\t? findBasicStringEnd(text, delimiterWidth, multilineBasic)\n\t\t\t: text.indexOf(multilineLiteral ? \"'''\" : \"'\", delimiterWidth);\n\tif (end < 0) {\n\t\treturn {\n\t\t\terror:\n\t\t\t\tmultilineBasic || multilineLiteral ? \"unterminated multiline string value\" : \"unterminated string value\",\n\t\t};\n\t}\n\tif (text.slice(end + delimiterWidth).trim().length > 0) {\n\t\treturn { error: \"unexpected content after string value\" };\n\t}\n\n\tlet body = text.slice(delimiterWidth, end);\n\tif ((multilineBasic || multilineLiteral) && body.startsWith(\"\\n\")) body = body.slice(1);\n\tconst parsed =\n\t\tmultilineBasic || basic\n\t\t\t? decodeTomlBasicString(body, multilineBasic)\n\t\t\t: /[\\u0000-\\u0008\\u000b\\u000c\\u000e-\\u001f\\u007f]/.test(body)\n\t\t\t\t? { error: \"invalid control character in string value\" as const }\n\t\t\t\t: { value: body };\n\tif (\"error\" in parsed) return parsed;\n\treturn requireNonempty && parsed.value.length === 0 ? { error: \"empty string value\" } : parsed;\n}\n\nfunction scanTomlLine(text: string, state: TomlScanState): { content: string; error?: string } {\n\tlet content = \"\";\n\tfor (let index = 0; index < text.length; index++) {\n\t\tconst char = text[index];\n\t\tif (state.quote === \"basic\") {\n\t\t\tcontent += char;\n\t\t\tif (char === \"\\\\\" && index + 1 < text.length) content += text[++index];\n\t\t\telse if (char === '\"') state.quote = undefined;\n\t\t\tcontinue;\n\t\t}\n\t\tif (state.quote === \"literal\") {\n\t\t\tcontent += char;\n\t\t\tif (char === \"'\") state.quote = undefined;\n\t\t\tcontinue;\n\t\t}\n\t\tif (state.quote === \"multiline-basic\") {\n\t\t\tif (text.startsWith('\"\"\"', index)) {\n\t\t\t\tcontent += '\"\"\"';\n\t\t\t\tindex += 2;\n\t\t\t\tstate.quote = undefined;\n\t\t\t} else {\n\t\t\t\tcontent += char;\n\t\t\t\tif (char === \"\\\\\" && index + 1 < text.length) content += text[++index];\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (state.quote === \"multiline-literal\") {\n\t\t\tif (text.startsWith(\"'''\", index)) {\n\t\t\t\tcontent += \"'''\";\n\t\t\t\tindex += 2;\n\t\t\t\tstate.quote = undefined;\n\t\t\t} else {\n\t\t\t\tcontent += char;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\n\t\tif (char === \"#\") break;\n\t\tif (text.startsWith('\"\"\"', index)) {\n\t\t\tcontent += '\"\"\"';\n\t\t\tindex += 2;\n\t\t\tstate.quote = \"multiline-basic\";\n\t\t\tcontinue;\n\t\t}\n\t\tif (text.startsWith(\"'''\", index)) {\n\t\t\tcontent += \"'''\";\n\t\t\tindex += 2;\n\t\t\tstate.quote = \"multiline-literal\";\n\t\t\tcontinue;\n\t\t}\n\t\tcontent += char;\n\t\tif (char === '\"') state.quote = \"basic\";\n\t\telse if (char === \"'\") state.quote = \"literal\";\n\t\telse if (char === \"[\" || char === \"{\") state.containers.push(char);\n\t\telse if (char === \"]\" || char === \"}\") {\n\t\t\tconst expected = char === \"]\" ? \"[\" : \"{\";\n\t\t\tif (state.containers.pop() !== expected) return { content, error: \"mismatched value delimiter\" };\n\t\t}\n\t}\n\tif (state.quote === \"basic\" || state.quote === \"literal\") {\n\t\treturn { content, error: \"unterminated string value\" };\n\t}\n\treturn { content };\n}\n\nfunction consumeTomlValue(\n\tlines: readonly string[],\n\tstartLine: number,\n\tinitial: string,\n): { value?: string; endLine: number; error?: string } {\n\tconst state: TomlScanState = { containers: [] };\n\tconst chunks: string[] = [];\n\tfor (let line = startLine; line < lines.length; line++) {\n\t\tconst scanned = scanTomlLine(line === startLine ? initial : lines[line], state);\n\t\tchunks.push(scanned.content);\n\t\tif (scanned.error) return { endLine: line, error: scanned.error };\n\t\tif (!state.quote && state.containers.length === 0) {\n\t\t\tconst value = chunks.join(\"\\n\").trim();\n\t\t\treturn value.length > 0\n\t\t\t\t? { value, endLine: line }\n\t\t\t\t: { endLine: startLine, error: \"assignment value is missing\" };\n\t\t}\n\t}\n\treturn {\n\t\tendLine: startLine,\n\t\terror: state.quote ? \"unterminated multiline string value\" : \"unterminated compound value\",\n\t};\n}\n\nfunction findTomlTopLevelCharacter(text: string, wanted: string): number {\n\tconst state: TomlScanState = { containers: [] };\n\tfor (let index = 0; index < text.length; index++) {\n\t\tconst char = text[index];\n\t\tif (state.quote === \"basic\" || state.quote === \"multiline-basic\") {\n\t\t\tif (char === \"\\\\\") index++;\n\t\t\telse if (state.quote === \"basic\" && char === '\"') state.quote = undefined;\n\t\t\telse if (state.quote === \"multiline-basic\" && text.startsWith('\"\"\"', index)) {\n\t\t\t\tstate.quote = undefined;\n\t\t\t\tindex += 2;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (state.quote === \"literal\" || state.quote === \"multiline-literal\") {\n\t\t\tconst delimiter = state.quote === \"literal\" ? \"'\" : \"'''\";\n\t\t\tif (text.startsWith(delimiter, index)) {\n\t\t\t\tstate.quote = undefined;\n\t\t\t\tindex += delimiter.length - 1;\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tif (char === \"#\") return -1;\n\t\tif (text.startsWith('\"\"\"', index)) {\n\t\t\tstate.quote = \"multiline-basic\";\n\t\t\tindex += 2;\n\t\t} else if (text.startsWith(\"'''\", index)) {\n\t\t\tstate.quote = \"multiline-literal\";\n\t\t\tindex += 2;\n\t\t} else if (char === '\"') state.quote = \"basic\";\n\t\telse if (char === \"'\") state.quote = \"literal\";\n\t\telse if (char === \"[\" || char === \"{\") state.containers.push(char);\n\t\telse if (char === \"]\" || char === \"}\") state.containers.pop();\n\t\telse if (char === wanted && state.containers.length === 0) return index;\n\t}\n\treturn -1;\n}\n\nfunction parseTomlDottedKey(raw: string): string[] | undefined {\n\tconst components: string[] = [];\n\tlet index = 0;\n\twhile (index < raw.length) {\n\t\twhile (/\\s/.test(raw[index] ?? \"\")) index++;\n\t\tlet component: string | undefined;\n\t\tif (raw[index] === '\"') {\n\t\t\tconst end = findBasicStringEnd(raw, index + 1, false);\n\t\t\tif (end < 0) return undefined;\n\t\t\tconst parsed = parseTomlStringValue(raw.slice(index, end + 1), false);\n\t\t\tif (\"error\" in parsed) return undefined;\n\t\t\tcomponent = parsed.value;\n\t\t\tindex = end + 1;\n\t\t} else if (raw[index] === \"'\") {\n\t\t\tconst end = raw.indexOf(\"'\", index + 1);\n\t\t\tif (end < 0) return undefined;\n\t\t\tcomponent = raw.slice(index + 1, end);\n\t\t\tindex = end + 1;\n\t\t} else {\n\t\t\tconst match = /^[A-Za-z0-9_-]+/.exec(raw.slice(index));\n\t\t\tif (!match) return undefined;\n\t\t\tcomponent = match[0];\n\t\t\tindex += match[0].length;\n\t\t}\n\t\tcomponents.push(component);\n\t\twhile (/\\s/.test(raw[index] ?? \"\")) index++;\n\t\tif (index === raw.length) return components;\n\t\tif (raw[index] !== \".\") return undefined;\n\t\tindex++;\n\t\tif (index === raw.length) return undefined;\n\t}\n\treturn undefined;\n}\n\nfunction splitTomlTopLevel(raw: string): string[] {\n\tconst parts: string[] = [];\n\tlet start = 0;\n\tfor (let index = 0; index < raw.length; index++) {\n\t\tif (raw[index] !== \",\") continue;\n\t\tconst relative = findTomlTopLevelCharacter(raw.slice(start, index + 1), \",\");\n\t\tif (relative !== index - start) continue;\n\t\tparts.push(raw.slice(start, index).trim());\n\t\tstart = index + 1;\n\t}\n\tparts.push(raw.slice(start).trim());\n\treturn parts;\n}\n\nfunction isValidTomlScalar(raw: string): boolean {\n\treturn (\n\t\traw === \"true\" ||\n\t\traw === \"false\" ||\n\t\t/^[+-]?(?:0|[1-9](?:_?\\d)*)$/.test(raw) ||\n\t\t/^[+-]?0x[0-9A-Fa-f](?:_?[0-9A-Fa-f])*$/.test(raw) ||\n\t\t/^[+-]?0o[0-7](?:_?[0-7])*$/.test(raw) ||\n\t\t/^[+-]?0b[01](?:_?[01])*$/.test(raw) ||\n\t\t/^[+-]?(?:(?:0|[1-9](?:_?\\d)*)\\.(?:\\d(?:_?\\d)*)(?:[eE][+-]?\\d(?:_?\\d)*)?|(?:0|[1-9](?:_?\\d)*)[eE][+-]?\\d(?:_?\\d)*|inf|nan)$/.test(\n\t\t\traw,\n\t\t) ||\n\t\t/^\\d{4}-\\d{2}-\\d{2}(?:[Tt ]\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:[Zz]|[+-]\\d{2}:\\d{2})?)?$/.test(raw) ||\n\t\t/^\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?$/.test(raw)\n\t);\n}\n\nfunction isValidTomlValue(raw: string): boolean {\n\tconst text = raw.trim();\n\tif (text.startsWith('\"') || text.startsWith(\"'\")) return !(\"error\" in parseTomlStringValue(text, false));\n\tif (text.startsWith(\"[\") && text.endsWith(\"]\")) {\n\t\tconst parts = splitTomlTopLevel(text.slice(1, -1));\n\t\tif (parts.at(-1) === \"\") parts.pop();\n\t\treturn parts.every((part) => part.length > 0 && isValidTomlValue(part));\n\t}\n\tif (text.startsWith(\"{\") && text.endsWith(\"}\")) {\n\t\tconst body = text.slice(1, -1).trim();\n\t\tif (body.length === 0) return true;\n\t\treturn splitTomlTopLevel(body).every((part) => {\n\t\t\tconst equals = findTomlTopLevelCharacter(part, \"=\");\n\t\t\treturn equals > 0 && !!parseTomlDottedKey(part.slice(0, equals)) && isValidTomlValue(part.slice(equals + 1));\n\t\t});\n\t}\n\treturn isValidTomlScalar(text);\n}\n\nfunction parseTomlTable(line: string): { components?: string[]; array?: boolean; error?: string } {\n\tconst state: TomlScanState = { containers: [] };\n\tconst scanned = scanTomlLine(line, state);\n\tif (scanned.error || state.quote || state.containers.length > 0) return { error: \"malformed table header\" };\n\tconst text = scanned.content.trim();\n\tconst array = text.startsWith(\"[[\");\n\tif (array ? !text.endsWith(\"]]\") : !text.endsWith(\"]\")) return { error: \"malformed table header\" };\n\tconst inner = text.slice(array ? 2 : 1, array ? -2 : -1).trim();\n\tconst components = parseTomlDottedKey(inner);\n\treturn components && components.length > 0 ? { components, array } : { error: \"malformed table header\" };\n}\n\n/**\n * Strict Kimi TOML subset reader. It validates every table/assignment and generic TOML value,\n * but extracts only root `base_url`/`model_name` and `[providers.<name>]` string fields. Fixed\n * line-number errors ensure credentials and other file content are never echoed.\n */\nfunction loadKimiConfig(path: string): KimiConfigLoad {\n\tif (!existsSync(path)) return { kind: \"missing\" };\n\tlet content: string;\n\ttry {\n\t\tcontent = readFileSync(path, \"utf-8\");\n\t} catch {\n\t\treturn { kind: \"invalid\", line: 0, reason: \"file is unreadable\" };\n\t}\n\tconst value: KimiConfigValues = { providers: [] };\n\tconst lines = content.split(/\\r?\\n/);\n\tconst assignments = new Set<string>();\n\tlet table: KimiTomlProviderEntry | \"root\" | \"other\" = \"root\";\n\tlet scope = \"root\";\n\tfor (let index = 0; index < lines.length; index++) {\n\t\tconst line = lines[index].trim();\n\t\tif (line.length === 0 || line.startsWith(\"#\")) continue;\n\t\tif (line.startsWith(\"[\")) {\n\t\t\tconst parsed = parseTomlTable(line);\n\t\t\tif (parsed.error || !parsed.components) {\n\t\t\t\treturn { kind: \"invalid\", line: index + 1, reason: parsed.error ?? \"malformed table header\" };\n\t\t\t}\n\t\t\tconst [first, name] = parsed.components;\n\t\t\tif (first === \"providers\" && parsed.array) {\n\t\t\t\treturn { kind: \"invalid\", line: index + 1, reason: \"provider table cannot be an array\" };\n\t\t\t}\n\t\t\tif (first === \"providers\" && parsed.components.length === 2 && name !== undefined && name.length > 0) {\n\t\t\t\tconst entry: KimiTomlProviderEntry = { name };\n\t\t\t\tvalue.providers.push(entry);\n\t\t\t\ttable = entry;\n\t\t\t} else {\n\t\t\t\ttable = \"other\";\n\t\t\t}\n\t\t\tscope = `${parsed.array ? \"array\" : \"table\"}:${JSON.stringify(parsed.components)}`;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst assignmentLine = index;\n\t\tconst equals = findTomlTopLevelCharacter(line, \"=\");\n\t\tconst key = equals > 0 ? parseTomlDottedKey(line.slice(0, equals)) : undefined;\n\t\tif (!key || key.length === 0) return { kind: \"invalid\", line: index + 1, reason: \"invalid assignment\" };\n\t\tconst consumed = consumeTomlValue(lines, index, line.slice(equals + 1));\n\t\tif (consumed.error || consumed.value === undefined) {\n\t\t\treturn { kind: \"invalid\", line: assignmentLine + 1, reason: consumed.error ?? \"invalid assignment value\" };\n\t\t}\n\t\tindex = consumed.endLine;\n\t\tif (!isValidTomlValue(consumed.value)) {\n\t\t\treturn { kind: \"invalid\", line: assignmentLine + 1, reason: \"invalid assignment value\" };\n\t\t}\n\t\tconst assignmentId = `${scope}:${JSON.stringify(key)}`;\n\t\tif (assignments.has(assignmentId)) {\n\t\t\treturn { kind: \"invalid\", line: assignmentLine + 1, reason: \"duplicate assignment\" };\n\t\t}\n\t\tassignments.add(assignmentId);\n\t\tif (key.length !== 1 || table === \"other\") continue;\n\n\t\tconst keyName = key[0];\n\t\tconst relevant =\n\t\t\ttable === \"root\"\n\t\t\t\t? keyName === \"base_url\" || keyName === \"model_name\"\n\t\t\t\t: keyName === \"base_url\" ||\n\t\t\t\t\tkeyName === \"model_name\" ||\n\t\t\t\t\tkeyName === \"model\" ||\n\t\t\t\t\tkeyName === \"type\" ||\n\t\t\t\t\tkeyName === \"api_key\";\n\t\tif (!relevant) continue;\n\t\tconst parsedValue = parseTomlStringValue(consumed.value);\n\t\tif (\"error\" in parsedValue) return { kind: \"invalid\", line: assignmentLine + 1, reason: parsedValue.error };\n\t\tif (table === \"root\") {\n\t\t\tif (keyName === \"base_url\") value.baseUrl = parsedValue.value;\n\t\t\telse value.modelName = parsedValue.value;\n\t\t} else {\n\t\t\tif (keyName === \"base_url\") table.baseUrl = parsedValue.value;\n\t\t\telse if (keyName === \"type\") table.type = parsedValue.value;\n\t\t\telse if (keyName === \"api_key\") table.apiKey = parsedValue.value;\n\t\t\telse table.modelName = parsedValue.value;\n\t\t}\n\t}\n\treturn { kind: \"ok\", value };\n}\n\nfunction nonemptyEnv(name: string): string | undefined {\n\tconst value = process.env[name];\n\treturn value && value.length > 0 ? value : undefined;\n}\n\ninterface KimiResolution {\n\tbaseUrl?: string;\n\tmodelName?: string;\n\tbaseUrlSource?: \"kimi-environment\" | \"kimi-config-toml\";\n\t/** First `[providers.<name>]` entry with `type = \"openai_legacy\"` and a base URL (§10.2). */\n\tcustomProvider?: { name: string; baseUrl: string; modelName?: string; apiKey?: string };\n\tfailure?: { line: number; reason: string };\n}\n\nfunction resolveKimiConfig(kimiConfigPath: string | undefined): KimiResolution {\n\tconst path = kimiConfigPath ?? join(homedir(), \".kimi\", \"config.toml\");\n\tconst loaded = loadKimiConfig(path);\n\tif (loaded.kind === \"invalid\") return { failure: { line: loaded.line, reason: loaded.reason } };\n\tconst fileValues: KimiConfigValues = loaded.kind === \"ok\" ? loaded.value : { providers: [] };\n\tconst envBaseUrl = nonemptyEnv(\"KIMI_BASE_URL\");\n\tconst envModelName = nonemptyEnv(\"KIMI_MODEL_NAME\");\n\tconst custom = fileValues.providers.find((entry) => entry.type === \"openai_legacy\" && entry.baseUrl);\n\treturn {\n\t\tbaseUrl: envBaseUrl ?? fileValues.baseUrl,\n\t\tmodelName: envModelName ?? fileValues.modelName,\n\t\tbaseUrlSource: envBaseUrl ? \"kimi-environment\" : fileValues.baseUrl ? \"kimi-config-toml\" : undefined,\n\t\tcustomProvider: custom\n\t\t\t? { name: custom.name, baseUrl: custom.baseUrl as string, modelName: custom.modelName, apiKey: custom.apiKey }\n\t\t\t: undefined,\n\t};\n}\n\nfunction loadConfig<T>(path: string, parse: (value: unknown) => T | undefined, allowComments = false): LoadedConfig<T> {\n\tif (!existsSync(path)) return { kind: \"missing\" };\n\ttry {\n\t\tconst content = readFileSync(path, \"utf-8\");\n\t\tconst parsed = JSON.parse(allowComments ? stripJsonComments(content) : content) as unknown;\n\t\tconst value = parse(parsed);\n\t\treturn value ? { kind: \"ok\", value } : { kind: \"invalid\" };\n\t} catch {\n\t\treturn { kind: \"invalid\" };\n\t}\n}\n\nexport function normalizedUrlHostname(url: URL): string {\n\treturn normalizedHostname(url);\n}\n\nfunction normalizedHostname(url: URL): string {\n\tconst hostname = url.hostname.toLowerCase();\n\tconst unwrapped = hostname.startsWith(\"[\") && hostname.endsWith(\"]\") ? hostname.slice(1, -1) : hostname;\n\treturn unwrapped.endsWith(\".\") ? unwrapped.slice(0, -1) : unwrapped;\n}\n\nfunction isLiteralLoopback(hostname: string): boolean {\n\tif (hostname === \"localhost\" || hostname === \"::1\") return true;\n\tif (isIP(hostname) !== 4) return false;\n\treturn Number(hostname.split(\".\")[0]) === 127;\n}\n\nfunction isBlockedPublicHost(hostname: string): boolean {\n\tif (hostname === \"localhost\" || hostname.endsWith(\".localhost\")) return true;\n\tif (isIP(hostname) === 0) return false;\n\treturn isBlockedPublicAddress(hostname);\n}\n\nfunction sanitizeUrl(rawUrl: string): URL | undefined {\n\ttry {\n\t\tconst url = new URL(rawUrl);\n\t\turl.username = \"\";\n\t\turl.password = \"\";\n\t\turl.search = \"\";\n\t\turl.hash = \"\";\n\t\treturn url;\n\t} catch {\n\t\treturn undefined;\n\t}\n}\n\nexport function canonicalProviderEndpointUrl(rawUrl: string | undefined): string | undefined {\n\tif (!rawUrl) return undefined;\n\tconst url = sanitizeUrl(rawUrl);\n\tif (!url) return undefined;\n\tconst hostname = normalizedHostname(url);\n\tconst host = isIP(hostname) === 6 ? `[${hostname}]` : hostname;\n\tconst pathname = url.pathname.replace(/\\/+$/, \"\") || \"/\";\n\treturn `${url.protocol}//${host}${url.port ? `:${url.port}` : \"\"}${pathname}`;\n}\n\nfunction credentialBindingMatchesTarget(\n\tbinding: ProviderDoctorCredentialBinding,\n\ttarget: ResolvedProviderTarget,\n): boolean {\n\treturn (\n\t\tbinding.origin === target.origin &&\n\t\tbinding.source === target.source &&\n\t\tbinding.baseUrl === canonicalProviderEndpointUrl(target.endpoint.baseUrl) &&\n\t\tbinding.api === target.endpoint.api &&\n\t\tbinding.modelId === target.endpoint.modelId\n\t);\n}\n\nfunction appendPath(url: URL, segment: string): URL {\n\tconst next = URL.parse(url.href);\n\tif (!next) throw new Error(\"validated provider URL could not be cloned\");\n\tnext.pathname = `${next.pathname.replace(/\\/$/, \"\")}/${segment}`;\n\treturn next;\n}\n\nfunction makeRootProbeUrl(url: URL, origin: ProviderOrigin): URL {\n\tconst root = URL.parse(url.href);\n\tif (!root) throw new Error(\"validated provider URL could not be cloned\");\n\tif (origin !== \"local-proxy\") return root;\n\troot.pathname = \"/health\";\n\treturn root;\n}\n\nfunction publicResult(\n\ttarget: ResolvedProviderTarget,\n\tlevel: ProviderDoctorLevel,\n\tchecks: ProviderDoctorCheck[],\n\turl: URL | undefined,\n\tfailure?: ProbeFailure,\n\tcostWarning?: boolean,\n): ProviderDoctorResult {\n\tconst targetUrl = url?.href;\n\treturn {\n\t\tprovider: target.providerId,\n\t\tstatus: failure ? \"fail\" : \"ok\",\n\t\tlevel,\n\t\torigin: target.origin,\n\t\tsource: target.source,\n\t\ttargetUrl,\n\t\tbaseUrl: targetUrl,\n\t\tapi: target.endpoint.api,\n\t\tmodelId: target.endpoint.modelId,\n\t\tauthPresent: target.auth.present,\n\t\t...(costWarning ? { costWarning: true } : {}),\n\t\tchecks,\n\t\terror: failure,\n\t};\n}\n\nfunction unresolvedFailure(\n\tproviderId: string,\n\tlevel: ProviderDoctorLevel,\n\tcode: ProviderDoctorCode,\n\tmessage: string,\n): ProviderDoctorResult {\n\tconst check: ProviderDoctorCheck = { name: \"config\", status: \"fail\", category: \"config\", code, message };\n\treturn {\n\t\tprovider: providerId,\n\t\tstatus: \"fail\",\n\t\tlevel,\n\t\torigin: \"unknown\",\n\t\tsource: \"unresolved\",\n\t\tauthPresent: false,\n\t\tchecks: [check],\n\t\terror: { category: \"config\", code, message },\n\t};\n}\n\nfunction staticChecks(target: ResolvedProviderTarget): {\n\tchecks: ProviderDoctorCheck[];\n\turl?: URL;\n\tfailure?: ProbeFailure;\n} {\n\tconst checks: ProviderDoctorCheck[] = [\n\t\t{ name: \"config-present\", status: \"ok\", code: \"ok\", message: \"Provider configuration resolved\" },\n\t];\n\tif (target.origin === \"custom-openai-compatible\") {\n\t\tchecks.push({\n\t\t\tname: \"native-provider-checks\",\n\t\t\tstatus: \"skipped\",\n\t\t\tcode: \"ok\",\n\t\t\tmessage: \"Custom OpenAI-compatible endpoint; native-only provider checks skipped\",\n\t\t});\n\t}\n\tlet failure: ProbeFailure | undefined;\n\tconst recordFailure = (next: ProbeFailure): void => {\n\t\tfailure ??= next;\n\t};\n\n\tconst requestedModel = target.endpoint.modelId;\n\tconst modelIds = target.endpoint.modelIds ?? [];\n\tif (!requestedModel) {\n\t\tchecks.push({ name: \"model-provider-relation\", status: \"skipped\", code: \"ok\", message: \"No model selected\" });\n\t} else if (!modelIds.includes(requestedModel)) {\n\t\tconst next: ProbeFailure = {\n\t\t\tcategory: \"model\",\n\t\t\tcode: \"model-provider-mismatch\",\n\t\t\tmessage: \"Selected model does not belong to the provider\",\n\t\t};\n\t\tchecks.push({ name: \"model-provider-relation\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t} else {\n\t\tchecks.push({ name: \"model-provider-relation\", status: \"ok\", code: \"ok\", message: \"Model belongs to provider\" });\n\t}\n\n\tconst api = target.endpoint.api;\n\tif (!api) {\n\t\tconst next: ProbeFailure = { category: \"config\", code: \"api-missing\", message: \"Provider API type is missing\" };\n\t\tchecks.push({ name: \"api\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t} else if (\n\t\t!KNOWN_APIS.has(api) ||\n\t\t(target.origin === \"custom-openai-compatible\" && !OPENAI_COMPATIBLE_APIS.has(api))\n\t) {\n\t\tconst next: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"api-unsupported\",\n\t\t\tmessage: \"Provider API type is unsupported\",\n\t\t};\n\t\tchecks.push({ name: \"api\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t} else {\n\t\tchecks.push({ name: \"api\", status: \"ok\", code: \"ok\", message: \"Provider API type is supported\" });\n\t}\n\n\tlet url: URL | undefined;\n\tif (!target.endpoint.baseUrl) {\n\t\tconst next: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"base-url-missing\",\n\t\t\tmessage: \"Provider base URL is missing\",\n\t\t};\n\t\tchecks.push({ name: \"base-url\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t} else {\n\t\turl = sanitizeUrl(target.endpoint.baseUrl);\n\t\tif (!url) {\n\t\t\tconst next: ProbeFailure = {\n\t\t\t\tcategory: \"config\",\n\t\t\t\tcode: \"base-url-invalid\",\n\t\t\t\tmessage: \"Provider base URL is invalid\",\n\t\t\t};\n\t\t\tchecks.push({ name: \"base-url\", status: \"fail\", ...next });\n\t\t\trecordFailure(next);\n\t\t} else {\n\t\t\tconst allowedScheme =\n\t\t\t\ttarget.origin === \"local-proxy\"\n\t\t\t\t\t? url.protocol === \"http:\" || url.protocol === \"https:\"\n\t\t\t\t\t: url.protocol === \"https:\";\n\t\t\tif (!allowedScheme) {\n\t\t\t\tconst next: ProbeFailure = {\n\t\t\t\t\tcategory: \"config\",\n\t\t\t\t\tcode: \"url-scheme-unsupported\",\n\t\t\t\t\tmessage: \"Provider URL scheme is not allowed\",\n\t\t\t\t};\n\t\t\t\tchecks.push({ name: \"base-url\", status: \"fail\", ...next });\n\t\t\t\trecordFailure(next);\n\t\t\t} else {\n\t\t\t\tchecks.push({ name: \"base-url\", status: \"ok\", code: \"ok\", message: \"Provider base URL is valid\" });\n\t\t\t}\n\t\t}\n\t}\n\n\tif (target.origin === \"unknown\") {\n\t\tconst next: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"origin-unsupported\",\n\t\t\tmessage: \"Provider origin is unsupported\",\n\t\t};\n\t\tchecks.push({ name: \"origin-policy\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t} else if (url) {\n\t\tconst hostname = normalizedHostname(url);\n\t\tconst blocked = target.origin === \"local-proxy\" ? !isLiteralLoopback(hostname) : isBlockedPublicHost(hostname);\n\t\tif (blocked) {\n\t\t\tconst next: ProbeFailure = {\n\t\t\t\tcategory: \"config\",\n\t\t\t\tcode: \"address-policy-blocked\",\n\t\t\t\tmessage: \"Provider address is blocked by origin policy\",\n\t\t\t};\n\t\t\tchecks.push({ name: \"origin-policy\", status: \"fail\", ...next });\n\t\t\trecordFailure(next);\n\t\t} else {\n\t\t\tchecks.push({ name: \"origin-policy\", status: \"ok\", code: \"ok\", message: \"Provider origin policy passed\" });\n\t\t}\n\t} else {\n\t\tchecks.push({ name: \"origin-policy\", status: \"skipped\", code: \"ok\", message: \"No valid URL to inspect\" });\n\t}\n\n\tif (target.auth.present) {\n\t\tchecks.push({ name: \"auth-present\", status: \"ok\", code: \"ok\", message: \"Authentication is configured\" });\n\t} else if (target.origin === \"custom-openai-compatible\" || target.origin === \"local-proxy\") {\n\t\t// Native login checks do not apply: custom/local OpenAI-compatible endpoints may be keyless.\n\t\tchecks.push({\n\t\t\tname: \"auth-present\",\n\t\t\tstatus: \"skipped\",\n\t\t\tcode: \"ok\",\n\t\t\tmessage: \"No credential configured; custom endpoints may be keyless\",\n\t\t});\n\t} else {\n\t\tconst next: ProbeFailure = {\n\t\t\tcategory: \"auth\",\n\t\t\tcode: \"auth-missing\",\n\t\t\tmessage: \"Authentication is not configured\",\n\t\t};\n\t\tchecks.push({ name: \"auth-present\", status: \"fail\", ...next });\n\t\trecordFailure(next);\n\t}\n\n\treturn { checks, url, failure };\n}\n\ntype ProbeEndpointKind = \"root\" | \"models\" | \"model-probe\";\n\nfunction classifyProbe(name: string, kind: ProbeEndpointKind, status: number): ProbeOutcome {\n\tconst forModels = kind === \"models\";\n\tif (Number.isInteger(status) && status >= 200 && status < 300) {\n\t\tconst probe: EndpointProbeResult = { reachable: true, authenticated: true, status, category: \"ok\" };\n\t\tif (forModels) probe.modelsSupported = true;\n\t\treturn { check: { name, status: \"ok\", code: \"ok\", message: `HTTP ${status}`, probe } };\n\t}\n\tif (status >= 300 && status < 400) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"redirect-blocked\",\n\t\t\tmessage: \"Provider probe returned a blocked redirect\",\n\t\t};\n\t\treturn { check: { name, status: \"fail\", ...failure }, failure };\n\t}\n\tif (status === 401 || status === 403) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"auth\",\n\t\t\tcode: \"authentication-failed\",\n\t\t\tmessage: \"Provider rejected authentication\",\n\t\t};\n\t\tconst probe: EndpointProbeResult = { reachable: true, authenticated: false, status, category: \"auth\" };\n\t\treturn { check: { name, status: \"fail\", ...failure, probe }, failure };\n\t}\n\tif (status === 404 || status === 405 || status === 501) {\n\t\t// A root or /models 404 is neutral: OpenAI-compatible servers may not expose these paths.\n\t\tconst probe: EndpointProbeResult = { reachable: true, status, category: \"unsupported-endpoint\" };\n\t\tif (forModels) probe.modelsSupported = false;\n\t\treturn {\n\t\t\tcheck: {\n\t\t\t\tname,\n\t\t\t\tstatus: \"unsupported\",\n\t\t\t\tcode: \"endpoint-unsupported\",\n\t\t\t\tmessage: `HTTP ${status}; endpoint is not required`,\n\t\t\t\tprobe,\n\t\t\t},\n\t\t};\n\t}\n\tif (status >= 500 && status <= 599) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"server\",\n\t\t\tcode: \"server-error\",\n\t\t\tmessage: \"Provider endpoint returned a server error\",\n\t\t};\n\t\tconst probe: EndpointProbeResult = { reachable: true, status, category: \"server\" };\n\t\treturn { check: { name, status: \"fail\", ...failure, probe }, failure };\n\t}\n\tif (status === 408 || status === 429) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"network\",\n\t\t\tcode: \"network-failure\",\n\t\t\tmessage: \"Provider probe failed at the network boundary\",\n\t\t};\n\t\tconst probe: EndpointProbeResult = { reachable: true, status, category: \"network\" };\n\t\treturn { check: { name, status: \"fail\", ...failure, probe }, failure };\n\t}\n\n\tconst failure: ProbeFailure = {\n\t\tcategory: \"config\",\n\t\tcode: \"unexpected-response\",\n\t\tmessage: \"Provider probe returned an unexpected response\",\n\t};\n\treturn { check: { name, status: \"fail\", ...failure }, failure };\n}\n\nfunction createComposedController(\n\tsignal: AbortSignal | undefined,\n\ttimeoutMs: number,\n): {\n\tcontroller: AbortController;\n\tabortKind: () => \"aborted\" | \"timeout\" | undefined;\n\tdispose: () => void;\n} {\n\tconst controller = new AbortController();\n\tlet kind: \"aborted\" | \"timeout\" | undefined;\n\tconst abortFromCaller = (): void => {\n\t\tkind ??= \"aborted\";\n\t\tcontroller.abort();\n\t};\n\tif (signal?.aborted) abortFromCaller();\n\telse signal?.addEventListener(\"abort\", abortFromCaller, { once: true });\n\tconst timeout = setTimeout(() => {\n\t\tkind ??= \"timeout\";\n\t\tcontroller.abort();\n\t}, timeoutMs);\n\n\treturn {\n\t\tcontroller,\n\t\tabortKind: () => kind,\n\t\tdispose: () => {\n\t\t\tclearTimeout(timeout);\n\t\t\tsignal?.removeEventListener(\"abort\", abortFromCaller);\n\t\t},\n\t};\n}\n\nfunction requestWithAbort(\n\ttransport: ProviderDoctorTransport,\n\trequest: ProviderDoctorTransportRequest,\n): Promise<ProviderDoctorTransportResponse> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (request.signal.aborted) {\n\t\t\treject(ABORTED);\n\t\t\treturn;\n\t\t}\n\t\tconst onAbort = (): void => reject(ABORTED);\n\t\trequest.signal.addEventListener(\"abort\", onAbort, { once: true });\n\t\tlet pending: Promise<ProviderDoctorTransportResponse>;\n\t\ttry {\n\t\t\tpending = transport.request(request);\n\t\t} catch (error) {\n\t\t\trequest.signal.removeEventListener(\"abort\", onAbort);\n\t\t\treject(error instanceof ProviderDoctorAuthMaterializationError ? error : undefined);\n\t\t\treturn;\n\t\t}\n\t\tvoid pending.then(\n\t\t\t(response) => {\n\t\t\t\trequest.signal.removeEventListener(\"abort\", onAbort);\n\t\t\t\tresolve(response);\n\t\t\t},\n\t\t\t(error: unknown) => {\n\t\t\t\trequest.signal.removeEventListener(\"abort\", onAbort);\n\t\t\t\treject(error instanceof ProviderDoctorAuthMaterializationError ? error : undefined);\n\t\t\t},\n\t\t);\n\t});\n}\n\ninterface ProbePayload {\n\tbody: string;\n\tcontentType: \"application/json\";\n}\n\nasync function runProbe(\n\tname: string,\n\tkind: ProbeEndpointKind,\n\turl: URL,\n\ttransport: ProviderDoctorTransport,\n\taddressPolicy: ProviderDoctorAddressPolicy,\n\tcreateHeaders: ProviderDoctorHeaderFactory,\n\tcontroller: ReturnType<typeof createComposedController>,\n\tpayload?: ProbePayload,\n): Promise<ProbeOutcome> {\n\ttry {\n\t\tconst response = await requestWithAbort(transport, {\n\t\t\turl,\n\t\t\tmethod: payload ? \"POST\" : \"GET\",\n\t\t\tredirect: \"manual\",\n\t\t\tsignal: controller.controller.signal,\n\t\t\taddressPolicy,\n\t\t\tcreateHeaders,\n\t\t\tbody: payload?.body,\n\t\t\tcontentType: payload?.contentType,\n\t\t});\n\t\treturn classifyProbe(name, kind, response.status);\n\t} catch (error) {\n\t\tif (error instanceof ProviderDoctorAuthMaterializationError) {\n\t\t\tconst failure: ProbeFailure = {\n\t\t\t\tcategory: \"auth\",\n\t\t\t\tcode: \"auth-materialization-failed\",\n\t\t\t\tmessage: \"Configured authentication could not be materialized; verify auth and config references\",\n\t\t\t};\n\t\t\treturn {\n\t\t\t\tcheck: {\n\t\t\t\t\tname,\n\t\t\t\t\tstatus: \"fail\",\n\t\t\t\t\t...failure,\n\t\t\t\t\tprobe: { reachable: false, authenticated: false, category: \"auth\" },\n\t\t\t\t},\n\t\t\t\tfailure,\n\t\t\t};\n\t\t}\n\t\tconst abortKind = controller.abortKind();\n\t\tconst failure: ProbeFailure = abortKind\n\t\t\t? {\n\t\t\t\t\tcategory: \"network\",\n\t\t\t\t\tcode: abortKind === \"timeout\" ? \"request-timeout\" : \"request-aborted\",\n\t\t\t\t\tmessage: abortKind === \"timeout\" ? \"Provider probe timed out\" : \"Provider probe was aborted\",\n\t\t\t\t}\n\t\t\t: { category: \"network\", code: \"network-failure\", message: \"Provider transport failed\" };\n\t\treturn {\n\t\t\tcheck: { name, status: \"fail\", ...failure, probe: { reachable: false, category: \"network\" } },\n\t\t\tfailure,\n\t\t};\n\t}\n}\n\n/** Minimal-token generative probe payload; never includes tools (no tool-call probe). */\nfunction modelProbeSpec(api: string, modelId: string): { path: string; payload: ProbePayload } | undefined {\n\tif (api === \"openai-completions\") {\n\t\treturn {\n\t\t\tpath: \"chat/completions\",\n\t\t\tpayload: {\n\t\t\t\tbody: JSON.stringify({\n\t\t\t\t\tmodel: modelId,\n\t\t\t\t\tmessages: [{ role: \"user\", content: \"ping\" }],\n\t\t\t\t\tmax_tokens: 1,\n\t\t\t\t\tstream: false,\n\t\t\t\t}),\n\t\t\t\tcontentType: \"application/json\",\n\t\t\t},\n\t\t};\n\t}\n\tif (api === \"openai-responses\") {\n\t\treturn {\n\t\t\tpath: \"responses\",\n\t\t\tpayload: {\n\t\t\t\t// The responses API rejects max_output_tokens below 16; still the minimal request.\n\t\t\t\tbody: JSON.stringify({ model: modelId, input: \"ping\", max_output_tokens: 16, stream: false }),\n\t\t\t\tcontentType: \"application/json\",\n\t\t\t},\n\t\t};\n\t}\n\treturn undefined;\n}\n\nfunction classifyOrigin(baseUrl: string | undefined, api: string | undefined, isNative: boolean): ProviderOrigin {\n\tconst url = baseUrl ? sanitizeUrl(baseUrl) : undefined;\n\tif (url && isLiteralLoopback(normalizedHostname(url))) {\n\t\treturn \"local-proxy\";\n\t}\n\tif (isNative) return \"native\";\n\tif (api && OPENAI_COMPATIBLE_APIS.has(api)) return \"custom-openai-compatible\";\n\treturn \"unknown\";\n}\n\nfunction resolveProviderTarget(\n\tproviderId: string,\n\toptions: ProviderDoctorOptions,\n): { target?: ResolvedProviderTarget; failure?: ProviderDoctorResult } {\n\tconst level = options.level ?? 0;\n\tconst agentDir = options.agentDir ?? getConfiguredAgentDir();\n\tconst modelsConfig = loadConfig(join(agentDir, \"models.json\"), parseModelsConfig, true);\n\tif (modelsConfig.kind === \"invalid\") {\n\t\treturn {\n\t\t\tfailure: unresolvedFailure(providerId, level, \"models-config-invalid\", \"models.json is invalid\"),\n\t\t};\n\t}\n\tconst authConfig = loadConfig(join(agentDir, \"auth.json\"), parseAuthConfig);\n\tif (authConfig.kind === \"invalid\") {\n\t\treturn { failure: unresolvedFailure(providerId, level, \"auth-config-invalid\", \"auth.json is invalid\") };\n\t}\n\n\tconst kimi = providerId === KIMI_PROVIDER_ID ? resolveKimiConfig(options.kimiConfigPath) : {};\n\tif (kimi.failure) {\n\t\treturn {\n\t\t\tfailure: unresolvedFailure(\n\t\t\t\tproviderId,\n\t\t\t\tlevel,\n\t\t\t\t\"kimi-config-invalid\",\n\t\t\t\t`Kimi config TOML is invalid (line ${kimi.failure.line}: ${kimi.failure.reason}); fix the Kimi config or set KIMI_BASE_URL/KIMI_MODEL_NAME`,\n\t\t\t),\n\t\t};\n\t}\n\n\tconst configured = modelsConfig.kind === \"ok\" ? modelsConfig.value.providers[providerId] : undefined;\n\tconst nativeProviders = getProviders();\n\tconst isNative = nativeProviders.includes(providerId as KnownProvider);\n\tconst nativeModels = isNative ? (getModels(providerId as KnownProvider) as Model<Api>[]) : [];\n\tconst configuredModels = configured?.models ?? [];\n\t// At Level 2 the probe model is the paid target and therefore drives endpoint resolution.\n\tconst requestedModel = level === 2 ? (options.probeModelId ?? options.modelId) : options.modelId;\n\tconst configuredModel = requestedModel\n\t\t? configuredModels.find((model) => model.id === requestedModel)\n\t\t: configuredModels[0];\n\n\t// §10.2: with no higher-precedence endpoint (models.json > KIMI_BASE_URL > root TOML), a\n\t// `[providers.<name>]` entry with `type = \"openai_legacy\"` selects a custom OpenAI-compatible\n\t// endpoint, so native-only checks and native credential/model inheritance are skipped downstream.\n\tconst kimiCustomSelected =\n\t\t!(configuredModel?.baseUrl ?? configured?.baseUrl) && !kimi.baseUrl && kimi.customProvider !== undefined;\n\tconst kimiModelName = kimi.modelName ?? (kimiCustomSelected ? kimi.customProvider?.modelName : undefined);\n\tconst endpointModelId = requestedModel ?? kimiModelName;\n\tconst modelIds = kimiCustomSelected\n\t\t? kimiModelName\n\t\t\t? [kimiModelName]\n\t\t\t: []\n\t\t: Array.from(\n\t\t\t\tnew Set([\n\t\t\t\t\t...nativeModels.map((model) => model.id),\n\t\t\t\t\t...configuredModels.map((model) => model.id),\n\t\t\t\t\t...(kimiModelName ? [kimiModelName] : []),\n\t\t\t\t]),\n\t\t\t);\n\tlet nativeModel = kimiCustomSelected\n\t\t? undefined\n\t\t: requestedModel\n\t\t\t? nativeModels.find((model) => model.id === requestedModel)\n\t\t\t: nativeModels[0];\n\tif (!nativeModel && !kimiCustomSelected && requestedModel !== undefined && requestedModel === kimiModelName) {\n\t\t// A native Kimi TOML/env model rides on the provider defaults for endpoint metadata.\n\t\tnativeModel = nativeModels[0];\n\t}\n\n\tlet baseUrl = configuredModel?.baseUrl ?? configured?.baseUrl;\n\tlet api = configuredModel?.api ?? configured?.api ?? nativeModel?.api;\n\tlet source = configured ? \"models.json\" : isNative ? \"built-in-model-registry\" : \"unresolved\";\n\tif (!baseUrl && kimi.baseUrl) {\n\t\tbaseUrl = kimi.baseUrl;\n\t\tsource = kimi.baseUrlSource ?? source;\n\t} else if (kimiCustomSelected && kimi.customProvider) {\n\t\tbaseUrl = kimi.customProvider.baseUrl;\n\t\tapi = \"openai-completions\";\n\t\tsource = `kimi-config-toml:providers.${kimi.customProvider.name}`;\n\t} else {\n\t\tbaseUrl = baseUrl ?? nativeModel?.baseUrl;\n\t}\n\n\tconst storedAuth = authConfig.kind === \"ok\" && authConfig.value[providerId] !== undefined;\n\tconst environmentAuth = findEnvKeys(providerId) !== undefined;\n\tconst configuredAuth = configured?.apiKey ? isConfigValueConfigured(configured.apiKey) : false;\n\tconst headerAuth = configured?.headers !== undefined && Object.keys(configured.headers).length > 0;\n\tconst customApiKey = kimiCustomSelected ? kimi.customProvider?.apiKey : undefined;\n\tconst customAuthPresent = customApiKey !== undefined && isConfigValueConfigured(customApiKey);\n\tconst authPresent = kimiCustomSelected\n\t\t? customAuthPresent\n\t\t: storedAuth || environmentAuth || configuredAuth || headerAuth;\n\tconst authSource = kimiCustomSelected\n\t\t? customAuthPresent\n\t\t\t? source\n\t\t\t: undefined\n\t\t: storedAuth\n\t\t\t? \"auth.json\"\n\t\t\t: environmentAuth\n\t\t\t\t? \"environment\"\n\t\t\t\t: configuredAuth || headerAuth\n\t\t\t\t\t? \"models.json\"\n\t\t\t\t\t: undefined;\n\n\tif (!configured && !isNative && !storedAuth && !environmentAuth) {\n\t\treturn { failure: unresolvedFailure(providerId, level, \"provider-not-found\", \"Provider was not found\") };\n\t}\n\n\tconst origin = classifyOrigin(baseUrl, api, isNative && !kimiCustomSelected);\n\tconst canonicalBaseUrl = canonicalProviderEndpointUrl(baseUrl);\n\tconst binding =\n\t\tcanonicalBaseUrl && api && endpointModelId\n\t\t\t? { origin, source, baseUrl: canonicalBaseUrl, api, modelId: endpointModelId }\n\t\t\t: undefined;\n\tconst createHeaders: ProviderDoctorHeaderFactory | undefined =\n\t\tkimiCustomSelected && binding\n\t\t\t? () => {\n\t\t\t\t\tconst headers = new Headers();\n\t\t\t\t\tif (customApiKey) {\n\t\t\t\t\t\theaders.set(\n\t\t\t\t\t\t\t\"Authorization\",\n\t\t\t\t\t\t\t`Bearer ${resolveConfigValueOrThrow(customApiKey, \"API key for custom Kimi endpoint\")}`,\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\t\t\t\t\treturn headers;\n\t\t\t\t}\n\t\t\t: undefined;\n\n\treturn {\n\t\ttarget: {\n\t\t\tproviderId,\n\t\t\torigin,\n\t\t\tsource,\n\t\t\tendpoint: { baseUrl, api, modelIds, modelId: endpointModelId },\n\t\t\tauth: { present: authPresent, source: authSource, createHeaders, binding },\n\t\t},\n\t};\n}\n\nexport async function diagnoseResolvedProvider(\n\ttarget: ResolvedProviderTarget,\n\toptions: ProviderDoctorOptions = {},\n\tdependencies: ProviderDoctorDependencies = {},\n): Promise<ProviderDoctorResult> {\n\tconst requestedLevel = options.level ?? 0;\n\tif (requestedLevel !== 0 && requestedLevel !== 1 && requestedLevel !== 2) {\n\t\treturn unresolvedFailure(target.providerId, 0, \"unsupported-level\", \"Provider doctor level is unsupported\");\n\t}\n\tconst level: ProviderDoctorLevel = requestedLevel;\n\t// Level 2 is opt-in only: probeModelId is ignored at levels 0/1, which stay GET-only.\n\tconst probeModelId = level === 2 ? options.probeModelId : undefined;\n\tconst effectiveModelId = probeModelId ?? options.modelId;\n\tconst resolvedTarget = effectiveModelId\n\t\t? { ...target, endpoint: { ...target.endpoint, modelId: effectiveModelId } }\n\t\t: target;\n\tif (level === 2 && options.modelId && probeModelId && options.modelId !== probeModelId) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"model\",\n\t\t\tcode: \"probe-model-conflict\",\n\t\t\tmessage: \"Validation model and paid probe model must match\",\n\t\t};\n\t\treturn publicResult(\n\t\t\tresolvedTarget,\n\t\t\tlevel,\n\t\t\t[{ name: \"model-probe\", status: \"fail\", ...failure }],\n\t\t\tundefined,\n\t\t\tfailure,\n\t\t);\n\t}\n\tif (level === 2 && !probeModelId) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"probe-model-required\",\n\t\t\tmessage: \"Level 2 requires an explicit probe model (--probe-model)\",\n\t\t};\n\t\treturn publicResult(\n\t\t\tresolvedTarget,\n\t\t\tlevel,\n\t\t\t[{ name: \"model-probe\", status: \"fail\", ...failure }],\n\t\t\tundefined,\n\t\t\tfailure,\n\t\t);\n\t}\n\tconst validation = staticChecks(resolvedTarget);\n\tif (validation.failure || level === 0) {\n\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, validation.failure);\n\t}\n\n\tconst transport = dependencies.transport ?? options.transport;\n\tif (!transport) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"transport-required\",\n\t\t\tmessage: \"Level 1 requires an injected provider transport\",\n\t\t};\n\t\tvalidation.checks.push({ name: \"transport\", status: \"fail\", ...failure });\n\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, failure);\n\t}\n\tif (resolvedTarget.origin !== \"local-proxy\" && transport.pinsResolvedAddress !== true) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"address-pinning-required\",\n\t\t\tmessage: \"Public provider transport must pin resolved addresses\",\n\t\t};\n\t\tvalidation.checks.push({ name: \"transport\", status: \"fail\", ...failure });\n\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, failure);\n\t}\n\n\tconst timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n\tif (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n\t\tconst failure: ProbeFailure = {\n\t\t\tcategory: \"config\",\n\t\t\tcode: \"unexpected-response\",\n\t\t\tmessage: \"Provider probe timeout is invalid\",\n\t\t};\n\t\tvalidation.checks.push({ name: \"transport\", status: \"fail\", ...failure });\n\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, failure);\n\t}\n\n\tconst addressPolicy: ProviderDoctorAddressPolicy =\n\t\tresolvedTarget.origin === \"local-proxy\"\n\t\t\t? { kind: \"loopback-only\", requireAddressPinning: false }\n\t\t\t: { kind: \"public\", requireAddressPinning: true };\n\tconst resolveAuthHeaders = dependencies.resolveAuthHeaders ?? options.resolveAuthHeaders;\n\tconst credentialBinding = resolvedTarget.auth.binding;\n\tconst boundHeaderFactory = resolvedTarget.auth.createHeaders;\n\tconst endpointBoundHeaders: ProviderDoctorHeaderFactory | undefined =\n\t\tcredentialBinding && boundHeaderFactory\n\t\t\t? async () => {\n\t\t\t\t\tif (!credentialBindingMatchesTarget(credentialBinding, resolvedTarget)) {\n\t\t\t\t\t\tthrow new ProviderDoctorAuthMaterializationError();\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn await boundHeaderFactory();\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthrow new ProviderDoctorAuthMaterializationError();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t: undefined;\n\tconst createHeaders: ProviderDoctorHeaderFactory = endpointBoundHeaders\n\t\t? endpointBoundHeaders\n\t\t: level === 2 && resolveAuthHeaders\n\t\t\t? async () => {\n\t\t\t\t\tif (credentialBinding && !credentialBindingMatchesTarget(credentialBinding, resolvedTarget)) {\n\t\t\t\t\t\tthrow new ProviderDoctorAuthMaterializationError();\n\t\t\t\t\t}\n\t\t\t\t\ttry {\n\t\t\t\t\t\treturn await resolveAuthHeaders(resolvedTarget);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\tthrow new ProviderDoctorAuthMaterializationError();\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t: (resolvedTarget.auth.createHeaders ?? (() => new Headers()));\n\tconst controller = createComposedController(options.signal, timeoutMs);\n\ttry {\n\t\tconst root = await runProbe(\n\t\t\t\"root-endpoint\",\n\t\t\t\"root\",\n\t\t\tmakeRootProbeUrl(validation.url!, resolvedTarget.origin),\n\t\t\ttransport,\n\t\t\taddressPolicy,\n\t\t\tcreateHeaders,\n\t\t\tcontroller,\n\t\t);\n\t\tvalidation.checks.push(root.check);\n\t\tif (root.failure) {\n\t\t\tvalidation.checks.push({\n\t\t\t\tname: \"models-endpoint\",\n\t\t\t\tstatus: \"skipped\",\n\t\t\t\tcode: \"ok\",\n\t\t\t\tmessage: \"Capability probe skipped after root failure\",\n\t\t\t});\n\t\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, root.failure);\n\t\t}\n\n\t\tconst models = await runProbe(\n\t\t\t\"models-endpoint\",\n\t\t\t\"models\",\n\t\t\tappendPath(validation.url!, \"models\"),\n\t\t\ttransport,\n\t\t\taddressPolicy,\n\t\t\tcreateHeaders,\n\t\t\tcontroller,\n\t\t);\n\t\tvalidation.checks.push(models.check);\n\t\tif (level !== 2 || models.failure) {\n\t\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, models.failure);\n\t\t}\n\n\t\tconst spec = modelProbeSpec(resolvedTarget.endpoint.api ?? \"\", probeModelId as string);\n\t\tif (!spec) {\n\t\t\tconst failure: ProbeFailure = {\n\t\t\t\tcategory: \"config\",\n\t\t\t\tcode: \"api-unsupported\",\n\t\t\t\tmessage: \"Model probe supports only OpenAI-compatible APIs\",\n\t\t\t};\n\t\t\tvalidation.checks.push({ name: \"model-probe\", status: \"fail\", ...failure });\n\t\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, failure);\n\t\t}\n\t\tconst probe = await runProbe(\n\t\t\t\"model-probe\",\n\t\t\t\"model-probe\",\n\t\t\tappendPath(validation.url!, spec.path),\n\t\t\ttransport,\n\t\t\taddressPolicy,\n\t\t\tcreateHeaders,\n\t\t\tcontroller,\n\t\t\tspec.payload,\n\t\t);\n\t\tconst dispatched = probe.failure?.code !== \"auth-materialization-failed\";\n\t\tif (dispatched) {\n\t\t\tprobe.check.message = `${probe.check.message}; minimal-token generative probe (may incur provider costs)`;\n\t\t}\n\t\tvalidation.checks.push(probe.check);\n\t\treturn publicResult(resolvedTarget, level, validation.checks, validation.url, probe.failure, dispatched);\n\t} finally {\n\t\tcontroller.dispose();\n\t}\n}\n\nexport async function diagnoseProvider(\n\tproviderId: string,\n\toptions: ProviderDoctorOptions = {},\n): Promise<ProviderDoctorResult> {\n\tconst requestedLevel = options.level ?? 0;\n\tif (requestedLevel !== 0 && requestedLevel !== 1 && requestedLevel !== 2) {\n\t\treturn unresolvedFailure(providerId, 0, \"unsupported-level\", \"Provider doctor level is unsupported\");\n\t}\n\tconst resolved = resolveProviderTarget(providerId, options);\n\tif (resolved.failure) return resolved.failure;\n\treturn diagnoseResolvedProvider(resolved.target!, options);\n}\n"]}
@@ -674,16 +674,20 @@ function credentialBindingMatchesTarget(binding, target) {
674
674
  binding.modelId === target.endpoint.modelId);
675
675
  }
676
676
  function appendPath(url, segment) {
677
- const next = new URL(url.href);
677
+ const next = URL.parse(url.href);
678
+ if (!next)
679
+ throw new Error("validated provider URL could not be cloned");
678
680
  next.pathname = `${next.pathname.replace(/\/$/, "")}/${segment}`;
679
681
  return next;
680
682
  }
681
683
  function makeRootProbeUrl(url, origin) {
684
+ const root = URL.parse(url.href);
685
+ if (!root)
686
+ throw new Error("validated provider URL could not be cloned");
682
687
  if (origin !== "local-proxy")
683
- return new URL(url.href);
684
- const health = new URL(url.href);
685
- health.pathname = "/health";
686
- return health;
688
+ return root;
689
+ root.pathname = "/health";
690
+ return root;
687
691
  }
688
692
  function publicResult(target, level, checks, url, failure, costWarning) {
689
693
  const targetUrl = url?.href;
@@ -1046,9 +1050,9 @@ function modelProbeSpec(api, modelId) {
1046
1050
  }
1047
1051
  return undefined;
1048
1052
  }
1049
- function classifyOrigin(providerId, baseUrl, api, isNative) {
1053
+ function classifyOrigin(baseUrl, api, isNative) {
1050
1054
  const url = baseUrl ? sanitizeUrl(baseUrl) : undefined;
1051
- if (providerId === "grok-oauth-proxy" || (url && isLiteralLoopback(normalizedHostname(url)))) {
1055
+ if (url && isLiteralLoopback(normalizedHostname(url))) {
1052
1056
  return "local-proxy";
1053
1057
  }
1054
1058
  if (isNative)
@@ -1125,13 +1129,6 @@ function resolveProviderTarget(providerId, options) {
1125
1129
  else {
1126
1130
  baseUrl = baseUrl ?? nativeModel?.baseUrl;
1127
1131
  }
1128
- let builtInAuth = false;
1129
- if (providerId === "grok-oauth-proxy" && !baseUrl) {
1130
- baseUrl = "http://127.0.0.1:9996/v1";
1131
- api = "openai-completions";
1132
- source = "built-in-grok-oauth-proxy-defaults";
1133
- builtInAuth = true;
1134
- }
1135
1132
  const storedAuth = authConfig.kind === "ok" && authConfig.value[providerId] !== undefined;
1136
1133
  const environmentAuth = findEnvKeys(providerId) !== undefined;
1137
1134
  const configuredAuth = configured?.apiKey ? isConfigValueConfigured(configured.apiKey) : false;
@@ -1140,7 +1137,7 @@ function resolveProviderTarget(providerId, options) {
1140
1137
  const customAuthPresent = customApiKey !== undefined && isConfigValueConfigured(customApiKey);
1141
1138
  const authPresent = kimiCustomSelected
1142
1139
  ? customAuthPresent
1143
- : storedAuth || environmentAuth || configuredAuth || headerAuth || builtInAuth;
1140
+ : storedAuth || environmentAuth || configuredAuth || headerAuth;
1144
1141
  const authSource = kimiCustomSelected
1145
1142
  ? customAuthPresent
1146
1143
  ? source
@@ -1151,13 +1148,11 @@ function resolveProviderTarget(providerId, options) {
1151
1148
  ? "environment"
1152
1149
  : configuredAuth || headerAuth
1153
1150
  ? "models.json"
1154
- : builtInAuth
1155
- ? "built-in"
1156
- : undefined;
1157
- if (!configured && !isNative && !storedAuth && !environmentAuth && providerId !== "grok-oauth-proxy") {
1151
+ : undefined;
1152
+ if (!configured && !isNative && !storedAuth && !environmentAuth) {
1158
1153
  return { failure: unresolvedFailure(providerId, level, "provider-not-found", "Provider was not found") };
1159
1154
  }
1160
- const origin = classifyOrigin(providerId, baseUrl, api, isNative && !kimiCustomSelected);
1155
+ const origin = classifyOrigin(baseUrl, api, isNative && !kimiCustomSelected);
1161
1156
  const canonicalBaseUrl = canonicalProviderEndpointUrl(baseUrl);
1162
1157
  const binding = canonicalBaseUrl && api && endpointModelId
1163
1158
  ? { origin, source, baseUrl: canonicalBaseUrl, api, modelId: endpointModelId }