@openadapter/koda 1.0.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (357) hide show
  1. package/CHANGELOG.md +4448 -0
  2. package/README.md +665 -0
  3. package/dist/bun/cli.d.ts +2 -0
  4. package/dist/bun/cli.js +2 -0
  5. package/dist/bun/register-bedrock.d.ts +1 -0
  6. package/dist/bun/register-bedrock.js +1 -0
  7. package/dist/bun/restore-sandbox-env.d.ts +12 -0
  8. package/dist/bun/restore-sandbox-env.js +1 -0
  9. package/dist/cli/args.d.ts +55 -0
  10. package/dist/cli/args.js +167 -0
  11. package/dist/cli/config-selector.d.ts +13 -0
  12. package/dist/cli/config-selector.js +1 -0
  13. package/dist/cli/file-processor.d.ts +14 -0
  14. package/dist/cli/file-processor.js +7 -0
  15. package/dist/cli/import-sessions.d.ts +34 -0
  16. package/dist/cli/import-sessions.js +6 -0
  17. package/dist/cli/initial-message.d.ts +17 -0
  18. package/dist/cli/initial-message.js +1 -0
  19. package/dist/cli/list-models.d.ts +8 -0
  20. package/dist/cli/list-models.js +2 -0
  21. package/dist/cli/openadapter-setup.d.ts +29 -0
  22. package/dist/cli/openadapter-setup.js +3 -0
  23. package/dist/cli/session-picker.d.ts +8 -0
  24. package/dist/cli/session-picker.js +1 -0
  25. package/dist/cli.d.ts +2 -0
  26. package/dist/cli.js +2 -0
  27. package/dist/config.d.ts +92 -0
  28. package/dist/config.js +1 -0
  29. package/dist/core/agent-session-runtime.d.ts +116 -0
  30. package/dist/core/agent-session-runtime.js +1 -0
  31. package/dist/core/agent-session-services.d.ts +86 -0
  32. package/dist/core/agent-session-services.js +1 -0
  33. package/dist/core/agent-session.d.ts +747 -0
  34. package/dist/core/agent-session.js +32 -0
  35. package/dist/core/auth-guidance.d.ts +4 -0
  36. package/dist/core/auth-guidance.js +8 -0
  37. package/dist/core/auth-storage.d.ts +140 -0
  38. package/dist/core/auth-storage.js +1 -0
  39. package/dist/core/bash-executor.d.ts +31 -0
  40. package/dist/core/bash-executor.js +1 -0
  41. package/dist/core/compaction/branch-summarization.d.ts +89 -0
  42. package/dist/core/compaction/branch-summarization.js +38 -0
  43. package/dist/core/compaction/compaction.d.ts +120 -0
  44. package/dist/core/compaction/compaction.js +104 -0
  45. package/dist/core/compaction/index.d.ts +6 -0
  46. package/dist/core/compaction/index.js +1 -0
  47. package/dist/core/compaction/utils.d.ts +37 -0
  48. package/dist/core/compaction/utils.js +19 -0
  49. package/dist/core/defaults.d.ts +2 -0
  50. package/dist/core/defaults.js +1 -0
  51. package/dist/core/diagnostics.d.ts +14 -0
  52. package/dist/core/diagnostics.js +0 -0
  53. package/dist/core/event-bus.d.ts +8 -0
  54. package/dist/core/event-bus.js +1 -0
  55. package/dist/core/exec.d.ts +28 -0
  56. package/dist/core/exec.js +1 -0
  57. package/dist/core/export-html/ansi-to-html.d.ts +21 -0
  58. package/dist/core/export-html/ansi-to-html.js +1 -0
  59. package/dist/core/export-html/index.d.ts +36 -0
  60. package/dist/core/export-html/index.js +2 -0
  61. package/dist/core/export-html/template.css +1066 -0
  62. package/dist/core/export-html/template.html +55 -0
  63. package/dist/core/export-html/template.js +72 -0
  64. package/dist/core/export-html/tool-renderer.d.ts +33 -0
  65. package/dist/core/export-html/tool-renderer.js +1 -0
  66. package/dist/core/export-html/vendor/highlight.min.js +8 -0
  67. package/dist/core/export-html/vendor/marked.min.js +56 -0
  68. package/dist/core/extensions/index.d.ts +11 -0
  69. package/dist/core/extensions/index.js +1 -0
  70. package/dist/core/extensions/loader.d.ts +23 -0
  71. package/dist/core/extensions/loader.js +1 -0
  72. package/dist/core/extensions/runner.d.ts +160 -0
  73. package/dist/core/extensions/runner.js +1 -0
  74. package/dist/core/extensions/types.d.ts +1180 -0
  75. package/dist/core/extensions/types.js +1 -0
  76. package/dist/core/extensions/wrapper.d.ts +19 -0
  77. package/dist/core/extensions/wrapper.js +1 -0
  78. package/dist/core/footer-data-provider.d.ts +53 -0
  79. package/dist/core/footer-data-provider.js +1 -0
  80. package/dist/core/http-dispatcher.d.ts +20 -0
  81. package/dist/core/http-dispatcher.js +1 -0
  82. package/dist/core/index.d.ts +11 -0
  83. package/dist/core/index.js +1 -0
  84. package/dist/core/keybindings.d.ts +352 -0
  85. package/dist/core/keybindings.js +1 -0
  86. package/dist/core/messages.d.ts +76 -0
  87. package/dist/core/messages.js +17 -0
  88. package/dist/core/model-registry.d.ts +149 -0
  89. package/dist/core/model-registry.js +9 -0
  90. package/dist/core/model-resolver.d.ts +109 -0
  91. package/dist/core/model-resolver.js +1 -0
  92. package/dist/core/output-guard.d.ts +6 -0
  93. package/dist/core/output-guard.js +1 -0
  94. package/dist/core/package-manager.d.ts +203 -0
  95. package/dist/core/package-manager.js +3 -0
  96. package/dist/core/prompt-templates.d.ts +51 -0
  97. package/dist/core/prompt-templates.js +2 -0
  98. package/dist/core/provider-attribution.d.ts +3 -0
  99. package/dist/core/provider-attribution.js +1 -0
  100. package/dist/core/provider-display-names.d.ts +1 -0
  101. package/dist/core/provider-display-names.js +1 -0
  102. package/dist/core/resolve-config-value.d.ts +30 -0
  103. package/dist/core/resolve-config-value.js +1 -0
  104. package/dist/core/resource-loader.d.ts +193 -0
  105. package/dist/core/resource-loader.js +1 -0
  106. package/dist/core/sdk.d.ts +108 -0
  107. package/dist/core/sdk.js +1 -0
  108. package/dist/core/session-cwd.d.ts +18 -0
  109. package/dist/core/session-cwd.js +7 -0
  110. package/dist/core/session-manager.d.ts +331 -0
  111. package/dist/core/session-manager.js +11 -0
  112. package/dist/core/settings-manager.d.ts +265 -0
  113. package/dist/core/settings-manager.js +1 -0
  114. package/dist/core/skills.d.ts +59 -0
  115. package/dist/core/skills.js +4 -0
  116. package/dist/core/slash-commands.d.ts +13 -0
  117. package/dist/core/slash-commands.js +1 -0
  118. package/dist/core/source-info.d.ts +17 -0
  119. package/dist/core/source-info.js +1 -0
  120. package/dist/core/system-prompt.d.ts +27 -0
  121. package/dist/core/system-prompt.js +52 -0
  122. package/dist/core/telemetry.d.ts +2 -0
  123. package/dist/core/telemetry.js +1 -0
  124. package/dist/core/timings.d.ts +7 -0
  125. package/dist/core/timings.js +3 -0
  126. package/dist/core/tools/bash.d.ts +67 -0
  127. package/dist/core/tools/bash.js +18 -0
  128. package/dist/core/tools/edit-diff.d.ts +86 -0
  129. package/dist/core/tools/edit-diff.js +16 -0
  130. package/dist/core/tools/edit.d.ts +50 -0
  131. package/dist/core/tools/edit.js +2 -0
  132. package/dist/core/tools/file-mutation-queue.d.ts +5 -0
  133. package/dist/core/tools/file-mutation-queue.js +1 -0
  134. package/dist/core/tools/find.d.ts +34 -0
  135. package/dist/core/tools/find.js +13 -0
  136. package/dist/core/tools/grep.d.ts +36 -0
  137. package/dist/core/tools/grep.js +13 -0
  138. package/dist/core/tools/index.d.ts +39 -0
  139. package/dist/core/tools/index.js +1 -0
  140. package/dist/core/tools/ls.d.ts +36 -0
  141. package/dist/core/tools/ls.js +9 -0
  142. package/dist/core/tools/output-accumulator.d.ts +51 -0
  143. package/dist/core/tools/output-accumulator.js +4 -0
  144. package/dist/core/tools/path-utils.d.ts +9 -0
  145. package/dist/core/tools/path-utils.js +1 -0
  146. package/dist/core/tools/read.d.ts +34 -0
  147. package/dist/core/tools/read.js +22 -0
  148. package/dist/core/tools/render-utils.d.ts +23 -0
  149. package/dist/core/tools/render-utils.js +4 -0
  150. package/dist/core/tools/tool-definition-wrapper.d.ts +13 -0
  151. package/dist/core/tools/tool-definition-wrapper.js +1 -0
  152. package/dist/core/tools/truncate.d.ts +69 -0
  153. package/dist/core/tools/truncate.js +5 -0
  154. package/dist/core/tools/write.d.ts +25 -0
  155. package/dist/core/tools/write.js +13 -0
  156. package/dist/index.d.ts +30 -0
  157. package/dist/index.js +1 -0
  158. package/dist/main.d.ts +11 -0
  159. package/dist/main.js +1 -0
  160. package/dist/migrations.d.ts +32 -0
  161. package/dist/migrations.js +8 -0
  162. package/dist/modes/index.d.ts +8 -0
  163. package/dist/modes/index.js +1 -0
  164. package/dist/modes/interactive/assets/clankolas.png +0 -0
  165. package/dist/modes/interactive/components/armin.d.ts +33 -0
  166. package/dist/modes/interactive/components/armin.js +1 -0
  167. package/dist/modes/interactive/components/assistant-message.d.ts +19 -0
  168. package/dist/modes/interactive/components/assistant-message.js +1 -0
  169. package/dist/modes/interactive/components/bash-execution.d.ts +33 -0
  170. package/dist/modes/interactive/components/bash-execution.js +13 -0
  171. package/dist/modes/interactive/components/bordered-loader.d.ts +15 -0
  172. package/dist/modes/interactive/components/bordered-loader.js +1 -0
  173. package/dist/modes/interactive/components/branch-summary-message.d.ts +15 -0
  174. package/dist/modes/interactive/components/branch-summary-message.js +3 -0
  175. package/dist/modes/interactive/components/compaction-summary-message.d.ts +15 -0
  176. package/dist/modes/interactive/components/compaction-summary-message.js +3 -0
  177. package/dist/modes/interactive/components/config-selector.d.ts +70 -0
  178. package/dist/modes/interactive/components/config-selector.js +1 -0
  179. package/dist/modes/interactive/components/countdown-timer.d.ts +13 -0
  180. package/dist/modes/interactive/components/countdown-timer.js +1 -0
  181. package/dist/modes/interactive/components/custom-editor.d.ts +20 -0
  182. package/dist/modes/interactive/components/custom-editor.js +1 -0
  183. package/dist/modes/interactive/components/custom-message.d.ts +19 -0
  184. package/dist/modes/interactive/components/custom-message.js +2 -0
  185. package/dist/modes/interactive/components/daxnuts.d.ts +22 -0
  186. package/dist/modes/interactive/components/daxnuts.js +1 -0
  187. package/dist/modes/interactive/components/diff.d.ts +11 -0
  188. package/dist/modes/interactive/components/diff.js +3 -0
  189. package/dist/modes/interactive/components/dynamic-border.d.ts +14 -0
  190. package/dist/modes/interactive/components/dynamic-border.js +1 -0
  191. package/dist/modes/interactive/components/earendil-announcement.d.ts +4 -0
  192. package/dist/modes/interactive/components/earendil-announcement.js +1 -0
  193. package/dist/modes/interactive/components/extension-editor.d.ts +19 -0
  194. package/dist/modes/interactive/components/extension-editor.js +3 -0
  195. package/dist/modes/interactive/components/extension-input.d.ts +22 -0
  196. package/dist/modes/interactive/components/extension-input.js +2 -0
  197. package/dist/modes/interactive/components/extension-selector.d.ts +25 -0
  198. package/dist/modes/interactive/components/extension-selector.js +2 -0
  199. package/dist/modes/interactive/components/footer.d.ts +27 -0
  200. package/dist/modes/interactive/components/footer.js +1 -0
  201. package/dist/modes/interactive/components/index.d.ts +31 -0
  202. package/dist/modes/interactive/components/index.js +1 -0
  203. package/dist/modes/interactive/components/keybinding-hints.d.ts +12 -0
  204. package/dist/modes/interactive/components/keybinding-hints.js +1 -0
  205. package/dist/modes/interactive/components/login-dialog.d.ts +51 -0
  206. package/dist/modes/interactive/components/login-dialog.js +1 -0
  207. package/dist/modes/interactive/components/model-selector.d.ts +46 -0
  208. package/dist/modes/interactive/components/model-selector.js +2 -0
  209. package/dist/modes/interactive/components/oauth-selector.d.ts +30 -0
  210. package/dist/modes/interactive/components/oauth-selector.js +1 -0
  211. package/dist/modes/interactive/components/scoped-models-selector.d.ts +41 -0
  212. package/dist/modes/interactive/components/scoped-models-selector.js +1 -0
  213. package/dist/modes/interactive/components/session-selector-search.d.ts +22 -0
  214. package/dist/modes/interactive/components/session-selector-search.js +1 -0
  215. package/dist/modes/interactive/components/session-selector.d.ts +95 -0
  216. package/dist/modes/interactive/components/session-selector.js +2 -0
  217. package/dist/modes/interactive/components/settings-selector.d.ts +68 -0
  218. package/dist/modes/interactive/components/settings-selector.js +1 -0
  219. package/dist/modes/interactive/components/show-images-selector.d.ts +9 -0
  220. package/dist/modes/interactive/components/show-images-selector.js +1 -0
  221. package/dist/modes/interactive/components/skill-invocation-message.d.ts +16 -0
  222. package/dist/modes/interactive/components/skill-invocation-message.js +3 -0
  223. package/dist/modes/interactive/components/theme-selector.d.ts +10 -0
  224. package/dist/modes/interactive/components/theme-selector.js +1 -0
  225. package/dist/modes/interactive/components/thinking-selector.d.ts +10 -0
  226. package/dist/modes/interactive/components/thinking-selector.js +1 -0
  227. package/dist/modes/interactive/components/tool-execution.d.ts +62 -0
  228. package/dist/modes/interactive/components/tool-execution.js +4 -0
  229. package/dist/modes/interactive/components/tree-selector.d.ts +88 -0
  230. package/dist/modes/interactive/components/tree-selector.js +1 -0
  231. package/dist/modes/interactive/components/user-message-selector.d.ts +29 -0
  232. package/dist/modes/interactive/components/user-message-selector.js +1 -0
  233. package/dist/modes/interactive/components/user-message.d.ts +9 -0
  234. package/dist/modes/interactive/components/user-message.js +1 -0
  235. package/dist/modes/interactive/components/visual-truncate.d.ts +23 -0
  236. package/dist/modes/interactive/components/visual-truncate.js +1 -0
  237. package/dist/modes/interactive/interactive-mode.d.ts +417 -0
  238. package/dist/modes/interactive/interactive-mode.js +116 -0
  239. package/dist/modes/interactive/theme/dark.json +86 -0
  240. package/dist/modes/interactive/theme/light.json +85 -0
  241. package/dist/modes/interactive/theme/theme-schema.json +335 -0
  242. package/dist/modes/interactive/theme/theme.d.ts +101 -0
  243. package/dist/modes/interactive/theme/theme.js +18 -0
  244. package/dist/modes/print-mode.d.ts +27 -0
  245. package/dist/modes/print-mode.js +4 -0
  246. package/dist/modes/rpc/jsonl.d.ts +16 -0
  247. package/dist/modes/rpc/jsonl.js +3 -0
  248. package/dist/modes/rpc/rpc-client.d.ts +226 -0
  249. package/dist/modes/rpc/rpc-client.js +1 -0
  250. package/dist/modes/rpc/rpc-mode.d.ts +19 -0
  251. package/dist/modes/rpc/rpc-mode.js +1 -0
  252. package/dist/modes/rpc/rpc-types.d.ts +419 -0
  253. package/dist/modes/rpc/rpc-types.js +0 -0
  254. package/dist/package-manager-cli.d.ts +3 -0
  255. package/dist/package-manager-cli.js +49 -0
  256. package/dist/utils/ansi.d.ts +1 -0
  257. package/dist/utils/ansi.js +1 -0
  258. package/dist/utils/auto-update.d.ts +13 -0
  259. package/dist/utils/auto-update.js +1 -0
  260. package/dist/utils/changelog.d.ts +20 -0
  261. package/dist/utils/changelog.js +4 -0
  262. package/dist/utils/child-process.d.ts +14 -0
  263. package/dist/utils/child-process.js +1 -0
  264. package/dist/utils/clipboard-image.d.ts +10 -0
  265. package/dist/utils/clipboard-image.js +1 -0
  266. package/dist/utils/clipboard-native.d.ts +9 -0
  267. package/dist/utils/clipboard-native.js +1 -0
  268. package/dist/utils/clipboard.d.ts +1 -0
  269. package/dist/utils/clipboard.js +1 -0
  270. package/dist/utils/deprecation.d.ts +3 -0
  271. package/dist/utils/deprecation.js +1 -0
  272. package/dist/utils/exif-orientation.d.ts +4 -0
  273. package/dist/utils/exif-orientation.js +1 -0
  274. package/dist/utils/frontmatter.d.ts +7 -0
  275. package/dist/utils/frontmatter.js +4 -0
  276. package/dist/utils/fs-watch.d.ts +4 -0
  277. package/dist/utils/fs-watch.js +1 -0
  278. package/dist/utils/git.d.ts +25 -0
  279. package/dist/utils/git.js +1 -0
  280. package/dist/utils/html.d.ts +6 -0
  281. package/dist/utils/html.js +1 -0
  282. package/dist/utils/image-convert.d.ts +8 -0
  283. package/dist/utils/image-convert.js +1 -0
  284. package/dist/utils/image-resize-core.d.ts +29 -0
  285. package/dist/utils/image-resize-core.js +1 -0
  286. package/dist/utils/image-resize-worker.d.ts +1 -0
  287. package/dist/utils/image-resize-worker.js +1 -0
  288. package/dist/utils/image-resize.d.ts +15 -0
  289. package/dist/utils/image-resize.js +1 -0
  290. package/dist/utils/json.d.ts +2 -0
  291. package/dist/utils/json.js +1 -0
  292. package/dist/utils/koda-user-agent.d.ts +1 -0
  293. package/dist/utils/koda-user-agent.js +1 -0
  294. package/dist/utils/mime.d.ts +2 -0
  295. package/dist/utils/mime.js +1 -0
  296. package/dist/utils/paths.d.ts +30 -0
  297. package/dist/utils/paths.js +1 -0
  298. package/dist/utils/photon.d.ts +20 -0
  299. package/dist/utils/photon.js +1 -0
  300. package/dist/utils/shell.d.ts +29 -0
  301. package/dist/utils/shell.js +8 -0
  302. package/dist/utils/sleep.d.ts +4 -0
  303. package/dist/utils/sleep.js +1 -0
  304. package/dist/utils/syntax-highlight.d.ts +11 -0
  305. package/dist/utils/syntax-highlight.js +2 -0
  306. package/dist/utils/tools-manager.d.ts +2 -0
  307. package/dist/utils/tools-manager.js +1 -0
  308. package/dist/utils/version-check.d.ts +14 -0
  309. package/dist/utils/version-check.js +1 -0
  310. package/dist/utils/windows-self-update.d.ts +2 -0
  311. package/dist/utils/windows-self-update.js +1 -0
  312. package/docs/compaction.md +394 -0
  313. package/docs/custom-provider.md +736 -0
  314. package/docs/development.md +71 -0
  315. package/docs/docs.json +148 -0
  316. package/docs/extensions.md +2626 -0
  317. package/docs/images/doom-extension.png +0 -0
  318. package/docs/images/exy.png +0 -0
  319. package/docs/images/interactive-mode.png +0 -0
  320. package/docs/images/tree-view.png +0 -0
  321. package/docs/index.md +80 -0
  322. package/docs/json.md +82 -0
  323. package/docs/keybindings.md +197 -0
  324. package/docs/models.md +493 -0
  325. package/docs/packages.md +226 -0
  326. package/docs/prompt-templates.md +88 -0
  327. package/docs/providers.md +253 -0
  328. package/docs/quickstart.md +165 -0
  329. package/docs/rpc.md +1408 -0
  330. package/docs/sdk.md +1137 -0
  331. package/docs/session-format.md +412 -0
  332. package/docs/sessions.md +145 -0
  333. package/docs/settings.md +281 -0
  334. package/docs/shell-aliases.md +13 -0
  335. package/docs/skills.md +231 -0
  336. package/docs/terminal-setup.md +114 -0
  337. package/docs/termux.md +127 -0
  338. package/docs/themes.md +295 -0
  339. package/docs/tmux.md +61 -0
  340. package/docs/tui.md +927 -0
  341. package/docs/usage.md +288 -0
  342. package/docs/windows.md +17 -0
  343. package/npm-shrinkwrap.json +1792 -0
  344. package/openadapter/extensions/koda-ask.js +12 -0
  345. package/openadapter/extensions/koda-bg.js +14 -0
  346. package/openadapter/extensions/koda-commands.mjs +15 -0
  347. package/openadapter/extensions/koda-help.js +8 -0
  348. package/openadapter/extensions/koda-memory.js +16 -0
  349. package/openadapter/extensions/koda-status.js +1 -0
  350. package/openadapter/extensions/koda-todo.js +4 -0
  351. package/openadapter/extensions/koda-vision.js +4 -0
  352. package/openadapter/extensions/koda-web.js +7 -0
  353. package/openadapter/setup.mjs +173 -0
  354. package/openadapter/skills/code-review/SKILL.md +22 -0
  355. package/openadapter/skills/debugging/SKILL.md +28 -0
  356. package/openadapter/skills/frontend/SKILL.md +38 -0
  357. package/package.json +108 -0
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Model registry - manages built-in and custom models, provides API key resolution.
3
+ */
4
+ import { type Api, type AssistantMessageEventStream, type Context, type Model, type OAuthProviderInterface, type SimpleStreamOptions } from "@openadapter/koda-ai";
5
+ import type { AuthStatus, AuthStorage } from "./auth-storage.ts";
6
+ import { clearConfigValueCache } from "./resolve-config-value.ts";
7
+ export type ResolvedRequestAuth = {
8
+ ok: true;
9
+ apiKey?: string;
10
+ headers?: Record<string, string>;
11
+ } | {
12
+ ok: false;
13
+ error: string;
14
+ };
15
+ /** Clear the config value command cache. Exported for testing. */
16
+ export declare const clearApiKeyCache: typeof clearConfigValueCache;
17
+ /**
18
+ * Model registry - loads and manages models, resolves API keys via AuthStorage.
19
+ */
20
+ export declare class ModelRegistry {
21
+ private models;
22
+ private providerRequestConfigs;
23
+ private modelRequestHeaders;
24
+ private registeredProviders;
25
+ private loadError;
26
+ readonly authStorage: AuthStorage;
27
+ private modelsJsonPath;
28
+ private constructor();
29
+ static create(authStorage: AuthStorage, modelsJsonPath?: string): ModelRegistry;
30
+ static inMemory(authStorage: AuthStorage): ModelRegistry;
31
+ /**
32
+ * Reload models from disk (built-in + custom from models.json).
33
+ */
34
+ refresh(): void;
35
+ /**
36
+ * Get any error from loading models.json (undefined if no error).
37
+ */
38
+ getError(): string | undefined;
39
+ private loadModels;
40
+ /** Load built-in models and apply provider/model overrides */
41
+ private loadBuiltInModels;
42
+ /** Merge custom models into built-in list by provider+id (custom wins on conflicts). */
43
+ private mergeCustomModels;
44
+ private loadCustomModels;
45
+ private validateConfig;
46
+ private parseModels;
47
+ /**
48
+ * Get all models (built-in + custom).
49
+ * If models.json had errors, returns only built-in models.
50
+ */
51
+ getAll(): Model<Api>[];
52
+ /**
53
+ * Get only models that have auth configured.
54
+ * This is a fast check that doesn't refresh OAuth tokens.
55
+ */
56
+ getAvailable(): Model<Api>[];
57
+ /**
58
+ * Find a model by provider and ID.
59
+ */
60
+ find(provider: string, modelId: string): Model<Api> | undefined;
61
+ /**
62
+ * Get API key for a model.
63
+ */
64
+ hasConfiguredAuth(model: Model<Api>): boolean;
65
+ private getModelRequestKey;
66
+ private storeProviderRequestConfig;
67
+ private storeModelHeaders;
68
+ /**
69
+ * Get API key and request headers for a model.
70
+ */
71
+ getApiKeyAndHeaders(model: Model<Api>): Promise<ResolvedRequestAuth>;
72
+ /**
73
+ * Return auth status for a provider, including request auth configured in models.json.
74
+ * This intentionally does not execute command-backed config values.
75
+ */
76
+ getProviderAuthStatus(provider: string): AuthStatus;
77
+ /**
78
+ * Get display name for a provider.
79
+ */
80
+ getProviderDisplayName(provider: string): string;
81
+ /**
82
+ * Get API key for a provider.
83
+ */
84
+ getApiKeyForProvider(provider: string): Promise<string | undefined>;
85
+ /**
86
+ * Check if a model is using OAuth credentials (subscription).
87
+ */
88
+ isUsingOAuth(model: Model<Api>): boolean;
89
+ /**
90
+ * Register a provider dynamically (from extensions).
91
+ *
92
+ * If provider has models: replaces all existing models for this provider.
93
+ * If provider has only baseUrl/headers: overrides existing models' URLs.
94
+ * If provider has oauth: registers OAuth provider for /login support.
95
+ */
96
+ registerProvider(providerName: string, config: ProviderConfigInput): void;
97
+ /**
98
+ * Unregister a previously registered provider.
99
+ *
100
+ * Removes the provider from the registry and reloads models from disk so that
101
+ * built-in models overridden by this provider are restored to their original state.
102
+ * Also resets dynamic OAuth and API stream registrations before reapplying
103
+ * remaining dynamic providers.
104
+ * Has no effect if the provider was never registered.
105
+ */
106
+ unregisterProvider(providerName: string): void;
107
+ /**
108
+ * Upsert a provider config into registeredProviders.
109
+ * If the provider is already registered, defined values in the incoming config
110
+ * override existing ones; undefined values are preserved from the stored config.
111
+ * If the provider is not registered, the incoming config is stored as-is.
112
+ */
113
+ private upsertRegisteredProvider;
114
+ private validateProviderConfig;
115
+ private applyProviderConfig;
116
+ }
117
+ /**
118
+ * Input type for registerProvider API.
119
+ */
120
+ export interface ProviderConfigInput {
121
+ name?: string;
122
+ baseUrl?: string;
123
+ apiKey?: string;
124
+ api?: Api;
125
+ streamSimple?: (model: Model<Api>, context: Context, options?: SimpleStreamOptions) => AssistantMessageEventStream;
126
+ headers?: Record<string, string>;
127
+ authHeader?: boolean;
128
+ /** OAuth provider for /login support */
129
+ oauth?: Omit<OAuthProviderInterface, "id">;
130
+ models?: Array<{
131
+ id: string;
132
+ name: string;
133
+ api?: Api;
134
+ baseUrl?: string;
135
+ reasoning: boolean;
136
+ thinkingLevelMap?: Model<Api>["thinkingLevelMap"];
137
+ input: ("text" | "image")[];
138
+ cost: {
139
+ input: number;
140
+ output: number;
141
+ cacheRead: number;
142
+ cacheWrite: number;
143
+ };
144
+ contextWindow: number;
145
+ maxTokens: number;
146
+ headers?: Record<string, string>;
147
+ compat?: Model<Api>["compat"];
148
+ }>;
149
+ }
@@ -0,0 +1,9 @@
1
+ var x=Object.defineProperty;var c=(d,t)=>x(d,"name",{value:t,configurable:!0});import{getModels as S,getProviders as g,registerApiProvider as $,resetApiProviders as q}from"@openadapter/koda-ai";import{registerOAuthProvider as j,resetOAuthProviders as K}from"@openadapter/koda-ai/oauth";import{existsSync as B,readFileSync as T}from"fs";import{join as E}from"path";import{Type as e}from"typebox";import{Compile as I}from"typebox/compile";import{getAgentDir as H}from"../config.js";import{warnDeprecation as _}from"../utils/deprecation.js";import{stripJsonComments as V}from"../utils/json.js";import{normalizePath as W}from"../utils/paths.js";import{BUILT_IN_PROVIDER_DISPLAY_NAMES as N}from"./provider-display-names.js";import{clearConfigValueCache as D,getConfigValueEnvVarNames as F,isCommandConfigValue as G,isConfigValueConfigured as w,isLegacyEnvVarNameConfigValue as z,resolveConfigValueOrThrow as J,resolveConfigValueUncached as Y,resolveHeadersOrThrow as C}from"./resolve-config-value.js";const P=e.Object({p50:e.Optional(e.Number()),p75:e.Optional(e.Number()),p90:e.Optional(e.Number()),p99:e.Optional(e.Number())}),Q=e.Object({allow_fallbacks:e.Optional(e.Boolean()),require_parameters:e.Optional(e.Boolean()),data_collection:e.Optional(e.Union([e.Literal("deny"),e.Literal("allow")])),zdr:e.Optional(e.Boolean()),enforce_distillable_text:e.Optional(e.Boolean()),order:e.Optional(e.Array(e.String())),only:e.Optional(e.Array(e.String())),ignore:e.Optional(e.Array(e.String())),quantizations:e.Optional(e.Array(e.String())),sort:e.Optional(e.Union([e.String(),e.Object({by:e.Optional(e.String()),partition:e.Optional(e.Union([e.String(),e.Null()]))})])),max_price:e.Optional(e.Object({prompt:e.Optional(e.Union([e.Number(),e.String()])),completion:e.Optional(e.Union([e.Number(),e.String()])),image:e.Optional(e.Union([e.Number(),e.String()])),audio:e.Optional(e.Union([e.Number(),e.String()])),request:e.Optional(e.Union([e.Number(),e.String()]))})),preferred_min_throughput:e.Optional(e.Union([e.Number(),P])),preferred_max_latency:e.Optional(e.Union([e.Number(),P]))}),X=e.Object({only:e.Optional(e.Array(e.String())),order:e.Optional(e.Array(e.String()))}),h=e.Union([e.String(),e.Null()]),R=e.Object({off:e.Optional(h),minimal:e.Optional(h),low:e.Optional(h),medium:e.Optional(h),high:e.Optional(h),xhigh:e.Optional(h)}),Z=e.Object({supportsStore:e.Optional(e.Boolean()),supportsDeveloperRole:e.Optional(e.Boolean()),supportsReasoningEffort:e.Optional(e.Boolean()),supportsUsageInStreaming:e.Optional(e.Boolean()),maxTokensField:e.Optional(e.Union([e.Literal("max_completion_tokens"),e.Literal("max_tokens")])),requiresToolResultName:e.Optional(e.Boolean()),requiresAssistantAfterToolResult:e.Optional(e.Boolean()),requiresThinkingAsText:e.Optional(e.Boolean()),requiresReasoningContentOnAssistantMessages:e.Optional(e.Boolean()),thinkingFormat:e.Optional(e.Union([e.Literal("openai"),e.Literal("openrouter"),e.Literal("together"),e.Literal("deepseek"),e.Literal("zai"),e.Literal("qwen"),e.Literal("qwen-chat-template")])),cacheControlFormat:e.Optional(e.Literal("anthropic")),openRouterRouting:e.Optional(Q),vercelGatewayRouting:e.Optional(X),supportsStrictMode:e.Optional(e.Boolean()),supportsLongCacheRetention:e.Optional(e.Boolean())}),ee=e.Object({sendSessionIdHeader:e.Optional(e.Boolean()),supportsLongCacheRetention:e.Optional(e.Boolean())}),te=e.Object({supportsEagerToolInputStreaming:e.Optional(e.Boolean()),supportsLongCacheRetention:e.Optional(e.Boolean()),sendSessionAffinityHeaders:e.Optional(e.Boolean()),supportsCacheControlOnTools:e.Optional(e.Boolean()),forceAdaptiveThinking:e.Optional(e.Boolean())}),f=e.Union([Z,ee,te]),oe=e.Object({id:e.String({minLength:1}),name:e.Optional(e.String({minLength:1})),api:e.Optional(e.String({minLength:1})),baseUrl:e.Optional(e.String({minLength:1})),reasoning:e.Optional(e.Boolean()),thinkingLevelMap:e.Optional(R),input:e.Optional(e.Array(e.Union([e.Literal("text"),e.Literal("image")]))),cost:e.Optional(e.Object({input:e.Number(),output:e.Number(),cacheRead:e.Number(),cacheWrite:e.Number()})),contextWindow:e.Optional(e.Number()),maxTokens:e.Optional(e.Number()),headers:e.Optional(e.Record(e.String(),e.String())),compat:e.Optional(f)}),re=e.Object({name:e.Optional(e.String({minLength:1})),reasoning:e.Optional(e.Boolean()),thinkingLevelMap:e.Optional(R),input:e.Optional(e.Array(e.Union([e.Literal("text"),e.Literal("image")]))),cost:e.Optional(e.Object({input:e.Optional(e.Number()),output:e.Optional(e.Number()),cacheRead:e.Optional(e.Number()),cacheWrite:e.Optional(e.Number())})),contextWindow:e.Optional(e.Number()),maxTokens:e.Optional(e.Number()),headers:e.Optional(e.Record(e.String(),e.String())),compat:e.Optional(f)}),ie=e.Object({name:e.Optional(e.String({minLength:1})),baseUrl:e.Optional(e.String({minLength:1})),apiKey:e.Optional(e.String({minLength:1})),api:e.Optional(e.String({minLength:1})),headers:e.Optional(e.Record(e.String(),e.String())),compat:e.Optional(f),authHeader:e.Optional(e.Boolean()),models:e.Optional(e.Array(oe)),modelOverrides:e.Optional(e.Record(e.String(),re))}),ne=e.Object({providers:e.Record(e.String(),ie)}),M=I(ne);function se(d){if(d.keyword==="required"){const r=d.params.requiredProperties?.[0];if(r){const i=d.instancePath.replace(/^\//,"").replace(/\//g,".");return i?`${i}.${r}`:r}}return d.instancePath.replace(/^\//,"").replace(/\//g,".")||"root"}c(se,"formatValidationPath");function A(d,t,o){return z(o)?(_(`registerProvider("${d}") ${t} value "${o}" is treated as a legacy environment variable reference. This will no longer be detected as an environment variable reference in a future release. Pass "$${o}" instead.`),`$${o}`):o}c(A,"migrateLegacyRegisterProviderConfigValue");function k(d,t,o){if(!o)return;let r;for(const[i,s]of Object.entries(o)){const n=A(d,`${t} header "${i}"`,s);n!==s&&(r??={...o},r[i]=n)}return r??o}c(k,"migrateLegacyRegisterProviderHeaders");function ae(d,t){let o;const r=c((s,n)=>{o??={...t},o[s]=n},"setMigratedConfigValue");if(t.apiKey){const s=A(d,"apiKey",t.apiKey);s!==t.apiKey&&r("apiKey",s)}const i=k(d,"headers",t.headers);if(i!==t.headers&&r("headers",i),t.models){let s;for(let n=0;n<t.models.length;n++){const a=t.models[n],l=k(d,`model "${a.id}" headers`,a.headers);l!==a.headers&&(s??=[...t.models],s[n]={...a,headers:l})}s&&r("models",s)}return o??t}c(ae,"migrateLegacyRegisterProviderConfigValues");function m(d){return{models:[],overrides:new Map,modelOverrides:new Map,error:d}}c(m,"emptyCustomModelsResult");function O(d,t){if(!t)return d;const o=d,r=t,i={...o,...r},s=o,n=r,a=i;return(s?.openRouterRouting||n.openRouterRouting)&&(a.openRouterRouting={...s?.openRouterRouting,...n.openRouterRouting}),(s?.vercelGatewayRouting||n.vercelGatewayRouting)&&(a.vercelGatewayRouting={...s?.vercelGatewayRouting,...n.vercelGatewayRouting}),i}c(O,"mergeCompat");function le(d,t){const o={...d};return t.name!==void 0&&(o.name=t.name),t.reasoning!==void 0&&(o.reasoning=t.reasoning),t.thinkingLevelMap!==void 0&&(o.thinkingLevelMap={...d.thinkingLevelMap,...t.thinkingLevelMap}),t.input!==void 0&&(o.input=t.input),t.contextWindow!==void 0&&(o.contextWindow=t.contextWindow),t.maxTokens!==void 0&&(o.maxTokens=t.maxTokens),t.cost&&(o.cost={input:t.cost.input??d.cost.input,output:t.cost.output??d.cost.output,cacheRead:t.cost.cacheRead??d.cost.cacheRead,cacheWrite:t.cost.cacheWrite??d.cost.cacheWrite}),o.compat=O(d.compat,t.compat),o}c(le,"applyModelOverride");const we=D;class v{static{c(this,"ModelRegistry")}models=[];providerRequestConfigs=new Map;modelRequestHeaders=new Map;registeredProviders=new Map;loadError=void 0;authStorage;modelsJsonPath;constructor(t,o){this.authStorage=t,this.modelsJsonPath=o?W(o):void 0,this.loadModels()}static create(t,o=E(H(),"models.json")){return new v(t,o)}static inMemory(t){return new v(t,void 0)}refresh(){this.providerRequestConfigs.clear(),this.modelRequestHeaders.clear(),this.loadError=void 0,q(),K(),this.loadModels();for(const[t,o]of this.registeredProviders.entries())this.applyProviderConfig(t,o)}getError(){return this.loadError}loadModels(){const{models:t,overrides:o,modelOverrides:r,error:i}=this.modelsJsonPath?this.loadCustomModels(this.modelsJsonPath):m();i&&(this.loadError=i);const s=this.loadBuiltInModels(o,r);let n=this.mergeCustomModels(s,t);for(const a of this.authStorage.getOAuthProviders()){const l=this.authStorage.get(a.id);l?.type==="oauth"&&a.modifyModels&&(n=a.modifyModels(n,l))}this.models=n}loadBuiltInModels(t,o){return g().flatMap(r=>{const i=S(r),s=t.get(r),n=o.get(r);return i.map(a=>{let l=a;s&&(l={...l,baseUrl:s.baseUrl??l.baseUrl,compat:O(l.compat,s.compat)});const u=n?.get(a.id);return u&&(l=le(l,u)),l})})}mergeCustomModels(t,o){const r=[...t];for(const i of o){const s=r.findIndex(n=>n.provider===i.provider&&n.id===i.id);s>=0?r[s]=i:r.push(i)}return r}loadCustomModels(t){if(!B(t))return m();try{const o=T(t,"utf-8"),r=JSON.parse(V(o));if(!M.Check(r)){const a=M.Errors(r).map(l=>` - ${se(l)}: ${l.message}`).join(`
2
+ `)||"Unknown schema error";return m(`Invalid models.json schema:
3
+ ${a}
4
+
5
+ File: ${t}`)}const i=r;this.validateConfig(i);const s=new Map,n=new Map;for(const[a,l]of Object.entries(i.providers))if((l.baseUrl||l.compat)&&s.set(a,{baseUrl:l.baseUrl,compat:l.compat}),this.storeProviderRequestConfig(a,l),l.modelOverrides){n.set(a,new Map(Object.entries(l.modelOverrides)));for(const[u,p]of Object.entries(l.modelOverrides))this.storeModelHeaders(a,u,p.headers)}return{models:this.parseModels(i),overrides:s,modelOverrides:n,error:void 0}}catch(o){return o instanceof SyntaxError?m(`Failed to parse models.json: ${o.message}
6
+
7
+ File: ${t}`):m(`Failed to load models.json: ${o instanceof Error?o.message:o}
8
+
9
+ File: ${t}`)}}validateConfig(t){const o=new Set(g());for(const[r,i]of Object.entries(t.providers)){const s=o.has(r),n=!!i.api,a=i.models??[],l=i.modelOverrides&&Object.keys(i.modelOverrides).length>0;if(a.length===0){if(!i.baseUrl&&!i.headers&&!i.compat&&!l)throw new Error(`Provider ${r}: must specify "baseUrl", "headers", "compat", "modelOverrides", or "models".`)}else if(!s){if(!i.baseUrl)throw new Error(`Provider ${r}: "baseUrl" is required when defining custom models.`);if(!i.apiKey)throw new Error(`Provider ${r}: "apiKey" is required when defining custom models.`)}for(const u of a){const p=!!u.api;if(!n&&!p&&!s)throw new Error(`Provider ${r}, model ${u.id}: no "api" specified. Set at provider or model level.`);if(!u.id)throw new Error(`Provider ${r}: model missing "id"`);if(u.contextWindow!==void 0&&u.contextWindow<=0)throw new Error(`Provider ${r}, model ${u.id}: invalid contextWindow`);if(u.maxTokens!==void 0&&u.maxTokens<=0)throw new Error(`Provider ${r}, model ${u.id}: invalid maxTokens`)}}}parseModels(t){const o=[],r=new Set(g()),i=new Map,s=c(n=>{if(!r.has(n))return;if(i.has(n))return i.get(n);const a=S(n);if(a.length===0)return;const l={api:a[0].api,baseUrl:a[0].baseUrl};return i.set(n,l),l},"getBuiltInDefaults");for(const[n,a]of Object.entries(t.providers)){const l=a.models??[];if(l.length===0)continue;const u=s(n);for(const p of l){const b=p.api??a.api??u?.api;if(!b)continue;const y=p.baseUrl??a.baseUrl??u?.baseUrl;if(!y)continue;const U=O(a.compat,p.compat);this.storeModelHeaders(n,p.id,p.headers);const L={input:0,output:0,cacheRead:0,cacheWrite:0};o.push({id:p.id,name:p.name??p.id,api:b,provider:n,baseUrl:y,reasoning:p.reasoning??!1,thinkingLevelMap:p.thinkingLevelMap,input:p.input??["text"],cost:p.cost??L,contextWindow:p.contextWindow??128e3,maxTokens:p.maxTokens??16384,headers:void 0,compat:U})}}return o}getAll(){return this.models}getAvailable(){return this.models.filter(t=>this.hasConfiguredAuth(t))}find(t,o){return this.models.find(r=>r.provider===t&&r.id===o)}hasConfiguredAuth(t){const o=this.providerRequestConfigs.get(t.provider)?.apiKey;return this.authStorage.hasAuth(t.provider)||o!==void 0&&w(o)}getModelRequestKey(t,o){return`${t}:${o}`}storeProviderRequestConfig(t,o){!o.apiKey&&!o.headers&&!o.authHeader||this.providerRequestConfigs.set(t,{apiKey:o.apiKey,headers:o.headers,authHeader:o.authHeader})}storeModelHeaders(t,o,r){const i=this.getModelRequestKey(t,o);if(!r||Object.keys(r).length===0){this.modelRequestHeaders.delete(i);return}this.modelRequestHeaders.set(i,r)}async getApiKeyAndHeaders(t){try{const o=this.providerRequestConfigs.get(t.provider),i=await this.authStorage.getApiKey(t.provider,{includeFallback:!1})??(o?.apiKey?J(o.apiKey,`API key for provider "${t.provider}"`):void 0),s=C(o?.headers,`provider "${t.provider}"`),n=C(this.modelRequestHeaders.get(this.getModelRequestKey(t.provider,t.id)),`model "${t.provider}/${t.id}"`);let a=t.headers||s||n?{...t.headers,...s,...n}:void 0;if(o?.authHeader){if(!i)return{ok:!1,error:`No API key found for "${t.provider}"`};a={...a,Authorization:`Bearer ${i}`}}return{ok:!0,apiKey:i,headers:a&&Object.keys(a).length>0?a:void 0}}catch(o){return{ok:!1,error:o instanceof Error?o.message:String(o)}}}getProviderAuthStatus(t){const o=this.authStorage.getAuthStatus(t);if(o.source)return o;const r=this.providerRequestConfigs.get(t)?.apiKey;if(!r)return o;if(G(r))return{configured:!0,source:"models_json_command"};const i=F(r);return i.length>0?w(r)?{configured:!0,source:"environment",label:i.join(", ")}:{configured:!1}:{configured:!0,source:"models_json_key"}}getProviderDisplayName(t){const o=this.registeredProviders.get(t),r=this.authStorage.getOAuthProviders().find(i=>i.id===t);return o?.name??o?.oauth?.name??r?.name??N[t]??t}async getApiKeyForProvider(t){const o=await this.authStorage.getApiKey(t,{includeFallback:!1});if(o!==void 0)return o;const r=this.providerRequestConfigs.get(t)?.apiKey;return r?Y(r):void 0}isUsingOAuth(t){return this.authStorage.get(t.provider)?.type==="oauth"}registerProvider(t,o){const r=ae(t,o);this.validateProviderConfig(t,r),this.applyProviderConfig(t,r),this.upsertRegisteredProvider(t,r)}unregisterProvider(t){this.registeredProviders.has(t)&&(this.registeredProviders.delete(t),this.refresh())}upsertRegisteredProvider(t,o){const r=this.registeredProviders.get(t);if(!r){this.registeredProviders.set(t,o);return}for(const i of Object.keys(o))o[i]!==void 0&&(r[i]=o[i])}validateProviderConfig(t,o){if(o.streamSimple&&!o.api)throw new Error(`Provider ${t}: "api" is required when registering streamSimple.`);if(!(!o.models||o.models.length===0)){if(!o.baseUrl)throw new Error(`Provider ${t}: "baseUrl" is required when defining models.`);if(!o.apiKey&&!o.oauth)throw new Error(`Provider ${t}: "apiKey" or "oauth" is required when defining models.`);for(const r of o.models)if(!(r.api||o.api))throw new Error(`Provider ${t}, model ${r.id}: no "api" specified.`)}}applyProviderConfig(t,o){if(o.oauth){const r={...o.oauth,id:t};j(r)}if(o.streamSimple){const r=o.streamSimple;$({api:o.api,stream:c((i,s,n)=>r(i,s,n),"stream"),streamSimple:r},`provider:${t}`)}if(this.storeProviderRequestConfig(t,o),o.models&&o.models.length>0){this.models=this.models.filter(r=>r.provider!==t);for(const r of o.models){const i=r.api||o.api;this.storeModelHeaders(t,r.id,r.headers),this.models.push({id:r.id,name:r.name,api:i,provider:t,baseUrl:r.baseUrl??o.baseUrl,reasoning:r.reasoning,thinkingLevelMap:r.thinkingLevelMap,input:r.input,cost:r.cost,contextWindow:r.contextWindow,maxTokens:r.maxTokens,headers:void 0,compat:r.compat})}if(o.oauth?.modifyModels){const r=this.authStorage.get(t);r?.type==="oauth"&&(this.models=o.oauth.modifyModels(this.models,r))}}else(o.baseUrl||o.headers)&&(this.models=this.models.map(r=>r.provider!==t?r:{...r,baseUrl:o.baseUrl??r.baseUrl}))}}export{v as ModelRegistry,we as clearApiKeyCache};
@@ -0,0 +1,109 @@
1
+ /**
2
+ * Model resolution, scoping, and initial selection
3
+ */
4
+ import type { ThinkingLevel } from "@openadapter/koda-agent-core";
5
+ import { type Api, type KnownProvider, type Model } from "@openadapter/koda-ai";
6
+ import type { ModelRegistry } from "./model-registry.ts";
7
+ /** Default model IDs for each known provider */
8
+ export declare const defaultModelPerProvider: Record<KnownProvider, string>;
9
+ export interface ScopedModel {
10
+ model: Model<Api>;
11
+ /** Thinking level if explicitly specified in pattern (e.g., "model:high"), undefined otherwise */
12
+ thinkingLevel?: ThinkingLevel;
13
+ }
14
+ /**
15
+ * Find an exact model reference match.
16
+ * Supports either a bare model id or a canonical provider/modelId reference.
17
+ * When matching by bare id, ambiguous matches across providers are rejected.
18
+ */
19
+ export declare function findExactModelReferenceMatch(modelReference: string, availableModels: Model<Api>[]): Model<Api> | undefined;
20
+ export interface ParsedModelResult {
21
+ model: Model<Api> | undefined;
22
+ /** Thinking level if explicitly specified in pattern, undefined otherwise */
23
+ thinkingLevel?: ThinkingLevel;
24
+ warning: string | undefined;
25
+ }
26
+ /**
27
+ * Parse a pattern to extract model and thinking level.
28
+ * Handles models with colons in their IDs (e.g., OpenRouter's :exacto suffix).
29
+ *
30
+ * Algorithm:
31
+ * 1. Try to match full pattern as a model
32
+ * 2. If found, return it with "off" thinking level
33
+ * 3. If not found and has colons, split on last colon:
34
+ * - If suffix is valid thinking level, use it and recurse on prefix
35
+ * - If suffix is invalid, warn and recurse on prefix with "off"
36
+ *
37
+ * @internal Exported for testing
38
+ */
39
+ export declare function parseModelPattern(pattern: string, availableModels: Model<Api>[], options?: {
40
+ allowInvalidThinkingLevelFallback?: boolean;
41
+ }): ParsedModelResult;
42
+ /**
43
+ * Resolve model patterns to actual Model objects with optional thinking levels
44
+ * Format: "pattern:level" where :level is optional
45
+ * For each pattern, finds all matching models and picks the best version:
46
+ * 1. Prefer alias (e.g., claude-sonnet-4-5) over dated versions (claude-sonnet-4-5-20250929)
47
+ * 2. If no alias, pick the latest dated version
48
+ *
49
+ * Supports models with colons in their IDs (e.g., OpenRouter's model:exacto).
50
+ * The algorithm tries to match the full pattern first, then progressively
51
+ * strips colon-suffixes to find a match.
52
+ */
53
+ export declare function resolveModelScope(patterns: string[], modelRegistry: ModelRegistry): Promise<ScopedModel[]>;
54
+ export interface ResolveCliModelResult {
55
+ model: Model<Api> | undefined;
56
+ thinkingLevel?: ThinkingLevel;
57
+ warning: string | undefined;
58
+ /**
59
+ * Error message suitable for CLI display.
60
+ * When set, model will be undefined.
61
+ */
62
+ error: string | undefined;
63
+ }
64
+ /**
65
+ * Resolve a single model from CLI flags.
66
+ *
67
+ * Supports:
68
+ * - --provider <provider> --model <pattern>
69
+ * - --model <provider>/<pattern>
70
+ * - Fuzzy matching (same rules as model scoping: exact id, then partial id/name)
71
+ *
72
+ * Note: This does not apply the thinking level by itself, but it may *parse* and
73
+ * return a thinking level from "<pattern>:<thinking>" so the caller can apply it.
74
+ */
75
+ export declare function resolveCliModel(options: {
76
+ cliProvider?: string;
77
+ cliModel?: string;
78
+ modelRegistry: ModelRegistry;
79
+ }): ResolveCliModelResult;
80
+ export interface InitialModelResult {
81
+ model: Model<Api> | undefined;
82
+ thinkingLevel: ThinkingLevel;
83
+ fallbackMessage: string | undefined;
84
+ }
85
+ /**
86
+ * Find the initial model to use based on priority:
87
+ * 1. CLI args (provider + model)
88
+ * 2. First model from scoped models (if not continuing/resuming)
89
+ * 3. Restored from session (if continuing/resuming)
90
+ * 4. Saved default from settings
91
+ * 5. First available model with valid API key
92
+ */
93
+ export declare function findInitialModel(options: {
94
+ cliProvider?: string;
95
+ cliModel?: string;
96
+ scopedModels: ScopedModel[];
97
+ isContinuing: boolean;
98
+ defaultProvider?: string;
99
+ defaultModelId?: string;
100
+ defaultThinkingLevel?: ThinkingLevel;
101
+ modelRegistry: ModelRegistry;
102
+ }): Promise<InitialModelResult>;
103
+ /**
104
+ * Restore model from session, with fallback to available models
105
+ */
106
+ export declare function restoreModelFromSession(savedProvider: string, savedModelId: string, currentModel: Model<Api> | undefined, shouldPrintMessages: boolean, modelRegistry: ModelRegistry): Promise<{
107
+ model: Model<Api> | undefined;
108
+ fallbackMessage: string | undefined;
109
+ }>;
@@ -0,0 +1 @@
1
+ var I=Object.defineProperty;var h=(t,r)=>I(t,"name",{value:r,configurable:!0});import{modelsAreEqual as x}from"@openadapter/koda-ai";import v from"chalk";import{minimatch as M}from"minimatch";import{isValidThinkingLevel as C}from"../cli/args.js";import{DEFAULT_THINKING_LEVEL as w}from"./defaults.js";const L={"amazon-bedrock":"us.anthropic.claude-opus-4-6-v1",anthropic:"claude-opus-4-8",openai:"gpt-5.4","azure-openai-responses":"gpt-5.4","openai-codex":"gpt-5.5",nvidia:"nvidia/nemotron-3-super-120b-a12b",deepseek:"deepseek-v4-pro",google:"gemini-3.1-pro-preview","google-vertex":"gemini-3.1-pro-preview","github-copilot":"gpt-5.4",openrouter:"moonshotai/kimi-k2.6","vercel-ai-gateway":"zai/glm-5.1",xai:"grok-4.20-0309-reasoning",groq:"openai/gpt-oss-120b",cerebras:"zai-glm-4.7",zai:"glm-5.1",mistral:"devstral-medium-latest",minimax:"MiniMax-M2.7","minimax-cn":"MiniMax-M2.7",moonshotai:"kimi-k2.6","moonshotai-cn":"kimi-k2.6",huggingface:"moonshotai/Kimi-K2.6",fireworks:"accounts/fireworks/models/kimi-k2p6",together:"moonshotai/Kimi-K2.6",opencode:"kimi-k2.6","opencode-go":"kimi-k2.6","kimi-coding":"kimi-for-coding","cloudflare-workers-ai":"@cf/moonshotai/kimi-k2.6","cloudflare-ai-gateway":"workers-ai/@cf/moonshotai/kimi-k2.6",xiaomi:"mimo-v2.5-pro","xiaomi-token-plan-cn":"mimo-v2.5-pro","xiaomi-token-plan-ams":"mimo-v2.5-pro","xiaomi-token-plan-sgp":"mimo-v2.5-pro"};function y(t){return t.endsWith("-latest")?!0:!/-\d{8}$/.test(t)}h(y,"isAlias");function F(t,r){const i=t.trim();if(!i)return;const l=i.toLowerCase(),n=r.filter(o=>`${o.provider}/${o.id}`.toLowerCase()===l);if(n.length===1)return n[0];if(n.length>1)return;const a=i.indexOf("/");if(a!==-1){const o=i.substring(0,a).trim(),s=i.substring(a+1).trim();if(o&&s){const c=r.filter(u=>u.provider.toLowerCase()===o.toLowerCase()&&u.id.toLowerCase()===s.toLowerCase());if(c.length===1)return c[0];if(c.length>1)return}}const e=r.filter(o=>o.id.toLowerCase()===l);return e.length===1?e[0]:void 0}h(F,"findExactModelReferenceMatch");function A(t,r){const i=F(t,r);if(i)return i;const l=r.filter(e=>e.id.toLowerCase().includes(t.toLowerCase())||e.name?.toLowerCase().includes(t.toLowerCase()));if(l.length===0)return;const n=l.filter(e=>y(e.id)),a=l.filter(e=>!y(e.id));return n.length>0?(n.sort((e,o)=>o.id.localeCompare(e.id)),n[0]):(a.sort((e,o)=>o.id.localeCompare(e.id)),a[0])}h(A,"tryMatchModel");function U(t,r,i){const l=i.filter(e=>e.provider===t);if(l.length===0)return;const n=L[t];return{...n?l.find(e=>e.id===n)??l[0]:l[0],id:r,name:r}}h(U,"buildFallbackModel");function b(t,r,i){const l=A(t,r);if(l)return{model:l,thinkingLevel:void 0,warning:void 0};const n=t.lastIndexOf(":");if(n===-1)return{model:void 0,thinkingLevel:void 0,warning:void 0};const a=t.substring(0,n),e=t.substring(n+1);if(C(e)){const o=b(a,r,i);return o.model?{model:o.model,thinkingLevel:o.warning?void 0:e,warning:o.warning}:o}else{if(!(i?.allowInvalidThinkingLevelFallback??!0))return{model:void 0,thinkingLevel:void 0,warning:void 0};const s=b(a,r,i);return s.model?{model:s.model,thinkingLevel:void 0,warning:`Invalid thinking level "${e}" in pattern "${t}". Using default instead.`}:s}}h(b,"parseModelPattern");async function R(t,r){const i=await r.getAvailable(),l=[];for(const n of t){if(n.includes("*")||n.includes("?")||n.includes("[")){const s=n.lastIndexOf(":");let c=n,u;if(s!==-1){const d=n.substring(s+1);C(d)&&(u=d,c=n.substring(0,s))}const p=i.filter(d=>{const k=`${d.provider}/${d.id}`;return M(k,c,{nocase:!0})||M(d.id,c,{nocase:!0})});if(p.length===0){console.warn(v.yellow(`Warning: No models match pattern "${n}"`));continue}for(const d of p)l.find(k=>x(k.model,d))||l.push({model:d,thinkingLevel:u});continue}const{model:a,thinkingLevel:e,warning:o}=b(n,i);if(o&&console.warn(v.yellow(`Warning: ${o}`)),!a){console.warn(v.yellow(`Warning: No models match pattern "${n}"`));continue}l.find(s=>x(s.model,a))||l.push({model:a,thinkingLevel:e})}return l}h(R,"resolveModelScope");function T(t){const{cliProvider:r,cliModel:i,modelRegistry:l}=t;if(!i)return{model:void 0,warning:void 0,error:void 0};const n=l.getAll();if(n.length===0)return{model:void 0,warning:void 0,error:"No models available. Check your installation or add models to models.json."};const a=new Map;for(const f of n)a.set(f.provider.toLowerCase(),f.provider);let e=r?a.get(r.toLowerCase()):void 0;if(r&&!e)return{model:void 0,warning:void 0,error:`Unknown provider "${r}". Use --list-models to see available providers/models.`};let o=i,s=!1;if(!e){const f=i.indexOf("/");if(f!==-1){const g=i.substring(0,f),m=a.get(g.toLowerCase());m&&(e=m,o=i.substring(f+1),s=!0)}}if(!e){const f=i.toLowerCase(),g=n.find(m=>m.id.toLowerCase()===f||`${m.provider}/${m.id}`.toLowerCase()===f);if(g)return{model:g,warning:void 0,thinkingLevel:void 0,error:void 0}}if(r&&e){const f=`${e}/`;i.toLowerCase().startsWith(f.toLowerCase())&&(o=i.substring(f.length))}const c=e?n.filter(f=>f.provider===e):n,{model:u,thinkingLevel:p,warning:d}=b(o,c,{allowInvalidThinkingLevelFallback:!1});if(u)return{model:u,thinkingLevel:p,warning:d,error:void 0};if(s){const f=i.toLowerCase(),g=n.find($=>$.id.toLowerCase()===f||`${$.provider}/${$.id}`.toLowerCase()===f);if(g)return{model:g,warning:void 0,thinkingLevel:void 0,error:void 0};const m=b(i,n,{allowInvalidThinkingLevelFallback:!1});if(m.model)return{model:m.model,thinkingLevel:m.thinkingLevel,warning:m.warning,error:void 0}}if(e){const f=U(e,o,n);if(f){const g=d?`${d} Model "${o}" not found for provider "${e}". Using custom model id.`:`Model "${o}" not found for provider "${e}". Using custom model id.`;return{model:f,thinkingLevel:void 0,warning:g,error:void 0}}}const k=e?`${e}/${o}`:i;return{model:void 0,thinkingLevel:void 0,warning:d,error:`Model "${k}" not found. Use --list-models to see available models.`}}h(T,"resolveCliModel");async function j(t){const{cliProvider:r,cliModel:i,scopedModels:l,isContinuing:n,defaultProvider:a,defaultModelId:e,defaultThinkingLevel:o,modelRegistry:s}=t;let c,u=w;if(r&&i){const d=T({cliProvider:r,cliModel:i,modelRegistry:s});if(d.error&&(console.error(v.red(d.error)),process.exit(1)),d.model)return{model:d.model,thinkingLevel:w,fallbackMessage:void 0}}if(l.length>0&&!n)return{model:l[0].model,thinkingLevel:l[0].thinkingLevel??o??w,fallbackMessage:void 0};if(a&&e){const d=s.find(a,e);if(d)return c=d,o&&(u=o),{model:c,thinkingLevel:u,fallbackMessage:void 0}}const p=await s.getAvailable();if(p.length>0){for(const d of Object.keys(L)){const k=L[d],f=p.find(g=>g.provider===d&&g.id===k);if(f)return{model:f,thinkingLevel:w,fallbackMessage:void 0}}return{model:p[0],thinkingLevel:w,fallbackMessage:void 0}}return{model:void 0,thinkingLevel:w,fallbackMessage:void 0}}h(j,"findInitialModel");async function V(t,r,i,l,n){const a=n.find(t,r),e=a?n.hasConfiguredAuth(a):!1;if(a&&e)return l&&console.log(v.dim(`Restored model: ${t}/${r}`)),{model:a,fallbackMessage:void 0};const o=a?"no auth configured":"model no longer exists";if(l&&console.error(v.yellow(`Warning: Could not restore model ${t}/${r} (${o}).`)),i)return l&&console.log(v.dim(`Falling back to: ${i.provider}/${i.id}`)),{model:i,fallbackMessage:`Could not restore model ${t}/${r} (${o}). Using ${i.provider}/${i.id}.`};const s=await n.getAvailable();if(s.length>0){let c;for(const u of Object.keys(L)){const p=L[u],d=s.find(k=>k.provider===u&&k.id===p);if(d){c=d;break}}return c||(c=s[0]),l&&console.log(v.dim(`Falling back to: ${c.provider}/${c.id}`)),{model:c,fallbackMessage:`Could not restore model ${t}/${r} (${o}). Using ${c.provider}/${c.id}.`}}return{model:void 0,fallbackMessage:void 0}}h(V,"restoreModelFromSession");export{L as defaultModelPerProvider,F as findExactModelReferenceMatch,j as findInitialModel,b as parseModelPattern,T as resolveCliModel,R as resolveModelScope,V as restoreModelFromSession};
@@ -0,0 +1,6 @@
1
+ export declare function takeOverStdout(): void;
2
+ export declare function restoreStdout(): void;
3
+ export declare function isStdoutTakenOver(): boolean;
4
+ export declare function writeRawStdout(text: string): void;
5
+ export declare function waitForRawStdoutBackpressure(): Promise<void>;
6
+ export declare function flushRawStdout(): Promise<void>;
@@ -0,0 +1 @@
1
+ var d=Object.defineProperty;var o=(r,e)=>d(r,"name",{value:e,configurable:!0});let i;const p=10;let s=Promise.resolve();function w(){return i?i.rawStdoutWrite:process.stdout.write.bind(process.stdout)}o(w,"getRawStdoutWrite");async function c(r){for(;;)try{await new Promise((e,n)=>{try{w()(r,t=>{t?n(t):e()})}catch(t){n(t instanceof Error?t:new Error(String(t)))}});return}catch(e){const n=e instanceof Error?e:new Error(String(e)),t=n.code;if(t!=="ENOBUFS"&&t!=="EAGAIN"&&t!=="EWOULDBLOCK")throw n;await new Promise(u=>setTimeout(u,10))}}o(c,"writeRawStdoutChunk");function E(){if(i)return;const r=process.stdout.write.bind(process.stdout),e=process.stderr.write.bind(process.stderr),n=process.stdout.write;process.stdout.write=((t,u,a)=>typeof u=="function"?e(String(t),u):e(String(t),a)),i={rawStdoutWrite:r,rawStderrWrite:e,originalStdoutWrite:n}}o(E,"takeOverStdout");function R(){i&&(process.stdout.write=i.originalStdoutWrite,i=void 0)}o(R,"restoreStdout");function l(){return i!==void 0}o(l,"isStdoutTakenOver");function T(r){r.length!==0&&(s=s.then(()=>c(r)),s.catch(()=>{process.exit(1)}))}o(T,"writeRawStdout");async function S(){for(;;){const r=s;if(await r,r===s)return}}o(S,"waitForRawStdoutBackpressure");async function W(){await S(),await c("")}o(W,"flushRawStdout");export{W as flushRawStdout,l as isStdoutTakenOver,R as restoreStdout,E as takeOverStdout,S as waitForRawStdoutBackpressure,T as writeRawStdout};
@@ -0,0 +1,203 @@
1
+ import type { SettingsManager } from "./settings-manager.ts";
2
+ export interface PathMetadata {
3
+ source: string;
4
+ scope: SourceScope;
5
+ origin: "package" | "top-level";
6
+ baseDir?: string;
7
+ }
8
+ export interface ResolvedResource {
9
+ path: string;
10
+ enabled: boolean;
11
+ metadata: PathMetadata;
12
+ }
13
+ export interface ResolvedPaths {
14
+ extensions: ResolvedResource[];
15
+ skills: ResolvedResource[];
16
+ prompts: ResolvedResource[];
17
+ themes: ResolvedResource[];
18
+ }
19
+ export type MissingSourceAction = "install" | "skip" | "error";
20
+ export interface ProgressEvent {
21
+ type: "start" | "progress" | "complete" | "error";
22
+ action: "install" | "remove" | "update" | "clone" | "pull";
23
+ source: string;
24
+ message?: string;
25
+ }
26
+ export type ProgressCallback = (event: ProgressEvent) => void;
27
+ export interface PackageUpdate {
28
+ source: string;
29
+ displayName: string;
30
+ type: "npm" | "git";
31
+ scope: Exclude<SourceScope, "temporary">;
32
+ }
33
+ export interface ConfiguredPackage {
34
+ source: string;
35
+ scope: "user" | "project";
36
+ filtered: boolean;
37
+ installedPath?: string;
38
+ }
39
+ export interface PackageManager {
40
+ resolve(onMissing?: (source: string) => Promise<MissingSourceAction>): Promise<ResolvedPaths>;
41
+ install(source: string, options?: {
42
+ local?: boolean;
43
+ }): Promise<void>;
44
+ installAndPersist(source: string, options?: {
45
+ local?: boolean;
46
+ }): Promise<void>;
47
+ remove(source: string, options?: {
48
+ local?: boolean;
49
+ }): Promise<void>;
50
+ removeAndPersist(source: string, options?: {
51
+ local?: boolean;
52
+ }): Promise<boolean>;
53
+ update(source?: string): Promise<void>;
54
+ listConfiguredPackages(): ConfiguredPackage[];
55
+ resolveExtensionSources(sources: string[], options?: {
56
+ local?: boolean;
57
+ temporary?: boolean;
58
+ }): Promise<ResolvedPaths>;
59
+ addSourceToSettings(source: string, options?: {
60
+ local?: boolean;
61
+ }): boolean;
62
+ removeSourceFromSettings(source: string, options?: {
63
+ local?: boolean;
64
+ }): boolean;
65
+ setProgressCallback(callback: ProgressCallback | undefined): void;
66
+ getInstalledPath(source: string, scope: "user" | "project"): string | undefined;
67
+ }
68
+ interface PackageManagerOptions {
69
+ cwd: string;
70
+ agentDir: string;
71
+ settingsManager: SettingsManager;
72
+ }
73
+ type SourceScope = "user" | "project" | "temporary";
74
+ export declare class DefaultPackageManager implements PackageManager {
75
+ private cwd;
76
+ private agentDir;
77
+ private settingsManager;
78
+ private globalNpmRoot;
79
+ private globalNpmRootCommandKey;
80
+ private progressCallback;
81
+ constructor(options: PackageManagerOptions);
82
+ setProgressCallback(callback: ProgressCallback | undefined): void;
83
+ addSourceToSettings(source: string, options?: {
84
+ local?: boolean;
85
+ }): boolean;
86
+ removeSourceFromSettings(source: string, options?: {
87
+ local?: boolean;
88
+ }): boolean;
89
+ getInstalledPath(source: string, scope: "user" | "project"): string | undefined;
90
+ private emitProgress;
91
+ private withProgress;
92
+ resolve(onMissing?: (source: string) => Promise<MissingSourceAction>): Promise<ResolvedPaths>;
93
+ resolveExtensionSources(sources: string[], options?: {
94
+ local?: boolean;
95
+ temporary?: boolean;
96
+ }): Promise<ResolvedPaths>;
97
+ listConfiguredPackages(): ConfiguredPackage[];
98
+ install(source: string, options?: {
99
+ local?: boolean;
100
+ }): Promise<void>;
101
+ installAndPersist(source: string, options?: {
102
+ local?: boolean;
103
+ }): Promise<void>;
104
+ remove(source: string, options?: {
105
+ local?: boolean;
106
+ }): Promise<void>;
107
+ removeAndPersist(source: string, options?: {
108
+ local?: boolean;
109
+ }): Promise<boolean>;
110
+ update(source?: string): Promise<void>;
111
+ private updateConfiguredSources;
112
+ private shouldUpdateNpmSource;
113
+ private updateNpmBatch;
114
+ private installNpmBatch;
115
+ checkForAvailableUpdates(): Promise<PackageUpdate[]>;
116
+ private resolvePackageSources;
117
+ private resolveLocalExtensionSource;
118
+ private installParsedSource;
119
+ private getPackageSourceString;
120
+ private getSourceMatchKeyForInput;
121
+ private getSourceMatchKeyForSettings;
122
+ private buildNoMatchingPackageMessage;
123
+ private findSuggestedConfiguredSource;
124
+ private packageSourcesMatch;
125
+ private normalizePackageSourceForSettings;
126
+ private parseSource;
127
+ private installedNpmMatchesPinnedVersion;
128
+ private npmHasAvailableUpdate;
129
+ private getInstalledNpmVersion;
130
+ private getLatestNpmVersion;
131
+ private gitHasAvailableUpdate;
132
+ private getRemoteGitHead;
133
+ private getLocalGitUpdateTarget;
134
+ private getGitUpstreamRef;
135
+ private runGitRemoteCommand;
136
+ private runWithConcurrency;
137
+ /**
138
+ * Get a unique identity for a package, ignoring version/ref.
139
+ * Used to detect when the same package is in both global and project settings.
140
+ * For git packages, uses normalized host/path to ensure SSH and HTTPS URLs
141
+ * for the same repository are treated as identical.
142
+ */
143
+ private getPackageIdentity;
144
+ /**
145
+ * Dedupe packages: if same package identity appears in both global and project,
146
+ * keep only the project one (project wins).
147
+ */
148
+ private dedupePackages;
149
+ private parseNpmSpec;
150
+ private getNpmCommand;
151
+ private getPackageManagerName;
152
+ private runNpmCommand;
153
+ private getGitDependencyInstallArgs;
154
+ private runNpmCommandSync;
155
+ private getNpmInstallArgs;
156
+ private installNpm;
157
+ private uninstallNpm;
158
+ private installGit;
159
+ private updateGit;
160
+ private ensureGitRef;
161
+ private refreshTemporaryGitSource;
162
+ private removeGit;
163
+ private pruneEmptyGitParents;
164
+ private ensureNpmProject;
165
+ private ensureGitIgnore;
166
+ private getNpmInstallRoot;
167
+ private getGlobalNpmRoot;
168
+ private getPnpmGlobalPackagePath;
169
+ private getManagedNpmInstallPath;
170
+ private getLegacyGlobalNpmInstallPath;
171
+ private getNpmInstallPath;
172
+ private getGitInstallPath;
173
+ private getGitInstallRoot;
174
+ private getTemporaryDir;
175
+ private getBaseDirForScope;
176
+ private resolvePath;
177
+ private resolvePathFromBase;
178
+ private collectPackageResources;
179
+ private collectDefaultResources;
180
+ private applyPackageFilter;
181
+ /**
182
+ * Collect all files from a package for a resource type, applying manifest patterns.
183
+ * Returns { allFiles, enabledByManifest } where enabledByManifest is the set of files
184
+ * that pass the manifest's own patterns.
185
+ */
186
+ private collectManifestFiles;
187
+ private readPiManifest;
188
+ private addManifestEntries;
189
+ private collectFilesFromManifestEntries;
190
+ private resolveLocalEntries;
191
+ private addAutoDiscoveredResources;
192
+ private collectFilesFromPaths;
193
+ private getTargetMap;
194
+ private addResource;
195
+ private createAccumulator;
196
+ private toResolvedPaths;
197
+ private spawnCommand;
198
+ private spawnCaptureCommand;
199
+ private runCommandCapture;
200
+ private runCommand;
201
+ private runCommandSync;
202
+ }
203
+ export {};
@@ -0,0 +1,3 @@
1
+ var ut=Object.defineProperty;var f=(c,t)=>ut(c,"name",{value:t,configurable:!0});import{createHash as ht}from"node:crypto";import{existsSync as m,mkdirSync as O,readdirSync as E,readFileSync as I,rmSync as q,statSync as v,writeFileSync as Q}from"node:fs";import{homedir as pt,tmpdir as mt}from"node:os";function _(){if(process.platform!=="linux"||Object.keys(process.env).length>0)return process.env;try{const c=I("/proc/self/environ","utf-8"),t={};for(const e of c.split("\0")){const s=e.indexOf("=");s>0&&(t[e.slice(0,s)]=e.slice(s+1))}return t}catch{return process.env}}f(_,"getEnv");import{basename as G,dirname as P,join as p,relative as w,resolve as N,sep as ft}from"node:path";import{globSync as gt}from"glob";import $ from"ignore";import{minimatch as F}from"minimatch";import{CONFIG_DIR_NAME as b}from"../config.js";import{spawnProcess as X,spawnProcessSync as dt}from"../utils/child-process.js";import{parseGitUrl as yt}from"../utils/git.js";import{canonicalizePath as Pt,isLocalPath as wt,markPathIgnoredByCloudSync as kt,resolvePath as A}from"../utils/paths.js";import{isStdoutTakenOver as St}from"./output-guard.js";const S=1e4,Z=4,vt=4;function C(){const c=process.env.KODA_OFFLINE;return c?c==="1"||c.toLowerCase()==="true"||c.toLowerCase()==="yes":!1}f(C,"isOfflineModeEnabled");function tt(c){return c.origin==="package"?4:(c.scope==="project"?0:2)+(c.source==="local"?0:1)}f(tt,"resourcePrecedenceRank");const j=["extensions","skills","prompts","themes"],Nt={extensions:/\.(ts|js)$/,skills:/\.md$/,prompts:/\.md$/,themes:/\.json$/},Ct=[".gitignore",".ignore",".fdignore"];function d(c){return c.split(ft).join("/")}f(d,"toPosixPath");function V(){return process.env.HOME||pt()}f(V,"getHomeDir");function Mt(c,t){const e=c.trim();if(!e||e.startsWith("#")&&!e.startsWith("\\#"))return null;let s=c,n=!1;s.startsWith("!")?(n=!0,s=s.slice(1)):s.startsWith("\\!")&&(s=s.slice(1)),s.startsWith("/")&&(s=s.slice(1));const r=t?`${t}${s}`:s;return n?`!${r}`:r}f(Mt,"prefixIgnorePattern");function R(c,t,e){const s=w(e,t),n=s?`${d(s)}/`:"";for(const r of Ct){const i=p(t,r);if(m(i))try{const a=I(i,"utf-8").split(/\r?\n/).map(l=>Mt(l,n)).filter(l=>!!l);a.length>0&&c.add(a)}catch{}}}f(R,"addIgnoreRules");function Et(c){return c.startsWith("!")||c.startsWith("+")||c.startsWith("-")||c.includes("*")||c.includes("?")}f(Et,"isPattern");function B(c){return c.startsWith("!")||c.startsWith("+")||c.startsWith("-")}f(B,"isOverridePattern");function Ft(c){return c.includes("*")||c.includes("?")}f(Ft,"hasGlobPattern");function bt(c){const t=[],e=[];for(const s of c)Et(s)?e.push(s):t.push(s);return{plain:t,patterns:e}}f(bt,"splitPatterns");function et(c,t,e=!0,s,n){const r=[];if(!m(c))return r;const i=n??c,o=s??$();R(o,c,i);try{const a=E(c,{withFileTypes:!0});for(const l of a){if(l.name.startsWith(".")||e&&l.name==="node_modules")continue;const h=p(c,l.name);let u=l.isDirectory(),g=l.isFile();if(l.isSymbolicLink())try{const x=v(h);u=x.isDirectory(),g=x.isFile()}catch{continue}const k=d(w(i,h)),y=u?`${k}/`:k;o.ignores(y)||(u?r.push(...et(h,t,e,o,i)):g&&t.test(l.name)&&r.push(h))}}catch{}return r}f(et,"collectFiles");function J(c,t,e,s){const n=[];if(!m(c))return n;const r=s??c,i=e??$();R(i,c,r);try{const o=E(c,{withFileTypes:!0});for(const a of o){if(a.name!=="SKILL.md")continue;const l=p(c,a.name);let h=a.isFile();if(a.isSymbolicLink())try{h=v(l).isFile()}catch{continue}const u=d(w(r,l));if(h&&!i.ignores(u))return n.push(l),n}for(const a of o){if(a.name.startsWith(".")||a.name==="node_modules")continue;const l=p(c,a.name);let h=a.isDirectory(),u=a.isFile();if(a.isSymbolicLink())try{const k=v(l);h=k.isDirectory(),u=k.isFile()}catch{continue}const g=d(w(r,l));if(t==="pi"&&c===r&&u&&a.name.endsWith(".md")&&!i.ignores(g)){n.push(l);continue}h&&(i.ignores(`${g}/`)||n.push(...J(l,t,i,r)))}}catch{}return n}f(J,"collectSkillEntries");function W(c,t){return J(c,t)}f(W,"collectAutoSkillEntries");function xt(c){let t=N(c);for(;;){if(m(p(t,".git")))return t;const e=P(t);if(e===t)return null;t=e}}f(xt,"findGitRepoRoot");function It(c){const t=[],e=N(c),s=xt(e);let n=e;for(;t.push(p(n,".agents","skills")),!(s&&n===s);){const r=P(n);if(r===n)break;n=r}return t}f(It,"collectAncestorAgentsSkillDirs");function st(c){const t=[];if(!m(c))return t;const e=$();R(e,c,c);try{const s=E(c,{withFileTypes:!0});for(const n of s){if(n.name.startsWith(".")||n.name==="node_modules")continue;const r=p(c,n.name);let i=n.isFile();if(n.isSymbolicLink())try{i=v(r).isFile()}catch{continue}const o=d(w(c,r));e.ignores(o)||i&&n.name.endsWith(".md")&&t.push(r)}}catch{}return t}f(st,"collectAutoPromptEntries");function nt(c){const t=[];if(!m(c))return t;const e=$();R(e,c,c);try{const s=E(c,{withFileTypes:!0});for(const n of s){if(n.name.startsWith(".")||n.name==="node_modules")continue;const r=p(c,n.name);let i=n.isFile();if(n.isSymbolicLink())try{i=v(r).isFile()}catch{continue}const o=d(w(c,r));e.ignores(o)||i&&n.name.endsWith(".json")&&t.push(r)}}catch{}return t}f(nt,"collectAutoThemeEntries");function $t(c){try{const t=I(c,"utf-8");return JSON.parse(t).pi??null}catch{return null}}f($t,"readPiManifestFile");function rt(c){const t=p(c,"package.json");if(m(t)){const n=$t(t);if(n?.extensions?.length){const r=[];for(const i of n.extensions){const o=N(c,i);m(o)&&r.push(o)}if(r.length>0)return r}}const e=p(c,"index.ts"),s=p(c,"index.js");return m(e)?[e]:m(s)?[s]:null}f(rt,"resolveExtensionEntries");function K(c){const t=[];if(!m(c))return t;const e=rt(c);if(e)return e;const s=$();R(s,c,c);try{const n=E(c,{withFileTypes:!0});for(const r of n){if(r.name.startsWith(".")||r.name==="node_modules")continue;const i=p(c,r.name);let o=r.isDirectory(),a=r.isFile();if(r.isSymbolicLink())try{const u=v(i);o=u.isDirectory(),a=u.isFile()}catch{continue}const l=d(w(c,i)),h=o?`${l}/`:l;if(!s.ignores(h)){if(a&&(r.name.endsWith(".ts")||r.name.endsWith(".js")))t.push(i);else if(o){const u=rt(i);u&&t.push(...u)}}}}catch{}return t}f(K,"collectAutoExtensionEntries");function T(c,t){return t==="skills"?J(c,"pi"):t==="extensions"?K(c):et(c,Nt[t])}f(T,"collectResourceFiles");function z(c,t,e){const s=d(w(e,c)),n=G(c),r=d(c),i=n==="SKILL.md",o=i?P(c):void 0,a=i?d(w(e,o)):void 0,l=i?G(o):void 0,h=i?d(o):void 0;return t.some(u=>{const g=d(u);return F(s,g)||F(n,g)||F(r,g)?!0:i?F(a,g)||F(l,g)||F(h,g):!1})}f(z,"matchesAnyPattern");function Rt(c){const t=c.startsWith("./")||c.startsWith(".\\")?c.slice(2):c;return d(t)}f(Rt,"normalizeExactPattern");function U(c,t,e){if(t.length===0)return!1;const s=d(w(e,c)),n=G(c),r=d(c),i=n==="SKILL.md",o=i?P(c):void 0,a=i?d(w(e,o)):void 0,l=i?d(o):void 0;return t.some(h=>{const u=Rt(h);return u===s||u===r?!0:i?u===a||u===l:!1})}f(U,"matchesAnyExactPattern");function Dt(c){return c.filter(t=>t.startsWith("!")||t.startsWith("+")||t.startsWith("-"))}f(Dt,"getOverridePatterns");function Gt(c,t,e){const s=Dt(t),n=s.filter(a=>a.startsWith("!")).map(a=>a.slice(1)),r=s.filter(a=>a.startsWith("+")).map(a=>a.slice(1)),i=s.filter(a=>a.startsWith("-")).map(a=>a.slice(1));let o=!0;return n.length>0&&z(c,n,e)&&(o=!1),r.length>0&&U(c,r,e)&&(o=!0),i.length>0&&U(c,i,e)&&(o=!1),o}f(Gt,"isEnabledByOverrides");function H(c,t,e){const s=[],n=[],r=[],i=[];for(const a of t)a.startsWith("+")?r.push(a.slice(1)):a.startsWith("-")?i.push(a.slice(1)):a.startsWith("!")?n.push(a.slice(1)):s.push(a);let o;if(s.length===0?o=[...c]:o=c.filter(a=>z(a,s,e)),n.length>0&&(o=o.filter(a=>!z(a,n,e))),r.length>0)for(const a of c)!o.includes(a)&&U(a,r,e)&&o.push(a);return i.length>0&&(o=o.filter(a=>!U(a,i,e))),new Set(o)}f(H,"applyPatterns");class zt{static{f(this,"DefaultPackageManager")}cwd;agentDir;settingsManager;globalNpmRoot;globalNpmRootCommandKey;progressCallback;constructor(t){this.cwd=A(t.cwd),this.agentDir=A(t.agentDir),this.settingsManager=t.settingsManager}setProgressCallback(t){this.progressCallback=t}addSourceToSettings(t,e){const s=e?.local?"project":"user",r=(s==="project"?this.settingsManager.getProjectSettings():this.settingsManager.getGlobalSettings()).packages??[],i=this.normalizePackageSourceForSettings(t,s),o=r.findIndex(l=>this.packageSourcesMatch(l,t,s));if(o!==-1){const l=r[o];if(this.getPackageSourceString(l)===i)return!1;const h=[...r];return h[o]=typeof l=="string"?i:{...l,source:i},s==="project"?this.settingsManager.setProjectPackages(h):this.settingsManager.setPackages(h),!0}const a=[...r,i];return s==="project"?this.settingsManager.setProjectPackages(a):this.settingsManager.setPackages(a),!0}removeSourceFromSettings(t,e){const s=e?.local?"project":"user",r=(s==="project"?this.settingsManager.getProjectSettings():this.settingsManager.getGlobalSettings()).packages??[],i=r.filter(a=>!this.packageSourcesMatch(a,t,s));return i.length!==r.length?(s==="project"?this.settingsManager.setProjectPackages(i):this.settingsManager.setPackages(i),!0):!1}getInstalledPath(t,e){const s=this.parseSource(t);if(s.type==="npm"){const n=this.getNpmInstallPath(s,e);return m(n)?n:void 0}if(s.type==="git"){const n=this.getGitInstallPath(s,e);return m(n)?n:void 0}if(s.type==="local"){const n=this.getBaseDirForScope(e),r=this.resolvePathFromBase(s.path,n);return m(r)?r:void 0}}emitProgress(t){this.progressCallback?.(t)}async withProgress(t,e,s,n){this.emitProgress({type:"start",action:t,source:e,message:s});try{await n(),this.emitProgress({type:"complete",action:t,source:e})}catch(r){const i=r instanceof Error?r.message:String(r);throw this.emitProgress({type:"error",action:t,source:e,message:i}),r}}async resolve(t){const e=this.createAccumulator(),s=this.settingsManager.getGlobalSettings(),n=this.settingsManager.getProjectSettings(),r=[];for(const l of n.packages??[])r.push({pkg:l,scope:"project"});for(const l of s.packages??[])r.push({pkg:l,scope:"user"});const i=this.dedupePackages(r);await this.resolvePackageSources(i,e,t);const o=this.agentDir,a=p(this.cwd,b);for(const l of j){const h=this.getTargetMap(e,l),u=s[l]??[],g=n[l]??[];this.resolveLocalEntries(g,l,h,{source:"local",scope:"project",origin:"top-level"},a),this.resolveLocalEntries(u,l,h,{source:"local",scope:"user",origin:"top-level"},o)}return this.addAutoDiscoveredResources(e,s,n,o,a),this.toResolvedPaths(e)}async resolveExtensionSources(t,e){const s=this.createAccumulator(),n=e?.temporary?"temporary":e?.local?"project":"user",r=t.map(i=>({pkg:i,scope:n}));return await this.resolvePackageSources(r,s),this.toResolvedPaths(s)}listConfiguredPackages(){const t=this.settingsManager.getGlobalSettings(),e=this.settingsManager.getProjectSettings(),s=[];for(const n of t.packages??[]){const r=typeof n=="string"?n:n.source;s.push({source:r,scope:"user",filtered:typeof n=="object",installedPath:this.getInstalledPath(r,"user")})}for(const n of e.packages??[]){const r=typeof n=="string"?n:n.source;s.push({source:r,scope:"project",filtered:typeof n=="object",installedPath:this.getInstalledPath(r,"project")})}return s}async install(t,e){const s=this.parseSource(t),n=e?.local?"project":"user";await this.withProgress("install",t,`Installing ${t}...`,async()=>{if(s.type==="npm"){await this.installNpm(s,n,!1);return}if(s.type==="git"){await this.installGit(s,n);return}if(s.type==="local"){const r=this.resolvePath(s.path);if(!m(r))throw new Error(`Path does not exist: ${r}`);return}throw new Error(`Unsupported install source: ${t}`)})}async installAndPersist(t,e){await this.install(t,e),this.addSourceToSettings(t,e)}async remove(t,e){const s=this.parseSource(t),n=e?.local?"project":"user";await this.withProgress("remove",t,`Removing ${t}...`,async()=>{if(s.type==="npm"){await this.uninstallNpm(s,n);return}if(s.type==="git"){await this.removeGit(s,n);return}if(s.type!=="local")throw new Error(`Unsupported remove source: ${t}`)})}async removeAndPersist(t,e){return await this.remove(t,e),this.removeSourceFromSettings(t,e)}async update(t){const e=this.settingsManager.getGlobalSettings(),s=this.settingsManager.getProjectSettings(),n=t?this.getPackageIdentity(t):void 0;let r=!1;const i=[];for(const o of e.packages??[]){const a=typeof o=="string"?o:o.source;n&&this.getPackageIdentity(a,"user")!==n||(r=!0,i.push({source:a,scope:"user"}))}for(const o of s.packages??[]){const a=typeof o=="string"?o:o.source;n&&this.getPackageIdentity(a,"project")!==n||(r=!0,i.push({source:a,scope:"project"}))}if(t&&!r)throw new Error(this.buildNoMatchingPackageMessage(t,[...e.packages??[],...s.packages??[]]));await this.updateConfiguredSources(i)}async updateConfiguredSources(t){if(C()||t.length===0)return;const e=[],s=[];for(const l of t){const h=this.parseSource(l.source);h.type==="npm"?h.pinned||e.push({...l,parsed:h}):h.type==="git"&&s.push({...l,parsed:h})}const n=e.map(l=>async()=>({entry:l,shouldUpdate:await this.shouldUpdateNpmSource(l.parsed,l.scope)})),r=await this.runWithConcurrency(n,Z),i=[],o=[];for(const l of r)l.shouldUpdate&&(l.entry.scope==="user"?i.push(l.entry):o.push(l.entry));const a=[];if(i.length>0&&a.push(this.updateNpmBatch(i,"user")),o.length>0&&a.push(this.updateNpmBatch(o,"project")),s.length>0){const l=s.map(h=>async()=>this.withProgress("update",h.source,`Updating ${h.source}...`,async()=>{await this.updateGit(h.parsed,h.scope)}));a.push(this.runWithConcurrency(l,vt).then(()=>{}))}await Promise.all(a)}async shouldUpdateNpmSource(t,e){const s=this.getManagedNpmInstallPath(t,e),n=m(s)?this.getInstalledNpmVersion(s):void 0;if(!n)return!0;try{return await this.getLatestNpmVersion(t.name)!==n}catch{return!0}}async updateNpmBatch(t,e){if(t.length===0)return;const s=t.length===1?t[0].source:`${e} npm packages`,n=t.length===1?`Updating ${t[0].source}...`:`Updating ${e} npm packages...`,r=t.map(i=>`${i.parsed.name}@latest`);await this.withProgress("update",s,n,async()=>{await this.installNpmBatch(r,e)})}async installNpmBatch(t,e){const s=this.getNpmInstallRoot(e,!1);this.ensureNpmProject(s),await this.runNpmCommand(this.getNpmInstallArgs(t,s))}async checkForAvailableUpdates(){if(C())return[];const t=this.settingsManager.getGlobalSettings(),e=this.settingsManager.getProjectSettings(),s=[];for(const o of e.packages??[])s.push({pkg:o,scope:"project"});for(const o of t.packages??[])s.push({pkg:o,scope:"user"});const r=this.dedupePackages(s).filter(o=>o.scope!=="temporary").map(o=>async()=>{const a=typeof o.pkg=="string"?o.pkg:o.pkg.source,l=this.parseSource(a);if(l.type==="local"||l.pinned)return;if(l.type==="npm"){const g=this.getNpmInstallPath(l,o.scope);return!m(g)||!await this.npmHasAvailableUpdate(l,g)?void 0:{source:a,displayName:l.name,type:"npm",scope:o.scope}}const h=this.getGitInstallPath(l,o.scope);if(!(!m(h)||!await this.gitHasAvailableUpdate(h)))return{source:a,displayName:`${l.host}/${l.path}`,type:"git",scope:o.scope}});return(await this.runWithConcurrency(r,Z)).filter(o=>o!==void 0)}async resolvePackageSources(t,e,s){for(const{pkg:n,scope:r}of t){const i=typeof n=="string"?n:n.source,o=typeof n=="object"?n:void 0,a=this.parseSource(i),l={source:i,scope:r,origin:"package"};if(a.type==="local"){const u=this.getBaseDirForScope(r);this.resolveLocalExtensionSource(a,e,o,l,u);continue}const h=f(async()=>{if(C())return!1;if(!s)return await this.installParsedSource(a,r),!0;const u=await s(i);if(u==="skip")return!1;if(u==="error")throw new Error(`Missing source: ${i}`);return await this.installParsedSource(a,r),!0},"installMissing");if(a.type==="npm"){let u=this.getNpmInstallPath(a,r);if(!m(u)||a.pinned&&!await this.installedNpmMatchesPinnedVersion(a,u)){if(!await h())continue;u=this.getNpmInstallPath(a,r)}l.baseDir=u,this.collectPackageResources(u,e,o,l);continue}if(a.type==="git"){const u=this.getGitInstallPath(a,r);if(m(u))r==="temporary"&&!a.pinned&&!C()&&await this.refreshTemporaryGitSource(a,i);else if(!await h())continue;l.baseDir=u,this.collectPackageResources(u,e,o,l)}}}resolveLocalExtensionSource(t,e,s,n,r){const i=this.resolvePathFromBase(t.path,r);if(m(i))try{const o=v(i);if(o.isFile()){n.baseDir=P(i),this.addResource(e.extensions,i,n,!0);return}o.isDirectory()&&(n.baseDir=i,this.collectPackageResources(i,e,s,n)||this.addResource(e.extensions,i,n,!0))}catch{return}}async installParsedSource(t,e){if(t.type==="npm"){await this.installNpm(t,e,e==="temporary");return}if(t.type==="git"){await this.installGit(t,e);return}}getPackageSourceString(t){return typeof t=="string"?t:t.source}getSourceMatchKeyForInput(t){const e=this.parseSource(t);return e.type==="npm"?`npm:${e.name}`:e.type==="git"?`git:${e.host}/${e.path}`:`local:${this.resolvePath(e.path)}`}getSourceMatchKeyForSettings(t,e){const s=this.parseSource(t);if(s.type==="npm")return`npm:${s.name}`;if(s.type==="git")return`git:${s.host}/${s.path}`;const n=this.getBaseDirForScope(e);return`local:${this.resolvePathFromBase(s.path,n)}`}buildNoMatchingPackageMessage(t,e){const s=this.findSuggestedConfiguredSource(t,e);return s?`No matching package found for ${t}. Did you mean ${s}?`:`No matching package found for ${t}`}findSuggestedConfiguredSource(t,e){const s=t.trim(),n=new Set;for(const r of e){const i=this.getPackageSourceString(r),o=this.parseSource(i);if(o.type==="npm"){(s===o.name||s===o.spec)&&n.add(i);continue}if(o.type==="git"){const a=`${o.host}/${o.path}`,l=o.ref?`${a}@${o.ref}`:void 0;(s===a||l&&s===l)&&n.add(i)}}return n.values().next().value}packageSourcesMatch(t,e,s){const n=this.getSourceMatchKeyForSettings(this.getPackageSourceString(t),s),r=this.getSourceMatchKeyForInput(e);return n===r}normalizePackageSourceForSettings(t,e){const s=this.parseSource(t);if(s.type!=="local")return t;const n=this.getBaseDirForScope(e),r=this.resolvePath(s.path);return w(n,r)||"."}parseSource(t){if(t.startsWith("npm:")){const s=t.slice(4).trim(),{name:n,version:r}=this.parseNpmSpec(s);return{type:"npm",spec:s,name:n,pinned:!!r}}if(wt(t))return{type:"local",path:t};const e=yt(t);return e||{type:"local",path:t}}async installedNpmMatchesPinnedVersion(t,e){const s=this.getInstalledNpmVersion(e);if(!s)return!1;const{version:n}=this.parseNpmSpec(t.spec);return n?s===n:!0}async npmHasAvailableUpdate(t,e){if(C())return!1;const s=this.getInstalledNpmVersion(e);if(!s)return!1;try{return await this.getLatestNpmVersion(t.name)!==s}catch{return!1}}getInstalledNpmVersion(t){const e=p(t,"package.json");if(m(e))try{const s=I(e,"utf-8");return JSON.parse(s).version}catch{return}}async getLatestNpmVersion(t){const e=this.getNpmCommand(),n=(await this.runCommandCapture(e.command,[...e.args,"view",t,"version","--json"],{cwd:this.cwd,timeoutMs:S})).trim();if(!n)throw new Error("Empty response from npm view");return JSON.parse(n)}async gitHasAvailableUpdate(t){if(C())return!1;try{const e=await this.runCommandCapture("git",["rev-parse","HEAD"],{cwd:t,timeoutMs:S}),s=await this.getRemoteGitHead(t);return e.trim()!==s.trim()}catch{return!1}}async getRemoteGitHead(t){const e=await this.getGitUpstreamRef(t);if(e){const i=(await this.runGitRemoteCommand(t,["ls-remote","origin",e])).match(/^([0-9a-f]{40})\s+/m);if(i?.[1])return i[1]}const n=(await this.runGitRemoteCommand(t,["ls-remote","origin","HEAD"])).match(/^([0-9a-f]{40})\s+HEAD$/m);if(!n?.[1])throw new Error("Failed to determine remote HEAD");return n[1]}async getLocalGitUpdateTarget(t){try{const s=(await this.runCommandCapture("git",["rev-parse","--abbrev-ref","@{upstream}"],{cwd:t,timeoutMs:S})).trim();if(!s.startsWith("origin/"))throw new Error(`Unsupported upstream remote: ${s}`);const n=s.slice(7);if(!n)throw new Error("Missing upstream branch name");return{ref:"@{upstream}",head:await this.runCommandCapture("git",["rev-parse","@{upstream}"],{cwd:t,timeoutMs:S}),fetchArgs:["fetch","--prune","--no-tags","origin",`+refs/heads/${n}:refs/remotes/origin/${n}`]}}catch{await this.runCommand("git",["remote","set-head","origin","-a"],{cwd:t}).catch(()=>{});const e=await this.runCommandCapture("git",["rev-parse","origin/HEAD"],{cwd:t,timeoutMs:S}),n=(await this.runCommandCapture("git",["symbolic-ref","refs/remotes/origin/HEAD"],{cwd:t,timeoutMs:S}).catch(()=>"")).trim().replace(/^refs\/remotes\/origin\//,"");return n?{ref:"origin/HEAD",head:e,fetchArgs:["fetch","--prune","--no-tags","origin",`+refs/heads/${n}:refs/remotes/origin/${n}`]}:{ref:"origin/HEAD",head:e,fetchArgs:["fetch","--prune","--no-tags","origin","+HEAD:refs/remotes/origin/HEAD"]}}}async getGitUpstreamRef(t){try{const s=(await this.runCommandCapture("git",["rev-parse","--abbrev-ref","@{upstream}"],{cwd:t,timeoutMs:S})).trim();if(!s.startsWith("origin/"))return;const n=s.slice(7);return n?`refs/heads/${n}`:void 0}catch{return}}runGitRemoteCommand(t,e){return this.runCommandCapture("git",e,{cwd:t,timeoutMs:S,env:{GIT_TERMINAL_PROMPT:"0"}})}async runWithConcurrency(t,e){if(t.length===0)return[];const s=new Array(t.length);let n=0;const r=Math.max(1,Math.min(e,t.length)),i=f(async()=>{for(;;){const o=n;if(n+=1,o>=t.length)return;s[o]=await t[o]()}},"worker");return await Promise.all(Array.from({length:r},()=>i())),s}getPackageIdentity(t,e){const s=this.parseSource(t);if(s.type==="npm")return`npm:${s.name}`;if(s.type==="git")return`git:${s.host}/${s.path}`;if(e){const n=this.getBaseDirForScope(e);return`local:${this.resolvePathFromBase(s.path,n)}`}return`local:${this.resolvePath(s.path)}`}dedupePackages(t){const e=new Map;for(const s of t){const n=typeof s.pkg=="string"?s.pkg:s.pkg.source,r=this.getPackageIdentity(n,s.scope),i=e.get(r);i?s.scope==="project"&&i.scope==="user"&&e.set(r,s):e.set(r,s)}return Array.from(e.values())}parseNpmSpec(t){const e=t.match(/^(@?[^@]+(?:\/[^@]+)?)(?:@(.+))?$/);if(!e)return{name:t};const s=e[1]??t,n=e[2];return{name:s,version:n}}getNpmCommand(){const t=this.settingsManager.getNpmCommand();if(!t||t.length===0)return{command:"npm",args:[]};const[e,...s]=t;if(!e)throw new Error("Invalid npmCommand: first array entry must be a non-empty command");return{command:e,args:s}}getPackageManagerName(){const t=this.getNpmCommand(),e=[t.command,...t.args],s=e.lastIndexOf("--"),n=s>=0?e[s+1]:t.command;return n?G(n).replace(/\.(cmd|exe)$/i,""):""}async runNpmCommand(t,e){const s=this.getNpmCommand();await this.runCommand(s.command,[...s.args,...t],e)}getGitDependencyInstallArgs(){const t=this.settingsManager.getNpmCommand();return t&&t.length>0?["install"]:["install","--omit=dev"]}runNpmCommandSync(t){const e=this.getNpmCommand();return this.runCommandSync(e.command,[...e.args,...t])}getNpmInstallArgs(t,e){const s=this.getPackageManagerName();return s==="bun"?["install",...t,"--cwd",e,"--omit=peer"]:s==="pnpm"?["install",...t,"--prefix",e,"--config.auto-install-peers=false","--config.strict-peer-dependencies=false","--config.strict-dep-builds=false"]:["install",...t,"--prefix",e,"--legacy-peer-deps"]}async installNpm(t,e,s){const n=this.getNpmInstallRoot(e,s);this.ensureNpmProject(n),await this.runNpmCommand(this.getNpmInstallArgs([t.spec],n))}async uninstallNpm(t,e){const s=this.getNpmInstallRoot(e,!1);if(m(s)){if(this.getPackageManagerName()==="bun"){await this.runNpmCommand(["uninstall",t.name,"--cwd",s]);return}await this.runNpmCommand(["uninstall",t.name,"--prefix",s])}}async installGit(t,e){const s=this.getGitInstallPath(t,e);if(m(s)){if(t.ref){await this.ensureGitRef(s,["fetch","origin",t.ref],"FETCH_HEAD");return}const i=await this.getLocalGitUpdateTarget(s);await this.ensureGitRef(s,i.fetchArgs,i.ref);return}const n=this.getGitInstallRoot(e);n&&this.ensureGitIgnore(n),O(P(s),{recursive:!0}),await this.runCommand("git",["clone",t.repo,s]),t.ref&&await this.runCommand("git",["checkout",t.ref],{cwd:s});const r=p(s,"package.json");m(r)&&await this.runNpmCommand(this.getGitDependencyInstallArgs(),{cwd:s})}async updateGit(t,e){const s=this.getGitInstallPath(t,e);if(!m(s)){await this.installGit(t,e);return}if(t.ref){await this.ensureGitRef(s,["fetch","origin",t.ref],"FETCH_HEAD");return}const n=await this.getLocalGitUpdateTarget(s);await this.ensureGitRef(s,n.fetchArgs,n.ref)}async ensureGitRef(t,e,s){await this.runCommand("git",e,{cwd:t});const n=await this.runCommandCapture("git",["rev-parse","HEAD"],{cwd:t,timeoutMs:S}),r=`${s}^{commit}`,i=await this.runCommandCapture("git",["rev-parse",r],{cwd:t,timeoutMs:S});if(n.trim()===i.trim())return;await this.runCommand("git",["reset","--hard",r],{cwd:t}),await this.runCommand("git",["clean","-fdx"],{cwd:t});const o=p(t,"package.json");m(o)&&await this.runNpmCommand(this.getGitDependencyInstallArgs(),{cwd:t})}async refreshTemporaryGitSource(t,e){if(!C())try{await this.withProgress("pull",e,`Refreshing ${e}...`,async()=>{await this.updateGit(t,"temporary")})}catch{}}async removeGit(t,e){const s=this.getGitInstallPath(t,e);m(s)&&(q(s,{recursive:!0,force:!0}),this.pruneEmptyGitParents(s,this.getGitInstallRoot(e)))}pruneEmptyGitParents(t,e){if(!e)return;const s=N(e);let n=P(t);for(;n.startsWith(s)&&n!==s;){if(!m(n)){n=P(n);continue}if(E(n).length>0)break;try{q(n,{recursive:!0,force:!0})}catch{break}n=P(n)}}ensureNpmProject(t){m(t)||O(t,{recursive:!0}),kt(t),this.ensureGitIgnore(t);const e=p(t,"package.json");m(e)||Q(e,JSON.stringify({name:"pi-extensions",private:!0},null,2),"utf-8")}ensureGitIgnore(t){m(t)||O(t,{recursive:!0});const e=p(t,".gitignore");m(e)||Q(e,`*
2
+ !.gitignore
3
+ `,"utf-8")}getNpmInstallRoot(t,e){return e?this.getTemporaryDir("npm"):t==="project"?p(this.cwd,b,"npm"):p(this.agentDir,"npm")}getGlobalNpmRoot(){const t=this.getNpmCommand(),e=[t.command,...t.args].join("\0");if(this.globalNpmRoot&&this.globalNpmRootCommandKey===e)return this.globalNpmRoot;if(this.getPackageManagerName()==="bun"){const s=this.runNpmCommandSync(["pm","bin","-g"]).trim();this.globalNpmRoot=p(P(s),"install","global","node_modules")}else this.globalNpmRoot=this.runNpmCommandSync(["root","-g"]).trim();return this.globalNpmRootCommandKey=e,this.globalNpmRoot}getPnpmGlobalPackagePath(t){if(this.getPackageManagerName()!=="pnpm")return;const e=this.runNpmCommandSync(["list","-g","--depth","0","--json"]),s=JSON.parse(e);for(const n of s){const r=n.dependencies?.[t]?.path;if(r)return r}}getManagedNpmInstallPath(t,e){return e==="temporary"?p(this.getTemporaryDir("npm"),"node_modules",t.name):e==="project"?p(this.cwd,b,"npm","node_modules",t.name):p(this.agentDir,"npm","node_modules",t.name)}getLegacyGlobalNpmInstallPath(t){try{return this.getPnpmGlobalPackagePath(t.name)??p(this.getGlobalNpmRoot(),t.name)}catch{return}}getNpmInstallPath(t,e){const s=this.getManagedNpmInstallPath(t,e);if(e!=="user"||m(s))return s;const n=this.getLegacyGlobalNpmInstallPath(t);return n&&m(n)?n:s}getGitInstallPath(t,e){return e==="temporary"?this.getTemporaryDir(`git-${t.host}`,t.path):e==="project"?p(this.cwd,b,"git",t.host,t.path):p(this.agentDir,"git",t.host,t.path)}getGitInstallRoot(t){if(t!=="temporary")return t==="project"?p(this.cwd,b,"git"):p(this.agentDir,"git")}getTemporaryDir(t,e){const s=ht("sha256").update(`${t}-${e??""}`).digest("hex").slice(0,8);return p(mt(),"pi-extensions",t,s,e??"")}getBaseDirForScope(t){return t==="project"?p(this.cwd,b):t==="user"?this.agentDir:this.cwd}resolvePath(t){return A(t,this.cwd,{homeDir:V(),trim:!0})}resolvePathFromBase(t,e){return A(t,e,{homeDir:V(),trim:!0})}collectPackageResources(t,e,s,n){if(s){for(const o of j){const a=s[o],l=this.getTargetMap(e,o);a!==void 0?this.applyPackageFilter(t,a,o,l,n):this.collectDefaultResources(t,o,l,n)}return!0}const r=this.readPiManifest(t);if(r){for(const o of j){const a=r[o];this.addManifestEntries(a,t,o,this.getTargetMap(e,o),n)}return!0}let i=!1;for(const o of j){const a=p(t,o);if(m(a)){const l=T(a,o);for(const h of l)this.addResource(this.getTargetMap(e,o),h,n,!0);i=!0}}return i}collectDefaultResources(t,e,s,n){const i=this.readPiManifest(t)?.[e];if(i){this.addManifestEntries(i,t,e,s,n);return}const o=p(t,e);if(m(o)){const a=T(o,e);for(const l of a)this.addResource(s,l,n,!0)}}applyPackageFilter(t,e,s,n,r){const{allFiles:i}=this.collectManifestFiles(t,s);if(e.length===0){for(const a of i)this.addResource(n,a,r,!1);return}const o=H(i,e,t);for(const a of i){const l=o.has(a);this.addResource(n,a,r,l)}}collectManifestFiles(t,e){const n=this.readPiManifest(t)?.[e];if(n&&n.length>0){const o=this.collectFilesFromManifestEntries(n,t,e),a=n.filter(B),l=a.length>0?H(o,a,t):new Set(o);return{allFiles:Array.from(l),enabledByManifest:l}}const r=p(t,e);if(!m(r))return{allFiles:[],enabledByManifest:new Set};const i=T(r,e);return{allFiles:i,enabledByManifest:new Set(i)}}readPiManifest(t){const e=p(t,"package.json");if(!m(e))return null;try{const s=I(e,"utf-8");return JSON.parse(s).pi??null}catch{return null}}addManifestEntries(t,e,s,n,r){if(!t)return;const i=this.collectFilesFromManifestEntries(t,e,s),o=t.filter(B),a=H(i,o,e);for(const l of i)a.has(l)&&this.addResource(n,l,r,!0)}collectFilesFromManifestEntries(t,e,s){const r=t.filter(i=>!B(i)).flatMap(i=>Ft(i)?gt(i,{cwd:e,absolute:!0,dot:!1,nodir:!1}).map(o=>N(o)):[N(e,i)]);return this.collectFilesFromPaths(r,s)}resolveLocalEntries(t,e,s,n,r){if(t.length===0)return;const{plain:i,patterns:o}=bt(t),a=i.map(u=>this.resolvePathFromBase(u,r)),l=this.collectFilesFromPaths(a,e),h=H(l,o,r);for(const u of l)this.addResource(s,u,n,h.has(u))}addAutoDiscoveredResources(t,e,s,n,r){const i={source:"auto",scope:"user",origin:"top-level",baseDir:n},o={source:"auto",scope:"project",origin:"top-level",baseDir:r},a={extensions:e.extensions??[],skills:e.skills??[],prompts:e.prompts??[],themes:e.themes??[]},l={extensions:s.extensions??[],skills:s.skills??[],prompts:s.prompts??[],themes:s.themes??[]},h={extensions:p(n,"extensions"),skills:p(n,"skills"),prompts:p(n,"prompts"),themes:p(n,"themes")},u={extensions:p(r,"extensions"),skills:p(r,"skills"),prompts:p(r,"prompts"),themes:p(r,"themes")},g=p(V(),".agents","skills"),k=It(this.cwd).filter(M=>N(M)!==N(g)),y=f((M,D,L,ot,at)=>{const ct=this.getTargetMap(t,M);for(const Y of D){const lt=Gt(Y,ot,at);this.addResource(ct,Y,L,lt)}},"addResources");y("extensions",K(u.extensions),o,l.extensions,r),y("skills",W(u.skills,"pi"),o,l.skills,r);for(const M of k){const D=P(M),L={...o,baseDir:D};y("skills",W(M,"agents"),L,l.skills,D)}y("prompts",st(u.prompts),o,l.prompts,r),y("themes",nt(u.themes),o,l.themes,r),y("extensions",K(h.extensions),i,a.extensions,n),y("skills",W(h.skills,"pi"),i,a.skills,n);const x=P(g),it={...i,baseDir:x};y("skills",W(g,"agents"),it,a.skills,x),y("prompts",st(h.prompts),i,a.prompts,n),y("themes",nt(h.themes),i,a.themes,n)}collectFilesFromPaths(t,e){const s=[];for(const n of t)if(m(n))try{const r=v(n);r.isFile()?s.push(n):r.isDirectory()&&s.push(...T(n,e))}catch{}return s}getTargetMap(t,e){switch(e){case"extensions":return t.extensions;case"skills":return t.skills;case"prompts":return t.prompts;case"themes":return t.themes;default:throw new Error(`Unknown resource type: ${e}`)}}addResource(t,e,s,n){e&&(t.has(e)||t.set(e,{metadata:s,enabled:n}))}createAccumulator(){return{extensions:new Map,skills:new Map,prompts:new Map,themes:new Map}}toResolvedPaths(t){const e=f(s=>{const n=Array.from(s.entries()).map(([i,{metadata:o,enabled:a}])=>({path:i,enabled:a,metadata:o}));n.sort((i,o)=>tt(i.metadata)-tt(o.metadata));const r=new Set;return n.filter(i=>{const o=Pt(i.path);return r.has(o)?!1:(r.add(o),!0)})},"mapToResolved");return{extensions:e(t.extensions),skills:e(t.skills),prompts:e(t.prompts),themes:e(t.themes)}}spawnCommand(t,e,s){const n=_();return X(t,e,{cwd:s?.cwd,stdio:St()?["ignore",2,2]:"inherit",env:n})}spawnCaptureCommand(t,e,s){const n=_(),r=s?.env?{...n,...s.env}:n;return X(t,e,{cwd:s?.cwd,stdio:["ignore","pipe","pipe"],env:r})}runCommandCapture(t,e,s){return new Promise((n,r)=>{const i=this.spawnCaptureCommand(t,e,s);let o="",a="",l=!1;const h=typeof s?.timeoutMs=="number"?setTimeout(()=>{l=!0,i.kill()},s.timeoutMs):void 0;i.stdout?.on("data",u=>{o+=u.toString()}),i.stderr?.on("data",u=>{a+=u.toString()}),i.once("error",u=>{h&&clearTimeout(h),r(u)}),i.once("close",(u,g)=>{if(h&&clearTimeout(h),l){r(new Error(`${t} ${e.join(" ")} timed out after ${s?.timeoutMs}ms`));return}if(u===0){n(o.trim());return}const k=u===null?`signal ${g??"unknown"}`:`code ${u}`;r(new Error(`${t} ${e.join(" ")} failed with ${k}: ${a||o}`))})})}runCommand(t,e,s){return new Promise((n,r)=>{const i=this.spawnCommand(t,e,s);i.on("error",r),i.on("exit",o=>{o===0?n():r(new Error(`${t} ${e.join(" ")} failed with code ${o}`))})})}runCommandSync(t,e){const s=_(),n=dt(t,e,{stdio:["ignore","pipe","pipe"],encoding:"utf-8",env:s});if(n.error||n.status!==0)throw new Error(`Failed to run ${t} ${e.join(" ")}: ${n.error?.message||n.stderr||n.stdout}`);return(n.stdout||n.stderr||"").trim()}}export{zt as DefaultPackageManager};