@averyyy/pi-coding-agent 0.85.1-piclient.9 → 0.86.1-piclient.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/CHANGELOG.md +109 -0
  2. package/README.md +3 -1
  3. package/dist/bundle/chunks/anthropic-messages-MYU5ZMRF.js +6 -0
  4. package/dist/bundle/chunks/azure-openai-responses-QJ7SPP5M.js +2 -0
  5. package/dist/bundle/chunks/bedrock-converse-stream.js +47 -38
  6. package/dist/bundle/chunks/chunk-7L6OAVKC.js +1663 -0
  7. package/dist/bundle/chunks/chunk-A3JYRWB6.js +2 -0
  8. package/dist/bundle/chunks/chunk-DTD7JQ7Y.js +42 -0
  9. package/dist/bundle/chunks/chunk-FUXEF6JQ.js +44 -0
  10. package/dist/bundle/chunks/{chunk-IDDQWTHI.js → chunk-RCZIEVGO.js} +10 -1
  11. package/dist/bundle/chunks/chunk-S7SZN6Z3.js +2 -0
  12. package/dist/bundle/chunks/chunk-UZNGGY6N.js +11 -0
  13. package/dist/bundle/chunks/chunk-XREANBOX.js +2 -0
  14. package/dist/bundle/chunks/devin-runtime.js +7 -2
  15. package/dist/bundle/chunks/github-copilot.js +1 -1
  16. package/dist/bundle/chunks/google-generative-ai-IMS5EK2Y.js +2 -0
  17. package/dist/bundle/chunks/google-vertex-O4YJEQUW.js +2 -0
  18. package/dist/bundle/chunks/jiti-loader-C3NU2SDH.js +21 -0
  19. package/dist/bundle/chunks/jiti-static-loader-E6ANQD5T.js +2 -0
  20. package/dist/bundle/chunks/meta.js +2 -0
  21. package/dist/bundle/chunks/mistral-conversations-NOSQHBEY.js +5 -0
  22. package/dist/bundle/chunks/{node-KG362ECQ.js → node-O3RIBJRH.js} +1 -1
  23. package/dist/bundle/chunks/openai-codex-responses-SG7PGUUZ.js +10 -0
  24. package/dist/bundle/chunks/openai-completions-CYGM3XXP.js +7 -0
  25. package/dist/bundle/chunks/openai-responses-AH7QTG23.js +2 -0
  26. package/dist/bundle/chunks/{pi-messages-PML4SPVJ.js → pi-messages-GFKBWJHZ.js} +1 -1
  27. package/dist/bundle/chunks/virtual-modules-SC5AFIK5.js +2 -0
  28. package/dist/bundle/cli-runtime.js +3 -0
  29. package/dist/bundle/cli.js +4 -2
  30. package/dist/bundle/index.js +1 -1
  31. package/dist/bundle/rpc-entry.js +1 -1
  32. package/dist/cli/args.d.ts.map +1 -1
  33. package/dist/cli/args.js +1 -0
  34. package/dist/cli/args.js.map +1 -1
  35. package/dist/cli/session-picker.d.ts +1 -1
  36. package/dist/cli/session-picker.d.ts.map +1 -1
  37. package/dist/cli/session-picker.js.map +1 -1
  38. package/dist/config.d.ts.map +1 -1
  39. package/dist/config.js +1 -1
  40. package/dist/config.js.map +1 -1
  41. package/dist/core/agent-session.d.ts +56 -6
  42. package/dist/core/agent-session.d.ts.map +1 -1
  43. package/dist/core/agent-session.js +362 -183
  44. package/dist/core/agent-session.js.map +1 -1
  45. package/dist/core/bug-report-upload.d.ts +12 -0
  46. package/dist/core/bug-report-upload.d.ts.map +1 -0
  47. package/dist/core/bug-report-upload.js +22 -0
  48. package/dist/core/bug-report-upload.js.map +1 -0
  49. package/dist/core/bug-report.d.ts +176 -0
  50. package/dist/core/bug-report.d.ts.map +1 -0
  51. package/dist/core/bug-report.js +292 -0
  52. package/dist/core/bug-report.js.map +1 -0
  53. package/dist/core/cache-stats.d.ts.map +1 -1
  54. package/dist/core/cache-stats.js +12 -1
  55. package/dist/core/cache-stats.js.map +1 -1
  56. package/dist/core/cache-warmer.d.ts +102 -0
  57. package/dist/core/cache-warmer.d.ts.map +1 -0
  58. package/dist/core/cache-warmer.js +342 -0
  59. package/dist/core/cache-warmer.js.map +1 -0
  60. package/dist/core/compaction/compaction.d.ts +2 -2
  61. package/dist/core/compaction/compaction.d.ts.map +1 -1
  62. package/dist/core/compaction/compaction.js +23 -18
  63. package/dist/core/compaction/compaction.js.map +1 -1
  64. package/dist/core/crash-log.d.ts +22 -0
  65. package/dist/core/crash-log.d.ts.map +1 -0
  66. package/dist/core/crash-log.js +71 -0
  67. package/dist/core/crash-log.js.map +1 -0
  68. package/dist/core/experimental.d.ts +0 -4
  69. package/dist/core/experimental.d.ts.map +1 -1
  70. package/dist/core/experimental.js +0 -4
  71. package/dist/core/experimental.js.map +1 -1
  72. package/dist/core/extensions/index.d.ts +1 -1
  73. package/dist/core/extensions/index.d.ts.map +1 -1
  74. package/dist/core/extensions/index.js.map +1 -1
  75. package/dist/core/extensions/jiti-loader.d.ts +2 -0
  76. package/dist/core/extensions/jiti-loader.d.ts.map +1 -0
  77. package/dist/core/extensions/jiti-loader.js +4 -0
  78. package/dist/core/extensions/jiti-loader.js.map +1 -0
  79. package/dist/core/extensions/jiti-static-loader.d.ts +2 -0
  80. package/dist/core/extensions/jiti-static-loader.d.ts.map +1 -0
  81. package/dist/core/extensions/jiti-static-loader.js +4 -0
  82. package/dist/core/extensions/jiti-static-loader.js.map +1 -0
  83. package/dist/core/extensions/loader.d.ts.map +1 -1
  84. package/dist/core/extensions/loader.js +38 -51
  85. package/dist/core/extensions/loader.js.map +1 -1
  86. package/dist/core/extensions/runner.d.ts +10 -7
  87. package/dist/core/extensions/runner.d.ts.map +1 -1
  88. package/dist/core/extensions/runner.js +85 -67
  89. package/dist/core/extensions/runner.js.map +1 -1
  90. package/dist/core/extensions/types.d.ts +60 -50
  91. package/dist/core/extensions/types.d.ts.map +1 -1
  92. package/dist/core/extensions/types.js.map +1 -1
  93. package/dist/core/extensions/virtual-modules.d.ts +3 -0
  94. package/dist/core/extensions/virtual-modules.d.ts.map +1 -0
  95. package/dist/core/extensions/virtual-modules.js +38 -0
  96. package/dist/core/extensions/virtual-modules.js.map +1 -0
  97. package/dist/core/extensions/wrapper.d.ts.map +1 -1
  98. package/dist/core/extensions/wrapper.js +1 -20
  99. package/dist/core/extensions/wrapper.js.map +1 -1
  100. package/dist/core/index.d.ts +2 -1
  101. package/dist/core/index.d.ts.map +1 -1
  102. package/dist/core/index.js.map +1 -1
  103. package/dist/core/keybindings.d.ts +1 -1
  104. package/dist/core/keybindings.d.ts.map +1 -1
  105. package/dist/core/keybindings.js +1 -1
  106. package/dist/core/keybindings.js.map +1 -1
  107. package/dist/core/messages.d.ts.map +1 -1
  108. package/dist/core/messages.js +1 -0
  109. package/dist/core/messages.js.map +1 -1
  110. package/dist/core/model-config.d.ts +101 -20
  111. package/dist/core/model-config.d.ts.map +1 -1
  112. package/dist/core/model-config.js +25 -18
  113. package/dist/core/model-config.js.map +1 -1
  114. package/dist/core/model-registry.d.ts +5 -1
  115. package/dist/core/model-registry.d.ts.map +1 -1
  116. package/dist/core/model-registry.js +8 -0
  117. package/dist/core/model-registry.js.map +1 -1
  118. package/dist/core/model-resolver.d.ts.map +1 -1
  119. package/dist/core/model-resolver.js +2 -1
  120. package/dist/core/model-resolver.js.map +1 -1
  121. package/dist/core/model-runtime.d.ts.map +1 -1
  122. package/dist/core/model-runtime.js +5 -3
  123. package/dist/core/model-runtime.js.map +1 -1
  124. package/dist/core/provider-composer.d.ts +3 -2
  125. package/dist/core/provider-composer.d.ts.map +1 -1
  126. package/dist/core/provider-composer.js +2 -0
  127. package/dist/core/provider-composer.js.map +1 -1
  128. package/dist/core/radius.d.ts +3 -0
  129. package/dist/core/radius.d.ts.map +1 -1
  130. package/dist/core/radius.js +6 -0
  131. package/dist/core/radius.js.map +1 -1
  132. package/dist/core/sdk.d.ts.map +1 -1
  133. package/dist/core/sdk.js +61 -41
  134. package/dist/core/sdk.js.map +1 -1
  135. package/dist/core/session-export.d.ts +6 -2
  136. package/dist/core/session-export.d.ts.map +1 -1
  137. package/dist/core/session-export.js +14 -13
  138. package/dist/core/session-export.js.map +1 -1
  139. package/dist/core/session-manager.d.ts +29 -6
  140. package/dist/core/session-manager.d.ts.map +1 -1
  141. package/dist/core/session-manager.js +159 -96
  142. package/dist/core/session-manager.js.map +1 -1
  143. package/dist/core/settings-manager.d.ts +20 -4
  144. package/dist/core/settings-manager.d.ts.map +1 -1
  145. package/dist/core/settings-manager.js +43 -7
  146. package/dist/core/settings-manager.js.map +1 -1
  147. package/dist/core/slash-commands.d.ts.map +1 -1
  148. package/dist/core/slash-commands.js +1 -0
  149. package/dist/core/slash-commands.js.map +1 -1
  150. package/dist/core/system-prompt.d.ts +49 -6
  151. package/dist/core/system-prompt.d.ts.map +1 -1
  152. package/dist/core/system-prompt.js +121 -92
  153. package/dist/core/system-prompt.js.map +1 -1
  154. package/dist/core/tools/bash.d.ts +2 -1
  155. package/dist/core/tools/bash.d.ts.map +1 -1
  156. package/dist/core/tools/bash.js +19 -5
  157. package/dist/core/tools/bash.js.map +1 -1
  158. package/dist/core/tools/edit.d.ts.map +1 -1
  159. package/dist/core/tools/edit.js +1 -2
  160. package/dist/core/tools/edit.js.map +1 -1
  161. package/dist/core/tools/read.d.ts.map +1 -1
  162. package/dist/core/tools/read.js +1 -2
  163. package/dist/core/tools/read.js.map +1 -1
  164. package/dist/core/tools/renderers/bash.d.ts.map +1 -1
  165. package/dist/core/tools/renderers/bash.js +9 -1
  166. package/dist/core/tools/renderers/bash.js.map +1 -1
  167. package/dist/core/tools/write.d.ts.map +1 -1
  168. package/dist/core/tools/write.js +1 -2
  169. package/dist/core/tools/write.js.map +1 -1
  170. package/dist/core/usage-totals.d.ts +1 -1
  171. package/dist/core/usage-totals.d.ts.map +1 -1
  172. package/dist/core/usage-totals.js +5 -1
  173. package/dist/core/usage-totals.js.map +1 -1
  174. package/dist/extensions/llama/client.d.ts +2 -0
  175. package/dist/extensions/llama/client.d.ts.map +1 -1
  176. package/dist/extensions/llama/client.js +7 -3
  177. package/dist/extensions/llama/client.js.map +1 -1
  178. package/dist/extensions/llama/provider.d.ts.map +1 -1
  179. package/dist/extensions/llama/provider.js +20 -5
  180. package/dist/extensions/llama/provider.js.map +1 -1
  181. package/dist/index.d.ts +3 -2
  182. package/dist/index.d.ts.map +1 -1
  183. package/dist/index.js.map +1 -1
  184. package/dist/main.d.ts.map +1 -1
  185. package/dist/main.js +13 -9
  186. package/dist/main.js.map +1 -1
  187. package/dist/migrations.d.ts.map +1 -1
  188. package/dist/migrations.js +2 -2
  189. package/dist/migrations.js.map +1 -1
  190. package/dist/modes/interactive/bug-report.d.ts +16 -0
  191. package/dist/modes/interactive/bug-report.d.ts.map +1 -0
  192. package/dist/modes/interactive/bug-report.js +206 -0
  193. package/dist/modes/interactive/bug-report.js.map +1 -0
  194. package/dist/modes/interactive/chat-viewport.d.ts.map +1 -1
  195. package/dist/modes/interactive/chat-viewport.js +1 -1
  196. package/dist/modes/interactive/chat-viewport.js.map +1 -1
  197. package/dist/modes/interactive/components/branch-summary-message.d.ts.map +1 -1
  198. package/dist/modes/interactive/components/branch-summary-message.js +12 -5
  199. package/dist/modes/interactive/components/branch-summary-message.js.map +1 -1
  200. package/dist/modes/interactive/components/compaction-summary-message.d.ts.map +1 -1
  201. package/dist/modes/interactive/components/compaction-summary-message.js +12 -5
  202. package/dist/modes/interactive/components/compaction-summary-message.js.map +1 -1
  203. package/dist/modes/interactive/components/custom-editor.d.ts +3 -3
  204. package/dist/modes/interactive/components/custom-editor.d.ts.map +1 -1
  205. package/dist/modes/interactive/components/custom-editor.js.map +1 -1
  206. package/dist/modes/interactive/components/extension-editor.d.ts +4 -1
  207. package/dist/modes/interactive/components/extension-editor.d.ts.map +1 -1
  208. package/dist/modes/interactive/components/extension-editor.js +7 -2
  209. package/dist/modes/interactive/components/extension-editor.js.map +1 -1
  210. package/dist/modes/interactive/components/extension-input.d.ts +2 -0
  211. package/dist/modes/interactive/components/extension-input.d.ts.map +1 -1
  212. package/dist/modes/interactive/components/extension-input.js +6 -0
  213. package/dist/modes/interactive/components/extension-input.js.map +1 -1
  214. package/dist/modes/interactive/components/extension-selector.d.ts +1 -0
  215. package/dist/modes/interactive/components/extension-selector.d.ts.map +1 -1
  216. package/dist/modes/interactive/components/extension-selector.js +4 -0
  217. package/dist/modes/interactive/components/extension-selector.js.map +1 -1
  218. package/dist/modes/interactive/components/footer.d.ts.map +1 -1
  219. package/dist/modes/interactive/components/footer.js +4 -1
  220. package/dist/modes/interactive/components/footer.js.map +1 -1
  221. package/dist/modes/interactive/components/session-selector.d.ts +5 -5
  222. package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
  223. package/dist/modes/interactive/components/session-selector.js +74 -48
  224. package/dist/modes/interactive/components/session-selector.js.map +1 -1
  225. package/dist/modes/interactive/components/settings-selector.d.ts +3 -1
  226. package/dist/modes/interactive/components/settings-selector.d.ts.map +1 -1
  227. package/dist/modes/interactive/components/settings-selector.js +11 -0
  228. package/dist/modes/interactive/components/settings-selector.js.map +1 -1
  229. package/dist/modes/interactive/components/skill-invocation-message.d.ts.map +1 -1
  230. package/dist/modes/interactive/components/skill-invocation-message.js +11 -4
  231. package/dist/modes/interactive/components/skill-invocation-message.js.map +1 -1
  232. package/dist/modes/interactive/components/status-indicator.d.ts +2 -2
  233. package/dist/modes/interactive/components/status-indicator.d.ts.map +1 -1
  234. package/dist/modes/interactive/components/status-indicator.js +7 -7
  235. package/dist/modes/interactive/components/status-indicator.js.map +1 -1
  236. package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
  237. package/dist/modes/interactive/components/tool-execution.js +18 -9
  238. package/dist/modes/interactive/components/tool-execution.js.map +1 -1
  239. package/dist/modes/interactive/components/tree-selector.d.ts.map +1 -1
  240. package/dist/modes/interactive/components/tree-selector.js +2 -0
  241. package/dist/modes/interactive/components/tree-selector.js.map +1 -1
  242. package/dist/modes/interactive/interactive-mode.d.ts +15 -2
  243. package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
  244. package/dist/modes/interactive/interactive-mode.js +235 -86
  245. package/dist/modes/interactive/interactive-mode.js.map +1 -1
  246. package/dist/modes/interactive/session-share.d.ts +2 -0
  247. package/dist/modes/interactive/session-share.d.ts.map +1 -1
  248. package/dist/modes/interactive/session-share.js +8 -4
  249. package/dist/modes/interactive/session-share.js.map +1 -1
  250. package/dist/modes/interactive/tui-renderer.d.ts.map +1 -1
  251. package/dist/modes/interactive/tui-renderer.js +2 -2
  252. package/dist/modes/interactive/tui-renderer.js.map +1 -1
  253. package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
  254. package/dist/modes/rpc/rpc-mode.js +2 -2
  255. package/dist/modes/rpc/rpc-mode.js.map +1 -1
  256. package/dist/utils/clipboard-command.d.ts +7 -0
  257. package/dist/utils/clipboard-command.d.ts.map +1 -0
  258. package/dist/utils/clipboard-command.js +45 -0
  259. package/dist/utils/clipboard-command.js.map +1 -0
  260. package/dist/utils/clipboard-image.d.ts.map +1 -1
  261. package/dist/utils/clipboard-image.js +53 -81
  262. package/dist/utils/clipboard-image.js.map +1 -1
  263. package/dist/utils/clipboard.d.ts.map +1 -1
  264. package/dist/utils/clipboard.js +111 -121
  265. package/dist/utils/clipboard.js.map +1 -1
  266. package/dist/utils/wsl.d.ts +3 -0
  267. package/dist/utils/wsl.d.ts.map +1 -0
  268. package/dist/utils/wsl.js +15 -0
  269. package/dist/utils/wsl.js.map +1 -0
  270. package/dist/utils/zip.d.ts +7 -0
  271. package/dist/utils/zip.d.ts.map +1 -0
  272. package/dist/utils/zip.js +60 -0
  273. package/dist/utils/zip.js.map +1 -0
  274. package/docs/compaction.md +39 -13
  275. package/docs/custom-provider.md +22 -13
  276. package/docs/development.md +4 -4
  277. package/docs/docs.json +4 -0
  278. package/docs/environment-variables.md +1 -0
  279. package/docs/extensions.md +57 -43
  280. package/docs/json.md +4 -4
  281. package/docs/models.md +33 -2
  282. package/docs/providers.md +10 -2
  283. package/docs/sdk.md +4 -2
  284. package/docs/security.md +1 -1
  285. package/docs/session-format.md +82 -40
  286. package/docs/sessions.md +27 -0
  287. package/docs/settings.md +60 -1
  288. package/docs/termux.md +0 -1
  289. package/docs/tui.md +2 -2
  290. package/docs/usage.md +1 -0
  291. package/examples/extensions/README.md +0 -1
  292. package/examples/extensions/custom-provider-anthropic/index.ts +18 -12
  293. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  294. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  295. package/examples/extensions/custom-provider-gitlab-duo/index.ts +2 -2
  296. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  297. package/examples/extensions/gondolin/package-lock.json +2 -2
  298. package/examples/extensions/gondolin/package.json +1 -1
  299. package/examples/extensions/prompt-customizer.ts +19 -67
  300. package/examples/extensions/sandbox/package-lock.json +2 -2
  301. package/examples/extensions/sandbox/package.json +1 -1
  302. package/examples/extensions/with-deps/package-lock.json +2 -2
  303. package/examples/extensions/with-deps/package.json +1 -1
  304. package/package.json +17 -23
  305. package/dist/bundle/chunks/anthropic-messages-VWZZOSJQ.js +0 -6
  306. package/dist/bundle/chunks/azure-openai-responses-B467Y57F.js +0 -2
  307. package/dist/bundle/chunks/chunk-6WPJTKUF.js +0 -11
  308. package/dist/bundle/chunks/chunk-AXIIZGTV.js +0 -2
  309. package/dist/bundle/chunks/chunk-CLNPYIDP.js +0 -42
  310. package/dist/bundle/chunks/chunk-GMWCTUPB.js +0 -2
  311. package/dist/bundle/chunks/chunk-ORJJLIYM.js +0 -1648
  312. package/dist/bundle/chunks/chunk-U6ZMQKGD.js +0 -50
  313. package/dist/bundle/chunks/chunk-UAQELI3K.js +0 -2
  314. package/dist/bundle/chunks/google-generative-ai-Q2K7FBDI.js +0 -2
  315. package/dist/bundle/chunks/google-vertex-7UJBF4S7.js +0 -2
  316. package/dist/bundle/chunks/mistral-conversations-4M6BZBX6.js +0 -5
  317. package/dist/bundle/chunks/openai-codex-responses-MERYAUSE.js +0 -10
  318. package/dist/bundle/chunks/openai-completions-EKZT2IH2.js +0 -7
  319. package/dist/bundle/chunks/openai-responses-YZ6M7S4X.js +0 -2
  320. package/dist/utils/clipboard-native.d.ts +0 -11
  321. package/dist/utils/clipboard-native.d.ts.map +0 -1
  322. package/dist/utils/clipboard-native.js +0 -20
  323. package/dist/utils/clipboard-native.js.map +0 -1
  324. package/examples/extensions/kimi-deferred-tools.ts +0 -61
@@ -1 +1 @@
1
- {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../../src/core/tools/renderers/bash.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Presentation for the shell tools.\n *\n * Renderers live apart from the implementation so a process that only displays tool output does not\n * load the execution path or its typebox parameter schema. `bash.ts` spreads these into the shell\n * tool definition, so the tool's public shape is unchanged.\n */\n\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { keyHint } from \"../../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../../extensions/types.ts\";\nimport type { BashToolDetails } from \"../bash.ts\";\nimport { getTextOutput, invalidArgText, str } from \"../render-utils.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize } from \"../truncate.ts\";\n\nconst BASH_PREVIEW_LINES = 5;\nexport const BASH_UPDATE_THROTTLE_MS = 100;\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\nfunction formatDuration(ms: number): string {\n\treturn `${(ms / 1000).toFixed(1)}s`;\n}\nfunction formatShellCall(args: { command?: string; timeout?: number } | undefined, prompt: string): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`${prompt} ${commandDisplay}`)) + timeoutSuffix;\n}\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result as any, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"to expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\n\n/** Shell renderers are shared by bash and powershell, which differ only in the prompt they display. */\nexport function createShellRenderers(prompt: string): Pick<ToolDefinition<any, any>, \"renderCall\" | \"renderResult\"> {\n\treturn {\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatShellCall(args as { command?: string; timeout?: number } | undefined, prompt));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult as any,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n"]}
1
+ {"version":3,"file":"bash.js","sourceRoot":"","sources":["../../../../src/core/tools/renderers/bash.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Presentation for the shell tools.\n *\n * Renderers live apart from the implementation so a process that only displays tool output does not\n * load the execution path or its typebox parameter schema. `bash.ts` spreads these into the shell\n * tool definition, so the tool's public shape is unchanged.\n */\n\nimport { Container, Text, truncateToWidth } from \"@earendil-works/pi-tui\";\nimport { keyHint } from \"../../../modes/interactive/components/keybinding-hints.ts\";\nimport { truncateToVisualLines } from \"../../../modes/interactive/components/visual-truncate.ts\";\nimport { theme } from \"../../../modes/interactive/theme/theme.ts\";\nimport type { ToolDefinition, ToolRenderResultOptions } from \"../../extensions/types.ts\";\nimport type { BashToolDetails } from \"../bash.ts\";\nimport { getTextOutput, invalidArgText, str } from \"../render-utils.ts\";\nimport { DEFAULT_MAX_BYTES, formatSize } from \"../truncate.ts\";\n\nconst BASH_PREVIEW_LINES = 5;\nexport const BASH_UPDATE_THROTTLE_MS = 100;\ntype BashResultRenderState = {\n\tcachedWidth: number | undefined;\n\tcachedLines: string[] | undefined;\n\tcachedSkipped: number | undefined;\n};\nclass BashResultRenderComponent extends Container {\n\tstate: BashResultRenderState = {\n\t\tcachedWidth: undefined,\n\t\tcachedLines: undefined,\n\t\tcachedSkipped: undefined,\n\t};\n}\nfunction formatDuration(ms: number): string {\n\tconst seconds = ms / 1000;\n\tif (seconds < 60) return `${seconds.toFixed(1)}s`;\n\n\tconst totalSeconds = Math.floor(seconds);\n\tconst minutes = Math.floor(totalSeconds / 60);\n\tconst remainder = totalSeconds % 60;\n\tif (minutes < 60) return `${minutes}m ${remainder}s`;\n\n\treturn `${Math.floor(minutes / 60)}h ${minutes % 60}m ${remainder}s`;\n}\nfunction formatShellCall(args: { command?: string; timeout?: number } | undefined, prompt: string): string {\n\tconst command = str(args?.command);\n\tconst timeout = args?.timeout as number | undefined;\n\tconst timeoutSuffix = timeout ? theme.fg(\"muted\", ` (timeout ${timeout}s)`) : \"\";\n\tconst commandDisplay = command === null ? invalidArgText(theme) : command ? command : theme.fg(\"toolOutput\", \"...\");\n\treturn theme.fg(\"toolTitle\", theme.bold(`${prompt} ${commandDisplay}`)) + timeoutSuffix;\n}\nfunction rebuildBashResultRenderComponent(\n\tcomponent: BashResultRenderComponent,\n\tresult: {\n\t\tcontent: Array<{ type: string; text?: string; data?: string; mimeType?: string }>;\n\t\tdetails?: BashToolDetails;\n\t},\n\toptions: ToolRenderResultOptions,\n\tshowImages: boolean,\n\tstartedAt: number | undefined,\n\tendedAt: number | undefined,\n): void {\n\tconst state = component.state;\n\tcomponent.clear();\n\n\tlet output = getTextOutput(result as any, showImages).trim();\n\tconst truncation = result.details?.truncation;\n\tconst fullOutputPath = result.details?.fullOutputPath;\n\tif (!options.isPartial && truncation?.truncated && fullOutputPath && output.endsWith(\"]\")) {\n\t\tconst footerStart = output.lastIndexOf(\"\\n\\n[\");\n\t\tif (footerStart !== -1 && output.slice(footerStart).includes(fullOutputPath)) {\n\t\t\toutput = output.slice(0, footerStart).trimEnd();\n\t\t}\n\t}\n\n\tif (output) {\n\t\tconst styledOutput = output\n\t\t\t.split(\"\\n\")\n\t\t\t.map((line) => theme.fg(\"toolOutput\", line))\n\t\t\t.join(\"\\n\");\n\n\t\tif (options.expanded) {\n\t\t\tcomponent.addChild(new Text(`\\n${styledOutput}`, 0, 0));\n\t\t} else {\n\t\t\tcomponent.addChild({\n\t\t\t\trender: (width: number) => {\n\t\t\t\t\tif (state.cachedLines === undefined || state.cachedWidth !== width) {\n\t\t\t\t\t\tconst preview = truncateToVisualLines(styledOutput, BASH_PREVIEW_LINES, width);\n\t\t\t\t\t\tstate.cachedLines = preview.visualLines;\n\t\t\t\t\t\tstate.cachedSkipped = preview.skippedCount;\n\t\t\t\t\t\tstate.cachedWidth = width;\n\t\t\t\t\t}\n\t\t\t\t\tif (state.cachedSkipped && state.cachedSkipped > 0) {\n\t\t\t\t\t\tconst hint =\n\t\t\t\t\t\t\ttheme.fg(\"muted\", `... (${state.cachedSkipped} earlier lines,`) +\n\t\t\t\t\t\t\t` ${keyHint(\"app.tools.expand\", \"to expand\")}${theme.fg(\"muted\", \")\")}`;\n\t\t\t\t\t\treturn [\"\", truncateToWidth(hint, width, \"...\"), ...(state.cachedLines ?? [])];\n\t\t\t\t\t}\n\t\t\t\t\treturn [\"\", ...(state.cachedLines ?? [])];\n\t\t\t\t},\n\t\t\t\tinvalidate: () => {\n\t\t\t\t\tstate.cachedWidth = undefined;\n\t\t\t\t\tstate.cachedLines = undefined;\n\t\t\t\t\tstate.cachedSkipped = undefined;\n\t\t\t\t},\n\t\t\t});\n\t\t}\n\t}\n\n\tif (truncation?.truncated || fullOutputPath) {\n\t\tconst warnings: string[] = [];\n\t\tif (fullOutputPath) {\n\t\t\twarnings.push(`Full output: ${fullOutputPath}`);\n\t\t}\n\t\tif (truncation?.truncated) {\n\t\t\tif (truncation.truncatedBy === \"lines\") {\n\t\t\t\twarnings.push(`Truncated: showing ${truncation.outputLines} of ${truncation.totalLines} lines`);\n\t\t\t} else {\n\t\t\t\twarnings.push(\n\t\t\t\t\t`Truncated: ${truncation.outputLines} lines shown (${formatSize(truncation.maxBytes ?? DEFAULT_MAX_BYTES)} limit)`,\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"warning\", `[${warnings.join(\". \")}]`)}`, 0, 0));\n\t}\n\n\tif (startedAt !== undefined) {\n\t\tconst label = options.isPartial ? \"Elapsed\" : \"Took\";\n\t\tconst endTime = endedAt ?? Date.now();\n\t\tcomponent.addChild(new Text(`\\n${theme.fg(\"muted\", `${label} ${formatDuration(endTime - startedAt)}`)}`, 0, 0));\n\t}\n}\n\n/** Shell renderers are shared by bash and powershell, which differ only in the prompt they display. */\nexport function createShellRenderers(prompt: string): Pick<ToolDefinition<any, any>, \"renderCall\" | \"renderResult\"> {\n\treturn {\n\t\trenderCall(args, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (context.executionStarted && state.startedAt === undefined) {\n\t\t\t\tstate.startedAt = Date.now();\n\t\t\t\tstate.endedAt = undefined;\n\t\t\t}\n\t\t\tconst text = (context.lastComponent as Text | undefined) ?? new Text(\"\", 0, 0);\n\t\t\ttext.setText(formatShellCall(args as { command?: string; timeout?: number } | undefined, prompt));\n\t\t\treturn text;\n\t\t},\n\t\trenderResult(result, options, _theme, context) {\n\t\t\tconst state = context.state;\n\t\t\tif (state.startedAt !== undefined && options.isPartial && !state.interval) {\n\t\t\t\tstate.interval = setInterval(() => context.invalidate(), 1000);\n\t\t\t}\n\t\t\tif (!options.isPartial || context.isError) {\n\t\t\t\tstate.endedAt ??= Date.now();\n\t\t\t\tif (state.interval) {\n\t\t\t\t\tclearInterval(state.interval);\n\t\t\t\t\tstate.interval = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tconst component =\n\t\t\t\t(context.lastComponent as BashResultRenderComponent | undefined) ?? new BashResultRenderComponent();\n\t\t\trebuildBashResultRenderComponent(\n\t\t\t\tcomponent,\n\t\t\t\tresult as any,\n\t\t\t\toptions,\n\t\t\t\tcontext.showImages,\n\t\t\t\tstate.startedAt,\n\t\t\t\tstate.endedAt,\n\t\t\t);\n\t\t\tcomponent.invalidate();\n\t\t\treturn component;\n\t\t},\n\t};\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAE5C,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAM/E,QAAA,MAAM,WAAW;;;EAGf,CAAC;AAEH,eAAO,MAAM,iCAAiC;;;CAGpC,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,mCAAmC;IACnC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAOD,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,UAAU,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,gBAAgB,GACxB,cAAc,CAAC,OAAO,WAAW,EAAE,SAAS,CAAC,CA8C/C;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC,OAAO,WAAW,CAAC,CAEtG","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { mkdir as fsMkdir, writeFile as fsWriteFile } from \"fs/promises\";\nimport { dirname } from \"path\";\nimport { type Static, Type } from \"typebox\";\nimport { getExperimentalToolSampling } from \"../experimental.ts\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\nimport { writeRenderers } from \"./renderers/write.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst writeSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n\tcontent: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport const writeToolSystemPromptContribution = {\n\tsnippet: \"Create or overwrite files\",\n\tguidelines: [\"Use write only for new files or complete rewrites.\"],\n} as const;\n\nexport type WriteToolInput = Static<typeof writeSchema>;\n\n/**\n * Pluggable operations for the write tool.\n * Override these to delegate file writing to remote systems (for example SSH).\n */\nexport interface WriteOperations {\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Create directory recursively */\n\tmkdir: (dir: string) => Promise<void>;\n}\n\nconst defaultWriteOperations: WriteOperations = {\n\twriteFile: (path, content) => fsWriteFile(path, content, \"utf-8\"),\n\tmkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => {}),\n};\n\nexport interface WriteToolOptions {\n\t/** Custom operations for file writing. Default: local filesystem */\n\toperations?: WriteOperations;\n}\n\nexport function createWriteToolDefinition(\n\tcwd: string,\n\toptions?: WriteToolOptions,\n): ToolDefinition<typeof writeSchema, undefined> {\n\tconst ops = options?.operations ?? defaultWriteOperations;\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\tdescription:\n\t\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\t\tpromptSnippet: writeToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...writeToolSystemPromptContribution.guidelines],\n\t\tparameters: writeSchema,\n\t\tconstrainedSampling: getExperimentalToolSampling(),\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ path, content }: { path: string; content: string },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\tctx?: ExtensionContext,\n\t\t) {\n\t\t\tconst absolutePath = resolveToCwd(path, ctx?.cwd || cwd);\n\t\t\tconst dir = dirname(absolutePath);\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t};\n\n\t\t\t\tthrowIfAborted();\n\t\t\t\t// Create parent directories if needed.\n\t\t\t\tawait ops.mkdir(dir);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Write the file contents.\n\t\t\t\tawait ops.writeFile(absolutePath, content);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Successfully wrote to ${path}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\t...writeRenderers,\n\t};\n}\n\nexport function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema> {\n\treturn wrapToolDefinition(createWriteToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"write.d.ts","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,+BAA+B,CAAC;AAG/D,OAAO,EAAE,KAAK,MAAM,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AAC5C,OAAO,KAAK,EAAoB,cAAc,EAAE,MAAM,wBAAwB,CAAC;AAM/E,QAAA,MAAM,WAAW;;;EAGf,CAAC;AAEH,eAAO,MAAM,iCAAiC;;;CAGpC,CAAC;AAEX,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,OAAO,WAAW,CAAC,CAAC;AAExD;;;GAGG;AACH,MAAM,WAAW,eAAe;IAC/B,8BAA8B;IAC9B,SAAS,EAAE,CAAC,YAAY,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,mCAAmC;IACnC,KAAK,EAAE,CAAC,GAAG,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACtC;AAOD,MAAM,WAAW,gBAAgB;IAChC,oEAAoE;IACpE,UAAU,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,wBAAgB,yBAAyB,CACxC,GAAG,EAAE,MAAM,EACX,OAAO,CAAC,EAAE,gBAAgB,GACxB,cAAc,CAAC,OAAO,WAAW,EAAE,SAAS,CAAC,CA8C/C;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,gBAAgB,GAAG,SAAS,CAAC,OAAO,WAAW,CAAC,CAEtG","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { mkdir as fsMkdir, writeFile as fsWriteFile } from \"fs/promises\";\nimport { dirname } from \"path\";\nimport { type Static, Type } from \"typebox\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\nimport { writeRenderers } from \"./renderers/write.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst writeSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n\tcontent: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport const writeToolSystemPromptContribution = {\n\tsnippet: \"Create or overwrite files\",\n\tguidelines: [\"Use write only for new files or complete rewrites.\"],\n} as const;\n\nexport type WriteToolInput = Static<typeof writeSchema>;\n\n/**\n * Pluggable operations for the write tool.\n * Override these to delegate file writing to remote systems (for example SSH).\n */\nexport interface WriteOperations {\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Create directory recursively */\n\tmkdir: (dir: string) => Promise<void>;\n}\n\nconst defaultWriteOperations: WriteOperations = {\n\twriteFile: (path, content) => fsWriteFile(path, content, \"utf-8\"),\n\tmkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => {}),\n};\n\nexport interface WriteToolOptions {\n\t/** Custom operations for file writing. Default: local filesystem */\n\toperations?: WriteOperations;\n}\n\nexport function createWriteToolDefinition(\n\tcwd: string,\n\toptions?: WriteToolOptions,\n): ToolDefinition<typeof writeSchema, undefined> {\n\tconst ops = options?.operations ?? defaultWriteOperations;\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\tdescription:\n\t\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\t\tpromptSnippet: writeToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...writeToolSystemPromptContribution.guidelines],\n\t\tparameters: writeSchema,\n\t\tconstrainedSampling: { type: \"json_schema\", strict: \"prefer\" },\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ path, content }: { path: string; content: string },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\tctx?: ExtensionContext,\n\t\t) {\n\t\t\tconst absolutePath = resolveToCwd(path, ctx?.cwd || cwd);\n\t\t\tconst dir = dirname(absolutePath);\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t};\n\n\t\t\t\tthrowIfAborted();\n\t\t\t\t// Create parent directories if needed.\n\t\t\t\tawait ops.mkdir(dir);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Write the file contents.\n\t\t\t\tawait ops.writeFile(absolutePath, content);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Successfully wrote to ${path}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\t...writeRenderers,\n\t};\n}\n\nexport function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema> {\n\treturn wrapToolDefinition(createWriteToolDefinition(cwd, options));\n}\n"]}
@@ -1,7 +1,6 @@
1
1
  import { mkdir as fsMkdir, writeFile as fsWriteFile } from "fs/promises";
2
2
  import { dirname } from "path";
3
3
  import { Type } from "typebox";
4
- import { getExperimentalToolSampling } from "../experimental.js";
5
4
  import { withFileMutationQueue } from "./file-mutation-queue.js";
6
5
  import { resolveToCwd } from "./path-utils.js";
7
6
  import { writeRenderers } from "./renderers/write.js";
@@ -27,7 +26,7 @@ export function createWriteToolDefinition(cwd, options) {
27
26
  promptSnippet: writeToolSystemPromptContribution.snippet,
28
27
  promptGuidelines: [...writeToolSystemPromptContribution.guidelines],
29
28
  parameters: writeSchema,
30
- constrainedSampling: getExperimentalToolSampling(),
29
+ constrainedSampling: { type: "json_schema", strict: "prefer" },
31
30
  async execute(_toolCallId, { path, content }, signal, _onUpdate, ctx) {
32
31
  const absolutePath = resolveToCwd(path, ctx?.cwd || cwd);
33
32
  const dir = dirname(absolutePath);
@@ -1 +1 @@
1
- {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { mkdir as fsMkdir, writeFile as fsWriteFile } from \"fs/promises\";\nimport { dirname } from \"path\";\nimport { type Static, Type } from \"typebox\";\nimport { getExperimentalToolSampling } from \"../experimental.ts\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\nimport { writeRenderers } from \"./renderers/write.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst writeSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n\tcontent: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport const writeToolSystemPromptContribution = {\n\tsnippet: \"Create or overwrite files\",\n\tguidelines: [\"Use write only for new files or complete rewrites.\"],\n} as const;\n\nexport type WriteToolInput = Static<typeof writeSchema>;\n\n/**\n * Pluggable operations for the write tool.\n * Override these to delegate file writing to remote systems (for example SSH).\n */\nexport interface WriteOperations {\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Create directory recursively */\n\tmkdir: (dir: string) => Promise<void>;\n}\n\nconst defaultWriteOperations: WriteOperations = {\n\twriteFile: (path, content) => fsWriteFile(path, content, \"utf-8\"),\n\tmkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => {}),\n};\n\nexport interface WriteToolOptions {\n\t/** Custom operations for file writing. Default: local filesystem */\n\toperations?: WriteOperations;\n}\n\nexport function createWriteToolDefinition(\n\tcwd: string,\n\toptions?: WriteToolOptions,\n): ToolDefinition<typeof writeSchema, undefined> {\n\tconst ops = options?.operations ?? defaultWriteOperations;\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\tdescription:\n\t\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\t\tpromptSnippet: writeToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...writeToolSystemPromptContribution.guidelines],\n\t\tparameters: writeSchema,\n\t\tconstrainedSampling: getExperimentalToolSampling(),\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ path, content }: { path: string; content: string },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\tctx?: ExtensionContext,\n\t\t) {\n\t\t\tconst absolutePath = resolveToCwd(path, ctx?.cwd || cwd);\n\t\t\tconst dir = dirname(absolutePath);\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t};\n\n\t\t\t\tthrowIfAborted();\n\t\t\t\t// Create parent directories if needed.\n\t\t\t\tawait ops.mkdir(dir);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Write the file contents.\n\t\t\t\tawait ops.writeFile(absolutePath, content);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Successfully wrote to ${path}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\t...writeRenderers,\n\t};\n}\n\nexport function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema> {\n\treturn wrapToolDefinition(createWriteToolDefinition(cwd, options));\n}\n"]}
1
+ {"version":3,"file":"write.js","sourceRoot":"","sources":["../../../src/core/tools/write.ts"],"names":[],"mappings":"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","sourcesContent":["import type { AgentTool } from \"@earendil-works/pi-agent-core\";\nimport { mkdir as fsMkdir, writeFile as fsWriteFile } from \"fs/promises\";\nimport { dirname } from \"path\";\nimport { type Static, Type } from \"typebox\";\nimport type { ExtensionContext, ToolDefinition } from \"../extensions/types.ts\";\nimport { withFileMutationQueue } from \"./file-mutation-queue.ts\";\nimport { resolveToCwd } from \"./path-utils.ts\";\nimport { writeRenderers } from \"./renderers/write.ts\";\nimport { wrapToolDefinition } from \"./tool-definition-wrapper.ts\";\n\nconst writeSchema = Type.Object({\n\tpath: Type.String({ description: \"Path to the file to write (relative or absolute)\" }),\n\tcontent: Type.String({ description: \"Content to write to the file\" }),\n});\n\nexport const writeToolSystemPromptContribution = {\n\tsnippet: \"Create or overwrite files\",\n\tguidelines: [\"Use write only for new files or complete rewrites.\"],\n} as const;\n\nexport type WriteToolInput = Static<typeof writeSchema>;\n\n/**\n * Pluggable operations for the write tool.\n * Override these to delegate file writing to remote systems (for example SSH).\n */\nexport interface WriteOperations {\n\t/** Write content to a file */\n\twriteFile: (absolutePath: string, content: string) => Promise<void>;\n\t/** Create directory recursively */\n\tmkdir: (dir: string) => Promise<void>;\n}\n\nconst defaultWriteOperations: WriteOperations = {\n\twriteFile: (path, content) => fsWriteFile(path, content, \"utf-8\"),\n\tmkdir: (dir) => fsMkdir(dir, { recursive: true }).then(() => {}),\n};\n\nexport interface WriteToolOptions {\n\t/** Custom operations for file writing. Default: local filesystem */\n\toperations?: WriteOperations;\n}\n\nexport function createWriteToolDefinition(\n\tcwd: string,\n\toptions?: WriteToolOptions,\n): ToolDefinition<typeof writeSchema, undefined> {\n\tconst ops = options?.operations ?? defaultWriteOperations;\n\treturn {\n\t\tname: \"write\",\n\t\tlabel: \"write\",\n\t\tdescription:\n\t\t\t\"Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.\",\n\t\tpromptSnippet: writeToolSystemPromptContribution.snippet,\n\t\tpromptGuidelines: [...writeToolSystemPromptContribution.guidelines],\n\t\tparameters: writeSchema,\n\t\tconstrainedSampling: { type: \"json_schema\", strict: \"prefer\" },\n\t\tasync execute(\n\t\t\t_toolCallId,\n\t\t\t{ path, content }: { path: string; content: string },\n\t\t\tsignal?: AbortSignal,\n\t\t\t_onUpdate?,\n\t\t\tctx?: ExtensionContext,\n\t\t) {\n\t\t\tconst absolutePath = resolveToCwd(path, ctx?.cwd || cwd);\n\t\t\tconst dir = dirname(absolutePath);\n\t\t\treturn withFileMutationQueue(absolutePath, async () => {\n\t\t\t\t// Do not reject from an abort event listener here: that would release the\n\t\t\t\t// mutation queue while an in-flight filesystem operation may still finish.\n\t\t\t\t// Checking signal.aborted after each await observes the same aborts while\n\t\t\t\t// keeping the queue locked until the current operation has settled.\n\t\t\t\tconst throwIfAborted = (): void => {\n\t\t\t\t\tif (signal?.aborted) throw new Error(\"Operation aborted\");\n\t\t\t\t};\n\n\t\t\t\tthrowIfAborted();\n\t\t\t\t// Create parent directories if needed.\n\t\t\t\tawait ops.mkdir(dir);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\t// Write the file contents.\n\t\t\t\tawait ops.writeFile(absolutePath, content);\n\t\t\t\tthrowIfAborted();\n\n\t\t\t\treturn {\n\t\t\t\t\tcontent: [{ type: \"text\", text: `Successfully wrote to ${path}` }],\n\t\t\t\t\tdetails: undefined,\n\t\t\t\t};\n\t\t\t});\n\t\t},\n\t\t...writeRenderers,\n\t};\n}\n\nexport function createWriteTool(cwd: string, options?: WriteToolOptions): AgentTool<typeof writeSchema> {\n\treturn wrapToolDefinition(createWriteToolDefinition(cwd, options));\n}\n"]}
@@ -14,6 +14,6 @@ export interface UsageCostBreakdownEntry {
14
14
  cost: number;
15
15
  tokens: number;
16
16
  }
17
- /** Group attributable assistant usage by model and all other usage into a separate bucket. */
17
+ /** Group model-attributed usage by model and all other usage into a separate bucket. */
18
18
  export declare function getUsageCostBreakdown(entries: SessionEntry[]): UsageCostBreakdownEntry[];
19
19
  //# sourceMappingURL=usage-totals.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"usage-totals.d.ts","sourceRoot":"","sources":["../../src/core/usage-totals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CAQ/C;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAMxE;AAED,MAAM,WAAW,uBAAuB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CACf;AAED,8FAA8F;AAC9F,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,uBAAuB,EAAE,CAiCxF","sourcesContent":["import type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { SessionEntry } from \"./session-manager.ts\";\n\nexport interface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\tcost: number;\n}\n\nexport function createUsageTotals(): UsageTotals {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\tcost: 0,\n\t};\n}\n\nexport function addUsageToTotals(totals: UsageTotals, usage: Usage): void {\n\ttotals.input += usage.input;\n\ttotals.output += usage.output;\n\ttotals.cacheRead += usage.cacheRead;\n\ttotals.cacheWrite += usage.cacheWrite;\n\ttotals.cost += usage.cost.total;\n}\n\nexport interface UsageCostBreakdownEntry {\n\tkey: string;\n\tcost: number;\n\ttokens: number;\n}\n\n/** Group attributable assistant usage by model and all other usage into a separate bucket. */\nexport function getUsageCostBreakdown(entries: SessionEntry[]): UsageCostBreakdownEntry[] {\n\tconst totalsByKey = new Map<string, UsageTotals>();\n\n\tfor (const entry of entries) {\n\t\tlet key: string | undefined;\n\t\tlet usage: Usage | undefined;\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\tkey = `${entry.message.provider}/${entry.message.responseModel ?? entry.message.model}`;\n\t\t\tusage = entry.message.usage;\n\t\t} else if (entry.type === \"message\" && entry.message.role === \"toolResult\" && entry.message.usage) {\n\t\t\tkey = \"Tools/summaries\";\n\t\t\tusage = entry.message.usage;\n\t\t} else if ((entry.type === \"branch_summary\" || entry.type === \"compaction\") && entry.usage) {\n\t\t\tkey = \"Tools/summaries\";\n\t\t\tusage = entry.usage;\n\t\t}\n\t\tif (!key || !usage) continue;\n\n\t\tlet totals = totalsByKey.get(key);\n\t\tif (!totals) {\n\t\t\ttotals = createUsageTotals();\n\t\t\ttotalsByKey.set(key, totals);\n\t\t}\n\t\taddUsageToTotals(totals, usage);\n\t}\n\n\treturn Array.from(totalsByKey, ([key, totals]) => ({\n\t\tkey,\n\t\tcost: totals.cost,\n\t\ttokens: totals.input + totals.output + totals.cacheRead + totals.cacheWrite,\n\t}))\n\t\t.filter((entry) => entry.cost > 0 || entry.tokens > 0)\n\t\t.sort((a, b) => b.cost - a.cost);\n}\n"]}
1
+ {"version":3,"file":"usage-totals.d.ts","sourceRoot":"","sources":["../../src/core/usage-totals.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAEzD,MAAM,WAAW,WAAW;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,iBAAiB,IAAI,WAAW,CAQ/C;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,GAAG,IAAI,CAMxE;AAED,MAAM,WAAW,uBAAuB;IACvC,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,MAAM,CAAC;CACf;AAED,wFAAwF;AACxF,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,YAAY,EAAE,GAAG,uBAAuB,EAAE,CAoCxF","sourcesContent":["import type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { SessionEntry } from \"./session-manager.ts\";\n\nexport interface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\tcost: number;\n}\n\nexport function createUsageTotals(): UsageTotals {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\tcost: 0,\n\t};\n}\n\nexport function addUsageToTotals(totals: UsageTotals, usage: Usage): void {\n\ttotals.input += usage.input;\n\ttotals.output += usage.output;\n\ttotals.cacheRead += usage.cacheRead;\n\ttotals.cacheWrite += usage.cacheWrite;\n\ttotals.cost += usage.cost.total;\n}\n\nexport interface UsageCostBreakdownEntry {\n\tkey: string;\n\tcost: number;\n\ttokens: number;\n}\n\n/** Group model-attributed usage by model and all other usage into a separate bucket. */\nexport function getUsageCostBreakdown(entries: SessionEntry[]): UsageCostBreakdownEntry[] {\n\tconst totalsByKey = new Map<string, UsageTotals>();\n\n\tfor (const entry of entries) {\n\t\tlet key: string | undefined;\n\t\tlet usage: Usage | undefined;\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\tkey = `${entry.message.provider}/${entry.message.responseModel ?? entry.message.model}`;\n\t\t\tusage = entry.message.usage;\n\t\t} else if (entry.type === \"usage\") {\n\t\t\tkey = `${entry.provider}/${entry.model}`;\n\t\t\tusage = entry.usage;\n\t\t} else if (entry.type === \"message\" && entry.message.role === \"toolResult\" && entry.message.usage) {\n\t\t\tkey = \"Tools/summaries\";\n\t\t\tusage = entry.message.usage;\n\t\t} else if ((entry.type === \"branch_summary\" || entry.type === \"compaction\") && entry.usage) {\n\t\t\tkey = \"Tools/summaries\";\n\t\t\tusage = entry.usage;\n\t\t}\n\t\tif (!key || !usage) continue;\n\n\t\tlet totals = totalsByKey.get(key);\n\t\tif (!totals) {\n\t\t\ttotals = createUsageTotals();\n\t\t\ttotalsByKey.set(key, totals);\n\t\t}\n\t\taddUsageToTotals(totals, usage);\n\t}\n\n\treturn Array.from(totalsByKey, ([key, totals]) => ({\n\t\tkey,\n\t\tcost: totals.cost,\n\t\ttokens: totals.input + totals.output + totals.cacheRead + totals.cacheWrite,\n\t}))\n\t\t.filter((entry) => entry.cost > 0 || entry.tokens > 0)\n\t\t.sort((a, b) => b.cost - a.cost);\n}\n"]}
@@ -14,7 +14,7 @@ export function addUsageToTotals(totals, usage) {
14
14
  totals.cacheWrite += usage.cacheWrite;
15
15
  totals.cost += usage.cost.total;
16
16
  }
17
- /** Group attributable assistant usage by model and all other usage into a separate bucket. */
17
+ /** Group model-attributed usage by model and all other usage into a separate bucket. */
18
18
  export function getUsageCostBreakdown(entries) {
19
19
  const totalsByKey = new Map();
20
20
  for (const entry of entries) {
@@ -24,6 +24,10 @@ export function getUsageCostBreakdown(entries) {
24
24
  key = `${entry.message.provider}/${entry.message.responseModel ?? entry.message.model}`;
25
25
  usage = entry.message.usage;
26
26
  }
27
+ else if (entry.type === "usage") {
28
+ key = `${entry.provider}/${entry.model}`;
29
+ usage = entry.usage;
30
+ }
27
31
  else if (entry.type === "message" && entry.message.role === "toolResult" && entry.message.usage) {
28
32
  key = "Tools/summaries";
29
33
  usage = entry.message.usage;
@@ -1 +1 @@
1
- {"version":3,"file":"usage-totals.js","sourceRoot":"","sources":["../../src/core/usage-totals.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { SessionEntry } from \"./session-manager.ts\";\n\nexport interface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\tcost: number;\n}\n\nexport function createUsageTotals(): UsageTotals {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\tcost: 0,\n\t};\n}\n\nexport function addUsageToTotals(totals: UsageTotals, usage: Usage): void {\n\ttotals.input += usage.input;\n\ttotals.output += usage.output;\n\ttotals.cacheRead += usage.cacheRead;\n\ttotals.cacheWrite += usage.cacheWrite;\n\ttotals.cost += usage.cost.total;\n}\n\nexport interface UsageCostBreakdownEntry {\n\tkey: string;\n\tcost: number;\n\ttokens: number;\n}\n\n/** Group attributable assistant usage by model and all other usage into a separate bucket. */\nexport function getUsageCostBreakdown(entries: SessionEntry[]): UsageCostBreakdownEntry[] {\n\tconst totalsByKey = new Map<string, UsageTotals>();\n\n\tfor (const entry of entries) {\n\t\tlet key: string | undefined;\n\t\tlet usage: Usage | undefined;\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\tkey = `${entry.message.provider}/${entry.message.responseModel ?? entry.message.model}`;\n\t\t\tusage = entry.message.usage;\n\t\t} else if (entry.type === \"message\" && entry.message.role === \"toolResult\" && entry.message.usage) {\n\t\t\tkey = \"Tools/summaries\";\n\t\t\tusage = entry.message.usage;\n\t\t} else if ((entry.type === \"branch_summary\" || entry.type === \"compaction\") && entry.usage) {\n\t\t\tkey = \"Tools/summaries\";\n\t\t\tusage = entry.usage;\n\t\t}\n\t\tif (!key || !usage) continue;\n\n\t\tlet totals = totalsByKey.get(key);\n\t\tif (!totals) {\n\t\t\ttotals = createUsageTotals();\n\t\t\ttotalsByKey.set(key, totals);\n\t\t}\n\t\taddUsageToTotals(totals, usage);\n\t}\n\n\treturn Array.from(totalsByKey, ([key, totals]) => ({\n\t\tkey,\n\t\tcost: totals.cost,\n\t\ttokens: totals.input + totals.output + totals.cacheRead + totals.cacheWrite,\n\t}))\n\t\t.filter((entry) => entry.cost > 0 || entry.tokens > 0)\n\t\t.sort((a, b) => b.cost - a.cost);\n}\n"]}
1
+ {"version":3,"file":"usage-totals.js","sourceRoot":"","sources":["../../src/core/usage-totals.ts"],"names":[],"mappings":"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","sourcesContent":["import type { Usage } from \"@earendil-works/pi-ai/compat\";\nimport type { SessionEntry } from \"./session-manager.ts\";\n\nexport interface UsageTotals {\n\tinput: number;\n\toutput: number;\n\tcacheRead: number;\n\tcacheWrite: number;\n\tcost: number;\n}\n\nexport function createUsageTotals(): UsageTotals {\n\treturn {\n\t\tinput: 0,\n\t\toutput: 0,\n\t\tcacheRead: 0,\n\t\tcacheWrite: 0,\n\t\tcost: 0,\n\t};\n}\n\nexport function addUsageToTotals(totals: UsageTotals, usage: Usage): void {\n\ttotals.input += usage.input;\n\ttotals.output += usage.output;\n\ttotals.cacheRead += usage.cacheRead;\n\ttotals.cacheWrite += usage.cacheWrite;\n\ttotals.cost += usage.cost.total;\n}\n\nexport interface UsageCostBreakdownEntry {\n\tkey: string;\n\tcost: number;\n\ttokens: number;\n}\n\n/** Group model-attributed usage by model and all other usage into a separate bucket. */\nexport function getUsageCostBreakdown(entries: SessionEntry[]): UsageCostBreakdownEntry[] {\n\tconst totalsByKey = new Map<string, UsageTotals>();\n\n\tfor (const entry of entries) {\n\t\tlet key: string | undefined;\n\t\tlet usage: Usage | undefined;\n\t\tif (entry.type === \"message\" && entry.message.role === \"assistant\") {\n\t\t\tkey = `${entry.message.provider}/${entry.message.responseModel ?? entry.message.model}`;\n\t\t\tusage = entry.message.usage;\n\t\t} else if (entry.type === \"usage\") {\n\t\t\tkey = `${entry.provider}/${entry.model}`;\n\t\t\tusage = entry.usage;\n\t\t} else if (entry.type === \"message\" && entry.message.role === \"toolResult\" && entry.message.usage) {\n\t\t\tkey = \"Tools/summaries\";\n\t\t\tusage = entry.message.usage;\n\t\t} else if ((entry.type === \"branch_summary\" || entry.type === \"compaction\") && entry.usage) {\n\t\t\tkey = \"Tools/summaries\";\n\t\t\tusage = entry.usage;\n\t\t}\n\t\tif (!key || !usage) continue;\n\n\t\tlet totals = totalsByKey.get(key);\n\t\tif (!totals) {\n\t\t\ttotals = createUsageTotals();\n\t\t\ttotalsByKey.set(key, totals);\n\t\t}\n\t\taddUsageToTotals(totals, usage);\n\t}\n\n\treturn Array.from(totalsByKey, ([key, totals]) => ({\n\t\tkey,\n\t\tcost: totals.cost,\n\t\ttokens: totals.input + totals.output + totals.cacheRead + totals.cacheWrite,\n\t}))\n\t\t.filter((entry) => entry.cost > 0 || entry.tokens > 0)\n\t\t.sort((a, b) => b.cost - a.cost);\n}\n"]}
@@ -30,6 +30,7 @@ export interface LlamaModelsResponse {
30
30
  }
31
31
  export interface LlamaServerProps {
32
32
  models_autoload?: boolean;
33
+ chat_template?: string;
33
34
  }
34
35
  export interface LlamaModelEvent {
35
36
  model: string;
@@ -54,6 +55,7 @@ export declare class LlamaClient {
54
55
  signal?: AbortSignal;
55
56
  }): Promise<LlamaModelInfo[]>;
56
57
  props(options?: {
58
+ model?: string;
57
59
  signal?: AbortSignal;
58
60
  }): Promise<LlamaServerProps>;
59
61
  load(model: string, signal?: AbortSignal): Promise<void>;
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/extensions/llama/client.ts"],"names":[],"mappings":"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","sourcesContent":["export type LlamaModelStatus = \"unloaded\" | \"loading\" | \"loaded\" | \"downloading\" | \"sleeping\";\n\nexport interface LlamaModelInfo {\n\tid: string;\n\taliases?: string[];\n\tstatus: {\n\t\tvalue: LlamaModelStatus;\n\t\targs?: string[];\n\t\tfailed?: boolean;\n\t\texit_code?: number;\n\t\tprogress?: Record<string, { done: number; total: number }>;\n\t};\n\tarchitecture?: {\n\t\tinput_modalities?: string[];\n\t\toutput_modalities?: string[];\n\t};\n\tsource?: string;\n\tmeta?: {\n\t\tn_ctx?: number;\n\t\tn_ctx_train?: number;\n\t\tsize?: number;\n\t\tftype?: string;\n\t};\n}\n\nexport interface LlamaModelsResponse {\n\tdata: LlamaModelInfo[];\n\tobject?: string;\n}\n\nexport interface LlamaServerProps {\n\tmodels_autoload?: boolean;\n}\n\nexport interface LlamaModelEvent {\n\tmodel: string;\n\tevent: string;\n\tdata?: unknown;\n}\n\nexport interface LlamaProgress {\n\tmessage: string;\n\tratio?: number;\n\tdetail?: string;\n}\n\nfunction errorMessage(payload: unknown, fallback: string): string {\n\tif (typeof payload !== \"object\" || payload === null) return fallback;\n\tconst error = (payload as { error?: unknown }).error;\n\tif (typeof error !== \"object\" || error === null) return fallback;\n\tconst message = (error as { message?: unknown }).message;\n\treturn typeof message === \"string\" && message ? message : fallback;\n}\n\nfunction isModelInfo(value: unknown): value is LlamaModelInfo {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst candidate = value as { id?: unknown; status?: { value?: unknown } };\n\treturn typeof candidate.id === \"string\" && typeof candidate.status?.value === \"string\";\n}\n\nfunction linkSignal(source: AbortSignal | undefined, target: AbortController): () => void {\n\tif (!source) return () => {};\n\tif (source.aborted) {\n\t\ttarget.abort(source.reason);\n\t\treturn () => {};\n\t}\n\tconst abort = () => target.abort(source.reason);\n\tsource.addEventListener(\"abort\", abort, { once: true });\n\treturn () => source.removeEventListener(\"abort\", abort);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(signal.reason ?? new Error(\"Cancelled\"));\n\t\t\treturn;\n\t\t}\n\t\tconst abort = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\treject(signal?.reason ?? new Error(\"Cancelled\"));\n\t\t};\n\t\tconst timeout = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t});\n}\n\nfunction parseLoadProgress(data: unknown): LlamaProgress | undefined {\n\tif (typeof data !== \"object\" || data === null) return undefined;\n\tconst progress = (data as { progress?: unknown }).progress;\n\tif (typeof progress !== \"object\" || progress === null) return undefined;\n\tconst value = progress as { stages?: unknown; current?: unknown; stage?: unknown; value?: unknown };\n\tconst stage =\n\t\ttypeof value.current === \"string\" ? value.current : typeof value.stage === \"string\" ? value.stage : undefined;\n\tconst stages = Array.isArray(value.stages)\n\t\t? value.stages.filter((entry): entry is string => typeof entry === \"string\")\n\t\t: [];\n\tconst stageRatio = typeof value.value === \"number\" ? Math.max(0, Math.min(1, value.value)) : undefined;\n\tlet ratio = stageRatio;\n\tif (stage && stages.length > 0) {\n\t\tconst index = stages.indexOf(stage);\n\t\tif (index >= 0) ratio = (index + (stageRatio ?? 0)) / stages.length;\n\t}\n\treturn {\n\t\tmessage: stage ? `Loading ${stage.replaceAll(\"_\", \" \")}` : \"Loading model\",\n\t\tratio,\n\t};\n}\n\nfunction parseDownloadProgress(data: unknown): LlamaProgress | undefined {\n\tif (typeof data !== \"object\" || data === null) return undefined;\n\tconst nested = (data as { progress?: unknown }).progress;\n\tconst files = typeof nested === \"object\" && nested !== null ? nested : data;\n\tlet done = 0;\n\tlet total = 0;\n\tfor (const value of Object.values(files as Record<string, unknown>)) {\n\t\tif (typeof value !== \"object\" || value === null) continue;\n\t\tconst entry = value as { done?: unknown; total?: unknown };\n\t\tif (typeof entry.done !== \"number\" || typeof entry.total !== \"number\") continue;\n\t\tdone += entry.done;\n\t\ttotal += entry.total;\n\t}\n\tif (total <= 0) return undefined;\n\treturn {\n\t\tmessage: \"Downloading model\",\n\t\tratio: done / total,\n\t\tdetail: `${formatBytes(done)} / ${formatBytes(total)}`,\n\t};\n}\n\nexport function formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tconst units = [\"KiB\", \"MiB\", \"GiB\", \"TiB\"];\n\tlet value = bytes / 1024;\n\tlet unit = units[0]!;\n\tfor (let index = 1; index < units.length && value >= 1024; index++) {\n\t\tvalue /= 1024;\n\t\tunit = units[index]!;\n\t}\n\treturn `${value >= 10 ? value.toFixed(1) : value.toFixed(2)} ${unit}`;\n}\n\nexport function normalizeLlamaServerUrl(value: string): string {\n\tconst url = new URL(value.trim());\n\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n\t\tthrow new Error(\"Server URL must use http or https\");\n\t}\n\turl.hash = \"\";\n\turl.search = \"\";\n\turl.pathname = url.pathname.replace(/\\/+$/u, \"\").replace(/\\/v1$/u, \"\") || \"/\";\n\treturn url.toString().replace(/\\/$/u, \"\");\n}\n\nexport function llamaInferenceUrl(serverUrl: string): string {\n\treturn `${normalizeLlamaServerUrl(serverUrl)}/v1`;\n}\n\nexport class LlamaClient {\n\treadonly serverUrl: string;\n\tprivate readonly apiKey: string | undefined;\n\n\tconstructor(serverUrl: string, apiKey?: string) {\n\t\tthis.serverUrl = normalizeLlamaServerUrl(serverUrl);\n\t\tthis.apiKey = apiKey;\n\t}\n\n\tprivate async request(path: string, init: RequestInit = {}): Promise<unknown> {\n\t\tconst headers = new Headers(init.headers);\n\t\tif (init.body !== undefined) headers.set(\"Content-Type\", \"application/json\");\n\t\tif (this.apiKey) headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n\t\tconst timeout = AbortSignal.timeout(15_000);\n\t\tconst signal = init.signal ? AbortSignal.any([init.signal, timeout]) : timeout;\n\t\tconst response = await fetch(`${this.serverUrl}${path}`, { ...init, headers, signal });\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = await response.json();\n\t\t} catch {\n\t\t\tpayload = undefined;\n\t\t}\n\t\tif (!response.ok) throw new Error(errorMessage(payload, `llama.cpp returned HTTP ${response.status}`));\n\t\treturn payload;\n\t}\n\n\tasync list(options: { reload?: boolean; signal?: AbortSignal } = {}): Promise<LlamaModelInfo[]> {\n\t\tconst payload = await this.request(`/models${options.reload ? \"?reload=1\" : \"\"}`, { signal: options.signal });\n\t\tif (typeof payload !== \"object\" || payload === null || !Array.isArray((payload as { data?: unknown }).data)) {\n\t\t\tthrow new Error(\"llama.cpp returned an invalid model catalog\");\n\t\t}\n\t\tconst data = (payload as { data: unknown[] }).data;\n\t\tif (!data.every(isModelInfo)) throw new Error(\"Server is not running in llama.cpp router mode\");\n\t\treturn data;\n\t}\n\n\tasync props(options: { signal?: AbortSignal } = {}): Promise<LlamaServerProps> {\n\t\tconst payload = await this.request(\"/props\", { signal: options.signal });\n\t\tif (typeof payload !== \"object\" || payload === null) return {};\n\t\tconst { models_autoload: modelsAutoload } = payload as Record<string, unknown>;\n\t\treturn typeof modelsAutoload === \"boolean\" ? { models_autoload: modelsAutoload } : {};\n\t}\n\n\tasync load(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models/load\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync unload(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models/unload\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync unloadAndWait(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.unload(model, signal);\n\t\twhile (true) {\n\t\t\tconst entry = (await this.list({ signal })).find((candidate) => candidate.id === model);\n\t\t\tif (!entry || entry.status.value === \"unloaded\") return;\n\t\t\tawait sleep(100, signal);\n\t\t}\n\t}\n\n\tasync download(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync watch(onEvent: (event: LlamaModelEvent) => void, signal?: AbortSignal): Promise<void> {\n\t\tconst headers = new Headers();\n\t\tif (this.apiKey) headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n\t\tconst response = await fetch(`${this.serverUrl}/models/sse`, { headers, signal });\n\t\tif (!response.ok || !response.body) throw new Error(`llama.cpp SSE returned HTTP ${response.status}`);\n\t\tconst reader = response.body.getReader();\n\t\tconst decoder = new TextDecoder();\n\t\tlet buffer = \"\";\n\t\twhile (true) {\n\t\t\tconst chunk = await reader.read();\n\t\t\tif (chunk.done) break;\n\t\t\tbuffer += decoder.decode(chunk.value, { stream: true }).replaceAll(\"\\r\\n\", \"\\n\");\n\t\t\tlet boundary = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (boundary >= 0) {\n\t\t\t\tconst frame = buffer.slice(0, boundary);\n\t\t\t\tbuffer = buffer.slice(boundary + 2);\n\t\t\t\tconst data = frame\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.filter((line) => line.startsWith(\"data:\"))\n\t\t\t\t\t.map((line) => line.slice(5).trimStart())\n\t\t\t\t\t.join(\"\\n\");\n\t\t\t\tif (data) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst event = JSON.parse(data) as LlamaModelEvent;\n\t\t\t\t\t\tif (event && typeof event.model === \"string\" && typeof event.event === \"string\") onEvent(event);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Ignore malformed events; catalog polling remains authoritative.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tboundary = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\t\t}\n\t}\n\n\tasync loadAndWait(\n\t\tmodel: string,\n\t\tonProgress: (progress: LlamaProgress) => void,\n\t\tsignal?: AbortSignal,\n\t): Promise<LlamaModelInfo> {\n\t\tconst watcher = new AbortController();\n\t\tconst unlink = linkSignal(signal, watcher);\n\t\tlet eventLoaded = false;\n\t\tlet eventError: string | undefined;\n\t\tvoid this.watch((event) => {\n\t\t\tif (event.model !== model) return;\n\t\t\tif (event.event !== \"model_status\" && event.event !== \"status_change\") return;\n\t\t\tconst data = event.data as { status?: unknown } | undefined;\n\t\t\tif (data?.status === \"loaded\") eventLoaded = true;\n\t\t\tif (data?.status === \"unloaded\") eventError = \"Model failed to load\";\n\t\t\tconst progress = parseLoadProgress(event.data);\n\t\t\tif (progress) onProgress(progress);\n\t\t}, watcher.signal).catch(() => {});\n\t\ttry {\n\t\t\tawait this.load(model, signal);\n\t\t\tonProgress({ message: \"Loading model\" });\n\t\t\twhile (true) {\n\t\t\t\tif (signal?.aborted) throw signal.reason ?? new Error(\"Cancelled\");\n\t\t\t\tconst entry = (await this.list({ signal })).find((candidate) => candidate.id === model);\n\t\t\t\tif (entry?.status.value === \"loaded\") return entry;\n\t\t\t\tif (eventLoaded && !entry) return { id: model, status: { value: \"loaded\" } };\n\t\t\t\tif (entry?.status.failed || eventError) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\tentry?.status.exit_code === undefined\n\t\t\t\t\t\t\t? (eventError ?? \"Model failed to load\")\n\t\t\t\t\t\t\t: `Model exited with code ${entry.status.exit_code}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait sleep(250, signal);\n\t\t\t}\n\t\t} finally {\n\t\t\tunlink();\n\t\t\twatcher.abort();\n\t\t}\n\t}\n\n\tasync downloadAndWait(\n\t\tmodel: string,\n\t\tonProgress: (progress: LlamaProgress) => void,\n\t\tsignal?: AbortSignal,\n\t): Promise<LlamaModelInfo[]> {\n\t\tconst watcher = new AbortController();\n\t\tconst unlink = linkSignal(signal, watcher);\n\t\tlet finished = false;\n\t\tlet failure: string | undefined;\n\t\tlet sawDownloading = false;\n\t\tlet polls = 0;\n\t\tvoid this.watch((event) => {\n\t\t\tif (event.model !== model) return;\n\t\t\tif (event.event === \"download_finished\") finished = true;\n\t\t\tif (event.event === \"download_failed\") failure = errorMessage(event.data, \"Download failed\");\n\t\t\tif (event.event === \"download_progress\") {\n\t\t\t\tsawDownloading = true;\n\t\t\t\tconst progress = parseDownloadProgress(event.data);\n\t\t\t\tif (progress) onProgress(progress);\n\t\t\t}\n\t\t}, watcher.signal).catch(() => {});\n\t\ttry {\n\t\t\tawait this.download(model, signal);\n\t\t\tonProgress({ message: \"Downloading model\" });\n\t\t\twhile (true) {\n\t\t\t\tif (signal?.aborted) throw signal.reason ?? new Error(\"Cancelled\");\n\t\t\t\tif (failure) throw new Error(failure);\n\t\t\t\tconst models = await this.list({ signal });\n\t\t\t\tpolls++;\n\t\t\t\tconst entry = models.find((candidate) => candidate.id === model);\n\t\t\t\tif (entry?.status.value === \"downloading\") {\n\t\t\t\t\tsawDownloading = true;\n\t\t\t\t\tconst progress = parseDownloadProgress(entry.status.progress);\n\t\t\t\t\tif (progress) onProgress(progress);\n\t\t\t\t} else if (finished || (entry && (sawDownloading || polls >= 2))) {\n\t\t\t\t\treturn this.list({ reload: true, signal });\n\t\t\t\t}\n\t\t\t\tawait sleep(500, signal);\n\t\t\t}\n\t\t} finally {\n\t\t\tunlink();\n\t\t\twatcher.abort();\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../../src/extensions/llama/client.ts"],"names":[],"mappings":"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","sourcesContent":["export type LlamaModelStatus = \"unloaded\" | \"loading\" | \"loaded\" | \"downloading\" | \"sleeping\";\n\nexport interface LlamaModelInfo {\n\tid: string;\n\taliases?: string[];\n\tstatus: {\n\t\tvalue: LlamaModelStatus;\n\t\targs?: string[];\n\t\tfailed?: boolean;\n\t\texit_code?: number;\n\t\tprogress?: Record<string, { done: number; total: number }>;\n\t};\n\tarchitecture?: {\n\t\tinput_modalities?: string[];\n\t\toutput_modalities?: string[];\n\t};\n\tsource?: string;\n\tmeta?: {\n\t\tn_ctx?: number;\n\t\tn_ctx_train?: number;\n\t\tsize?: number;\n\t\tftype?: string;\n\t};\n}\n\nexport interface LlamaModelsResponse {\n\tdata: LlamaModelInfo[];\n\tobject?: string;\n}\n\nexport interface LlamaServerProps {\n\tmodels_autoload?: boolean;\n\tchat_template?: string;\n}\n\nexport interface LlamaModelEvent {\n\tmodel: string;\n\tevent: string;\n\tdata?: unknown;\n}\n\nexport interface LlamaProgress {\n\tmessage: string;\n\tratio?: number;\n\tdetail?: string;\n}\n\nfunction errorMessage(payload: unknown, fallback: string): string {\n\tif (typeof payload !== \"object\" || payload === null) return fallback;\n\tconst error = (payload as { error?: unknown }).error;\n\tif (typeof error !== \"object\" || error === null) return fallback;\n\tconst message = (error as { message?: unknown }).message;\n\treturn typeof message === \"string\" && message ? message : fallback;\n}\n\nfunction isModelInfo(value: unknown): value is LlamaModelInfo {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst candidate = value as { id?: unknown; status?: { value?: unknown } };\n\treturn typeof candidate.id === \"string\" && typeof candidate.status?.value === \"string\";\n}\n\nfunction linkSignal(source: AbortSignal | undefined, target: AbortController): () => void {\n\tif (!source) return () => {};\n\tif (source.aborted) {\n\t\ttarget.abort(source.reason);\n\t\treturn () => {};\n\t}\n\tconst abort = () => target.abort(source.reason);\n\tsource.addEventListener(\"abort\", abort, { once: true });\n\treturn () => source.removeEventListener(\"abort\", abort);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(signal.reason ?? new Error(\"Cancelled\"));\n\t\t\treturn;\n\t\t}\n\t\tconst abort = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\treject(signal?.reason ?? new Error(\"Cancelled\"));\n\t\t};\n\t\tconst timeout = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t});\n}\n\nfunction parseLoadProgress(data: unknown): LlamaProgress | undefined {\n\tif (typeof data !== \"object\" || data === null) return undefined;\n\tconst progress = (data as { progress?: unknown }).progress;\n\tif (typeof progress !== \"object\" || progress === null) return undefined;\n\tconst value = progress as { stages?: unknown; current?: unknown; stage?: unknown; value?: unknown };\n\tconst stage =\n\t\ttypeof value.current === \"string\" ? value.current : typeof value.stage === \"string\" ? value.stage : undefined;\n\tconst stages = Array.isArray(value.stages)\n\t\t? value.stages.filter((entry): entry is string => typeof entry === \"string\")\n\t\t: [];\n\tconst stageRatio = typeof value.value === \"number\" ? Math.max(0, Math.min(1, value.value)) : undefined;\n\tlet ratio = stageRatio;\n\tif (stage && stages.length > 0) {\n\t\tconst index = stages.indexOf(stage);\n\t\tif (index >= 0) ratio = (index + (stageRatio ?? 0)) / stages.length;\n\t}\n\treturn {\n\t\tmessage: stage ? `Loading ${stage.replaceAll(\"_\", \" \")}` : \"Loading model\",\n\t\tratio,\n\t};\n}\n\nfunction parseDownloadProgress(data: unknown): LlamaProgress | undefined {\n\tif (typeof data !== \"object\" || data === null) return undefined;\n\tconst nested = (data as { progress?: unknown }).progress;\n\tconst files = typeof nested === \"object\" && nested !== null ? nested : data;\n\tlet done = 0;\n\tlet total = 0;\n\tfor (const value of Object.values(files as Record<string, unknown>)) {\n\t\tif (typeof value !== \"object\" || value === null) continue;\n\t\tconst entry = value as { done?: unknown; total?: unknown };\n\t\tif (typeof entry.done !== \"number\" || typeof entry.total !== \"number\") continue;\n\t\tdone += entry.done;\n\t\ttotal += entry.total;\n\t}\n\tif (total <= 0) return undefined;\n\treturn {\n\t\tmessage: \"Downloading model\",\n\t\tratio: done / total,\n\t\tdetail: `${formatBytes(done)} / ${formatBytes(total)}`,\n\t};\n}\n\nexport function formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tconst units = [\"KiB\", \"MiB\", \"GiB\", \"TiB\"];\n\tlet value = bytes / 1024;\n\tlet unit = units[0]!;\n\tfor (let index = 1; index < units.length && value >= 1024; index++) {\n\t\tvalue /= 1024;\n\t\tunit = units[index]!;\n\t}\n\treturn `${value >= 10 ? value.toFixed(1) : value.toFixed(2)} ${unit}`;\n}\n\nexport function normalizeLlamaServerUrl(value: string): string {\n\tconst url = new URL(value.trim());\n\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n\t\tthrow new Error(\"Server URL must use http or https\");\n\t}\n\turl.hash = \"\";\n\turl.search = \"\";\n\turl.pathname = url.pathname.replace(/\\/+$/u, \"\").replace(/\\/v1$/u, \"\") || \"/\";\n\treturn url.toString().replace(/\\/$/u, \"\");\n}\n\nexport function llamaInferenceUrl(serverUrl: string): string {\n\treturn `${normalizeLlamaServerUrl(serverUrl)}/v1`;\n}\n\nexport class LlamaClient {\n\treadonly serverUrl: string;\n\tprivate readonly apiKey: string | undefined;\n\n\tconstructor(serverUrl: string, apiKey?: string) {\n\t\tthis.serverUrl = normalizeLlamaServerUrl(serverUrl);\n\t\tthis.apiKey = apiKey;\n\t}\n\n\tprivate async request(path: string, init: RequestInit = {}): Promise<unknown> {\n\t\tconst headers = new Headers(init.headers);\n\t\tif (init.body !== undefined) headers.set(\"Content-Type\", \"application/json\");\n\t\tif (this.apiKey) headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n\t\tconst timeout = AbortSignal.timeout(15_000);\n\t\tconst signal = init.signal ? AbortSignal.any([init.signal, timeout]) : timeout;\n\t\tconst response = await fetch(`${this.serverUrl}${path}`, { ...init, headers, signal });\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = await response.json();\n\t\t} catch {\n\t\t\tpayload = undefined;\n\t\t}\n\t\tif (!response.ok) throw new Error(errorMessage(payload, `llama.cpp returned HTTP ${response.status}`));\n\t\treturn payload;\n\t}\n\n\tasync list(options: { reload?: boolean; signal?: AbortSignal } = {}): Promise<LlamaModelInfo[]> {\n\t\tconst payload = await this.request(`/models${options.reload ? \"?reload=1\" : \"\"}`, { signal: options.signal });\n\t\tif (typeof payload !== \"object\" || payload === null || !Array.isArray((payload as { data?: unknown }).data)) {\n\t\t\tthrow new Error(\"llama.cpp returned an invalid model catalog\");\n\t\t}\n\t\tconst data = (payload as { data: unknown[] }).data;\n\t\tif (!data.every(isModelInfo)) throw new Error(\"Server is not running in llama.cpp router mode\");\n\t\treturn data;\n\t}\n\n\tasync props(options: { model?: string; signal?: AbortSignal } = {}): Promise<LlamaServerProps> {\n\t\tconst query = options.model ? `?${new URLSearchParams({ model: options.model, autoload: \"false\" })}` : \"\";\n\t\tconst payload = await this.request(`/props${query}`, { signal: options.signal });\n\t\tif (typeof payload !== \"object\" || payload === null) return {};\n\t\tconst { models_autoload: modelsAutoload, chat_template: chatTemplate } = payload as Record<string, unknown>;\n\t\treturn {\n\t\t\t...(typeof modelsAutoload === \"boolean\" ? { models_autoload: modelsAutoload } : {}),\n\t\t\t...(typeof chatTemplate === \"string\" ? { chat_template: chatTemplate } : {}),\n\t\t};\n\t}\n\n\tasync load(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models/load\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync unload(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models/unload\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync unloadAndWait(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.unload(model, signal);\n\t\twhile (true) {\n\t\t\tconst entry = (await this.list({ signal })).find((candidate) => candidate.id === model);\n\t\t\tif (!entry || entry.status.value === \"unloaded\") return;\n\t\t\tawait sleep(100, signal);\n\t\t}\n\t}\n\n\tasync download(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync watch(onEvent: (event: LlamaModelEvent) => void, signal?: AbortSignal): Promise<void> {\n\t\tconst headers = new Headers();\n\t\tif (this.apiKey) headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n\t\tconst response = await fetch(`${this.serverUrl}/models/sse`, { headers, signal });\n\t\tif (!response.ok || !response.body) throw new Error(`llama.cpp SSE returned HTTP ${response.status}`);\n\t\tconst reader = response.body.getReader();\n\t\tconst decoder = new TextDecoder();\n\t\tlet buffer = \"\";\n\t\twhile (true) {\n\t\t\tconst chunk = await reader.read();\n\t\t\tif (chunk.done) break;\n\t\t\tbuffer += decoder.decode(chunk.value, { stream: true }).replaceAll(\"\\r\\n\", \"\\n\");\n\t\t\tlet boundary = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (boundary >= 0) {\n\t\t\t\tconst frame = buffer.slice(0, boundary);\n\t\t\t\tbuffer = buffer.slice(boundary + 2);\n\t\t\t\tconst data = frame\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.filter((line) => line.startsWith(\"data:\"))\n\t\t\t\t\t.map((line) => line.slice(5).trimStart())\n\t\t\t\t\t.join(\"\\n\");\n\t\t\t\tif (data) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst event = JSON.parse(data) as LlamaModelEvent;\n\t\t\t\t\t\tif (event && typeof event.model === \"string\" && typeof event.event === \"string\") onEvent(event);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Ignore malformed events; catalog polling remains authoritative.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tboundary = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\t\t}\n\t}\n\n\tasync loadAndWait(\n\t\tmodel: string,\n\t\tonProgress: (progress: LlamaProgress) => void,\n\t\tsignal?: AbortSignal,\n\t): Promise<LlamaModelInfo> {\n\t\tconst watcher = new AbortController();\n\t\tconst unlink = linkSignal(signal, watcher);\n\t\tlet eventLoaded = false;\n\t\tlet eventError: string | undefined;\n\t\tvoid this.watch((event) => {\n\t\t\tif (event.model !== model) return;\n\t\t\tif (event.event !== \"model_status\" && event.event !== \"status_change\") return;\n\t\t\tconst data = event.data as { status?: unknown } | undefined;\n\t\t\tif (data?.status === \"loaded\") eventLoaded = true;\n\t\t\tif (data?.status === \"unloaded\") eventError = \"Model failed to load\";\n\t\t\tconst progress = parseLoadProgress(event.data);\n\t\t\tif (progress) onProgress(progress);\n\t\t}, watcher.signal).catch(() => {});\n\t\ttry {\n\t\t\tawait this.load(model, signal);\n\t\t\tonProgress({ message: \"Loading model\" });\n\t\t\twhile (true) {\n\t\t\t\tif (signal?.aborted) throw signal.reason ?? new Error(\"Cancelled\");\n\t\t\t\tconst entry = (await this.list({ signal })).find((candidate) => candidate.id === model);\n\t\t\t\tif (entry?.status.value === \"loaded\") return entry;\n\t\t\t\tif (eventLoaded && !entry) return { id: model, status: { value: \"loaded\" } };\n\t\t\t\tif (entry?.status.failed || eventError) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\tentry?.status.exit_code === undefined\n\t\t\t\t\t\t\t? (eventError ?? \"Model failed to load\")\n\t\t\t\t\t\t\t: `Model exited with code ${entry.status.exit_code}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait sleep(250, signal);\n\t\t\t}\n\t\t} finally {\n\t\t\tunlink();\n\t\t\twatcher.abort();\n\t\t}\n\t}\n\n\tasync downloadAndWait(\n\t\tmodel: string,\n\t\tonProgress: (progress: LlamaProgress) => void,\n\t\tsignal?: AbortSignal,\n\t): Promise<LlamaModelInfo[]> {\n\t\tconst watcher = new AbortController();\n\t\tconst unlink = linkSignal(signal, watcher);\n\t\tlet finished = false;\n\t\tlet failure: string | undefined;\n\t\tlet sawDownloading = false;\n\t\tlet polls = 0;\n\t\tvoid this.watch((event) => {\n\t\t\tif (event.model !== model) return;\n\t\t\tif (event.event === \"download_finished\") finished = true;\n\t\t\tif (event.event === \"download_failed\") failure = errorMessage(event.data, \"Download failed\");\n\t\t\tif (event.event === \"download_progress\") {\n\t\t\t\tsawDownloading = true;\n\t\t\t\tconst progress = parseDownloadProgress(event.data);\n\t\t\t\tif (progress) onProgress(progress);\n\t\t\t}\n\t\t}, watcher.signal).catch(() => {});\n\t\ttry {\n\t\t\tawait this.download(model, signal);\n\t\t\tonProgress({ message: \"Downloading model\" });\n\t\t\twhile (true) {\n\t\t\t\tif (signal?.aborted) throw signal.reason ?? new Error(\"Cancelled\");\n\t\t\t\tif (failure) throw new Error(failure);\n\t\t\t\tconst models = await this.list({ signal });\n\t\t\t\tpolls++;\n\t\t\t\tconst entry = models.find((candidate) => candidate.id === model);\n\t\t\t\tif (entry?.status.value === \"downloading\") {\n\t\t\t\t\tsawDownloading = true;\n\t\t\t\t\tconst progress = parseDownloadProgress(entry.status.progress);\n\t\t\t\t\tif (progress) onProgress(progress);\n\t\t\t\t} else if (finished || (entry && (sawDownloading || polls >= 2))) {\n\t\t\t\t\treturn this.list({ reload: true, signal });\n\t\t\t\t}\n\t\t\t\tawait sleep(500, signal);\n\t\t\t}\n\t\t} finally {\n\t\t\tunlink();\n\t\t\twatcher.abort();\n\t\t}\n\t}\n}\n"]}
@@ -151,11 +151,15 @@ export class LlamaClient {
151
151
  return data;
152
152
  }
153
153
  async props(options = {}) {
154
- const payload = await this.request("/props", { signal: options.signal });
154
+ const query = options.model ? `?${new URLSearchParams({ model: options.model, autoload: "false" })}` : "";
155
+ const payload = await this.request(`/props${query}`, { signal: options.signal });
155
156
  if (typeof payload !== "object" || payload === null)
156
157
  return {};
157
- const { models_autoload: modelsAutoload } = payload;
158
- return typeof modelsAutoload === "boolean" ? { models_autoload: modelsAutoload } : {};
158
+ const { models_autoload: modelsAutoload, chat_template: chatTemplate } = payload;
159
+ return {
160
+ ...(typeof modelsAutoload === "boolean" ? { models_autoload: modelsAutoload } : {}),
161
+ ...(typeof chatTemplate === "string" ? { chat_template: chatTemplate } : {}),
162
+ };
159
163
  }
160
164
  async load(model, signal) {
161
165
  await this.request("/models/load", { method: "POST", body: JSON.stringify({ model }), signal });
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/extensions/llama/client.ts"],"names":[],"mappings":"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","sourcesContent":["export type LlamaModelStatus = \"unloaded\" | \"loading\" | \"loaded\" | \"downloading\" | \"sleeping\";\n\nexport interface LlamaModelInfo {\n\tid: string;\n\taliases?: string[];\n\tstatus: {\n\t\tvalue: LlamaModelStatus;\n\t\targs?: string[];\n\t\tfailed?: boolean;\n\t\texit_code?: number;\n\t\tprogress?: Record<string, { done: number; total: number }>;\n\t};\n\tarchitecture?: {\n\t\tinput_modalities?: string[];\n\t\toutput_modalities?: string[];\n\t};\n\tsource?: string;\n\tmeta?: {\n\t\tn_ctx?: number;\n\t\tn_ctx_train?: number;\n\t\tsize?: number;\n\t\tftype?: string;\n\t};\n}\n\nexport interface LlamaModelsResponse {\n\tdata: LlamaModelInfo[];\n\tobject?: string;\n}\n\nexport interface LlamaServerProps {\n\tmodels_autoload?: boolean;\n}\n\nexport interface LlamaModelEvent {\n\tmodel: string;\n\tevent: string;\n\tdata?: unknown;\n}\n\nexport interface LlamaProgress {\n\tmessage: string;\n\tratio?: number;\n\tdetail?: string;\n}\n\nfunction errorMessage(payload: unknown, fallback: string): string {\n\tif (typeof payload !== \"object\" || payload === null) return fallback;\n\tconst error = (payload as { error?: unknown }).error;\n\tif (typeof error !== \"object\" || error === null) return fallback;\n\tconst message = (error as { message?: unknown }).message;\n\treturn typeof message === \"string\" && message ? message : fallback;\n}\n\nfunction isModelInfo(value: unknown): value is LlamaModelInfo {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst candidate = value as { id?: unknown; status?: { value?: unknown } };\n\treturn typeof candidate.id === \"string\" && typeof candidate.status?.value === \"string\";\n}\n\nfunction linkSignal(source: AbortSignal | undefined, target: AbortController): () => void {\n\tif (!source) return () => {};\n\tif (source.aborted) {\n\t\ttarget.abort(source.reason);\n\t\treturn () => {};\n\t}\n\tconst abort = () => target.abort(source.reason);\n\tsource.addEventListener(\"abort\", abort, { once: true });\n\treturn () => source.removeEventListener(\"abort\", abort);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(signal.reason ?? new Error(\"Cancelled\"));\n\t\t\treturn;\n\t\t}\n\t\tconst abort = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\treject(signal?.reason ?? new Error(\"Cancelled\"));\n\t\t};\n\t\tconst timeout = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t});\n}\n\nfunction parseLoadProgress(data: unknown): LlamaProgress | undefined {\n\tif (typeof data !== \"object\" || data === null) return undefined;\n\tconst progress = (data as { progress?: unknown }).progress;\n\tif (typeof progress !== \"object\" || progress === null) return undefined;\n\tconst value = progress as { stages?: unknown; current?: unknown; stage?: unknown; value?: unknown };\n\tconst stage =\n\t\ttypeof value.current === \"string\" ? value.current : typeof value.stage === \"string\" ? value.stage : undefined;\n\tconst stages = Array.isArray(value.stages)\n\t\t? value.stages.filter((entry): entry is string => typeof entry === \"string\")\n\t\t: [];\n\tconst stageRatio = typeof value.value === \"number\" ? Math.max(0, Math.min(1, value.value)) : undefined;\n\tlet ratio = stageRatio;\n\tif (stage && stages.length > 0) {\n\t\tconst index = stages.indexOf(stage);\n\t\tif (index >= 0) ratio = (index + (stageRatio ?? 0)) / stages.length;\n\t}\n\treturn {\n\t\tmessage: stage ? `Loading ${stage.replaceAll(\"_\", \" \")}` : \"Loading model\",\n\t\tratio,\n\t};\n}\n\nfunction parseDownloadProgress(data: unknown): LlamaProgress | undefined {\n\tif (typeof data !== \"object\" || data === null) return undefined;\n\tconst nested = (data as { progress?: unknown }).progress;\n\tconst files = typeof nested === \"object\" && nested !== null ? nested : data;\n\tlet done = 0;\n\tlet total = 0;\n\tfor (const value of Object.values(files as Record<string, unknown>)) {\n\t\tif (typeof value !== \"object\" || value === null) continue;\n\t\tconst entry = value as { done?: unknown; total?: unknown };\n\t\tif (typeof entry.done !== \"number\" || typeof entry.total !== \"number\") continue;\n\t\tdone += entry.done;\n\t\ttotal += entry.total;\n\t}\n\tif (total <= 0) return undefined;\n\treturn {\n\t\tmessage: \"Downloading model\",\n\t\tratio: done / total,\n\t\tdetail: `${formatBytes(done)} / ${formatBytes(total)}`,\n\t};\n}\n\nexport function formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tconst units = [\"KiB\", \"MiB\", \"GiB\", \"TiB\"];\n\tlet value = bytes / 1024;\n\tlet unit = units[0]!;\n\tfor (let index = 1; index < units.length && value >= 1024; index++) {\n\t\tvalue /= 1024;\n\t\tunit = units[index]!;\n\t}\n\treturn `${value >= 10 ? value.toFixed(1) : value.toFixed(2)} ${unit}`;\n}\n\nexport function normalizeLlamaServerUrl(value: string): string {\n\tconst url = new URL(value.trim());\n\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n\t\tthrow new Error(\"Server URL must use http or https\");\n\t}\n\turl.hash = \"\";\n\turl.search = \"\";\n\turl.pathname = url.pathname.replace(/\\/+$/u, \"\").replace(/\\/v1$/u, \"\") || \"/\";\n\treturn url.toString().replace(/\\/$/u, \"\");\n}\n\nexport function llamaInferenceUrl(serverUrl: string): string {\n\treturn `${normalizeLlamaServerUrl(serverUrl)}/v1`;\n}\n\nexport class LlamaClient {\n\treadonly serverUrl: string;\n\tprivate readonly apiKey: string | undefined;\n\n\tconstructor(serverUrl: string, apiKey?: string) {\n\t\tthis.serverUrl = normalizeLlamaServerUrl(serverUrl);\n\t\tthis.apiKey = apiKey;\n\t}\n\n\tprivate async request(path: string, init: RequestInit = {}): Promise<unknown> {\n\t\tconst headers = new Headers(init.headers);\n\t\tif (init.body !== undefined) headers.set(\"Content-Type\", \"application/json\");\n\t\tif (this.apiKey) headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n\t\tconst timeout = AbortSignal.timeout(15_000);\n\t\tconst signal = init.signal ? AbortSignal.any([init.signal, timeout]) : timeout;\n\t\tconst response = await fetch(`${this.serverUrl}${path}`, { ...init, headers, signal });\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = await response.json();\n\t\t} catch {\n\t\t\tpayload = undefined;\n\t\t}\n\t\tif (!response.ok) throw new Error(errorMessage(payload, `llama.cpp returned HTTP ${response.status}`));\n\t\treturn payload;\n\t}\n\n\tasync list(options: { reload?: boolean; signal?: AbortSignal } = {}): Promise<LlamaModelInfo[]> {\n\t\tconst payload = await this.request(`/models${options.reload ? \"?reload=1\" : \"\"}`, { signal: options.signal });\n\t\tif (typeof payload !== \"object\" || payload === null || !Array.isArray((payload as { data?: unknown }).data)) {\n\t\t\tthrow new Error(\"llama.cpp returned an invalid model catalog\");\n\t\t}\n\t\tconst data = (payload as { data: unknown[] }).data;\n\t\tif (!data.every(isModelInfo)) throw new Error(\"Server is not running in llama.cpp router mode\");\n\t\treturn data;\n\t}\n\n\tasync props(options: { signal?: AbortSignal } = {}): Promise<LlamaServerProps> {\n\t\tconst payload = await this.request(\"/props\", { signal: options.signal });\n\t\tif (typeof payload !== \"object\" || payload === null) return {};\n\t\tconst { models_autoload: modelsAutoload } = payload as Record<string, unknown>;\n\t\treturn typeof modelsAutoload === \"boolean\" ? { models_autoload: modelsAutoload } : {};\n\t}\n\n\tasync load(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models/load\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync unload(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models/unload\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync unloadAndWait(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.unload(model, signal);\n\t\twhile (true) {\n\t\t\tconst entry = (await this.list({ signal })).find((candidate) => candidate.id === model);\n\t\t\tif (!entry || entry.status.value === \"unloaded\") return;\n\t\t\tawait sleep(100, signal);\n\t\t}\n\t}\n\n\tasync download(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync watch(onEvent: (event: LlamaModelEvent) => void, signal?: AbortSignal): Promise<void> {\n\t\tconst headers = new Headers();\n\t\tif (this.apiKey) headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n\t\tconst response = await fetch(`${this.serverUrl}/models/sse`, { headers, signal });\n\t\tif (!response.ok || !response.body) throw new Error(`llama.cpp SSE returned HTTP ${response.status}`);\n\t\tconst reader = response.body.getReader();\n\t\tconst decoder = new TextDecoder();\n\t\tlet buffer = \"\";\n\t\twhile (true) {\n\t\t\tconst chunk = await reader.read();\n\t\t\tif (chunk.done) break;\n\t\t\tbuffer += decoder.decode(chunk.value, { stream: true }).replaceAll(\"\\r\\n\", \"\\n\");\n\t\t\tlet boundary = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (boundary >= 0) {\n\t\t\t\tconst frame = buffer.slice(0, boundary);\n\t\t\t\tbuffer = buffer.slice(boundary + 2);\n\t\t\t\tconst data = frame\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.filter((line) => line.startsWith(\"data:\"))\n\t\t\t\t\t.map((line) => line.slice(5).trimStart())\n\t\t\t\t\t.join(\"\\n\");\n\t\t\t\tif (data) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst event = JSON.parse(data) as LlamaModelEvent;\n\t\t\t\t\t\tif (event && typeof event.model === \"string\" && typeof event.event === \"string\") onEvent(event);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Ignore malformed events; catalog polling remains authoritative.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tboundary = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\t\t}\n\t}\n\n\tasync loadAndWait(\n\t\tmodel: string,\n\t\tonProgress: (progress: LlamaProgress) => void,\n\t\tsignal?: AbortSignal,\n\t): Promise<LlamaModelInfo> {\n\t\tconst watcher = new AbortController();\n\t\tconst unlink = linkSignal(signal, watcher);\n\t\tlet eventLoaded = false;\n\t\tlet eventError: string | undefined;\n\t\tvoid this.watch((event) => {\n\t\t\tif (event.model !== model) return;\n\t\t\tif (event.event !== \"model_status\" && event.event !== \"status_change\") return;\n\t\t\tconst data = event.data as { status?: unknown } | undefined;\n\t\t\tif (data?.status === \"loaded\") eventLoaded = true;\n\t\t\tif (data?.status === \"unloaded\") eventError = \"Model failed to load\";\n\t\t\tconst progress = parseLoadProgress(event.data);\n\t\t\tif (progress) onProgress(progress);\n\t\t}, watcher.signal).catch(() => {});\n\t\ttry {\n\t\t\tawait this.load(model, signal);\n\t\t\tonProgress({ message: \"Loading model\" });\n\t\t\twhile (true) {\n\t\t\t\tif (signal?.aborted) throw signal.reason ?? new Error(\"Cancelled\");\n\t\t\t\tconst entry = (await this.list({ signal })).find((candidate) => candidate.id === model);\n\t\t\t\tif (entry?.status.value === \"loaded\") return entry;\n\t\t\t\tif (eventLoaded && !entry) return { id: model, status: { value: \"loaded\" } };\n\t\t\t\tif (entry?.status.failed || eventError) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\tentry?.status.exit_code === undefined\n\t\t\t\t\t\t\t? (eventError ?? \"Model failed to load\")\n\t\t\t\t\t\t\t: `Model exited with code ${entry.status.exit_code}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait sleep(250, signal);\n\t\t\t}\n\t\t} finally {\n\t\t\tunlink();\n\t\t\twatcher.abort();\n\t\t}\n\t}\n\n\tasync downloadAndWait(\n\t\tmodel: string,\n\t\tonProgress: (progress: LlamaProgress) => void,\n\t\tsignal?: AbortSignal,\n\t): Promise<LlamaModelInfo[]> {\n\t\tconst watcher = new AbortController();\n\t\tconst unlink = linkSignal(signal, watcher);\n\t\tlet finished = false;\n\t\tlet failure: string | undefined;\n\t\tlet sawDownloading = false;\n\t\tlet polls = 0;\n\t\tvoid this.watch((event) => {\n\t\t\tif (event.model !== model) return;\n\t\t\tif (event.event === \"download_finished\") finished = true;\n\t\t\tif (event.event === \"download_failed\") failure = errorMessage(event.data, \"Download failed\");\n\t\t\tif (event.event === \"download_progress\") {\n\t\t\t\tsawDownloading = true;\n\t\t\t\tconst progress = parseDownloadProgress(event.data);\n\t\t\t\tif (progress) onProgress(progress);\n\t\t\t}\n\t\t}, watcher.signal).catch(() => {});\n\t\ttry {\n\t\t\tawait this.download(model, signal);\n\t\t\tonProgress({ message: \"Downloading model\" });\n\t\t\twhile (true) {\n\t\t\t\tif (signal?.aborted) throw signal.reason ?? new Error(\"Cancelled\");\n\t\t\t\tif (failure) throw new Error(failure);\n\t\t\t\tconst models = await this.list({ signal });\n\t\t\t\tpolls++;\n\t\t\t\tconst entry = models.find((candidate) => candidate.id === model);\n\t\t\t\tif (entry?.status.value === \"downloading\") {\n\t\t\t\t\tsawDownloading = true;\n\t\t\t\t\tconst progress = parseDownloadProgress(entry.status.progress);\n\t\t\t\t\tif (progress) onProgress(progress);\n\t\t\t\t} else if (finished || (entry && (sawDownloading || polls >= 2))) {\n\t\t\t\t\treturn this.list({ reload: true, signal });\n\t\t\t\t}\n\t\t\t\tawait sleep(500, signal);\n\t\t\t}\n\t\t} finally {\n\t\t\tunlink();\n\t\t\twatcher.abort();\n\t\t}\n\t}\n}\n"]}
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../../src/extensions/llama/client.ts"],"names":[],"mappings":"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","sourcesContent":["export type LlamaModelStatus = \"unloaded\" | \"loading\" | \"loaded\" | \"downloading\" | \"sleeping\";\n\nexport interface LlamaModelInfo {\n\tid: string;\n\taliases?: string[];\n\tstatus: {\n\t\tvalue: LlamaModelStatus;\n\t\targs?: string[];\n\t\tfailed?: boolean;\n\t\texit_code?: number;\n\t\tprogress?: Record<string, { done: number; total: number }>;\n\t};\n\tarchitecture?: {\n\t\tinput_modalities?: string[];\n\t\toutput_modalities?: string[];\n\t};\n\tsource?: string;\n\tmeta?: {\n\t\tn_ctx?: number;\n\t\tn_ctx_train?: number;\n\t\tsize?: number;\n\t\tftype?: string;\n\t};\n}\n\nexport interface LlamaModelsResponse {\n\tdata: LlamaModelInfo[];\n\tobject?: string;\n}\n\nexport interface LlamaServerProps {\n\tmodels_autoload?: boolean;\n\tchat_template?: string;\n}\n\nexport interface LlamaModelEvent {\n\tmodel: string;\n\tevent: string;\n\tdata?: unknown;\n}\n\nexport interface LlamaProgress {\n\tmessage: string;\n\tratio?: number;\n\tdetail?: string;\n}\n\nfunction errorMessage(payload: unknown, fallback: string): string {\n\tif (typeof payload !== \"object\" || payload === null) return fallback;\n\tconst error = (payload as { error?: unknown }).error;\n\tif (typeof error !== \"object\" || error === null) return fallback;\n\tconst message = (error as { message?: unknown }).message;\n\treturn typeof message === \"string\" && message ? message : fallback;\n}\n\nfunction isModelInfo(value: unknown): value is LlamaModelInfo {\n\tif (typeof value !== \"object\" || value === null) return false;\n\tconst candidate = value as { id?: unknown; status?: { value?: unknown } };\n\treturn typeof candidate.id === \"string\" && typeof candidate.status?.value === \"string\";\n}\n\nfunction linkSignal(source: AbortSignal | undefined, target: AbortController): () => void {\n\tif (!source) return () => {};\n\tif (source.aborted) {\n\t\ttarget.abort(source.reason);\n\t\treturn () => {};\n\t}\n\tconst abort = () => target.abort(source.reason);\n\tsource.addEventListener(\"abort\", abort, { once: true });\n\treturn () => source.removeEventListener(\"abort\", abort);\n}\n\nfunction sleep(ms: number, signal?: AbortSignal): Promise<void> {\n\treturn new Promise((resolve, reject) => {\n\t\tif (signal?.aborted) {\n\t\t\treject(signal.reason ?? new Error(\"Cancelled\"));\n\t\t\treturn;\n\t\t}\n\t\tconst abort = () => {\n\t\t\tclearTimeout(timeout);\n\t\t\treject(signal?.reason ?? new Error(\"Cancelled\"));\n\t\t};\n\t\tconst timeout = setTimeout(() => {\n\t\t\tsignal?.removeEventListener(\"abort\", abort);\n\t\t\tresolve();\n\t\t}, ms);\n\t\tsignal?.addEventListener(\"abort\", abort, { once: true });\n\t});\n}\n\nfunction parseLoadProgress(data: unknown): LlamaProgress | undefined {\n\tif (typeof data !== \"object\" || data === null) return undefined;\n\tconst progress = (data as { progress?: unknown }).progress;\n\tif (typeof progress !== \"object\" || progress === null) return undefined;\n\tconst value = progress as { stages?: unknown; current?: unknown; stage?: unknown; value?: unknown };\n\tconst stage =\n\t\ttypeof value.current === \"string\" ? value.current : typeof value.stage === \"string\" ? value.stage : undefined;\n\tconst stages = Array.isArray(value.stages)\n\t\t? value.stages.filter((entry): entry is string => typeof entry === \"string\")\n\t\t: [];\n\tconst stageRatio = typeof value.value === \"number\" ? Math.max(0, Math.min(1, value.value)) : undefined;\n\tlet ratio = stageRatio;\n\tif (stage && stages.length > 0) {\n\t\tconst index = stages.indexOf(stage);\n\t\tif (index >= 0) ratio = (index + (stageRatio ?? 0)) / stages.length;\n\t}\n\treturn {\n\t\tmessage: stage ? `Loading ${stage.replaceAll(\"_\", \" \")}` : \"Loading model\",\n\t\tratio,\n\t};\n}\n\nfunction parseDownloadProgress(data: unknown): LlamaProgress | undefined {\n\tif (typeof data !== \"object\" || data === null) return undefined;\n\tconst nested = (data as { progress?: unknown }).progress;\n\tconst files = typeof nested === \"object\" && nested !== null ? nested : data;\n\tlet done = 0;\n\tlet total = 0;\n\tfor (const value of Object.values(files as Record<string, unknown>)) {\n\t\tif (typeof value !== \"object\" || value === null) continue;\n\t\tconst entry = value as { done?: unknown; total?: unknown };\n\t\tif (typeof entry.done !== \"number\" || typeof entry.total !== \"number\") continue;\n\t\tdone += entry.done;\n\t\ttotal += entry.total;\n\t}\n\tif (total <= 0) return undefined;\n\treturn {\n\t\tmessage: \"Downloading model\",\n\t\tratio: done / total,\n\t\tdetail: `${formatBytes(done)} / ${formatBytes(total)}`,\n\t};\n}\n\nexport function formatBytes(bytes: number): string {\n\tif (bytes < 1024) return `${bytes} B`;\n\tconst units = [\"KiB\", \"MiB\", \"GiB\", \"TiB\"];\n\tlet value = bytes / 1024;\n\tlet unit = units[0]!;\n\tfor (let index = 1; index < units.length && value >= 1024; index++) {\n\t\tvalue /= 1024;\n\t\tunit = units[index]!;\n\t}\n\treturn `${value >= 10 ? value.toFixed(1) : value.toFixed(2)} ${unit}`;\n}\n\nexport function normalizeLlamaServerUrl(value: string): string {\n\tconst url = new URL(value.trim());\n\tif (url.protocol !== \"http:\" && url.protocol !== \"https:\") {\n\t\tthrow new Error(\"Server URL must use http or https\");\n\t}\n\turl.hash = \"\";\n\turl.search = \"\";\n\turl.pathname = url.pathname.replace(/\\/+$/u, \"\").replace(/\\/v1$/u, \"\") || \"/\";\n\treturn url.toString().replace(/\\/$/u, \"\");\n}\n\nexport function llamaInferenceUrl(serverUrl: string): string {\n\treturn `${normalizeLlamaServerUrl(serverUrl)}/v1`;\n}\n\nexport class LlamaClient {\n\treadonly serverUrl: string;\n\tprivate readonly apiKey: string | undefined;\n\n\tconstructor(serverUrl: string, apiKey?: string) {\n\t\tthis.serverUrl = normalizeLlamaServerUrl(serverUrl);\n\t\tthis.apiKey = apiKey;\n\t}\n\n\tprivate async request(path: string, init: RequestInit = {}): Promise<unknown> {\n\t\tconst headers = new Headers(init.headers);\n\t\tif (init.body !== undefined) headers.set(\"Content-Type\", \"application/json\");\n\t\tif (this.apiKey) headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n\t\tconst timeout = AbortSignal.timeout(15_000);\n\t\tconst signal = init.signal ? AbortSignal.any([init.signal, timeout]) : timeout;\n\t\tconst response = await fetch(`${this.serverUrl}${path}`, { ...init, headers, signal });\n\t\tlet payload: unknown;\n\t\ttry {\n\t\t\tpayload = await response.json();\n\t\t} catch {\n\t\t\tpayload = undefined;\n\t\t}\n\t\tif (!response.ok) throw new Error(errorMessage(payload, `llama.cpp returned HTTP ${response.status}`));\n\t\treturn payload;\n\t}\n\n\tasync list(options: { reload?: boolean; signal?: AbortSignal } = {}): Promise<LlamaModelInfo[]> {\n\t\tconst payload = await this.request(`/models${options.reload ? \"?reload=1\" : \"\"}`, { signal: options.signal });\n\t\tif (typeof payload !== \"object\" || payload === null || !Array.isArray((payload as { data?: unknown }).data)) {\n\t\t\tthrow new Error(\"llama.cpp returned an invalid model catalog\");\n\t\t}\n\t\tconst data = (payload as { data: unknown[] }).data;\n\t\tif (!data.every(isModelInfo)) throw new Error(\"Server is not running in llama.cpp router mode\");\n\t\treturn data;\n\t}\n\n\tasync props(options: { model?: string; signal?: AbortSignal } = {}): Promise<LlamaServerProps> {\n\t\tconst query = options.model ? `?${new URLSearchParams({ model: options.model, autoload: \"false\" })}` : \"\";\n\t\tconst payload = await this.request(`/props${query}`, { signal: options.signal });\n\t\tif (typeof payload !== \"object\" || payload === null) return {};\n\t\tconst { models_autoload: modelsAutoload, chat_template: chatTemplate } = payload as Record<string, unknown>;\n\t\treturn {\n\t\t\t...(typeof modelsAutoload === \"boolean\" ? { models_autoload: modelsAutoload } : {}),\n\t\t\t...(typeof chatTemplate === \"string\" ? { chat_template: chatTemplate } : {}),\n\t\t};\n\t}\n\n\tasync load(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models/load\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync unload(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models/unload\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync unloadAndWait(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.unload(model, signal);\n\t\twhile (true) {\n\t\t\tconst entry = (await this.list({ signal })).find((candidate) => candidate.id === model);\n\t\t\tif (!entry || entry.status.value === \"unloaded\") return;\n\t\t\tawait sleep(100, signal);\n\t\t}\n\t}\n\n\tasync download(model: string, signal?: AbortSignal): Promise<void> {\n\t\tawait this.request(\"/models\", { method: \"POST\", body: JSON.stringify({ model }), signal });\n\t}\n\n\tasync watch(onEvent: (event: LlamaModelEvent) => void, signal?: AbortSignal): Promise<void> {\n\t\tconst headers = new Headers();\n\t\tif (this.apiKey) headers.set(\"Authorization\", `Bearer ${this.apiKey}`);\n\t\tconst response = await fetch(`${this.serverUrl}/models/sse`, { headers, signal });\n\t\tif (!response.ok || !response.body) throw new Error(`llama.cpp SSE returned HTTP ${response.status}`);\n\t\tconst reader = response.body.getReader();\n\t\tconst decoder = new TextDecoder();\n\t\tlet buffer = \"\";\n\t\twhile (true) {\n\t\t\tconst chunk = await reader.read();\n\t\t\tif (chunk.done) break;\n\t\t\tbuffer += decoder.decode(chunk.value, { stream: true }).replaceAll(\"\\r\\n\", \"\\n\");\n\t\t\tlet boundary = buffer.indexOf(\"\\n\\n\");\n\t\t\twhile (boundary >= 0) {\n\t\t\t\tconst frame = buffer.slice(0, boundary);\n\t\t\t\tbuffer = buffer.slice(boundary + 2);\n\t\t\t\tconst data = frame\n\t\t\t\t\t.split(\"\\n\")\n\t\t\t\t\t.filter((line) => line.startsWith(\"data:\"))\n\t\t\t\t\t.map((line) => line.slice(5).trimStart())\n\t\t\t\t\t.join(\"\\n\");\n\t\t\t\tif (data) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tconst event = JSON.parse(data) as LlamaModelEvent;\n\t\t\t\t\t\tif (event && typeof event.model === \"string\" && typeof event.event === \"string\") onEvent(event);\n\t\t\t\t\t} catch {\n\t\t\t\t\t\t// Ignore malformed events; catalog polling remains authoritative.\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tboundary = buffer.indexOf(\"\\n\\n\");\n\t\t\t}\n\t\t}\n\t}\n\n\tasync loadAndWait(\n\t\tmodel: string,\n\t\tonProgress: (progress: LlamaProgress) => void,\n\t\tsignal?: AbortSignal,\n\t): Promise<LlamaModelInfo> {\n\t\tconst watcher = new AbortController();\n\t\tconst unlink = linkSignal(signal, watcher);\n\t\tlet eventLoaded = false;\n\t\tlet eventError: string | undefined;\n\t\tvoid this.watch((event) => {\n\t\t\tif (event.model !== model) return;\n\t\t\tif (event.event !== \"model_status\" && event.event !== \"status_change\") return;\n\t\t\tconst data = event.data as { status?: unknown } | undefined;\n\t\t\tif (data?.status === \"loaded\") eventLoaded = true;\n\t\t\tif (data?.status === \"unloaded\") eventError = \"Model failed to load\";\n\t\t\tconst progress = parseLoadProgress(event.data);\n\t\t\tif (progress) onProgress(progress);\n\t\t}, watcher.signal).catch(() => {});\n\t\ttry {\n\t\t\tawait this.load(model, signal);\n\t\t\tonProgress({ message: \"Loading model\" });\n\t\t\twhile (true) {\n\t\t\t\tif (signal?.aborted) throw signal.reason ?? new Error(\"Cancelled\");\n\t\t\t\tconst entry = (await this.list({ signal })).find((candidate) => candidate.id === model);\n\t\t\t\tif (entry?.status.value === \"loaded\") return entry;\n\t\t\t\tif (eventLoaded && !entry) return { id: model, status: { value: \"loaded\" } };\n\t\t\t\tif (entry?.status.failed || eventError) {\n\t\t\t\t\tthrow new Error(\n\t\t\t\t\t\tentry?.status.exit_code === undefined\n\t\t\t\t\t\t\t? (eventError ?? \"Model failed to load\")\n\t\t\t\t\t\t\t: `Model exited with code ${entry.status.exit_code}`,\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t\tawait sleep(250, signal);\n\t\t\t}\n\t\t} finally {\n\t\t\tunlink();\n\t\t\twatcher.abort();\n\t\t}\n\t}\n\n\tasync downloadAndWait(\n\t\tmodel: string,\n\t\tonProgress: (progress: LlamaProgress) => void,\n\t\tsignal?: AbortSignal,\n\t): Promise<LlamaModelInfo[]> {\n\t\tconst watcher = new AbortController();\n\t\tconst unlink = linkSignal(signal, watcher);\n\t\tlet finished = false;\n\t\tlet failure: string | undefined;\n\t\tlet sawDownloading = false;\n\t\tlet polls = 0;\n\t\tvoid this.watch((event) => {\n\t\t\tif (event.model !== model) return;\n\t\t\tif (event.event === \"download_finished\") finished = true;\n\t\t\tif (event.event === \"download_failed\") failure = errorMessage(event.data, \"Download failed\");\n\t\t\tif (event.event === \"download_progress\") {\n\t\t\t\tsawDownloading = true;\n\t\t\t\tconst progress = parseDownloadProgress(event.data);\n\t\t\t\tif (progress) onProgress(progress);\n\t\t\t}\n\t\t}, watcher.signal).catch(() => {});\n\t\ttry {\n\t\t\tawait this.download(model, signal);\n\t\t\tonProgress({ message: \"Downloading model\" });\n\t\t\twhile (true) {\n\t\t\t\tif (signal?.aborted) throw signal.reason ?? new Error(\"Cancelled\");\n\t\t\t\tif (failure) throw new Error(failure);\n\t\t\t\tconst models = await this.list({ signal });\n\t\t\t\tpolls++;\n\t\t\t\tconst entry = models.find((candidate) => candidate.id === model);\n\t\t\t\tif (entry?.status.value === \"downloading\") {\n\t\t\t\t\tsawDownloading = true;\n\t\t\t\t\tconst progress = parseDownloadProgress(entry.status.progress);\n\t\t\t\t\tif (progress) onProgress(progress);\n\t\t\t\t} else if (finished || (entry && (sawDownloading || polls >= 2))) {\n\t\t\t\t\treturn this.list({ reload: true, signal });\n\t\t\t\t}\n\t\t\t\tawait sleep(500, signal);\n\t\t\t}\n\t\t} finally {\n\t\t\tunlink();\n\t\t\twatcher.abort();\n\t\t}\n\t}\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/extensions/llama/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKX,QAAQ,EAGR,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAe,KAAK,cAAc,EAA8C,MAAM,aAAa,CAAC;AAE3G,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAC7C,eAAO,MAAM,wBAAwB,0BAA0B,CAAC;AA4DhE,MAAM,WAAW,uBAAuB;IACvC,QAAQ,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IACzC,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CAC/G;AAED,wBAAgB,mBAAmB,IAAI,uBAAuB,CAqG7D","sourcesContent":["import type {\n\tApiKeyCredential,\n\tAuthContext,\n\tAuthResult,\n\tModel,\n\tProvider,\n\tProviderStreamOptions,\n\tRefreshModelsContext,\n} from \"@earendil-works/pi-ai\";\nimport { stream, streamSimple } from \"@earendil-works/pi-ai/compat\";\nimport { LlamaClient, type LlamaModelInfo, llamaInferenceUrl, normalizeLlamaServerUrl } from \"./client.ts\";\n\nexport const LLAMA_PROVIDER_ID = \"llama.cpp\";\nexport const DEFAULT_LLAMA_SERVER_URL = \"http://127.0.0.1:8080\";\nfunction credentialServerUrl(credential: ApiKeyCredential | undefined): string | undefined {\n\tconst value = credential?.env?.LLAMA_BASE_URL;\n\treturn typeof value === \"string\" && value.trim() ? normalizeLlamaServerUrl(value) : undefined;\n}\n\nasync function resolveServerUrl(\n\tctx: AuthContext,\n\tcredential: ApiKeyCredential | undefined,\n): Promise<string | undefined> {\n\tconst configured = credentialServerUrl(credential) ?? (await ctx.env(\"LLAMA_BASE_URL\"))?.trim();\n\treturn configured ? normalizeLlamaServerUrl(configured) : undefined;\n}\n\nfunction modelIsSelectable(model: LlamaModelInfo, routerAutoload: boolean): boolean {\n\tif (model.status.value === \"loaded\") return true;\n\t// llama.cpp reports idle-slept models as \"sleeping\"; requests wake them automatically.\n\tif (model.status.value === \"sleeping\") return true;\n\t// Unloaded presets are routable only when llama.cpp router autoload can load them on first use.\n\treturn routerAutoload && model.status.value === \"unloaded\" && !model.status.failed && model.source === \"preset\";\n}\n\nasync function routerAutoloadEnabled(\n\tclient: LlamaClient,\n\tcatalog: readonly LlamaModelInfo[],\n\tsignal: AbortSignal,\n): Promise<boolean> {\n\tif (!catalog.some((model) => model.status.value === \"unloaded\" && model.source === \"preset\")) return false;\n\ttry {\n\t\treturn (await client.props({ signal })).models_autoload === true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction toPiModel(model: LlamaModelInfo, serverUrl: string): Model<\"openai-completions\"> {\n\tconst reportedContextWindow = model.meta?.n_ctx ?? model.meta?.n_ctx_train;\n\tconst contextWindow = reportedContextWindow && reportedContextWindow > 0 ? reportedContextWindow : 128000;\n\treturn {\n\t\tid: model.id,\n\t\tname: model.id,\n\t\tapi: \"openai-completions\",\n\t\tprovider: LLAMA_PROVIDER_ID,\n\t\tbaseUrl: llamaInferenceUrl(serverUrl),\n\t\treasoning: false,\n\t\tinput: model.architecture?.input_modalities?.includes(\"image\") ? [\"text\", \"image\"] : [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow,\n\t\tmaxTokens: contextWindow,\n\t\tcompat: {\n\t\t\tsupportsStore: false,\n\t\t\tsupportsDeveloperRole: false,\n\t\t\tsupportsReasoningEffort: false,\n\t\t\tsupportsUsageInStreaming: true,\n\t\t\tsupportsStrictMode: false,\n\t\t\tmaxTokensField: \"max_tokens\",\n\t\t},\n\t};\n}\n\nexport interface LlamaProviderController {\n\tprovider: Provider<\"openai-completions\">;\n\tsetCatalog(models: readonly LlamaModelInfo[], serverUrl: string, options?: { routerAutoload?: boolean }): void;\n}\n\nexport function createLlamaProvider(): LlamaProviderController {\n\tlet models: readonly Model<\"openai-completions\">[] = [];\n\n\tconst setCatalog = (\n\t\tcatalog: readonly LlamaModelInfo[],\n\t\tserverUrl: string,\n\t\toptions: { routerAutoload?: boolean } = {},\n\t): void => {\n\t\tmodels = catalog\n\t\t\t.filter((model) => modelIsSelectable(model, options.routerAutoload === true))\n\t\t\t.map((model) => toPiModel(model, serverUrl));\n\t};\n\n\tconst provider: Provider<\"openai-completions\"> = {\n\t\tid: LLAMA_PROVIDER_ID,\n\t\tname: \"llama.cpp\",\n\t\tbaseUrl: llamaInferenceUrl(DEFAULT_LLAMA_SERVER_URL),\n\t\tauth: {\n\t\t\tapiKey: {\n\t\t\t\tname: \"llama.cpp server\",\n\t\t\t\tlogin: async (interaction): Promise<ApiKeyCredential> => {\n\t\t\t\t\tconst enteredUrl = await interaction.prompt({\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\tmessage: \"llama.cpp server URL\",\n\t\t\t\t\t\tplaceholder: process.env.LLAMA_BASE_URL ?? DEFAULT_LLAMA_SERVER_URL,\n\t\t\t\t\t});\n\t\t\t\t\tconst serverUrl = normalizeLlamaServerUrl(\n\t\t\t\t\t\tenteredUrl.trim() || process.env.LLAMA_BASE_URL || DEFAULT_LLAMA_SERVER_URL,\n\t\t\t\t\t);\n\t\t\t\t\tconst apiKey = (\n\t\t\t\t\t\tawait interaction.prompt({\n\t\t\t\t\t\t\ttype: \"secret\",\n\t\t\t\t\t\t\tmessage: \"API key (optional)\",\n\t\t\t\t\t\t})\n\t\t\t\t\t).trim();\n\t\t\t\t\tawait new LlamaClient(serverUrl, apiKey || undefined).list({ signal: interaction.signal });\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"api_key\",\n\t\t\t\t\t\tkey: apiKey || undefined,\n\t\t\t\t\t\tenv: { LLAMA_BASE_URL: serverUrl },\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\tcheck: async ({ ctx, credential }) => {\n\t\t\t\t\tconst serverUrl = await resolveServerUrl(ctx, credential);\n\t\t\t\t\treturn serverUrl\n\t\t\t\t\t\t? { type: \"api_key\", source: credential ? \"stored credential\" : \"LLAMA_BASE_URL\" }\n\t\t\t\t\t\t: undefined;\n\t\t\t\t},\n\t\t\t\tresolve: async ({ ctx, credential }): Promise<AuthResult | undefined> => {\n\t\t\t\t\tconst serverUrl = await resolveServerUrl(ctx, credential);\n\t\t\t\t\tif (!serverUrl) return undefined;\n\t\t\t\t\tconst apiKey = credential?.key ?? (await ctx.env(\"LLAMA_API_KEY\")) ?? \"local\";\n\t\t\t\t\treturn {\n\t\t\t\t\t\tauth: { apiKey, baseUrl: llamaInferenceUrl(serverUrl) },\n\t\t\t\t\t\tenv: { ...credential?.env, LLAMA_BASE_URL: serverUrl },\n\t\t\t\t\t\tsource: credential ? \"stored credential\" : \"LLAMA_BASE_URL\",\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tgetModels: () => models,\n\t\trefreshModels: async (context: RefreshModelsContext): Promise<void> => {\n\t\t\tif (context.stored) {\n\t\t\t\tconst restored = context.stored.models.filter(\n\t\t\t\t\t(model): model is Model<\"openai-completions\"> =>\n\t\t\t\t\t\tmodel.provider === LLAMA_PROVIDER_ID && model.api === \"openai-completions\",\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\tmodels = restored;\n\t\t\t\t\t\t},\n\t\t\t\t\t}))\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!context.allowNetwork || context.signal.aborted || context.credential?.type !== \"api_key\") return;\n\t\t\tconst serverUrl = credentialServerUrl(context.credential);\n\t\t\tif (!serverUrl) return;\n\t\t\tconst client = new LlamaClient(serverUrl, context.credential.key);\n\t\t\tconst catalog = await client.list({ signal: context.signal });\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst routerAutoload = await routerAutoloadEnabled(client, catalog, context.signal);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst refreshed = catalog\n\t\t\t\t.filter((model) => modelIsSelectable(model, routerAutoload))\n\t\t\t\t.map((model) => toPiModel(model, serverUrl));\n\t\t\tawait context.publish({\n\t\t\t\tpersist: { models: refreshed, checkedAt: Date.now() },\n\t\t\t\tupdate: () => {\n\t\t\t\t\tmodels = refreshed;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tstream: (model, context, options) => stream(model, context, options as ProviderStreamOptions | undefined),\n\t\tstreamSimple: (model, context, options) => streamSimple(model, context, options),\n\t};\n\n\treturn { provider, setCatalog };\n}\n"]}
1
+ {"version":3,"file":"provider.d.ts","sourceRoot":"","sources":["../../../src/extensions/llama/provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAKX,QAAQ,EAGR,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAEN,KAAK,cAAc,EAInB,MAAM,aAAa,CAAC;AAErB,eAAO,MAAM,iBAAiB,cAAc,CAAC;AAC7C,eAAO,MAAM,wBAAwB,0BAA0B,CAAC;AAiEhE,MAAM,WAAW,uBAAuB;IACvC,QAAQ,EAAE,QAAQ,CAAC,oBAAoB,CAAC,CAAC;IACzC,UAAU,CAAC,MAAM,EAAE,SAAS,cAAc,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE;QAAE,cAAc,CAAC,EAAE,OAAO,CAAA;KAAE,GAAG,IAAI,CAAC;CAC/G;AAED,wBAAgB,mBAAmB,IAAI,uBAAuB,CA+G7D","sourcesContent":["import type {\n\tApiKeyCredential,\n\tAuthContext,\n\tAuthResult,\n\tModel,\n\tProvider,\n\tProviderStreamOptions,\n\tRefreshModelsContext,\n} from \"@earendil-works/pi-ai\";\nimport { stream, streamSimple } from \"@earendil-works/pi-ai/compat\";\nimport {\n\tLlamaClient,\n\ttype LlamaModelInfo,\n\ttype LlamaServerProps,\n\tllamaInferenceUrl,\n\tnormalizeLlamaServerUrl,\n} from \"./client.ts\";\n\nexport const LLAMA_PROVIDER_ID = \"llama.cpp\";\nexport const DEFAULT_LLAMA_SERVER_URL = \"http://127.0.0.1:8080\";\nfunction credentialServerUrl(credential: ApiKeyCredential | undefined): string | undefined {\n\tconst value = credential?.env?.LLAMA_BASE_URL;\n\treturn typeof value === \"string\" && value.trim() ? normalizeLlamaServerUrl(value) : undefined;\n}\n\nasync function resolveServerUrl(\n\tctx: AuthContext,\n\tcredential: ApiKeyCredential | undefined,\n): Promise<string | undefined> {\n\tconst configured = credentialServerUrl(credential) ?? (await ctx.env(\"LLAMA_BASE_URL\"))?.trim();\n\treturn configured ? normalizeLlamaServerUrl(configured) : undefined;\n}\n\nfunction modelIsSelectable(model: LlamaModelInfo, routerAutoload: boolean): boolean {\n\tif (model.status.value === \"loaded\") return true;\n\t// llama.cpp reports idle-slept models as \"sleeping\"; requests wake them automatically.\n\tif (model.status.value === \"sleeping\") return true;\n\t// Unloaded presets are routable only when llama.cpp router autoload can load them on first use.\n\treturn routerAutoload && model.status.value === \"unloaded\" && !model.status.failed && model.source === \"preset\";\n}\n\nasync function routerAutoloadEnabled(\n\tclient: LlamaClient,\n\tcatalog: readonly LlamaModelInfo[],\n\tsignal: AbortSignal,\n): Promise<boolean> {\n\tif (!catalog.some((model) => model.status.value === \"unloaded\" && model.source === \"preset\")) return false;\n\ttry {\n\t\treturn (await client.props({ signal })).models_autoload === true;\n\t} catch {\n\t\treturn false;\n\t}\n}\n\nfunction toPiModel(model: LlamaModelInfo, serverUrl: string, props?: LlamaServerProps): Model<\"openai-completions\"> {\n\tconst reportedContextWindow = model.meta?.n_ctx ?? model.meta?.n_ctx_train;\n\tconst contextWindow = reportedContextWindow && reportedContextWindow > 0 ? reportedContextWindow : 128000;\n\tconst reasoning = props?.chat_template?.includes(\"enable_thinking\") === true;\n\treturn {\n\t\tid: model.id,\n\t\tname: model.id,\n\t\tapi: \"openai-completions\",\n\t\tprovider: LLAMA_PROVIDER_ID,\n\t\tbaseUrl: llamaInferenceUrl(serverUrl),\n\t\treasoning,\n\t\t...(reasoning && {\n\t\t\tthinkingLevelMap: { off: \"off\", minimal: null, low: null, medium: \"medium\", high: null, xhigh: null },\n\t\t}),\n\t\tinput: model.architecture?.input_modalities?.includes(\"image\") ? [\"text\", \"image\"] : [\"text\"],\n\t\tcost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },\n\t\tcontextWindow,\n\t\tmaxTokens: contextWindow,\n\t\tcompat: {\n\t\t\tsupportsStore: false,\n\t\t\tsupportsDeveloperRole: false,\n\t\t\tsupportsReasoningEffort: false,\n\t\t\tsupportsUsageInStreaming: true,\n\t\t\tsupportsStrictMode: false,\n\t\t\tmaxTokensField: \"max_tokens\",\n\t\t\t...(reasoning && { thinkingFormat: \"qwen-chat-template\" }),\n\t\t},\n\t};\n}\n\nexport interface LlamaProviderController {\n\tprovider: Provider<\"openai-completions\">;\n\tsetCatalog(models: readonly LlamaModelInfo[], serverUrl: string, options?: { routerAutoload?: boolean }): void;\n}\n\nexport function createLlamaProvider(): LlamaProviderController {\n\tlet models: readonly Model<\"openai-completions\">[] = [];\n\n\tconst setCatalog = (\n\t\tcatalog: readonly LlamaModelInfo[],\n\t\tserverUrl: string,\n\t\toptions: { routerAutoload?: boolean } = {},\n\t): void => {\n\t\tmodels = catalog\n\t\t\t.filter((model) => modelIsSelectable(model, options.routerAutoload === true))\n\t\t\t.map((model) => toPiModel(model, serverUrl));\n\t};\n\n\tconst provider: Provider<\"openai-completions\"> = {\n\t\tid: LLAMA_PROVIDER_ID,\n\t\tname: \"llama.cpp\",\n\t\tbaseUrl: llamaInferenceUrl(DEFAULT_LLAMA_SERVER_URL),\n\t\tauth: {\n\t\t\tapiKey: {\n\t\t\t\tname: \"llama.cpp server\",\n\t\t\t\tlogin: async (interaction): Promise<ApiKeyCredential> => {\n\t\t\t\t\tconst enteredUrl = await interaction.prompt({\n\t\t\t\t\t\ttype: \"text\",\n\t\t\t\t\t\tmessage: \"llama.cpp server URL\",\n\t\t\t\t\t\tplaceholder: process.env.LLAMA_BASE_URL ?? DEFAULT_LLAMA_SERVER_URL,\n\t\t\t\t\t});\n\t\t\t\t\tconst serverUrl = normalizeLlamaServerUrl(\n\t\t\t\t\t\tenteredUrl.trim() || process.env.LLAMA_BASE_URL || DEFAULT_LLAMA_SERVER_URL,\n\t\t\t\t\t);\n\t\t\t\t\tconst apiKey = (\n\t\t\t\t\t\tawait interaction.prompt({\n\t\t\t\t\t\t\ttype: \"secret\",\n\t\t\t\t\t\t\tmessage: \"API key (optional)\",\n\t\t\t\t\t\t})\n\t\t\t\t\t).trim();\n\t\t\t\t\tawait new LlamaClient(serverUrl, apiKey || undefined).list({ signal: interaction.signal });\n\t\t\t\t\treturn {\n\t\t\t\t\t\ttype: \"api_key\",\n\t\t\t\t\t\tkey: apiKey || undefined,\n\t\t\t\t\t\tenv: { LLAMA_BASE_URL: serverUrl },\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t\tcheck: async ({ ctx, credential }) => {\n\t\t\t\t\tconst serverUrl = await resolveServerUrl(ctx, credential);\n\t\t\t\t\treturn serverUrl\n\t\t\t\t\t\t? { type: \"api_key\", source: credential ? \"stored credential\" : \"LLAMA_BASE_URL\" }\n\t\t\t\t\t\t: undefined;\n\t\t\t\t},\n\t\t\t\tresolve: async ({ ctx, credential }): Promise<AuthResult | undefined> => {\n\t\t\t\t\tconst serverUrl = await resolveServerUrl(ctx, credential);\n\t\t\t\t\tif (!serverUrl) return undefined;\n\t\t\t\t\tconst apiKey = credential?.key ?? (await ctx.env(\"LLAMA_API_KEY\")) ?? \"local\";\n\t\t\t\t\treturn {\n\t\t\t\t\t\tauth: { apiKey, baseUrl: llamaInferenceUrl(serverUrl) },\n\t\t\t\t\t\tenv: { ...credential?.env, LLAMA_BASE_URL: serverUrl },\n\t\t\t\t\t\tsource: credential ? \"stored credential\" : \"LLAMA_BASE_URL\",\n\t\t\t\t\t};\n\t\t\t\t},\n\t\t\t},\n\t\t},\n\t\tgetModels: () => models,\n\t\trefreshModels: async (context: RefreshModelsContext): Promise<void> => {\n\t\t\tif (context.stored) {\n\t\t\t\tconst restored = context.stored.models.filter(\n\t\t\t\t\t(model): model is Model<\"openai-completions\"> =>\n\t\t\t\t\t\tmodel.provider === LLAMA_PROVIDER_ID && model.api === \"openai-completions\",\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\t!(await context.publish({\n\t\t\t\t\t\tupdate: () => {\n\t\t\t\t\t\t\tmodels = restored;\n\t\t\t\t\t\t},\n\t\t\t\t\t}))\n\t\t\t\t) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif (!context.allowNetwork || context.signal.aborted || context.credential?.type !== \"api_key\") return;\n\t\t\tconst serverUrl = credentialServerUrl(context.credential);\n\t\t\tif (!serverUrl) return;\n\t\t\tconst client = new LlamaClient(serverUrl, context.credential.key);\n\t\t\tconst catalog = await client.list({ signal: context.signal });\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst routerAutoload = await routerAutoloadEnabled(client, catalog, context.signal);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tconst refreshed = await Promise.all(\n\t\t\t\tcatalog\n\t\t\t\t\t.filter((model) => modelIsSelectable(model, routerAutoload))\n\t\t\t\t\t.map(async (model) => {\n\t\t\t\t\t\t// Only loaded models expose their template without side effects. Unloaded autoload presets\n\t\t\t\t\t\t// would need to be loaded, while querying sleeping models may wake them. Those models remain\n\t\t\t\t\t\t// unclassified until they are loaded or woken and a later catalog refresh discovers them.\n\t\t\t\t\t\tif (model.status.value !== \"loaded\") return toPiModel(model, serverUrl);\n\t\t\t\t\t\tconst props = await client.props({ model: model.id, signal: context.signal });\n\t\t\t\t\t\treturn toPiModel(model, serverUrl, props);\n\t\t\t\t\t}),\n\t\t\t);\n\t\t\tif (context.signal.aborted) return;\n\t\t\tawait context.publish({\n\t\t\t\tpersist: { models: refreshed, checkedAt: Date.now() },\n\t\t\t\tupdate: () => {\n\t\t\t\t\tmodels = refreshed;\n\t\t\t\t},\n\t\t\t});\n\t\t},\n\t\tstream: (model, context, options) => stream(model, context, options as ProviderStreamOptions | undefined),\n\t\tstreamSimple: (model, context, options) => streamSimple(model, context, options),\n\t};\n\n\treturn { provider, setCatalog };\n}\n"]}
@@ -1,5 +1,5 @@
1
1
  import { stream, streamSimple } from "@earendil-works/pi-ai/compat";
2
- import { LlamaClient, llamaInferenceUrl, normalizeLlamaServerUrl } from "./client.js";
2
+ import { LlamaClient, llamaInferenceUrl, normalizeLlamaServerUrl, } from "./client.js";
3
3
  export const LLAMA_PROVIDER_ID = "llama.cpp";
4
4
  export const DEFAULT_LLAMA_SERVER_URL = "http://127.0.0.1:8080";
5
5
  function credentialServerUrl(credential) {
@@ -29,16 +29,20 @@ async function routerAutoloadEnabled(client, catalog, signal) {
29
29
  return false;
30
30
  }
31
31
  }
32
- function toPiModel(model, serverUrl) {
32
+ function toPiModel(model, serverUrl, props) {
33
33
  const reportedContextWindow = model.meta?.n_ctx ?? model.meta?.n_ctx_train;
34
34
  const contextWindow = reportedContextWindow && reportedContextWindow > 0 ? reportedContextWindow : 128000;
35
+ const reasoning = props?.chat_template?.includes("enable_thinking") === true;
35
36
  return {
36
37
  id: model.id,
37
38
  name: model.id,
38
39
  api: "openai-completions",
39
40
  provider: LLAMA_PROVIDER_ID,
40
41
  baseUrl: llamaInferenceUrl(serverUrl),
41
- reasoning: false,
42
+ reasoning,
43
+ ...(reasoning && {
44
+ thinkingLevelMap: { off: "off", minimal: null, low: null, medium: "medium", high: null, xhigh: null },
45
+ }),
42
46
  input: model.architecture?.input_modalities?.includes("image") ? ["text", "image"] : ["text"],
43
47
  cost: { input: 0, output: 0, cacheRead: 0, cacheWrite: 0 },
44
48
  contextWindow,
@@ -50,6 +54,7 @@ function toPiModel(model, serverUrl) {
50
54
  supportsUsageInStreaming: true,
51
55
  supportsStrictMode: false,
52
56
  maxTokensField: "max_tokens",
57
+ ...(reasoning && { thinkingFormat: "qwen-chat-template" }),
53
58
  },
54
59
  };
55
60
  }
@@ -128,9 +133,19 @@ export function createLlamaProvider() {
128
133
  const routerAutoload = await routerAutoloadEnabled(client, catalog, context.signal);
129
134
  if (context.signal.aborted)
130
135
  return;
131
- const refreshed = catalog
136
+ const refreshed = await Promise.all(catalog
132
137
  .filter((model) => modelIsSelectable(model, routerAutoload))
133
- .map((model) => toPiModel(model, serverUrl));
138
+ .map(async (model) => {
139
+ // Only loaded models expose their template without side effects. Unloaded autoload presets
140
+ // would need to be loaded, while querying sleeping models may wake them. Those models remain
141
+ // unclassified until they are loaded or woken and a later catalog refresh discovers them.
142
+ if (model.status.value !== "loaded")
143
+ return toPiModel(model, serverUrl);
144
+ const props = await client.props({ model: model.id, signal: context.signal });
145
+ return toPiModel(model, serverUrl, props);
146
+ }));
147
+ if (context.signal.aborted)
148
+ return;
134
149
  await context.publish({
135
150
  persist: { models: refreshed, checkedAt: Date.now() },
136
151
  update: () => {