mu-agent 0.1.7 → 0.1.10

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 (198) hide show
  1. package/CHANGELOG.md +52 -0
  2. package/README.md +34 -29
  3. package/dist/bundle/chunks/anthropic-messages-4PAJY4R6.js +6 -0
  4. package/dist/bundle/chunks/anthropic.js +2 -2
  5. package/dist/bundle/chunks/azure-openai-responses-Y4BBWQ3N.js +2 -0
  6. package/dist/bundle/chunks/bedrock-converse-stream.js +12 -9
  7. package/dist/bundle/chunks/{chunk-TRDNDS6A.js → chunk-3V45WARH.js} +6 -3
  8. package/dist/bundle/chunks/{chunk-XDUWOHPL.js → chunk-5AGIVGSV.js} +3 -3
  9. package/dist/bundle/chunks/chunk-6QGV3IWD.js +6 -0
  10. package/dist/bundle/chunks/chunk-7CBJINYJ.js +20 -0
  11. package/dist/bundle/chunks/{chunk-DRQDKNXA.js → chunk-7DDKXS2Q.js} +1 -1
  12. package/dist/bundle/chunks/chunk-BSS6T6KQ.js +2 -0
  13. package/dist/bundle/chunks/chunk-CF5GWZHW.js +31 -0
  14. package/dist/bundle/chunks/chunk-DNNHZBQR.js +4 -0
  15. package/dist/bundle/chunks/chunk-FN6OEZYR.js +2 -0
  16. package/dist/bundle/chunks/chunk-FTJT2X6E.js +2 -0
  17. package/dist/bundle/chunks/chunk-HZNN636Z.js +130 -0
  18. package/dist/bundle/chunks/{chunk-4L3WN2XY.js → chunk-JXWJOIH4.js} +1 -1
  19. package/dist/bundle/chunks/{chunk-4O2SCVYF.js → chunk-KIDDRTZP.js} +4 -4
  20. package/dist/bundle/chunks/chunk-LMNWTX2L.js +11 -0
  21. package/dist/bundle/chunks/chunk-LPXNMA2W.js +2 -0
  22. package/dist/bundle/chunks/{chunk-6CYCI3EJ.js → chunk-LVVZS2NO.js} +1 -1
  23. package/dist/bundle/chunks/chunk-NN4BEPYX.js +2 -0
  24. package/dist/bundle/chunks/chunk-O7IPTASE.js +1221 -0
  25. package/dist/bundle/chunks/chunk-PMRZO46Y.js +2 -0
  26. package/dist/bundle/chunks/chunk-QOEEJKS4.js +9 -0
  27. package/dist/bundle/chunks/chunk-R4VPBBDS.js +2 -0
  28. package/dist/bundle/chunks/chunk-RAQ6TU76.js +2 -0
  29. package/dist/bundle/chunks/chunk-RDZVAGPR.js +2 -0
  30. package/dist/bundle/chunks/chunk-SGOTYFMT.js +91 -0
  31. package/dist/bundle/chunks/chunk-TMTOQ7H7.js +2 -0
  32. package/dist/bundle/chunks/chunk-UKVNB6C4.js +2 -0
  33. package/dist/bundle/chunks/chunk-VJLOQZKR.js +9 -0
  34. package/dist/bundle/chunks/chunk-WCGU75WO.js +11 -0
  35. package/dist/bundle/chunks/chunk-X234222Q.js +64 -0
  36. package/dist/bundle/chunks/cli-722OL3K5.js +51 -0
  37. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-MEZHQVNP.js +2 -0
  38. package/dist/bundle/chunks/codemode-worker.js +478 -0
  39. package/dist/bundle/chunks/easter-egg-3d-6H34EDGX.js +2 -0
  40. package/dist/bundle/chunks/execute-KVSEIDWL.js +499 -0
  41. package/dist/bundle/chunks/github-copilot.js +1 -1
  42. package/dist/bundle/chunks/{google-generative-ai-C44KRRZ4.js → google-generative-ai-D2VJQBTK.js} +1 -1
  43. package/dist/bundle/chunks/{google-vertex-25DUXPTJ.js → google-vertex-SQG2BO6C.js} +1 -1
  44. package/dist/bundle/chunks/https-proxy-agent-LVOO5TPL.js +13 -0
  45. package/dist/bundle/chunks/image-resize-worker.js +1 -1
  46. package/dist/bundle/chunks/{jiti-loader-C3NU2SDH.js → jiti-loader-GL4HJFAD.js} +1 -1
  47. package/dist/bundle/chunks/{jiti-static-loader-E6ANQD5T.js → jiti-static-loader-2RCDI6B4.js} +1 -1
  48. package/dist/bundle/chunks/{lib-HGQMNYVT.js → lib-4AVRLBHM.js} +2 -2
  49. package/dist/bundle/chunks/llama-cpp-classify-5YHLY3RC.js +22 -0
  50. package/dist/bundle/chunks/mistral-conversations-BDARVJTT.js +5 -0
  51. package/dist/bundle/chunks/{multipart-parser-SQ6GDJL7.js → multipart-parser-FMGQ7342.js} +1 -1
  52. package/dist/bundle/chunks/{node-TWVVAGPO.js → node-AUOGOBCN.js} +1 -1
  53. package/dist/bundle/chunks/node-KCMANYC2.js +16 -0
  54. package/dist/bundle/chunks/openai-chatgpt.js +86 -0
  55. package/dist/bundle/chunks/openai-codex-responses-CECGTDYD.js +10 -0
  56. package/dist/bundle/chunks/openai-codex.js +2 -2
  57. package/dist/bundle/chunks/openai-completions-UOA7MELD.js +7 -0
  58. package/dist/bundle/chunks/openai-decisions-HLM372N6.js +5 -0
  59. package/dist/bundle/chunks/openai-responses-TII7ZY5X.js +3 -0
  60. package/dist/bundle/chunks/{openrouter-images-JVEJN44Q.js → openrouter-images-7T452AS5.js} +1 -1
  61. package/dist/bundle/chunks/openrouter.js +2 -2
  62. package/dist/bundle/chunks/{pi-messages-TM5SOOIW.js → pi-messages-2UDKLKOO.js} +1 -1
  63. package/dist/bundle/chunks/radius.js +2 -2
  64. package/dist/bundle/chunks/runtime-O3ELDOM7.js +2 -0
  65. package/dist/bundle/chunks/{src-UK77SYZE.js → src-QKGKDFSU.js} +1 -1
  66. package/dist/bundle/chunks/typesafe-system-one-KNCICMO5.js +2 -0
  67. package/dist/bundle/chunks/virtual-modules-IKEARUOZ.js +2 -0
  68. package/dist/bundle/cli-runtime.js +1 -1
  69. package/dist/bundle/index.js +1 -1
  70. package/dist/bundle/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
  71. package/dist/bundle/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
  72. package/dist/bundle/rpc-entry.js +1 -1
  73. package/dist/core/export-html/template.js +37 -16
  74. package/dist/modes/interactive/theme/dark.json +60 -73
  75. package/dist/modes/interactive/theme/light.json +58 -70
  76. package/dist/modes/interactive/theme/system-theme.d.ts +55 -0
  77. package/dist/modes/interactive/theme/system-theme.d.ts.map +1 -0
  78. package/dist/modes/interactive/theme/system-theme.js +546 -0
  79. package/dist/modes/interactive/theme/system-theme.js.map +1 -0
  80. package/dist/modes/interactive/theme/theme-controller.d.ts +43 -9
  81. package/dist/modes/interactive/theme/theme-controller.d.ts.map +1 -1
  82. package/dist/modes/interactive/theme/theme-controller.js +121 -79
  83. package/dist/modes/interactive/theme/theme-controller.js.map +1 -1
  84. package/dist/modes/interactive/theme/theme-schema.d.ts +28 -0
  85. package/dist/modes/interactive/theme/theme-schema.d.ts.map +1 -0
  86. package/dist/modes/interactive/theme/theme-schema.js +105 -0
  87. package/dist/modes/interactive/theme/theme-schema.js.map +1 -0
  88. package/dist/modes/interactive/theme/theme-tokens.d.ts +257 -0
  89. package/dist/modes/interactive/theme/theme-tokens.d.ts.map +1 -0
  90. package/dist/modes/interactive/theme/theme-tokens.js +94 -0
  91. package/dist/modes/interactive/theme/theme-tokens.js.map +1 -0
  92. package/dist/modes/interactive/theme/theme.d.ts +47 -56
  93. package/dist/modes/interactive/theme/theme.d.ts.map +1 -1
  94. package/dist/modes/interactive/theme/theme.js +149 -143
  95. package/dist/modes/interactive/theme/theme.js.map +1 -1
  96. package/dist/native/darwin/prebuilds/darwin-arm64/darwin-platform.node +0 -0
  97. package/dist/native/darwin/prebuilds/darwin-x64/darwin-platform.node +0 -0
  98. package/docs/cli-integration.md +1 -1
  99. package/docs/cli.md +78 -13
  100. package/docs/codemode.md +230 -0
  101. package/docs/compaction.md +5 -5
  102. package/docs/configuration.md +2 -0
  103. package/docs/custom-provider.md +53 -1
  104. package/docs/docs.json +21 -1
  105. package/docs/environment-variables.md +5 -3
  106. package/docs/extensions.md +172 -10
  107. package/docs/index.md +1 -1
  108. package/docs/json.md +3 -3
  109. package/docs/keybindings.md +7 -6
  110. package/docs/llama-cpp.md +21 -1
  111. package/docs/mcp.md +272 -0
  112. package/docs/message-types.md +22 -4
  113. package/docs/models-configuration.md +187 -0
  114. package/docs/models.md +100 -2
  115. package/docs/nvidia-rtx-llama-cpp.md +96 -0
  116. package/docs/packages.md +1 -1
  117. package/docs/providers.md +66 -6
  118. package/docs/quickstart.md +16 -2
  119. package/docs/rpc-commands.md +9 -3
  120. package/docs/rpc.md +3 -1
  121. package/docs/sdk.md +8 -3
  122. package/docs/security.md +2 -0
  123. package/docs/session-format.md +5 -1
  124. package/docs/sessions.md +1 -1
  125. package/docs/settings.md +30 -8
  126. package/docs/terminal-setup.md +14 -0
  127. package/docs/themes.md +31 -7
  128. package/docs/tui.md +71 -1
  129. package/docs/usage.md +2 -2
  130. package/docs/virtual-models.md +114 -0
  131. package/docs/windows.md +2 -0
  132. package/examples/README.md +1 -4
  133. package/examples/extensions/README.md +1 -0
  134. package/examples/extensions/built-in-tool-renderer.ts +16 -40
  135. package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
  136. package/examples/extensions/custom-provider-anthropic/package.json +1 -1
  137. package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
  138. package/examples/extensions/custom-provider-gitlab-duo/test.ts +5 -5
  139. package/examples/extensions/dynamic-resources/dynamic.json +1 -1
  140. package/examples/extensions/gondolin/package-lock.json +2 -2
  141. package/examples/extensions/gondolin/package.json +1 -1
  142. package/examples/extensions/jev-router.ts +113 -0
  143. package/examples/extensions/minimal-mode.ts +28 -101
  144. package/examples/extensions/overlay-test.ts +2 -2
  145. package/examples/extensions/plan-mode/index.ts +6 -2
  146. package/examples/extensions/sandbox/package-lock.json +2 -2
  147. package/examples/extensions/sandbox/package.json +1 -1
  148. package/examples/extensions/subagent/index.ts +4 -6
  149. package/examples/extensions/with-deps/package-lock.json +2 -2
  150. package/examples/extensions/with-deps/package.json +1 -1
  151. package/examples/rpc-client.ts +1 -1
  152. package/examples/rpc-extension-ui.ts +1 -1
  153. package/examples/sdk/14-codemode-mcp.ts +61 -0
  154. package/examples/sdk/README.md +2 -1
  155. package/judge/THIRD_PARTY_NOTICES.md +63 -0
  156. package/judge/dist/auth.js +169 -123
  157. package/judge/dist/import.js +36 -30
  158. package/judge/dist/setup.js +250 -120
  159. package/judge/manifest.json +1008 -316
  160. package/judge/{dist/kyrn-judge.js → mu/index.js} +6933 -5995
  161. package/judge/themes/mu-dark.json +80 -0
  162. package/judge/themes/mu-light.json +80 -0
  163. package/kyrn/bin/kyrn-doctor +75 -25
  164. package/kyrn/bin/kyrn-judge-local +2 -2
  165. package/kyrn/bin/kyrn-ledger +1 -1
  166. package/kyrn/bin/mu.mjs +149 -107
  167. package/package.json +4 -5
  168. package/dist/bundle/chunks/anthropic-messages-VMESUHQ7.js +0 -6
  169. package/dist/bundle/chunks/azure-openai-responses-K232MQFF.js +0 -2
  170. package/dist/bundle/chunks/chunk-A3JYRWB6.js +0 -2
  171. package/dist/bundle/chunks/chunk-AYFRR3OD.js +0 -2
  172. package/dist/bundle/chunks/chunk-DTD7JQ7Y.js +0 -42
  173. package/dist/bundle/chunks/chunk-FU4XQUSL.js +0 -11
  174. package/dist/bundle/chunks/chunk-GNYZK6XN.js +0 -2
  175. package/dist/bundle/chunks/chunk-HEMXN7VJ.js +0 -1653
  176. package/dist/bundle/chunks/chunk-MVPXOVOJ.js +0 -2
  177. package/dist/bundle/chunks/chunk-NUHFSC37.js +0 -25
  178. package/dist/bundle/chunks/chunk-V7IXECST.js +0 -11
  179. package/dist/bundle/chunks/chunk-XNGRGP62.js +0 -2
  180. package/dist/bundle/chunks/cloudflare-workers-ai-system-one-NR2TDCXU.js +0 -2
  181. package/dist/bundle/chunks/https-proxy-agent-2VXB7436.js +0 -13
  182. package/dist/bundle/chunks/mistral-conversations-6IHQOR4R.js +0 -5
  183. package/dist/bundle/chunks/node-O3RIBJRH.js +0 -16
  184. package/dist/bundle/chunks/openai-codex-responses-3UAYOSSR.js +0 -10
  185. package/dist/bundle/chunks/openai-completions-FIEQGWAH.js +0 -7
  186. package/dist/bundle/chunks/openai-responses-OZJXLHFC.js +0 -2
  187. package/dist/bundle/chunks/typesafe-system-one-VKYX4OGY.js +0 -2
  188. package/dist/bundle/chunks/virtual-modules-V7SXVVLP.js +0 -2
  189. package/dist/modes/interactive/theme/theme-json.d.ts +0 -85
  190. package/dist/modes/interactive/theme/theme-json.d.ts.map +0 -1
  191. package/dist/modes/interactive/theme/theme-json.js +0 -132
  192. package/dist/modes/interactive/theme/theme-json.js.map +0 -1
  193. package/dist/modes/interactive/theme/theme-schema.json +0 -361
  194. package/examples/plugins/pi-example-plugin/README.md +0 -38
  195. package/examples/plugins/pi-example-plugin/package.json +0 -10
  196. package/examples/plugins/pi-example-plugin/src/contract.ts +0 -13
  197. package/examples/plugins/pi-example-plugin/src/session.ts +0 -24
  198. package/examples/plugins/pi-example-plugin/src/tui.ts +0 -31
package/kyrn/bin/mu.mjs CHANGED
@@ -94,26 +94,28 @@ export function platformName({ platform, wsl }) {
94
94
  export function usage(platform) {
95
95
  const linkDir = platform === "win32" ? "%USERPROFILE%\\.local\\bin" : "~/.local/bin";
96
96
  return [
97
- "mu command line. (The project was called KYRN until 2026-09-21; the old spellings below still work.)",
97
+ "mu: a coding agent with a judgment kernel, built on pi.",
98
98
  "",
99
- " mu interactive session in the current directory",
100
- ' mu "prompt" interactive, starting with this prompt',
101
- ' mu -p "prompt" one-shot: print the answer and exit',
102
- " mu -c | -r continue the last session | pick one to resume",
103
- " mu setup connect a model (an API key, or a service from a list) and choose the judge",
104
- " (mu setup --help: scripts, a key from stdin, the services it knows)",
105
- " mu judge <cmd> the local judge (Laya): setup | start | stop | status | run",
106
- " mu ledger [n] [--json] what the judge decided in the last n sessions",
107
- " mu import --list | <file>... bring Claude Code and Codex conversations into mu (mu import --help)",
108
- " mu doctor check the installation",
109
- " mu auth <cmd> subscription sign-in for the desktop app, as JSON lines:",
99
+ " mu start a session in the current directory",
100
+ ' mu "prompt" start a session with this prompt',
101
+ ' mu -p "prompt" run one prompt, print the answer and exit',
102
+ " mu -c | -r continue the last session | pick a session to resume",
103
+ " mu setup connect a model (paste an API key or pick a service) and choose a judge",
104
+ " (see mu setup --help for scripting, reading a key from stdin and the supported services)",
105
+ " mu judge <cmd> manage the local judge, Laya (macOS on Apple silicon): setup | start | stop | status | run",
106
+ " mu ledger [n] [--json] print the judge's verdicts from the last n sessions",
107
+ " mu import --list | <file>... import Claude Code and Codex conversations (mu import --help)",
108
+ " mu doctor check the installation, the judges and the connections",
109
+ " mu auth <cmd> sign-in helper for the desktop app (JSON lines):",
110
110
  " status | login <provider> | logout <provider>",
111
- ` mu link | unlink put the \`mu\` command on your PATH (${linkDir}) | remove it`,
112
- " mu migrate [--dry-run] once: move the home from before the rename, ~/.kyrn, to ~/.mu",
113
- " mu help | version",
111
+ ` mu link | unlink put the mu command on your PATH (${linkDir}) | remove it`,
112
+ " mu migrate [--dry-run] move the old home folder, ~/.kyrn, to ~/.mu (once)",
113
+ " mu help | version show this help | print the version",
114
114
  "",
115
- "Everything else goes to the agent unchanged: `mu --help` lists every flag,",
116
- "and `mu install|remove|update|list|config` manage pi packages.",
115
+ "Everything else goes to pi unchanged: mu --help also shows pi's options,",
116
+ "and mu install|remove|update|list|config manage pi packages.",
117
+ "",
118
+ "Formerly KYRN: the kyrn commands still work.",
117
119
  ].join("\n");
118
120
  }
119
121
 
@@ -310,7 +312,7 @@ export function ensureAppView({ platform, app, upstream, fs = realFs }) {
310
312
  /**
311
313
  * Where this mu comes from: "repo", a checkout that runs the TypeScript sources (sourceRuntime), or "package", the
312
314
  * npm package mu-agent, which carries pi's bundle (dist/bundle/cli.js) and the judgment layer built to
313
- * JavaScript (judge/dist/kyrn-judge.js). A checkout without its dependencies is still a checkout.
315
+ * JavaScript (judge/mu/index.js). A checkout without its dependencies is still a checkout.
314
316
  */
315
317
  export function layoutOf({ root, platform, exists }) {
316
318
  const path = pathFor(platform);
@@ -326,7 +328,7 @@ export function packageEntries({ root, platform }) {
326
328
  const path = pathFor(platform);
327
329
  return {
328
330
  cli: path.join(root, "dist", "bundle", "cli.js"),
329
- extension: path.join(root, "judge", "dist", "kyrn-judge.js"),
331
+ extension: path.join(root, "judge", "mu", "index.js"),
330
332
  auth: path.join(root, "judge", "dist", "auth.js"),
331
333
  import: path.join(root, "judge", "dist", "import.js"),
332
334
  setup: path.join(root, "judge", "dist", "setup.js"),
@@ -339,59 +341,45 @@ export function envFilePath({ layout, root, muDir, platform }) {
339
341
  }
340
342
 
341
343
  /**
342
- * The JavaScript file behind the `tsx` command. node_modules/.bin/tsx is a `.cmd` shim on Windows, and a shim
343
- * can only be started through a shell, where a prompt with quotes or `&` in it is re-parsed. Running the real
344
- * entry with the Node that runs this file avoids the shell on every platform.
344
+ * Whether a checkout's dependencies are installed: undici, which pi and the judgment layer both depend on, is found
345
+ * the way Node resolves an import: here, then in every parent. A git worktree of this repository kept under the
346
+ * main checkout (as the agent worktrees are) has no node_modules of its own and runs on the main checkout's,
347
+ * exactly as its imports do.
345
348
  */
346
- export function resolveTsx({ root, platform, exists, readFile }) {
349
+ export function dependenciesInstalled({ root, platform, exists }) {
347
350
  const path = pathFor(platform);
348
- // Looked for the way Node resolves an import: here, then in every parent. A git worktree of this repository
349
- // kept under the main checkout (as the agent worktrees are) has no node_modules of its own and runs on the
350
- // main checkout's, exactly as its imports do.
351
351
  for (let dir = root; ; dir = path.dirname(dir)) {
352
- const entry = tsxEntry(path.join(dir, "node_modules", "tsx"), path, exists, readFile);
353
- if (entry) return entry;
354
- if (path.dirname(dir) === dir) return undefined;
352
+ if (exists(path.join(dir, "node_modules", "undici", "package.json"))) return true;
353
+ if (path.dirname(dir) === dir) return false;
355
354
  }
356
355
  }
357
356
 
358
- function tsxEntry(dir, path, exists, readFile) {
359
- let bin;
360
- try {
361
- bin = JSON.parse(readFile(path.join(dir, "package.json"))).bin;
362
- } catch {
363
- return undefined;
364
- }
365
- const relative = typeof bin === "string" ? bin : bin?.tsx;
366
- if (typeof relative !== "string") return undefined;
367
- const entry = path.join(dir, ...relative.split("/").filter((part) => part && part !== "."));
368
- return exists(entry) ? entry : undefined;
369
- }
370
-
371
357
  export function installHint({ root, platform }) {
372
358
  const steps = [`cd ${root}`, "npm ci --ignore-scripts", "npm run hydrate:model-data"];
373
359
  // Windows PowerShell 5 has no `&&`.
374
360
  return platform === "win32"
375
- ? `mu's dependencies are not installed. Run:\n${steps.map((step) => ` ${step}`).join("\n")}`
376
- : `mu's dependencies are not installed. Run: ${steps.join(" && ")}`;
361
+ ? `mu's dependencies aren't installed. Run:\n${steps.map((step) => ` ${step}`).join("\n")}`
362
+ : `mu's dependencies aren't installed. Run: ${steps.join(" && ")}`;
377
363
  }
378
364
 
365
+ /** What mu says on a Node that does not strip TypeScript types, which a checkout cannot run on. */
366
+ const NO_TYPE_STRIPPING =
367
+ "mu runs a source checkout's TypeScript with Node's built-in type stripping (on by default since Node 22.18), but this Node doesn't strip types. Use Node 22.19 or newer.";
368
+
379
369
  /**
380
- * Node's arguments for running a checkout's TypeScript, up to the entry file. A Node that strips types itself (on
381
- * by default from 22.18) runs the sources as they are, with pi's own source resolver
382
- * (packages/coding-agent/src/experimental/source-resolver.ts: each workspace package resolves to its sources, as
383
- * tsconfig.json's paths say) and Node's compile cache (compile-cache.mjs). tsx runs its loader on a thread of its
384
- * own and hands every file over from there: pi with the judgment layer took 2 s to start that way, about 0.85 s
385
- * this way, and a checkout starts mu for every conversation the desktop app opens. A runtime that does not strip
386
- * types (`stripsTypes` false; an Electron that runs mu as Node may not), or a checkout from before the resolver,
387
- * still goes through tsx. tsx is one of the checkout's dependencies either way: without it they are not installed.
370
+ * Node's arguments for running a checkout's TypeScript, up to the entry file. Node strips the types itself (on by
371
+ * default from 22.18, in both Electrons the desktop app runs mu with too) and runs the sources as they are, with
372
+ * pi's own source resolver (packages/coding-agent/src/experimental/source-resolver.ts: each workspace package
373
+ * resolves to its sources, as tsconfig.json's paths say) and Node's compile cache (compile-cache.mjs), the way pi
374
+ * runs its own checkout (pi-test.sh). A runtime that does not strip types, a checkout whose dependencies are not
375
+ * installed and one without the resolver are each said, not left to a failed import.
388
376
  */
389
- export function sourceRuntime({ root, platform, stripsTypes, exists, readFile }) {
377
+ export function sourceRuntime({ root, platform, stripsTypes, exists }) {
390
378
  const path = pathFor(platform);
391
- const tsx = resolveTsx({ root, platform, exists, readFile });
392
- if (!tsx) return { error: installHint({ root, platform }) };
379
+ if (!stripsTypes) return { error: NO_TYPE_STRIPPING };
380
+ if (!dependenciesInstalled({ root, platform, exists })) return { error: installHint({ root, platform }) };
393
381
  const resolver = path.join(root, "packages", "coding-agent", "src", "experimental", "source-resolver.ts");
394
- if (!stripsTypes || !exists(resolver)) return { args: [tsx, "--tsconfig", path.join(root, "tsconfig.json")] };
382
+ if (!exists(resolver)) return { error: `pi's source resolver is missing from this checkout (${resolver})` };
395
383
  // As URLs: `--import` reads a Windows path such as C:\... as a URL whose scheme is c:.
396
384
  const url = (file) => pathToFileURL(file, { windows: platform === "win32" }).href;
397
385
  return {
@@ -442,10 +430,10 @@ export function localJudgeSupport({ platform, env, wsl = false }) {
442
430
  runs: false,
443
431
  url,
444
432
  message: [
445
- `The local judge (Laya) is a Core ML sidecar: it runs on macOS with Apple Silicon only, not on ${where}.`,
446
- "mu works without it: use Jev (TYPESAFE_API_KEY or AI_GATEWAY_API_KEY) or an llm judge in mu.json;",
447
- "the desktop app's own local judge is being built. Decisions without a judge fall back to pi's behaviour.",
448
- "A server that speaks the same contract (GET /health, POST /evaluate) can be used from here:",
433
+ `The local judge (Laya) is a Core ML sidecar that runs only on macOS on Apple silicon, not on ${where}.`,
434
+ "mu works without it: Jev answers by default (free on OpenCode Zen, or with your own key: mu setup), or set an LLM judge in mu.json.",
435
+ "A local judge for the desktop app is in progress. Without a judge, decision points use their fallbacks.",
436
+ "To use a server that implements the same API (GET /health, POST /evaluate), set:",
449
437
  " MU_LOCAL_JUDGE_URL=http://host:port",
450
438
  ].join("\n"),
451
439
  };
@@ -458,6 +446,42 @@ export function launchStrategy({ platform, env, canExec }) {
458
446
  return "exec";
459
447
  }
460
448
 
449
+ /** How the judgment layer's extension joins pi's arguments: in front for a session, never in front of pi's own
450
+ * commands (PI_COMMANDS), which pi reads as its first argument — an -e before them would turn them into a prompt.
451
+ * The judgment layer never runs for them, so its extension stays out of their way. */
452
+ function judgeArgs({ argv, layout, root, platform, agentDir, readFile }) {
453
+ if (PI_COMMANDS.has(argv[0])) return [];
454
+ const path = pathFor(platform);
455
+ const extension =
456
+ layout === "package"
457
+ ? ["-e", packageEntries({ root, platform }).extension]
458
+ : ["-e", path.join(root, "packages", "kyrn-judge", "src", "extension", "kyrn-judge.ts")];
459
+ return [...extension, ...themeArgs({ argv, layout, root, platform, agentDir, readFile })];
460
+ }
461
+
462
+ /** mu's own terminal themes, beside the judgment layer's files. */
463
+ export function themesDir({ layout, root, platform }) {
464
+ const path = pathFor(platform);
465
+ return layout === "package" ? path.join(root, "judge", "themes") : path.join(root, "packages", "kyrn-judge", "themes");
466
+ }
467
+
468
+ /**
469
+ * An interactive session gets mu's themes (mu-light and mu-dark, which /settings then lists beside pi's) and, while the
470
+ * person has chosen no theme of their own, starts in them: light or dark as the terminal is. A theme chosen in
471
+ * /settings is saved in settings.json and wins; so does --use-theme. Print and RPC modes draw nothing and get neither.
472
+ */
473
+ function themeArgs({ argv, layout, root, platform, agentDir, readFile }) {
474
+ if (argv.includes("--mode") || argv.includes("-p") || argv.includes("--print")) return [];
475
+ const args = ["--theme", themesDir({ layout, root, platform })];
476
+ if (argv.includes("--use-theme") || !agentDir || !readFile) return args;
477
+ let chosen = false;
478
+ try {
479
+ const settings = JSON.parse(readFile(pathFor(platform).join(agentDir, "settings.json")));
480
+ chosen = typeof settings?.theme === "string" && settings.theme !== "";
481
+ } catch {}
482
+ return chosen ? args : [...args, "--use-theme", "mu-light/mu-dark"];
483
+ }
484
+
461
485
  /**
462
486
  * Everything about starting pi, decided without touching anything: the command, its arguments as an array
463
487
  * (never a shell string) and the child's whole environment.
@@ -484,16 +508,11 @@ export function planLaunch({
484
508
  if (!fs.exists(files.extension)) {
485
509
  return { error: `This mu-agent package is incomplete (${files.extension} is missing). Reinstall it: npm i -g mu-agent` };
486
510
  }
487
- entry = [files.cli, "-e", files.extension];
511
+ entry = [files.cli];
488
512
  } else {
489
- const runtime = sourceRuntime({ root, platform, stripsTypes, exists: fs.exists, readFile: fs.readFile });
513
+ const runtime = sourceRuntime({ root, platform, stripsTypes, exists: fs.exists });
490
514
  if (runtime.error) return { error: runtime.error };
491
- entry = [
492
- ...runtime.args,
493
- path.join(root, "packages", "coding-agent", "src", "experimental", "cli.ts"),
494
- "-e",
495
- path.join(root, "packages", "kyrn-judge", "src", "extension", "kyrn-judge.ts"),
496
- ];
515
+ entry = [...runtime.args, path.join(root, "packages", "coding-agent", "src", "cli.ts")];
497
516
  }
498
517
 
499
518
  const muDir = muHome({ home, platform, isDir: fs.isDir });
@@ -511,7 +530,7 @@ export function planLaunch({
511
530
  const parsed = parseEnvFile(envText);
512
531
  fromFile = envFileAdditions({ env, entries: parsed.entries, platform });
513
532
  // Line numbers only: the text of a line that did not parse may well be a secret.
514
- if (parsed.problems.length > 0) notes.push(`mu: .env: skipped line ${parsed.problems.join(", ")} (not KEY=VALUE)`);
533
+ if (parsed.problems.length > 0) notes.push(`mu: .env: skipped ${parsed.problems.length === 1 ? "line" : "lines"} ${parsed.problems.join(", ")} (expected KEY=VALUE)`);
515
534
  }
516
535
 
517
536
  const childEnv = {};
@@ -534,14 +553,14 @@ export function planLaunch({
534
553
  if (support.runs) startJudge = true;
535
554
  else if (!support.url) {
536
555
  notes.push(
537
- `mu: the configuration asks for the local judge (laya), which runs on macOS only; on ${platformName({ platform, wsl })} its decisions fall back to the next judge or to pi's behaviour (mu judge status)`,
556
+ `mu: the configuration asks for the local judge (Laya), which runs on macOS only; on ${platformName({ platform, wsl })} its decision points use the next judge or their fallbacks (mu judge status)`,
538
557
  );
539
558
  }
540
559
  }
541
560
 
542
561
  return {
543
562
  command: execPath,
544
- args: [...entry, ...argv],
563
+ args: [...entry, ...judgeArgs({ argv, layout, root, platform, agentDir, readFile: fs.readFile }), ...argv],
545
564
  env: childEnv,
546
565
  strategy: launchStrategy({ platform, env, canExec }),
547
566
  layout,
@@ -550,7 +569,7 @@ export function planLaunch({
550
569
  agentDir,
551
570
  startJudge,
552
571
  notes,
553
- preface: argv[0] === "-h" || argv[0] === "--help" ? `${usage(platform)}\n\nAgent flags:\n` : undefined,
572
+ preface: argv[0] === "-h" || argv[0] === "--help" ? `${usage(platform)}\n\npi's help (mu passes all of this through):\n` : undefined,
554
573
  };
555
574
  }
556
575
 
@@ -560,8 +579,7 @@ export function planLaunch({
560
579
  * Node flags that process starts with, pi's arguments (the judgment layer, then `argv`) and its whole environment.
561
580
  * The app's pi and the command line's are then one: the same files, settings, sign-ins and keys.
562
581
  *
563
- * A checkout runs in such a process only on a Node that strips TypeScript types itself, with pi's source resolver:
564
- * tsx cannot be put in front of a module another program imports. Returns { error } otherwise.
582
+ * A checkout runs there as it runs on the command line (sourceRuntime). Returns { error } when pi cannot run.
565
583
  */
566
584
  export function planHost({ platform, env, argv, root, home, fs, wsl = false, stripsTypes = true }) {
567
585
  const path = pathFor(platform);
@@ -581,28 +599,22 @@ export function planHost({ platform, env, argv, root, home, fs, wsl = false, str
581
599
  ...common,
582
600
  module: path.join(root, "dist", "bundle", "index.js"),
583
601
  execArgv: [],
584
- args: ["-e", packageEntries({ root, platform }).extension, ...argv],
585
- };
586
- }
587
- const resolver = path.join(root, "packages", "coding-agent", "src", "experimental", "source-resolver.ts");
588
- if (!stripsTypes || !fs.exists(resolver)) {
589
- return {
590
- error: `pi's sources run inside another program only on a Node that strips TypeScript types itself (22.18 or newer), with pi's source resolver (${resolver})`,
602
+ args: [...judgeArgs({ argv, layout: launch.layout, root, platform, agentDir: launch.agentDir, readFile: fs.readFile }), ...argv],
591
603
  };
592
604
  }
593
- const runtime = sourceRuntime({ root, platform, stripsTypes, exists: fs.exists, readFile: fs.readFile });
605
+ const runtime = sourceRuntime({ root, platform, stripsTypes, exists: fs.exists });
594
606
  if (runtime.error) return { error: runtime.error };
595
607
  return {
596
608
  ...common,
597
609
  module: path.join(root, "packages", "coding-agent", "src", "index.ts"),
598
610
  execArgv: runtime.args,
599
- args: ["-e", path.join(root, "packages", "kyrn-judge", "src", "extension", "kyrn-judge.ts"), ...argv],
611
+ args: [...judgeArgs({ argv, layout: launch.layout, root, platform, agentDir: launch.agentDir, readFile: fs.readFile }), ...argv],
600
612
  };
601
613
  }
602
614
 
603
615
  /** What mu says when the local judge does not come up. */
604
616
  const LOCAL_JUDGE_NOT_STARTED =
605
- "mu: the local judge did not start (mu judge status); decisions fall back to pi's behaviour";
617
+ "mu: the local judge (Laya) didn't start; decision points use the next judge or their fallbacks. Run mu judge status for details.";
606
618
 
607
619
  /** The part of the preparation that is files: the app view of a checkout, mu's agent folder, the configuration's notes. */
608
620
  function prepareFiles({ plan, platform, root, err }) {
@@ -671,7 +683,7 @@ export function planAuth({ platform, env, argv, root, home, execPath, fs, canExe
671
683
  }
672
684
  entry = [auth];
673
685
  } else {
674
- const runtime = sourceRuntime({ root, platform, stripsTypes, exists: fs.exists, readFile: fs.readFile });
686
+ const runtime = sourceRuntime({ root, platform, stripsTypes, exists: fs.exists });
675
687
  if (runtime.error) return { error: runtime.error };
676
688
  entry = [...runtime.args, path.join(root, "packages", "kyrn-judge", "src", "auth", "main.ts")];
677
689
  }
@@ -705,8 +717,7 @@ export function planJudge({ platform, env, argv, bin, wsl = false }) {
705
717
  /**
706
718
  * `mu import`: Claude Code and Codex conversations into mu's sessions (packages/kyrn-judge/src/import). The importer
707
719
  * needs nothing but Node: the npm package runs its build, judge/dist/import.js, and a checkout its TypeScript with
708
- * Node's own type stripping (on by default from 22.18). A runtime that does not strip types (`stripsTypes` false;
709
- * an Electron that runs mu as Node may not) takes the sources through tsx, as pi runs in a checkout.
720
+ * Node's own type stripping (on by default from 22.18).
710
721
  */
711
722
  export function planImport({ platform, env, argv, root, home, execPath, fs, stripsTypes = true }) {
712
723
  const path = pathFor(platform);
@@ -720,12 +731,8 @@ export function planImport({ platform, env, argv, root, home, execPath, fs, stri
720
731
  } else {
721
732
  const source = path.join(root, "packages", "kyrn-judge", "src", "import", "cli.ts");
722
733
  if (!fs.exists(source)) return { error: `mu import is missing from this checkout (${source})` };
723
- if (stripsTypes) entry = ["--disable-warning=ExperimentalWarning", source];
724
- else {
725
- const tsx = resolveTsx({ root, platform, exists: fs.exists, readFile: fs.readFile });
726
- if (!tsx) return { error: installHint({ root, platform }) };
727
- entry = [tsx, "--tsconfig", path.join(root, "tsconfig.json"), source];
728
- }
734
+ if (!stripsTypes) return { error: NO_TYPE_STRIPPING };
735
+ entry = ["--disable-warning=ExperimentalWarning", source];
729
736
  }
730
737
  const agentDir = agentDirFor({ env, muDir: muHome({ home, platform, isDir: fs.isDir }), platform });
731
738
  const childEnv = {};
@@ -763,6 +770,8 @@ export const MODEL_KEY_VARIABLES = [
763
770
  "ANTHROPIC_AUTH_TOKEN",
764
771
  "ANTHROPIC_OAUTH_TOKEN",
765
772
  "ANTHROPIC_API_KEY",
773
+ // Anthropic's workload identity federation needs three variables together; its rule id stands for them.
774
+ "ANTHROPIC_FEDERATION_RULE_ID",
766
775
  "ANT_LING_API_KEY",
767
776
  "QWEN_TOKEN_PLAN_API_KEY",
768
777
  "QWEN_TOKEN_PLAN_CN_API_KEY",
@@ -816,7 +825,7 @@ export function planSetup({ platform, env, argv, root, home, execPath, fs, strip
816
825
  }
817
826
  entry = [setup];
818
827
  } else {
819
- const runtime = sourceRuntime({ root, platform, stripsTypes, exists: fs.exists, readFile: fs.readFile });
828
+ const runtime = sourceRuntime({ root, platform, stripsTypes, exists: fs.exists });
820
829
  if (runtime.error) return { error: runtime.error };
821
830
  entry = [...runtime.args, path.join(root, "packages", "kyrn-judge", "src", "setup", "main.ts")];
822
831
  }
@@ -846,8 +855,41 @@ export function planSetup({ platform, env, argv, root, home, execPath, fs, strip
846
855
  return { command: execPath, args: [...entry, ...args], env: childEnv, strategy: "spawn", agentDir, keyGiven: key !== undefined };
847
856
  }
848
857
 
849
- /** pi's own commands: none of them starts a session. */
850
- const PI_COMMANDS = new Set(["install", "remove", "uninstall", "update", "list", "config", "auth"]);
858
+ /** pi's own commands, read from its first argument: none of them starts a session. */
859
+ const PI_COMMANDS = new Set(["install", "remove", "uninstall", "update", "list", "config", "auth", "mcp"]);
860
+
861
+ /** Options of `pi mcp add` that take a value (extensions/mcp/cli.ts); the rest are flags. */
862
+ const MCP_ADD_VALUES = new Set([
863
+ "--url",
864
+ "--env",
865
+ "--cwd",
866
+ "--header",
867
+ "--bearer-token-env-var",
868
+ "--oauth-client-id",
869
+ "--oauth-client-secret",
870
+ "--oauth-callback-port",
871
+ "--oauth-client-name",
872
+ "--exposure",
873
+ "--description",
874
+ ]);
875
+
876
+ /**
877
+ * `mu mcp add` without `--exposure`: the server's tools are `deferred`, loaded by tool_search when a task needs them,
878
+ * instead of pi's default `codemode`, which reaches them only from scripts. Like pi, the options end at `--` or at the
879
+ * second positional argument; what follows belongs to the server's command.
880
+ */
881
+ export function mcpAddDefaults(argv) {
882
+ if (argv[0] !== "mcp" || argv[1] !== "add") return argv;
883
+ let positionals = 0;
884
+ for (let index = 2; index < argv.length && positionals < 2; index++) {
885
+ const arg = argv[index];
886
+ if (arg === "--") break;
887
+ if (arg === "--exposure") return argv;
888
+ if (MCP_ADD_VALUES.has(arg)) index++;
889
+ else if (!arg.startsWith("-")) positionals++;
890
+ }
891
+ return [...argv.slice(0, 2), "--exposure", "deferred", ...argv.slice(2)];
892
+ }
851
893
  /** Options for a run without a person (-p, --mode rpc), one that ends at once, or one that names its model itself. */
852
894
  const NO_SETUP_FLAGS = new Set([
853
895
  "-p",
@@ -988,7 +1030,7 @@ export function planLink({ platform, env, home, bin, argv, fs }) {
988
1030
  return {
989
1031
  action: "refuse",
990
1032
  errors: [
991
- `${link} already exists and is not this mu; it was left alone. Choose another folder: MU_LINK_DIR=<dir> mu link`,
1033
+ `${link} already exists and is not this mu, so it was left alone. To use another folder: MU_LINK_DIR=<dir> mu link`,
992
1034
  ],
993
1035
  };
994
1036
  }
@@ -1016,7 +1058,7 @@ export function planLink({ platform, env, home, bin, argv, fs }) {
1016
1058
  if (windows && /[^\x00-\x7f]/.test(content)) {
1017
1059
  notes.push(
1018
1060
  "Note: the path from that folder to this repository has non-ASCII characters in it, and cmd reads a batch file in the",
1019
- "console's code page. If `mu` then cannot find its target, choose a folder on the same drive (MU_LINK_DIR), or put",
1061
+ "console's code page. If mu then can't find its target, choose a folder on the same drive (MU_LINK_DIR), or put",
1020
1062
  `${bin} on your PATH instead.`,
1021
1063
  );
1022
1064
  }
@@ -1185,8 +1227,8 @@ export function migrate({ platform, home, argv, fs, run, alive, self, out, err }
1185
1227
  return 0;
1186
1228
  }
1187
1229
  if (fs.exists(next) || fs.isLink(next)) {
1188
- err(`${next} already exists, so nothing was moved. Two homes are never merged or overwritten here:`);
1189
- err("look at both folders and decide which one is the real one.");
1230
+ err(`${next} already exists, so nothing was moved. mu never merges or overwrites two home folders:`);
1231
+ err("look at both and decide which one to keep.");
1190
1232
  return 1;
1191
1233
  }
1192
1234
  // Whatever is running would write into the gap between the rename and the link, and split the home in two.
@@ -1195,10 +1237,10 @@ export function migrate({ platform, home, argv, fs, run, alive, self, out, err }
1195
1237
  try {
1196
1238
  pid = Number.parseInt(fs.readFile(path.join(old, "local-judge", "judge.pid")).trim(), 10);
1197
1239
  } catch {}
1198
- if (pid > 0 && alive(pid)) busy.push(` the local judge (pid ${pid}). Stop it: mu judge stop`);
1240
+ if (pid > 0 && alive(pid)) busy.push(` the local judge (pid ${pid}). Stop it with mu judge stop`);
1199
1241
  const found = findBusy({ platform, old, run, self });
1200
1242
  if (!found) {
1201
- err("Nothing was moved: the list of running processes could not be read (tasklist, powershell), so it is not known whether mu is still running.");
1243
+ err("Nothing was moved: mu couldn't read the list of running processes (tasklist, powershell), so it can't tell whether mu is still running.");
1202
1244
  return 1;
1203
1245
  }
1204
1246
  const list = (pids) => pids.join(" ");
@@ -1232,7 +1274,7 @@ export function migrate({ platform, home, argv, fs, run, alive, self, out, err }
1232
1274
  out(`renamed ${path.join(next, config)} -> mu.json`);
1233
1275
  }
1234
1276
  out(`linked ${old} -> ${next} (paths stored from before the rename keep working)`);
1235
- out("Check it: mu doctor");
1277
+ out("To check it, run mu doctor");
1236
1278
  return 0;
1237
1279
  }
1238
1280
 
@@ -1314,7 +1356,7 @@ function handOver({ command, args, env, strategy }) {
1314
1356
  for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) process.on(signal, () => relay(signal));
1315
1357
  if (process.platform === "win32") process.on("SIGBREAK", () => {});
1316
1358
  child.on("error", (error) => {
1317
- err(`mu: could not start ${command}: ${error.message}`);
1359
+ err(`mu: couldn't start ${command}: ${error.message}`);
1318
1360
  resolve(1);
1319
1361
  });
1320
1362
  child.on("exit", (code, signal) => resolve(code ?? 128 + (osConstants.signals[signal] ?? 0)));
@@ -1411,7 +1453,7 @@ export async function main(argv = process.argv.slice(2)) {
1411
1453
  out(await response.text());
1412
1454
  return 0;
1413
1455
  } catch {
1414
- out(`the judge server does not answer at ${plan.url}`);
1456
+ out(`The local judge server isn't answering at ${plan.url}. Check that it's running.`);
1415
1457
  return 1;
1416
1458
  }
1417
1459
  }
@@ -1436,7 +1478,7 @@ export async function main(argv = process.argv.slice(2)) {
1436
1478
  return handOver({ command: plan.command, args: plan.args, env: plan.env, strategy });
1437
1479
  }
1438
1480
  // What the session gets, when there is one: after a `mu setup` that ends in "start mu now", a plain session.
1439
- let sessionArgv = argv;
1481
+ let sessionArgv = mcpAddDefaults(argv);
1440
1482
  if (command === "setup") {
1441
1483
  const plan = planSetup({
1442
1484
  platform,
@@ -1508,7 +1550,7 @@ export async function main(argv = process.argv.slice(2)) {
1508
1550
  return 0;
1509
1551
  }
1510
1552
  // Asked before `version` too, as it always was: a checkout without its dependencies says so at the first command.
1511
- if (layout === "repo" && !resolveTsx({ root, platform, exists: existsSync, readFile: readText })) {
1553
+ if (layout === "repo" && !dependenciesInstalled({ root, platform, exists: existsSync })) {
1512
1554
  err(installHint({ root, platform }));
1513
1555
  return 1;
1514
1556
  }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "mu-agent",
3
- "version": "0.1.7",
4
- "description": "mu: a coding agent that thinks before it acts. A small, fast judge makes the routine calls; the big model keeps its attention for the work. Built on pi.",
3
+ "version": "0.1.10",
4
+ "description": "mu: a coding agent that hands its routine decisions to a small, fast judge model, so the main model can keep its attention on the work. Built on pi.",
5
5
  "type": "module",
6
6
  "bin": {
7
7
  "mu": "kyrn/bin/mu.mjs"
@@ -33,13 +33,12 @@
33
33
  "node": ">=22.19.0"
34
34
  },
35
35
  "dependencies": {
36
- "@earendil-works/chord": "0.87.1",
37
36
  "@silvia-odwyer/photon-node": "0.3.4",
38
37
  "jiti": "2.7.0"
39
38
  },
40
39
  "muBuild": {
41
- "pi": "0.87.1",
40
+ "pi": "1.3.0",
42
41
  "judge": "0.1.0",
43
- "commit": "c645b9c64"
42
+ "commit": "84e66744e"
44
43
  }
45
44
  }
@@ -1,6 +0,0 @@
1
- import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import{buildCopilotDynamicHeaders,hasCopilotVisionInput}from"./chunk-PGXDEOVV.js";import{Anthropic}from"./chunk-DTD7JQ7Y.js";import{retryProviderRequest}from"./chunk-XNGRGP62.js";import{adjustMaxTokensForThinking,buildBaseOptions,clampMaxTokensToContext,getJsonSchemaToolParameters,getPiUserAgent,resolveJsonSchemaStrictSampling,transformMessages}from"./chunk-GNYZK6XN.js";import{sanitizeSurrogates}from"./chunk-L2ZPNLYD.js";import{headersToRecord}from"./chunk-UTB4DTYQ.js";import{getProviderEnvValue}from"./chunk-DRQDKNXA.js";import{parseJsonWithRepair,parseStreamingJson}from"./chunk-TRDNDS6A.js";import{calculateCost,getCurrentTools,getDeclaredTools,getInitialSystemMessage,getSystemMessageText,hasToolRedefinitions,renderSystemMessageUpdate,resolveTranscript}from"./chunk-FU4XQUSL.js";import{AssistantMessageEventStream,appendAssistantMessageDiagnostic}from"./chunk-A3JYRWB6.js";import"./chunk-4L3WN2XY.js";function resolveCacheRetention(cacheRetention,env){return cacheRetention||(getProviderEnvValue("PI_CACHE_RETENTION",env)==="long"?"long":"short")}function getCacheControl(model,cacheRetention,env){let retention=resolveCacheRetention(cacheRetention,env);if(retention==="none")return{retention};let ttl=retention==="long"&&getAnthropicCompat(model).supportsLongCacheRetention?"1h":void 0;return{retention,cacheControl:{type:"ephemeral",...ttl&&{ttl}}}}var claudeCodeVersion="2.1.280",claudeCodeTools=["Read","Write","Edit","Bash","Grep","Glob","AskUserQuestion","EnterPlanMode","ExitPlanMode","KillShell","NotebookEdit","Skill","Task","TaskOutput","TodoWrite","WebFetch","WebSearch"],ccToolLookup=new Map(claudeCodeTools.map(t=>[t.toLowerCase(),t])),toClaudeCodeName=name=>ccToolLookup.get(name.toLowerCase())??name,fromClaudeCodeName=(name,tools)=>{if(tools&&tools.length>0){let lowerName=name.toLowerCase(),matchedTool=tools.find(tool=>tool.name.toLowerCase()===lowerName);if(matchedTool)return matchedTool.name}return name};function convertContentBlocks(content){if(!content.some(c=>c.type==="image"))return sanitizeSurrogates(content.map(c=>c.text).join(`
3
- `));let blocks=content.map(block=>block.type==="text"?{type:"text",text:sanitizeSurrogates(block.text)}:{type:"image",source:{type:"base64",media_type:block.mimeType,data:block.data}});return blocks.some(b=>b.type==="text")||blocks.unshift({type:"text",text:"(see attached image)"}),blocks}var FINE_GRAINED_TOOL_STREAMING_BETA="fine-grained-tool-streaming-2025-05-14",INTERLEAVED_THINKING_BETA="interleaved-thinking-2025-05-14",SERVER_SIDE_FALLBACK_BETA="server-side-fallback-2026-07-01",MID_CONVERSATION_OUTPUT_CONFIG_BETA="mid-conversation-output-config-2026-07-01",THINKING_BINDING_CONTROLS_BETA="thinking-binding-controls-2026-08-01",MID_CONVERSATION_TOOL_CHANGES_BETA="mid-conversation-tool-changes-2026-07-01",DEFERRED_TOOL_PLACEHOLDER={name:"__pi_deferred_placeholder__",description:"Reserved placeholder. Never available. Never call this.",input_schema:{type:"object",properties:{},required:[]},defer_loading:!0};function shouldUseServerSideFallbackBeta(model){return(model.compat?.allowedFallbackModels?.length??0)>0}function getAnthropicCompat(model){let isOpenRouter=model.provider==="openrouter"||model.baseUrl.includes("openrouter.ai");return{supportsEagerToolInputStreaming:model.compat?.supportsEagerToolInputStreaming??!0,supportsLongCacheRetention:model.compat?.supportsLongCacheRetention??!0,sendSessionAffinityHeaders:model.compat?.sendSessionAffinityHeaders??isOpenRouter,sessionAffinityFormat:model.compat?.sessionAffinityFormat??(isOpenRouter?"openrouter":void 0),supportsCacheControlOnTools:model.compat?.supportsCacheControlOnTools??!0,supportsTemperature:model.compat?.supportsTemperature??!0,allowEmptySignature:model.compat?.allowEmptySignature??!1,supportsStrictTools:model.compat?.supportsStrictTools??!1,supportsMidConvoSystemMessages:model.compat?.supportsMidConvoSystemMessages??!1,supportsMidConvoToolChanges:model.compat?.supportsMidConvoToolChanges??!1}}function mergeHeaders(...headerSources){let merged={};for(let headers of headerSources)headers&&Object.assign(merged,headers);return merged}function mergeClientHeaders(...headerSources){return mergeHeaders({"User-Agent":getPiUserAgent()},...headerSources)}function hasHeader(headers,name){if(!headers)return!1;let expected=name.toLowerCase();for(let[key,value]of Object.entries(headers))if(key.toLowerCase()===expected&&value!==null&&value.trim().length>0)return!0;return!1}function assertRequestAuth(provider,apiKey,headers){if(!apiKey&&!(hasHeader(headers,"authorization")||hasHeader(headers,"x-api-key")||hasHeader(headers,"cf-aig-authorization")))throw new Error(`No API key for provider: ${provider}`)}var ANTHROPIC_MESSAGE_EVENTS=new Set(["message_start","message_delta","message_stop","content_block_start","content_block_delta","content_block_stop"]);function flushSseEvent(state){if(!state.event&&state.data.length===0)return null;let event={event:state.event,data:state.data.join(`
4
- `),raw:[...state.raw]};return state.event=null,state.data=[],state.raw=[],event}function decodeSseLine(line,state){if(line==="")return flushSseEvent(state);if(state.raw.push(line),line.startsWith(":"))return null;let delimiterIndex=line.indexOf(":"),fieldName=delimiterIndex===-1?line:line.slice(0,delimiterIndex),value=delimiterIndex===-1?"":line.slice(delimiterIndex+1);return value.startsWith(" ")&&(value=value.slice(1)),fieldName==="event"?state.event=value:fieldName==="data"&&state.data.push(value),null}function nextLineBreakIndex(text){let carriageReturnIndex=text.indexOf("\r"),newlineIndex=text.indexOf(`
5
- `);return carriageReturnIndex===-1?newlineIndex:newlineIndex===-1?carriageReturnIndex:Math.min(carriageReturnIndex,newlineIndex)}function consumeLine(text){let lineBreakIndex=nextLineBreakIndex(text);if(lineBreakIndex===-1)return null;let nextIndex=lineBreakIndex+1;return text[lineBreakIndex]==="\r"&&text[nextIndex]===`
6
- `&&(nextIndex+=1),{line:text.slice(0,lineBreakIndex),rest:text.slice(nextIndex)}}async function*iterateSseMessages(body,signal){let reader=body.getReader(),decoder=new TextDecoder,state={event:null,data:[],raw:[]},buffer="";try{for(;;){if(signal?.aborted)throw new Error("Request was aborted");let{value,done}=await reader.read();if(done)break;buffer+=decoder.decode(value,{stream:!0});let consumed2=consumeLine(buffer);for(;consumed2;){buffer=consumed2.rest;let event=decodeSseLine(consumed2.line,state);event&&(yield event),consumed2=consumeLine(buffer)}}buffer+=decoder.decode();let consumed=consumeLine(buffer);for(;consumed;){buffer=consumed.rest;let event=decodeSseLine(consumed.line,state);event&&(yield event),consumed=consumeLine(buffer)}if(buffer.length>0){let event=decodeSseLine(buffer,state);event&&(yield event)}let trailingEvent=flushSseEvent(state);trailingEvent&&(yield trailingEvent)}finally{reader.releaseLock()}}async function*iterateAnthropicEvents(response,signal){if(!response.body)throw new Error("Attempted to iterate over an Anthropic response with no body");let sawMessageStart=!1,sawMessageEnd=!1;for await(let sse of iterateSseMessages(response.body,signal)){if(sse.event==="error")throw new Error(sse.data);if(ANTHROPIC_MESSAGE_EVENTS.has(sse.event??""))try{let event=parseJsonWithRepair(sse.data);event.type==="message_start"?sawMessageStart=!0:event.type==="message_stop"&&(sawMessageEnd=!0),yield event}catch(error){let message=error instanceof Error?error.message:String(error);throw new Error(`Could not parse Anthropic SSE event ${sse.event}: ${message}; data=${sse.data}; raw=${sse.raw.join("\\n")}`)}}if(sawMessageStart&&!sawMessageEnd)throw new Error("Anthropic stream ended before message_stop")}var stream=(model,context,options)=>{let stream2=new AssistantMessageEventStream,normalizedContext=resolveTranscript(context,getAnthropicCompat(model).supportsMidConvoSystemMessages),currentTools=getCurrentTools(normalizedContext.messages);return(async()=>{let providerThinkingLevel=model.compat?.supportsMidConvoEffort?options?.effort??"high":void 0,output={role:"assistant",content:[],api:model.api,provider:model.provider,model:model.id,...providerThinkingLevel===void 0?{}:{providerThinkingLevel},usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"pending",timestamp:Date.now()};try{let client,isOAuth,usageModel=model,inputTransformations;if(options?.client)client=options.client,isOAuth=!1;else{let apiKey=options?.apiKey;assertRequestAuth(model.provider,apiKey,options?.headers);let copilotDynamicHeaders;if(model.provider==="github-copilot"){let hasImages=hasCopilotVisionInput(normalizedContext.messages);copilotDynamicHeaders=buildCopilotDynamicHeaders({messages:normalizedContext.messages,hasImages})}let cacheSessionId=resolveCacheRetention(options?.cacheRetention,options?.env)==="none"?void 0:options?.sessionId,created=createClient(model,apiKey,options?.headers,options?.fetch,copilotDynamicHeaders,cacheSessionId);client=created.client,isOAuth=created.isOAuthToken}let params=buildParams(model,normalizedContext,isOAuth,options),nextParams=await options?.onPayload?.(params,model);nextParams!==void 0&&(params={...nextParams,stream:!0});let requestOptions={...options?.signal?{signal:options.signal}:{},...options?.timeoutMs!==void 0?{timeout:options.timeoutMs}:{},maxRetries:0},response=await retryProviderRequest(()=>client.beta.messages.create(params,requestOptions).asResponse(),{maxRetries:options?.maxRetries,maxRetryDelayMs:options?.maxRetryDelayMs,signal:options?.signal});await options?.onResponse?.({status:response.status,headers:headersToRecord(response.headers)},model),stream2.push({type:"start",partial:output});let blocks=output.content;for await(let event of iterateAnthropicEvents(response,options?.signal))if(await options?.onProviderStreamEvent?.(event,model),event.type==="message_start"){output.responseId=event.message.id;let transformations=event.message.input_transformations;Array.isArray(transformations)&&(inputTransformations=transformations);let responseModel=event.message.model;responseModel!==model.id&&(output.responseModel=responseModel);let fallbackCost=responseModel===model.id?void 0:model.compat?.allowedFallbackModels?.find(fallback=>fallback.provider===model.provider&&fallback.model===responseModel)?.cost;usageModel=fallbackCost?{...model,id:responseModel,cost:fallbackCost}:model,output.usage.input=event.message.usage.input_tokens||0,output.usage.output=event.message.usage.output_tokens||0,output.usage.cacheRead=event.message.usage.cache_read_input_tokens||0,output.usage.cacheWrite=event.message.usage.cache_creation_input_tokens||0,output.usage.cacheWrite1h=event.message.usage.cache_creation?.ephemeral_1h_input_tokens||0,output.usage.totalTokens=output.usage.input+output.usage.output+output.usage.cacheRead+output.usage.cacheWrite,calculateCost(usageModel,output.usage)}else if(event.type==="content_block_start"){if(event.content_block.type==="fallback"){if(output.content.length>0)throw new Error("Anthropic performed an unsupported mid-output model fallback");continue}if(event.content_block.type==="text"){let block={type:"text",text:event.content_block.text??"",index:event.index};output.content.push(block),stream2.push({type:"text_start",contentIndex:output.content.length-1,partial:output})}else if(event.content_block.type==="thinking"){let block={type:"thinking",thinking:event.content_block.thinking??"",thinkingSignature:event.content_block.signature??"",index:event.index};output.content.push(block),stream2.push({type:"thinking_start",contentIndex:output.content.length-1,partial:output})}else if(event.content_block.type==="redacted_thinking"){let block={type:"thinking",thinking:"[Reasoning redacted]",thinkingSignature:event.content_block.data,redacted:!0,index:event.index};output.content.push(block),stream2.push({type:"thinking_start",contentIndex:output.content.length-1,partial:output})}else if(event.content_block.type==="tool_use"){let block={type:"toolCall",id:event.content_block.id,name:isOAuth?fromClaudeCodeName(event.content_block.name,currentTools):event.content_block.name,arguments:event.content_block.input??{},partialJson:"",index:event.index};output.content.push(block),stream2.push({type:"toolcall_start",contentIndex:output.content.length-1,partial:output})}}else if(event.type==="content_block_delta"){if(event.delta.type==="text_delta"){let index=blocks.findIndex(b=>b.index===event.index),block=blocks[index];block&&block.type==="text"&&(block.text+=event.delta.text,stream2.push({type:"text_delta",contentIndex:index,delta:event.delta.text,partial:output}))}else if(event.delta.type==="thinking_delta"){let index=blocks.findIndex(b=>b.index===event.index),block=blocks[index];block&&block.type==="thinking"&&(block.thinking+=event.delta.thinking,stream2.push({type:"thinking_delta",contentIndex:index,delta:event.delta.thinking,partial:output}))}else if(event.delta.type==="input_json_delta"){let index=blocks.findIndex(b=>b.index===event.index),block=blocks[index];block&&block.type==="toolCall"&&(block.partialJson+=event.delta.partial_json,block.arguments=parseStreamingJson(block.partialJson),stream2.push({type:"toolcall_delta",contentIndex:index,delta:event.delta.partial_json,partial:output}))}else if(event.delta.type==="signature_delta"){let index=blocks.findIndex(b=>b.index===event.index),block=blocks[index];block&&block.type==="thinking"&&(block.thinkingSignature=block.thinkingSignature||"",block.thinkingSignature+=event.delta.signature)}}else if(event.type==="content_block_stop"){let index=blocks.findIndex(b=>b.index===event.index),block=blocks[index];block&&(delete block.index,block.type==="text"?stream2.push({type:"text_end",contentIndex:index,content:block.text,partial:output}):block.type==="thinking"?stream2.push({type:"thinking_end",contentIndex:index,content:block.thinking,partial:output}):block.type==="toolCall"&&(block.arguments=parseStreamingJson(block.partialJson),delete block.partialJson,stream2.push({type:"toolcall_end",contentIndex:index,toolCall:block,partial:output})))}else if(event.type==="message_delta"){let transformations=event.input_transformations;if(Array.isArray(transformations)&&(inputTransformations=transformations),event.delta.stop_reason){output.rawStopReason=event.delta.stop_reason;let stopReasonResult=mapStopReason(event.delta.stop_reason,event.delta.stop_details);output.stopReason=stopReasonResult.stopReason,stopReasonResult.errorMessage&&(output.errorMessage=stopReasonResult.errorMessage)}if(event.usage){event.usage.input_tokens!=null&&(output.usage.input=event.usage.input_tokens),event.usage.output_tokens!=null&&(output.usage.output=event.usage.output_tokens),event.usage.cache_read_input_tokens!=null&&(output.usage.cacheRead=event.usage.cache_read_input_tokens),event.usage.cache_creation_input_tokens!=null&&(output.usage.cacheWrite=event.usage.cache_creation_input_tokens);let cacheCreation=event.usage.cache_creation;cacheCreation?.ephemeral_1h_input_tokens!=null&&(output.usage.cacheWrite1h=cacheCreation.ephemeral_1h_input_tokens);let thinkingTokens=event.usage.output_tokens_details?.thinking_tokens;thinkingTokens!=null&&(output.usage.reasoning=thinkingTokens)}output.usage.totalTokens=output.usage.input+output.usage.output+output.usage.cacheRead+output.usage.cacheWrite,calculateCost(usageModel,output.usage)}if(options?.signal?.aborted)throw new Error("Request was aborted");if(output.stopReason==="pending")throw new Error("Anthropic stream ended without a stop reason");if(output.stopReason==="aborted"||output.stopReason==="error")throw new Error(output.errorMessage||"An unknown error occurred");inputTransformations&&inputTransformations.length>0&&appendAssistantMessageDiagnostic(output,{type:"anthropic_input_transformations",timestamp:Date.now(),details:{transformations:inputTransformations.map(transformation=>({type:transformation.type??void 0,path:transformation.path??void 0,reason:transformation.reason??void 0}))}}),stream2.push({type:"done",reason:output.stopReason,message:output}),stream2.end()}catch(error){for(let block of output.content)delete block.index,delete block.partialJson;output.stopReason=options?.signal?.aborted?"aborted":"error",output.errorMessage=error instanceof Error?error.message:JSON.stringify(error),stream2.push({type:"error",reason:output.stopReason,error:output}),stream2.end()}})(),stream2};function mapThinkingLevelToEffort(model,level){let mapped=level?model.thinkingLevelMap?.[level]:void 0;if(typeof mapped=="string")return mapped;switch(level){case"minimal":case"low":return"low";case"medium":return"medium";case"high":return"high";default:return"high"}}var streamSimple=(model,context,options)=>{assertRequestAuth(model.provider,options?.apiKey,options?.headers);let base={...buildBaseOptions(model,context,options,options?.apiKey),toolChoice:options?.toolChoice};if(!options?.reasoning)return stream(model,context,{...base,thinkingEnabled:!1});if(model.compat?.forceAdaptiveThinking===!0){let effort=mapThinkingLevelToEffort(model,options.reasoning);return stream(model,context,{...base,thinkingEnabled:!0,effort})}let adjusted=adjustMaxTokensForThinking(base.maxTokens,model.maxTokens,options.reasoning,options.thinkingBudgets),maxTokens=clampMaxTokensToContext(model,context,adjusted.maxTokens);return stream(model,context,{...base,maxTokens,thinkingEnabled:!0,thinkingBudgetTokens:Math.min(adjusted.thinkingBudget,Math.max(0,maxTokens-1024))})};function isOAuthToken(apiKey){return apiKey.includes("sk-ant-oat")}function createClient(model,apiKey,optionsHeaders,fetch,dynamicHeaders,sessionId){if(model.provider==="github-copilot")return{client:new Anthropic({apiKey:null,authToken:apiKey??null,baseURL:model.baseUrl,dangerouslyAllowBrowser:!0,fetch,defaultHeaders:mergeClientHeaders({accept:"application/json","anthropic-dangerous-direct-browser-access":"true"},model.headers,dynamicHeaders,optionsHeaders)}),isOAuthToken:!1};if(apiKey&&isOAuthToken(apiKey))return{client:new Anthropic({apiKey:null,authToken:apiKey,baseURL:model.baseUrl,dangerouslyAllowBrowser:!0,fetch,defaultHeaders:mergeClientHeaders({accept:"application/json","anthropic-dangerous-direct-browser-access":"true","user-agent":`claude-cli/${claudeCodeVersion}`,"x-app":"cli"},model.headers,optionsHeaders)}),isOAuthToken:!0};let compat=getAnthropicCompat(model),sessionAffinityHeaders={};if(sessionId&&compat.sendSessionAffinityHeaders){let header=compat.sessionAffinityFormat==="openrouter"?"x-session-id":"x-session-affinity";sessionAffinityHeaders[header]=sessionId}let defaultHeaders=mergeClientHeaders({accept:"application/json","anthropic-dangerous-direct-browser-access":"true"},sessionAffinityHeaders,model.headers,optionsHeaders);return{client:new Anthropic({apiKey:apiKey??null,authToken:null,baseURL:model.baseUrl,dangerouslyAllowBrowser:!0,fetch,defaultHeaders}),isOAuthToken:!1}}function getBetaFeatures(model,context,isOAuthToken2,nativeToolChanges,options){let configuredFeatures;for(let headers of[model.headers,options?.headers])for(let[name,value]of Object.entries(headers??{}))name.toLowerCase()==="anthropic-beta"&&(configuredFeatures=value);if(configuredFeatures===null)return[];if(configuredFeatures!==void 0)return[...new Set(configuredFeatures.split(",").map(feature=>feature.trim()).filter(feature=>feature.length>0))];let features=[];return isOAuthToken2&&features.push("claude-code-20250219","oauth-2025-04-20"),shouldUseFineGrainedToolStreamingBeta(model,context)&&features.push(FINE_GRAINED_TOOL_STREAMING_BETA),model.reasoning&&options?.thinkingEnabled===!0&&(options.interleavedThinking??!0)&&model.compat?.forceAdaptiveThinking!==!0&&features.push(INTERLEAVED_THINKING_BETA),shouldUseServerSideFallbackBeta(model)&&features.push(SERVER_SIDE_FALLBACK_BETA),model.compat?.supportsMidConvoEffort===!0&&features.push(MID_CONVERSATION_OUTPUT_CONFIG_BETA,THINKING_BINDING_CONTROLS_BETA),nativeToolChanges&&features.push(MID_CONVERSATION_TOOL_CHANGES_BETA),[...new Set(features)]}function buildParams(model,context,isOAuthToken2,options){let{cacheControl}=getCacheControl(model,options?.cacheRetention,options?.env),compat=getAnthropicCompat(model),initialSystemMessage=getInitialSystemMessage(context.messages),initialSystemText=initialSystemMessage?getSystemMessageText(initialSystemMessage):"",transformedMessages=transformMessages(context.messages,model,normalizeToolCallId),conversationMessages=initialSystemMessage?transformedMessages.slice(1):transformedMessages,initialTools=initialSystemMessage?.toolsAdded??[],nativeToolChanges=compat.supportsMidConvoSystemMessages&&compat.supportsMidConvoToolChanges&&initialTools.length>0&&!hasToolRedefinitions(context.messages),converted=convertMessages(conversationMessages,isOAuthToken2,cacheControl,compat.allowEmptySignature,model.compat?.supportsMidConvoEffort===!0?model.provider:void 0,nativeToolChanges),activeEffort=options?.effort??"high",betaFeatures=getBetaFeatures(model,context,isOAuthToken2,nativeToolChanges,options),params={model:model.id,messages:model.compat?.supportsMidConvoEffort===!0?insertThinkingLevelMessages(converted,activeEffort):converted.messages,max_tokens:options?.maxTokens??model.maxTokens,stream:!0,...betaFeatures.length>0?{betas:betaFeatures}:{}};isOAuthToken2?(params.system=[{type:"text",text:"You are Claude Code, Anthropic's official CLI for Claude.",...cacheControl?{cache_control:cacheControl}:{}}],initialSystemText&&params.system.push({type:"text",text:sanitizeSurrogates(initialSystemText),...cacheControl?{cache_control:cacheControl}:{}})):initialSystemText&&(params.system=[{type:"text",text:sanitizeSurrogates(initialSystemText),...cacheControl?{cache_control:cacheControl}:{}}]),options?.temperature!==void 0&&!options?.thinkingEnabled&&model.compat?.supportsMidConvoEffort!==!0&&compat.supportsTemperature&&(params.temperature=options.temperature);let toolCacheControl=compat.supportsCacheControlOnTools?cacheControl:void 0;if(nativeToolChanges){let initialNames=new Set(initialTools.map(tool=>tool.name)),laterTools=getDeclaredTools(context.messages).filter(tool=>!initialNames.has(tool.name));params.tools=[...convertTools(initialTools,isOAuthToken2,compat.supportsEagerToolInputStreaming,compat.supportsStrictTools,toolCacheControl),DEFERRED_TOOL_PLACEHOLDER,...convertTools(laterTools,isOAuthToken2,compat.supportsEagerToolInputStreaming,compat.supportsStrictTools).map(tool=>({...tool,defer_loading:!0}))]}else{let tools=getCurrentTools(context.messages);tools.length>0&&(params.tools=convertTools(tools,isOAuthToken2,compat.supportsEagerToolInputStreaming,compat.supportsStrictTools,toolCacheControl))}if(model.compat?.supportsMidConvoEffort===!0)params.thinking={type:"adaptive",display:options?.thinkingDisplay??"summarized",block_binding:{prefix_mismatch_behavior:"drop_block"}},params.output_config={effort:"high"};else if(model.reasoning)if(options?.thinkingEnabled){let display=options.thinkingDisplay??"summarized";model.compat?.forceAdaptiveThinking===!0?(params.thinking={type:"adaptive",display},options.effort&&(params.output_config={effort:options.effort})):params.thinking={type:"enabled",budget_tokens:options.thinkingBudgetTokens||1024,display}}else options?.thinkingEnabled===!1&&model.thinkingLevelMap?.off!==null&&(params.thinking={type:"disabled"});if(options?.metadata){let userId=options.metadata.user_id;typeof userId=="string"&&(params.metadata={user_id:userId})}options?.toolChoice&&(typeof options.toolChoice=="string"?params.tool_choice={type:options.toolChoice}:params.tool_choice=options.toolChoice);let allowedFallbackModels=model.compat?.allowedFallbackModels;return allowedFallbackModels&&allowedFallbackModels.length>0&&(params.fallbacks=allowedFallbackModels.map(fallback=>({model:fallback.model}))),params}function normalizeToolCallId(id){return id.replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,64)}function convertToolResult(msg){return{type:"tool_result",tool_use_id:msg.toolCallId,content:convertContentBlocks(msg.content),is_error:msg.isError}}function convertMessages(transformedMessages,isOAuthToken2,cacheControl,allowEmptySignature=!1,managedProvider,nativeToolChanges=!1){let params=[],assistantLevels=new Map,pendingSystemMessages=[],flushPendingSystemMessages=()=>{params.push(...pendingSystemMessages),pendingSystemMessages.length=0};for(let i=0;i<transformedMessages.length;i++){let msg=transformedMessages[i];if(msg.role==="system"){let text=renderSystemMessageUpdate(msg),blocks=[];if(text.length>0&&blocks.push({type:"text",text:sanitizeSurrogates(text)}),nativeToolChanges){for(let tool of msg.toolsRemoved??[])blocks.push({type:"tool_removal",tool:{type:"tool_reference",name:isOAuthToken2?toClaudeCodeName(tool.name):tool.name}});for(let tool of msg.toolsAdded??[])blocks.push({type:"tool_addition",tool:{type:"tool_reference",name:isOAuthToken2?toClaudeCodeName(tool.name):tool.name}})}blocks.length>0&&pendingSystemMessages.push({role:"system",content:blocks})}else if(msg.role==="user")if(typeof msg.content=="string")msg.content.trim().length>0&&params.push({role:"user",content:sanitizeSurrogates(msg.content)});else{let filteredBlocks=msg.content.map(item=>item.type==="text"?{type:"text",text:sanitizeSurrogates(item.text)}:{type:"image",source:{type:"base64",media_type:item.mimeType,data:item.data}}).filter(b=>b.type==="text"?b.text.trim().length>0:!0);if(filteredBlocks.length===0)continue;params.push({role:"user",content:filteredBlocks})}else if(msg.role==="assistant"){flushPendingSystemMessages();let blocks=[];for(let block of msg.content)if(block.type==="text"){if(block.text.trim().length===0)continue;blocks.push({type:"text",text:sanitizeSurrogates(block.text)})}else if(block.type==="thinking"){if(block.redacted){blocks.push({type:"redacted_thinking",data:block.thinkingSignature});continue}let thinkingSignature=block.thinkingSignature,hasThinkingSignature=!!thinkingSignature&&thinkingSignature.trim().length>0;if(block.thinking.trim().length===0&&!hasThinkingSignature)continue;hasThinkingSignature?blocks.push({type:"thinking",thinking:sanitizeSurrogates(block.thinking),signature:thinkingSignature}):blocks.push(allowEmptySignature?{type:"thinking",thinking:sanitizeSurrogates(block.thinking),signature:""}:{type:"text",text:sanitizeSurrogates(block.thinking)})}else block.type==="toolCall"&&blocks.push({type:"tool_use",id:block.id,name:isOAuthToken2?toClaudeCodeName(block.name):block.name,input:block.arguments??{}});if(blocks.length===0)continue;let messageIndex=params.length;params.push({role:"assistant",content:blocks}),managedProvider!==void 0&&msg.api==="anthropic-messages"&&msg.provider===managedProvider&&isAnthropicEffort(msg.providerThinkingLevel)&&assistantLevels.set(messageIndex,msg.providerThinkingLevel)}else if(msg.role==="toolResult"){let toolResults=[],j=i;for(;j<transformedMessages.length&&transformedMessages[j].role==="toolResult";)toolResults.push(convertToolResult(transformedMessages[j])),j++;i=j-1,params.push({role:"user",content:toolResults})}}if(flushPendingSystemMessages(),cacheControl&&params.length>0){let lastMessage=params[params.length-1];if(lastMessage.role==="user"||lastMessage.role==="system")if(Array.isArray(lastMessage.content)){let lastBlock=lastMessage.content[lastMessage.content.length-1];lastBlock&&(lastBlock.type==="text"||lastBlock.type==="image"||lastBlock.type==="tool_result"||lastBlock.type==="tool_addition"||lastBlock.type==="tool_removal")&&(lastBlock.cache_control=cacheControl)}else typeof lastMessage.content=="string"&&(lastMessage.content=[{type:"text",text:lastMessage.content,cache_control:cacheControl}])}return{messages:params,assistantLevels}}function isAnthropicEffort(value){return value==="low"||value==="medium"||value==="high"||value==="xhigh"||value==="max"}function insertThinkingLevelMessages(converted,activeEffort){let messages=[];for(let index=0;index<converted.messages.length;index++){let historicalEffort=converted.assistantLevels.get(index);historicalEffort!==void 0&&messages.push({role:"system",content:[],output_config:{effort:historicalEffort}}),messages.push(converted.messages[index])}return messages.push({role:"system",content:[],output_config:{effort:activeEffort}}),messages}function shouldUseFineGrainedToolStreamingBeta(model,context){return getCurrentTools(context.messages).length>0&&!getAnthropicCompat(model).supportsEagerToolInputStreaming}function convertTools(tools,isOAuthToken2,supportsEagerToolInputStreaming,supportsStrictTools,cacheControl){return tools?tools.map((tool,index)=>{let strict=resolveJsonSchemaStrictSampling(tool,supportsStrictTools),parameters=getJsonSchemaToolParameters(tool,strict),schema=parameters,legacyInputSchema={type:"object",properties:schema.properties??{},required:schema.required??[]},inputSchema=strict===!0?{...parameters,...legacyInputSchema}:legacyInputSchema;return{name:isOAuthToken2?toClaudeCodeName(tool.name):tool.name,description:tool.description,...supportsEagerToolInputStreaming?{eager_input_streaming:!0}:{},...strict===!0?{strict:!0}:{},input_schema:inputSchema,...cacheControl&&index===tools.length-1?{cache_control:cacheControl}:{}}}):[]}function mapStopReason(reason,stopDetails){switch(reason){case"end_turn":return{stopReason:"stop"};case"max_tokens":return{stopReason:"length"};case"tool_use":return{stopReason:"toolUse"};case"refusal":return{stopReason:"error",errorMessage:stopDetails?.explanation||"The model refused to complete the request"};case"pause_turn":return{stopReason:"stop"};case"stop_sequence":return{stopReason:"stop"};case"sensitive":return{stopReason:"error",errorMessage:"Provider stopped with: sensitive"};default:throw new Error(`Unhandled stop reason: ${reason}`)}}export{stream,streamSimple};
@@ -1,2 +0,0 @@
1
- import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- import{convertResponsesMessages,convertResponsesTools,processResponsesStream}from"./chunk-V7IXECST.js";import{clampOpenAIPromptCacheKey}from"./chunk-PRRNXB7S.js";import{AzureOpenAI}from"./chunk-NUHFSC37.js";import{formatProviderError,normalizeProviderError}from"./chunk-TEPMHNKQ.js";import"./chunk-PJACZCIR.js";import{retryProviderRequest}from"./chunk-XNGRGP62.js";import{buildBaseOptions,createGrammarToolInputProperties,getPiUserAgent}from"./chunk-GNYZK6XN.js";import"./chunk-L2ZPNLYD.js";import{headersToRecord}from"./chunk-UTB4DTYQ.js";import{getProviderEnvValue}from"./chunk-DRQDKNXA.js";import"./chunk-TRDNDS6A.js";import{clampThinkingLevel,getDeclaredTools,resolveTranscript,resolveTranscriptTools}from"./chunk-FU4XQUSL.js";import{AssistantMessageEventStream}from"./chunk-A3JYRWB6.js";import"./chunk-4L3WN2XY.js";var DEFAULT_AZURE_API_VERSION="v1",AZURE_TOOL_CALL_PROVIDERS=new Set(["openai","openai-codex","opencode","azure-openai-responses"]),OPENAI_RESPONSES_MIN_OUTPUT_TOKENS=16;function parseDeploymentNameMap(value){let map=new Map;if(!value)return map;for(let entry of value.split(",")){let trimmed=entry.trim();if(!trimmed)continue;let[modelId,deploymentName]=trimmed.split("=",2);!modelId||!deploymentName||map.set(modelId.trim(),deploymentName.trim())}return map}function resolveDeploymentName(model,options){return options?.azureDeploymentName?options.azureDeploymentName:parseDeploymentNameMap(getProviderEnvValue("AZURE_OPENAI_DEPLOYMENT_NAME_MAP",options?.env)).get(model.id)||model.id}function formatAzureOpenAIError(error){return formatProviderError(normalizeProviderError(error),"Azure OpenAI API error")}var stream=(model,context,options)=>{let stream2=new AssistantMessageEventStream,normalizedContext=resolveTranscript(context,model.compat?.supportsMidConvoSystemMessages);return(async()=>{let deploymentName=resolveDeploymentName(model,options),output={role:"assistant",content:[],api:"azure-openai-responses",provider:model.provider,model:model.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"pending",timestamp:Date.now()};try{let apiKey=options?.apiKey;if(!apiKey)throw new Error(`No API key for provider: ${model.provider}`);let client=createClient(model,apiKey,options),grammarToolInputProperties=createGrammarToolInputProperties(getDeclaredTools(normalizedContext.messages),model.compat?.supportsOpenAIGrammarTools??!1),params=buildParams(model,normalizedContext,options,deploymentName,grammarToolInputProperties),nextParams=await options?.onPayload?.(params,model);nextParams!==void 0&&(params=nextParams);let requestOptions={...options?.signal?{signal:options.signal}:{},...options?.timeoutMs!==void 0?{timeout:options.timeoutMs}:{},maxRetries:0},{data:openaiStream,response}=await retryProviderRequest(()=>client.responses.create(params,requestOptions).withResponse(),{maxRetries:options?.maxRetries,maxRetryDelayMs:options?.maxRetryDelayMs,signal:options?.signal});if(await options?.onResponse?.({status:response.status,headers:headersToRecord(response.headers)},model),stream2.push({type:"start",partial:output}),await processResponsesStream(openaiStream,output,stream2,model,{onProviderStreamEvent:options?.onProviderStreamEvent,grammarToolInputProperties}),options?.signal?.aborted)throw new Error("Request was aborted");if(output.stopReason==="pending")throw new Error("Azure OpenAI Responses stream ended without a stop reason");if(output.stopReason==="aborted"||output.stopReason==="error")throw new Error(output.errorMessage||"An unknown error occurred");stream2.push({type:"done",reason:output.stopReason,message:output}),stream2.end()}catch(error){for(let block of output.content)delete block.index,delete block.partialJson,delete block.customInput;output.stopReason=options?.signal?.aborted?"aborted":"error",output.errorMessage=formatAzureOpenAIError(error),stream2.push({type:"error",reason:output.stopReason,error:output}),stream2.end()}})(),stream2},streamSimple=(model,context,options)=>{let apiKey=options?.apiKey;if(!apiKey)throw new Error(`No API key for provider: ${model.provider}`);let base={...buildBaseOptions(model,context,options,apiKey),toolChoice:options?.toolChoice},clampedReasoning=options?.reasoning?clampThinkingLevel(model,options.reasoning):void 0;return stream(model,context,{...base,reasoningEffort:clampedReasoning==="off"?void 0:clampedReasoning})};function normalizeAzureBaseUrl(baseUrl){let trimmed=baseUrl.trim().replace(/\/+$/,""),url;try{url=new URL(trimmed)}catch{throw new Error(`Invalid Azure OpenAI base URL: ${baseUrl}`)}let isAzureHost=url.hostname.endsWith(".openai.azure.com")||url.hostname.endsWith(".cognitiveservices.azure.com")||url.hostname.endsWith(".ai.azure.com"),normalizedPath=url.pathname.replace(/\/+$/,"");return isAzureHost&&(normalizedPath===""||normalizedPath==="/"||normalizedPath==="/openai"||normalizedPath==="/openai/v1/responses")&&(url.pathname="/openai/v1",url.search=""),url.toString().replace(/\/+$/,"")}function buildDefaultBaseUrl(resourceName){return`https://${resourceName}.openai.azure.com/openai/v1`}function resolveAzureConfig(model,options){let apiVersion=options?.azureApiVersion||getProviderEnvValue("AZURE_OPENAI_API_VERSION",options?.env)||DEFAULT_AZURE_API_VERSION,baseUrl=options?.azureBaseUrl?.trim()||getProviderEnvValue("AZURE_OPENAI_BASE_URL",options?.env)?.trim()||void 0,resourceName=options?.azureResourceName||getProviderEnvValue("AZURE_OPENAI_RESOURCE_NAME",options?.env),resolvedBaseUrl=baseUrl;if(!resolvedBaseUrl&&resourceName&&(resolvedBaseUrl=buildDefaultBaseUrl(resourceName)),!resolvedBaseUrl&&model.baseUrl&&(resolvedBaseUrl=model.baseUrl),!resolvedBaseUrl)throw new Error("Azure OpenAI base URL is required. Set AZURE_OPENAI_BASE_URL or AZURE_OPENAI_RESOURCE_NAME, or pass azureBaseUrl, azureResourceName, or model.baseUrl.");return{baseUrl:normalizeAzureBaseUrl(resolvedBaseUrl),apiVersion}}function createClient(model,apiKey,options){let headers={"User-Agent":getPiUserAgent(),...model.headers};options?.headers&&Object.assign(headers,options.headers);let{baseUrl,apiVersion}=resolveAzureConfig(model,options);return new AzureOpenAI({apiKey,apiVersion,dangerouslyAllowBrowser:!0,fetch:options?.fetch,defaultHeaders:headers,baseURL:baseUrl})}function buildParams(model,context,options,deploymentName,grammarToolInputProperties=createGrammarToolInputProperties(getDeclaredTools(context.messages),model.compat?.supportsOpenAIGrammarTools??!1)){let supportsAdditionalTools=model.compat?.supportsAdditionalTools??!1,supportsToolSearch=model.compat?.supportsToolSearch??!1,transcriptTools=resolveTranscriptTools(context.messages,supportsAdditionalTools||supportsToolSearch),messages=convertResponsesMessages(model,context,AZURE_TOOL_CALL_PROVIDERS,{grammarToolInputProperties,supportsMidConvoSystemMessages:model.compat?.supportsMidConvoSystemMessages??!1,supportsAdditionalTools,supportsToolSearch,toolOptions:{supportsStrictMode:model.compat?.supportsStrictMode??!0,supportsOpenAIGrammarTools:model.compat?.supportsOpenAIGrammarTools??!1}}),params={model:deploymentName,input:messages,stream:!0,prompt_cache_key:clampOpenAIPromptCacheKey(options?.sessionId),store:!1};if(options?.maxTokens&&(params.max_output_tokens=Math.max(options.maxTokens,OPENAI_RESPONSES_MIN_OUTPUT_TOKENS)),options?.temperature!==void 0&&(params.temperature=options?.temperature),transcriptTools.requestTools.length>0&&(params.tools=convertResponsesTools(transcriptTools.requestTools,{supportsStrictMode:model.compat?.supportsStrictMode??!0,supportsOpenAIGrammarTools:model.compat?.supportsOpenAIGrammarTools??!1})),options?.toolChoice!==void 0&&(params.tool_choice=options.toolChoice),model.reasoning)if(options?.reasoningEffort||options?.reasoningSummary){let effort=options?.reasoningEffort?model.thinkingLevelMap?.[options.reasoningEffort]??options.reasoningEffort:"medium";params.reasoning={effort,summary:options?.reasoningSummary||"auto"},params.include=["reasoning.encrypted_content"]}else model.thinkingLevelMap?.off!==null&&(params.reasoning={effort:model.thinkingLevelMap?.off??"none"});return options?.samplingParams&&Object.assign(params,options.samplingParams),params}export{stream,streamSimple};
@@ -1,2 +0,0 @@
1
- import { createRequire as __piCreateRequire } from "node:module"; const require = __piCreateRequire(import.meta.url);
2
- var FifoQueue=class{incoming=[];outgoing=[];get length(){return this.incoming.length+this.outgoing.length}enqueue(value){this.incoming.push(value)}dequeue(){if(this.outgoing.length===0)for(;this.incoming.length>0;)this.outgoing.push(this.incoming.pop());return this.outgoing.pop()}},EventStream=class{queue=new FifoQueue;waiting=new FifoQueue;done=!1;finalResultPromise;resolveFinalResult;isComplete;extractResult;constructor(isComplete,extractResult){this.isComplete=isComplete,this.extractResult=extractResult,this.finalResultPromise=new Promise(resolve=>{this.resolveFinalResult=resolve})}push(event){if(this.done)return;this.isComplete(event)&&(this.done=!0,this.resolveFinalResult(this.extractResult(event)));let waiter=this.waiting.dequeue();waiter?waiter({value:event,done:!1}):this.queue.enqueue(event)}end(result){for(this.done=!0,result!==void 0&&this.resolveFinalResult(result);this.waiting.length>0;)this.waiting.dequeue()({value:void 0,done:!0})}async*[Symbol.asyncIterator](){for(;;)if(this.queue.length>0)yield this.queue.dequeue();else{if(this.done)return;{let result=await new Promise(resolve=>this.waiting.enqueue(resolve));if(result.done)return;yield result.value}}}result(){return this.finalResultPromise}},AssistantMessageEventStream=class extends EventStream{constructor(){super(event=>event.type==="done"||event.type==="error",event=>{if(event.type==="done")return event.message;if(event.type==="error")return event.error;throw new Error("Unexpected event type for final result")})}};function createAssistantMessageEventStream(){return new AssistantMessageEventStream}function formatThrownValue(value){return value instanceof Error?value.message||value.name:typeof value=="string"?value:String(value)}function extractDiagnosticError(error){if(!(error instanceof Error))return{name:"ThrownValue",message:formatThrownValue(error)};let code=error.code;return{name:error.name||void 0,message:error.message||error.name,stack:error.stack,code:typeof code=="string"||typeof code=="number"?code:void 0}}function createAssistantMessageDiagnostic(type,error,details){return{type,timestamp:Date.now(),error:extractDiagnosticError(error),details}}function appendAssistantMessageDiagnostic(message,diagnostic){message.diagnostics=[...message.diagnostics??[],diagnostic]}export{EventStream,AssistantMessageEventStream,createAssistantMessageEventStream,formatThrownValue,extractDiagnosticError,createAssistantMessageDiagnostic,appendAssistantMessageDiagnostic};