Mike0021 commited on
Commit
ac7f517
·
verified ·
1 Parent(s): 96ec1de

Port Pi CLI to browser terminal

Browse files
Files changed (41) hide show
  1. README.md +23 -9
  2. dist/assets/__vite-browser-external-2447137e-BIHI7g3E.js +1 -0
  3. dist/assets/addon-fit-DX4qG4td.js +1 -0
  4. dist/assets/{anthropic-krspaSzV.js → anthropic-Dm0nVZ1A.js} +0 -0
  5. dist/assets/{azure-openai-responses-DQgZJh_L.js → azure-openai-responses-BGzUURKK.js} +1 -1
  6. dist/assets/ghostty-web-C21go6Pk.js +0 -0
  7. dist/assets/{google-H5Z3-yH4.js → google-kA_fw5EZ.js} +1 -1
  8. dist/assets/{google-shared-CZIKa0Kf.js → google-shared-tMPbwRUC.js} +0 -0
  9. dist/assets/{google-vertex-YpwsH_3V.js → google-vertex-CxMnHyvQ.js} +1 -1
  10. dist/assets/index-4NYd9uAS.css +0 -1
  11. dist/assets/index-CB_zB4U3.js +0 -0
  12. dist/assets/index-CgfZNSZZ.js +0 -0
  13. dist/assets/index-NRwwiW4N.css +1 -0
  14. dist/assets/{json-parse-B9Wfu_bW.js → json-parse-cUk3uCki.js} +1 -1
  15. dist/assets/{mistral-D2dGPAye.js → mistral-mDLdw-bF.js} +1 -1
  16. dist/assets/openai-codex-responses-7plNQja4.js +7 -0
  17. dist/assets/openai-codex-responses-CTXzuzSc.js +0 -7
  18. dist/assets/{openai-completions-ChsgufLt.js → openai-completions-CTz74GS-.js} +5 -5
  19. dist/assets/{openai-responses-wXWgXVPI.js → openai-responses-CW5o7IM-.js} +1 -1
  20. dist/assets/{openai-responses-shared-HtwCtL3B.js → openai-responses-shared-DBUlz2NN.js} +5 -5
  21. dist/assets/openrouter-CMw3KGq6.js +0 -1
  22. dist/assets/openrouter-DE7amXV2.js +1 -0
  23. dist/assets/transform-messages-Bxe2XUr4.js +0 -1
  24. dist/assets/transform-messages-DSNYjDRn.js +1 -0
  25. dist/assets/xterm-B-qIQCd3.js +0 -0
  26. dist/index.html +17 -76
  27. index.html +15 -74
  28. package-lock.json +0 -0
  29. package.json +7 -2
  30. scripts/compare_pi_cli_parity.mjs +89 -0
  31. scripts/probe_token_budgets.mjs +15 -20
  32. scripts/smoke_complex_tasks.mjs +24 -34
  33. scripts/smoke_local_model_web_agent.mjs +18 -28
  34. scripts/smoke_web_agent.mjs +33 -20
  35. src/main.js +30 -358
  36. src/piAgent.js +322 -166
  37. src/piCli.js +524 -0
  38. src/piCliContract.js +101 -0
  39. src/sandbox.js +224 -19
  40. src/styles.css +79 -271
  41. src/webTerminal.js +88 -0
README.md CHANGED
@@ -1,5 +1,5 @@
1
  ---
2
- title: Pi Web Agent
3
  sdk: static
4
  app_file: dist/index.html
5
  fullWidth: true
@@ -13,9 +13,11 @@ custom_headers:
13
  cross-origin-resource-policy: cross-origin
14
  ---
15
 
16
- # Pi Web Agent
17
 
18
- This workspace ships a browser-only pi agent app backed by Transformers.js and WebContainers. The default planner is `onnx-community/Qwen2.5-Coder-0.5B-Instruct` because it produced the strongest browser result in the local task suite; Qwen3 0.6B and the converted MiniCPM5 model remain selectable for comparison.
 
 
19
 
20
  Published artifact: https://huggingface.co/Mike0021/MiniCPM5-1B-ONNX-Web
21
 
@@ -39,14 +41,16 @@ Open http://localhost:5173/.
39
  The app uses:
40
 
41
  - `@earendil-works/pi-agent-core` for the agent loop, transcript state, and tool execution.
 
 
42
  - `@huggingface/transformers` with `onnx-community/Qwen2.5-Coder-0.5B-Instruct` as the default local browser planner.
43
  - `@webcontainer/api` for the client-only sandbox with a virtual filesystem and browser-contained Node.js processes.
44
 
45
- Vite serves the app with COOP/COEP headers and boots WebContainers with `coep: "credentialless"`. The deterministic test model is available at `http://localhost:5173/?mode=mock&device=wasm` for fast harness and sandbox smoke tests without downloading an ONNX model. The local model defaults to a tested 256-token generation budget in WASM mode and the UI allows budgets up to 8192.
46
 
47
  The Static Space uses the same isolation policy through `custom_headers` in this README frontmatter. The app is built with `npm run build` and the generated `dist/` directory is uploaded to the Space.
48
 
49
- ## Test the Agent App
50
 
51
  Start the dev server, then run:
52
 
@@ -54,7 +58,15 @@ Start the dev server, then run:
54
  npm run smoke:web
55
  ```
56
 
57
- The smoke test opens Chromium, confirms `crossOriginIsolated`, submits the chat prompt in deterministic mode, boots the WebContainer sandbox, writes `hello.js`, spawns `node hello.js`, and checks for `pi sandbox result: 42` in the chat transcript.
 
 
 
 
 
 
 
 
58
 
59
  For the heavier end-to-end check with the real ONNX model in browser WASM mode:
60
 
@@ -70,7 +82,7 @@ The complex smoke test covers simple code execution, installing and using an npm
70
  npm run smoke:complex
71
  ```
72
 
73
- The sandbox can install and use Node packages through the same `run_command` tool, for example `npm install is-number@7.0.0` followed by `node check-package.mjs`.
74
 
75
  To probe larger browser generation budgets:
76
 
@@ -80,8 +92,10 @@ TOKEN_BUDGETS=80,256,2048,8192 npm run probe:tokens
80
 
81
  Measured local WASM results with Qwen2.5-Coder 0.5B:
82
 
83
- - `npm run smoke:local-model` passed at 80 max new tokens.
84
- - `MAX_NEW_TOKENS=256 npm run smoke:complex` passed simple, npm dependency, and multi-file module tasks.
 
 
85
  - `TOKEN_BUDGETS=80,160,256,512,1024,2048,4096,8192 npm run probe:tokens` passed. Higher caps were accepted; for the probe task the model stopped naturally before using the full cap.
86
 
87
  ## Verify the Published Artifact
 
1
  ---
2
+ title: Pi CLI Web
3
  sdk: static
4
  app_file: dist/index.html
5
  fullWidth: true
 
13
  cross-origin-resource-policy: cross-origin
14
  ---
15
 
16
+ # Pi CLI Web
17
 
18
+ This workspace ships a browser-only port of the `pi` CLI backed by Transformers.js, WebContainers, and a real terminal surface. The UI uses `ghostty-web` first, with `@xterm/xterm` as a fallback, and exposes Pi's built-in tool names: `read`, `bash`, `edit`, `write`, plus read-only `grep`, `find`, and `ls`.
19
+
20
+ The default planner is `onnx-community/Qwen2.5-Coder-0.5B-Instruct` because it produced the strongest browser result in the local task suite; Qwen3 0.6B and the converted MiniCPM5 model remain selectable for comparison.
21
 
22
  Published artifact: https://huggingface.co/Mike0021/MiniCPM5-1B-ONNX-Web
23
 
 
41
  The app uses:
42
 
43
  - `@earendil-works/pi-agent-core` for the agent loop, transcript state, and tool execution.
44
+ - `@earendil-works/pi-coding-agent` as the installed CLI contract for parity checks against `pi --help` and `pi --version`.
45
+ - `ghostty-web` as the terminal frontend, with `@xterm/xterm` fallback.
46
  - `@huggingface/transformers` with `onnx-community/Qwen2.5-Coder-0.5B-Instruct` as the default local browser planner.
47
  - `@webcontainer/api` for the client-only sandbox with a virtual filesystem and browser-contained Node.js processes.
48
 
49
+ Vite serves the app with COOP/COEP headers and boots WebContainers with `coep: "credentialless"`. The deterministic test model is available at `http://localhost:5173/?mode=mock&device=wasm` for fast harness and sandbox smoke tests without downloading an ONNX model. The local model defaults to a tested 256-token generation budget in WASM mode and supports budgets up to 8192 through the `tokens=` query parameter and `/settings tokens=<n>`.
50
 
51
  The Static Space uses the same isolation policy through `custom_headers` in this README frontmatter. The app is built with `npm run build` and the generated `dist/` directory is uploaded to the Space.
52
 
53
+ ## Test the CLI Web App
54
 
55
  Start the dev server, then run:
56
 
 
58
  npm run smoke:web
59
  ```
60
 
61
+ The smoke test opens Chromium, confirms `crossOriginIsolated`, verifies the terminal startup, runs `/help`, executes a direct `!!node ...` command, then submits a deterministic Pi task that writes `hello.js`, runs `bash`/Node in WebContainer, and checks for `pi sandbox result: 42`.
62
+
63
+ To compare the web terminal contract against the installed real CLI:
64
+
65
+ ```bash
66
+ npm run parity:cli
67
+ ```
68
+
69
+ This checks `pi --version`, the `pi --help` contract, slash commands, and the built-in tool names exposed by the browser terminal.
70
 
71
  For the heavier end-to-end check with the real ONNX model in browser WASM mode:
72
 
 
82
  npm run smoke:complex
83
  ```
84
 
85
+ The sandbox can install and use Node packages through the same Pi `bash` tool, for example `npm install is-number@7.0.0` followed by `node check-package.mjs`.
86
 
87
  To probe larger browser generation budgets:
88
 
 
92
 
93
  Measured local WASM results with Qwen2.5-Coder 0.5B:
94
 
95
+ - `npm run smoke:web` passed in deterministic mode using the `ghostty-web` terminal.
96
+ - `npm run parity:cli` passed against `@earendil-works/pi-coding-agent@0.77.0`.
97
+ - `MAX_NEW_TOKENS=80 npm run smoke:local-model` passed with the real browser model.
98
+ - `MAX_NEW_TOKENS=256 npm run smoke:complex` passed simple, npm dependency, and multi-file module tasks with the real browser model.
99
  - `TOKEN_BUDGETS=80,160,256,512,1024,2048,4096,8192 npm run probe:tokens` passed. Higher caps were accepted; for the probe task the model stopped naturally before using the full cap.
100
 
101
  ## Verify the Published Artifact
dist/assets/__vite-browser-external-2447137e-BIHI7g3E.js ADDED
@@ -0,0 +1 @@
 
 
1
+ const e={};export{e as default};
dist/assets/addon-fit-DX4qG4td.js ADDED
@@ -0,0 +1 @@
 
 
1
+ var p=2,c=1,d=class{activate(e){this._terminal=e}dispose(){}fit(){let e=this.proposeDimensions();if(!e||!this._terminal||isNaN(e.cols)||isNaN(e.rows))return;let i=this._terminal._core;(this._terminal.rows!==e.rows||this._terminal.cols!==e.cols)&&(i._renderService.clear(),this._terminal.resize(e.cols,e.rows))}proposeDimensions(){if(!this._terminal||!this._terminal.element||!this._terminal.element.parentElement)return;let e=this._terminal._core._renderService.dimensions;if(e.css.cell.width===0||e.css.cell.height===0)return;let i=this._terminal.options.scrollback===0?0:this._terminal.options.overviewRuler?.width||14,s=window.getComputedStyle(this._terminal.element.parentElement),l=parseInt(s.getPropertyValue("height")),o=Math.max(0,parseInt(s.getPropertyValue("width"))),t=window.getComputedStyle(this._terminal.element),r={top:parseInt(t.getPropertyValue("padding-top")),bottom:parseInt(t.getPropertyValue("padding-bottom")),right:parseInt(t.getPropertyValue("padding-right")),left:parseInt(t.getPropertyValue("padding-left"))},a=r.top+r.bottom,n=r.right+r.left,h=l-a,m=o-n-i;return{cols:Math.max(p,Math.floor(m/e.css.cell.width)),rows:Math.max(c,Math.floor(h/e.css.cell.height))}}};export{d as FitAddon};
dist/assets/{anthropic-krspaSzV.js → anthropic-Dm0nVZ1A.js} RENAMED
The diff for this file is too large to render. See raw diff
 
dist/assets/{azure-openai-responses-DQgZJh_L.js → azure-openai-responses-BGzUURKK.js} RENAMED
@@ -1 +1 @@
1
- import{O as h,a as c,r as m,i as _,b as R}from"./client-Sq9UPDIz.js";import{A as y,g as l,a as I}from"./index-CgfZNSZZ.js";import{h as g}from"./headers-CgnjaPPL.js";import{c as v}from"./openai-prompt-cache-h_V5PL7P.js";import{p as O,c as N,a as b}from"./openai-responses-shared-HtwCtL3B.js";import{b as P}from"./transform-messages-Bxe2XUr4.js";import"./hash-DMDecQcg.js";import"./json-parse-B9Wfu_bW.js";import"./sanitize-unicode-B62XMGgN.js";var w={};class U extends h{constructor({baseURL:t=m("OPENAI_BASE_URL"),apiKey:e=m("AZURE_OPENAI_API_KEY"),apiVersion:s=m("OPENAI_API_VERSION"),endpoint:n,deployment:a,azureADTokenProvider:o,dangerouslyAllowBrowser:i,...u}={}){if(!s)throw new c("The OPENAI_API_VERSION environment variable is missing or empty; either provide it, or instantiate the AzureOpenAI client with an apiVersion option, like new AzureOpenAI({ apiVersion: 'My API Version' }).");if(typeof o=="function"&&(i=!0),!o&&!e)throw new c("Missing credentials. Please pass one of `apiKey` and `azureADTokenProvider`, or set the `AZURE_OPENAI_API_KEY` environment variable.");if(o&&e)throw new c("The `apiKey` and `azureADTokenProvider` arguments are mutually exclusive; only one can be passed at a time.");if(u.defaultQuery={...u.defaultQuery,"api-version":s},t){if(n)throw new c("baseURL and endpoint are mutually exclusive")}else{if(n||(n=w.AZURE_OPENAI_ENDPOINT),!n)throw new c("Must provide one of the `baseURL` or `endpoint` arguments, or the `AZURE_OPENAI_ENDPOINT` environment variable");t=`${n}/openai`}super({apiKey:o??e,baseURL:t,...u,...i!==void 0?{dangerouslyAllowBrowser:i}:{}}),this.apiVersion="",this.apiVersion=s,this.deploymentName=a}async buildRequest(t,e={}){if(z.has(t.path)&&t.method==="post"&&t.body!==void 0){if(!_(t.body))throw new Error("Expected request body to be an object");const s=this.deploymentName||t.body.model||t.__metadata?.model;s!==void 0&&!this.baseURL.includes("/deployments")&&(t.path=`/deployments/${s}${t.path}`)}return super.buildRequest(t,e)}async authHeaders(t){return typeof this._options.apiKey=="string"?R([{"api-key":this.apiKey}]):super.authHeaders(t)}}const z=new Set(["/completions","/chat/completions","/embeddings","/audio/transcriptions","/audio/translations","/audio/speech","/images/generations","/batches","/images/edits"]);var p={};const S="v1",M=new Set(["openai","openai-codex","opencode","azure-openai-responses"]);function L(r){const t=new Map;if(!r)return t;for(const e of r.split(",")){const s=e.trim();if(!s)continue;const[n,a]=s.split("=",2);!n||!a||t.set(n.trim(),a.trim())}return t}function Z(r,t){return t?.azureDeploymentName?t.azureDeploymentName:L(p.AZURE_OPENAI_DEPLOYMENT_NAME_MAP).get(r.id)||r.id}function k(r){if(r instanceof Error){const t=r.status,e=typeof t=="number"?t:void 0;return e!==void 0?`Azure OpenAI API error (${e}): ${r.message}`:r.message}try{return JSON.stringify(r)}catch{return String(r)}}const D=(r,t,e)=>{const s=new y;return(async()=>{const n=Z(r,e),a={role:"assistant",content:[],api:"azure-openai-responses",provider:r.provider,model:r.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const o=e?.apiKey||l(r.provider)||"",i=x(r,o,e);let u=V(r,t,e,n);const d=await e?.onPayload?.(u,r);d!==void 0&&(u=d);const A={...e?.signal?{signal:e.signal}:{},...e?.timeoutMs!==void 0?{timeout:e.timeoutMs}:{},...e?.maxRetries!==void 0?{maxRetries:e.maxRetries}:{}},{data:E,response:f}=await i.responses.create(u,A).withResponse();if(await e?.onResponse?.({status:f.status,headers:g(f.headers)},r),s.push({type:"start",partial:a}),await O(E,a,s,r),e?.signal?.aborted)throw new Error("Request was aborted");if(a.stopReason==="aborted"||a.stopReason==="error")throw new Error("An unknown error occurred");s.push({type:"done",reason:a.stopReason,message:a}),s.end()}catch(o){for(const i of a.content)delete i.index,delete i.partialJson;a.stopReason=e?.signal?.aborted?"aborted":"error",a.errorMessage=k(o),s.push({type:"error",reason:a.stopReason,error:a}),s.end()}})(),s},F=(r,t,e)=>{const s=e?.apiKey||l(r.provider);if(!s)throw new Error(`No API key for provider: ${r.provider}`);const n=P(r,e,s),a=e?.reasoning?I(r,e.reasoning):void 0;return D(r,t,{...n,reasoningEffort:a==="off"?void 0:a})};function K(r){const t=r.trim().replace(/\/+$/,"");let e;try{e=new URL(t)}catch{throw new Error(`Invalid Azure OpenAI base URL: ${r}`)}const s=e.hostname.endsWith(".openai.azure.com")||e.hostname.endsWith(".cognitiveservices.azure.com"),n=e.pathname.replace(/\/+$/,"");return s&&(n===""||n==="/"||n==="/openai")&&(e.pathname="/openai/v1",e.search=""),e.toString().replace(/\/+$/,"")}function T(r){return`https://${r}.openai.azure.com/openai/v1`}function $(r,t){const e=t?.azureApiVersion||p.AZURE_OPENAI_API_VERSION||S,s=t?.azureBaseUrl?.trim()||p.AZURE_OPENAI_BASE_URL?.trim()||void 0,n=t?.azureResourceName||p.AZURE_OPENAI_RESOURCE_NAME;let a=s;if(!a&&n&&(a=T(n)),!a&&r.baseUrl&&(a=r.baseUrl),!a)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:K(a),apiVersion:e}}function x(r,t,e){if(!t){if(!p.AZURE_OPENAI_API_KEY)throw new Error("Azure OpenAI API key is required. Set AZURE_OPENAI_API_KEY environment variable or pass it as an argument.");t=p.AZURE_OPENAI_API_KEY}const s={...r.headers};e?.headers&&Object.assign(s,e.headers);const{baseUrl:n,apiVersion:a}=$(r,e);return new U({apiKey:t,apiVersion:a,dangerouslyAllowBrowser:!0,defaultHeaders:s,baseURL:n})}function V(r,t,e,s){const n=N(r,t,M),a={model:s,input:n,stream:!0,prompt_cache_key:v(e?.sessionId)};if(e?.maxTokens&&(a.max_output_tokens=e?.maxTokens),e?.temperature!==void 0&&(a.temperature=e?.temperature),t.tools&&t.tools.length>0&&(a.tools=b(t.tools)),r.reasoning)if(e?.reasoningEffort||e?.reasoningSummary){const o=e?.reasoningEffort?r.thinkingLevelMap?.[e.reasoningEffort]??e.reasoningEffort:"medium";a.reasoning={effort:o,summary:e?.reasoningSummary||"auto"},a.include=["reasoning.encrypted_content"]}else r.thinkingLevelMap?.off!==null&&(a.reasoning={effort:r.thinkingLevelMap?.off??"none"});return a}export{D as streamAzureOpenAIResponses,F as streamSimpleAzureOpenAIResponses};
 
1
+ import{O as h,a as c,r as m,i as _,b as R}from"./client-Sq9UPDIz.js";import{A as y,g as l,a as I}from"./index-CB_zB4U3.js";import{h as g}from"./headers-CgnjaPPL.js";import{c as v}from"./openai-prompt-cache-h_V5PL7P.js";import{p as O,c as N,a as b}from"./openai-responses-shared-DBUlz2NN.js";import{b as P}from"./transform-messages-DSNYjDRn.js";import"./hash-DMDecQcg.js";import"./json-parse-cUk3uCki.js";import"./sanitize-unicode-B62XMGgN.js";var w={};class U extends h{constructor({baseURL:t=m("OPENAI_BASE_URL"),apiKey:e=m("AZURE_OPENAI_API_KEY"),apiVersion:s=m("OPENAI_API_VERSION"),endpoint:n,deployment:a,azureADTokenProvider:o,dangerouslyAllowBrowser:i,...u}={}){if(!s)throw new c("The OPENAI_API_VERSION environment variable is missing or empty; either provide it, or instantiate the AzureOpenAI client with an apiVersion option, like new AzureOpenAI({ apiVersion: 'My API Version' }).");if(typeof o=="function"&&(i=!0),!o&&!e)throw new c("Missing credentials. Please pass one of `apiKey` and `azureADTokenProvider`, or set the `AZURE_OPENAI_API_KEY` environment variable.");if(o&&e)throw new c("The `apiKey` and `azureADTokenProvider` arguments are mutually exclusive; only one can be passed at a time.");if(u.defaultQuery={...u.defaultQuery,"api-version":s},t){if(n)throw new c("baseURL and endpoint are mutually exclusive")}else{if(n||(n=w.AZURE_OPENAI_ENDPOINT),!n)throw new c("Must provide one of the `baseURL` or `endpoint` arguments, or the `AZURE_OPENAI_ENDPOINT` environment variable");t=`${n}/openai`}super({apiKey:o??e,baseURL:t,...u,...i!==void 0?{dangerouslyAllowBrowser:i}:{}}),this.apiVersion="",this.apiVersion=s,this.deploymentName=a}async buildRequest(t,e={}){if(z.has(t.path)&&t.method==="post"&&t.body!==void 0){if(!_(t.body))throw new Error("Expected request body to be an object");const s=this.deploymentName||t.body.model||t.__metadata?.model;s!==void 0&&!this.baseURL.includes("/deployments")&&(t.path=`/deployments/${s}${t.path}`)}return super.buildRequest(t,e)}async authHeaders(t){return typeof this._options.apiKey=="string"?R([{"api-key":this.apiKey}]):super.authHeaders(t)}}const z=new Set(["/completions","/chat/completions","/embeddings","/audio/transcriptions","/audio/translations","/audio/speech","/images/generations","/batches","/images/edits"]);var p={};const S="v1",M=new Set(["openai","openai-codex","opencode","azure-openai-responses"]);function L(r){const t=new Map;if(!r)return t;for(const e of r.split(",")){const s=e.trim();if(!s)continue;const[n,a]=s.split("=",2);!n||!a||t.set(n.trim(),a.trim())}return t}function Z(r,t){return t?.azureDeploymentName?t.azureDeploymentName:L(p.AZURE_OPENAI_DEPLOYMENT_NAME_MAP).get(r.id)||r.id}function k(r){if(r instanceof Error){const t=r.status,e=typeof t=="number"?t:void 0;return e!==void 0?`Azure OpenAI API error (${e}): ${r.message}`:r.message}try{return JSON.stringify(r)}catch{return String(r)}}const D=(r,t,e)=>{const s=new y;return(async()=>{const n=Z(r,e),a={role:"assistant",content:[],api:"azure-openai-responses",provider:r.provider,model:r.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const o=e?.apiKey||l(r.provider)||"",i=V(r,o,e);let u=x(r,t,e,n);const d=await e?.onPayload?.(u,r);d!==void 0&&(u=d);const A={...e?.signal?{signal:e.signal}:{},...e?.timeoutMs!==void 0?{timeout:e.timeoutMs}:{},maxRetries:e?.maxRetries??0},{data:E,response:f}=await i.responses.create(u,A).withResponse();if(await e?.onResponse?.({status:f.status,headers:g(f.headers)},r),s.push({type:"start",partial:a}),await O(E,a,s,r),e?.signal?.aborted)throw new Error("Request was aborted");if(a.stopReason==="aborted"||a.stopReason==="error")throw new Error("An unknown error occurred");s.push({type:"done",reason:a.stopReason,message:a}),s.end()}catch(o){for(const i of a.content)delete i.index,delete i.partialJson;a.stopReason=e?.signal?.aborted?"aborted":"error",a.errorMessage=k(o),s.push({type:"error",reason:a.stopReason,error:a}),s.end()}})(),s},F=(r,t,e)=>{const s=e?.apiKey||l(r.provider);if(!s)throw new Error(`No API key for provider: ${r.provider}`);const n=P(r,e,s),a=e?.reasoning?I(r,e.reasoning):void 0;return D(r,t,{...n,reasoningEffort:a==="off"?void 0:a})};function K(r){const t=r.trim().replace(/\/+$/,"");let e;try{e=new URL(t)}catch{throw new Error(`Invalid Azure OpenAI base URL: ${r}`)}const s=e.hostname.endsWith(".openai.azure.com")||e.hostname.endsWith(".cognitiveservices.azure.com"),n=e.pathname.replace(/\/+$/,"");return s&&(n===""||n==="/"||n==="/openai")&&(e.pathname="/openai/v1",e.search=""),e.toString().replace(/\/+$/,"")}function T(r){return`https://${r}.openai.azure.com/openai/v1`}function $(r,t){const e=t?.azureApiVersion||p.AZURE_OPENAI_API_VERSION||S,s=t?.azureBaseUrl?.trim()||p.AZURE_OPENAI_BASE_URL?.trim()||void 0,n=t?.azureResourceName||p.AZURE_OPENAI_RESOURCE_NAME;let a=s;if(!a&&n&&(a=T(n)),!a&&r.baseUrl&&(a=r.baseUrl),!a)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:K(a),apiVersion:e}}function V(r,t,e){if(!t){if(!p.AZURE_OPENAI_API_KEY)throw new Error("Azure OpenAI API key is required. Set AZURE_OPENAI_API_KEY environment variable or pass it as an argument.");t=p.AZURE_OPENAI_API_KEY}const s={...r.headers};e?.headers&&Object.assign(s,e.headers);const{baseUrl:n,apiVersion:a}=$(r,e);return new U({apiKey:t,apiVersion:a,dangerouslyAllowBrowser:!0,defaultHeaders:s,baseURL:n})}function x(r,t,e,s){const n=N(r,t,M),a={model:s,input:n,stream:!0,prompt_cache_key:v(e?.sessionId)};if(e?.maxTokens&&(a.max_output_tokens=e?.maxTokens),e?.temperature!==void 0&&(a.temperature=e?.temperature),t.tools&&t.tools.length>0&&(a.tools=b(t.tools)),r.reasoning)if(e?.reasoningEffort||e?.reasoningSummary){const o=e?.reasoningEffort?r.thinkingLevelMap?.[e.reasoningEffort]??e.reasoningEffort:"medium";a.reasoning={effort:o,summary:e?.reasoningSummary||"auto"},a.include=["reasoning.encrypted_content"]}else r.thinkingLevelMap?.off!==null&&(a.reasoning={effort:r.thinkingLevelMap?.off??"none"});return a}export{D as streamAzureOpenAIResponses,F as streamSimpleAzureOpenAIResponses};
dist/assets/ghostty-web-C21go6Pk.js ADDED
The diff for this file is too large to render. See raw diff
 
dist/assets/{google-H5Z3-yH4.js → google-kA_fw5EZ.js} RENAMED
@@ -1 +1 @@
1
- import{i as T,r as b,m as v,G as S,c as R,a as L,b as _}from"./google-shared-CZIKa0Kf.js";import{A as G,g as x,c as O,a as A}from"./index-CgfZNSZZ.js";import{s as N}from"./sanitize-unicode-B62XMGgN.js";import{b as E}from"./transform-messages-Bxe2XUr4.js";let P=0;const f=(e,o,n)=>{const i=new G;return(async()=>{const t={role:"assistant",content:[],api:"google-generative-ai",provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const r=n?.apiKey||x(e.provider)||"",c=W(e,r,n?.headers);let u=B(e,o,n);const y=await n?.onPayload?.(u,e);y!==void 0&&(u=y);const M=await c.models.generateContentStream(u);i.push({type:"start",partial:t});let a=null;const C=t.content,l=()=>C.length-1;for await(const g of M){t.responseId||=g.responseId;const d=g.candidates?.[0];if(d?.content?.parts)for(const s of d.content.parts){if(s.text!==void 0){const h=T(s);(!a||h&&a.type!=="thinking"||!h&&a.type!=="text")&&(a&&(a.type==="text"?i.push({type:"text_end",contentIndex:C.length-1,content:a.text,partial:t}):i.push({type:"thinking_end",contentIndex:l(),content:a.thinking,partial:t})),h?(a={type:"thinking",thinking:"",thinkingSignature:void 0},t.content.push(a),i.push({type:"thinking_start",contentIndex:l(),partial:t})):(a={type:"text",text:""},t.content.push(a),i.push({type:"text_start",contentIndex:l(),partial:t}))),a.type==="thinking"?(a.thinking+=s.text,a.thinkingSignature=b(a.thinkingSignature,s.thoughtSignature),i.push({type:"thinking_delta",contentIndex:l(),delta:s.text,partial:t})):(a.text+=s.text,a.textSignature=b(a.textSignature,s.thoughtSignature),i.push({type:"text_delta",contentIndex:l(),delta:s.text,partial:t}))}if(s.functionCall){a&&(a.type==="text"?i.push({type:"text_end",contentIndex:l(),content:a.text,partial:t}):i.push({type:"thinking_end",contentIndex:l(),content:a.thinking,partial:t}),a=null);const h=s.functionCall.id,p={type:"toolCall",id:!h||t.content.some(I=>I.type==="toolCall"&&I.id===h)?`${s.functionCall.name}_${Date.now()}_${++P}`:h,name:s.functionCall.name||"",arguments:s.functionCall.args??{},...s.thoughtSignature&&{thoughtSignature:s.thoughtSignature}};t.content.push(p),i.push({type:"toolcall_start",contentIndex:l(),partial:t}),i.push({type:"toolcall_delta",contentIndex:l(),delta:JSON.stringify(p.arguments),partial:t}),i.push({type:"toolcall_end",contentIndex:l(),toolCall:p,partial:t})}}d?.finishReason&&(t.stopReason=v(d.finishReason),t.content.some(s=>s.type==="toolCall")&&(t.stopReason="toolUse")),g.usageMetadata&&(t.usage={input:(g.usageMetadata.promptTokenCount||0)-(g.usageMetadata.cachedContentTokenCount||0),output:(g.usageMetadata.candidatesTokenCount||0)+(g.usageMetadata.thoughtsTokenCount||0),cacheRead:g.usageMetadata.cachedContentTokenCount||0,cacheWrite:0,totalTokens:g.usageMetadata.totalTokenCount||0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},O(e,t.usage))}if(a&&(a.type==="text"?i.push({type:"text_end",contentIndex:l(),content:a.text,partial:t}):i.push({type:"thinking_end",contentIndex:l(),content:a.thinking,partial:t})),n?.signal?.aborted)throw new Error("Request was aborted");if(t.stopReason==="aborted"||t.stopReason==="error")throw new Error("An unknown error occurred");i.push({type:"done",reason:t.stopReason,message:t}),i.end()}catch(r){for(const c of t.content)"index"in c&&delete c.index;t.stopReason=n?.signal?.aborted?"aborted":"error",t.errorMessage=r instanceof Error?r.message:JSON.stringify(r),i.push({type:"error",reason:t.stopReason,error:t}),i.end()}})(),i},F=(e,o,n)=>{const i=n?.apiKey||x(e.provider);if(!i)throw new Error(`No API key for provider: ${e.provider}`);const t=E(e,n,i);if(!n?.reasoning)return f(e,o,{...t,thinking:{enabled:!1}});const r=A(e,n.reasoning),c=r==="off"?"high":r,u=e;return m(u)||w(u)||k(u)?f(e,o,{...t,thinking:{enabled:!0,level:K(c,u)}}):f(e,o,{...t,thinking:{enabled:!0,budgetTokens:U(u,c,n.thinkingBudgets)}})};function W(e,o,n){const i={};return e.baseUrl&&(i.baseUrl=e.baseUrl,i.apiVersion=""),(e.headers||n)&&(i.headers={...e.headers,...n}),new S({apiKey:o,httpOptions:Object.keys(i).length>0?i:void 0})}function B(e,o,n={}){const i=R(e,o),t={};n.temperature!==void 0&&(t.temperature=n.temperature),n.maxTokens!==void 0&&(t.maxOutputTokens=n.maxTokens);const r={...Object.keys(t).length>0&&t,...o.systemPrompt&&{systemInstruction:N(o.systemPrompt)},...o.tools&&o.tools.length>0&&{tools:L(o.tools)}};if(o.tools&&o.tools.length>0&&n.toolChoice?r.toolConfig={functionCallingConfig:{mode:_(n.toolChoice)}}:r.toolConfig=void 0,n.thinking?.enabled&&e.reasoning){const u={includeThoughts:!0};n.thinking.level!==void 0?u.thinkingLevel=n.thinking.level:n.thinking.budgetTokens!==void 0&&(u.thinkingBudget=n.thinking.budgetTokens),r.thinkingConfig=u}else e.reasoning&&n.thinking&&!n.thinking.enabled&&(r.thinkingConfig=H(e));if(n.signal){if(n.signal.aborted)throw new Error("Request aborted");r.abortSignal=n.signal}return{model:e.id,contents:i,config:r}}function k(e){return/gemma-?4/.test(e.id.toLowerCase())}function m(e){return/gemini-3(?:\.\d+)?-pro/.test(e.id.toLowerCase())}function w(e){return/gemini-3(?:\.\d+)?-flash/.test(e.id.toLowerCase())}function H(e){return m(e)?{thinkingLevel:"LOW"}:w(e)?{thinkingLevel:"MINIMAL"}:k(e)?{thinkingLevel:"MINIMAL"}:{thinkingBudget:0}}function K(e,o){if(m(o))switch(e){case"minimal":case"low":return"LOW";case"medium":case"high":return"HIGH"}if(k(o))switch(e){case"minimal":case"low":return"MINIMAL";case"medium":case"high":return"HIGH"}switch(e){case"minimal":return"MINIMAL";case"low":return"LOW";case"medium":return"MEDIUM";case"high":return"HIGH"}}function U(e,o,n){return n?.[o]!==void 0?n[o]:e.id.includes("2.5-pro")?{minimal:128,low:2048,medium:8192,high:32768}[o]:e.id.includes("2.5-flash-lite")?{minimal:512,low:2048,medium:8192,high:24576}[o]:e.id.includes("2.5-flash")?{minimal:128,low:2048,medium:8192,high:24576}[o]:-1}export{f as streamGoogle,F as streamSimpleGoogle};
 
1
+ import{i as T,r as b,m as v,G as S,c as R,a as L,b as _}from"./google-shared-tMPbwRUC.js";import{A as G,g as x,c as O,a as A}from"./index-CB_zB4U3.js";import{s as N}from"./sanitize-unicode-B62XMGgN.js";import{b as E}from"./transform-messages-DSNYjDRn.js";let P=0;const f=(e,o,n)=>{const i=new G;return(async()=>{const t={role:"assistant",content:[],api:"google-generative-ai",provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const r=n?.apiKey||x(e.provider)||"",c=W(e,r,n?.headers);let u=B(e,o,n);const y=await n?.onPayload?.(u,e);y!==void 0&&(u=y);const M=await c.models.generateContentStream(u);i.push({type:"start",partial:t});let a=null;const C=t.content,l=()=>C.length-1;for await(const g of M){t.responseId||=g.responseId;const d=g.candidates?.[0];if(d?.content?.parts)for(const s of d.content.parts){if(s.text!==void 0){const h=T(s);(!a||h&&a.type!=="thinking"||!h&&a.type!=="text")&&(a&&(a.type==="text"?i.push({type:"text_end",contentIndex:C.length-1,content:a.text,partial:t}):i.push({type:"thinking_end",contentIndex:l(),content:a.thinking,partial:t})),h?(a={type:"thinking",thinking:"",thinkingSignature:void 0},t.content.push(a),i.push({type:"thinking_start",contentIndex:l(),partial:t})):(a={type:"text",text:""},t.content.push(a),i.push({type:"text_start",contentIndex:l(),partial:t}))),a.type==="thinking"?(a.thinking+=s.text,a.thinkingSignature=b(a.thinkingSignature,s.thoughtSignature),i.push({type:"thinking_delta",contentIndex:l(),delta:s.text,partial:t})):(a.text+=s.text,a.textSignature=b(a.textSignature,s.thoughtSignature),i.push({type:"text_delta",contentIndex:l(),delta:s.text,partial:t}))}if(s.functionCall){a&&(a.type==="text"?i.push({type:"text_end",contentIndex:l(),content:a.text,partial:t}):i.push({type:"thinking_end",contentIndex:l(),content:a.thinking,partial:t}),a=null);const h=s.functionCall.id,p={type:"toolCall",id:!h||t.content.some(I=>I.type==="toolCall"&&I.id===h)?`${s.functionCall.name}_${Date.now()}_${++P}`:h,name:s.functionCall.name||"",arguments:s.functionCall.args??{},...s.thoughtSignature&&{thoughtSignature:s.thoughtSignature}};t.content.push(p),i.push({type:"toolcall_start",contentIndex:l(),partial:t}),i.push({type:"toolcall_delta",contentIndex:l(),delta:JSON.stringify(p.arguments),partial:t}),i.push({type:"toolcall_end",contentIndex:l(),toolCall:p,partial:t})}}d?.finishReason&&(t.stopReason=v(d.finishReason),t.content.some(s=>s.type==="toolCall")&&(t.stopReason="toolUse")),g.usageMetadata&&(t.usage={input:(g.usageMetadata.promptTokenCount||0)-(g.usageMetadata.cachedContentTokenCount||0),output:(g.usageMetadata.candidatesTokenCount||0)+(g.usageMetadata.thoughtsTokenCount||0),cacheRead:g.usageMetadata.cachedContentTokenCount||0,cacheWrite:0,totalTokens:g.usageMetadata.totalTokenCount||0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},O(e,t.usage))}if(a&&(a.type==="text"?i.push({type:"text_end",contentIndex:l(),content:a.text,partial:t}):i.push({type:"thinking_end",contentIndex:l(),content:a.thinking,partial:t})),n?.signal?.aborted)throw new Error("Request was aborted");if(t.stopReason==="aborted"||t.stopReason==="error")throw new Error("An unknown error occurred");i.push({type:"done",reason:t.stopReason,message:t}),i.end()}catch(r){for(const c of t.content)"index"in c&&delete c.index;t.stopReason=n?.signal?.aborted?"aborted":"error",t.errorMessage=r instanceof Error?r.message:JSON.stringify(r),i.push({type:"error",reason:t.stopReason,error:t}),i.end()}})(),i},F=(e,o,n)=>{const i=n?.apiKey||x(e.provider);if(!i)throw new Error(`No API key for provider: ${e.provider}`);const t=E(e,n,i);if(!n?.reasoning)return f(e,o,{...t,thinking:{enabled:!1}});const r=A(e,n.reasoning),c=r==="off"?"high":r,u=e;return m(u)||w(u)||k(u)?f(e,o,{...t,thinking:{enabled:!0,level:K(c,u)}}):f(e,o,{...t,thinking:{enabled:!0,budgetTokens:U(u,c,n.thinkingBudgets)}})};function W(e,o,n){const i={};return e.baseUrl&&(i.baseUrl=e.baseUrl,i.apiVersion=""),(e.headers||n)&&(i.headers={...e.headers,...n}),new S({apiKey:o,httpOptions:Object.keys(i).length>0?i:void 0})}function B(e,o,n={}){const i=R(e,o),t={};n.temperature!==void 0&&(t.temperature=n.temperature),n.maxTokens!==void 0&&(t.maxOutputTokens=n.maxTokens);const r={...Object.keys(t).length>0&&t,...o.systemPrompt&&{systemInstruction:N(o.systemPrompt)},...o.tools&&o.tools.length>0&&{tools:L(o.tools)}};if(o.tools&&o.tools.length>0&&n.toolChoice?r.toolConfig={functionCallingConfig:{mode:_(n.toolChoice)}}:r.toolConfig=void 0,n.thinking?.enabled&&e.reasoning){const u={includeThoughts:!0};n.thinking.level!==void 0?u.thinkingLevel=n.thinking.level:n.thinking.budgetTokens!==void 0&&(u.thinkingBudget=n.thinking.budgetTokens),r.thinkingConfig=u}else e.reasoning&&n.thinking&&!n.thinking.enabled&&(r.thinkingConfig=H(e));if(n.signal){if(n.signal.aborted)throw new Error("Request aborted");r.abortSignal=n.signal}return{model:e.id,contents:i,config:r}}function k(e){return/gemma-?4/.test(e.id.toLowerCase())}function m(e){return/gemini-3(?:\.\d+)?-pro/.test(e.id.toLowerCase())}function w(e){return/gemini-3(?:\.\d+)?-flash/.test(e.id.toLowerCase())}function H(e){return m(e)?{thinkingLevel:"LOW"}:w(e)?{thinkingLevel:"MINIMAL"}:k(e)?{thinkingLevel:"MINIMAL"}:{thinkingBudget:0}}function K(e,o){if(m(o))switch(e){case"minimal":case"low":return"LOW";case"medium":case"high":return"HIGH"}if(k(o))switch(e){case"minimal":case"low":return"MINIMAL";case"medium":case"high":return"HIGH"}switch(e){case"minimal":return"MINIMAL";case"low":return"LOW";case"medium":return"MEDIUM";case"high":return"HIGH"}}function U(e,o,n){return n?.[o]!==void 0?n[o]:e.id.includes("2.5-pro")?{minimal:128,low:2048,medium:8192,high:32768}[o]:e.id.includes("2.5-flash-lite")?{minimal:512,low:2048,medium:8192,high:24576}[o]:e.id.includes("2.5-flash")?{minimal:128,low:2048,medium:8192,high:24576}[o]:-1}export{f as streamGoogle,F as streamSimpleGoogle};
dist/assets/{google-shared-CZIKa0Kf.js → google-shared-tMPbwRUC.js} RENAMED
The diff for this file is too large to render. See raw diff
 
dist/assets/{google-vertex-YpwsH_3V.js → google-vertex-CxMnHyvQ.js} RENAMED
@@ -1 +1 @@
1
- import{i as T,r as x,m as w,G as L,c as R,a as M,b as G,T as d,R as S}from"./google-shared-CZIKa0Kf.js";import{A,c as N,a as P}from"./index-CgfZNSZZ.js";import{s as U}from"./sanitize-unicode-B62XMGgN.js";import{b as D}from"./transform-messages-Bxe2XUr4.js";var f={};const v="v1",V="gcp-vertex-credentials",H={THINKING_LEVEL_UNSPECIFIED:d.THINKING_LEVEL_UNSPECIFIED,MINIMAL:d.MINIMAL,LOW:d.LOW,MEDIUM:d.MEDIUM,HIGH:d.HIGH};let K=0;const k=(t,e,n)=>{const a=new A;return(async()=>{const i={role:"assistant",content:[],api:"google-vertex",provider:t.provider,model:t.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const s=$(n),l=s?j(t,s,n?.headers):W(t,F(n),z(n),n?.headers);let g=X(t,e,n);const I=await n?.onPayload?.(g,t);I!==void 0&&(g=I);const E=await l.models.generateContentStream(g);a.push({type:"start",partial:i});let o=null;const y=i.content,c=()=>y.length-1;for await(const u of E){i.responseId||=u.responseId;const p=u.candidates?.[0];if(p?.content?.parts)for(const r of p.content.parts){if(r.text!==void 0){const h=T(r);(!o||h&&o.type!=="thinking"||!h&&o.type!=="text")&&(o&&(o.type==="text"?a.push({type:"text_end",contentIndex:y.length-1,content:o.text,partial:i}):a.push({type:"thinking_end",contentIndex:c(),content:o.thinking,partial:i})),h?(o={type:"thinking",thinking:"",thinkingSignature:void 0},i.content.push(o),a.push({type:"thinking_start",contentIndex:c(),partial:i})):(o={type:"text",text:""},i.content.push(o),a.push({type:"text_start",contentIndex:c(),partial:i}))),o.type==="thinking"?(o.thinking+=r.text,o.thinkingSignature=x(o.thinkingSignature,r.thoughtSignature),a.push({type:"thinking_delta",contentIndex:c(),delta:r.text,partial:i})):(o.text+=r.text,o.textSignature=x(o.textSignature,r.thoughtSignature),a.push({type:"text_delta",contentIndex:c(),delta:r.text,partial:i}))}if(r.functionCall){o&&(o.type==="text"?a.push({type:"text_end",contentIndex:c(),content:o.text,partial:i}):a.push({type:"thinking_end",contentIndex:c(),content:o.thinking,partial:i}),o=null);const h=r.functionCall.id,m={type:"toolCall",id:!h||i.content.some(O=>O.type==="toolCall"&&O.id===h)?`${r.functionCall.name}_${Date.now()}_${++K}`:h,name:r.functionCall.name||"",arguments:r.functionCall.args??{},...r.thoughtSignature&&{thoughtSignature:r.thoughtSignature}};i.content.push(m),a.push({type:"toolcall_start",contentIndex:c(),partial:i}),a.push({type:"toolcall_delta",contentIndex:c(),delta:JSON.stringify(m.arguments),partial:i}),a.push({type:"toolcall_end",contentIndex:c(),toolCall:m,partial:i})}}p?.finishReason&&(i.stopReason=w(p.finishReason),i.content.some(r=>r.type==="toolCall")&&(i.stopReason="toolUse")),u.usageMetadata&&(i.usage={input:(u.usageMetadata.promptTokenCount||0)-(u.usageMetadata.cachedContentTokenCount||0),output:(u.usageMetadata.candidatesTokenCount||0)+(u.usageMetadata.thoughtsTokenCount||0),cacheRead:u.usageMetadata.cachedContentTokenCount||0,cacheWrite:0,totalTokens:u.usageMetadata.totalTokenCount||0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},N(t,i.usage))}if(o&&(o.type==="text"?a.push({type:"text_end",contentIndex:c(),content:o.text,partial:i}):a.push({type:"thinking_end",contentIndex:c(),content:o.thinking,partial:i})),n?.signal?.aborted)throw new Error("Request was aborted");if(i.stopReason==="aborted"||i.stopReason==="error")throw new Error("An unknown error occurred");a.push({type:"done",reason:i.stopReason,message:i}),a.end()}catch(s){for(const l of i.content)"index"in l&&delete l.index;i.stopReason=n?.signal?.aborted?"aborted":"error",i.errorMessage=s instanceof Error?s.message:JSON.stringify(s),a.push({type:"error",reason:i.stopReason,error:i}),a.end()}})(),a},rt=(t,e,n)=>{const a=D(t,n,void 0);if(!n?.reasoning)return k(t,e,{...a,thinking:{enabled:!1}});const i=P(t,n.reasoning),s=i==="off"?"high":i,l=t;return C(l)||b(l)?k(t,e,{...a,thinking:{enabled:!0,level:Q(s,l)}}):k(t,e,{...a,thinking:{enabled:!0,budgetTokens:Z(l,s,n.thinkingBudgets)}})};function W(t,e,n,a){return new L({vertexai:!0,project:e,location:n,apiVersion:v,httpOptions:_(t,a)})}function j(t,e,n){return new L({vertexai:!0,apiKey:e,apiVersion:v,httpOptions:_(t,n)})}function _(t,e){const n={},a=B(t.baseUrl);return a&&(n.baseUrl=a,n.baseUrlResourceScope=S.COLLECTION,J(a)&&(n.apiVersion="")),(t.headers||e)&&(n.headers={...t.headers,...e}),Object.keys(n).length>0?n:void 0}function B(t){const e=t.trim();if(!(!e||e.includes("{location}")))return e}function J(t){try{return new URL(t).pathname.split("/").some(n=>/^v\d+(?:beta\d*)?$/.test(n))}catch{return/(?:^|\/)v\d+(?:beta\d*)?(?:\/|$)/.test(t)}}function $(t){const e=t?.apiKey?.trim()||f.GOOGLE_CLOUD_API_KEY?.trim();if(!(!e||e===V||q(e)))return e}function q(t){return/^<[^>]+>$/.test(t)}function F(t){const e=t?.project||f.GOOGLE_CLOUD_PROJECT||f.GCLOUD_PROJECT;if(!e)throw new Error("Vertex AI requires a project ID. Set GOOGLE_CLOUD_PROJECT/GCLOUD_PROJECT or pass project in options.");return e}function z(t){const e=t?.location||f.GOOGLE_CLOUD_LOCATION;if(!e)throw new Error("Vertex AI requires a location. Set GOOGLE_CLOUD_LOCATION or pass location in options.");return e}function X(t,e,n={}){const a=R(t,e),i={};n.temperature!==void 0&&(i.temperature=n.temperature),n.maxTokens!==void 0&&(i.maxOutputTokens=n.maxTokens);const s={...Object.keys(i).length>0&&i,...e.systemPrompt&&{systemInstruction:U(e.systemPrompt)},...e.tools&&e.tools.length>0&&{tools:M(e.tools)}};if(e.tools&&e.tools.length>0&&n.toolChoice?s.toolConfig={functionCallingConfig:{mode:G(n.toolChoice)}}:s.toolConfig=void 0,n.thinking?.enabled&&t.reasoning){const g={includeThoughts:!0};n.thinking.level!==void 0?g.thinkingLevel=H[n.thinking.level]:n.thinking.budgetTokens!==void 0&&(g.thinkingBudget=n.thinking.budgetTokens),s.thinkingConfig=g}else t.reasoning&&n.thinking&&!n.thinking.enabled&&(s.thinkingConfig=Y(t));if(n.signal){if(n.signal.aborted)throw new Error("Request aborted");s.abortSignal=n.signal}return{model:t.id,contents:a,config:s}}function C(t){return/gemini-3(?:\.\d+)?-pro/.test(t.id.toLowerCase())}function b(t){return/gemini-3(?:\.\d+)?-flash/.test(t.id.toLowerCase())}function Y(t){const e=t;return C(e)?{thinkingLevel:d.LOW}:b(e)?{thinkingLevel:d.MINIMAL}:{thinkingBudget:0}}function Q(t,e){if(C(e))switch(t){case"minimal":case"low":return"LOW";case"medium":case"high":return"HIGH"}switch(t){case"minimal":return"MINIMAL";case"low":return"LOW";case"medium":return"MEDIUM";case"high":return"HIGH"}}function Z(t,e,n){return n?.[e]!==void 0?n[e]:t.id.includes("2.5-pro")?{minimal:128,low:2048,medium:8192,high:32768}[e]:t.id.includes("2.5-flash")?{minimal:128,low:2048,medium:8192,high:24576}[e]:-1}export{k as streamGoogleVertex,rt as streamSimpleGoogleVertex};
 
1
+ import{i as T,r as x,m as w,G as L,c as R,a as M,b as G,T as d,R as S}from"./google-shared-tMPbwRUC.js";import{A,c as N,a as P}from"./index-CB_zB4U3.js";import{s as U}from"./sanitize-unicode-B62XMGgN.js";import{b as D}from"./transform-messages-DSNYjDRn.js";var f={};const v="v1",V="gcp-vertex-credentials",H={THINKING_LEVEL_UNSPECIFIED:d.THINKING_LEVEL_UNSPECIFIED,MINIMAL:d.MINIMAL,LOW:d.LOW,MEDIUM:d.MEDIUM,HIGH:d.HIGH};let K=0;const k=(t,e,n)=>{const a=new A;return(async()=>{const i={role:"assistant",content:[],api:"google-vertex",provider:t.provider,model:t.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const s=$(n),l=s?j(t,s,n?.headers):W(t,F(n),z(n),n?.headers);let g=X(t,e,n);const I=await n?.onPayload?.(g,t);I!==void 0&&(g=I);const E=await l.models.generateContentStream(g);a.push({type:"start",partial:i});let o=null;const y=i.content,c=()=>y.length-1;for await(const u of E){i.responseId||=u.responseId;const p=u.candidates?.[0];if(p?.content?.parts)for(const r of p.content.parts){if(r.text!==void 0){const h=T(r);(!o||h&&o.type!=="thinking"||!h&&o.type!=="text")&&(o&&(o.type==="text"?a.push({type:"text_end",contentIndex:y.length-1,content:o.text,partial:i}):a.push({type:"thinking_end",contentIndex:c(),content:o.thinking,partial:i})),h?(o={type:"thinking",thinking:"",thinkingSignature:void 0},i.content.push(o),a.push({type:"thinking_start",contentIndex:c(),partial:i})):(o={type:"text",text:""},i.content.push(o),a.push({type:"text_start",contentIndex:c(),partial:i}))),o.type==="thinking"?(o.thinking+=r.text,o.thinkingSignature=x(o.thinkingSignature,r.thoughtSignature),a.push({type:"thinking_delta",contentIndex:c(),delta:r.text,partial:i})):(o.text+=r.text,o.textSignature=x(o.textSignature,r.thoughtSignature),a.push({type:"text_delta",contentIndex:c(),delta:r.text,partial:i}))}if(r.functionCall){o&&(o.type==="text"?a.push({type:"text_end",contentIndex:c(),content:o.text,partial:i}):a.push({type:"thinking_end",contentIndex:c(),content:o.thinking,partial:i}),o=null);const h=r.functionCall.id,m={type:"toolCall",id:!h||i.content.some(O=>O.type==="toolCall"&&O.id===h)?`${r.functionCall.name}_${Date.now()}_${++K}`:h,name:r.functionCall.name||"",arguments:r.functionCall.args??{},...r.thoughtSignature&&{thoughtSignature:r.thoughtSignature}};i.content.push(m),a.push({type:"toolcall_start",contentIndex:c(),partial:i}),a.push({type:"toolcall_delta",contentIndex:c(),delta:JSON.stringify(m.arguments),partial:i}),a.push({type:"toolcall_end",contentIndex:c(),toolCall:m,partial:i})}}p?.finishReason&&(i.stopReason=w(p.finishReason),i.content.some(r=>r.type==="toolCall")&&(i.stopReason="toolUse")),u.usageMetadata&&(i.usage={input:(u.usageMetadata.promptTokenCount||0)-(u.usageMetadata.cachedContentTokenCount||0),output:(u.usageMetadata.candidatesTokenCount||0)+(u.usageMetadata.thoughtsTokenCount||0),cacheRead:u.usageMetadata.cachedContentTokenCount||0,cacheWrite:0,totalTokens:u.usageMetadata.totalTokenCount||0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},N(t,i.usage))}if(o&&(o.type==="text"?a.push({type:"text_end",contentIndex:c(),content:o.text,partial:i}):a.push({type:"thinking_end",contentIndex:c(),content:o.thinking,partial:i})),n?.signal?.aborted)throw new Error("Request was aborted");if(i.stopReason==="aborted"||i.stopReason==="error")throw new Error("An unknown error occurred");a.push({type:"done",reason:i.stopReason,message:i}),a.end()}catch(s){for(const l of i.content)"index"in l&&delete l.index;i.stopReason=n?.signal?.aborted?"aborted":"error",i.errorMessage=s instanceof Error?s.message:JSON.stringify(s),a.push({type:"error",reason:i.stopReason,error:i}),a.end()}})(),a},rt=(t,e,n)=>{const a=D(t,n,void 0);if(!n?.reasoning)return k(t,e,{...a,thinking:{enabled:!1}});const i=P(t,n.reasoning),s=i==="off"?"high":i,l=t;return C(l)||b(l)?k(t,e,{...a,thinking:{enabled:!0,level:Q(s,l)}}):k(t,e,{...a,thinking:{enabled:!0,budgetTokens:Z(l,s,n.thinkingBudgets)}})};function W(t,e,n,a){return new L({vertexai:!0,project:e,location:n,apiVersion:v,httpOptions:_(t,a)})}function j(t,e,n){return new L({vertexai:!0,apiKey:e,apiVersion:v,httpOptions:_(t,n)})}function _(t,e){const n={},a=B(t.baseUrl);return a&&(n.baseUrl=a,n.baseUrlResourceScope=S.COLLECTION,J(a)&&(n.apiVersion="")),(t.headers||e)&&(n.headers={...t.headers,...e}),Object.keys(n).length>0?n:void 0}function B(t){const e=t.trim();if(!(!e||e.includes("{location}")))return e}function J(t){try{return new URL(t).pathname.split("/").some(n=>/^v\d+(?:beta\d*)?$/.test(n))}catch{return/(?:^|\/)v\d+(?:beta\d*)?(?:\/|$)/.test(t)}}function $(t){const e=t?.apiKey?.trim()||f.GOOGLE_CLOUD_API_KEY?.trim();if(!(!e||e===V||q(e)))return e}function q(t){return/^<[^>]+>$/.test(t)}function F(t){const e=t?.project||f.GOOGLE_CLOUD_PROJECT||f.GCLOUD_PROJECT;if(!e)throw new Error("Vertex AI requires a project ID. Set GOOGLE_CLOUD_PROJECT/GCLOUD_PROJECT or pass project in options.");return e}function z(t){const e=t?.location||f.GOOGLE_CLOUD_LOCATION;if(!e)throw new Error("Vertex AI requires a location. Set GOOGLE_CLOUD_LOCATION or pass location in options.");return e}function X(t,e,n={}){const a=R(t,e),i={};n.temperature!==void 0&&(i.temperature=n.temperature),n.maxTokens!==void 0&&(i.maxOutputTokens=n.maxTokens);const s={...Object.keys(i).length>0&&i,...e.systemPrompt&&{systemInstruction:U(e.systemPrompt)},...e.tools&&e.tools.length>0&&{tools:M(e.tools)}};if(e.tools&&e.tools.length>0&&n.toolChoice?s.toolConfig={functionCallingConfig:{mode:G(n.toolChoice)}}:s.toolConfig=void 0,n.thinking?.enabled&&t.reasoning){const g={includeThoughts:!0};n.thinking.level!==void 0?g.thinkingLevel=H[n.thinking.level]:n.thinking.budgetTokens!==void 0&&(g.thinkingBudget=n.thinking.budgetTokens),s.thinkingConfig=g}else t.reasoning&&n.thinking&&!n.thinking.enabled&&(s.thinkingConfig=Y(t));if(n.signal){if(n.signal.aborted)throw new Error("Request aborted");s.abortSignal=n.signal}return{model:t.id,contents:a,config:s}}function C(t){return/gemini-3(?:\.\d+)?-pro/.test(t.id.toLowerCase())}function b(t){return/gemini-3(?:\.\d+)?-flash/.test(t.id.toLowerCase())}function Y(t){const e=t;return C(e)?{thinkingLevel:d.LOW}:b(e)?{thinkingLevel:d.MINIMAL}:{thinkingBudget:0}}function Q(t,e){if(C(e))switch(t){case"minimal":case"low":return"LOW";case"medium":case"high":return"HIGH"}switch(t){case"minimal":return"MINIMAL";case"low":return"LOW";case"medium":return"MEDIUM";case"high":return"HIGH"}}function Z(t,e,n){return n?.[e]!==void 0?n[e]:t.id.includes("2.5-pro")?{minimal:128,low:2048,medium:8192,high:32768}[e]:t.id.includes("2.5-flash")?{minimal:128,low:2048,medium:8192,high:24576}[e]:-1}export{k as streamGoogleVertex,rt as streamSimpleGoogleVertex};
dist/assets/index-4NYd9uAS.css DELETED
@@ -1 +0,0 @@
1
- :root{color:#182233;background:#eef2f6;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}*{box-sizing:border-box}body{margin:0;min-width:320px}button,input,select,textarea{font:inherit}button{min-height:40px;padding:0 15px;border:0;border-radius:6px;background:#176b6c;color:#fff;font-weight:750;cursor:pointer}button:disabled{cursor:wait;opacity:.6}#app{min-height:100vh;padding:14px}.app-shell{display:grid;grid-template-rows:auto minmax(0,1fr);gap:12px;width:min(1360px,100%);min-height:calc(100vh - 28px);margin:0 auto}.topbar{display:flex;align-items:end;justify-content:space-between;gap:16px;padding:8px 0 14px;border-bottom:1px solid #c7d2df}h1,h2,p{margin:0}h1{font-size:34px;line-height:1;letter-spacing:0}h2{font-size:15px;line-height:1.2;color:#3f5064}#model-label{margin-top:7px;color:#5d6c7f;overflow-wrap:anywhere}.status-stack{display:flex;flex-wrap:wrap;justify-content:end;gap:8px;max-width:680px}.status{min-height:34px;max-width:260px;padding:7px 10px;border:1px solid #b7c4d3;border-radius:6px;background:#fff;color:#314155;overflow-wrap:anywhere}.layout{display:grid;grid-template-columns:minmax(0,1fr) 340px;gap:12px;min-height:0}.chat-panel,.side-panel{min-height:0}.chat-panel{display:grid;grid-template-rows:minmax(0,1fr) auto;gap:12px}.chat-scroll{min-height:420px;max-height:calc(100vh - 214px);overflow:auto;padding:18px;border:1px solid #c1ccda;border-radius:8px;background:#fbfcfe}.empty-chat{display:grid;align-content:center;gap:10px;min-height:320px;color:#4c5d72;text-align:center}.empty-chat h2{font-size:24px;color:#182233}.message{display:grid;gap:7px;width:min(760px,92%);margin-bottom:14px;padding:12px 14px;border:1px solid #c4ceda;border-radius:8px;background:#fff}.message.user{margin-left:auto;border-color:#99bfbd;background:#e9f7f4}.message.assistant{border-color:#c4ceda}.message.tool{width:min(820px,96%);margin-left:24px;background:#f5f7fa}.message.error{border-color:#d99a9a;background:#fff4f4}.message-label{color:#5e6e82;font-size:12px;font-weight:800;text-transform:uppercase}.message-body{white-space:pre-wrap;overflow-wrap:anywhere;line-height:1.48}.message-code,pre{margin:0;white-space:pre-wrap;overflow:auto;overflow-wrap:anywhere;line-height:1.45}.message-code{max-height:240px;padding:10px;border-radius:6px;background:#182233;color:#e9eef5}.tool-call{display:grid;gap:6px;padding:10px;border:1px solid #d1dae5;border-radius:6px;background:#f7f9fc}.tool-name{color:#315f63;font-weight:800}.tool-call code{white-space:pre-wrap;overflow-wrap:anywhere}.composer{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:10px;align-items:end;padding:10px;border:1px solid #c1ccda;border-radius:8px;background:#fff}textarea{width:100%;min-height:64px;max-height:180px;resize:vertical;padding:12px;border:1px solid #b8c5d4;border-radius:6px;background:#fff;color:#152033;line-height:1.45}.composer-actions{display:flex;gap:8px}#demo-prompt{background:#4f5f73}.side-panel{display:grid;align-content:start;gap:12px}.control-group{display:grid;gap:10px;padding:12px;border:1px solid #c1ccda;border-radius:8px;background:#fff}label{display:grid;gap:6px;color:#526173;font-size:13px;font-weight:700}select,input{width:100%;height:40px;padding:0 10px;border:1px solid #b8c5d4;border-radius:6px;background:#fff;color:#152033}.compact-grid,.button-row{display:grid;grid-template-columns:1fr 1fr;gap:8px}#reset-sandbox,#use-test-model{background:#4f5f73}#files,#event-log{min-height:150px;max-height:230px;padding:10px;border:1px solid #d1dae5;border-radius:6px;background:#f7f9fc;color:#243248}#event-log{max-height:270px}.model-gate{position:fixed;inset:0;display:grid;place-items:center;padding:18px;background:#141f2d75;z-index:20}.model-gate.hidden{display:none}.model-dialog{display:grid;gap:16px;width:min(540px,100%);padding:22px;border-radius:8px;background:#fff;box-shadow:0 24px 80px #111b2a38}.eyebrow{margin-bottom:7px;color:#176b6c;font-size:12px;font-weight:850;text-transform:uppercase}.model-dialog h2{font-size:24px;color:#172033}.dialog-copy{margin-top:8px;color:#526173;line-height:1.5}.dialog-actions{display:flex;flex-wrap:wrap;gap:10px}.dialog-options{display:grid;gap:10px;color:#526173}#gate-status{min-height:22px;overflow-wrap:anywhere}@media(max-width:900px){#app{padding:10px}.topbar{align-items:stretch;flex-direction:column}.status-stack{justify-content:start}.layout{grid-template-columns:1fr}.chat-scroll{min-height:360px;max-height:none}.composer{grid-template-columns:1fr}.composer-actions{justify-content:end}}
 
 
dist/assets/index-CB_zB4U3.js ADDED
The diff for this file is too large to render. See raw diff
 
dist/assets/index-CgfZNSZZ.js DELETED
The diff for this file is too large to render. See raw diff
 
dist/assets/index-NRwwiW4N.css ADDED
@@ -0,0 +1 @@
 
 
1
+ :root{color:#d6deeb;background:#0b0f16;font-family:Inter,ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,sans-serif}*{box-sizing:border-box}html,body,#app{min-width:320px;min-height:100vh;margin:0}button,select{font:inherit}button{min-height:40px;padding:0 15px;border:0;border-radius:6px;background:#227c70;color:#fff;font-weight:750;cursor:pointer}button:disabled{cursor:wait;opacity:.6}#app{display:grid;grid-template-rows:auto minmax(0,1fr);gap:10px;padding:10px}.runtime-bar{display:flex;align-items:end;justify-content:space-between;gap:16px;min-height:54px;padding:4px 2px 10px;border-bottom:1px solid #263244}h1,h2,p{margin:0}h1{color:#f8fafc;font-size:30px;line-height:1;letter-spacing:0}#model-label{margin-top:5px;color:#9eb1ca;font-size:13px;overflow-wrap:anywhere}.status-stack{display:flex;flex-wrap:wrap;justify-content:end;gap:8px;max-width:760px}.status{min-height:32px;max-width:280px;padding:6px 10px;border:1px solid #344156;border-radius:6px;background:#141b27;color:#cad7ea;font-size:13px;overflow-wrap:anywhere}.terminal-shell{min-height:0;border:1px solid #263244;border-radius:8px;background:#10141c;overflow:hidden}#terminal{width:100%;height:calc(100vh - 86px);min-height:420px;padding:10px}.xterm{height:100%}.xterm-viewport,.xterm-screen{border-radius:0}.model-gate{position:fixed;inset:0;display:grid;place-items:center;padding:18px;background:#04080ea3;z-index:20}.model-gate.hidden{display:none}.model-dialog{display:grid;gap:16px;width:min(560px,100%);padding:22px;border:1px solid #334155;border-radius:8px;background:#f8fafc;color:#172033;box-shadow:0 24px 80px #00000059}.eyebrow{margin-bottom:7px;color:#227c70;font-size:12px;font-weight:850;text-transform:uppercase}.model-dialog h2{color:#172033;font-size:24px;line-height:1.15}.dialog-copy{margin-top:8px;color:#526173;line-height:1.5}.dialog-actions{display:flex;flex-wrap:wrap;gap:10px}#use-test-model{background:#4f5f73}.dialog-options{display:grid;gap:10px;color:#526173}label{display:grid;gap:6px;font-size:13px;font-weight:700}select{width:100%;height:40px;padding:0 10px;border:1px solid #b8c5d4;border-radius:6px;background:#fff;color:#152033}#gate-status{min-height:22px;color:#526173;overflow-wrap:anywhere}@media(max-width:760px){#app{padding:8px}.runtime-bar{align-items:stretch;flex-direction:column}.status-stack{justify-content:start}#terminal{height:calc(100vh - 164px);min-height:360px;padding:8px}}.xterm{cursor:text;position:relative;user-select:none;-ms-user-select:none;-webkit-user-select:none}.xterm.focus,.xterm:focus{outline:none}.xterm .xterm-helpers{position:absolute;top:0;z-index:5}.xterm .xterm-helper-textarea{padding:0;border:0;margin:0;position:absolute;opacity:0;left:-9999em;top:0;width:0;height:0;z-index:-5;white-space:nowrap;overflow:hidden;resize:none}.xterm .composition-view{background:#000;color:#fff;display:none;position:absolute;white-space:nowrap;z-index:1}.xterm .composition-view.active{display:block}.xterm .xterm-viewport{background-color:#000;overflow-y:scroll;cursor:default;position:absolute;inset:0}.xterm .xterm-screen{position:relative}.xterm .xterm-screen canvas{position:absolute;left:0;top:0}.xterm-char-measure-element{display:inline-block;visibility:hidden;position:absolute;top:0;left:-9999em;line-height:normal}.xterm.enable-mouse-events{cursor:default}.xterm.xterm-cursor-pointer,.xterm .xterm-cursor-pointer{cursor:pointer}.xterm.column-select.focus{cursor:crosshair}.xterm .xterm-accessibility:not(.debug),.xterm .xterm-message{position:absolute;inset:0;z-index:10;color:transparent;pointer-events:none}.xterm .xterm-accessibility-tree:not(.debug) *::selection{color:transparent}.xterm .xterm-accessibility-tree{font-family:monospace;-webkit-user-select:text;user-select:text;white-space:pre}.xterm .xterm-accessibility-tree>div{transform-origin:left;width:fit-content}.xterm .live-region{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}.xterm-dim{opacity:1!important}.xterm-underline-1{text-decoration:underline}.xterm-underline-2{text-decoration:double underline}.xterm-underline-3{text-decoration:wavy underline}.xterm-underline-4{text-decoration:dotted underline}.xterm-underline-5{text-decoration:dashed underline}.xterm-overline{text-decoration:overline}.xterm-overline.xterm-underline-1{text-decoration:overline underline}.xterm-overline.xterm-underline-2{text-decoration:overline double underline}.xterm-overline.xterm-underline-3{text-decoration:overline wavy underline}.xterm-overline.xterm-underline-4{text-decoration:overline dotted underline}.xterm-overline.xterm-underline-5{text-decoration:overline dashed underline}.xterm-strikethrough{text-decoration:line-through}.xterm-screen .xterm-decoration-container .xterm-decoration{z-index:6;position:absolute}.xterm-screen .xterm-decoration-container .xterm-decoration.xterm-decoration-top-layer{z-index:7}.xterm-decoration-overview-ruler{z-index:8;position:absolute;top:0;right:0;pointer-events:none}.xterm-decoration-top{z-index:2;position:relative}.xterm .xterm-scrollable-element>.scrollbar{cursor:default}.xterm .xterm-scrollable-element>.scrollbar>.scra{cursor:pointer;font-size:11px!important}.xterm .xterm-scrollable-element>.visible{opacity:1;background:#0000;transition:opacity .1s linear;z-index:11}.xterm .xterm-scrollable-element>.invisible{opacity:0;pointer-events:none}.xterm .xterm-scrollable-element>.invisible.fade{transition:opacity .8s linear}.xterm .xterm-scrollable-element>.shadow{position:absolute;display:none}.xterm .xterm-scrollable-element>.shadow.top{display:block;top:0;left:3px;height:3px;width:100%;box-shadow:var(--vscode-scrollbar-shadow, #000) 0 6px 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.left{display:block;top:3px;left:0;height:100%;width:3px;box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}.xterm .xterm-scrollable-element>.shadow.top-left-corner{display:block;top:0;left:0;height:3px;width:3px}.xterm .xterm-scrollable-element>.shadow.top.left{box-shadow:var(--vscode-scrollbar-shadow, #000) 6px 0 6px -6px inset}
dist/assets/{json-parse-B9Wfu_bW.js → json-parse-cUk3uCki.js} RENAMED
@@ -1,2 +1,2 @@
1
- import{d as o}from"./index-CgfZNSZZ.js";const a=new Set(['"',"\\","/","b","f","n","r","t","u"]);function f(t){const r=t.codePointAt(0);return r!==void 0&&r>=0&&r<=31}function d(t){switch(t){case"\b":return"\\b";case"\f":return"\\f";case`
2
  `:return"\\n";case"\r":return"\\r";case" ":return"\\t";default:return`\\u${t.codePointAt(0)?.toString(16).padStart(4,"0")??"0000"}`}}function s(t){let r="",c=!1;for(let e=0;e<t.length;e++){const n=t[e];if(!c){r+=n,n==='"'&&(c=!0);continue}if(n==='"'){r+=n,c=!1;continue}if(n==="\\"){const i=t[e+1];if(i===void 0){r+="\\\\";continue}if(i==="u"){const u=t.slice(e+2,e+6);if(/^[0-9a-fA-F]{4}$/.test(u)){r+=`\\u${u}`,e+=5;continue}}if(a.has(i)){r+=`\\${i}`,e+=1;continue}r+="\\\\";continue}r+=f(n)?d(n):n}return r}function h(t){try{return JSON.parse(t)}catch(r){const c=s(t);if(c!==t)return JSON.parse(c);throw r}}function l(t){if(!t||t.trim()==="")return{};try{return h(t)}catch{try{return o.parse(t)??{}}catch{try{return o.parse(s(t))??{}}catch{return{}}}}}export{l as a,h as p};
 
1
+ import{d as o}from"./index-CB_zB4U3.js";const a=new Set(['"',"\\","/","b","f","n","r","t","u"]);function f(t){const r=t.codePointAt(0);return r!==void 0&&r>=0&&r<=31}function d(t){switch(t){case"\b":return"\\b";case"\f":return"\\f";case`
2
  `:return"\\n";case"\r":return"\\r";case" ":return"\\t";default:return`\\u${t.codePointAt(0)?.toString(16).padStart(4,"0")??"0000"}`}}function s(t){let r="",c=!1;for(let e=0;e<t.length;e++){const n=t[e];if(!c){r+=n,n==='"'&&(c=!0);continue}if(n==='"'){r+=n,c=!1;continue}if(n==="\\"){const i=t[e+1];if(i===void 0){r+="\\\\";continue}if(i==="u"){const u=t.slice(e+2,e+6);if(/^[0-9a-fA-F]{4}$/.test(u)){r+=`\\u${u}`,e+=5;continue}}if(a.has(i)){r+=`\\${i}`,e+=1;continue}r+="\\\\";continue}r+=f(n)?d(n):n}return r}function h(t){try{return JSON.parse(t)}catch(r){const c=s(t);if(c!==t)return JSON.parse(c);throw r}}function l(t){if(!t||t.trim()==="")return{};try{return h(t)}catch{try{return o.parse(t)??{}}catch{try{return o.parse(s(t))??{}}catch{return{}}}}}export{l as a,h as p};
dist/assets/{mistral-D2dGPAye.js → mistral-mDLdw-bF.js} RENAMED
@@ -1,4 +1,4 @@
1
- import{A as Vu,g as Cn,a as Gu,c as Ju}from"./index-CgfZNSZZ.js";import{s as Bu}from"./hash-DMDecQcg.js";import{a as Ir}from"./json-parse-B9Wfu_bW.js";import{s as We}from"./sanitize-unicode-B62XMGgN.js";import{t as Yu,b as Qu}from"./transform-messages-Bxe2XUr4.js";const ec=Object.prototype.hasOwnProperty;function E(e,o){const t=/\{([a-zA-Z0-9_][a-zA-Z0-9_-]*?)\}/g;return function(r={}){return e.replace(t,function(c,l){if(!ec.call(r,l))throw new Error(`Parameter '${l}' is required`);const m=r[l];if(typeof m!="string"&&typeof m!="number")throw new Error(`Parameter '${l}' must be a string or number`);return`${m}`}).replace(/^\/+/,"")}}const Rn="eu",tc={[Rn]:"https://api.mistral.ai"};function oc(e){let o=e.serverURL;const t={};if(!o){const r=e.server??Rn;o=tc[r]||""}const s=E(o)(t);return new URL(s)}const Sn={sdkVersion:"2.2.1",userAgent:"speakeasy-sdk/typescript 2.2.1 2.881.4 1.0.0 @mistralai/mistralai"};async function qo(e){const o=e.getReader(),t=[];let s=0,r=!1;for(;!r;){const{value:m,done:g}=await o.read();g?r=!0:(t.push(m),s+=m.length)}const c=new Uint8Array(s);let l=0;for(const m of t)c.set(m,l),l+=m.length;return c.buffer}function et(e){if(!e)return null;const o=e.toLowerCase().split(".").pop();return o&&{json:"application/json",xml:"application/xml",html:"text/html",htm:"text/html",txt:"text/plain",csv:"text/csv",pdf:"application/pdf",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",js:"application/javascript",css:"text/css",zip:"application/zip",tar:"application/x-tar",gz:"application/gzip",mp4:"video/mp4",mp3:"audio/mpeg",wav:"audio/wav",webp:"image/webp",ico:"image/x-icon",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf"}[o]||null}function tt(e,o){return e instanceof Uint8Array?new Blob([new Uint8Array(e)],{type:o}):new Blob([e],{type:o})}const sc=(e,o)=>o==null?fetch(e):fetch(e,o);class Os{options;fetcher;requestHooks=[];requestErrorHooks=[];responseHooks=[];constructor(o={}){this.options=o,this.fetcher=o.fetcher||sc}async request(o){let t=o;for(const s of this.requestHooks){const r=await s(t);r&&(t=r)}try{const s=await this.fetcher(t);for(const r of this.responseHooks)await r(s,t);return s}catch(s){for(const r of this.requestErrorHooks)await r(s,t);throw s}}addHook(...o){if(o[0]==="beforeRequest")this.requestHooks.push(o[1]);else if(o[0]==="requestError")this.requestErrorHooks.push(o[1]);else if(o[0]==="response")this.responseHooks.push(o[1]);else throw new Error(`Invalid hook type: ${o[0]}`);return this}removeHook(...o){let t;if(o[0]==="beforeRequest")t=this.requestHooks;else if(o[0]==="requestError")t=this.requestErrorHooks;else if(o[0]==="response")t=this.responseHooks;else throw new Error(`Invalid hook type: ${o[0]}`);const s=t.findIndex(r=>r===o[1]);return s>=0&&t.splice(s,1),this}clone(){const o=new Os(this.options);return o.requestHooks=this.requestHooks.slice(),o.requestErrorHooks=this.requestErrorHooks.slice(),o.responseHooks=this.responseHooks.slice(),o}}const xr=/\s*;\s*/g;function yt(e,o){if(o==="*")return!0;let t=e.headers.get("content-type")?.trim()||"application/octet-stream";t=t.toLowerCase();const s=o.toLowerCase().trim().split(xr),[r="",...c]=s;if(r.split("/").length!==2)return!1;const l=t.split(xr),[m="",...g]=l,[y="",b=""]=m.split("/");if(!y||!b||r!=="*/*"&&m!==r&&`${y}/*`!==r&&`*/${b}`!==r||g.length<c.length)return!1;const _=new Set(g);for(const i of c)if(!_.has(i))return!1;return!0}const rc=new RegExp("^[0-9]xx$","i");function A(e,o){const t=`${e.status}`,s=Array.isArray(o)?o:[o];return s.length?s.some(r=>{const c=`${r}`;if(c==="default")return!0;if(!rc.test(`${c}`))return c===t;const l=c.charAt(0);if(!l)throw new Error("Invalid status code range");const m=t.charAt(0);if(!m)throw new Error(`Invalid response status code: ${t}`);return m===l}):!1}function nc(e,o,t){return A(e,o)&&yt(e,t)}function kn(e){if(typeof e!="object"||e==null)return!1;const o=e instanceof TypeError&&e.message.toLowerCase().startsWith("failed to fetch"),t=e instanceof TypeError&&e.message.toLowerCase().startsWith("fetch failed"),s="name"in e&&e.name==="ConnectionError",r="code"in e&&typeof e.code=="string"&&e.code.toLowerCase()==="econnreset";return o||t||r||s}function qn(e){if(typeof e!="object"||e==null)return!1;const o="name"in e&&e.name==="TimeoutError",t="code"in e&&e.code===23,s="code"in e&&typeof e.code=="string"&&e.code.toLowerCase()==="econnaborted";return o||t||s}function ac(e){if(typeof e!="object"||e==null)return!1;const o="name"in e&&e.name==="AbortError",t="code"in e&&e.code===20,s="code"in e&&typeof e.code=="string"&&e.code.toLowerCase()==="econnaborted";return o||t||s}class ic{beforeRequest(o,t){const r=`mistral-client-typescript/${Sn.sdkVersion}`;return t.headers.set("user-agent",r),t.headers.get("user-agent")||t.headers.set("x-mistral-user-agent",r),t}}const Ar="x-model-deprecation-timestamp";class uc{afterSuccess(o,t){return t.headers.has(Ar)&&t.clone().json().then(s=>{const r=s.model;console.warn(`WARNING: The model ${r} is deprecated and will be removed on ${t.headers.get(Ar)}. Please refer to https://docs.mistral.ai/getting-started/models/#api-versioning for more information.`)}),t}}function cc(e){const o=new ic;e.registerBeforeRequestHook(o);const t=new uc;e.registerAfterSuccessHook(t)}class Er{sdkInitHooks=[];beforeCreateRequestHooks=[];beforeRequestHooks=[];afterSuccessHooks=[];afterErrorHooks=[];constructor(){const o=[];for(const t of o)"sdkInit"in t&&this.registerSDKInitHook(t),"beforeCreateRequest"in t&&this.registerBeforeCreateRequestHook(t),"beforeRequest"in t&&this.registerBeforeRequestHook(t),"afterSuccess"in t&&this.registerAfterSuccessHook(t),"afterError"in t&&this.registerAfterErrorHook(t);cc(this)}registerSDKInitHook(o){this.sdkInitHooks.push(o)}registerBeforeCreateRequestHook(o){this.beforeCreateRequestHooks.push(o)}registerBeforeRequestHook(o){this.beforeRequestHooks.push(o)}registerAfterSuccessHook(o){this.afterSuccessHooks.push(o)}registerAfterErrorHook(o){this.afterErrorHooks.push(o)}sdkInit(o){return this.sdkInitHooks.reduce((t,s)=>s.sdkInit(t),o)}beforeCreateRequest(o,t){let s=t;for(const r of this.beforeCreateRequestHooks)s=r.beforeCreateRequest(o,s);return s}async beforeRequest(o,t){let s=t;for(const r of this.beforeRequestHooks)s=await r.beforeRequest(o,s);return s}async afterSuccess(o,t){let s=t;for(const r of this.afterSuccessHooks)s=await r.afterSuccess(o,s);return s}async afterError(o,t,s){let r=t,c=s;for(const l of this.afterErrorHooks){const m=await l.afterError(o,r,c);r=m.response,c=m.error}return{response:r,error:c}}}class zt extends Error{cause;name="HTTPClientError";constructor(o,t){let s=o;t?.cause&&(s+=`: ${t.cause}`),super(s,t),typeof this.cause>"u"&&(this.cause=t?.cause)}}class $r extends zt{name="UnexpectedClientError"}class dc extends zt{name="InvalidRequestError"}class lc extends zt{name="RequestAbortedError"}class pc extends zt{name="RequestTimeoutError"}class fc extends zt{name="ConnectionError"}function fo(e){return{ok:!0,value:e}}function Ye(e){return{ok:!1,error:e}}async function x(e){const o=await e;if(!o.ok)throw o.error;return o.value}var Tr;const lt=Object.freeze({status:"aborted"});function H(e,o,t){function s(m,g){if(m._zod||Object.defineProperty(m,"_zod",{value:{def:g,constr:l,traits:new Set},enumerable:!1}),m._zod.traits.has(e))return;m._zod.traits.add(e),o(m,g);const y=l.prototype,b=Object.keys(y);for(let _=0;_<b.length;_++){const i=b[_];i in m||(m[i]=y[i].bind(m))}}const r=t?.Parent??Object;class c extends r{}Object.defineProperty(c,"name",{value:e});function l(m){var g;const y=t?.Parent?new c:this;s(y,m),(g=y._zod).deferred??(g.deferred=[]);for(const b of y._zod.deferred)b();return y}return Object.defineProperty(l,"init",{value:s}),Object.defineProperty(l,Symbol.hasInstance,{value:m=>t?.Parent&&m instanceof t.Parent?!0:m?._zod?.traits?.has(e)}),Object.defineProperty(l,"name",{value:e}),l}class vt extends Error{constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}}class In extends Error{constructor(o){super(`Encountered unidirectional transform during encode: ${o}`),this.name="ZodEncodeError"}}(Tr=globalThis).__zod_globalConfig??(Tr.__zod_globalConfig={});const Fs=globalThis.__zod_globalConfig;function Ve(e){return Fs}function xn(e){const o=Object.values(e).filter(s=>typeof s=="number");return Object.entries(e).filter(([s,r])=>o.indexOf(+s)===-1).map(([s,r])=>r)}function Xs(e,o){return typeof o=="bigint"?o.toString():o}function js(e){return{get value(){{const o=e();return Object.defineProperty(this,"value",{value:o}),o}}}}function Ps(e){return e==null}function Ns(e){const o=e.startsWith("^")?1:0,t=e.endsWith("$")?e.length-1:e.length;return e.slice(o,t)}function _c(e,o){const t=e/o,s=Math.round(t),r=Number.EPSILON*Math.max(Math.abs(t),1);return Math.abs(t-s)<r?0:t-s}const Xr=Symbol("evaluating");function ne(e,o,t){let s;Object.defineProperty(e,o,{get(){if(s!==Xr)return s===void 0&&(s=Xr,s=t()),s},set(r){Object.defineProperty(e,o,{value:r})},configurable:!0})}function pt(e,o,t){Object.defineProperty(e,o,{value:t,writable:!0,enumerable:!0,configurable:!0})}function ot(...e){const o={};for(const t of e){const s=Object.getOwnPropertyDescriptors(t);Object.assign(o,s)}return Object.defineProperties({},o)}function Lr(e){return JSON.stringify(e)}function mc(e){return e.toLowerCase().trim().replace(/[^\w\s-]/g,"").replace(/[\s_-]+/g,"-").replace(/^-+|-+$/g,"")}const An="captureStackTrace"in Error?Error.captureStackTrace:(...e)=>{};function _o(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}const yc=js(()=>{if(Fs.jitless||typeof navigator<"u"&&navigator?.userAgent?.includes("Cloudflare"))return!1;try{const e=Function;return new e(""),!0}catch{return!1}});function bt(e){if(_o(e)===!1)return!1;const o=e.constructor;if(o===void 0||typeof o!="function")return!0;const t=o.prototype;return!(_o(t)===!1||Object.prototype.hasOwnProperty.call(t,"isPrototypeOf")===!1)}function En(e){return bt(e)?{...e}:Array.isArray(e)?[...e]:e instanceof Map?new Map(e):e instanceof Set?new Set(e):e}const hc=new Set(["string","number","symbol"]);function wt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function st(e,o,t){const s=new e._zod.constr(o??e._zod.def);return(!o||t?.parent)&&(s._zod.parent=e),s}function J(e){const o=e;if(!o)return{};if(typeof o=="string")return{error:()=>o};if(o?.message!==void 0){if(o?.error!==void 0)throw new Error("Cannot specify both `message` and `error` params");o.error=o.message}return delete o.message,typeof o.error=="string"?{...o,error:()=>o.error}:o}function gc(e){return Object.keys(e).filter(o=>e[o]._zod.optin==="optional"&&e[o]._zod.optout==="optional")}const vc={safeint:[Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER],int32:[-2147483648,2147483647],uint32:[0,4294967295],float32:[-34028234663852886e22,34028234663852886e22],float64:[-Number.MAX_VALUE,Number.MAX_VALUE]};function bc(e,o){const t=e._zod.def,s=t.checks;if(s&&s.length>0)throw new Error(".pick() cannot be used on object schemas containing refinements");const c=ot(e._zod.def,{get shape(){const l={};for(const m in o){if(!(m in t.shape))throw new Error(`Unrecognized key: "${m}"`);o[m]&&(l[m]=t.shape[m])}return pt(this,"shape",l),l},checks:[]});return st(e,c)}function wc(e,o){const t=e._zod.def,s=t.checks;if(s&&s.length>0)throw new Error(".omit() cannot be used on object schemas containing refinements");const c=ot(e._zod.def,{get shape(){const l={...e._zod.def.shape};for(const m in o){if(!(m in t.shape))throw new Error(`Unrecognized key: "${m}"`);o[m]&&delete l[m]}return pt(this,"shape",l),l},checks:[]});return st(e,c)}function Cc(e,o){if(!bt(o))throw new Error("Invalid input to extend: expected a plain object");const t=e._zod.def.checks;if(t&&t.length>0){const c=e._zod.def.shape;for(const l in o)if(Object.getOwnPropertyDescriptor(c,l)!==void 0)throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.")}const r=ot(e._zod.def,{get shape(){const c={...e._zod.def.shape,...o};return pt(this,"shape",c),c}});return st(e,r)}function Rc(e,o){if(!bt(o))throw new Error("Invalid input to safeExtend: expected a plain object");const t=ot(e._zod.def,{get shape(){const s={...e._zod.def.shape,...o};return pt(this,"shape",s),s}});return st(e,t)}function Sc(e,o){if(e._zod.def.checks?.length)throw new Error(".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.");const t=ot(e._zod.def,{get shape(){const s={...e._zod.def.shape,...o._zod.def.shape};return pt(this,"shape",s),s},get catchall(){return o._zod.def.catchall},checks:o._zod.def.checks??[]});return st(e,t)}function kc(e,o,t){const r=o._zod.def.checks;if(r&&r.length>0)throw new Error(".partial() cannot be used on object schemas containing refinements");const l=ot(o._zod.def,{get shape(){const m=o._zod.def.shape,g={...m};if(t)for(const y in t){if(!(y in m))throw new Error(`Unrecognized key: "${y}"`);t[y]&&(g[y]=e?new e({type:"optional",innerType:m[y]}):m[y])}else for(const y in m)g[y]=e?new e({type:"optional",innerType:m[y]}):m[y];return pt(this,"shape",g),g},checks:[]});return st(o,l)}function qc(e,o,t){const s=ot(o._zod.def,{get shape(){const r=o._zod.def.shape,c={...r};if(t)for(const l in t){if(!(l in c))throw new Error(`Unrecognized key: "${l}"`);t[l]&&(c[l]=new e({type:"nonoptional",innerType:r[l]}))}else for(const l in r)c[l]=new e({type:"nonoptional",innerType:r[l]});return pt(this,"shape",c),c}});return st(o,s)}function ht(e,o=0){if(e.aborted===!0)return!0;for(let t=o;t<e.issues.length;t++)if(e.issues[t]?.continue!==!0)return!0;return!1}function Ic(e,o=0){if(e.aborted===!0)return!0;for(let t=o;t<e.issues.length;t++)if(e.issues[t]?.continue===!1)return!0;return!1}function gt(e,o){return o.map(t=>{var s;return(s=t).path??(s.path=[]),t.path.unshift(e),t})}function ro(e){return typeof e=="string"?e:e?.message}function Ge(e,o,t){const s=e.message?e.message:ro(e.inst?._zod.def?.error?.(e))??ro(o?.error?.(e))??ro(t.customError?.(e))??ro(t.localeError?.(e))??"Invalid input",{inst:r,continue:c,input:l,...m}=e;return m.path??(m.path=[]),m.message=s,o?.reportInput&&(m.input=l),m}function zs(e){return Array.isArray(e)?"array":typeof e=="string"?"string":"unknown"}function Pt(...e){const[o,t,s]=e;return typeof o=="string"?{message:o,code:"custom",input:t,inst:s}:{...o}}const $n=(e,o)=>{e.name="$ZodError",Object.defineProperty(e,"_zod",{value:e._zod,enumerable:!1}),Object.defineProperty(e,"issues",{value:o,enumerable:!1}),e.message=JSON.stringify(o,Xs,2),Object.defineProperty(e,"toString",{value:()=>e.message,enumerable:!1})},Io=H("$ZodError",$n),Tn=H("$ZodError",$n,{Parent:Error});function xc(e,o=t=>t.message){const t={},s=[];for(const r of e.issues)r.path.length>0?(t[r.path[0]]=t[r.path[0]]||[],t[r.path[0]].push(o(r))):s.push(o(r));return{formErrors:s,fieldErrors:t}}function Ac(e,o=t=>t.message){const t={_errors:[]},s=(r,c=[])=>{for(const l of r.issues)if(l.code==="invalid_union"&&l.errors.length)l.errors.map(m=>s({issues:m},[...c,...l.path]));else if(l.code==="invalid_key")s({issues:l.issues},[...c,...l.path]);else if(l.code==="invalid_element")s({issues:l.issues},[...c,...l.path]);else{const m=[...c,...l.path];if(m.length===0)t._errors.push(o(l));else{let g=t,y=0;for(;y<m.length;){const b=m[y];y===m.length-1?(g[b]=g[b]||{_errors:[]},g[b]._errors.push(o(l))):g[b]=g[b]||{_errors:[]},g=g[b],y++}}}};return s(e),t}function Ec(e){const o=[],t=e.map(s=>typeof s=="object"?s.key:s);for(const s of t)typeof s=="number"?o.push(`[${s}]`):typeof s=="symbol"?o.push(`[${JSON.stringify(String(s))}]`):/[^\w$]/.test(s)?o.push(`[${JSON.stringify(s)}]`):(o.length&&o.push("."),o.push(s));return o.join("")}function $c(e){const o=[],t=[...e.issues].sort((s,r)=>(s.path??[]).length-(r.path??[]).length);for(const s of t)o.push(`✖ ${s.message}`),s.path?.length&&o.push(` → at ${Ec(s.path)}`);return o.join(`
2
  `)}const Ks=e=>(o,t,s,r)=>{const c=s?{...s,async:!1}:{async:!1},l=o._zod.run({value:t,issues:[]},c);if(l instanceof Promise)throw new vt;if(l.issues.length){const m=new(r?.Err??e)(l.issues.map(g=>Ge(g,c,Ve())));throw An(m,r?.callee),m}return l.value},Hs=e=>async(o,t,s,r)=>{const c=s?{...s,async:!0}:{async:!0};let l=o._zod.run({value:t,issues:[]},c);if(l instanceof Promise&&(l=await l),l.issues.length){const m=new(r?.Err??e)(l.issues.map(g=>Ge(g,c,Ve())));throw An(m,r?.callee),m}return l.value},xo=e=>(o,t,s)=>{const r=s?{...s,async:!1}:{async:!1},c=o._zod.run({value:t,issues:[]},r);if(c instanceof Promise)throw new vt;return c.issues.length?{success:!1,error:new(e??Io)(c.issues.map(l=>Ge(l,r,Ve())))}:{success:!0,data:c.value}},Tc=xo(Tn),Ao=e=>async(o,t,s)=>{const r=s?{...s,async:!0}:{async:!0};let c=o._zod.run({value:t,issues:[]},r);return c instanceof Promise&&(c=await c),c.issues.length?{success:!1,error:new e(c.issues.map(l=>Ge(l,r,Ve())))}:{success:!0,data:c.value}},Xc=Ao(Tn),Lc=e=>(o,t,s)=>{const r=s?{...s,direction:"backward"}:{direction:"backward"};return Ks(e)(o,t,r)},Uc=e=>(o,t,s)=>Ks(e)(o,t,s),Mc=e=>async(o,t,s)=>{const r=s?{...s,direction:"backward"}:{direction:"backward"};return Hs(e)(o,t,r)},Dc=e=>async(o,t,s)=>Hs(e)(o,t,s),Oc=e=>(o,t,s)=>{const r=s?{...s,direction:"backward"}:{direction:"backward"};return xo(e)(o,t,r)},Fc=e=>(o,t,s)=>xo(e)(o,t,s),jc=e=>async(o,t,s)=>{const r=s?{...s,direction:"backward"}:{direction:"backward"};return Ao(e)(o,t,r)},Pc=e=>async(o,t,s)=>Ao(e)(o,t,s),Nc=/^[cC][0-9a-z]{6,}$/,zc=/^[0-9a-z]+$/,Kc=/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/,Hc=/^[0-9a-vA-V]{20}$/,Zc=/^[A-Za-z0-9]{27}$/,Wc=/^[a-zA-Z0-9_-]{21}$/,Vc=/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/,Gc=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/,Ur=e=>e?new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${e}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/,Jc=/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/,Bc="^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$";function Yc(){return new RegExp(Bc,"u")}const Qc=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,ed=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/,td=/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,od=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,sd=/^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/,Xn=/^[A-Za-z0-9_-]*$/,rd=/^https?$/,nd=/^\+[1-9]\d{6,14}$/,Ln="(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))",ad=new RegExp(`^${Ln}$`);function Un(e){const o="(?:[01]\\d|2[0-3]):[0-5]\\d";return typeof e.precision=="number"?e.precision===-1?`${o}`:e.precision===0?`${o}:[0-5]\\d`:`${o}:[0-5]\\d\\.\\d{${e.precision}}`:`${o}(?::[0-5]\\d(?:\\.\\d+)?)?`}function id(e){return new RegExp(`^${Un(e)}$`)}function ud(e){const o=Un({precision:e.precision}),t=["Z"];e.local&&t.push(""),e.offset&&t.push("([+-](?:[01]\\d|2[0-3]):[0-5]\\d)");const s=`${o}(?:${t.join("|")})`;return new RegExp(`^${Ln}T(?:${s})$`)}const cd=e=>{const o=e?`[\\s\\S]{${e?.minimum??0},${e?.maximum??""}}`:"[\\s\\S]*";return new RegExp(`^${o}$`)},dd=/^-?\d+$/,Mn=/^-?\d+(?:\.\d+)?$/,ld=/^(?:true|false)$/i,pd=/^[^A-Z]*$/,fd=/^[^a-z]*$/,Me=H("$ZodCheck",(e,o)=>{var t;e._zod??(e._zod={}),e._zod.def=o,(t=e._zod).onattach??(t.onattach=[])}),Dn={number:"number",bigint:"bigint",object:"date"},On=H("$ZodCheckLessThan",(e,o)=>{Me.init(e,o);const t=Dn[typeof o.value];e._zod.onattach.push(s=>{const r=s._zod.bag,c=(o.inclusive?r.maximum:r.exclusiveMaximum)??Number.POSITIVE_INFINITY;o.value<c&&(o.inclusive?r.maximum=o.value:r.exclusiveMaximum=o.value)}),e._zod.check=s=>{(o.inclusive?s.value<=o.value:s.value<o.value)||s.issues.push({origin:t,code:"too_big",maximum:typeof o.value=="object"?o.value.getTime():o.value,input:s.value,inclusive:o.inclusive,inst:e,continue:!o.abort})}}),Fn=H("$ZodCheckGreaterThan",(e,o)=>{Me.init(e,o);const t=Dn[typeof o.value];e._zod.onattach.push(s=>{const r=s._zod.bag,c=(o.inclusive?r.minimum:r.exclusiveMinimum)??Number.NEGATIVE_INFINITY;o.value>c&&(o.inclusive?r.minimum=o.value:r.exclusiveMinimum=o.value)}),e._zod.check=s=>{(o.inclusive?s.value>=o.value:s.value>o.value)||s.issues.push({origin:t,code:"too_small",minimum:typeof o.value=="object"?o.value.getTime():o.value,input:s.value,inclusive:o.inclusive,inst:e,continue:!o.abort})}}),_d=H("$ZodCheckMultipleOf",(e,o)=>{Me.init(e,o),e._zod.onattach.push(t=>{var s;(s=t._zod.bag).multipleOf??(s.multipleOf=o.value)}),e._zod.check=t=>{if(typeof t.value!=typeof o.value)throw new Error("Cannot mix number and bigint in multiple_of check.");(typeof t.value=="bigint"?t.value%o.value===BigInt(0):_c(t.value,o.value)===0)||t.issues.push({origin:typeof t.value,code:"not_multiple_of",divisor:o.value,input:t.value,inst:e,continue:!o.abort})}}),md=H("$ZodCheckNumberFormat",(e,o)=>{Me.init(e,o),o.format=o.format||"float64";const t=o.format?.includes("int"),s=t?"int":"number",[r,c]=vc[o.format];e._zod.onattach.push(l=>{const m=l._zod.bag;m.format=o.format,m.minimum=r,m.maximum=c,t&&(m.pattern=dd)}),e._zod.check=l=>{const m=l.value;if(t){if(!Number.isInteger(m)){l.issues.push({expected:s,format:o.format,code:"invalid_type",continue:!1,input:m,inst:e});return}if(!Number.isSafeInteger(m)){m>0?l.issues.push({input:m,code:"too_big",maximum:Number.MAX_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:e,origin:s,inclusive:!0,continue:!o.abort}):l.issues.push({input:m,code:"too_small",minimum:Number.MIN_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:e,origin:s,inclusive:!0,continue:!o.abort});return}}m<r&&l.issues.push({origin:"number",input:m,code:"too_small",minimum:r,inclusive:!0,inst:e,continue:!o.abort}),m>c&&l.issues.push({origin:"number",input:m,code:"too_big",maximum:c,inclusive:!0,inst:e,continue:!o.abort})}}),yd=H("$ZodCheckMaxLength",(e,o)=>{var t;Me.init(e,o),(t=e._zod.def).when??(t.when=s=>{const r=s.value;return!Ps(r)&&r.length!==void 0}),e._zod.onattach.push(s=>{const r=s._zod.bag.maximum??Number.POSITIVE_INFINITY;o.maximum<r&&(s._zod.bag.maximum=o.maximum)}),e._zod.check=s=>{const r=s.value;if(r.length<=o.maximum)return;const l=zs(r);s.issues.push({origin:l,code:"too_big",maximum:o.maximum,inclusive:!0,input:r,inst:e,continue:!o.abort})}}),hd=H("$ZodCheckMinLength",(e,o)=>{var t;Me.init(e,o),(t=e._zod.def).when??(t.when=s=>{const r=s.value;return!Ps(r)&&r.length!==void 0}),e._zod.onattach.push(s=>{const r=s._zod.bag.minimum??Number.NEGATIVE_INFINITY;o.minimum>r&&(s._zod.bag.minimum=o.minimum)}),e._zod.check=s=>{const r=s.value;if(r.length>=o.minimum)return;const l=zs(r);s.issues.push({origin:l,code:"too_small",minimum:o.minimum,inclusive:!0,input:r,inst:e,continue:!o.abort})}}),gd=H("$ZodCheckLengthEquals",(e,o)=>{var t;Me.init(e,o),(t=e._zod.def).when??(t.when=s=>{const r=s.value;return!Ps(r)&&r.length!==void 0}),e._zod.onattach.push(s=>{const r=s._zod.bag;r.minimum=o.length,r.maximum=o.length,r.length=o.length}),e._zod.check=s=>{const r=s.value,c=r.length;if(c===o.length)return;const l=zs(r),m=c>o.length;s.issues.push({origin:l,...m?{code:"too_big",maximum:o.length}:{code:"too_small",minimum:o.length},inclusive:!0,exact:!0,input:s.value,inst:e,continue:!o.abort})}}),Eo=H("$ZodCheckStringFormat",(e,o)=>{var t,s;Me.init(e,o),e._zod.onattach.push(r=>{const c=r._zod.bag;c.format=o.format,o.pattern&&(c.patterns??(c.patterns=new Set),c.patterns.add(o.pattern))}),o.pattern?(t=e._zod).check??(t.check=r=>{o.pattern.lastIndex=0,!o.pattern.test(r.value)&&r.issues.push({origin:"string",code:"invalid_format",format:o.format,input:r.value,...o.pattern?{pattern:o.pattern.toString()}:{},inst:e,continue:!o.abort})}):(s=e._zod).check??(s.check=()=>{})}),vd=H("$ZodCheckRegex",(e,o)=>{Eo.init(e,o),e._zod.check=t=>{o.pattern.lastIndex=0,!o.pattern.test(t.value)&&t.issues.push({origin:"string",code:"invalid_format",format:"regex",input:t.value,pattern:o.pattern.toString(),inst:e,continue:!o.abort})}}),bd=H("$ZodCheckLowerCase",(e,o)=>{o.pattern??(o.pattern=pd),Eo.init(e,o)}),wd=H("$ZodCheckUpperCase",(e,o)=>{o.pattern??(o.pattern=fd),Eo.init(e,o)}),Cd=H("$ZodCheckIncludes",(e,o)=>{Me.init(e,o);const t=wt(o.includes),s=new RegExp(typeof o.position=="number"?`^.{${o.position}}${t}`:t);o.pattern=s,e._zod.onattach.push(r=>{const c=r._zod.bag;c.patterns??(c.patterns=new Set),c.patterns.add(s)}),e._zod.check=r=>{r.value.includes(o.includes,o.position)||r.issues.push({origin:"string",code:"invalid_format",format:"includes",includes:o.includes,input:r.value,inst:e,continue:!o.abort})}}),Rd=H("$ZodCheckStartsWith",(e,o)=>{Me.init(e,o);const t=new RegExp(`^${wt(o.prefix)}.*`);o.pattern??(o.pattern=t),e._zod.onattach.push(s=>{const r=s._zod.bag;r.patterns??(r.patterns=new Set),r.patterns.add(t)}),e._zod.check=s=>{s.value.startsWith(o.prefix)||s.issues.push({origin:"string",code:"invalid_format",format:"starts_with",prefix:o.prefix,input:s.value,inst:e,continue:!o.abort})}}),Sd=H("$ZodCheckEndsWith",(e,o)=>{Me.init(e,o);const t=new RegExp(`.*${wt(o.suffix)}$`);o.pattern??(o.pattern=t),e._zod.onattach.push(s=>{const r=s._zod.bag;r.patterns??(r.patterns=new Set),r.patterns.add(t)}),e._zod.check=s=>{s.value.endsWith(o.suffix)||s.issues.push({origin:"string",code:"invalid_format",format:"ends_with",suffix:o.suffix,input:s.value,inst:e,continue:!o.abort})}}),kd=H("$ZodCheckOverwrite",(e,o)=>{Me.init(e,o),e._zod.check=t=>{t.value=o.tx(t.value)}});class qd{constructor(o=[]){this.content=[],this.indent=0,this&&(this.args=o)}indented(o){this.indent+=1,o(this),this.indent-=1}write(o){if(typeof o=="function"){o(this,{execution:"sync"}),o(this,{execution:"async"});return}const s=o.split(`
3
  `).filter(l=>l),r=Math.min(...s.map(l=>l.length-l.trimStart().length)),c=s.map(l=>l.slice(r)).map(l=>" ".repeat(this.indent*2)+l);for(const l of c)this.content.push(l)}compile(){const o=Function,t=this?.args,r=[...(this?.content??[""]).map(c=>` ${c}`)];return new o(...t,r.join(`
4
  `))}}const Id={major:4,minor:4,patch:3},le=H("$ZodType",(e,o)=>{var t;e??(e={}),e._zod.def=o,e._zod.bag=e._zod.bag||{},e._zod.version=Id;const s=[...e._zod.def.checks??[]];e._zod.traits.has("$ZodCheck")&&s.unshift(e);for(const r of s)for(const c of r._zod.onattach)c(e);if(s.length===0)(t=e._zod).deferred??(t.deferred=[]),e._zod.deferred?.push(()=>{e._zod.run=e._zod.parse});else{const r=(l,m,g)=>{let y=ht(l),b;for(const _ of m){if(_._zod.def.when){if(Ic(l)||!_._zod.def.when(l))continue}else if(y)continue;const i=l.issues.length,u=_._zod.check(l);if(u instanceof Promise&&g?.async===!1)throw new vt;if(b||u instanceof Promise)b=(b??Promise.resolve()).then(async()=>{await u,l.issues.length!==i&&(y||(y=ht(l,i)))});else{if(l.issues.length===i)continue;y||(y=ht(l,i))}}return b?b.then(()=>l):l},c=(l,m,g)=>{if(ht(l))return l.aborted=!0,l;const y=r(m,s,g);if(y instanceof Promise){if(g.async===!1)throw new vt;return y.then(b=>e._zod.parse(b,g))}return e._zod.parse(y,g)};e._zod.run=(l,m)=>{if(m.skipChecks)return e._zod.parse(l,m);if(m.direction==="backward"){const y=e._zod.parse({value:l.value,issues:[]},{...m,skipChecks:!0});return y instanceof Promise?y.then(b=>c(b,l,m)):c(y,l,m)}const g=e._zod.parse(l,m);if(g instanceof Promise){if(m.async===!1)throw new vt;return g.then(y=>r(y,s,m))}return r(g,s,m)}}ne(e,"~standard",()=>({validate:r=>{try{const c=Tc(e,r);return c.success?{value:c.data}:{issues:c.error?.issues}}catch{return Xc(e,r).then(l=>l.success?{value:l.data}:{issues:l.error?.issues})}},vendor:"zod",version:1}))}),Zs=H("$ZodString",(e,o)=>{le.init(e,o),e._zod.pattern=[...e?._zod.bag?.patterns??[]].pop()??cd(e._zod.bag),e._zod.parse=(t,s)=>{if(o.coerce)try{t.value=String(t.value)}catch{}return typeof t.value=="string"||t.issues.push({expected:"string",code:"invalid_type",input:t.value,inst:e}),t}}),_e=H("$ZodStringFormat",(e,o)=>{Eo.init(e,o),Zs.init(e,o)}),xd=H("$ZodGUID",(e,o)=>{o.pattern??(o.pattern=Gc),_e.init(e,o)}),Ad=H("$ZodUUID",(e,o)=>{if(o.version){const s={v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8}[o.version];if(s===void 0)throw new Error(`Invalid UUID version: "${o.version}"`);o.pattern??(o.pattern=Ur(s))}else o.pattern??(o.pattern=Ur());_e.init(e,o)}),Ed=H("$ZodEmail",(e,o)=>{o.pattern??(o.pattern=Jc),_e.init(e,o)}),$d=H("$ZodURL",(e,o)=>{_e.init(e,o),e._zod.check=t=>{try{const s=t.value.trim();if(!o.normalize&&o.protocol?.source===rd.source&&!/^https?:\/\//i.test(s)){t.issues.push({code:"invalid_format",format:"url",note:"Invalid URL format",input:t.value,inst:e,continue:!o.abort});return}const r=new URL(s);o.hostname&&(o.hostname.lastIndex=0,o.hostname.test(r.hostname)||t.issues.push({code:"invalid_format",format:"url",note:"Invalid hostname",pattern:o.hostname.source,input:t.value,inst:e,continue:!o.abort})),o.protocol&&(o.protocol.lastIndex=0,o.protocol.test(r.protocol.endsWith(":")?r.protocol.slice(0,-1):r.protocol)||t.issues.push({code:"invalid_format",format:"url",note:"Invalid protocol",pattern:o.protocol.source,input:t.value,inst:e,continue:!o.abort})),o.normalize?t.value=r.href:t.value=s;return}catch{t.issues.push({code:"invalid_format",format:"url",input:t.value,inst:e,continue:!o.abort})}}}),Td=H("$ZodEmoji",(e,o)=>{o.pattern??(o.pattern=Yc()),_e.init(e,o)}),Xd=H("$ZodNanoID",(e,o)=>{o.pattern??(o.pattern=Wc),_e.init(e,o)}),Ld=H("$ZodCUID",(e,o)=>{o.pattern??(o.pattern=Nc),_e.init(e,o)}),Ud=H("$ZodCUID2",(e,o)=>{o.pattern??(o.pattern=zc),_e.init(e,o)}),Md=H("$ZodULID",(e,o)=>{o.pattern??(o.pattern=Kc),_e.init(e,o)}),Dd=H("$ZodXID",(e,o)=>{o.pattern??(o.pattern=Hc),_e.init(e,o)}),Od=H("$ZodKSUID",(e,o)=>{o.pattern??(o.pattern=Zc),_e.init(e,o)}),Fd=H("$ZodISODateTime",(e,o)=>{o.pattern??(o.pattern=ud(o)),_e.init(e,o)}),jd=H("$ZodISODate",(e,o)=>{o.pattern??(o.pattern=ad),_e.init(e,o)}),Pd=H("$ZodISOTime",(e,o)=>{o.pattern??(o.pattern=id(o)),_e.init(e,o)}),Nd=H("$ZodISODuration",(e,o)=>{o.pattern??(o.pattern=Vc),_e.init(e,o)}),zd=H("$ZodIPv4",(e,o)=>{o.pattern??(o.pattern=Qc),_e.init(e,o),e._zod.bag.format="ipv4"}),Kd=H("$ZodIPv6",(e,o)=>{o.pattern??(o.pattern=ed),_e.init(e,o),e._zod.bag.format="ipv6",e._zod.check=t=>{try{new URL(`http://[${t.value}]`)}catch{t.issues.push({code:"invalid_format",format:"ipv6",input:t.value,inst:e,continue:!o.abort})}}}),Hd=H("$ZodCIDRv4",(e,o)=>{o.pattern??(o.pattern=td),_e.init(e,o)}),Zd=H("$ZodCIDRv6",(e,o)=>{o.pattern??(o.pattern=od),_e.init(e,o),e._zod.check=t=>{const s=t.value.split("/");try{if(s.length!==2)throw new Error;const[r,c]=s;if(!c)throw new Error;const l=Number(c);if(`${l}`!==c)throw new Error;if(l<0||l>128)throw new Error;new URL(`http://[${r}]`)}catch{t.issues.push({code:"invalid_format",format:"cidrv6",input:t.value,inst:e,continue:!o.abort})}}});function jn(e){if(e==="")return!0;if(/\s/.test(e)||e.length%4!==0)return!1;try{return atob(e),!0}catch{return!1}}const Wd=H("$ZodBase64",(e,o)=>{o.pattern??(o.pattern=sd),_e.init(e,o),e._zod.bag.contentEncoding="base64",e._zod.check=t=>{jn(t.value)||t.issues.push({code:"invalid_format",format:"base64",input:t.value,inst:e,continue:!o.abort})}});function Vd(e){if(!Xn.test(e))return!1;const o=e.replace(/[-_]/g,s=>s==="-"?"+":"/"),t=o.padEnd(Math.ceil(o.length/4)*4,"=");return jn(t)}const Gd=H("$ZodBase64URL",(e,o)=>{o.pattern??(o.pattern=Xn),_e.init(e,o),e._zod.bag.contentEncoding="base64url",e._zod.check=t=>{Vd(t.value)||t.issues.push({code:"invalid_format",format:"base64url",input:t.value,inst:e,continue:!o.abort})}}),Jd=H("$ZodE164",(e,o)=>{o.pattern??(o.pattern=nd),_e.init(e,o)});function Bd(e,o=null){try{const t=e.split(".");if(t.length!==3)return!1;const[s]=t;if(!s)return!1;const r=JSON.parse(atob(s));return!("typ"in r&&r?.typ!=="JWT"||!r.alg||o&&(!("alg"in r)||r.alg!==o))}catch{return!1}}const Yd=H("$ZodJWT",(e,o)=>{_e.init(e,o),e._zod.check=t=>{Bd(t.value,o.alg)||t.issues.push({code:"invalid_format",format:"jwt",input:t.value,inst:e,continue:!o.abort})}}),Pn=H("$ZodNumber",(e,o)=>{le.init(e,o),e._zod.pattern=e._zod.bag.pattern??Mn,e._zod.parse=(t,s)=>{if(o.coerce)try{t.value=Number(t.value)}catch{}const r=t.value;if(typeof r=="number"&&!Number.isNaN(r)&&Number.isFinite(r))return t;const c=typeof r=="number"?Number.isNaN(r)?"NaN":Number.isFinite(r)?void 0:"Infinity":void 0;return t.issues.push({expected:"number",code:"invalid_type",input:r,inst:e,...c?{received:c}:{}}),t}}),Qd=H("$ZodNumberFormat",(e,o)=>{md.init(e,o),Pn.init(e,o)}),el=H("$ZodBoolean",(e,o)=>{le.init(e,o),e._zod.pattern=ld,e._zod.parse=(t,s)=>{if(o.coerce)try{t.value=!!t.value}catch{}const r=t.value;return typeof r=="boolean"||t.issues.push({expected:"boolean",code:"invalid_type",input:r,inst:e}),t}}),tl=H("$ZodAny",(e,o)=>{le.init(e,o),e._zod.parse=t=>t}),ol=H("$ZodUnknown",(e,o)=>{le.init(e,o),e._zod.parse=t=>t}),sl=H("$ZodNever",(e,o)=>{le.init(e,o),e._zod.parse=(t,s)=>(t.issues.push({expected:"never",code:"invalid_type",input:t.value,inst:e}),t)}),rl=H("$ZodVoid",(e,o)=>{le.init(e,o),e._zod.parse=(t,s)=>{const r=t.value;return typeof r>"u"||t.issues.push({expected:"void",code:"invalid_type",input:r,inst:e}),t}}),nl=H("$ZodDate",(e,o)=>{le.init(e,o),e._zod.parse=(t,s)=>{if(o.coerce)try{t.value=new Date(t.value)}catch{}const r=t.value,c=r instanceof Date;return c&&!Number.isNaN(r.getTime())||t.issues.push({expected:"date",code:"invalid_type",input:r,...c?{received:"Invalid Date"}:{},inst:e}),t}});function Mr(e,o,t){e.issues.length&&o.issues.push(...gt(t,e.issues)),o.value[t]=e.value}const al=H("$ZodArray",(e,o)=>{le.init(e,o),e._zod.parse=(t,s)=>{const r=t.value;if(!Array.isArray(r))return t.issues.push({expected:"array",code:"invalid_type",input:r,inst:e}),t;t.value=Array(r.length);const c=[];for(let l=0;l<r.length;l++){const m=r[l],g=o.element._zod.run({value:m,issues:[]},s);g instanceof Promise?c.push(g.then(y=>Mr(y,t,l))):Mr(g,t,l)}return c.length?Promise.all(c).then(()=>t):t}});function mo(e,o,t,s,r,c){const l=t in s;if(e.issues.length){if(r&&c&&!l)return;o.issues.push(...gt(t,e.issues))}if(!l&&!r){e.issues.length||o.issues.push({code:"invalid_type",expected:"nonoptional",input:void 0,path:[t]});return}e.value===void 0?l&&(o.value[t]=void 0):o.value[t]=e.value}function Nn(e){const o=Object.keys(e.shape);for(const s of o)if(!e.shape?.[s]?._zod?.traits?.has("$ZodType"))throw new Error(`Invalid element at key "${s}": expected a Zod schema`);const t=gc(e.shape);return{...e,keys:o,keySet:new Set(o),numKeys:o.length,optionalKeys:new Set(t)}}function zn(e,o,t,s,r,c){const l=[],m=r.keySet,g=r.catchall._zod,y=g.def.type,b=g.optin==="optional",_=g.optout==="optional";for(const i in o){if(i==="__proto__"||m.has(i))continue;if(y==="never"){l.push(i);continue}const u=g.run({value:o[i],issues:[]},s);u instanceof Promise?e.push(u.then(a=>mo(a,t,i,o,b,_))):mo(u,t,i,o,b,_)}return l.length&&t.issues.push({code:"unrecognized_keys",keys:l,input:o,inst:c}),e.length?Promise.all(e).then(()=>t):t}const il=H("$ZodObject",(e,o)=>{if(le.init(e,o),!Object.getOwnPropertyDescriptor(o,"shape")?.get){const m=o.shape;Object.defineProperty(o,"shape",{get:()=>{const g={...m};return Object.defineProperty(o,"shape",{value:g}),g}})}const s=js(()=>Nn(o));ne(e._zod,"propValues",()=>{const m=o.shape,g={};for(const y in m){const b=m[y]._zod;if(b.values){g[y]??(g[y]=new Set);for(const _ of b.values)g[y].add(_)}}return g});const r=_o,c=o.catchall;let l;e._zod.parse=(m,g)=>{l??(l=s.value);const y=m.value;if(!r(y))return m.issues.push({expected:"object",code:"invalid_type",input:y,inst:e}),m;m.value={};const b=[],_=l.shape;for(const i of l.keys){const u=_[i],a=u._zod.optin==="optional",p=u._zod.optout==="optional",f=u._zod.run({value:y[i],issues:[]},g);f instanceof Promise?b.push(f.then(w=>mo(w,m,i,y,a,p))):mo(f,m,i,y,a,p)}return c?zn(b,y,m,g,s.value,e):b.length?Promise.all(b).then(()=>m):m}}),ul=H("$ZodObjectJIT",(e,o)=>{il.init(e,o);const t=e._zod.parse,s=js(()=>Nn(o)),r=i=>{const u=new qd(["shape","payload","ctx"]),a=s.value,p=C=>{const P=Lr(C);return`shape[${P}]._zod.run({ value: input[${P}], issues: [] }, ctx)`};u.write("const input = payload.value;");const f=Object.create(null);let w=0;for(const C of a.keys)f[C]=`key_${w++}`;u.write("const newResult = {};");for(const C of a.keys){const P=f[C],ie=Lr(C),se=i[C],ve=se?._zod?.optin==="optional",De=se?._zod?.optout==="optional";u.write(`const ${P} = ${p(C)};`),ve&&De?u.write(`
 
1
+ import{A as Vu,g as Cn,a as Gu,c as Ju}from"./index-CB_zB4U3.js";import{s as Bu}from"./hash-DMDecQcg.js";import{a as Ir}from"./json-parse-cUk3uCki.js";import{s as We}from"./sanitize-unicode-B62XMGgN.js";import{t as Yu,b as Qu}from"./transform-messages-DSNYjDRn.js";const ec=Object.prototype.hasOwnProperty;function E(e,o){const t=/\{([a-zA-Z0-9_][a-zA-Z0-9_-]*?)\}/g;return function(r={}){return e.replace(t,function(c,l){if(!ec.call(r,l))throw new Error(`Parameter '${l}' is required`);const m=r[l];if(typeof m!="string"&&typeof m!="number")throw new Error(`Parameter '${l}' must be a string or number`);return`${m}`}).replace(/^\/+/,"")}}const Rn="eu",tc={[Rn]:"https://api.mistral.ai"};function oc(e){let o=e.serverURL;const t={};if(!o){const r=e.server??Rn;o=tc[r]||""}const s=E(o)(t);return new URL(s)}const Sn={sdkVersion:"2.2.1",userAgent:"speakeasy-sdk/typescript 2.2.1 2.881.4 1.0.0 @mistralai/mistralai"};async function qo(e){const o=e.getReader(),t=[];let s=0,r=!1;for(;!r;){const{value:m,done:g}=await o.read();g?r=!0:(t.push(m),s+=m.length)}const c=new Uint8Array(s);let l=0;for(const m of t)c.set(m,l),l+=m.length;return c.buffer}function et(e){if(!e)return null;const o=e.toLowerCase().split(".").pop();return o&&{json:"application/json",xml:"application/xml",html:"text/html",htm:"text/html",txt:"text/plain",csv:"text/csv",pdf:"application/pdf",png:"image/png",jpg:"image/jpeg",jpeg:"image/jpeg",gif:"image/gif",svg:"image/svg+xml",js:"application/javascript",css:"text/css",zip:"application/zip",tar:"application/x-tar",gz:"application/gzip",mp4:"video/mp4",mp3:"audio/mpeg",wav:"audio/wav",webp:"image/webp",ico:"image/x-icon",woff:"font/woff",woff2:"font/woff2",ttf:"font/ttf",otf:"font/otf"}[o]||null}function tt(e,o){return e instanceof Uint8Array?new Blob([new Uint8Array(e)],{type:o}):new Blob([e],{type:o})}const sc=(e,o)=>o==null?fetch(e):fetch(e,o);class Os{options;fetcher;requestHooks=[];requestErrorHooks=[];responseHooks=[];constructor(o={}){this.options=o,this.fetcher=o.fetcher||sc}async request(o){let t=o;for(const s of this.requestHooks){const r=await s(t);r&&(t=r)}try{const s=await this.fetcher(t);for(const r of this.responseHooks)await r(s,t);return s}catch(s){for(const r of this.requestErrorHooks)await r(s,t);throw s}}addHook(...o){if(o[0]==="beforeRequest")this.requestHooks.push(o[1]);else if(o[0]==="requestError")this.requestErrorHooks.push(o[1]);else if(o[0]==="response")this.responseHooks.push(o[1]);else throw new Error(`Invalid hook type: ${o[0]}`);return this}removeHook(...o){let t;if(o[0]==="beforeRequest")t=this.requestHooks;else if(o[0]==="requestError")t=this.requestErrorHooks;else if(o[0]==="response")t=this.responseHooks;else throw new Error(`Invalid hook type: ${o[0]}`);const s=t.findIndex(r=>r===o[1]);return s>=0&&t.splice(s,1),this}clone(){const o=new Os(this.options);return o.requestHooks=this.requestHooks.slice(),o.requestErrorHooks=this.requestErrorHooks.slice(),o.responseHooks=this.responseHooks.slice(),o}}const xr=/\s*;\s*/g;function yt(e,o){if(o==="*")return!0;let t=e.headers.get("content-type")?.trim()||"application/octet-stream";t=t.toLowerCase();const s=o.toLowerCase().trim().split(xr),[r="",...c]=s;if(r.split("/").length!==2)return!1;const l=t.split(xr),[m="",...g]=l,[y="",b=""]=m.split("/");if(!y||!b||r!=="*/*"&&m!==r&&`${y}/*`!==r&&`*/${b}`!==r||g.length<c.length)return!1;const _=new Set(g);for(const i of c)if(!_.has(i))return!1;return!0}const rc=new RegExp("^[0-9]xx$","i");function A(e,o){const t=`${e.status}`,s=Array.isArray(o)?o:[o];return s.length?s.some(r=>{const c=`${r}`;if(c==="default")return!0;if(!rc.test(`${c}`))return c===t;const l=c.charAt(0);if(!l)throw new Error("Invalid status code range");const m=t.charAt(0);if(!m)throw new Error(`Invalid response status code: ${t}`);return m===l}):!1}function nc(e,o,t){return A(e,o)&&yt(e,t)}function kn(e){if(typeof e!="object"||e==null)return!1;const o=e instanceof TypeError&&e.message.toLowerCase().startsWith("failed to fetch"),t=e instanceof TypeError&&e.message.toLowerCase().startsWith("fetch failed"),s="name"in e&&e.name==="ConnectionError",r="code"in e&&typeof e.code=="string"&&e.code.toLowerCase()==="econnreset";return o||t||r||s}function qn(e){if(typeof e!="object"||e==null)return!1;const o="name"in e&&e.name==="TimeoutError",t="code"in e&&e.code===23,s="code"in e&&typeof e.code=="string"&&e.code.toLowerCase()==="econnaborted";return o||t||s}function ac(e){if(typeof e!="object"||e==null)return!1;const o="name"in e&&e.name==="AbortError",t="code"in e&&e.code===20,s="code"in e&&typeof e.code=="string"&&e.code.toLowerCase()==="econnaborted";return o||t||s}class ic{beforeRequest(o,t){const r=`mistral-client-typescript/${Sn.sdkVersion}`;return t.headers.set("user-agent",r),t.headers.get("user-agent")||t.headers.set("x-mistral-user-agent",r),t}}const Ar="x-model-deprecation-timestamp";class uc{afterSuccess(o,t){return t.headers.has(Ar)&&t.clone().json().then(s=>{const r=s.model;console.warn(`WARNING: The model ${r} is deprecated and will be removed on ${t.headers.get(Ar)}. Please refer to https://docs.mistral.ai/getting-started/models/#api-versioning for more information.`)}),t}}function cc(e){const o=new ic;e.registerBeforeRequestHook(o);const t=new uc;e.registerAfterSuccessHook(t)}class Er{sdkInitHooks=[];beforeCreateRequestHooks=[];beforeRequestHooks=[];afterSuccessHooks=[];afterErrorHooks=[];constructor(){const o=[];for(const t of o)"sdkInit"in t&&this.registerSDKInitHook(t),"beforeCreateRequest"in t&&this.registerBeforeCreateRequestHook(t),"beforeRequest"in t&&this.registerBeforeRequestHook(t),"afterSuccess"in t&&this.registerAfterSuccessHook(t),"afterError"in t&&this.registerAfterErrorHook(t);cc(this)}registerSDKInitHook(o){this.sdkInitHooks.push(o)}registerBeforeCreateRequestHook(o){this.beforeCreateRequestHooks.push(o)}registerBeforeRequestHook(o){this.beforeRequestHooks.push(o)}registerAfterSuccessHook(o){this.afterSuccessHooks.push(o)}registerAfterErrorHook(o){this.afterErrorHooks.push(o)}sdkInit(o){return this.sdkInitHooks.reduce((t,s)=>s.sdkInit(t),o)}beforeCreateRequest(o,t){let s=t;for(const r of this.beforeCreateRequestHooks)s=r.beforeCreateRequest(o,s);return s}async beforeRequest(o,t){let s=t;for(const r of this.beforeRequestHooks)s=await r.beforeRequest(o,s);return s}async afterSuccess(o,t){let s=t;for(const r of this.afterSuccessHooks)s=await r.afterSuccess(o,s);return s}async afterError(o,t,s){let r=t,c=s;for(const l of this.afterErrorHooks){const m=await l.afterError(o,r,c);r=m.response,c=m.error}return{response:r,error:c}}}class zt extends Error{cause;name="HTTPClientError";constructor(o,t){let s=o;t?.cause&&(s+=`: ${t.cause}`),super(s,t),typeof this.cause>"u"&&(this.cause=t?.cause)}}class $r extends zt{name="UnexpectedClientError"}class dc extends zt{name="InvalidRequestError"}class lc extends zt{name="RequestAbortedError"}class pc extends zt{name="RequestTimeoutError"}class fc extends zt{name="ConnectionError"}function fo(e){return{ok:!0,value:e}}function Ye(e){return{ok:!1,error:e}}async function x(e){const o=await e;if(!o.ok)throw o.error;return o.value}var Tr;const lt=Object.freeze({status:"aborted"});function H(e,o,t){function s(m,g){if(m._zod||Object.defineProperty(m,"_zod",{value:{def:g,constr:l,traits:new Set},enumerable:!1}),m._zod.traits.has(e))return;m._zod.traits.add(e),o(m,g);const y=l.prototype,b=Object.keys(y);for(let _=0;_<b.length;_++){const i=b[_];i in m||(m[i]=y[i].bind(m))}}const r=t?.Parent??Object;class c extends r{}Object.defineProperty(c,"name",{value:e});function l(m){var g;const y=t?.Parent?new c:this;s(y,m),(g=y._zod).deferred??(g.deferred=[]);for(const b of y._zod.deferred)b();return y}return Object.defineProperty(l,"init",{value:s}),Object.defineProperty(l,Symbol.hasInstance,{value:m=>t?.Parent&&m instanceof t.Parent?!0:m?._zod?.traits?.has(e)}),Object.defineProperty(l,"name",{value:e}),l}class vt extends Error{constructor(){super("Encountered Promise during synchronous parse. Use .parseAsync() instead.")}}class In extends Error{constructor(o){super(`Encountered unidirectional transform during encode: ${o}`),this.name="ZodEncodeError"}}(Tr=globalThis).__zod_globalConfig??(Tr.__zod_globalConfig={});const Fs=globalThis.__zod_globalConfig;function Ve(e){return Fs}function xn(e){const o=Object.values(e).filter(s=>typeof s=="number");return Object.entries(e).filter(([s,r])=>o.indexOf(+s)===-1).map(([s,r])=>r)}function Xs(e,o){return typeof o=="bigint"?o.toString():o}function js(e){return{get value(){{const o=e();return Object.defineProperty(this,"value",{value:o}),o}}}}function Ps(e){return e==null}function Ns(e){const o=e.startsWith("^")?1:0,t=e.endsWith("$")?e.length-1:e.length;return e.slice(o,t)}function _c(e,o){const t=e/o,s=Math.round(t),r=Number.EPSILON*Math.max(Math.abs(t),1);return Math.abs(t-s)<r?0:t-s}const Xr=Symbol("evaluating");function ne(e,o,t){let s;Object.defineProperty(e,o,{get(){if(s!==Xr)return s===void 0&&(s=Xr,s=t()),s},set(r){Object.defineProperty(e,o,{value:r})},configurable:!0})}function pt(e,o,t){Object.defineProperty(e,o,{value:t,writable:!0,enumerable:!0,configurable:!0})}function ot(...e){const o={};for(const t of e){const s=Object.getOwnPropertyDescriptors(t);Object.assign(o,s)}return Object.defineProperties({},o)}function Lr(e){return JSON.stringify(e)}function mc(e){return e.toLowerCase().trim().replace(/[^\w\s-]/g,"").replace(/[\s_-]+/g,"-").replace(/^-+|-+$/g,"")}const An="captureStackTrace"in Error?Error.captureStackTrace:(...e)=>{};function _o(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}const yc=js(()=>{if(Fs.jitless||typeof navigator<"u"&&navigator?.userAgent?.includes("Cloudflare"))return!1;try{const e=Function;return new e(""),!0}catch{return!1}});function bt(e){if(_o(e)===!1)return!1;const o=e.constructor;if(o===void 0||typeof o!="function")return!0;const t=o.prototype;return!(_o(t)===!1||Object.prototype.hasOwnProperty.call(t,"isPrototypeOf")===!1)}function En(e){return bt(e)?{...e}:Array.isArray(e)?[...e]:e instanceof Map?new Map(e):e instanceof Set?new Set(e):e}const hc=new Set(["string","number","symbol"]);function wt(e){return e.replace(/[.*+?^${}()|[\]\\]/g,"\\$&")}function st(e,o,t){const s=new e._zod.constr(o??e._zod.def);return(!o||t?.parent)&&(s._zod.parent=e),s}function J(e){const o=e;if(!o)return{};if(typeof o=="string")return{error:()=>o};if(o?.message!==void 0){if(o?.error!==void 0)throw new Error("Cannot specify both `message` and `error` params");o.error=o.message}return delete o.message,typeof o.error=="string"?{...o,error:()=>o.error}:o}function gc(e){return Object.keys(e).filter(o=>e[o]._zod.optin==="optional"&&e[o]._zod.optout==="optional")}const vc={safeint:[Number.MIN_SAFE_INTEGER,Number.MAX_SAFE_INTEGER],int32:[-2147483648,2147483647],uint32:[0,4294967295],float32:[-34028234663852886e22,34028234663852886e22],float64:[-Number.MAX_VALUE,Number.MAX_VALUE]};function bc(e,o){const t=e._zod.def,s=t.checks;if(s&&s.length>0)throw new Error(".pick() cannot be used on object schemas containing refinements");const c=ot(e._zod.def,{get shape(){const l={};for(const m in o){if(!(m in t.shape))throw new Error(`Unrecognized key: "${m}"`);o[m]&&(l[m]=t.shape[m])}return pt(this,"shape",l),l},checks:[]});return st(e,c)}function wc(e,o){const t=e._zod.def,s=t.checks;if(s&&s.length>0)throw new Error(".omit() cannot be used on object schemas containing refinements");const c=ot(e._zod.def,{get shape(){const l={...e._zod.def.shape};for(const m in o){if(!(m in t.shape))throw new Error(`Unrecognized key: "${m}"`);o[m]&&delete l[m]}return pt(this,"shape",l),l},checks:[]});return st(e,c)}function Cc(e,o){if(!bt(o))throw new Error("Invalid input to extend: expected a plain object");const t=e._zod.def.checks;if(t&&t.length>0){const c=e._zod.def.shape;for(const l in o)if(Object.getOwnPropertyDescriptor(c,l)!==void 0)throw new Error("Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.")}const r=ot(e._zod.def,{get shape(){const c={...e._zod.def.shape,...o};return pt(this,"shape",c),c}});return st(e,r)}function Rc(e,o){if(!bt(o))throw new Error("Invalid input to safeExtend: expected a plain object");const t=ot(e._zod.def,{get shape(){const s={...e._zod.def.shape,...o};return pt(this,"shape",s),s}});return st(e,t)}function Sc(e,o){if(e._zod.def.checks?.length)throw new Error(".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.");const t=ot(e._zod.def,{get shape(){const s={...e._zod.def.shape,...o._zod.def.shape};return pt(this,"shape",s),s},get catchall(){return o._zod.def.catchall},checks:o._zod.def.checks??[]});return st(e,t)}function kc(e,o,t){const r=o._zod.def.checks;if(r&&r.length>0)throw new Error(".partial() cannot be used on object schemas containing refinements");const l=ot(o._zod.def,{get shape(){const m=o._zod.def.shape,g={...m};if(t)for(const y in t){if(!(y in m))throw new Error(`Unrecognized key: "${y}"`);t[y]&&(g[y]=e?new e({type:"optional",innerType:m[y]}):m[y])}else for(const y in m)g[y]=e?new e({type:"optional",innerType:m[y]}):m[y];return pt(this,"shape",g),g},checks:[]});return st(o,l)}function qc(e,o,t){const s=ot(o._zod.def,{get shape(){const r=o._zod.def.shape,c={...r};if(t)for(const l in t){if(!(l in c))throw new Error(`Unrecognized key: "${l}"`);t[l]&&(c[l]=new e({type:"nonoptional",innerType:r[l]}))}else for(const l in r)c[l]=new e({type:"nonoptional",innerType:r[l]});return pt(this,"shape",c),c}});return st(o,s)}function ht(e,o=0){if(e.aborted===!0)return!0;for(let t=o;t<e.issues.length;t++)if(e.issues[t]?.continue!==!0)return!0;return!1}function Ic(e,o=0){if(e.aborted===!0)return!0;for(let t=o;t<e.issues.length;t++)if(e.issues[t]?.continue===!1)return!0;return!1}function gt(e,o){return o.map(t=>{var s;return(s=t).path??(s.path=[]),t.path.unshift(e),t})}function ro(e){return typeof e=="string"?e:e?.message}function Ge(e,o,t){const s=e.message?e.message:ro(e.inst?._zod.def?.error?.(e))??ro(o?.error?.(e))??ro(t.customError?.(e))??ro(t.localeError?.(e))??"Invalid input",{inst:r,continue:c,input:l,...m}=e;return m.path??(m.path=[]),m.message=s,o?.reportInput&&(m.input=l),m}function zs(e){return Array.isArray(e)?"array":typeof e=="string"?"string":"unknown"}function Pt(...e){const[o,t,s]=e;return typeof o=="string"?{message:o,code:"custom",input:t,inst:s}:{...o}}const $n=(e,o)=>{e.name="$ZodError",Object.defineProperty(e,"_zod",{value:e._zod,enumerable:!1}),Object.defineProperty(e,"issues",{value:o,enumerable:!1}),e.message=JSON.stringify(o,Xs,2),Object.defineProperty(e,"toString",{value:()=>e.message,enumerable:!1})},Io=H("$ZodError",$n),Tn=H("$ZodError",$n,{Parent:Error});function xc(e,o=t=>t.message){const t={},s=[];for(const r of e.issues)r.path.length>0?(t[r.path[0]]=t[r.path[0]]||[],t[r.path[0]].push(o(r))):s.push(o(r));return{formErrors:s,fieldErrors:t}}function Ac(e,o=t=>t.message){const t={_errors:[]},s=(r,c=[])=>{for(const l of r.issues)if(l.code==="invalid_union"&&l.errors.length)l.errors.map(m=>s({issues:m},[...c,...l.path]));else if(l.code==="invalid_key")s({issues:l.issues},[...c,...l.path]);else if(l.code==="invalid_element")s({issues:l.issues},[...c,...l.path]);else{const m=[...c,...l.path];if(m.length===0)t._errors.push(o(l));else{let g=t,y=0;for(;y<m.length;){const b=m[y];y===m.length-1?(g[b]=g[b]||{_errors:[]},g[b]._errors.push(o(l))):g[b]=g[b]||{_errors:[]},g=g[b],y++}}}};return s(e),t}function Ec(e){const o=[],t=e.map(s=>typeof s=="object"?s.key:s);for(const s of t)typeof s=="number"?o.push(`[${s}]`):typeof s=="symbol"?o.push(`[${JSON.stringify(String(s))}]`):/[^\w$]/.test(s)?o.push(`[${JSON.stringify(s)}]`):(o.length&&o.push("."),o.push(s));return o.join("")}function $c(e){const o=[],t=[...e.issues].sort((s,r)=>(s.path??[]).length-(r.path??[]).length);for(const s of t)o.push(`✖ ${s.message}`),s.path?.length&&o.push(` → at ${Ec(s.path)}`);return o.join(`
2
  `)}const Ks=e=>(o,t,s,r)=>{const c=s?{...s,async:!1}:{async:!1},l=o._zod.run({value:t,issues:[]},c);if(l instanceof Promise)throw new vt;if(l.issues.length){const m=new(r?.Err??e)(l.issues.map(g=>Ge(g,c,Ve())));throw An(m,r?.callee),m}return l.value},Hs=e=>async(o,t,s,r)=>{const c=s?{...s,async:!0}:{async:!0};let l=o._zod.run({value:t,issues:[]},c);if(l instanceof Promise&&(l=await l),l.issues.length){const m=new(r?.Err??e)(l.issues.map(g=>Ge(g,c,Ve())));throw An(m,r?.callee),m}return l.value},xo=e=>(o,t,s)=>{const r=s?{...s,async:!1}:{async:!1},c=o._zod.run({value:t,issues:[]},r);if(c instanceof Promise)throw new vt;return c.issues.length?{success:!1,error:new(e??Io)(c.issues.map(l=>Ge(l,r,Ve())))}:{success:!0,data:c.value}},Tc=xo(Tn),Ao=e=>async(o,t,s)=>{const r=s?{...s,async:!0}:{async:!0};let c=o._zod.run({value:t,issues:[]},r);return c instanceof Promise&&(c=await c),c.issues.length?{success:!1,error:new e(c.issues.map(l=>Ge(l,r,Ve())))}:{success:!0,data:c.value}},Xc=Ao(Tn),Lc=e=>(o,t,s)=>{const r=s?{...s,direction:"backward"}:{direction:"backward"};return Ks(e)(o,t,r)},Uc=e=>(o,t,s)=>Ks(e)(o,t,s),Mc=e=>async(o,t,s)=>{const r=s?{...s,direction:"backward"}:{direction:"backward"};return Hs(e)(o,t,r)},Dc=e=>async(o,t,s)=>Hs(e)(o,t,s),Oc=e=>(o,t,s)=>{const r=s?{...s,direction:"backward"}:{direction:"backward"};return xo(e)(o,t,r)},Fc=e=>(o,t,s)=>xo(e)(o,t,s),jc=e=>async(o,t,s)=>{const r=s?{...s,direction:"backward"}:{direction:"backward"};return Ao(e)(o,t,r)},Pc=e=>async(o,t,s)=>Ao(e)(o,t,s),Nc=/^[cC][0-9a-z]{6,}$/,zc=/^[0-9a-z]+$/,Kc=/^[0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{26}$/,Hc=/^[0-9a-vA-V]{20}$/,Zc=/^[A-Za-z0-9]{27}$/,Wc=/^[a-zA-Z0-9_-]{21}$/,Vc=/^P(?:(\d+W)|(?!.*W)(?=\d|T\d)(\d+Y)?(\d+M)?(\d+D)?(T(?=\d)(\d+H)?(\d+M)?(\d+([.,]\d+)?S)?)?)$/,Gc=/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/,Ur=e=>e?new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${e}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`):/^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/,Jc=/^(?!\.)(?!.*\.\.)([A-Za-z0-9_'+\-\.]*)[A-Za-z0-9_+-]@([A-Za-z0-9][A-Za-z0-9\-]*\.)+[A-Za-z]{2,}$/,Bc="^(\\p{Extended_Pictographic}|\\p{Emoji_Component})+$";function Yc(){return new RegExp(Bc,"u")}const Qc=/^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/,ed=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/,td=/^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\/([0-9]|[1-2][0-9]|3[0-2])$/,od=/^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|::|([0-9a-fA-F]{1,4})?::([0-9a-fA-F]{1,4}:?){0,6})\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/,sd=/^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/,Xn=/^[A-Za-z0-9_-]*$/,rd=/^https?$/,nd=/^\+[1-9]\d{6,14}$/,Ln="(?:(?:\\d\\d[2468][048]|\\d\\d[13579][26]|\\d\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\d|30)|(?:02)-(?:0[1-9]|1\\d|2[0-8])))",ad=new RegExp(`^${Ln}$`);function Un(e){const o="(?:[01]\\d|2[0-3]):[0-5]\\d";return typeof e.precision=="number"?e.precision===-1?`${o}`:e.precision===0?`${o}:[0-5]\\d`:`${o}:[0-5]\\d\\.\\d{${e.precision}}`:`${o}(?::[0-5]\\d(?:\\.\\d+)?)?`}function id(e){return new RegExp(`^${Un(e)}$`)}function ud(e){const o=Un({precision:e.precision}),t=["Z"];e.local&&t.push(""),e.offset&&t.push("([+-](?:[01]\\d|2[0-3]):[0-5]\\d)");const s=`${o}(?:${t.join("|")})`;return new RegExp(`^${Ln}T(?:${s})$`)}const cd=e=>{const o=e?`[\\s\\S]{${e?.minimum??0},${e?.maximum??""}}`:"[\\s\\S]*";return new RegExp(`^${o}$`)},dd=/^-?\d+$/,Mn=/^-?\d+(?:\.\d+)?$/,ld=/^(?:true|false)$/i,pd=/^[^A-Z]*$/,fd=/^[^a-z]*$/,Me=H("$ZodCheck",(e,o)=>{var t;e._zod??(e._zod={}),e._zod.def=o,(t=e._zod).onattach??(t.onattach=[])}),Dn={number:"number",bigint:"bigint",object:"date"},On=H("$ZodCheckLessThan",(e,o)=>{Me.init(e,o);const t=Dn[typeof o.value];e._zod.onattach.push(s=>{const r=s._zod.bag,c=(o.inclusive?r.maximum:r.exclusiveMaximum)??Number.POSITIVE_INFINITY;o.value<c&&(o.inclusive?r.maximum=o.value:r.exclusiveMaximum=o.value)}),e._zod.check=s=>{(o.inclusive?s.value<=o.value:s.value<o.value)||s.issues.push({origin:t,code:"too_big",maximum:typeof o.value=="object"?o.value.getTime():o.value,input:s.value,inclusive:o.inclusive,inst:e,continue:!o.abort})}}),Fn=H("$ZodCheckGreaterThan",(e,o)=>{Me.init(e,o);const t=Dn[typeof o.value];e._zod.onattach.push(s=>{const r=s._zod.bag,c=(o.inclusive?r.minimum:r.exclusiveMinimum)??Number.NEGATIVE_INFINITY;o.value>c&&(o.inclusive?r.minimum=o.value:r.exclusiveMinimum=o.value)}),e._zod.check=s=>{(o.inclusive?s.value>=o.value:s.value>o.value)||s.issues.push({origin:t,code:"too_small",minimum:typeof o.value=="object"?o.value.getTime():o.value,input:s.value,inclusive:o.inclusive,inst:e,continue:!o.abort})}}),_d=H("$ZodCheckMultipleOf",(e,o)=>{Me.init(e,o),e._zod.onattach.push(t=>{var s;(s=t._zod.bag).multipleOf??(s.multipleOf=o.value)}),e._zod.check=t=>{if(typeof t.value!=typeof o.value)throw new Error("Cannot mix number and bigint in multiple_of check.");(typeof t.value=="bigint"?t.value%o.value===BigInt(0):_c(t.value,o.value)===0)||t.issues.push({origin:typeof t.value,code:"not_multiple_of",divisor:o.value,input:t.value,inst:e,continue:!o.abort})}}),md=H("$ZodCheckNumberFormat",(e,o)=>{Me.init(e,o),o.format=o.format||"float64";const t=o.format?.includes("int"),s=t?"int":"number",[r,c]=vc[o.format];e._zod.onattach.push(l=>{const m=l._zod.bag;m.format=o.format,m.minimum=r,m.maximum=c,t&&(m.pattern=dd)}),e._zod.check=l=>{const m=l.value;if(t){if(!Number.isInteger(m)){l.issues.push({expected:s,format:o.format,code:"invalid_type",continue:!1,input:m,inst:e});return}if(!Number.isSafeInteger(m)){m>0?l.issues.push({input:m,code:"too_big",maximum:Number.MAX_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:e,origin:s,inclusive:!0,continue:!o.abort}):l.issues.push({input:m,code:"too_small",minimum:Number.MIN_SAFE_INTEGER,note:"Integers must be within the safe integer range.",inst:e,origin:s,inclusive:!0,continue:!o.abort});return}}m<r&&l.issues.push({origin:"number",input:m,code:"too_small",minimum:r,inclusive:!0,inst:e,continue:!o.abort}),m>c&&l.issues.push({origin:"number",input:m,code:"too_big",maximum:c,inclusive:!0,inst:e,continue:!o.abort})}}),yd=H("$ZodCheckMaxLength",(e,o)=>{var t;Me.init(e,o),(t=e._zod.def).when??(t.when=s=>{const r=s.value;return!Ps(r)&&r.length!==void 0}),e._zod.onattach.push(s=>{const r=s._zod.bag.maximum??Number.POSITIVE_INFINITY;o.maximum<r&&(s._zod.bag.maximum=o.maximum)}),e._zod.check=s=>{const r=s.value;if(r.length<=o.maximum)return;const l=zs(r);s.issues.push({origin:l,code:"too_big",maximum:o.maximum,inclusive:!0,input:r,inst:e,continue:!o.abort})}}),hd=H("$ZodCheckMinLength",(e,o)=>{var t;Me.init(e,o),(t=e._zod.def).when??(t.when=s=>{const r=s.value;return!Ps(r)&&r.length!==void 0}),e._zod.onattach.push(s=>{const r=s._zod.bag.minimum??Number.NEGATIVE_INFINITY;o.minimum>r&&(s._zod.bag.minimum=o.minimum)}),e._zod.check=s=>{const r=s.value;if(r.length>=o.minimum)return;const l=zs(r);s.issues.push({origin:l,code:"too_small",minimum:o.minimum,inclusive:!0,input:r,inst:e,continue:!o.abort})}}),gd=H("$ZodCheckLengthEquals",(e,o)=>{var t;Me.init(e,o),(t=e._zod.def).when??(t.when=s=>{const r=s.value;return!Ps(r)&&r.length!==void 0}),e._zod.onattach.push(s=>{const r=s._zod.bag;r.minimum=o.length,r.maximum=o.length,r.length=o.length}),e._zod.check=s=>{const r=s.value,c=r.length;if(c===o.length)return;const l=zs(r),m=c>o.length;s.issues.push({origin:l,...m?{code:"too_big",maximum:o.length}:{code:"too_small",minimum:o.length},inclusive:!0,exact:!0,input:s.value,inst:e,continue:!o.abort})}}),Eo=H("$ZodCheckStringFormat",(e,o)=>{var t,s;Me.init(e,o),e._zod.onattach.push(r=>{const c=r._zod.bag;c.format=o.format,o.pattern&&(c.patterns??(c.patterns=new Set),c.patterns.add(o.pattern))}),o.pattern?(t=e._zod).check??(t.check=r=>{o.pattern.lastIndex=0,!o.pattern.test(r.value)&&r.issues.push({origin:"string",code:"invalid_format",format:o.format,input:r.value,...o.pattern?{pattern:o.pattern.toString()}:{},inst:e,continue:!o.abort})}):(s=e._zod).check??(s.check=()=>{})}),vd=H("$ZodCheckRegex",(e,o)=>{Eo.init(e,o),e._zod.check=t=>{o.pattern.lastIndex=0,!o.pattern.test(t.value)&&t.issues.push({origin:"string",code:"invalid_format",format:"regex",input:t.value,pattern:o.pattern.toString(),inst:e,continue:!o.abort})}}),bd=H("$ZodCheckLowerCase",(e,o)=>{o.pattern??(o.pattern=pd),Eo.init(e,o)}),wd=H("$ZodCheckUpperCase",(e,o)=>{o.pattern??(o.pattern=fd),Eo.init(e,o)}),Cd=H("$ZodCheckIncludes",(e,o)=>{Me.init(e,o);const t=wt(o.includes),s=new RegExp(typeof o.position=="number"?`^.{${o.position}}${t}`:t);o.pattern=s,e._zod.onattach.push(r=>{const c=r._zod.bag;c.patterns??(c.patterns=new Set),c.patterns.add(s)}),e._zod.check=r=>{r.value.includes(o.includes,o.position)||r.issues.push({origin:"string",code:"invalid_format",format:"includes",includes:o.includes,input:r.value,inst:e,continue:!o.abort})}}),Rd=H("$ZodCheckStartsWith",(e,o)=>{Me.init(e,o);const t=new RegExp(`^${wt(o.prefix)}.*`);o.pattern??(o.pattern=t),e._zod.onattach.push(s=>{const r=s._zod.bag;r.patterns??(r.patterns=new Set),r.patterns.add(t)}),e._zod.check=s=>{s.value.startsWith(o.prefix)||s.issues.push({origin:"string",code:"invalid_format",format:"starts_with",prefix:o.prefix,input:s.value,inst:e,continue:!o.abort})}}),Sd=H("$ZodCheckEndsWith",(e,o)=>{Me.init(e,o);const t=new RegExp(`.*${wt(o.suffix)}$`);o.pattern??(o.pattern=t),e._zod.onattach.push(s=>{const r=s._zod.bag;r.patterns??(r.patterns=new Set),r.patterns.add(t)}),e._zod.check=s=>{s.value.endsWith(o.suffix)||s.issues.push({origin:"string",code:"invalid_format",format:"ends_with",suffix:o.suffix,input:s.value,inst:e,continue:!o.abort})}}),kd=H("$ZodCheckOverwrite",(e,o)=>{Me.init(e,o),e._zod.check=t=>{t.value=o.tx(t.value)}});class qd{constructor(o=[]){this.content=[],this.indent=0,this&&(this.args=o)}indented(o){this.indent+=1,o(this),this.indent-=1}write(o){if(typeof o=="function"){o(this,{execution:"sync"}),o(this,{execution:"async"});return}const s=o.split(`
3
  `).filter(l=>l),r=Math.min(...s.map(l=>l.length-l.trimStart().length)),c=s.map(l=>l.slice(r)).map(l=>" ".repeat(this.indent*2)+l);for(const l of c)this.content.push(l)}compile(){const o=Function,t=this?.args,r=[...(this?.content??[""]).map(c=>` ${c}`)];return new o(...t,r.join(`
4
  `))}}const Id={major:4,minor:4,patch:3},le=H("$ZodType",(e,o)=>{var t;e??(e={}),e._zod.def=o,e._zod.bag=e._zod.bag||{},e._zod.version=Id;const s=[...e._zod.def.checks??[]];e._zod.traits.has("$ZodCheck")&&s.unshift(e);for(const r of s)for(const c of r._zod.onattach)c(e);if(s.length===0)(t=e._zod).deferred??(t.deferred=[]),e._zod.deferred?.push(()=>{e._zod.run=e._zod.parse});else{const r=(l,m,g)=>{let y=ht(l),b;for(const _ of m){if(_._zod.def.when){if(Ic(l)||!_._zod.def.when(l))continue}else if(y)continue;const i=l.issues.length,u=_._zod.check(l);if(u instanceof Promise&&g?.async===!1)throw new vt;if(b||u instanceof Promise)b=(b??Promise.resolve()).then(async()=>{await u,l.issues.length!==i&&(y||(y=ht(l,i)))});else{if(l.issues.length===i)continue;y||(y=ht(l,i))}}return b?b.then(()=>l):l},c=(l,m,g)=>{if(ht(l))return l.aborted=!0,l;const y=r(m,s,g);if(y instanceof Promise){if(g.async===!1)throw new vt;return y.then(b=>e._zod.parse(b,g))}return e._zod.parse(y,g)};e._zod.run=(l,m)=>{if(m.skipChecks)return e._zod.parse(l,m);if(m.direction==="backward"){const y=e._zod.parse({value:l.value,issues:[]},{...m,skipChecks:!0});return y instanceof Promise?y.then(b=>c(b,l,m)):c(y,l,m)}const g=e._zod.parse(l,m);if(g instanceof Promise){if(m.async===!1)throw new vt;return g.then(y=>r(y,s,m))}return r(g,s,m)}}ne(e,"~standard",()=>({validate:r=>{try{const c=Tc(e,r);return c.success?{value:c.data}:{issues:c.error?.issues}}catch{return Xc(e,r).then(l=>l.success?{value:l.data}:{issues:l.error?.issues})}},vendor:"zod",version:1}))}),Zs=H("$ZodString",(e,o)=>{le.init(e,o),e._zod.pattern=[...e?._zod.bag?.patterns??[]].pop()??cd(e._zod.bag),e._zod.parse=(t,s)=>{if(o.coerce)try{t.value=String(t.value)}catch{}return typeof t.value=="string"||t.issues.push({expected:"string",code:"invalid_type",input:t.value,inst:e}),t}}),_e=H("$ZodStringFormat",(e,o)=>{Eo.init(e,o),Zs.init(e,o)}),xd=H("$ZodGUID",(e,o)=>{o.pattern??(o.pattern=Gc),_e.init(e,o)}),Ad=H("$ZodUUID",(e,o)=>{if(o.version){const s={v1:1,v2:2,v3:3,v4:4,v5:5,v6:6,v7:7,v8:8}[o.version];if(s===void 0)throw new Error(`Invalid UUID version: "${o.version}"`);o.pattern??(o.pattern=Ur(s))}else o.pattern??(o.pattern=Ur());_e.init(e,o)}),Ed=H("$ZodEmail",(e,o)=>{o.pattern??(o.pattern=Jc),_e.init(e,o)}),$d=H("$ZodURL",(e,o)=>{_e.init(e,o),e._zod.check=t=>{try{const s=t.value.trim();if(!o.normalize&&o.protocol?.source===rd.source&&!/^https?:\/\//i.test(s)){t.issues.push({code:"invalid_format",format:"url",note:"Invalid URL format",input:t.value,inst:e,continue:!o.abort});return}const r=new URL(s);o.hostname&&(o.hostname.lastIndex=0,o.hostname.test(r.hostname)||t.issues.push({code:"invalid_format",format:"url",note:"Invalid hostname",pattern:o.hostname.source,input:t.value,inst:e,continue:!o.abort})),o.protocol&&(o.protocol.lastIndex=0,o.protocol.test(r.protocol.endsWith(":")?r.protocol.slice(0,-1):r.protocol)||t.issues.push({code:"invalid_format",format:"url",note:"Invalid protocol",pattern:o.protocol.source,input:t.value,inst:e,continue:!o.abort})),o.normalize?t.value=r.href:t.value=s;return}catch{t.issues.push({code:"invalid_format",format:"url",input:t.value,inst:e,continue:!o.abort})}}}),Td=H("$ZodEmoji",(e,o)=>{o.pattern??(o.pattern=Yc()),_e.init(e,o)}),Xd=H("$ZodNanoID",(e,o)=>{o.pattern??(o.pattern=Wc),_e.init(e,o)}),Ld=H("$ZodCUID",(e,o)=>{o.pattern??(o.pattern=Nc),_e.init(e,o)}),Ud=H("$ZodCUID2",(e,o)=>{o.pattern??(o.pattern=zc),_e.init(e,o)}),Md=H("$ZodULID",(e,o)=>{o.pattern??(o.pattern=Kc),_e.init(e,o)}),Dd=H("$ZodXID",(e,o)=>{o.pattern??(o.pattern=Hc),_e.init(e,o)}),Od=H("$ZodKSUID",(e,o)=>{o.pattern??(o.pattern=Zc),_e.init(e,o)}),Fd=H("$ZodISODateTime",(e,o)=>{o.pattern??(o.pattern=ud(o)),_e.init(e,o)}),jd=H("$ZodISODate",(e,o)=>{o.pattern??(o.pattern=ad),_e.init(e,o)}),Pd=H("$ZodISOTime",(e,o)=>{o.pattern??(o.pattern=id(o)),_e.init(e,o)}),Nd=H("$ZodISODuration",(e,o)=>{o.pattern??(o.pattern=Vc),_e.init(e,o)}),zd=H("$ZodIPv4",(e,o)=>{o.pattern??(o.pattern=Qc),_e.init(e,o),e._zod.bag.format="ipv4"}),Kd=H("$ZodIPv6",(e,o)=>{o.pattern??(o.pattern=ed),_e.init(e,o),e._zod.bag.format="ipv6",e._zod.check=t=>{try{new URL(`http://[${t.value}]`)}catch{t.issues.push({code:"invalid_format",format:"ipv6",input:t.value,inst:e,continue:!o.abort})}}}),Hd=H("$ZodCIDRv4",(e,o)=>{o.pattern??(o.pattern=td),_e.init(e,o)}),Zd=H("$ZodCIDRv6",(e,o)=>{o.pattern??(o.pattern=od),_e.init(e,o),e._zod.check=t=>{const s=t.value.split("/");try{if(s.length!==2)throw new Error;const[r,c]=s;if(!c)throw new Error;const l=Number(c);if(`${l}`!==c)throw new Error;if(l<0||l>128)throw new Error;new URL(`http://[${r}]`)}catch{t.issues.push({code:"invalid_format",format:"cidrv6",input:t.value,inst:e,continue:!o.abort})}}});function jn(e){if(e==="")return!0;if(/\s/.test(e)||e.length%4!==0)return!1;try{return atob(e),!0}catch{return!1}}const Wd=H("$ZodBase64",(e,o)=>{o.pattern??(o.pattern=sd),_e.init(e,o),e._zod.bag.contentEncoding="base64",e._zod.check=t=>{jn(t.value)||t.issues.push({code:"invalid_format",format:"base64",input:t.value,inst:e,continue:!o.abort})}});function Vd(e){if(!Xn.test(e))return!1;const o=e.replace(/[-_]/g,s=>s==="-"?"+":"/"),t=o.padEnd(Math.ceil(o.length/4)*4,"=");return jn(t)}const Gd=H("$ZodBase64URL",(e,o)=>{o.pattern??(o.pattern=Xn),_e.init(e,o),e._zod.bag.contentEncoding="base64url",e._zod.check=t=>{Vd(t.value)||t.issues.push({code:"invalid_format",format:"base64url",input:t.value,inst:e,continue:!o.abort})}}),Jd=H("$ZodE164",(e,o)=>{o.pattern??(o.pattern=nd),_e.init(e,o)});function Bd(e,o=null){try{const t=e.split(".");if(t.length!==3)return!1;const[s]=t;if(!s)return!1;const r=JSON.parse(atob(s));return!("typ"in r&&r?.typ!=="JWT"||!r.alg||o&&(!("alg"in r)||r.alg!==o))}catch{return!1}}const Yd=H("$ZodJWT",(e,o)=>{_e.init(e,o),e._zod.check=t=>{Bd(t.value,o.alg)||t.issues.push({code:"invalid_format",format:"jwt",input:t.value,inst:e,continue:!o.abort})}}),Pn=H("$ZodNumber",(e,o)=>{le.init(e,o),e._zod.pattern=e._zod.bag.pattern??Mn,e._zod.parse=(t,s)=>{if(o.coerce)try{t.value=Number(t.value)}catch{}const r=t.value;if(typeof r=="number"&&!Number.isNaN(r)&&Number.isFinite(r))return t;const c=typeof r=="number"?Number.isNaN(r)?"NaN":Number.isFinite(r)?void 0:"Infinity":void 0;return t.issues.push({expected:"number",code:"invalid_type",input:r,inst:e,...c?{received:c}:{}}),t}}),Qd=H("$ZodNumberFormat",(e,o)=>{md.init(e,o),Pn.init(e,o)}),el=H("$ZodBoolean",(e,o)=>{le.init(e,o),e._zod.pattern=ld,e._zod.parse=(t,s)=>{if(o.coerce)try{t.value=!!t.value}catch{}const r=t.value;return typeof r=="boolean"||t.issues.push({expected:"boolean",code:"invalid_type",input:r,inst:e}),t}}),tl=H("$ZodAny",(e,o)=>{le.init(e,o),e._zod.parse=t=>t}),ol=H("$ZodUnknown",(e,o)=>{le.init(e,o),e._zod.parse=t=>t}),sl=H("$ZodNever",(e,o)=>{le.init(e,o),e._zod.parse=(t,s)=>(t.issues.push({expected:"never",code:"invalid_type",input:t.value,inst:e}),t)}),rl=H("$ZodVoid",(e,o)=>{le.init(e,o),e._zod.parse=(t,s)=>{const r=t.value;return typeof r>"u"||t.issues.push({expected:"void",code:"invalid_type",input:r,inst:e}),t}}),nl=H("$ZodDate",(e,o)=>{le.init(e,o),e._zod.parse=(t,s)=>{if(o.coerce)try{t.value=new Date(t.value)}catch{}const r=t.value,c=r instanceof Date;return c&&!Number.isNaN(r.getTime())||t.issues.push({expected:"date",code:"invalid_type",input:r,...c?{received:"Invalid Date"}:{},inst:e}),t}});function Mr(e,o,t){e.issues.length&&o.issues.push(...gt(t,e.issues)),o.value[t]=e.value}const al=H("$ZodArray",(e,o)=>{le.init(e,o),e._zod.parse=(t,s)=>{const r=t.value;if(!Array.isArray(r))return t.issues.push({expected:"array",code:"invalid_type",input:r,inst:e}),t;t.value=Array(r.length);const c=[];for(let l=0;l<r.length;l++){const m=r[l],g=o.element._zod.run({value:m,issues:[]},s);g instanceof Promise?c.push(g.then(y=>Mr(y,t,l))):Mr(g,t,l)}return c.length?Promise.all(c).then(()=>t):t}});function mo(e,o,t,s,r,c){const l=t in s;if(e.issues.length){if(r&&c&&!l)return;o.issues.push(...gt(t,e.issues))}if(!l&&!r){e.issues.length||o.issues.push({code:"invalid_type",expected:"nonoptional",input:void 0,path:[t]});return}e.value===void 0?l&&(o.value[t]=void 0):o.value[t]=e.value}function Nn(e){const o=Object.keys(e.shape);for(const s of o)if(!e.shape?.[s]?._zod?.traits?.has("$ZodType"))throw new Error(`Invalid element at key "${s}": expected a Zod schema`);const t=gc(e.shape);return{...e,keys:o,keySet:new Set(o),numKeys:o.length,optionalKeys:new Set(t)}}function zn(e,o,t,s,r,c){const l=[],m=r.keySet,g=r.catchall._zod,y=g.def.type,b=g.optin==="optional",_=g.optout==="optional";for(const i in o){if(i==="__proto__"||m.has(i))continue;if(y==="never"){l.push(i);continue}const u=g.run({value:o[i],issues:[]},s);u instanceof Promise?e.push(u.then(a=>mo(a,t,i,o,b,_))):mo(u,t,i,o,b,_)}return l.length&&t.issues.push({code:"unrecognized_keys",keys:l,input:o,inst:c}),e.length?Promise.all(e).then(()=>t):t}const il=H("$ZodObject",(e,o)=>{if(le.init(e,o),!Object.getOwnPropertyDescriptor(o,"shape")?.get){const m=o.shape;Object.defineProperty(o,"shape",{get:()=>{const g={...m};return Object.defineProperty(o,"shape",{value:g}),g}})}const s=js(()=>Nn(o));ne(e._zod,"propValues",()=>{const m=o.shape,g={};for(const y in m){const b=m[y]._zod;if(b.values){g[y]??(g[y]=new Set);for(const _ of b.values)g[y].add(_)}}return g});const r=_o,c=o.catchall;let l;e._zod.parse=(m,g)=>{l??(l=s.value);const y=m.value;if(!r(y))return m.issues.push({expected:"object",code:"invalid_type",input:y,inst:e}),m;m.value={};const b=[],_=l.shape;for(const i of l.keys){const u=_[i],a=u._zod.optin==="optional",p=u._zod.optout==="optional",f=u._zod.run({value:y[i],issues:[]},g);f instanceof Promise?b.push(f.then(w=>mo(w,m,i,y,a,p))):mo(f,m,i,y,a,p)}return c?zn(b,y,m,g,s.value,e):b.length?Promise.all(b).then(()=>m):m}}),ul=H("$ZodObjectJIT",(e,o)=>{il.init(e,o);const t=e._zod.parse,s=js(()=>Nn(o)),r=i=>{const u=new qd(["shape","payload","ctx"]),a=s.value,p=C=>{const P=Lr(C);return`shape[${P}]._zod.run({ value: input[${P}], issues: [] }, ctx)`};u.write("const input = payload.value;");const f=Object.create(null);let w=0;for(const C of a.keys)f[C]=`key_${w++}`;u.write("const newResult = {};");for(const C of a.keys){const P=f[C],ie=Lr(C),se=i[C],ve=se?._zod?.optin==="optional",De=se?._zod?.optout==="optional";u.write(`const ${P} = ${p(C)};`),ve&&De?u.write(`
dist/assets/openai-codex-responses-7plNQja4.js ADDED
@@ -0,0 +1,7 @@
 
 
 
 
 
 
 
 
1
+ import{A as ue,g as Y,a as le}from"./index-CB_zB4U3.js";import{h as z}from"./headers-CgnjaPPL.js";import{c as de}from"./openai-prompt-cache-h_V5PL7P.js";import{c as V,a as fe,p as G}from"./openai-responses-shared-DBUlz2NN.js";import{b as pe}from"./transform-messages-DSNYjDRn.js";import"./hash-DMDecQcg.js";import"./json-parse-cUk3uCki.js";import"./sanitize-unicode-B62XMGgN.js";const $=new Set;function me(e){return $.add(e),()=>{$.delete(e)}}function L(e){return e instanceof Error?e.message||e.name:typeof e=="string"?e:String(e)}function ye(e){if(!(e instanceof Error))return{name:"ThrownValue",message:L(e)};const r=e.code;return{name:e.name||void 0,message:e.message||e.name,stack:e.stack,code:typeof r=="string"||typeof r=="number"?r:void 0}}function be(e,r,t){return{type:e,timestamp:Date.now(),error:ye(r),details:t}}function we(e,r){e.diagnostics=[...e.diagnostics??[],r]}function ge(e){const r=e.filter(o=>o!==void 0);if(r.length===0)return{cleanup:()=>{}};if(r.length===1)return{signal:r[0],cleanup:()=>{}};const t=new AbortController,s=[],n=o=>{t.signal.aborted||t.abort(o.reason)};for(const o of r){if(o.aborted){n(o);break}const a=()=>n(o);o.addEventListener("abort",a,{once:!0}),s.push({signal:o,listener:a})}return{signal:t.signal,cleanup:()=>{for(const{signal:o,listener:a}of s)o.removeEventListener("abort",a)}}}var A={},he=function(e,r){return typeof e=="string"&&/^\.\.?\//.test(e)?e.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i,function(t,s,n,o,a){return s?".js":n&&(!o||!a)?t:n+o+"."+a.toLowerCase()+"js"}):e};let x=null;const Q=e=>import(he(e)),Ee="node:os";typeof process<"u"&&(process.versions?.node||process.versions?.bun)&&Q(Ee).then(e=>{x=e});const Se="https://chatgpt.com/backend-api",ve="https://api.openai.com/auth",ke=0,F=1e3,_e=6e4,U=1e4,Te=15e3,Z=new Set(["openai","openai-codex","opencode"]),xe=1009,Re=new Set(["completed","incomplete","failed","cancelled","queued","in_progress"]);function Ce(e){return/GoUsageLimitError|FreeUsageLimitError|Monthly usage limit reached|available balance|insufficient_quota|out of budget|quota exceeded|billing/i.test(e)}function Ae(e,r){return e===429&&Ce(r)?!1:e===429||e===500||e===502||e===503||e===504?!0:/rate.?limit|overloaded|service.?unavailable|upstream.?connect|connection.?refused/i.test(r)}function Oe(e){const r=e.get("retry-after-ms");if(r!==null){const o=Number(r);if(Number.isFinite(o))return Math.max(0,o)}const t=e.get("retry-after");if(!t)return;const s=Number(t);if(Number.isFinite(s))return Math.max(0,s*1e3);const n=Date.parse(t);if(!Number.isNaN(n))return Math.max(0,n-Date.now())}function We(e,r){const t=r?.maxRetryDelayMs??_e;return t>0?Math.min(e,t):e}function J(e,r){return new Promise((t,s)=>{if(r?.aborted){s(new Error("Request was aborted"));return}const n=setTimeout(t,e);r?.addEventListener("abort",()=>{clearTimeout(n),s(new Error("Request was aborted"))})})}function H(e){if(e!==void 0){if(!Number.isFinite(e)||e<0)throw new Error(`Invalid timeoutMs: ${String(e)}`);return Math.floor(e)}}function Ie(){const e=new AbortController;let r;const t=setTimeout(()=>{r=new Error(`Codex SSE response headers timed out after ${U}ms`),e.abort(r)},U);return{signal:e.signal,clear:()=>clearTimeout(t),error:()=>r}}const Le=(e,r,t)=>{const s=new ue;return(async()=>{const n={role:"assistant",content:[],api:"openai-codex-responses",provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const o=t?.apiKey||Y(e.provider)||"";if(!o)throw new Error(`No API key for provider: ${e.provider}`);const a=st(o);let l=De(e,r,t);const i=await t?.onPayload?.(l,e);i!==void 0&&(l=i);const c=t?.sessionId||nt(),p=at(e.headers,t?.headers,a,o,t?.sessionId),h=it(e.headers,t?.headers,a,o,c),E=JSON.stringify(l),d=H(t?.timeoutMs),g=H(t?.websocketConnectTimeoutMs),m=t?.transport||"auto",y=m!=="sse"&&se(t?.sessionId);if(y&&K(t?.sessionId),m!=="sse"&&!y){let b=!1;try{if(await rt(qe(e.baseUrl),l,h,n,s,e,()=>{b=!0},d,g,t),t?.signal?.aborted)throw new Error("Request was aborted");s.push({type:"done",reason:n.stopReason,message:n}),s.end();return}catch(w){if(t?.signal?.aborted||Be(w)||(we(n,be("provider_transport_failure",w,{configuredTransport:m,fallbackTransport:b?void 0:"sse",eventsEmitted:b,phase:b?"after_message_stream_start":"before_message_stream_start",requestBytes:new TextEncoder().encode(E).byteLength})),He(t?.sessionId,w),b))throw w;K(t?.sessionId)}}let u,f;const v=t?.maxRetries??ke;for(let b=0;b<=v;b++){if(t?.signal?.aborted)throw new Error("Request was aborted");try{const w=Ie(),_=ge([t?.signal,w.signal]);try{u=await fetch(re(e.baseUrl),{method:"POST",headers:p,body:E,signal:_.signal})}catch(T){const C=w.error();throw C&&!t?.signal?.aborted?C:T}finally{_.cleanup(),w.clear()}if(await t?.onResponse?.({status:u.status,headers:z(u.headers)},e),u.ok)break;const B=await u.text();if(b<v&&Ae(u.status,B)){const T=Oe(u.headers),C=T===void 0?F*2**b:u.status===429?We(T,t):T;await J(C,t?.signal);continue}const ce=new Response(B,{status:u.status,statusText:u.statusText}),P=await ot(ce);throw new Error(P.friendlyMessage||P.message)}catch(w){if(w instanceof Error&&(w.name==="AbortError"||w.message==="Request was aborted"))throw new Error("Request was aborted");if(f=w instanceof Error?w:new Error(String(w)),b<v&&!f.message.includes("usage limit")){const _=F*2**b;await J(_,t?.signal);continue}throw f}}if(!u?.ok)throw f??new Error("Failed after retries");if(!u.body)throw new Error("No response body");if(s.push({type:"start",partial:n}),await Ne(u,n,s,e,t),t?.signal?.aborted)throw new Error("Request was aborted");s.push({type:"done",reason:n.stopReason,message:n}),s.end()}catch(o){for(const a of n.content)delete a.partialJson;n.stopReason=t?.signal?.aborted?"aborted":"error",n.errorMessage=o instanceof Error?o.message:String(o),s.push({type:"error",reason:n.stopReason,error:n}),s.end()}})(),s},bt=(e,r,t)=>{const s=t?.apiKey||Y(e.provider);if(!s)throw new Error(`No API key for provider: ${e.provider}`);const n=pe(e,t,s),o=t?.reasoning?le(e,t.reasoning):void 0;return Le(e,r,{...n,reasoningEffort:o==="off"?void 0:o})};function De(e,r,t){const s=V(e,r,Z,{includeSystemPrompt:!1}),n={model:e.id,store:!1,stream:!0,instructions:r.systemPrompt||"You are a helpful assistant.",input:s,text:{verbosity:t?.textVerbosity||"low"},include:["reasoning.encrypted_content"],prompt_cache_key:de(t?.sessionId),tool_choice:"auto",parallel_tool_calls:!0};if(t?.temperature!==void 0&&(n.temperature=t.temperature),t?.serviceTier!==void 0&&(n.service_tier=t.serviceTier),r.tools&&r.tools.length>0&&(n.tools=fe(r.tools,{strict:null})),t?.reasoningEffort!==void 0){const o=t.reasoningEffort==="none"?e.thinkingLevelMap?.off??"none":e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort;o!==null&&(n.reasoning={effort:o,summary:t.reasoningSummary??"auto"})}return n}function Me(e,r){switch(r){case"flex":return .5;case"priority":return e.id==="gpt-5.5"?2.5:2;default:return 1}}function ee(e,r,t){const s=Me(t,r);s!==1&&(e.cost.input*=s,e.cost.output*=s,e.cost.cacheRead*=s,e.cost.cacheWrite*=s,e.cost.total=e.cost.input+e.cost.output+e.cost.cacheRead+e.cost.cacheWrite)}function te(e,r){return e==="default"&&(r==="flex"||r==="priority")?r:e??r}function re(e){const t=(e&&e.trim().length>0?e:Se).replace(/\/+$/,"");return t.endsWith("/codex/responses")?t:t.endsWith("/codex")?`${t}/responses`:`${t}/codex/responses`}function qe(e){const r=new URL(re(e));return r.protocol==="https:"&&(r.protocol="wss:"),r.protocol==="http:"&&(r.protocol="ws:"),r.toString()}async function Ne(e,r,t,s,n){await G(oe($e(e)),r,t,s,{serviceTier:n?.serviceTier,resolveServiceTier:te,applyServiceTierPricing:(o,a)=>ee(o,a,s)})}class M extends Error{code;payload;constructor(r,t){super(r),this.name="CodexApiError",this.code=t?.code,this.payload=t?.payload,this.cause=t?.cause}}class q extends Error{payload;constructor(r,t){super(r),this.name="CodexProtocolError",this.payload=t?.payload,this.cause=t?.cause}}function Be(e){return e instanceof M||e instanceof q}async function*oe(e){for await(const r of e){const t=typeof r.type=="string"?r.type:void 0;if(t){if(t==="error"){const s=r.code||"",n=r.message||"";throw new M(`Codex error: ${n||s||JSON.stringify(r)}`,{code:s||void 0,payload:r})}if(t==="response.failed"){const s=r.response,n=s?.error?.code,o=s?.error?.message;throw new M(o||"Codex response failed",{code:n,payload:r})}if(t==="response.done"||t==="response.completed"||t==="response.incomplete"){const s=r.response,n=s&&{...s,status:Pe(s.status)};yield{...r,type:"response.completed",response:n};return}yield r}}}function Pe(e){if(typeof e=="string")return Re.has(e)?e:void 0}async function*$e(e){if(!e.body)return;const r=e.body.getReader(),t=new TextDecoder;let s="";try{for(;;){const{done:n,value:o}=await r.read();if(n)break;s+=t.decode(o,{stream:!0});let a=s.indexOf(`
2
+
3
+ `);for(;a!==-1;){const l=s.slice(0,a);s=s.slice(a+2);const i=l.split(`
4
+ `).filter(c=>c.startsWith("data:")).map(c=>c.slice(5).trim());if(i.length>0){const c=i.join(`
5
+ `).trim();if(c&&c!=="[DONE]")try{yield JSON.parse(c)}catch(p){throw new q(`Invalid Codex SSE JSON: ${L(p)}`,{cause:p,payload:c})}}a=s.indexOf(`
6
+
7
+ `)}}}finally{try{await r.cancel()}catch{}try{r.releaseLock()}catch{}}}const Fe="responses_websockets=2026-02-06",Ue=300*1e3,S=new Map,R=new Map,I=new Set;function N(e){let r=R.get(e);return r||(r={requests:0,connectionsCreated:0,connectionsReused:0,cachedContextRequests:0,storeTrueRequests:0,fullContextRequests:0,deltaRequests:0,lastInputItems:0,websocketFailures:0,sseFallbacks:0},R.set(e,r)),r}function wt(e){const r=R.get(e);return r?{...r}:void 0}function gt(e){if(e){R.delete(e),I.delete(e);return}R.clear(),I.clear()}function Je(e){const r=t=>{t.idleTimer&&clearTimeout(t.idleTimer),k(t.socket,1e3,"debug_close")};if(e){const t=S.get(e);t&&r(t),S.delete(e);return}for(const t of S.values())r(t);S.clear()}me(Je);function se(e){return e?I.has(e):!1}function K(e){if(!e)return;const r=N(e);r.sseFallbacks++,r.websocketFallbackActive=se(e)}function He(e,r){if(!e)return;I.add(e);const t=N(e);t.websocketFailures++,t.lastWebSocketError=L(r),t.websocketFallbackActive=!0}let O=null;async function Ke(){if(O)return O;if(process?.versions?.bun&&(A.HTTP_PROXY||A.HTTPS_PROXY||A.http_proxy||A.https_proxy)){const t=(await Q("proxy-from-env")).getProxyForUrl;return O=class extends WebSocket{constructor(s,n){let o={};Array.isArray(n)||typeof n=="string"?o={protocols:n}:o={...n};const a=t(s.toString().replace(/^wss:/,"https:").replace(/^ws:/,"http:"));super(s,{...o,...a?{proxy:a}:{}})}},O}const e=globalThis.WebSocket;return typeof e!="function"?null:e}class je extends Error{code;reason;wasClean;constructor(r,t){super(r),this.name="WebSocketCloseError",this.code=t?.code,this.reason=t?.reason,this.wasClean=t?.wasClean}}function Xe(e){const r=e.readyState;return typeof r=="number"?r:void 0}function W(e){const r=Xe(e);return r===void 0||r===1}function k(e,r=1e3,t="done"){try{e.close(r,t)}catch{}}function j(e,r){r.idleTimer&&clearTimeout(r.idleTimer),r.idleTimer=setTimeout(()=>{r.busy||(k(r.socket,1e3,"idle_timeout"),S.delete(e))},Ue)}async function D(e,r,t,s=Te){const n=await Ke();if(!n)throw new Error("WebSocket transport is not available in this runtime");const o=z(r);return delete o["OpenAI-Beta"],new Promise((a,l)=>{let i=!1,c,p;try{p=new n(e,{headers:o})}catch(u){l(u instanceof Error?u:new Error(String(u)));return}const h=()=>{c&&(clearTimeout(c),c=void 0),p.removeEventListener("open",d),p.removeEventListener("error",g),p.removeEventListener("close",m),t?.removeEventListener("abort",y)},E=(u,f)=>{i||(i=!0,h(),f&&k(p,1e3,f),l(u))},d=()=>{i||(i=!0,h(),a(p))},g=u=>{E(ne(u))},m=u=>{E(ae(u))},y=()=>{E(new Error("Request was aborted"),"aborted")};p.addEventListener("open",d),p.addEventListener("error",g),p.addEventListener("close",m),t?.addEventListener("abort",y),s>0&&(c=setTimeout(()=>{E(new Error(`WebSocket connect timeout after ${s}ms`),"connect_timeout")},s)),t?.aborted&&y()})}async function Ye(e,r,t,s,n){if(!t){const i=await D(e,r,s,n);return{socket:i,reused:!1,release:()=>k(i)}}const o=S.get(t);if(o){if(o.idleTimer&&(clearTimeout(o.idleTimer),o.idleTimer=void 0),!o.busy&&W(o.socket))return o.busy=!0,{socket:o.socket,entry:o,reused:!0,release:({keep:i}={})=>{if(!i||!W(o.socket)){k(o.socket),S.delete(t);return}o.busy=!1,j(t,o)}};if(o.busy){const i=await D(e,r,s,n);return{socket:i,reused:!1,release:()=>{k(i)}}}W(o.socket)||(k(o.socket),S.delete(t))}const a=await D(e,r,s,n),l={socket:a,busy:!0};return S.set(t,l),{socket:a,entry:l,reused:!1,release:({keep:i}={})=>{if(!i||!W(l.socket)){k(l.socket),l.idleTimer&&clearTimeout(l.idleTimer),S.get(t)===l&&S.delete(t);return}l.busy=!1,j(t,l)}}}function ne(e){if(e&&typeof e=="object"){const r="message"in e?e.message:void 0;if(typeof r=="string"&&r.length>0)return new Error(r);const t="error"in e?e.error:void 0;if(t instanceof Error&&t.message.length>0)return t;if(t&&typeof t=="object"&&"message"in t){const s=t.message;if(typeof s=="string"&&s.length>0)return new Error(s)}}return new Error("WebSocket error")}function ae(e){if(e&&typeof e=="object"){const r="code"in e?e.code:void 0,t="reason"in e?e.reason:void 0,s="wasClean"in e?e.wasClean:void 0,n=typeof r=="number"?` ${r}`:"";let o=typeof t=="string"&&t.length>0?` ${t}`:"";return!o&&r===xe&&(o=" message too big"),new je(`WebSocket closed${n}${o}`.trim(),{code:typeof r=="number"?r:void 0,reason:typeof t=="string"&&t.length>0?t:void 0,wasClean:typeof s=="boolean"?s:void 0})}return new Error("WebSocket closed")}async function ze(e){if(typeof e=="string")return e;if(e instanceof ArrayBuffer)return new TextDecoder().decode(new Uint8Array(e));if(ArrayBuffer.isView(e)){const r=e;return new TextDecoder().decode(new Uint8Array(r.buffer,r.byteOffset,r.byteLength))}if(e&&typeof e=="object"&&"arrayBuffer"in e){const t=await e.arrayBuffer();return new TextDecoder().decode(new Uint8Array(t))}return null}async function*Ve(e,r,t){const s=[];let n=null,o=!1,a=null,l=!1;const i=()=>{if(!n)return;const d=n;n=null,d()},c=d=>{(async()=>{let g=null;try{if(!d||typeof d!="object"||!("data"in d)||(g=await ze(d.data),!g))return;const m=JSON.parse(g),y=typeof m.type=="string"?m.type:"";(y==="response.completed"||y==="response.done"||y==="response.incomplete")&&(l=!0,o=!0),s.push(m),i()}catch(m){a=new q(`Invalid Codex WebSocket JSON: ${L(m)}`,{cause:m,payload:g}),o=!0,i()}})()},p=d=>{a=ne(d),o=!0,i()},h=d=>{if(l){o=!0,i();return}a||(a=ae(d)),o=!0,i()},E=()=>{a=new Error("Request was aborted"),o=!0,i()};e.addEventListener("message",c),e.addEventListener("error",p),e.addEventListener("close",h),r?.addEventListener("abort",E);try{for(;;){if(r?.aborted)throw new Error("Request was aborted");if(s.length>0){yield s.shift();continue}if(o)break;let d;await new Promise((g,m)=>{n=g,t!==void 0&&t>0&&(d=setTimeout(()=>{const y=new Error(`WebSocket idle timeout after ${t}ms`);a=y,o=!0,n=null,k(e,1e3,"idle_timeout"),m(y)},t))}).finally(()=>{d&&clearTimeout(d)})}if(a)throw a;if(!l)throw new Error("WebSocket stream closed before response.completed")}finally{e.removeEventListener("message",c),e.removeEventListener("error",p),e.removeEventListener("close",h),r?.removeEventListener("abort",E)}}function X(e){const{input:r,previous_response_id:t,...s}=e;return s}function Ge(e,r){return JSON.stringify(e??[])===JSON.stringify(r??[])}function Qe(e,r){return JSON.stringify(X(e))===JSON.stringify(X(r))}function Ze(e,r){if(!Qe(e,r.lastRequestBody))return;const t=e.input??[],s=[...r.lastRequestBody.input??[],...r.lastResponseItems];if(t.length<s.length)return;const n=t.slice(0,s.length);if(Ge(n,s))return t.slice(s.length)}function et(e,r){const t=e.continuation;if(!t)return r;const s=Ze(r,t);return!s||!t.lastResponseId?(e.continuation=void 0,r):{...r,previous_response_id:t.lastResponseId,input:s}}async function*tt(e,r,t,s){let n=!1;for await(const o of e)n||(n=!0,s(),t.push({type:"start",partial:r})),yield o}async function rt(e,r,t,s,n,o,a,l,i,c){const{socket:p,entry:h,reused:E,release:d}=await Ye(e,t,c?.sessionId,c?.signal,i);let g=!0;const m=c?.transport==="websocket-cached"||c?.transport==="auto",y=r,u=m&&h?et(h,y):y,f=c?.sessionId?N(c.sessionId):void 0;f&&(f.requests++,E?f.connectionsReused++:f.connectionsCreated++,m&&f.cachedContextRequests++,u.store===!0&&f.storeTrueRequests++,f.lastInputItems=u.input?.length??0,u.previous_response_id?(f.deltaRequests++,f.lastDeltaInputItems=u.input?.length??0,f.lastPreviousResponseId=u.previous_response_id):(f.fullContextRequests++,f.lastDeltaInputItems=void 0,f.lastPreviousResponseId=void 0));try{if(p.send(JSON.stringify({type:"response.create",...u})),await G(tt(oe(Ve(p,c?.signal,l)),s,n,a),s,n,o,{serviceTier:c?.serviceTier,resolveServiceTier:te,applyServiceTierPricing:(v,b)=>ee(v,b,o)}),c?.signal?.aborted)g=!1;else if(m&&h&&s.responseId){const v=V(o,{messages:[s]},Z,{includeSystemPrompt:!1}).filter(b=>b.type!=="function_call_output");h.continuation={lastRequestBody:y,lastResponseId:s.responseId,lastResponseItems:v}}}catch(v){throw h&&(h.continuation=void 0),g=!1,v}finally{d({keep:g})}}async function ot(e){const r=await e.text();let t=r||e.statusText||"Request failed",s;try{const o=JSON.parse(r)?.error;if(o){const a=o.code||o.type||"";if(/usage_limit_reached|usage_not_included|rate_limit_exceeded/i.test(a)||e.status===429){const l=o.plan_type?` (${o.plan_type.toLowerCase()} plan)`:"",i=o.resets_at?Math.max(0,Math.round((o.resets_at*1e3-Date.now())/6e4)):void 0,c=i!==void 0?` Try again in ~${i} min.`:"";s=`You have hit your ChatGPT usage limit${l}.${c}`.trim()}t=o.message||s||t}}catch{}return{message:t,friendlyMessage:s}}function st(e){try{const r=e.split(".");if(r.length!==3)throw new Error("Invalid token");const s=JSON.parse(atob(r[1]))?.[ve]?.chatgpt_account_id;if(!s)throw new Error("No account ID in token");return s}catch{throw new Error("Failed to extract accountId from token")}}function nt(){return typeof globalThis.crypto?.randomUUID=="function"?globalThis.crypto.randomUUID():`codex_${Date.now()}_${Math.random().toString(36).slice(2,10)}`}function ie(e,r,t,s){const n=new Headers(e);for(const[a,l]of Object.entries(r||{}))n.set(a,l);n.set("Authorization",`Bearer ${s}`),n.set("chatgpt-account-id",t),n.set("originator","pi");const o=x?`pi (${x.platform()} ${x.release()}; ${x.arch()})`:"pi (browser)";return n.set("User-Agent",o),n}function at(e,r,t,s,n){const o=ie(e,r,t,s);return o.set("OpenAI-Beta","responses=experimental"),o.set("accept","text/event-stream"),o.set("content-type","application/json"),n&&(o.set("session-id",n),o.set("x-client-request-id",n)),o}function it(e,r,t,s,n){const o=ie(e,r,t,s);return o.delete("accept"),o.delete("content-type"),o.delete("OpenAI-Beta"),o.delete("openai-beta"),o.set("OpenAI-Beta",Fe),o.set("x-client-request-id",n),o.set("session-id",n),o}export{Je as closeOpenAICodexWebSocketSessions,wt as getOpenAICodexWebSocketDebugStats,gt as resetOpenAICodexWebSocketDebugStats,Le as streamOpenAICodexResponses,bt as streamSimpleOpenAICodexResponses};
dist/assets/openai-codex-responses-CTXzuzSc.js DELETED
@@ -1,7 +0,0 @@
1
- import{A as ae,g as j,a as ie}from"./index-CgfZNSZZ.js";import{h as X}from"./headers-CgnjaPPL.js";import{c as ce}from"./openai-prompt-cache-h_V5PL7P.js";import{c as V,a as ue,p as Y}from"./openai-responses-shared-HtwCtL3B.js";import{b as le}from"./transform-messages-Bxe2XUr4.js";import"./hash-DMDecQcg.js";import"./json-parse-B9Wfu_bW.js";import"./sanitize-unicode-B62XMGgN.js";const $=new Set;function de(e){return $.add(e),()=>{$.delete(e)}}function A(e){return e instanceof Error?e.message||e.name:typeof e=="string"?e:String(e)}function fe(e){if(!(e instanceof Error))return{name:"ThrownValue",message:A(e)};const r=e.code;return{name:e.name||void 0,message:e.message||e.name,stack:e.stack,code:typeof r=="string"||typeof r=="number"?r:void 0}}function pe(e,r,t){return{type:e,timestamp:Date.now(),error:fe(r),details:t}}function ye(e,r){e.diagnostics=[...e.diagnostics??[],r]}var R={},me=function(e,r){return typeof e=="string"&&/^\.\.?\//.test(e)?e.replace(/\.(tsx)$|((?:\.d)?)((?:\.[^./]+?)?)\.([cm]?)ts$/i,function(t,s,o,n,i){return s?".js":o&&(!n||!i)?t:o+n+"."+i.toLowerCase()+"js"}):e};let v=null;const z=e=>import(me(e)),be="node:os";typeof process<"u"&&(process.versions?.node||process.versions?.bun)&&z(be).then(e=>{v=e});const we="https://chatgpt.com/backend-api",he="https://api.openai.com/auth",W=3,F=1e3,G=new Set(["openai","openai-codex","opencode"]),ge=1009,Se=new Set(["completed","incomplete","failed","cancelled","queued","in_progress"]);function Ee(e,r){return e===429||e===500||e===502||e===503||e===504?!0:/rate.?limit|overloaded|service.?unavailable|upstream.?connect|connection.?refused/i.test(r)}function J(e,r){return new Promise((t,s)=>{if(r?.aborted){s(new Error("Request was aborted"));return}const o=setTimeout(t,e);r?.addEventListener("abort",()=>{clearTimeout(o),s(new Error("Request was aborted"))})})}const ve=(e,r,t)=>{const s=new ae;return(async()=>{const o={role:"assistant",content:[],api:"openai-codex-responses",provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const n=t?.apiKey||j(e.provider)||"";if(!n)throw new Error(`No API key for provider: ${e.provider}`);const i=Xe(n);let a=ke(e,r,t);const u=await t?.onPayload?.(a,e);u!==void 0&&(a=u);const l=t?.sessionId||Ve(),w=Ye(e.headers,t?.headers,i,n,t?.sessionId),g=ze(e.headers,t?.headers,i,n,l),d=JSON.stringify(a),b=t?.transport||"auto",f=b!=="sse"&&re(t?.sessionId);if(f&&U(t?.sessionId),b!=="sse"&&!f){let m=!1;try{if(await Ke(xe(e.baseUrl),a,g,o,s,e,()=>{m=!0},t),t?.signal?.aborted)throw new Error("Request was aborted");s.push({type:"done",reason:o.stopReason,message:o}),s.end();return}catch(p){if(t?.signal?.aborted||Te(p)||(ye(o,pe("provider_transport_failure",p,{configuredTransport:b,fallbackTransport:m?void 0:"sse",eventsEmitted:m,phase:m?"after_message_stream_start":"before_message_stream_start",requestBytes:new TextEncoder().encode(d).byteLength})),Le(t?.sessionId,p),m))throw p;U(t?.sessionId)}}let c,y;for(let m=0;m<=W;m++){if(t?.signal?.aborted)throw new Error("Request was aborted");try{if(c=await fetch(ee(e.baseUrl),{method:"POST",headers:w,body:d,signal:t?.signal}),await t?.onResponse?.({status:c.status,headers:X(c.headers)},e),c.ok)break;const p=await c.text();if(m<W&&Ee(c.status,p)){let x=F*2**m;const P=c.headers.get("retry-after-ms");if(P!==null){const E=Number(P);Number.isFinite(E)&&(x=Math.max(0,E))}else{const E=c.headers.get("retry-after");if(E){const B=Number(E);if(Number.isFinite(B))x=Math.max(0,B*1e3);else{const M=Date.parse(E);Number.isNaN(M)||(x=Math.max(0,M-Date.now()))}}}await J(x,t?.signal);continue}const _=new Response(p,{status:c.status,statusText:c.statusText}),N=await je(_);throw new Error(N.friendlyMessage||N.message)}catch(p){if(p instanceof Error&&(p.name==="AbortError"||p.message==="Request was aborted"))throw new Error("Request was aborted");if(y=p instanceof Error?p:new Error(String(p)),m<W&&!y.message.includes("usage limit")){const _=F*2**m;await J(_,t?.signal);continue}throw y}}if(!c?.ok)throw y??new Error("Failed after retries");if(!c.body)throw new Error("No response body");if(s.push({type:"start",partial:o}),await Re(c,o,s,e,t),t?.signal?.aborted)throw new Error("Request was aborted");s.push({type:"done",reason:o.stopReason,message:o}),s.end()}catch(n){for(const i of o.content)delete i.partialJson;o.stopReason=t?.signal?.aborted?"aborted":"error",o.errorMessage=n instanceof Error?n.message:String(n),s.push({type:"error",reason:o.stopReason,error:o}),s.end()}})(),s},nt=(e,r,t)=>{const s=t?.apiKey||j(e.provider);if(!s)throw new Error(`No API key for provider: ${e.provider}`);const o=le(e,t,s),n=t?.reasoning?ie(e,t.reasoning):void 0;return ve(e,r,{...o,reasoningEffort:n==="off"?void 0:n})};function ke(e,r,t){const s=V(e,r,G,{includeSystemPrompt:!1}),o={model:e.id,store:!1,stream:!0,instructions:r.systemPrompt||"You are a helpful assistant.",input:s,text:{verbosity:t?.textVerbosity||"low"},include:["reasoning.encrypted_content"],prompt_cache_key:ce(t?.sessionId),tool_choice:"auto",parallel_tool_calls:!0};if(t?.temperature!==void 0&&(o.temperature=t.temperature),t?.serviceTier!==void 0&&(o.service_tier=t.serviceTier),r.tools&&r.tools.length>0&&(o.tools=ue(r.tools,{strict:null})),t?.reasoningEffort!==void 0){const n=t.reasoningEffort==="none"?e.thinkingLevelMap?.off??"none":e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort;n!==null&&(o.reasoning={effort:n,summary:t.reasoningSummary??"auto"})}return o}function _e(e,r){switch(r){case"flex":return .5;case"priority":return e.id==="gpt-5.5"?2.5:2;default:return 1}}function Q(e,r,t){const s=_e(t,r);s!==1&&(e.cost.input*=s,e.cost.output*=s,e.cost.cacheRead*=s,e.cost.cacheWrite*=s,e.cost.total=e.cost.input+e.cost.output+e.cost.cacheRead+e.cost.cacheWrite)}function Z(e,r){return e==="default"&&(r==="flex"||r==="priority")?r:e??r}function ee(e){const t=(e&&e.trim().length>0?e:we).replace(/\/+$/,"");return t.endsWith("/codex/responses")?t:t.endsWith("/codex")?`${t}/responses`:`${t}/codex/responses`}function xe(e){const r=new URL(ee(e));return r.protocol==="https:"&&(r.protocol="wss:"),r.protocol==="http:"&&(r.protocol="ws:"),r.toString()}async function Re(e,r,t,s,o){await Y(te(Oe(e)),r,t,s,{serviceTier:o?.serviceTier,resolveServiceTier:Z,applyServiceTierPricing:(n,i)=>Q(n,i,s)})}class L extends Error{code;payload;constructor(r,t){super(r),this.name="CodexApiError",this.code=t?.code,this.payload=t?.payload,this.cause=t?.cause}}class q extends Error{payload;constructor(r,t){super(r),this.name="CodexProtocolError",this.payload=t?.payload,this.cause=t?.cause}}function Te(e){return e instanceof L||e instanceof q}async function*te(e){for await(const r of e){const t=typeof r.type=="string"?r.type:void 0;if(t){if(t==="error"){const s=r.code||"",o=r.message||"";throw new L(`Codex error: ${o||s||JSON.stringify(r)}`,{code:s||void 0,payload:r})}if(t==="response.failed"){const s=r.response,o=s?.error?.code,n=s?.error?.message;throw new L(n||"Codex response failed",{code:o,payload:r})}if(t==="response.done"||t==="response.completed"||t==="response.incomplete"){const s=r.response,o=s&&{...s,status:Ce(s.status)};yield{...r,type:"response.completed",response:o};return}yield r}}}function Ce(e){if(typeof e=="string")return Se.has(e)?e:void 0}async function*Oe(e){if(!e.body)return;const r=e.body.getReader(),t=new TextDecoder;let s="";try{for(;;){const{done:o,value:n}=await r.read();if(o)break;s+=t.decode(n,{stream:!0});let i=s.indexOf(`
2
-
3
- `);for(;i!==-1;){const a=s.slice(0,i);s=s.slice(i+2);const u=a.split(`
4
- `).filter(l=>l.startsWith("data:")).map(l=>l.slice(5).trim());if(u.length>0){const l=u.join(`
5
- `).trim();if(l&&l!=="[DONE]")try{yield JSON.parse(l)}catch(w){throw new q(`Invalid Codex SSE JSON: ${A(w)}`,{cause:w,payload:l})}}i=s.indexOf(`
6
-
7
- `)}}}finally{try{await r.cancel()}catch{}try{r.releaseLock()}catch{}}}const Ae="responses_websockets=2026-02-06",We=300*1e3,h=new Map,k=new Map,O=new Set;function D(e){let r=k.get(e);return r||(r={requests:0,connectionsCreated:0,connectionsReused:0,cachedContextRequests:0,storeTrueRequests:0,fullContextRequests:0,deltaRequests:0,lastInputItems:0,websocketFailures:0,sseFallbacks:0},k.set(e,r)),r}function at(e){const r=k.get(e);return r?{...r}:void 0}function it(e){if(e){k.delete(e),O.delete(e);return}k.clear(),O.clear()}function Ie(e){const r=t=>{t.idleTimer&&clearTimeout(t.idleTimer),S(t.socket,1e3,"debug_close")};if(e){const t=h.get(e);t&&r(t),h.delete(e);return}for(const t of h.values())r(t);h.clear()}de(Ie);function re(e){return e?O.has(e):!1}function U(e){if(!e)return;const r=D(e);r.sseFallbacks++,r.websocketFallbackActive=re(e)}function Le(e,r){if(!e)return;O.add(e);const t=D(e);t.websocketFailures++,t.lastWebSocketError=A(r),t.websocketFallbackActive=!0}let T=null;async function qe(){if(T)return T;if(process?.versions?.bun&&(R.HTTP_PROXY||R.HTTPS_PROXY||R.http_proxy||R.https_proxy)){const t=(await z("proxy-from-env")).getProxyForUrl;return T=class extends WebSocket{constructor(s,o){let n={};Array.isArray(o)||typeof o=="string"?n={protocols:o}:n={...o};const i=t(s.toString().replace(/^wss:/,"https:").replace(/^ws:/,"http:"));super(s,{...n,...i?{proxy:i}:{}})}},T}const e=globalThis.WebSocket;return typeof e!="function"?null:e}class De extends Error{code;reason;wasClean;constructor(r,t){super(r),this.name="WebSocketCloseError",this.code=t?.code,this.reason=t?.reason,this.wasClean=t?.wasClean}}function Ne(e){const r=e.readyState;return typeof r=="number"?r:void 0}function C(e){const r=Ne(e);return r===void 0||r===1}function S(e,r=1e3,t="done"){try{e.close(r,t)}catch{}}function H(e,r){r.idleTimer&&clearTimeout(r.idleTimer),r.idleTimer=setTimeout(()=>{r.busy||(S(r.socket,1e3,"idle_timeout"),h.delete(e))},We)}async function I(e,r,t){const s=await qe();if(!s)throw new Error("WebSocket transport is not available in this runtime");const o=X(r);return delete o["OpenAI-Beta"],new Promise((n,i)=>{let a=!1,u;try{u=new s(e,{headers:o})}catch(f){i(f instanceof Error?f:new Error(String(f)));return}const l=()=>{a||(a=!0,b(),n(u))},w=f=>{const c=se(f);a||(a=!0,b(),i(c))},g=f=>{const c=oe(f);a||(a=!0,b(),i(c))},d=()=>{a||(a=!0,b(),u.close(1e3,"aborted"),i(new Error("Request was aborted")))},b=()=>{u.removeEventListener("open",l),u.removeEventListener("error",w),u.removeEventListener("close",g),t?.removeEventListener("abort",d)};u.addEventListener("open",l),u.addEventListener("error",w),u.addEventListener("close",g),t?.addEventListener("abort",d)})}async function Pe(e,r,t,s){if(!t){const a=await I(e,r,s);return{socket:a,reused:!1,release:({keep:u}={})=>{if(u===!1){S(a);return}S(a)}}}const o=h.get(t);if(o){if(o.idleTimer&&(clearTimeout(o.idleTimer),o.idleTimer=void 0),!o.busy&&C(o.socket))return o.busy=!0,{socket:o.socket,entry:o,reused:!0,release:({keep:a}={})=>{if(!a||!C(o.socket)){S(o.socket),h.delete(t);return}o.busy=!1,H(t,o)}};if(o.busy){const a=await I(e,r,s);return{socket:a,reused:!1,release:()=>{S(a)}}}C(o.socket)||(S(o.socket),h.delete(t))}const n=await I(e,r,s),i={socket:n,busy:!0};return h.set(t,i),{socket:n,entry:i,reused:!1,release:({keep:a}={})=>{if(!a||!C(i.socket)){S(i.socket),i.idleTimer&&clearTimeout(i.idleTimer),h.get(t)===i&&h.delete(t);return}i.busy=!1,H(t,i)}}}function se(e){if(e&&typeof e=="object"){const r="message"in e?e.message:void 0;if(typeof r=="string"&&r.length>0)return new Error(r);const t="error"in e?e.error:void 0;if(t instanceof Error&&t.message.length>0)return t;if(t&&typeof t=="object"&&"message"in t){const s=t.message;if(typeof s=="string"&&s.length>0)return new Error(s)}}return new Error("WebSocket error")}function oe(e){if(e&&typeof e=="object"){const r="code"in e?e.code:void 0,t="reason"in e?e.reason:void 0,s="wasClean"in e?e.wasClean:void 0,o=typeof r=="number"?` ${r}`:"";let n=typeof t=="string"&&t.length>0?` ${t}`:"";return!n&&r===ge&&(n=" message too big"),new De(`WebSocket closed${o}${n}`.trim(),{code:typeof r=="number"?r:void 0,reason:typeof t=="string"&&t.length>0?t:void 0,wasClean:typeof s=="boolean"?s:void 0})}return new Error("WebSocket closed")}async function Be(e){if(typeof e=="string")return e;if(e instanceof ArrayBuffer)return new TextDecoder().decode(new Uint8Array(e));if(ArrayBuffer.isView(e)){const r=e;return new TextDecoder().decode(new Uint8Array(r.buffer,r.byteOffset,r.byteLength))}if(e&&typeof e=="object"&&"arrayBuffer"in e){const t=await e.arrayBuffer();return new TextDecoder().decode(new Uint8Array(t))}return null}async function*Me(e,r){const t=[];let s=null,o=!1,n=null,i=!1;const a=()=>{if(!s)return;const d=s;s=null,d()},u=d=>{(async()=>{let b=null;try{if(!d||typeof d!="object"||!("data"in d)||(b=await Be(d.data),!b))return;const f=JSON.parse(b),c=typeof f.type=="string"?f.type:"";(c==="response.completed"||c==="response.done"||c==="response.incomplete")&&(i=!0,o=!0),t.push(f),a()}catch(f){n=new q(`Invalid Codex WebSocket JSON: ${A(f)}`,{cause:f,payload:b}),o=!0,a()}})()},l=d=>{n=se(d),o=!0,a()},w=d=>{if(i){o=!0,a();return}n||(n=oe(d)),o=!0,a()},g=()=>{n=new Error("Request was aborted"),o=!0,a()};e.addEventListener("message",u),e.addEventListener("error",l),e.addEventListener("close",w),r?.addEventListener("abort",g);try{for(;;){if(r?.aborted)throw new Error("Request was aborted");if(t.length>0){yield t.shift();continue}if(o)break;await new Promise(d=>{s=d})}if(n)throw n;if(!i)throw new Error("WebSocket stream closed before response.completed")}finally{e.removeEventListener("message",u),e.removeEventListener("error",l),e.removeEventListener("close",w),r?.removeEventListener("abort",g)}}function K(e){const{input:r,previous_response_id:t,...s}=e;return s}function $e(e,r){return JSON.stringify(e??[])===JSON.stringify(r??[])}function Fe(e,r){return JSON.stringify(K(e))===JSON.stringify(K(r))}function Je(e,r){if(!Fe(e,r.lastRequestBody))return;const t=e.input??[],s=[...r.lastRequestBody.input??[],...r.lastResponseItems];if(t.length<s.length)return;const o=t.slice(0,s.length);if($e(o,s))return t.slice(s.length)}function Ue(e,r){const t=e.continuation;if(!t)return r;const s=Je(r,t);return!s||!t.lastResponseId?(e.continuation=void 0,r):{...r,previous_response_id:t.lastResponseId,input:s}}async function*He(e,r,t,s){let o=!1;for await(const n of e)o||(o=!0,s(),t.push({type:"start",partial:r})),yield n}async function Ke(e,r,t,s,o,n,i,a){const{socket:u,entry:l,reused:w,release:g}=await Pe(e,t,a?.sessionId,a?.signal);let d=!0;const b=a?.transport==="websocket-cached"||a?.transport==="auto",f=r,c=b&&l?Ue(l,f):f,y=a?.sessionId?D(a.sessionId):void 0;y&&(y.requests++,w?y.connectionsReused++:y.connectionsCreated++,b&&y.cachedContextRequests++,c.store===!0&&y.storeTrueRequests++,y.lastInputItems=c.input?.length??0,c.previous_response_id?(y.deltaRequests++,y.lastDeltaInputItems=c.input?.length??0,y.lastPreviousResponseId=c.previous_response_id):(y.fullContextRequests++,y.lastDeltaInputItems=void 0,y.lastPreviousResponseId=void 0));try{if(u.send(JSON.stringify({type:"response.create",...c})),await Y(He(te(Me(u,a?.signal)),s,o,i),s,o,n,{serviceTier:a?.serviceTier,resolveServiceTier:Z,applyServiceTierPricing:(m,p)=>Q(m,p,n)}),a?.signal?.aborted)d=!1;else if(b&&l&&s.responseId){const m=V(n,{messages:[s]},G,{includeSystemPrompt:!1}).filter(p=>p.type!=="function_call_output");l.continuation={lastRequestBody:f,lastResponseId:s.responseId,lastResponseItems:m}}}catch(m){throw l&&(l.continuation=void 0),d=!1,m}finally{g({keep:d})}}async function je(e){const r=await e.text();let t=r||e.statusText||"Request failed",s;try{const n=JSON.parse(r)?.error;if(n){const i=n.code||n.type||"";if(/usage_limit_reached|usage_not_included|rate_limit_exceeded/i.test(i)||e.status===429){const a=n.plan_type?` (${n.plan_type.toLowerCase()} plan)`:"",u=n.resets_at?Math.max(0,Math.round((n.resets_at*1e3-Date.now())/6e4)):void 0,l=u!==void 0?` Try again in ~${u} min.`:"";s=`You have hit your ChatGPT usage limit${a}.${l}`.trim()}t=n.message||s||t}}catch{}return{message:t,friendlyMessage:s}}function Xe(e){try{const r=e.split(".");if(r.length!==3)throw new Error("Invalid token");const s=JSON.parse(atob(r[1]))?.[he]?.chatgpt_account_id;if(!s)throw new Error("No account ID in token");return s}catch{throw new Error("Failed to extract accountId from token")}}function Ve(){return typeof globalThis.crypto?.randomUUID=="function"?globalThis.crypto.randomUUID():`codex_${Date.now()}_${Math.random().toString(36).slice(2,10)}`}function ne(e,r,t,s){const o=new Headers(e);for(const[i,a]of Object.entries(r||{}))o.set(i,a);o.set("Authorization",`Bearer ${s}`),o.set("chatgpt-account-id",t),o.set("originator","pi");const n=v?`pi (${v.platform()} ${v.release()}; ${v.arch()})`:"pi (browser)";return o.set("User-Agent",n),o}function Ye(e,r,t,s,o){const n=ne(e,r,t,s);return n.set("OpenAI-Beta","responses=experimental"),n.set("accept","text/event-stream"),n.set("content-type","application/json"),o&&(n.set("session_id",o),n.set("x-client-request-id",o)),n}function ze(e,r,t,s,o){const n=ne(e,r,t,s);return n.delete("accept"),n.delete("content-type"),n.delete("OpenAI-Beta"),n.delete("openai-beta"),n.set("OpenAI-Beta",Ae),n.set("x-client-request-id",o),n.set("session_id",o),n}export{Ie as closeOpenAICodexWebSocketSessions,at as getOpenAICodexWebSocketDebugStats,it as resetOpenAICodexWebSocketDebugStats,ve as streamOpenAICodexResponses,nt as streamSimpleOpenAICodexResponses};
 
 
 
 
 
 
 
 
dist/assets/{openai-completions-ChsgufLt.js → openai-completions-CTz74GS-.js} RENAMED
@@ -1,6 +1,6 @@
1
- import{O as G}from"./client-Sq9UPDIz.js";import{A as $,g as L,a as W,c as K}from"./index-CgfZNSZZ.js";import{h as J}from"./headers-CgnjaPPL.js";import{a as P}from"./json-parse-B9Wfu_bW.js";import{s as C}from"./sanitize-unicode-B62XMGgN.js";import{h as Y,b as V,i as Z,r as Q}from"./github-copilot-headers-CVWOSrQr.js";import{c as X}from"./openai-prompt-cache-h_V5PL7P.js";import{t as ee,b as te}from"./transform-messages-Bxe2XUr4.js";var b={};function ne(e){for(const n of e)if(n.role==="toolResult"||n.role==="assistant"&&n.content.some(t=>t.type==="toolCall"))return!0;return!1}function F(e){return e.type==="text"}function se(e){return e.type==="thinking"}function oe(e){return e.type==="toolCall"}function re(e){return e.type==="image"}function N(e){return e||(typeof process<"u"&&b.PI_CACHE_RETENTION==="long"?"long":"short")}const ae=(e,n,t)=>{const s=new $;return(async()=>{const r={role:"assistant",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const c=t?.apiKey||L(e.provider)||"",u=q(e),o=N(t?.cacheRetention),i=o==="none"?void 0:t?.sessionId,p=ie(e,n,c,t?.headers,i,u);let h=le(e,n,t,u,o);const y=await t?.onPayload?.(h,e);y!==void 0&&(h=y);const R={...t?.signal?{signal:t.signal}:{},...t?.timeoutMs!==void 0?{timeout:t.timeoutMs}:{},...t?.maxRetries!==void 0?{maxRetries:t.maxRetries}:{}},{data:T,response:_}=await p.chat.completions.create(h,R).withResponse();await t?.onResponse?.({status:_.status,headers:J(_.headers)},e),s.push({type:"start",partial:r});let v=null,l=null,k=!1;const E=new Map,S=new Map,I=r.content,A=a=>I.indexOf(a),D=a=>{const f=A(a);f!==-1&&(a.type==="text"?s.push({type:"text_end",contentIndex:f,content:a.text,partial:r}):a.type==="thinking"?s.push({type:"thinking_end",contentIndex:f,content:a.thinking,partial:r}):a.type==="toolCall"&&(a.arguments=P(a.partialArgs),delete a.partialArgs,delete a.streamIndex,s.push({type:"toolcall_end",contentIndex:f,toolCall:a,partial:r})))},U=()=>(v||(v={type:"text",text:""},I.push(v),s.push({type:"text_start",contentIndex:A(v),partial:r})),v),H=a=>(l||(l={type:"thinking",thinking:"",thinkingSignature:a},I.push(l),s.push({type:"thinking_start",contentIndex:A(l),partial:r})),l),j=a=>{const f=typeof a.index=="number"?a.index:void 0;let d=f!==void 0?E.get(f):void 0;return!d&&a.id&&(d=S.get(a.id)),d||(d={type:"toolCall",id:a.id||"",name:a.function?.name||"",arguments:{},partialArgs:"",streamIndex:f},f!==void 0&&E.set(f,d),a.id&&S.set(a.id,d),I.push(d),s.push({type:"toolcall_start",contentIndex:A(d),partial:r})),f!==void 0&&d.streamIndex===void 0&&(d.streamIndex=f,E.set(f,d)),a.id&&S.set(a.id,d),d};for await(const a of T){if(!a||typeof a!="object")continue;r.responseId||=a.id,typeof a.model=="string"&&a.model.length>0&&a.model!==e.id&&(r.responseModel||=a.model),a.usage&&(r.usage=B(a.usage,e));const f=Array.isArray(a.choices)?a.choices[0]:void 0;if(f){if(!a.usage&&f.usage&&(r.usage=B(f.usage,e)),f.finish_reason){const d=ke(f.finish_reason);r.stopReason=d.stopReason,d.errorMessage&&(r.errorMessage=d.errorMessage),k=!0}if(f.delta){if(f.delta.content!==null&&f.delta.content!==void 0&&f.delta.content.length>0){const g=U();g.text+=f.delta.content,s.push({type:"text_delta",contentIndex:A(g),delta:f.delta.content,partial:r})}const d=["reasoning_content","reasoning","reasoning_text"],O=f.delta;let w=null;for(const g of d){const m=O[g];if(typeof m=="string"&&m.length>0){w=g;break}}if(w){const g=O[w];if(typeof g=="string"&&g.length>0){const m=e.provider==="opencode-go"&&w==="reasoning"?"reasoning_content":w,x=H(m);x.thinking+=g,s.push({type:"thinking_delta",contentIndex:A(x),delta:g,partial:r})}}if(f?.delta?.tool_calls)for(const g of f.delta.tool_calls){const m=j(g);!m.id&&g.id&&(m.id=g.id,S.set(g.id,m)),!m.name&&g.function?.name&&(m.name=g.function.name);let x="";g.function?.arguments&&(x=g.function.arguments,m.partialArgs=(m.partialArgs??"")+g.function.arguments,m.arguments=P(m.partialArgs)),s.push({type:"toolcall_delta",contentIndex:A(m),delta:x,partial:r})}const M=f.delta.reasoning_details;if(M&&Array.isArray(M)){for(const g of M)if(g.type==="reasoning.encrypted"&&g.id&&g.data){const m=r.content.find(x=>x.type==="toolCall"&&x.id===g.id);m&&(m.thoughtSignature=JSON.stringify(g))}}}}}for(const a of I)D(a);if(t?.signal?.aborted)throw new Error("Request was aborted");if(r.stopReason==="aborted")throw new Error("Request was aborted");if(r.stopReason==="error")throw new Error(r.errorMessage||"Provider returned an error stop reason");if(!k)throw new Error("Stream ended without finish_reason");s.push({type:"done",reason:r.stopReason,message:r}),s.end()}catch(c){for(const o of r.content)delete o.index,delete o.partialArgs,delete o.streamIndex;r.stopReason=t?.signal?.aborted?"aborted":"error",r.errorMessage=c instanceof Error?c.message:JSON.stringify(c);const u=c?.error?.metadata?.raw;u&&(r.errorMessage+=`
2
- ${u}`),s.push({type:"error",reason:r.stopReason,error:r}),s.end()}})(),s},Se=(e,n,t)=>{const s=t?.apiKey||L(e.provider);if(!s)throw new Error(`No API key for provider: ${e.provider}`);const r=te(e,t,s),c=t?.reasoning?W(e,t.reasoning):void 0,u=c==="off"?void 0:c,o=t?.toolChoice;return ae(e,n,{...r,reasoningEffort:u,toolChoice:o})};function ie(e,n,t,s,r,c=q(e)){if(!t){if(!b.OPENAI_API_KEY)throw new Error("OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.");t=b.OPENAI_API_KEY}const u={...e.headers};if(e.provider==="github-copilot"){const i=Y(n.messages),p=V({messages:n.messages,hasImages:i});Object.assign(u,p)}r&&c.sendSessionAffinityHeaders&&(u.session_id=r,u["x-client-request-id"]=r,u["x-session-affinity"]=r),s&&Object.assign(u,s);const o=e.provider==="cloudflare-ai-gateway"?{...u,Authorization:u.Authorization??null,"cf-aig-authorization":`Bearer ${t}`}:u;return new G({apiKey:t,baseURL:Z(e.provider)?Q(e):e.baseUrl,dangerouslyAllowBrowser:!0,defaultHeaders:o})}function le(e,n,t,s=q(e),r=N(t?.cacheRetention)){const c=me(e,n,s),u=ce(s,r),o={model:e.id,messages:c,stream:!0,prompt_cache_key:e.baseUrl.includes("api.openai.com")&&r!=="none"||r==="long"&&s.supportsLongCacheRetention?X(t?.sessionId):void 0,prompt_cache_retention:r==="long"&&s.supportsLongCacheRetention?"24h":void 0};if(s.supportsUsageInStreaming!==!1&&(o.stream_options={include_usage:!0}),s.supportsStore&&(o.store=!1),t?.maxTokens&&(s.maxTokensField==="max_tokens"?o.max_tokens=t.maxTokens:o.max_completion_tokens=t.maxTokens),t?.temperature!==void 0&&(o.temperature=t.temperature),n.tools&&n.tools.length>0?(o.tools=ye(n.tools,s),s.zaiToolStream&&(o.tool_stream=!0)):ne(n.messages)&&(o.tools=[]),u&&ue(c,o.tools,u),t?.toolChoice&&(o.tool_choice=t.toolChoice),s.thinkingFormat==="zai"&&e.reasoning)o.enable_thinking=!!t?.reasoningEffort;else if(s.thinkingFormat==="qwen"&&e.reasoning)o.enable_thinking=!!t?.reasoningEffort;else if(s.thinkingFormat==="qwen-chat-template"&&e.reasoning)o.chat_template_kwargs={enable_thinking:!!t?.reasoningEffort,preserve_thinking:!0};else if(s.thinkingFormat==="deepseek"&&e.reasoning)o.thinking={type:t?.reasoningEffort?"enabled":"disabled"},t?.reasoningEffort&&(o.reasoning_effort=e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort);else if(s.thinkingFormat==="openrouter"&&e.reasoning){const i=o;t?.reasoningEffort?i.reasoning={effort:e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort}:e.thinkingLevelMap?.off!==null&&(i.reasoning={effort:e.thinkingLevelMap?.off??"none"})}else if(s.thinkingFormat==="together"&&e.reasoning){const i=o;i.reasoning={enabled:!!t?.reasoningEffort},t?.reasoningEffort&&s.supportsReasoningEffort&&(i.reasoning_effort=e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort)}else if(t?.reasoningEffort&&e.reasoning&&s.supportsReasoningEffort)o.reasoning_effort=e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort;else if(!t?.reasoningEffort&&e.reasoning&&s.supportsReasoningEffort){const i=e.thinkingLevelMap?.off;typeof i=="string"&&(o.reasoning_effort=i)}if(e.baseUrl.includes("openrouter.ai")&&e.compat?.openRouterRouting&&(o.provider=e.compat.openRouterRouting),e.baseUrl.includes("ai-gateway.vercel.sh")&&e.compat?.vercelGatewayRouting){const i=e.compat.vercelGatewayRouting;if(i.only||i.order){const p={};i.only&&(p.only=i.only),i.order&&(p.order=i.order),o.providerOptions={gateway:p}}}return o}function ce(e,n){if(e.cacheControlFormat!=="anthropic"||n==="none")return;const t=n==="long"&&e.supportsLongCacheRetention?"1h":void 0;return{type:"ephemeral",...t?{ttl:t}:{}}}function ue(e,n,t){fe(e,t),ge(n,t),pe(e,t)}function fe(e,n){for(const t of e)if(t.role==="system"||t.role==="developer"){he(t,n);return}}function pe(e,n){for(let t=e.length-1;t>=0;t--){const s=e[t];if((s.role==="user"||s.role==="assistant")&&de(s,n))return}}function ge(e,n){if(!e||e.length===0)return;const t=e[e.length-1];t.cache_control=n}function he(e,n){return z(e,n)}function de(e,n){return e.role==="user"||e.role==="assistant"?z(e,n):!1}function z(e,n){const t=e.content;if(typeof t=="string")return t.length===0?!1:(e.content=[{type:"text",text:t,cache_control:n}],!0);if(!Array.isArray(t))return!1;for(let s=t.length-1;s>=0;s--){const r=t[s];if(r?.type==="text"){const c=r;return c.cache_control=n,!0}}return!1}function me(e,n,t){const s=[],r=o=>{if(o.includes("|")){const[i]=o.split("|");return i.replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,40)}return e.provider==="openai"&&o.length>40?o.slice(0,40):o},c=ee(n.messages,e,o=>r(o));if(n.systemPrompt){const i=e.reasoning&&t.supportsDeveloperRole?"developer":"system";s.push({role:i,content:C(n.systemPrompt)})}let u=null;for(let o=0;o<c.length;o++){const i=c[o];if(t.requiresAssistantAfterToolResult&&u==="toolResult"&&i.role==="user"&&s.push({role:"assistant",content:"I have processed the tool results."}),i.role==="user")if(typeof i.content=="string")s.push({role:"user",content:C(i.content)});else{const p=i.content.map(h=>h.type==="text"?{type:"text",text:C(h.text)}:{type:"image_url",image_url:{url:`data:${h.mimeType};base64,${h.data}`}});if(p.length===0)continue;s.push({role:"user",content:p})}else if(i.role==="assistant"){const p={role:"assistant",content:t.requiresAssistantAfterToolResult?"":null},h=i.content.filter(F).filter(l=>l.text.trim().length>0).map(l=>({type:"text",text:C(l.text)})),y=h.map(l=>l.text).join(""),R=i.content.filter(se).filter(l=>l.thinking.trim().length>0);if(R.length>0)if(t.requiresThinkingAsText){const l=R.map(k=>C(k.thinking)).join(`
3
 
4
- `);p.content=[{type:"text",text:l},...h]}else{y.length>0&&(p.content=y);let l=R[0].thinkingSignature;e.provider==="opencode-go"&&l==="reasoning"&&(l="reasoning_content"),l&&l.length>0&&(p[l]=R.map(k=>k.thinking).join(`
5
- `))}else y.length>0&&(p.content=y);const T=i.content.filter(oe);if(T.length>0){p.tool_calls=T.map(k=>({id:k.id,type:"function",function:{name:k.name,arguments:JSON.stringify(k.arguments)}}));const l=T.filter(k=>k.thoughtSignature).map(k=>{try{return JSON.parse(k.thoughtSignature)}catch{return null}}).filter(Boolean);l.length>0&&(p.reasoning_details=l)}t.requiresReasoningContentOnAssistantMessages&&e.reasoning&&p.reasoning_content===void 0&&(p.reasoning_content="");const _=p.content;if(!(_!=null&&_.length>0)&&!p.tool_calls)continue;s.push(p)}else if(i.role==="toolResult"){const p=[];let h=o;for(;h<c.length&&c[h].role==="toolResult";h++){const y=c[h],R=y.content.filter(F).map(l=>l.text).join(`
6
- `),T=y.content.some(l=>l.type==="image"),_=R.length>0,v={role:"tool",content:C(_?R:"(see attached image)"),tool_call_id:y.toolCallId};if(t.requiresToolResultName&&y.toolName&&(v.name=y.toolName),s.push(v),T&&e.input.includes("image"))for(const l of y.content)re(l)&&p.push({type:"image_url",image_url:{url:`data:${l.mimeType};base64,${l.data}`}})}o=h-1,p.length>0?(t.requiresAssistantAfterToolResult&&s.push({role:"assistant",content:"I have processed the tool results."}),s.push({role:"user",content:[{type:"text",text:"Attached image(s) from tool result:"},...p]}),u="user"):u="toolResult";continue}u=i.role}return s}function ye(e,n){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.parameters,...n.supportsStrictMode!==!1&&{strict:!1}}}))}function B(e,n){const t=e.prompt_tokens||0,s=e.prompt_tokens_details?.cached_tokens??e.prompt_cache_hit_tokens??0,r=e.prompt_tokens_details?.cache_write_tokens||0,c=Math.max(0,t-s-r),u=e.completion_tokens||0,o={input:c,output:u,cacheRead:s,cacheWrite:r,totalTokens:c+u+s+r,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}};return K(n,o),o}function ke(e){if(e===null)return{stopReason:"stop"};switch(e){case"stop":case"end":return{stopReason:"stop"};case"length":return{stopReason:"length"};case"function_call":case"tool_calls":return{stopReason:"toolUse"};case"content_filter":return{stopReason:"error",errorMessage:"Provider finish_reason: content_filter"};case"network_error":return{stopReason:"error",errorMessage:"Provider finish_reason: network_error"};default:return{stopReason:"error",errorMessage:`Provider finish_reason: ${e}`}}}function Re(e){const n=e.provider,t=e.baseUrl,s=n==="zai"||t.includes("api.z.ai"),r=n==="together"||t.includes("api.together.ai")||t.includes("api.together.xyz"),c=n==="moonshotai"||n==="moonshotai-cn"||t.includes("api.moonshot."),u=n==="cloudflare-workers-ai"||t.includes("api.cloudflare.com"),o=n==="cloudflare-ai-gateway"||t.includes("gateway.ai.cloudflare.com"),i=n==="cerebras"||t.includes("cerebras.ai")||n==="xai"||t.includes("api.x.ai")||r||t.includes("chutes.ai")||t.includes("deepseek.com")||s||c||n==="opencode"||t.includes("opencode.ai")||u||o,p=t.includes("chutes.ai")||c||o||r,h=n==="xai"||t.includes("api.x.ai"),y=n==="deepseek"||t.includes("deepseek.com"),R=n==="openrouter"&&e.id.startsWith("anthropic/")?"anthropic":void 0;return{supportsStore:!i,supportsDeveloperRole:!i,supportsReasoningEffort:!h&&!s&&!c&&!r&&!o,supportsUsageInStreaming:!0,maxTokensField:p?"max_tokens":"max_completion_tokens",requiresToolResultName:!1,requiresAssistantAfterToolResult:!1,requiresThinkingAsText:!1,requiresReasoningContentOnAssistantMessages:y,thinkingFormat:y?"deepseek":s?"zai":r?"together":n==="openrouter"||t.includes("openrouter.ai")?"openrouter":"openai",openRouterRouting:{},vercelGatewayRouting:{},zaiToolStream:!1,supportsStrictMode:!c&&!r&&!o,cacheControlFormat:R,sendSessionAffinityHeaders:!1,supportsLongCacheRetention:!(r||u||o)}}function q(e){const n=Re(e);return e.compat?{supportsStore:e.compat.supportsStore??n.supportsStore,supportsDeveloperRole:e.compat.supportsDeveloperRole??n.supportsDeveloperRole,supportsReasoningEffort:e.compat.supportsReasoningEffort??n.supportsReasoningEffort,supportsUsageInStreaming:e.compat.supportsUsageInStreaming??n.supportsUsageInStreaming,maxTokensField:e.compat.maxTokensField??n.maxTokensField,requiresToolResultName:e.compat.requiresToolResultName??n.requiresToolResultName,requiresAssistantAfterToolResult:e.compat.requiresAssistantAfterToolResult??n.requiresAssistantAfterToolResult,requiresThinkingAsText:e.compat.requiresThinkingAsText??n.requiresThinkingAsText,requiresReasoningContentOnAssistantMessages:e.compat.requiresReasoningContentOnAssistantMessages??n.requiresReasoningContentOnAssistantMessages,thinkingFormat:e.compat.thinkingFormat??n.thinkingFormat,openRouterRouting:e.compat.openRouterRouting??{},vercelGatewayRouting:e.compat.vercelGatewayRouting??n.vercelGatewayRouting,zaiToolStream:e.compat.zaiToolStream??n.zaiToolStream,supportsStrictMode:e.compat.supportsStrictMode??n.supportsStrictMode,cacheControlFormat:e.compat.cacheControlFormat??n.cacheControlFormat,sendSessionAffinityHeaders:e.compat.sendSessionAffinityHeaders??n.sendSessionAffinityHeaders,supportsLongCacheRetention:e.compat.supportsLongCacheRetention??n.supportsLongCacheRetention}:n}export{me as convertMessages,ae as streamOpenAICompletions,Se as streamSimpleOpenAICompletions};
 
1
+ import{O as G}from"./client-Sq9UPDIz.js";import{A as $,g as L,a as W,c as K}from"./index-CB_zB4U3.js";import{h as J}from"./headers-CgnjaPPL.js";import{a as P}from"./json-parse-cUk3uCki.js";import{s as C}from"./sanitize-unicode-B62XMGgN.js";import{h as Y,b as V,i as Z,r as Q}from"./github-copilot-headers-CVWOSrQr.js";import{c as X}from"./openai-prompt-cache-h_V5PL7P.js";import{t as ee,b as te}from"./transform-messages-DSNYjDRn.js";var b={};function ne(e){for(const n of e)if(n.role==="toolResult"||n.role==="assistant"&&n.content.some(t=>t.type==="toolCall"))return!0;return!1}function F(e){return e.type==="text"}function se(e){return e.type==="thinking"}function oe(e){return e.type==="toolCall"}function re(e){return e.type==="image"}function N(e){return e||(typeof process<"u"&&b.PI_CACHE_RETENTION==="long"?"long":"short")}const ie=(e,n,t)=>{const s=new $;return(async()=>{const r={role:"assistant",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const c=t?.apiKey||L(e.provider)||"",u=q(e),o=N(t?.cacheRetention),i=o==="none"?void 0:t?.sessionId,p=ae(e,n,c,t?.headers,i,u);let h=le(e,n,t,u,o);const k=await t?.onPayload?.(h,e);k!==void 0&&(h=k);const R={...t?.signal?{signal:t.signal}:{},...t?.timeoutMs!==void 0?{timeout:t.timeoutMs}:{},maxRetries:t?.maxRetries??0},{data:T,response:_}=await p.chat.completions.create(h,R).withResponse();await t?.onResponse?.({status:_.status,headers:J(_.headers)},e),s.push({type:"start",partial:r});let v=null,l=null,y=!1;const w=new Map,I=new Map,E=r.content,A=a=>E.indexOf(a),D=a=>{const f=A(a);f!==-1&&(a.type==="text"?s.push({type:"text_end",contentIndex:f,content:a.text,partial:r}):a.type==="thinking"?s.push({type:"thinking_end",contentIndex:f,content:a.thinking,partial:r}):a.type==="toolCall"&&(a.arguments=P(a.partialArgs),delete a.partialArgs,delete a.streamIndex,s.push({type:"toolcall_end",contentIndex:f,toolCall:a,partial:r})))},U=()=>(v||(v={type:"text",text:""},E.push(v),s.push({type:"text_start",contentIndex:A(v),partial:r})),v),H=a=>(l||(l={type:"thinking",thinking:"",thinkingSignature:a},E.push(l),s.push({type:"thinking_start",contentIndex:A(l),partial:r})),l),j=a=>{const f=typeof a.index=="number"?a.index:void 0;let d=f!==void 0?w.get(f):void 0;return!d&&a.id&&(d=I.get(a.id)),d||(d={type:"toolCall",id:a.id||"",name:a.function?.name||"",arguments:{},partialArgs:"",streamIndex:f},f!==void 0&&w.set(f,d),a.id&&I.set(a.id,d),E.push(d),s.push({type:"toolcall_start",contentIndex:A(d),partial:r})),f!==void 0&&d.streamIndex===void 0&&(d.streamIndex=f,w.set(f,d)),a.id&&I.set(a.id,d),d};for await(const a of T){if(!a||typeof a!="object")continue;r.responseId||=a.id,typeof a.model=="string"&&a.model.length>0&&a.model!==e.id&&(r.responseModel||=a.model),a.usage&&(r.usage=B(a.usage,e));const f=Array.isArray(a.choices)?a.choices[0]:void 0;if(f){if(!a.usage&&f.usage&&(r.usage=B(f.usage,e)),f.finish_reason){const d=ye(f.finish_reason);r.stopReason=d.stopReason,d.errorMessage&&(r.errorMessage=d.errorMessage),y=!0}if(f.delta){if(f.delta.content!==null&&f.delta.content!==void 0&&f.delta.content.length>0){const g=U();g.text+=f.delta.content,s.push({type:"text_delta",contentIndex:A(g),delta:f.delta.content,partial:r})}const d=["reasoning_content","reasoning","reasoning_text"],O=f.delta;let M=null;for(const g of d){const m=O[g];if(typeof m=="string"&&m.length>0){M=g;break}}if(M){const g=O[M];if(typeof g=="string"&&g.length>0){const m=e.provider==="opencode-go"&&M==="reasoning"?"reasoning_content":M,x=H(m);x.thinking+=g,s.push({type:"thinking_delta",contentIndex:A(x),delta:g,partial:r})}}if(f?.delta?.tool_calls)for(const g of f.delta.tool_calls){const m=j(g);!m.id&&g.id&&(m.id=g.id,I.set(g.id,m)),!m.name&&g.function?.name&&(m.name=g.function.name);let x="";g.function?.arguments&&(x=g.function.arguments,m.partialArgs=(m.partialArgs??"")+g.function.arguments,m.arguments=P(m.partialArgs)),s.push({type:"toolcall_delta",contentIndex:A(m),delta:x,partial:r})}const S=f.delta.reasoning_details;if(S&&Array.isArray(S)){for(const g of S)if(g.type==="reasoning.encrypted"&&g.id&&g.data){const m=r.content.find(x=>x.type==="toolCall"&&x.id===g.id);m&&(m.thoughtSignature=JSON.stringify(g))}}}}}for(const a of E)D(a);if(t?.signal?.aborted)throw new Error("Request was aborted");if(r.stopReason==="aborted")throw new Error("Request was aborted");if(r.stopReason==="error")throw new Error(r.errorMessage||"Provider returned an error stop reason");if(!y)throw new Error("Stream ended without finish_reason");s.push({type:"done",reason:r.stopReason,message:r}),s.end()}catch(c){for(const o of r.content)delete o.index,delete o.partialArgs,delete o.streamIndex;r.stopReason=t?.signal?.aborted?"aborted":"error",r.errorMessage=c instanceof Error?c.message:JSON.stringify(c);const u=c?.error?.metadata?.raw;u&&(r.errorMessage+=`
2
+ ${u}`),s.push({type:"error",reason:r.stopReason,error:r}),s.end()}})(),s},Ie=(e,n,t)=>{const s=t?.apiKey||L(e.provider);if(!s)throw new Error(`No API key for provider: ${e.provider}`);const r=te(e,t,s),c=t?.reasoning?W(e,t.reasoning):void 0,u=c==="off"?void 0:c,o=t?.toolChoice;return ie(e,n,{...r,reasoningEffort:u,toolChoice:o})};function ae(e,n,t,s,r,c=q(e)){if(!t){if(!b.OPENAI_API_KEY)throw new Error("OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.");t=b.OPENAI_API_KEY}const u={...e.headers};if(e.provider==="github-copilot"){const i=Y(n.messages),p=V({messages:n.messages,hasImages:i});Object.assign(u,p)}r&&c.sendSessionAffinityHeaders&&(u.session_id=r,u["x-client-request-id"]=r,u["x-session-affinity"]=r),s&&Object.assign(u,s);const o=e.provider==="cloudflare-ai-gateway"?{...u,Authorization:u.Authorization??null,"cf-aig-authorization":`Bearer ${t}`}:u;return new G({apiKey:t,baseURL:Z(e.provider)?Q(e):e.baseUrl,dangerouslyAllowBrowser:!0,defaultHeaders:o})}function le(e,n,t,s=q(e),r=N(t?.cacheRetention)){const c=me(e,n,s),u=ce(s,r),o={model:e.id,messages:c,stream:!0,prompt_cache_key:e.baseUrl.includes("api.openai.com")&&r!=="none"||r==="long"&&s.supportsLongCacheRetention?X(t?.sessionId):void 0,prompt_cache_retention:r==="long"&&s.supportsLongCacheRetention?"24h":void 0};if(s.supportsUsageInStreaming!==!1&&(o.stream_options={include_usage:!0}),s.supportsStore&&(o.store=!1),t?.maxTokens&&(s.maxTokensField==="max_tokens"?o.max_tokens=t.maxTokens:o.max_completion_tokens=t.maxTokens),t?.temperature!==void 0&&(o.temperature=t.temperature),n.tools&&n.tools.length>0?(o.tools=ke(n.tools,s),s.zaiToolStream&&(o.tool_stream=!0)):ne(n.messages)&&(o.tools=[]),u&&ue(c,o.tools,u),t?.toolChoice&&(o.tool_choice=t.toolChoice),s.thinkingFormat==="zai"&&e.reasoning)o.enable_thinking=!!t?.reasoningEffort;else if(s.thinkingFormat==="qwen"&&e.reasoning)o.enable_thinking=!!t?.reasoningEffort;else if(s.thinkingFormat==="qwen-chat-template"&&e.reasoning)o.chat_template_kwargs={enable_thinking:!!t?.reasoningEffort,preserve_thinking:!0};else if(s.thinkingFormat==="deepseek"&&e.reasoning)o.thinking={type:t?.reasoningEffort?"enabled":"disabled"},t?.reasoningEffort&&(o.reasoning_effort=e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort);else if(s.thinkingFormat==="openrouter"&&e.reasoning){const i=o;t?.reasoningEffort?i.reasoning={effort:e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort}:e.thinkingLevelMap?.off!==null&&(i.reasoning={effort:e.thinkingLevelMap?.off??"none"})}else if(s.thinkingFormat==="together"&&e.reasoning){const i=o;i.reasoning={enabled:!!t?.reasoningEffort},t?.reasoningEffort&&s.supportsReasoningEffort&&(i.reasoning_effort=e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort)}else if(s.thinkingFormat==="string-thinking"&&e.reasoning){const i=o;t?.reasoningEffort?i.thinking=e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort:e.thinkingLevelMap?.off!==null&&(i.thinking=e.thinkingLevelMap?.off??"none")}else if(t?.reasoningEffort&&e.reasoning&&s.supportsReasoningEffort)o.reasoning_effort=e.thinkingLevelMap?.[t.reasoningEffort]??t.reasoningEffort;else if(!t?.reasoningEffort&&e.reasoning&&s.supportsReasoningEffort){const i=e.thinkingLevelMap?.off;typeof i=="string"&&(o.reasoning_effort=i)}if(e.baseUrl.includes("openrouter.ai")&&e.compat?.openRouterRouting&&(o.provider=e.compat.openRouterRouting),e.baseUrl.includes("ai-gateway.vercel.sh")&&e.compat?.vercelGatewayRouting){const i=e.compat.vercelGatewayRouting;if(i.only||i.order){const p={};i.only&&(p.only=i.only),i.order&&(p.order=i.order),o.providerOptions={gateway:p}}}return o}function ce(e,n){if(e.cacheControlFormat!=="anthropic"||n==="none")return;const t=n==="long"&&e.supportsLongCacheRetention?"1h":void 0;return{type:"ephemeral",...t?{ttl:t}:{}}}function ue(e,n,t){fe(e,t),ge(n,t),pe(e,t)}function fe(e,n){for(const t of e)if(t.role==="system"||t.role==="developer"){he(t,n);return}}function pe(e,n){for(let t=e.length-1;t>=0;t--){const s=e[t];if((s.role==="user"||s.role==="assistant")&&de(s,n))return}}function ge(e,n){if(!e||e.length===0)return;const t=e[e.length-1];t.cache_control=n}function he(e,n){return z(e,n)}function de(e,n){return e.role==="user"||e.role==="assistant"?z(e,n):!1}function z(e,n){const t=e.content;if(typeof t=="string")return t.length===0?!1:(e.content=[{type:"text",text:t,cache_control:n}],!0);if(!Array.isArray(t))return!1;for(let s=t.length-1;s>=0;s--){const r=t[s];if(r?.type==="text"){const c=r;return c.cache_control=n,!0}}return!1}function me(e,n,t){const s=[],r=o=>{if(o.includes("|")){const[i]=o.split("|");return i.replace(/[^a-zA-Z0-9_-]/g,"_").slice(0,40)}return e.provider==="openai"&&o.length>40?o.slice(0,40):o},c=ee(n.messages,e,o=>r(o));if(n.systemPrompt){const i=e.reasoning&&t.supportsDeveloperRole?"developer":"system";s.push({role:i,content:C(n.systemPrompt)})}let u=null;for(let o=0;o<c.length;o++){const i=c[o];if(t.requiresAssistantAfterToolResult&&u==="toolResult"&&i.role==="user"&&s.push({role:"assistant",content:"I have processed the tool results."}),i.role==="user")if(typeof i.content=="string")s.push({role:"user",content:C(i.content)});else{const p=i.content.map(h=>h.type==="text"?{type:"text",text:C(h.text)}:{type:"image_url",image_url:{url:`data:${h.mimeType};base64,${h.data}`}});if(p.length===0)continue;s.push({role:"user",content:p})}else if(i.role==="assistant"){const p={role:"assistant",content:t.requiresAssistantAfterToolResult?"":null},h=i.content.filter(F).filter(l=>l.text.trim().length>0).map(l=>({type:"text",text:C(l.text)})),k=h.map(l=>l.text).join(""),R=i.content.filter(se).filter(l=>l.thinking.trim().length>0);if(R.length>0)if(t.requiresThinkingAsText){const l=R.map(y=>C(y.thinking)).join(`
3
 
4
+ `);p.content=[{type:"text",text:l},...h]}else{k.length>0&&(p.content=k);let l=R[0].thinkingSignature;e.provider==="opencode-go"&&l==="reasoning"&&(l="reasoning_content"),l&&l.length>0&&(p[l]=R.map(y=>y.thinking).join(`
5
+ `))}else k.length>0&&(p.content=k);const T=i.content.filter(oe);if(T.length>0){p.tool_calls=T.map(y=>({id:y.id,type:"function",function:{name:y.name,arguments:JSON.stringify(y.arguments)}}));const l=T.filter(y=>y.thoughtSignature).map(y=>{try{return JSON.parse(y.thoughtSignature)}catch{return null}}).filter(Boolean);l.length>0&&(p.reasoning_details=l)}t.requiresReasoningContentOnAssistantMessages&&e.reasoning&&p.reasoning_content===void 0&&(p.reasoning_content="");const _=p.content;if(!(_!=null&&_.length>0)&&!p.tool_calls)continue;s.push(p)}else if(i.role==="toolResult"){const p=[];let h=o;for(;h<c.length&&c[h].role==="toolResult";h++){const k=c[h],R=k.content.filter(F).map(l=>l.text).join(`
6
+ `),T=k.content.some(l=>l.type==="image"),_=R.length>0,v={role:"tool",content:C(_?R:"(see attached image)"),tool_call_id:k.toolCallId};if(t.requiresToolResultName&&k.toolName&&(v.name=k.toolName),s.push(v),T&&e.input.includes("image"))for(const l of k.content)re(l)&&p.push({type:"image_url",image_url:{url:`data:${l.mimeType};base64,${l.data}`}})}o=h-1,p.length>0?(t.requiresAssistantAfterToolResult&&s.push({role:"assistant",content:"I have processed the tool results."}),s.push({role:"user",content:[{type:"text",text:"Attached image(s) from tool result:"},...p]}),u="user"):u="toolResult";continue}u=i.role}return s}function ke(e,n){return e.map(t=>({type:"function",function:{name:t.name,description:t.description,parameters:t.parameters,...n.supportsStrictMode!==!1&&{strict:!1}}}))}function B(e,n){const t=e.prompt_tokens||0,s=e.prompt_tokens_details?.cached_tokens??e.prompt_cache_hit_tokens??0,r=e.prompt_tokens_details?.cache_write_tokens||0,c=Math.max(0,t-s-r),u=e.completion_tokens||0,o={input:c,output:u,cacheRead:s,cacheWrite:r,totalTokens:c+u+s+r,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}};return K(n,o),o}function ye(e){if(e===null)return{stopReason:"stop"};switch(e){case"stop":case"end":return{stopReason:"stop"};case"length":return{stopReason:"length"};case"function_call":case"tool_calls":return{stopReason:"toolUse"};case"content_filter":return{stopReason:"error",errorMessage:"Provider finish_reason: content_filter"};case"network_error":return{stopReason:"error",errorMessage:"Provider finish_reason: network_error"};default:return{stopReason:"error",errorMessage:`Provider finish_reason: ${e}`}}}function Re(e){const n=e.provider,t=e.baseUrl,s=n==="zai"||t.includes("api.z.ai"),r=n==="together"||t.includes("api.together.ai")||t.includes("api.together.xyz"),c=n==="moonshotai"||n==="moonshotai-cn"||t.includes("api.moonshot."),u=n==="cloudflare-workers-ai"||t.includes("api.cloudflare.com"),o=n==="cloudflare-ai-gateway"||t.includes("gateway.ai.cloudflare.com"),i=n==="cerebras"||t.includes("cerebras.ai")||n==="xai"||t.includes("api.x.ai")||r||t.includes("chutes.ai")||t.includes("deepseek.com")||s||c||n==="opencode"||t.includes("opencode.ai")||u||o,p=t.includes("chutes.ai")||c||o||r,h=n==="xai"||t.includes("api.x.ai"),k=n==="deepseek"||t.includes("deepseek.com"),R=n==="openrouter"&&e.id.startsWith("anthropic/")?"anthropic":void 0;return{supportsStore:!i,supportsDeveloperRole:!i,supportsReasoningEffort:!h&&!s&&!c&&!r&&!o,supportsUsageInStreaming:!0,maxTokensField:p?"max_tokens":"max_completion_tokens",requiresToolResultName:!1,requiresAssistantAfterToolResult:!1,requiresThinkingAsText:!1,requiresReasoningContentOnAssistantMessages:k,thinkingFormat:k?"deepseek":s?"zai":r?"together":n==="openrouter"||t.includes("openrouter.ai")?"openrouter":"openai",openRouterRouting:{},vercelGatewayRouting:{},zaiToolStream:!1,supportsStrictMode:!c&&!r&&!o,cacheControlFormat:R,sendSessionAffinityHeaders:!1,supportsLongCacheRetention:!(r||u||o)}}function q(e){const n=Re(e);return e.compat?{supportsStore:e.compat.supportsStore??n.supportsStore,supportsDeveloperRole:e.compat.supportsDeveloperRole??n.supportsDeveloperRole,supportsReasoningEffort:e.compat.supportsReasoningEffort??n.supportsReasoningEffort,supportsUsageInStreaming:e.compat.supportsUsageInStreaming??n.supportsUsageInStreaming,maxTokensField:e.compat.maxTokensField??n.maxTokensField,requiresToolResultName:e.compat.requiresToolResultName??n.requiresToolResultName,requiresAssistantAfterToolResult:e.compat.requiresAssistantAfterToolResult??n.requiresAssistantAfterToolResult,requiresThinkingAsText:e.compat.requiresThinkingAsText??n.requiresThinkingAsText,requiresReasoningContentOnAssistantMessages:e.compat.requiresReasoningContentOnAssistantMessages??n.requiresReasoningContentOnAssistantMessages,thinkingFormat:e.compat.thinkingFormat??n.thinkingFormat,openRouterRouting:e.compat.openRouterRouting??{},vercelGatewayRouting:e.compat.vercelGatewayRouting??n.vercelGatewayRouting,zaiToolStream:e.compat.zaiToolStream??n.zaiToolStream,supportsStrictMode:e.compat.supportsStrictMode??n.supportsStrictMode,cacheControlFormat:e.compat.cacheControlFormat??n.cacheControlFormat,sendSessionAffinityHeaders:e.compat.sendSessionAffinityHeaders??n.sendSessionAffinityHeaders,supportsLongCacheRetention:e.compat.supportsLongCacheRetention??n.supportsLongCacheRetention}:n}export{me as convertMessages,ie as streamOpenAICompletions,Ie as streamSimpleOpenAICompletions};
dist/assets/{openai-responses-wXWgXVPI.js → openai-responses-CW5o7IM-.js} RENAMED
@@ -1 +1 @@
1
- import{O as A}from"./client-Sq9UPDIz.js";import{A as I,g as h,a as E}from"./index-CgfZNSZZ.js";import{h as w}from"./headers-CgnjaPPL.js";import{h as _,b as O,i as b,r as P}from"./github-copilot-headers-CVWOSrQr.js";import{c as S}from"./openai-prompt-cache-h_V5PL7P.js";import{p as C,c as T,a as k}from"./openai-responses-shared-HtwCtL3B.js";import{b as L}from"./transform-messages-Bxe2XUr4.js";import"./hash-DMDecQcg.js";import"./json-parse-B9Wfu_bW.js";import"./sanitize-unicode-B62XMGgN.js";var u={};const M=new Set(["openai","openai-codex","opencode"]);function g(e){return e||(typeof process<"u"&&u.PI_CACHE_RETENTION==="long"?"long":"short")}function m(e){return{sendSessionIdHeader:e.compat?.sendSessionIdHeader??!0,supportsLongCacheRetention:e.compat?.supportsLongCacheRetention??!0}}function N(e,t){return t==="long"&&e.supportsLongCacheRetention?"24h":void 0}function x(e){if(e instanceof Error){const t=e.status,r=typeof t=="number"?t:void 0;return r!==void 0?`OpenAI API error (${r}): ${e.message}`:e.message}try{return JSON.stringify(e)}catch{return String(e)}}const H=(e,t,r)=>{const s=new I;return(async()=>{const a={role:"assistant",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const o=r?.apiKey||h(e.provider)||"",i=g(r?.cacheRetention)==="none"?void 0:r?.sessionId,p=K(e,t,o,r?.headers,i);let c=q(e,t,r);const f=await r?.onPayload?.(c,e);f!==void 0&&(c=f);const l={...r?.signal?{signal:r.signal}:{},...r?.timeoutMs!==void 0?{timeout:r.timeoutMs}:{},...r?.maxRetries!==void 0?{maxRetries:r.maxRetries}:{}},{data:v,response:d}=await p.responses.create(c,l).withResponse();if(await r?.onResponse?.({status:d.status,headers:w(d.headers)},e),s.push({type:"start",partial:a}),await C(v,a,s,e,{serviceTier:r?.serviceTier,applyServiceTierPricing:(R,y)=>W(R,y,e)}),r?.signal?.aborted)throw new Error("Request was aborted");if(a.stopReason==="aborted"||a.stopReason==="error")throw new Error("An unknown error occurred");s.push({type:"done",reason:a.stopReason,message:a}),s.end()}catch(o){for(const n of a.content)delete n.index,delete n.partialJson;a.stopReason=r?.signal?.aborted?"aborted":"error",a.errorMessage=x(o),s.push({type:"error",reason:a.stopReason,error:a}),s.end()}})(),s},Q=(e,t,r)=>{const s=r?.apiKey||h(e.provider);if(!s)throw new Error(`No API key for provider: ${e.provider}`);const a=L(e,r,s),o=r?.reasoning?E(e,r.reasoning):void 0;return H(e,t,{...a,reasoningEffort:o==="off"?void 0:o})};function K(e,t,r,s,a){if(!r){if(!u.OPENAI_API_KEY)throw new Error("OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.");r=u.OPENAI_API_KEY}const o=m(e),n={...e.headers};if(e.provider==="github-copilot"){const p=_(t.messages),c=O({messages:t.messages,hasImages:p});Object.assign(n,c)}a&&(o.sendSessionIdHeader&&(n.session_id=a),n["x-client-request-id"]=a),s&&Object.assign(n,s);const i=e.provider==="cloudflare-ai-gateway"?{...n,Authorization:n.Authorization??null,"cf-aig-authorization":`Bearer ${r}`}:n;return new A({apiKey:r,baseURL:b(e.provider)?P(e):e.baseUrl,dangerouslyAllowBrowser:!0,defaultHeaders:i})}function q(e,t,r){const s=T(e,t,M),a=g(r?.cacheRetention),o=m(e),n={model:e.id,input:s,stream:!0,prompt_cache_key:a==="none"?void 0:S(r?.sessionId),prompt_cache_retention:N(o,a),store:!1};if(r?.maxTokens&&(n.max_output_tokens=r?.maxTokens),r?.temperature!==void 0&&(n.temperature=r?.temperature),r?.serviceTier!==void 0&&(n.service_tier=r.serviceTier),t.tools&&t.tools.length>0&&(n.tools=k(t.tools)),e.reasoning)if(r?.reasoningEffort||r?.reasoningSummary){const i=r?.reasoningEffort?e.thinkingLevelMap?.[r.reasoningEffort]??r.reasoningEffort:"medium";n.reasoning={effort:i,summary:r?.reasoningSummary||"auto"},n.include=["reasoning.encrypted_content"]}else e.provider!=="github-copilot"&&e.thinkingLevelMap?.off!==null&&(n.reasoning={effort:e.thinkingLevelMap?.off??"none"});return n}function B(e,t){switch(t){case"flex":return .5;case"priority":return e.id==="gpt-5.5"?2.5:2;default:return 1}}function W(e,t,r){const s=B(r,t);s!==1&&(e.cost.input*=s,e.cost.output*=s,e.cost.cacheRead*=s,e.cost.cacheWrite*=s,e.cost.total=e.cost.input+e.cost.output+e.cost.cacheRead+e.cost.cacheWrite)}export{H as streamOpenAIResponses,Q as streamSimpleOpenAIResponses};
 
1
+ import{O as A}from"./client-Sq9UPDIz.js";import{A as I,g as h,a as E}from"./index-CB_zB4U3.js";import{h as w}from"./headers-CgnjaPPL.js";import{h as _,b as O,i as b,r as P}from"./github-copilot-headers-CVWOSrQr.js";import{c as S}from"./openai-prompt-cache-h_V5PL7P.js";import{p as C,c as T,a as k}from"./openai-responses-shared-DBUlz2NN.js";import{b as L}from"./transform-messages-DSNYjDRn.js";import"./hash-DMDecQcg.js";import"./json-parse-cUk3uCki.js";import"./sanitize-unicode-B62XMGgN.js";var u={};const M=new Set(["openai","openai-codex","opencode"]);function g(e){return e||(typeof process<"u"&&u.PI_CACHE_RETENTION==="long"?"long":"short")}function m(e){return{sendSessionIdHeader:e.compat?.sendSessionIdHeader??!0,supportsLongCacheRetention:e.compat?.supportsLongCacheRetention??!0}}function N(e,t){return t==="long"&&e.supportsLongCacheRetention?"24h":void 0}function x(e){if(e instanceof Error){const t=e.status,r=typeof t=="number"?t:void 0;return r!==void 0?`OpenAI API error (${r}): ${e.message}`:e.message}try{return JSON.stringify(e)}catch{return String(e)}}const H=(e,t,r)=>{const s=new I;return(async()=>{const a={role:"assistant",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"stop",timestamp:Date.now()};try{const o=r?.apiKey||h(e.provider)||"",i=g(r?.cacheRetention)==="none"?void 0:r?.sessionId,p=K(e,t,o,r?.headers,i);let c=q(e,t,r);const f=await r?.onPayload?.(c,e);f!==void 0&&(c=f);const l={...r?.signal?{signal:r.signal}:{},...r?.timeoutMs!==void 0?{timeout:r.timeoutMs}:{},maxRetries:r?.maxRetries??0},{data:v,response:d}=await p.responses.create(c,l).withResponse();if(await r?.onResponse?.({status:d.status,headers:w(d.headers)},e),s.push({type:"start",partial:a}),await C(v,a,s,e,{serviceTier:r?.serviceTier,applyServiceTierPricing:(R,y)=>W(R,y,e)}),r?.signal?.aborted)throw new Error("Request was aborted");if(a.stopReason==="aborted"||a.stopReason==="error")throw new Error("An unknown error occurred");s.push({type:"done",reason:a.stopReason,message:a}),s.end()}catch(o){for(const n of a.content)delete n.index,delete n.partialJson;a.stopReason=r?.signal?.aborted?"aborted":"error",a.errorMessage=x(o),s.push({type:"error",reason:a.stopReason,error:a}),s.end()}})(),s},Q=(e,t,r)=>{const s=r?.apiKey||h(e.provider);if(!s)throw new Error(`No API key for provider: ${e.provider}`);const a=L(e,r,s),o=r?.reasoning?E(e,r.reasoning):void 0;return H(e,t,{...a,reasoningEffort:o==="off"?void 0:o})};function K(e,t,r,s,a){if(!r){if(!u.OPENAI_API_KEY)throw new Error("OpenAI API key is required. Set OPENAI_API_KEY environment variable or pass it as an argument.");r=u.OPENAI_API_KEY}const o=m(e),n={...e.headers};if(e.provider==="github-copilot"){const p=_(t.messages),c=O({messages:t.messages,hasImages:p});Object.assign(n,c)}a&&(o.sendSessionIdHeader&&(n.session_id=a),n["x-client-request-id"]=a),s&&Object.assign(n,s);const i=e.provider==="cloudflare-ai-gateway"?{...n,Authorization:n.Authorization??null,"cf-aig-authorization":`Bearer ${r}`}:n;return new A({apiKey:r,baseURL:b(e.provider)?P(e):e.baseUrl,dangerouslyAllowBrowser:!0,defaultHeaders:i})}function q(e,t,r){const s=T(e,t,M),a=g(r?.cacheRetention),o=m(e),n={model:e.id,input:s,stream:!0,prompt_cache_key:a==="none"?void 0:S(r?.sessionId),prompt_cache_retention:N(o,a),store:!1};if(r?.maxTokens&&(n.max_output_tokens=r?.maxTokens),r?.temperature!==void 0&&(n.temperature=r?.temperature),r?.serviceTier!==void 0&&(n.service_tier=r.serviceTier),t.tools&&t.tools.length>0&&(n.tools=k(t.tools)),e.reasoning)if(r?.reasoningEffort||r?.reasoningSummary){const i=r?.reasoningEffort?e.thinkingLevelMap?.[r.reasoningEffort]??r.reasoningEffort:"medium";n.reasoning={effort:i,summary:r?.reasoningSummary||"auto"},n.include=["reasoning.encrypted_content"]}else e.provider!=="github-copilot"&&e.thinkingLevelMap?.off!==null&&(n.reasoning={effort:e.thinkingLevelMap?.off??"none"});return n}function B(e,t){switch(t){case"flex":return .5;case"priority":return e.id==="gpt-5.5"?2.5:2;default:return 1}}function W(e,t,r){const s=B(r,t);s!==1&&(e.cost.input*=s,e.cost.output*=s,e.cost.cacheRead*=s,e.cost.cacheWrite*=s,e.cost.total=e.cost.input+e.cost.output+e.cost.cacheRead+e.cost.cacheWrite)}export{H as streamOpenAIResponses,Q as streamSimpleOpenAIResponses};
dist/assets/{openai-responses-shared-HtwCtL3B.js → openai-responses-shared-DBUlz2NN.js} RENAMED
@@ -1,12 +1,12 @@
1
- import{c as S}from"./index-CgfZNSZZ.js";import{s as v}from"./hash-DMDecQcg.js";import{a as x}from"./json-parse-B9Wfu_bW.js";import{s as _}from"./sanitize-unicode-B62XMGgN.js";import{t as $}from"./transform-messages-Bxe2XUr4.js";function T(r,t){const l={v:1,id:r};return t&&(l.phase=t),JSON.stringify(l)}function C(r){if(r){if(r.startsWith("{"))try{const t=JSON.parse(r);if(t.v===1&&typeof t.id=="string")return t.phase==="commentary"||t.phase==="final_answer"?{id:t.id,phase:t.phase}:{id:t.id}}catch{}return{id:r}}}function M(r,t,l,y){const m=[],i=s=>{const o=s.replace(/[^a-zA-Z0-9_-]/g,"_");return(o.length>64?o.slice(0,64):o).replace(/_+$/,"")},n=s=>{const o=`fc_${v(s)}`;return o.length>64?o.slice(0,64):o},k=(s,o,p)=>{if(!l.has(r.provider)||!s.includes("|"))return i(s);const[h,g]=s.split("|"),f=i(h);let c=p.provider!==r.provider||p.api!==r.api?n(g):i(g);return c.startsWith("fc_")||(c=i(`fc_${c}`)),`${f}|${c}`},d=$(t.messages,r,k);if((y?.includeSystemPrompt??!0)&&t.systemPrompt){const s=r.reasoning?"developer":"system";m.push({role:s,content:_(t.systemPrompt)})}let e=0;for(const s of d){if(s.role==="user")if(typeof s.content=="string")m.push({role:"user",content:[{type:"input_text",text:_(s.content)}]});else{const o=s.content.map(p=>p.type==="text"?{type:"input_text",text:_(p.text)}:{type:"input_image",detail:"auto",image_url:`data:${p.mimeType};base64,${p.data}`});if(o.length===0)continue;m.push({role:"user",content:o})}else if(s.role==="assistant"){const o=[],p=s,h=p.model!==r.id&&p.provider===r.provider&&p.api===r.api;for(const g of s.content)if(g.type==="thinking"){if(g.thinkingSignature){const f=JSON.parse(g.thinkingSignature);o.push(f)}}else if(g.type==="text"){const f=g,u=C(f.textSignature);let c=u?.id;c?c.length>64&&(c=`msg_${v(c)}`):c=`msg_${e}`,o.push({type:"message",role:"assistant",content:[{type:"output_text",text:_(f.text),annotations:[]}],status:"completed",id:c,phase:u?.phase})}else if(g.type==="toolCall"){const f=g,[u,c]=f.id.split("|");let I=c;h&&I?.startsWith("fc_")&&(I=void 0),o.push({type:"function_call",id:I,call_id:u,name:f.name,arguments:JSON.stringify(f.arguments)})}if(o.length===0)continue;m.push(...o)}else if(s.role==="toolResult"){const o=s.content.filter(u=>u.type==="text").map(u=>u.text).join(`
2
- `),p=s.content.some(u=>u.type==="image"),h=o.length>0,[g]=s.toolCallId.split("|");let f;if(p&&r.input.includes("image")){const u=[];h&&u.push({type:"input_text",text:_(o)});for(const c of s.content)c.type==="image"&&u.push({type:"input_image",detail:"auto",image_url:`data:${c.mimeType};base64,${c.data}`});f=u}else f=_(h?o:"(see attached image)");m.push({type:"function_call_output",call_id:g,output:f})}e++}return m}function W(r,t){const l=t?.strict===void 0?!1:t.strict;return r.map(y=>({type:"function",name:y.name,description:y.description,parameters:y.parameters,strict:l}))}async function N(r,t,l,y,m){let i=null,n=null;const k=t.content,d=()=>k.length-1;for await(const a of r)if(a.type==="response.created")t.responseId=a.response.id;else if(a.type==="response.output_item.added"){const e=a.item;e.type==="reasoning"?(i=e,n={type:"thinking",thinking:""},t.content.push(n),l.push({type:"thinking_start",contentIndex:d(),partial:t})):e.type==="message"?(i=e,n={type:"text",text:""},t.content.push(n),l.push({type:"text_start",contentIndex:d(),partial:t})):e.type==="function_call"&&(i=e,n={type:"toolCall",id:`${e.call_id}|${e.id}`,name:e.name,arguments:{},partialJson:e.arguments||""},t.content.push(n),l.push({type:"toolcall_start",contentIndex:d(),partial:t}))}else if(a.type==="response.reasoning_summary_part.added")i&&i.type==="reasoning"&&(i.summary=i.summary||[],i.summary.push(a.part));else if(a.type==="response.reasoning_summary_text.delta"){if(i?.type==="reasoning"&&n?.type==="thinking"){i.summary=i.summary||[];const e=i.summary[i.summary.length-1];e&&(n.thinking+=a.delta,e.text+=a.delta,l.push({type:"thinking_delta",contentIndex:d(),delta:a.delta,partial:t}))}}else if(a.type==="response.reasoning_summary_part.done"){if(i?.type==="reasoning"&&n?.type==="thinking"){i.summary=i.summary||[];const e=i.summary[i.summary.length-1];e&&(n.thinking+=`
3
 
4
  `,e.text+=`
5
 
6
  `,l.push({type:"thinking_delta",contentIndex:d(),delta:`
7
 
8
- `,partial:t}))}}else if(a.type==="response.reasoning_text.delta")i?.type==="reasoning"&&n?.type==="thinking"&&(n.thinking+=a.delta,l.push({type:"thinking_delta",contentIndex:d(),delta:a.delta,partial:t}));else if(a.type==="response.content_part.added")i?.type==="message"&&(i.content=i.content||[],(a.part.type==="output_text"||a.part.type==="refusal")&&i.content.push(a.part));else if(a.type==="response.output_text.delta"){if(i?.type==="message"&&n?.type==="text"){if(!i.content||i.content.length===0)continue;const e=i.content[i.content.length-1];e?.type==="output_text"&&(n.text+=a.delta,e.text+=a.delta,l.push({type:"text_delta",contentIndex:d(),delta:a.delta,partial:t}))}}else if(a.type==="response.refusal.delta"){if(i?.type==="message"&&n?.type==="text"){if(!i.content||i.content.length===0)continue;const e=i.content[i.content.length-1];e?.type==="refusal"&&(n.text+=a.delta,e.refusal+=a.delta,l.push({type:"text_delta",contentIndex:d(),delta:a.delta,partial:t}))}}else if(a.type==="response.function_call_arguments.delta")i?.type==="function_call"&&n?.type==="toolCall"&&(n.partialJson+=a.delta,n.arguments=x(n.partialJson),l.push({type:"toolcall_delta",contentIndex:d(),delta:a.delta,partial:t}));else if(a.type==="response.function_call_arguments.done"){if(i?.type==="function_call"&&n?.type==="toolCall"){const e=n.partialJson;if(n.partialJson=a.arguments,n.arguments=x(n.partialJson),a.arguments.startsWith(e)){const s=a.arguments.slice(e.length);s.length>0&&l.push({type:"toolcall_delta",contentIndex:d(),delta:s,partial:t})}}}else if(a.type==="response.output_item.done"){const e=a.item;if(e.type==="reasoning"&&n?.type==="thinking"){const s=e.summary?.map(p=>p.text).join(`
9
 
10
- `)||"",o=e.content?.map(p=>p.text).join(`
11
 
12
- `)||"";n.thinking=s||o||n.thinking,n.thinkingSignature=JSON.stringify(e),l.push({type:"thinking_end",contentIndex:d(),content:n.thinking,partial:t}),n=null}else if(e.type==="message"&&n?.type==="text")n.text=e.content.map(s=>s.type==="output_text"?s.text:s.refusal).join(""),n.textSignature=T(e.id,e.phase??void 0),l.push({type:"text_end",contentIndex:d(),content:n.text,partial:t}),n=null;else if(e.type==="function_call"){const s=n?.type==="toolCall"&&n.partialJson?x(n.partialJson):x(e.arguments||"{}");let o;n?.type==="toolCall"?(n.arguments=s,delete n.partialJson,o=n):o={type:"toolCall",id:`${e.call_id}|${e.id}`,name:e.name,arguments:s},n=null,l.push({type:"toolcall_end",contentIndex:d(),toolCall:o,partial:t})}}else if(a.type==="response.completed"){const e=a.response;if(e?.id&&(t.responseId=e.id),e?.usage){const s=e.usage.input_tokens_details?.cached_tokens||0;t.usage={input:(e.usage.input_tokens||0)-s,output:e.usage.output_tokens||0,cacheRead:s,cacheWrite:0,totalTokens:e.usage.total_tokens||0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}}}if(S(y,t.usage),m?.applyServiceTierPricing){const s=m.resolveServiceTier?m.resolveServiceTier(e?.service_tier,m.serviceTier):e?.service_tier??m.serviceTier;m.applyServiceTierPricing(t.usage,s)}t.stopReason=J(e?.status),t.content.some(s=>s.type==="toolCall")&&t.stopReason==="stop"&&(t.stopReason="toolUse")}else{if(a.type==="error")throw new Error(`Error Code ${a.code}: ${a.message}`||"Unknown error");if(a.type==="response.failed"){const e=a.response?.error,s=a.response?.incomplete_details,o=e?`${e.code||"unknown"}: ${e.message||"no message"}`:s?.reason?`incomplete: ${s.reason}`:"Unknown error (no error details in response)";throw new Error(o)}}}function J(r){if(!r)return"stop";switch(r){case"completed":return"stop";case"incomplete":return"length";case"failed":case"cancelled":return"error";case"in_progress":case"queued":return"stop";default:{const t=r;throw new Error(`Unhandled stop reason: ${t}`)}}}export{W as a,M as c,N as p};
 
1
+ import{c as $}from"./index-CB_zB4U3.js";import{s as S}from"./hash-DMDecQcg.js";import{a as k}from"./json-parse-cUk3uCki.js";import{s as x}from"./sanitize-unicode-B62XMGgN.js";import{t as T}from"./transform-messages-DSNYjDRn.js";function C(r,t){const l={v:1,id:r};return t&&(l.phase=t),JSON.stringify(l)}function J(r){if(r){if(r.startsWith("{"))try{const t=JSON.parse(r);if(t.v===1&&typeof t.id=="string")return t.phase==="commentary"||t.phase==="final_answer"?{id:t.id,phase:t.phase}:{id:t.id}}catch{}return{id:r}}}function W(r,t,l,h){const u=[],i=s=>{const o=s.replace(/[^a-zA-Z0-9_-]/g,"_");return(o.length>64?o.slice(0,64):o).replace(/_+$/,"")},n=s=>{const o=`fc_${S(s)}`;return o.length>64?o.slice(0,64):o},I=(s,o,c)=>{if(!l.has(r.provider)||!s.includes("|"))return i(s);const[_,y]=s.split("|"),f=i(_);let m=c.provider!==r.provider||c.api!==r.api?n(y):i(y);return m.startsWith("fc_")||(m=i(`fc_${m}`)),`${f}|${m}`},d=T(t.messages,r,I);if((h?.includeSystemPrompt??!0)&&t.systemPrompt){const s=r.reasoning?"developer":"system";u.push({role:s,content:x(t.systemPrompt)})}let e=0;for(const s of d){if(s.role==="user")if(typeof s.content=="string")u.push({role:"user",content:[{type:"input_text",text:x(s.content)}]});else{const o=s.content.map(c=>c.type==="text"?{type:"input_text",text:x(c.text)}:{type:"input_image",detail:"auto",image_url:`data:${c.mimeType};base64,${c.data}`});if(o.length===0)continue;u.push({role:"user",content:o})}else if(s.role==="assistant"){const o=[],c=s,_=c.model!==r.id&&c.provider===r.provider&&c.api===r.api;let y=0;for(const f of s.content)if(f.type==="thinking"){if(f.thinkingSignature){const p=JSON.parse(f.thinkingSignature);o.push(p)}}else if(f.type==="text"){const p=f,m=J(p.textSignature),v=y===0?`msg_pi_${e}`:`msg_pi_${e}_${y}`;y++;let g=m?.id;g?g.length>64&&(g=`msg_${S(g)}`):g=v,o.push({type:"message",role:"assistant",content:[{type:"output_text",text:x(p.text),annotations:[]}],status:"completed",id:g,phase:m?.phase})}else if(f.type==="toolCall"){const p=f,[m,v]=p.id.split("|");let g=v;_&&g?.startsWith("fc_")&&(g=void 0),o.push({type:"function_call",id:g,call_id:m,name:p.name,arguments:JSON.stringify(p.arguments)})}if(o.length===0)continue;u.push(...o)}else if(s.role==="toolResult"){const o=s.content.filter(p=>p.type==="text").map(p=>p.text).join(`
2
+ `),c=s.content.some(p=>p.type==="image"),_=o.length>0,[y]=s.toolCallId.split("|");let f;if(c&&r.input.includes("image")){const p=[];_&&p.push({type:"input_text",text:x(o)});for(const m of s.content)m.type==="image"&&p.push({type:"input_image",detail:"auto",image_url:`data:${m.mimeType};base64,${m.data}`});f=p}else f=x(_?o:"(see attached image)");u.push({type:"function_call_output",call_id:y,output:f})}e++}return u}function N(r,t){const l=t?.strict===void 0?!1:t.strict;return r.map(h=>({type:"function",name:h.name,description:h.description,parameters:h.parameters,strict:l}))}async function O(r,t,l,h,u){let i=null,n=null;const I=t.content,d=()=>I.length-1;for await(const a of r)if(a.type==="response.created")t.responseId=a.response.id;else if(a.type==="response.output_item.added"){const e=a.item;e.type==="reasoning"?(i=e,n={type:"thinking",thinking:""},t.content.push(n),l.push({type:"thinking_start",contentIndex:d(),partial:t})):e.type==="message"?(i=e,n={type:"text",text:""},t.content.push(n),l.push({type:"text_start",contentIndex:d(),partial:t})):e.type==="function_call"&&(i=e,n={type:"toolCall",id:`${e.call_id}|${e.id}`,name:e.name,arguments:{},partialJson:e.arguments||""},t.content.push(n),l.push({type:"toolcall_start",contentIndex:d(),partial:t}))}else if(a.type==="response.reasoning_summary_part.added")i&&i.type==="reasoning"&&(i.summary=i.summary||[],i.summary.push(a.part));else if(a.type==="response.reasoning_summary_text.delta"){if(i?.type==="reasoning"&&n?.type==="thinking"){i.summary=i.summary||[];const e=i.summary[i.summary.length-1];e&&(n.thinking+=a.delta,e.text+=a.delta,l.push({type:"thinking_delta",contentIndex:d(),delta:a.delta,partial:t}))}}else if(a.type==="response.reasoning_summary_part.done"){if(i?.type==="reasoning"&&n?.type==="thinking"){i.summary=i.summary||[];const e=i.summary[i.summary.length-1];e&&(n.thinking+=`
3
 
4
  `,e.text+=`
5
 
6
  `,l.push({type:"thinking_delta",contentIndex:d(),delta:`
7
 
8
+ `,partial:t}))}}else if(a.type==="response.reasoning_text.delta")i?.type==="reasoning"&&n?.type==="thinking"&&(n.thinking+=a.delta,l.push({type:"thinking_delta",contentIndex:d(),delta:a.delta,partial:t}));else if(a.type==="response.content_part.added")i?.type==="message"&&(i.content=i.content||[],(a.part.type==="output_text"||a.part.type==="refusal")&&i.content.push(a.part));else if(a.type==="response.output_text.delta"){if(i?.type==="message"&&n?.type==="text"){if(!i.content||i.content.length===0)continue;const e=i.content[i.content.length-1];e?.type==="output_text"&&(n.text+=a.delta,e.text+=a.delta,l.push({type:"text_delta",contentIndex:d(),delta:a.delta,partial:t}))}}else if(a.type==="response.refusal.delta"){if(i?.type==="message"&&n?.type==="text"){if(!i.content||i.content.length===0)continue;const e=i.content[i.content.length-1];e?.type==="refusal"&&(n.text+=a.delta,e.refusal+=a.delta,l.push({type:"text_delta",contentIndex:d(),delta:a.delta,partial:t}))}}else if(a.type==="response.function_call_arguments.delta")i?.type==="function_call"&&n?.type==="toolCall"&&(n.partialJson+=a.delta,n.arguments=k(n.partialJson),l.push({type:"toolcall_delta",contentIndex:d(),delta:a.delta,partial:t}));else if(a.type==="response.function_call_arguments.done"){if(i?.type==="function_call"&&n?.type==="toolCall"){const e=n.partialJson;if(n.partialJson=a.arguments,n.arguments=k(n.partialJson),a.arguments.startsWith(e)){const s=a.arguments.slice(e.length);s.length>0&&l.push({type:"toolcall_delta",contentIndex:d(),delta:s,partial:t})}}}else if(a.type==="response.output_item.done"){const e=a.item;if(e.type==="reasoning"&&n?.type==="thinking"){const s=e.summary?.map(c=>c.text).join(`
9
 
10
+ `)||"",o=e.content?.map(c=>c.text).join(`
11
 
12
+ `)||"";n.thinking=s||o||n.thinking,n.thinkingSignature=JSON.stringify(e),l.push({type:"thinking_end",contentIndex:d(),content:n.thinking,partial:t}),n=null}else if(e.type==="message"&&n?.type==="text")n.text=e.content.map(s=>s.type==="output_text"?s.text:s.refusal).join(""),n.textSignature=C(e.id,e.phase??void 0),l.push({type:"text_end",contentIndex:d(),content:n.text,partial:t}),n=null;else if(e.type==="function_call"){const s=n?.type==="toolCall"&&n.partialJson?k(n.partialJson):k(e.arguments||"{}");let o;n?.type==="toolCall"?(n.arguments=s,delete n.partialJson,o=n):o={type:"toolCall",id:`${e.call_id}|${e.id}`,name:e.name,arguments:s},n=null,l.push({type:"toolcall_end",contentIndex:d(),toolCall:o,partial:t})}}else if(a.type==="response.completed"){const e=a.response;if(e?.id&&(t.responseId=e.id),e?.usage){const s=e.usage.input_tokens_details?.cached_tokens||0;t.usage={input:(e.usage.input_tokens||0)-s,output:e.usage.output_tokens||0,cacheRead:s,cacheWrite:0,totalTokens:e.usage.total_tokens||0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}}}if($(h,t.usage),u?.applyServiceTierPricing){const s=u.resolveServiceTier?u.resolveServiceTier(e?.service_tier,u.serviceTier):e?.service_tier??u.serviceTier;u.applyServiceTierPricing(t.usage,s)}t.stopReason=P(e?.status),t.content.some(s=>s.type==="toolCall")&&t.stopReason==="stop"&&(t.stopReason="toolUse")}else{if(a.type==="error")throw new Error(`Error Code ${a.code}: ${a.message}`||"Unknown error");if(a.type==="response.failed"){const e=a.response?.error,s=a.response?.incomplete_details,o=e?`${e.code||"unknown"}: ${e.message||"no message"}`:s?.reason?`incomplete: ${s.reason}`:"Unknown error (no error details in response)";throw new Error(o)}}}function P(r){if(!r)return"stop";switch(r){case"completed":return"stop";case"incomplete":return"length";case"failed":case"cancelled":return"error";case"in_progress":case"queued":return"stop";default:{const t=r;throw new Error(`Unhandled stop reason: ${t}`)}}}export{N as a,W as c,O as p};
dist/assets/openrouter-CMw3KGq6.js DELETED
@@ -1 +0,0 @@
1
- import{O as y}from"./client-Sq9UPDIz.js";import{g as R}from"./index-CgfZNSZZ.js";import{h as x}from"./headers-CgnjaPPL.js";import{s as _}from"./sanitize-unicode-B62XMGgN.js";const O=async(e,r,t)=>{const a={api:e.api,provider:e.provider,model:e.id,output:[],stopReason:"stop",timestamp:Date.now()};try{const s=t?.apiKey||R(e.provider);if(!s)throw new Error(`No API key available for provider: ${e.provider}`);const c=k(e,s,t?.headers);let n=w(e,r);const i=await t?.onPayload?.(n,e);i!==void 0&&(n=i);const o={...t?.signal?{signal:t.signal}:{},...t?.timeoutMs!==void 0?{timeout:t.timeoutMs}:{},...t?.maxRetries!==void 0?{maxRetries:t.maxRetries}:{}},{data:l,response:h}=await c.chat.completions.create(n,o).withResponse();await t?.onResponse?.({status:h.status,headers:x(h.headers)},e);const u=l;a.responseId=u.id,u.usage&&(a.usage=b(u.usage,e));const p=u.choices[0];if(p){const m=p.message.content;typeof m=="string"&&m.length>0&&a.output.push({type:"text",text:m});for(const d of p.message.images??[]){const f=typeof d.image_url=="string"?d.image_url:d.image_url?.url;if(!f?.startsWith("data:"))continue;const g=f.match(/^data:([^;]+);base64,(.+)$/);g&&a.output.push({type:"image",mimeType:g[1],data:g[2]})}}return a}catch(s){return a.stopReason=t?.signal?.aborted?"aborted":"error",a.errorMessage=s instanceof Error?s.message:JSON.stringify(s),a}};function k(e,r,t){return new y({apiKey:r,baseURL:e.baseUrl,dangerouslyAllowBrowser:!0,defaultHeaders:{...e.headers,...t}})}function w(e,r){const t=r.input.map(a=>a.type==="text"?{type:"text",text:_(a.text)}:{type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});return{model:e.id,messages:[{role:"user",content:t}],stream:!1,modalities:e.output.includes("text")?["image","text"]:["image"]}}function b(e,r){const t=e.prompt_tokens||0,a=e.prompt_tokens_details?.cached_tokens||0,s=e.prompt_tokens_details?.cache_write_tokens||0,c=s>0?Math.max(0,a-s):a,n=Math.max(0,t-c-s),i=e.completion_tokens||0,o={input:n,output:i,cacheRead:c,cacheWrite:s,totalTokens:n+i+c+s,cost:{input:r.cost.input/1e6*n,output:r.cost.output/1e6*i,cacheRead:r.cost.cacheRead/1e6*c,cacheWrite:r.cost.cacheWrite/1e6*s,total:0}};return o.cost.total=o.cost.input+o.cost.output+o.cost.cacheRead+o.cost.cacheWrite,o}export{O as generateImagesOpenRouter};
 
 
dist/assets/openrouter-DE7amXV2.js ADDED
@@ -0,0 +1 @@
 
 
1
+ import{O as y}from"./client-Sq9UPDIz.js";import{g as R}from"./index-CB_zB4U3.js";import{h as x}from"./headers-CgnjaPPL.js";import{s as _}from"./sanitize-unicode-B62XMGgN.js";const O=async(e,r,t)=>{const a={api:e.api,provider:e.provider,model:e.id,output:[],stopReason:"stop",timestamp:Date.now()};try{const s=t?.apiKey||R(e.provider);if(!s)throw new Error(`No API key available for provider: ${e.provider}`);const c=k(e,s,t?.headers);let n=w(e,r);const i=await t?.onPayload?.(n,e);i!==void 0&&(n=i);const o={...t?.signal?{signal:t.signal}:{},...t?.timeoutMs!==void 0?{timeout:t.timeoutMs}:{},maxRetries:t?.maxRetries??0},{data:l,response:d}=await c.chat.completions.create(n,o).withResponse();await t?.onResponse?.({status:d.status,headers:x(d.headers)},e);const u=l;a.responseId=u.id,u.usage&&(a.usage=b(u.usage,e));const p=u.choices[0];if(p){const m=p.message.content;typeof m=="string"&&m.length>0&&a.output.push({type:"text",text:m});for(const g of p.message.images??[]){const f=typeof g.image_url=="string"?g.image_url:g.image_url?.url;if(!f?.startsWith("data:"))continue;const h=f.match(/^data:([^;]+);base64,(.+)$/);h&&a.output.push({type:"image",mimeType:h[1],data:h[2]})}}return a}catch(s){return a.stopReason=t?.signal?.aborted?"aborted":"error",a.errorMessage=s instanceof Error?s.message:JSON.stringify(s),a}};function k(e,r,t){return new y({apiKey:r,baseURL:e.baseUrl,dangerouslyAllowBrowser:!0,defaultHeaders:{...e.headers,...t}})}function w(e,r){const t=r.input.map(a=>a.type==="text"?{type:"text",text:_(a.text)}:{type:"image_url",image_url:{url:`data:${a.mimeType};base64,${a.data}`}});return{model:e.id,messages:[{role:"user",content:t}],stream:!1,modalities:e.output.includes("text")?["image","text"]:["image"]}}function b(e,r){const t=e.prompt_tokens||0,a=e.prompt_tokens_details?.cached_tokens||0,s=e.prompt_tokens_details?.cache_write_tokens||0,c=s>0?Math.max(0,a-s):a,n=Math.max(0,t-c-s),i=e.completion_tokens||0,o={input:n,output:i,cacheRead:c,cacheWrite:s,totalTokens:n+i+c+s,cost:{input:r.cost.input/1e6*n,output:r.cost.output/1e6*i,cacheRead:r.cost.cacheRead/1e6*c,cacheWrite:r.cost.cacheWrite/1e6*s,total:0}};return o.cost.total=o.cost.input+o.cost.output+o.cost.cacheRead+o.cost.cacheWrite,o}export{O as generateImagesOpenRouter};
dist/assets/transform-messages-Bxe2XUr4.js DELETED
@@ -1 +0,0 @@
1
- function S(o,t,n){return{temperature:t?.temperature,maxTokens:t?.maxTokens,signal:t?.signal,apiKey:n||t?.apiKey,transport:t?.transport,cacheRetention:t?.cacheRetention,sessionId:t?.sessionId,headers:t?.headers,onPayload:t?.onPayload,onResponse:t?.onResponse,timeoutMs:t?.timeoutMs,maxRetries:t?.maxRetries,maxRetryDelayMs:t?.maxRetryDelayMs,metadata:t?.metadata}}function R(o){return o==="xhigh"?"high":o}function O(o,t,n,l){const m={...{minimal:1024,low:2048,medium:8192,high:16384},...l},u=1024,f=R(n);let s=m[f];const d=o===void 0?t:Math.min(o+s,t);return d<=s&&(s=Math.max(0,d-u)),{maxTokens:d,thinkingBudget:s}}const I="(image omitted: model does not support images)",M="(tool image omitted: model does not support images)";function y(o,t){const n=[];let l=!1;for(const h of o){if(h.type==="image"){l||n.push({type:"text",text:t}),l=!0;continue}n.push(h),l=h.text===t}return n}function C(o,t){return t.input.includes("image")?o:o.map(n=>n.role==="user"&&Array.isArray(n.content)?{...n,content:y(n.content,I)}:n.role==="toolResult"?{...n,content:y(n.content,M)}:n)}function w(o,t,n){const l=new Map,m=C(o,t).map(r=>{if(r.role==="user")return r;if(r.role==="toolResult"){const e=l.get(r.toolCallId);return e&&e!==r.toolCallId?{...r,toolCallId:e}:r}if(r.role==="assistant"){const e=r,i=e.provider===t.provider&&e.api===t.api&&e.model===t.id,g=e.content.flatMap(a=>{if(a.type==="thinking")return a.redacted?i?a:[]:i&&a.thinkingSignature?a:!a.thinking||a.thinking.trim()===""?[]:i?a:{type:"text",text:a.thinking};if(a.type==="text")return i?a:{type:"text",text:a.text};if(a.type==="toolCall"){const c=a;let p=c;if(!i&&c.thoughtSignature&&(p={...c},delete p.thoughtSignature),!i&&n){const x=n(c.id,t,e);x!==c.id&&(l.set(c.id,x),p={...p,id:x})}return p}return a});return{...e,content:g}}return r}),u=[];let f=[],s=new Set;const d=()=>{if(f.length>0){for(const r of f)s.has(r.id)||u.push({role:"toolResult",toolCallId:r.id,toolName:r.name,content:[{type:"text",text:"No result provided"}],isError:!0,timestamp:Date.now()});f=[],s=new Set}};for(let r=0;r<m.length;r++){const e=m[r];if(e.role==="assistant"){d();const i=e;if(i.stopReason==="error"||i.stopReason==="aborted")continue;const g=i.content.filter(a=>a.type==="toolCall");g.length>0&&(f=g,s=new Set),u.push(e)}else e.role==="toolResult"?(s.add(e.toolCallId),u.push(e)):(e.role==="user"&&d(),u.push(e))}return d(),u}export{O as a,S as b,w as t};
 
 
dist/assets/transform-messages-DSNYjDRn.js ADDED
@@ -0,0 +1 @@
 
 
1
+ function w(a,t,n){return{temperature:t?.temperature,maxTokens:t?.maxTokens,signal:t?.signal,apiKey:n||t?.apiKey,transport:t?.transport,cacheRetention:t?.cacheRetention,sessionId:t?.sessionId,headers:t?.headers,onPayload:t?.onPayload,onResponse:t?.onResponse,timeoutMs:t?.timeoutMs,websocketConnectTimeoutMs:t?.websocketConnectTimeoutMs,maxRetries:t?.maxRetries,maxRetryDelayMs:t?.maxRetryDelayMs,metadata:t?.metadata}}function R(a){return a==="xhigh"?"high":a}function S(a,t,n,l){const m={...{minimal:1024,low:2048,medium:8192,high:16384},...l},u=1024,f=R(n);let s=m[f];const d=a===void 0?t:Math.min(a+s,t);return d<=s&&(s=Math.max(0,d-u)),{maxTokens:d,thinkingBudget:s}}const I="(image omitted: model does not support images)",M="(tool image omitted: model does not support images)";function y(a,t){const n=[];let l=!1;for(const h of a){if(h.type==="image"){l||n.push({type:"text",text:t}),l=!0;continue}n.push(h),l=h.text===t}return n}function C(a,t){return t.input.includes("image")?a:a.map(n=>n.role==="user"&&Array.isArray(n.content)?{...n,content:y(n.content,I)}:n.role==="toolResult"?{...n,content:y(n.content,M)}:n)}function O(a,t,n){const l=new Map,m=C(a,t).map(r=>{if(r.role==="user")return r;if(r.role==="toolResult"){const e=l.get(r.toolCallId);return e&&e!==r.toolCallId?{...r,toolCallId:e}:r}if(r.role==="assistant"){const e=r,i=e.provider===t.provider&&e.api===t.api&&e.model===t.id,g=e.content.flatMap(o=>{if(o.type==="thinking")return o.redacted?i?o:[]:i&&o.thinkingSignature?o:!o.thinking||o.thinking.trim()===""?[]:i?o:{type:"text",text:o.thinking};if(o.type==="text")return i?o:{type:"text",text:o.text};if(o.type==="toolCall"){const c=o;let p=c;if(!i&&c.thoughtSignature&&(p={...c},delete p.thoughtSignature),!i&&n){const x=n(c.id,t,e);x!==c.id&&(l.set(c.id,x),p={...p,id:x})}return p}return o});return{...e,content:g}}return r}),u=[];let f=[],s=new Set;const d=()=>{if(f.length>0){for(const r of f)s.has(r.id)||u.push({role:"toolResult",toolCallId:r.id,toolName:r.name,content:[{type:"text",text:"No result provided"}],isError:!0,timestamp:Date.now()});f=[],s=new Set}};for(let r=0;r<m.length;r++){const e=m[r];if(e.role==="assistant"){d();const i=e;if(i.stopReason==="error"||i.stopReason==="aborted")continue;const g=i.content.filter(o=>o.type==="toolCall");g.length>0&&(f=g,s=new Set),u.push(e)}else e.role==="toolResult"?(s.add(e.toolCallId),u.push(e)):(e.role==="user"&&d(),u.push(e))}return d(),u}export{S as a,w as b,O as t};
dist/assets/xterm-B-qIQCd3.js ADDED
The diff for this file is too large to render. See raw diff
 
dist/index.html CHANGED
@@ -3,85 +3,26 @@
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Pi Web Agent</title>
7
- <script type="module" crossorigin src="/assets/index-CgfZNSZZ.js"></script>
8
- <link rel="stylesheet" crossorigin href="/assets/index-4NYd9uAS.css">
9
  </head>
10
  <body>
11
  <main id="app">
12
- <section class="app-shell">
13
- <header class="topbar">
14
- <div>
15
- <h1>Pi Web Agent</h1>
16
- <p id="model-label"></p>
17
- </div>
18
- <div class="status-stack" aria-label="Runtime status">
19
- <span class="status" id="status">Idle</span>
20
- <span class="status" id="model-status">Model idle</span>
21
- <span class="status" id="sandbox-status">Sandbox idle</span>
22
- </div>
23
- </header>
24
-
25
- <section class="layout">
26
- <section class="chat-panel" aria-label="Conversation">
27
- <div class="chat-scroll" id="chat"></div>
28
-
29
- <form class="composer" id="composer">
30
- <textarea id="prompt" spellcheck="true" rows="2">Create hello.js containing JavaScript that computes 21 * 2 and prints result: 42, then run node hello.js.</textarea>
31
- <div class="composer-actions">
32
- <button id="demo-prompt" type="button">Demo</button>
33
- <button id="send" type="submit">Send</button>
34
- </div>
35
- </form>
36
- </section>
37
-
38
- <aside class="side-panel" aria-label="Agent controls and sandbox">
39
- <section class="control-group">
40
- <h2>Runtime</h2>
41
- <label>
42
- Model
43
- <select id="mode">
44
- <option value="qwen25coder">Qwen2.5 Coder 0.5B planner</option>
45
- <option value="qwen">Qwen3 0.6B planner</option>
46
- <option value="minicpm">MiniCPM5 q4</option>
47
- <option value="mock">Deterministic test</option>
48
- </select>
49
- </label>
50
- <label>
51
- Device
52
- <select id="device">
53
- <option value="webgpu">WebGPU</option>
54
- <option value="wasm">WASM</option>
55
- </select>
56
- </label>
57
- <div class="compact-grid">
58
- <label>
59
- Max tokens
60
- <input id="max-new-tokens" type="number" min="16" max="8192" step="1" value="256" />
61
- </label>
62
- <label>
63
- Temperature
64
- <input id="temperature" type="number" min="0" max="1.5" step="0.05" value="0" />
65
- </label>
66
- </div>
67
- <button id="load-model" type="button">Download Model</button>
68
- </section>
69
-
70
- <section class="control-group">
71
- <h2>Sandbox</h2>
72
- <div class="button-row">
73
- <button id="boot-sandbox" type="button">Boot</button>
74
- <button id="reset-sandbox" type="button">Reset</button>
75
- </div>
76
- <pre id="files"></pre>
77
- </section>
78
 
79
- <section class="control-group">
80
- <h2>Events</h2>
81
- <pre id="event-log"></pre>
82
- </section>
83
- </aside>
84
- </section>
85
  </section>
86
 
87
  <section class="model-gate" id="model-gate" aria-labelledby="model-gate-title" aria-modal="true" role="dialog">
@@ -90,7 +31,7 @@
90
  <p class="eyebrow">Local model setup</p>
91
  <h2 id="model-gate-title">Download the selected model to this browser?</h2>
92
  <p class="dialog-copy">
93
- The agent can run fully locally with a q4 ONNX model in Transformers.js. The download is large and stays in the browser cache when possible.
94
  </p>
95
  </div>
96
  <div class="dialog-actions">
 
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Pi CLI Web</title>
7
+ <script type="module" crossorigin src="/assets/index-CB_zB4U3.js"></script>
8
+ <link rel="stylesheet" crossorigin href="/assets/index-NRwwiW4N.css">
9
  </head>
10
  <body>
11
  <main id="app">
12
+ <header class="runtime-bar" aria-label="Runtime status">
13
+ <div>
14
+ <h1>pi</h1>
15
+ <p id="model-label"></p>
16
+ </div>
17
+ <div class="status-stack">
18
+ <span class="status" id="status">Idle</span>
19
+ <span class="status" id="model-status">Model idle</span>
20
+ <span class="status" id="sandbox-status">Sandbox idle</span>
21
+ </div>
22
+ </header>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
23
 
24
+ <section class="terminal-shell" aria-label="Pi terminal">
25
+ <div id="terminal"></div>
 
 
 
 
26
  </section>
27
 
28
  <section class="model-gate" id="model-gate" aria-labelledby="model-gate-title" aria-modal="true" role="dialog">
 
31
  <p class="eyebrow">Local model setup</p>
32
  <h2 id="model-gate-title">Download the selected model to this browser?</h2>
33
  <p class="dialog-copy">
34
+ This static web port runs pi with Transformers.js and WebContainers. The model download stays in browser storage when possible.
35
  </p>
36
  </div>
37
  <div class="dialog-actions">
index.html CHANGED
@@ -3,83 +3,24 @@
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
- <title>Pi Web Agent</title>
7
  </head>
8
  <body>
9
  <main id="app">
10
- <section class="app-shell">
11
- <header class="topbar">
12
- <div>
13
- <h1>Pi Web Agent</h1>
14
- <p id="model-label"></p>
15
- </div>
16
- <div class="status-stack" aria-label="Runtime status">
17
- <span class="status" id="status">Idle</span>
18
- <span class="status" id="model-status">Model idle</span>
19
- <span class="status" id="sandbox-status">Sandbox idle</span>
20
- </div>
21
- </header>
22
-
23
- <section class="layout">
24
- <section class="chat-panel" aria-label="Conversation">
25
- <div class="chat-scroll" id="chat"></div>
26
-
27
- <form class="composer" id="composer">
28
- <textarea id="prompt" spellcheck="true" rows="2">Create hello.js containing JavaScript that computes 21 * 2 and prints result: 42, then run node hello.js.</textarea>
29
- <div class="composer-actions">
30
- <button id="demo-prompt" type="button">Demo</button>
31
- <button id="send" type="submit">Send</button>
32
- </div>
33
- </form>
34
- </section>
35
-
36
- <aside class="side-panel" aria-label="Agent controls and sandbox">
37
- <section class="control-group">
38
- <h2>Runtime</h2>
39
- <label>
40
- Model
41
- <select id="mode">
42
- <option value="qwen25coder">Qwen2.5 Coder 0.5B planner</option>
43
- <option value="qwen">Qwen3 0.6B planner</option>
44
- <option value="minicpm">MiniCPM5 q4</option>
45
- <option value="mock">Deterministic test</option>
46
- </select>
47
- </label>
48
- <label>
49
- Device
50
- <select id="device">
51
- <option value="webgpu">WebGPU</option>
52
- <option value="wasm">WASM</option>
53
- </select>
54
- </label>
55
- <div class="compact-grid">
56
- <label>
57
- Max tokens
58
- <input id="max-new-tokens" type="number" min="16" max="8192" step="1" value="256" />
59
- </label>
60
- <label>
61
- Temperature
62
- <input id="temperature" type="number" min="0" max="1.5" step="0.05" value="0" />
63
- </label>
64
- </div>
65
- <button id="load-model" type="button">Download Model</button>
66
- </section>
67
-
68
- <section class="control-group">
69
- <h2>Sandbox</h2>
70
- <div class="button-row">
71
- <button id="boot-sandbox" type="button">Boot</button>
72
- <button id="reset-sandbox" type="button">Reset</button>
73
- </div>
74
- <pre id="files"></pre>
75
- </section>
76
 
77
- <section class="control-group">
78
- <h2>Events</h2>
79
- <pre id="event-log"></pre>
80
- </section>
81
- </aside>
82
- </section>
83
  </section>
84
 
85
  <section class="model-gate" id="model-gate" aria-labelledby="model-gate-title" aria-modal="true" role="dialog">
@@ -88,7 +29,7 @@
88
  <p class="eyebrow">Local model setup</p>
89
  <h2 id="model-gate-title">Download the selected model to this browser?</h2>
90
  <p class="dialog-copy">
91
- The agent can run fully locally with a q4 ONNX model in Transformers.js. The download is large and stays in the browser cache when possible.
92
  </p>
93
  </div>
94
  <div class="dialog-actions">
 
3
  <head>
4
  <meta charset="UTF-8" />
5
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
6
+ <title>Pi CLI Web</title>
7
  </head>
8
  <body>
9
  <main id="app">
10
+ <header class="runtime-bar" aria-label="Runtime status">
11
+ <div>
12
+ <h1>pi</h1>
13
+ <p id="model-label"></p>
14
+ </div>
15
+ <div class="status-stack">
16
+ <span class="status" id="status">Idle</span>
17
+ <span class="status" id="model-status">Model idle</span>
18
+ <span class="status" id="sandbox-status">Sandbox idle</span>
19
+ </div>
20
+ </header>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
+ <section class="terminal-shell" aria-label="Pi terminal">
23
+ <div id="terminal"></div>
 
 
 
 
24
  </section>
25
 
26
  <section class="model-gate" id="model-gate" aria-labelledby="model-gate-title" aria-modal="true" role="dialog">
 
29
  <p class="eyebrow">Local model setup</p>
30
  <h2 id="model-gate-title">Download the selected model to this browser?</h2>
31
  <p class="dialog-copy">
32
+ This static web port runs pi with Transformers.js and WebContainers. The model download stays in browser storage when possible.
33
  </p>
34
  </div>
35
  <div class="dialog-actions">
package-lock.json CHANGED
The diff for this file is too large to render. See raw diff
 
package.json CHANGED
@@ -6,6 +6,7 @@
6
  "dev": "vite --host 0.0.0.0",
7
  "build": "vite build",
8
  "preview": "vite preview --host 0.0.0.0",
 
9
  "probe:tokens": "node scripts/probe_token_budgets.mjs",
10
  "smoke:complex": "node scripts/smoke_complex_tasks.mjs",
11
  "smoke:local-model": "node scripts/smoke_local_model_web_agent.mjs",
@@ -13,10 +14,14 @@
13
  "verify": "node scripts/verify_tjs_model.mjs"
14
  },
15
  "dependencies": {
16
- "@earendil-works/pi-agent-core": "^0.75.5",
17
- "@earendil-works/pi-ai": "^0.75.5",
 
18
  "@huggingface/transformers": "^4.2.0",
19
  "@webcontainer/api": "^1.6.4",
 
 
 
20
  "vite": "^7.2.0"
21
  },
22
  "devDependencies": {
 
6
  "dev": "vite --host 0.0.0.0",
7
  "build": "vite build",
8
  "preview": "vite preview --host 0.0.0.0",
9
+ "parity:cli": "node scripts/compare_pi_cli_parity.mjs",
10
  "probe:tokens": "node scripts/probe_token_budgets.mjs",
11
  "smoke:complex": "node scripts/smoke_complex_tasks.mjs",
12
  "smoke:local-model": "node scripts/smoke_local_model_web_agent.mjs",
 
14
  "verify": "node scripts/verify_tjs_model.mjs"
15
  },
16
  "dependencies": {
17
+ "@earendil-works/pi-agent-core": "0.77.0",
18
+ "@earendil-works/pi-ai": "0.77.0",
19
+ "@earendil-works/pi-coding-agent": "0.77.0",
20
  "@huggingface/transformers": "^4.2.0",
21
  "@webcontainer/api": "^1.6.4",
22
+ "@xterm/addon-fit": "0.11.0",
23
+ "@xterm/xterm": "6.0.0",
24
+ "ghostty-web": "0.4.0",
25
  "vite": "^7.2.0"
26
  },
27
  "devDependencies": {
scripts/compare_pi_cli_parity.mjs ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { chromium } from "@playwright/test";
2
+ import { spawnSync } from "node:child_process";
3
+ import { existsSync } from "node:fs";
4
+
5
+ const baseUrl = process.argv[2] || "http://localhost:5173/?mode=mock&device=wasm";
6
+ const executablePath = process.env.CHROMIUM_PATH || (existsSync("/usr/bin/google-chrome") ? "/usr/bin/google-chrome" : "/snap/bin/chromium");
7
+
8
+ function extractToolBlock(text) {
9
+ const start = text.indexOf("Built-in Tool Names:");
10
+ if (start === -1) throw new Error("Missing Built-in Tool Names block.");
11
+ return text.slice(start).trim();
12
+ }
13
+
14
+ const piCli = "node_modules/@earendil-works/pi-coding-agent/dist/cli.js";
15
+ function runPi(args) {
16
+ const result = spawnSync(process.execPath, [piCli, ...args], {
17
+ cwd: process.cwd(),
18
+ encoding: "utf-8",
19
+ });
20
+ if (result.status !== 0) {
21
+ throw new Error(`pi ${args.join(" ")} failed:\n${result.stderr || result.stdout}`);
22
+ }
23
+ return `${result.stdout || ""}${result.stderr || ""}`;
24
+ }
25
+
26
+ const cliHelp = runPi(["--help"]);
27
+ const cliVersion = runPi(["--version"]).trim();
28
+
29
+ const browser = await chromium.launch({
30
+ executablePath,
31
+ headless: true,
32
+ args: ["--no-sandbox", "--disable-dev-shm-usage"],
33
+ });
34
+
35
+ try {
36
+ const page = await browser.newPage();
37
+ page.setDefaultTimeout(120000);
38
+ await page.goto(baseUrl, { waitUntil: "domcontentloaded" });
39
+ await page.waitForFunction(() => window.__piCliWeb?.status === "Ready");
40
+ await page.evaluate(() => window.__piWebAgent.runInput("/help"));
41
+ await page.waitForFunction(() => window.__piCliWeb?.outputText?.includes("Built-in Tool Names:"));
42
+ await page.evaluate(() => window.__piWebAgent.runInput("/commands"));
43
+ await page.waitForFunction(() => window.__piCliWeb?.outputText?.includes("/compact [prompt]"));
44
+
45
+ const terminalText = await page.evaluate(() => window.__piCliWeb.outputText);
46
+ const cliToolBlock = extractToolBlock(cliHelp);
47
+ const webToolBlock = extractToolBlock(terminalText);
48
+ const requiredHelpLines = [
49
+ "pi - AI coding assistant with read, bash, edit, write tools",
50
+ "Usage:",
51
+ "--model <pattern>",
52
+ "--tools, -t <tools>",
53
+ "--exclude-tools, -xt <tools>",
54
+ "Built-in Tool Names:",
55
+ ];
56
+ const requiredSlashCommands = [
57
+ "/login",
58
+ "/model",
59
+ "/settings",
60
+ "/session",
61
+ "/tree",
62
+ "/compact [prompt]",
63
+ "/quit",
64
+ ];
65
+
66
+ for (const line of requiredHelpLines) {
67
+ if (!terminalText.includes(line) || !cliHelp.includes(line)) {
68
+ throw new Error(`Help parity failed for line: ${line}`);
69
+ }
70
+ }
71
+ for (const command of requiredSlashCommands) {
72
+ if (!terminalText.includes(command)) {
73
+ throw new Error(`Missing web slash command: ${command}`);
74
+ }
75
+ }
76
+ for (const tool of ["read", "bash", "edit", "write", "grep", "find", "ls"]) {
77
+ const marker = `${tool} `;
78
+ if (!cliToolBlock.includes(marker) || !webToolBlock.includes(marker)) {
79
+ throw new Error(`Tool parity failed for ${tool}.\nCLI:\n${cliToolBlock}\n\nWeb:\n${webToolBlock}`);
80
+ }
81
+ }
82
+ if (!terminalText.includes(`version ${cliVersion}`)) {
83
+ throw new Error(`Expected web startup to include CLI version ${cliVersion}.\n\nTerminal:\n${terminalText}`);
84
+ }
85
+
86
+ console.log(JSON.stringify({ ok: true, cliVersion, checkedTools: ["read", "bash", "edit", "write", "grep", "find", "ls"] }, null, 2));
87
+ } finally {
88
+ await browser.close();
89
+ }
scripts/probe_token_budgets.mjs CHANGED
@@ -1,7 +1,7 @@
1
  import { chromium } from "@playwright/test";
2
  import { existsSync } from "node:fs";
3
 
4
- const baseUrl = process.argv[2] || "http://localhost:5173/?device=wasm";
5
  const budgets = (process.env.TOKEN_BUDGETS || "80,256,2048,8192")
6
  .split(",")
7
  .map((value) => value.trim())
@@ -35,34 +35,29 @@ for (const budget of budgets) {
35
  });
36
 
37
  const started = Date.now();
38
- await page.goto(baseUrl, { waitUntil: "networkidle" });
39
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Ready");
40
- await page.fill("#max-new-tokens", budget);
41
- await page.fill("#temperature", "0");
42
- await page.selectOption("#gate-device", "wasm");
43
- await page.click("#confirm-load-model");
44
- await page.waitForFunction(() => window.__piWebAgent?.modelReady === true, null, {
45
- timeout: 600000,
46
- });
47
  result.loadMs = Date.now() - started;
48
 
49
  const runStarted = Date.now();
50
- await page.click("#send");
51
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Agent running", null, {
52
- timeout: 120000,
53
- });
54
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Ready", null, {
55
  timeout: 1200000,
56
  });
57
- await page.waitForFunction(() => window.__piWebAgent?.transcript?.includes("42"), null, {
58
- timeout: 120000,
59
- });
60
  result.runMs = Date.now() - runStarted;
61
 
62
  const transcript = await page.evaluate(() => window.__piWebAgent?.transcript || "");
63
- const files = await page.textContent("#files");
64
  result.modelStatus = await page.textContent("#model-status");
65
- result.ok = transcript.includes("42") && files?.includes("hello.js");
66
  result.transcriptChars = transcript.length;
67
  } catch (error) {
68
  result.error = error instanceof Error ? error.message : String(error);
 
1
  import { chromium } from "@playwright/test";
2
  import { existsSync } from "node:fs";
3
 
4
+ const baseUrl = process.argv[2] || "http://localhost:5173/?model=qwen25coder&device=wasm";
5
  const budgets = (process.env.TOKEN_BUDGETS || "80,256,2048,8192")
6
  .split(",")
7
  .map((value) => value.trim())
 
35
  });
36
 
37
  const started = Date.now();
38
+ await page.goto(`${baseUrl}&tokens=${budget}`, { waitUntil: "domcontentloaded" });
39
+ await page.waitForFunction(() => window.__piCliWeb?.status === "Ready");
40
+ if (!(await page.evaluate(() => window.__piWebAgent?.modelReady === true))) {
41
+ await page.evaluate(() => window.__piWebAgent.loadModel());
42
+ await page.waitForFunction(() => window.__piWebAgent?.modelReady === true, null, {
43
+ timeout: 600000,
44
+ });
45
+ }
 
46
  result.loadMs = Date.now() - started;
47
 
48
  const runStarted = Date.now();
49
+ await page.evaluate(() =>
50
+ window.__piWebAgent.runInput("Create hello.js containing JavaScript that computes 21 * 2 and prints result: 42, then run node hello.js."),
51
+ );
52
+ await page.waitForFunction(() => window.__piCliWeb?.status === "Ready" && window.__piWebAgent?.transcript?.includes("42"), null, {
 
53
  timeout: 1200000,
54
  });
 
 
 
55
  result.runMs = Date.now() - runStarted;
56
 
57
  const transcript = await page.evaluate(() => window.__piWebAgent?.transcript || "");
58
+ const terminalText = await page.evaluate(() => window.__piCliWeb?.outputText || "");
59
  result.modelStatus = await page.textContent("#model-status");
60
+ result.ok = transcript.includes("42") && terminalText.includes("write hello.js");
61
  result.transcriptChars = transcript.length;
62
  } catch (error) {
63
  result.error = error instanceof Error ? error.message : String(error);
scripts/smoke_complex_tasks.mjs CHANGED
@@ -11,21 +11,21 @@ const tasks = [
11
  prompt:
12
  "Create hello.js containing JavaScript that computes 21 * 2 and prints result: 42, then run node hello.js.",
13
  expectedOutput: "42",
14
- expectedFiles: ["hello.js"],
15
  },
16
  {
17
  id: "npm-dependency",
18
  prompt:
19
  "Install npm package is-number@7.0.0, create check-package.mjs that imports it and prints dependency check: true, then run it with Node.",
20
  expectedOutput: "dependency check: true",
21
- expectedFiles: ["check-package.mjs", "node_modules"],
22
  },
23
  {
24
  id: "multi-file-module",
25
  prompt:
26
  "Create src/math.mjs exporting multiply(a,b), create test.mjs importing it and printing multi result: 42 for multiply(6,7), then run node test.mjs.",
27
  expectedOutput: "multi result: 42",
28
- expectedFiles: ["test.mjs", "src"],
29
  },
30
  ];
31
 
@@ -47,48 +47,39 @@ async function runTask(task) {
47
  consoleLines.push(`pageerror: ${error.stack || error.message}`);
48
  });
49
 
50
- await page.goto(baseUrl, { waitUntil: "networkidle" });
51
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Ready");
52
  const isolated = await page.evaluate(() => globalThis.crossOriginIsolated);
53
  if (!isolated) throw new Error("Page is not cross-origin isolated.");
54
 
55
- await page.fill("#max-new-tokens", maxNewTokens);
56
- await page.fill("#temperature", "0");
57
- await page.selectOption("#gate-device", "wasm");
58
- await page.click("#confirm-load-model");
59
- await page.waitForFunction(() => window.__piWebAgent?.modelReady === true, null, {
60
- timeout: 600000,
61
- });
62
 
63
  const started = Date.now();
64
- await page.fill("#prompt", task.prompt);
65
- await page.click("#send");
66
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Agent running", null, {
67
- timeout: 120000,
68
- });
69
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Ready", null, {
70
- timeout: 1200000,
71
- });
72
 
73
  const transcript = await page.evaluate(() => window.__piWebAgent?.transcript || "");
74
- const files = await page.textContent("#files");
75
- const events = await page.textContent("#event-log");
76
  const modelStatus = await page.textContent("#model-status");
77
- const lowerTranscript = transcript.toLowerCase();
78
- const lowerEvents = events?.toLowerCase() || "";
79
- const lowerFiles = files?.toLowerCase() || "";
80
 
81
- if (!lowerTranscript.includes(task.expectedOutput.toLowerCase())) {
82
- throw new Error(`Expected output ${task.expectedOutput}.\n\nTranscript:\n${transcript}\n\nEvents:\n${events}`);
83
  }
84
- for (const file of task.expectedFiles) {
85
- if (!lowerFiles.includes(file.toLowerCase())) {
86
- throw new Error(`Expected ${file} in file listing.\n\nFiles:\n${files}\n\nTranscript:\n${transcript}`);
87
  }
88
  }
89
- if (!lowerEvents.includes("tool: run_command finished")) {
90
- throw new Error(`Expected run_command tool execution.\n\nEvents:\n${events}`);
91
- }
92
 
93
  return {
94
  id: task.id,
@@ -96,7 +87,6 @@ async function runTask(task) {
96
  maxNewTokens,
97
  modelStatus,
98
  runMs: Date.now() - started,
99
- files,
100
  transcriptChars: transcript.length,
101
  warnings: consoleLines.filter((line) => line.startsWith("warning:")).slice(-3),
102
  };
 
11
  prompt:
12
  "Create hello.js containing JavaScript that computes 21 * 2 and prints result: 42, then run node hello.js.",
13
  expectedOutput: "42",
14
+ expectedTerminal: ["write hello.js", "$ node hello.js"],
15
  },
16
  {
17
  id: "npm-dependency",
18
  prompt:
19
  "Install npm package is-number@7.0.0, create check-package.mjs that imports it and prints dependency check: true, then run it with Node.",
20
  expectedOutput: "dependency check: true",
21
+ expectedTerminal: ["npm install is-number@7.0.0", "$ node check-package.mjs"],
22
  },
23
  {
24
  id: "multi-file-module",
25
  prompt:
26
  "Create src/math.mjs exporting multiply(a,b), create test.mjs importing it and printing multi result: 42 for multiply(6,7), then run node test.mjs.",
27
  expectedOutput: "multi result: 42",
28
+ expectedTerminal: ["write src/math.mjs", "write test.mjs", "$ node test.mjs"],
29
  },
30
  ];
31
 
 
47
  consoleLines.push(`pageerror: ${error.stack || error.message}`);
48
  });
49
 
50
+ await page.goto(`${baseUrl}&tokens=${maxNewTokens}`, { waitUntil: "domcontentloaded" });
51
+ await page.waitForFunction(() => window.__piCliWeb?.status === "Ready");
52
  const isolated = await page.evaluate(() => globalThis.crossOriginIsolated);
53
  if (!isolated) throw new Error("Page is not cross-origin isolated.");
54
 
55
+ if (!(await page.evaluate(() => window.__piWebAgent?.modelReady === true))) {
56
+ await page.evaluate(() => window.__piWebAgent.loadModel());
57
+ await page.waitForFunction(() => window.__piWebAgent?.modelReady === true, null, {
58
+ timeout: 600000,
59
+ });
60
+ }
 
61
 
62
  const started = Date.now();
63
+ await page.evaluate((prompt) => window.__piWebAgent.runInput(prompt), task.prompt);
64
+ await page.waitForFunction(
65
+ (expected) => window.__piCliWeb?.status === "Ready" && window.__piCliWeb?.outputText?.toLowerCase().includes(expected.toLowerCase()),
66
+ task.expectedOutput,
67
+ { timeout: 1200000 },
68
+ );
 
 
69
 
70
  const transcript = await page.evaluate(() => window.__piWebAgent?.transcript || "");
71
+ const terminalText = await page.evaluate(() => window.__piCliWeb?.outputText || "");
 
72
  const modelStatus = await page.textContent("#model-status");
73
+ const lowerTerminal = terminalText.toLowerCase();
 
 
74
 
75
+ if (!lowerTerminal.includes(task.expectedOutput.toLowerCase()) || !transcript.toLowerCase().includes(task.expectedOutput.toLowerCase())) {
76
+ throw new Error(`Expected output ${task.expectedOutput}.\n\nTranscript:\n${transcript}\n\nTerminal:\n${terminalText}`);
77
  }
78
+ for (const marker of task.expectedTerminal) {
79
+ if (!lowerTerminal.includes(marker.toLowerCase())) {
80
+ throw new Error(`Expected terminal marker ${marker}.\n\nTerminal:\n${terminalText}`);
81
  }
82
  }
 
 
 
83
 
84
  return {
85
  id: task.id,
 
87
  maxNewTokens,
88
  modelStatus,
89
  runMs: Date.now() - started,
 
90
  transcriptChars: transcript.length,
91
  warnings: consoleLines.filter((line) => line.startsWith("warning:")).slice(-3),
92
  };
scripts/smoke_local_model_web_agent.mjs CHANGED
@@ -1,7 +1,7 @@
1
  import { chromium } from "@playwright/test";
2
  import { existsSync } from "node:fs";
3
 
4
- const baseUrl = process.argv[2] || "http://localhost:5173/?device=wasm";
5
  const executablePath = process.env.CHROMIUM_PATH || (existsSync("/usr/bin/google-chrome") ? "/usr/bin/google-chrome" : "/snap/bin/chromium");
6
  const maxNewTokens = process.env.MAX_NEW_TOKENS || "80";
7
 
@@ -13,7 +13,7 @@ const browser = await chromium.launch({
13
 
14
  try {
15
  const page = await browser.newPage();
16
- page.setDefaultTimeout(600000);
17
  const consoleLines = [];
18
  page.on("console", (message) => {
19
  consoleLines.push(`${message.type()}: ${message.text()}`);
@@ -22,48 +22,38 @@ try {
22
  consoleLines.push(`pageerror: ${error.stack || error.message}`);
23
  });
24
 
25
- await page.goto(baseUrl, { waitUntil: "networkidle" });
26
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Ready");
27
 
28
  const isolated = await page.evaluate(() => globalThis.crossOriginIsolated);
29
  if (!isolated) throw new Error("Page is not cross-origin isolated.");
30
 
31
- await page.fill("#max-new-tokens", maxNewTokens);
32
- await page.fill("#temperature", "0");
33
- await page.selectOption("#gate-device", "wasm");
34
- await page.click("#confirm-load-model");
35
- await page.waitForFunction(() => window.__piWebAgent?.modelReady === true, null, {
36
- timeout: 600000,
37
- });
38
 
39
- await page.click("#send");
40
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Agent running", null, {
41
- timeout: 120000,
42
- });
43
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Ready", null, {
44
  timeout: 600000,
45
  });
46
- await page.waitForFunction(() => window.__piWebAgent?.transcript?.includes("42"), null, {
47
- timeout: 120000,
48
- });
49
 
50
  const transcript = await page.evaluate(() => window.__piWebAgent?.transcript || "");
51
- const chatText = await page.textContent("#chat");
52
- const files = await page.textContent("#files");
53
- const events = await page.textContent("#event-log");
54
  const modelStatus = await page.textContent("#model-status");
55
 
56
- if (!transcript.includes("42") || !chatText?.includes("42")) {
57
- throw new Error(`Expected command output in chat transcript.\n\nTranscript:\n${transcript}\n\nChat:\n${chatText}\n\nEvents:\n${events}`);
58
- }
59
- if (!files?.includes("hello.js")) {
60
- throw new Error(`Expected hello.js in file listing.\n\nFiles:\n${files}`);
61
  }
62
  if (modelStatus !== "Model ready") {
63
  throw new Error(`Expected local model status to be ready, got: ${modelStatus}`);
64
  }
65
 
66
- console.log(JSON.stringify({ ok: true, isolated, maxNewTokens, modelStatus, transcript, files }, null, 2));
67
  } catch (error) {
68
  console.error(error instanceof Error ? error.stack || error.message : String(error));
69
  throw error;
 
1
  import { chromium } from "@playwright/test";
2
  import { existsSync } from "node:fs";
3
 
4
+ const baseUrl = process.argv[2] || "http://localhost:5173/?model=qwen25coder&device=wasm";
5
  const executablePath = process.env.CHROMIUM_PATH || (existsSync("/usr/bin/google-chrome") ? "/usr/bin/google-chrome" : "/snap/bin/chromium");
6
  const maxNewTokens = process.env.MAX_NEW_TOKENS || "80";
7
 
 
13
 
14
  try {
15
  const page = await browser.newPage();
16
+ page.setDefaultTimeout(900000);
17
  const consoleLines = [];
18
  page.on("console", (message) => {
19
  consoleLines.push(`${message.type()}: ${message.text()}`);
 
22
  consoleLines.push(`pageerror: ${error.stack || error.message}`);
23
  });
24
 
25
+ await page.goto(`${baseUrl}&tokens=${maxNewTokens}`, { waitUntil: "domcontentloaded" });
26
+ await page.waitForFunction(() => window.__piCliWeb?.status === "Ready");
27
 
28
  const isolated = await page.evaluate(() => globalThis.crossOriginIsolated);
29
  if (!isolated) throw new Error("Page is not cross-origin isolated.");
30
 
31
+ if (!(await page.evaluate(() => window.__piWebAgent?.modelReady === true))) {
32
+ await page.evaluate(() => window.__piWebAgent.loadModel());
33
+ await page.waitForFunction(() => window.__piWebAgent?.modelReady === true, null, {
34
+ timeout: 600000,
35
+ });
36
+ }
 
37
 
38
+ await page.evaluate(() =>
39
+ window.__piWebAgent.runInput("Create hello.js containing JavaScript that computes 21 * 2 and prints result: 42, then run node hello.js."),
40
+ );
41
+ await page.waitForFunction(() => window.__piCliWeb?.status === "Ready" && window.__piWebAgent?.transcript?.includes("42"), null, {
 
42
  timeout: 600000,
43
  });
 
 
 
44
 
45
  const transcript = await page.evaluate(() => window.__piWebAgent?.transcript || "");
46
+ const terminalText = await page.evaluate(() => window.__piCliWeb?.outputText || "");
 
 
47
  const modelStatus = await page.textContent("#model-status");
48
 
49
+ if (!transcript.includes("42") || !terminalText.includes("42")) {
50
+ throw new Error(`Expected command output in terminal transcript.\n\nTranscript:\n${transcript}\n\nTerminal:\n${terminalText}`);
 
 
 
51
  }
52
  if (modelStatus !== "Model ready") {
53
  throw new Error(`Expected local model status to be ready, got: ${modelStatus}`);
54
  }
55
 
56
+ console.log(JSON.stringify({ ok: true, isolated, maxNewTokens, modelStatus, transcriptChars: transcript.length, warnings: consoleLines.filter((line) => line.startsWith("warning:")).slice(-3) }, null, 2));
57
  } catch (error) {
58
  console.error(error instanceof Error ? error.stack || error.message : String(error));
59
  throw error;
scripts/smoke_web_agent.mjs CHANGED
@@ -12,7 +12,7 @@ const browser = await chromium.launch({
12
 
13
  try {
14
  const page = await browser.newPage();
15
- page.setDefaultTimeout(90000);
16
 
17
  const consoleLines = [];
18
  page.on("console", (message) => {
@@ -23,37 +23,50 @@ try {
23
  });
24
 
25
  await page.goto(baseUrl, { waitUntil: "domcontentloaded" });
 
26
  const isolated = await page.evaluate(() => globalThis.crossOriginIsolated);
27
- if (!isolated) {
28
- throw new Error("Page is not cross-origin isolated.");
29
- }
 
 
 
30
 
31
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Ready");
32
- await page.click("#send");
33
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Agent running", null, {
34
  timeout: 120000,
35
  });
36
- await page.waitForFunction(() => window.__piWebAgent?.transcript?.includes("pi sandbox result: 42"), null, {
 
 
 
 
37
  timeout: 120000,
38
  });
39
- await page.waitForFunction(() => document.querySelector("#status")?.textContent === "Ready");
40
 
 
41
  const transcript = await page.evaluate(() => window.__piWebAgent?.transcript || "");
42
- const chatText = await page.textContent("#chat");
43
- const files = await page.textContent("#files");
44
- const events = await page.textContent("#event-log");
 
 
 
 
 
 
45
 
46
- if (!transcript.includes("pi sandbox result: 42") || !chatText?.includes("pi sandbox result: 42")) {
47
- throw new Error(`Expected command output in chat transcript.\n\nTranscript:\n${transcript}\n\nChat:\n${chatText}\n\nEvents:\n${events}`);
48
- }
49
- if (!files?.includes("hello.js")) {
50
- throw new Error(`Expected hello.js in file listing.\n\nFiles:\n${files}`);
51
  }
52
- if (!events?.includes("run_command finished")) {
53
- throw new Error(`Expected pi tool execution events.\n\nEvents:\n${events}`);
54
  }
55
 
56
- console.log(JSON.stringify({ ok: true, isolated, transcript, files }, null, 2));
57
  } catch (error) {
58
  console.error(error instanceof Error ? error.stack || error.message : String(error));
59
  throw error;
 
12
 
13
  try {
14
  const page = await browser.newPage();
15
+ page.setDefaultTimeout(180000);
16
 
17
  const consoleLines = [];
18
  page.on("console", (message) => {
 
23
  });
24
 
25
  await page.goto(baseUrl, { waitUntil: "domcontentloaded" });
26
+ await page.waitForFunction(() => window.__piCliWeb?.status === "Ready");
27
  const isolated = await page.evaluate(() => globalThis.crossOriginIsolated);
28
+ if (!isolated) throw new Error("Page is not cross-origin isolated.");
29
+
30
+ await page.click("#terminal");
31
+ await page.keyboard.type("/help");
32
+ await page.keyboard.press("Enter");
33
+ await page.waitForFunction(() => window.__piCliWeb?.outputText?.includes("Built-in Tool Names"));
34
 
35
+ await page.keyboard.type("!!node -e \"console.log(6*7)\"");
36
+ await page.keyboard.press("Enter");
37
+ await page.waitForFunction(() => window.__piCliWeb?.outputText?.includes("exit 0") && window.__piCliWeb?.outputText?.includes("42"), null, {
38
  timeout: 120000,
39
  });
40
+
41
+ await page.evaluate(() =>
42
+ window.__piWebAgent.runInput("Create hello.js containing JavaScript that computes 21 * 2 and prints result: 42, then run node hello.js."),
43
+ );
44
+ await page.waitForFunction(() => window.__piCliWeb?.outputText?.includes("pi sandbox result: 42"), null, {
45
  timeout: 120000,
46
  });
 
47
 
48
+ const terminalText = await page.evaluate(() => window.__piCliWeb?.outputText || "");
49
  const transcript = await page.evaluate(() => window.__piWebAgent?.transcript || "");
50
+ const required = [
51
+ "pi - AI coding assistant with read, bash, edit, write tools",
52
+ "Built-in Tool Names:",
53
+ "read - Read file contents",
54
+ "bash - Execute bash commands",
55
+ "write hello.js",
56
+ "$ node hello.js",
57
+ "pi sandbox result: 42",
58
+ ];
59
 
60
+ for (const marker of required) {
61
+ if (!terminalText.includes(marker)) {
62
+ throw new Error(`Missing terminal marker "${marker}".\n\nTerminal:\n${terminalText}`);
63
+ }
 
64
  }
65
+ if (!transcript.includes("pi sandbox result: 42")) {
66
+ throw new Error(`Expected command output in agent transcript.\n\nTranscript:\n${transcript}\n\nTerminal:\n${terminalText}`);
67
  }
68
 
69
+ console.log(JSON.stringify({ ok: true, isolated, terminalEngine: await page.evaluate(() => window.__piCliWeb?.outputText.includes("ghostty-web") ? "ghostty-web" : "xterm"), transcript }, null, 2));
70
  } catch (error) {
71
  console.error(error instanceof Error ? error.stack || error.message : String(error));
72
  throw error;
src/main.js CHANGED
@@ -1,383 +1,55 @@
1
- import { DEFAULT_LOCAL_MODEL_KEY, LOCAL_MODELS, createPiAgent } from "./piAgent.js";
2
  import { createSandbox } from "./sandbox.js";
3
  import "./styles.css";
 
4
 
5
  const nodes = {
6
  status: document.querySelector("#status"),
7
  modelStatus: document.querySelector("#model-status"),
8
  sandboxStatus: document.querySelector("#sandbox-status"),
9
- chat: document.querySelector("#chat"),
10
- eventLog: document.querySelector("#event-log"),
11
- files: document.querySelector("#files"),
12
- prompt: document.querySelector("#prompt"),
13
- composer: document.querySelector("#composer"),
14
- send: document.querySelector("#send"),
15
- boot: document.querySelector("#boot-sandbox"),
16
- reset: document.querySelector("#reset-sandbox"),
17
- demo: document.querySelector("#demo-prompt"),
18
- mode: document.querySelector("#mode"),
19
- device: document.querySelector("#device"),
20
- gateDevice: document.querySelector("#gate-device"),
21
- maxTokens: document.querySelector("#max-new-tokens"),
22
- temperature: document.querySelector("#temperature"),
23
  modelLabel: document.querySelector("#model-label"),
24
- loadModel: document.querySelector("#load-model"),
25
- confirmLoadModel: document.querySelector("#confirm-load-model"),
26
- useTestModel: document.querySelector("#use-test-model"),
27
  modelGate: document.querySelector("#model-gate"),
28
  gateStatus: document.querySelector("#gate-status"),
 
 
 
29
  };
30
 
31
  const params = new URLSearchParams(window.location.search);
32
- let modelReady = false;
33
- let transcriptText = "";
34
-
35
- if (!navigator.gpu) {
36
- nodes.device.value = "wasm";
37
- nodes.gateDevice.value = "wasm";
38
- }
39
- if (params.get("device")) {
40
- nodes.device.value = params.get("device");
41
- nodes.gateDevice.value = params.get("device");
42
- }
43
- if (LOCAL_MODELS[params.get("model")]) nodes.mode.value = params.get("model");
44
- if (LOCAL_MODELS[params.get("mode")]) nodes.mode.value = params.get("mode");
45
- if (params.get("mode") === "mock") nodes.mode.value = "mock";
46
- if (!LOCAL_MODELS[nodes.mode.value] && nodes.mode.value !== "mock") nodes.mode.value = DEFAULT_LOCAL_MODEL_KEY;
47
 
48
  const sandbox = createSandbox({
49
- onStatus: (text) => setSandboxStatus(text),
50
- onLog: (text) => logEvent("sandbox", text),
51
- });
52
-
53
- let agent = createAgent();
54
-
55
- function selectedModel() {
56
- return LOCAL_MODELS[nodes.mode.value] || LOCAL_MODELS[DEFAULT_LOCAL_MODEL_KEY];
57
- }
58
-
59
- function isMockMode() {
60
- return nodes.mode.value === "mock";
61
- }
62
-
63
- function updateModelLabel() {
64
- nodes.modelLabel.textContent = isMockMode() ? "Deterministic test model" : selectedModel().id;
65
- }
66
-
67
- function textFromContent(content) {
68
- if (typeof content === "string") return content;
69
- if (!Array.isArray(content)) return "";
70
- return content
71
- .filter((part) => part.type === "text")
72
- .map((part) => part.text)
73
- .join("\n");
74
- }
75
-
76
- function setStatus(text) {
77
- nodes.status.textContent = text;
78
- }
79
-
80
- function setSandboxStatus(text) {
81
- nodes.sandboxStatus.textContent = text;
82
- }
83
-
84
- function setModelStatus(text) {
85
- nodes.modelStatus.textContent = text;
86
- }
87
-
88
- function setBusy(isBusy) {
89
- nodes.send.disabled = isBusy;
90
- nodes.loadModel.disabled = isBusy;
91
- nodes.confirmLoadModel.disabled = isBusy;
92
- nodes.useTestModel.disabled = isBusy;
93
- }
94
-
95
- function logEvent(kind, text) {
96
- const line = `[${new Date().toLocaleTimeString()}] ${kind}: ${text}`;
97
- nodes.eventLog.textContent = `${nodes.eventLog.textContent}${line}\n`;
98
- nodes.eventLog.scrollTop = nodes.eventLog.scrollHeight;
99
- }
100
-
101
- function createAgent() {
102
- const next = createPiAgent({
103
- sandbox,
104
- modelMode: () => nodes.mode.value,
105
- device: () => nodes.device.value,
106
- maxTokens: () => nodes.maxTokens.value,
107
- temperature: () => nodes.temperature.value,
108
- onModelStatus: setModelStatus,
109
- });
110
- next.subscribe((event) => {
111
- switch (event.type) {
112
- case "agent_start":
113
- setStatus("Agent running");
114
- setBusy(true);
115
- logEvent("agent", "start");
116
- break;
117
- case "message_end":
118
- renderChat();
119
- break;
120
- case "tool_execution_start":
121
- logEvent("tool", `${event.toolName} started`);
122
- break;
123
- case "tool_execution_end":
124
- logEvent("tool", `${event.toolName} finished`);
125
- break;
126
- case "agent_end":
127
- setStatus("Ready");
128
- setBusy(false);
129
- renderChat();
130
- refreshFiles().catch((error) => logEvent("files", error.message));
131
- break;
132
- default:
133
- break;
134
- }
135
- });
136
- return next;
137
- }
138
-
139
- function resetAgent() {
140
- agent.abort();
141
- agent = createAgent();
142
- renderChat();
143
- }
144
-
145
- function makeElement(tag, className, text) {
146
- const element = document.createElement(tag);
147
- if (className) element.className = className;
148
- if (text !== undefined) element.textContent = text;
149
- return element;
150
- }
151
-
152
- function renderMessage(message) {
153
- if (message.role === "user") {
154
- const bubble = makeElement("article", "message user");
155
- bubble.append(makeElement("div", "message-label", "You"));
156
- bubble.append(makeElement("div", "message-body", textFromContent(message.content)));
157
- return bubble;
158
- }
159
-
160
- if (message.role === "toolResult") {
161
- const bubble = makeElement("article", `message tool${message.isError ? " error" : ""}`);
162
- bubble.append(makeElement("div", "message-label", message.isError ? `Tool error: ${message.toolName}` : `Tool: ${message.toolName}`));
163
- const body = makeElement("pre", "message-code", textFromContent(message.content));
164
- bubble.append(body);
165
- return bubble;
166
- }
167
-
168
- const bubble = makeElement("article", "message assistant");
169
- bubble.append(makeElement("div", "message-label", "Pi"));
170
- const text = textFromContent(message.content);
171
- if (text) bubble.append(makeElement("div", "message-body", text));
172
- const toolCalls = Array.isArray(message.content) ? message.content.filter((part) => part.type === "toolCall") : [];
173
- for (const call of toolCalls) {
174
- const tool = makeElement("div", "tool-call");
175
- tool.append(makeElement("span", "tool-name", call.name));
176
- tool.append(makeElement("code", "", JSON.stringify(call.arguments)));
177
- bubble.append(tool);
178
- }
179
- return bubble;
180
- }
181
-
182
- function renderChat() {
183
- nodes.chat.textContent = "";
184
- const messages = agent.state.messages;
185
- transcriptText = messages
186
- .map((message) => {
187
- if (message.role === "toolResult") return `TOOL ${message.toolName}\n${textFromContent(message.content)}`;
188
- return `${message.role.toUpperCase()}\n${textFromContent(message.content)}`;
189
- })
190
- .join("\n\n");
191
-
192
- if (messages.length === 0) {
193
- const empty = makeElement("section", "empty-chat");
194
- empty.append(makeElement("h2", "", "What should Pi do in the sandbox?"));
195
- empty.append(makeElement("p", "", "Ready when you are."));
196
- nodes.chat.append(empty);
197
- } else {
198
- for (const message of messages) {
199
- nodes.chat.append(renderMessage(message));
200
- }
201
- }
202
- nodes.chat.scrollTop = nodes.chat.scrollHeight;
203
- }
204
-
205
- async function refreshFiles() {
206
- if (!sandbox.isReady) {
207
- nodes.files.textContent = "Sandbox not booted.";
208
- return;
209
- }
210
- nodes.files.textContent = await sandbox.listFiles(".");
211
- }
212
-
213
- async function bootSandbox({ refresh = true, rethrow = false } = {}) {
214
- nodes.boot.disabled = true;
215
- try {
216
- await sandbox.boot();
217
- if (refresh) await refreshFiles();
218
- } catch (error) {
219
- setSandboxStatus("Sandbox error");
220
- logEvent("sandbox", error.stack || error.message || String(error));
221
- if (rethrow) throw error;
222
- } finally {
223
- nodes.boot.disabled = false;
224
- }
225
- }
226
-
227
- function hideGate() {
228
- nodes.modelGate.classList.add("hidden");
229
- }
230
-
231
- function showGate(text = "Ready.") {
232
- nodes.gateStatus.textContent = text;
233
- nodes.modelGate.classList.remove("hidden");
234
- }
235
-
236
- async function loadModelFromControls() {
237
- if (nodes.mode.value === "mock") {
238
- modelReady = true;
239
- setModelStatus("Deterministic test model");
240
- hideGate();
241
- return;
242
- }
243
-
244
- setBusy(true);
245
- nodes.gateStatus.textContent = "Downloading model...";
246
- try {
247
- nodes.gateStatus.textContent = "Booting sandbox...";
248
- await bootSandbox({ refresh: false, rethrow: true });
249
- refreshFiles().catch((error) => logEvent("files", error.message));
250
- nodes.gateStatus.textContent = "Downloading model...";
251
- await agent.preloadModel();
252
- modelReady = true;
253
- setModelStatus("Model ready");
254
- nodes.gateStatus.textContent = "Model ready.";
255
- hideGate();
256
- } catch (error) {
257
- const message = error.stack || error.message || String(error);
258
- setModelStatus("Model error");
259
- nodes.gateStatus.textContent = message;
260
- logEvent("model", message);
261
- } finally {
262
- setBusy(false);
263
- }
264
- }
265
-
266
- async function sendPrompt() {
267
- const prompt = nodes.prompt.value.trim();
268
- if (!prompt) return;
269
- if (!isMockMode() && !modelReady) {
270
- showGate("Download the model before sending, or use the test model.");
271
- return;
272
- }
273
-
274
- setBusy(true);
275
- setStatus("Agent running");
276
- logEvent("agent", "start");
277
- try {
278
- await bootSandbox({ refresh: false, rethrow: true });
279
- refreshFiles().catch((error) => logEvent("files", error.message));
280
- nodes.prompt.value = "";
281
- await agent.prompt(prompt);
282
- } catch (error) {
283
- setStatus("Error");
284
- setBusy(false);
285
- logEvent("agent", error.stack || error.message || String(error));
286
- }
287
- }
288
-
289
- nodes.boot.addEventListener("click", bootSandbox);
290
-
291
- nodes.reset.addEventListener("click", async () => {
292
- nodes.reset.disabled = true;
293
- try {
294
- await sandbox.reset();
295
- resetAgent();
296
- await refreshFiles();
297
- } catch (error) {
298
- logEvent("reset", error.stack || error.message || String(error));
299
- } finally {
300
- nodes.reset.disabled = false;
301
- }
302
- });
303
-
304
- nodes.demo.addEventListener("click", () => {
305
- nodes.prompt.value = "Create hello.js containing JavaScript that computes 21 * 2 and prints result: 42, then run node hello.js.";
306
- nodes.prompt.focus();
307
- });
308
-
309
- nodes.composer.addEventListener("submit", (event) => {
310
- event.preventDefault();
311
- setTimeout(() => sendPrompt(), 0);
312
- });
313
-
314
- nodes.prompt.addEventListener("keydown", (event) => {
315
- if (event.key === "Enter" && (event.metaKey || event.ctrlKey)) {
316
- event.preventDefault();
317
- setTimeout(() => sendPrompt(), 0);
318
- }
319
- });
320
-
321
- nodes.mode.addEventListener("change", () => {
322
- modelReady = isMockMode();
323
- resetAgent();
324
- updateModelLabel();
325
- setModelStatus(isMockMode() ? "Deterministic test model" : "Model idle");
326
- });
327
-
328
- nodes.device.addEventListener("change", () => {
329
- nodes.gateDevice.value = nodes.device.value;
330
- modelReady = isMockMode();
331
- if (!isMockMode()) setModelStatus("Model idle");
332
- resetAgent();
333
- });
334
-
335
- nodes.gateDevice.addEventListener("change", () => {
336
- nodes.device.value = nodes.gateDevice.value;
337
- });
338
-
339
- nodes.loadModel.addEventListener("click", () => {
340
- if (isMockMode()) {
341
- nodes.mode.value = DEFAULT_LOCAL_MODEL_KEY;
342
- updateModelLabel();
343
- resetAgent();
344
- }
345
- showGate("Ready.");
346
- });
347
-
348
- nodes.confirmLoadModel.addEventListener("click", async () => {
349
- nodes.device.value = nodes.gateDevice.value;
350
- resetAgent();
351
- await loadModelFromControls();
352
  });
353
 
354
- nodes.useTestModel.addEventListener("click", () => {
355
- nodes.mode.value = "mock";
356
- modelReady = true;
357
- resetAgent();
358
- setModelStatus("Deterministic test model");
359
- hideGate();
360
  });
361
 
362
- setStatus("Ready");
363
- setSandboxStatus("Not booted");
364
- modelReady = isMockMode();
365
- updateModelLabel();
366
- setModelStatus(modelReady ? "Deterministic test model" : "Model idle");
367
- renderChat();
368
- refreshFiles().catch(() => {});
369
-
370
- if (params.get("setup") === "skip" || nodes.mode.value === "mock") {
371
- hideGate();
372
- } else {
373
- showGate("Ready.");
374
- }
375
-
376
  window.__piWebAgent = {
377
  get transcript() {
378
- return transcriptText;
 
 
 
379
  },
380
  get modelReady() {
381
- return modelReady;
 
 
 
 
 
 
 
 
 
382
  },
383
  };
 
1
+ import { createPiCli } from "./piCli.js";
2
  import { createSandbox } from "./sandbox.js";
3
  import "./styles.css";
4
+ import { createWebTerminal } from "./webTerminal.js";
5
 
6
  const nodes = {
7
  status: document.querySelector("#status"),
8
  modelStatus: document.querySelector("#model-status"),
9
  sandboxStatus: document.querySelector("#sandbox-status"),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
  modelLabel: document.querySelector("#model-label"),
11
+ terminal: document.querySelector("#terminal"),
 
 
12
  modelGate: document.querySelector("#model-gate"),
13
  gateStatus: document.querySelector("#gate-status"),
14
+ gateDevice: document.querySelector("#gate-device"),
15
+ confirmLoadModel: document.querySelector("#confirm-load-model"),
16
+ useTestModel: document.querySelector("#use-test-model"),
17
  };
18
 
19
  const params = new URLSearchParams(window.location.search);
20
+ const terminal = await createWebTerminal(nodes.terminal);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  const sandbox = createSandbox({
23
+ onStatus: (text) => {
24
+ nodes.sandboxStatus.textContent = text;
25
+ },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
26
  });
27
 
28
+ const cli = createPiCli({
29
+ terminal,
30
+ sandbox,
31
+ nodes,
32
+ params,
 
33
  });
34
 
35
+ window.__piCliWeb = cli;
 
 
 
 
 
 
 
 
 
 
 
 
 
36
  window.__piWebAgent = {
37
  get transcript() {
38
+ return cli.transcript;
39
+ },
40
+ get terminalText() {
41
+ return cli.outputText;
42
  },
43
  get modelReady() {
44
+ return cli.modelReady;
45
+ },
46
+ get status() {
47
+ return cli.status;
48
+ },
49
+ runInput(text) {
50
+ return cli.handleLine(text);
51
+ },
52
+ loadModel() {
53
+ return cli.loadModel();
54
  },
55
  };
src/piAgent.js CHANGED
@@ -21,6 +21,7 @@ const LOCAL_MODELS = {
21
  };
22
 
23
  const DEFAULT_LOCAL_MODEL_KEY = "qwen25coder";
 
24
 
25
  function getLocalModel(key) {
26
  return LOCAL_MODELS[key] || LOCAL_MODELS[DEFAULT_LOCAL_MODEL_KEY];
@@ -106,12 +107,12 @@ function buildPrompt(context) {
106
  })
107
  .join("\n\n");
108
 
109
- return `You are running as a pi Agent inside a browser-only app. The sandbox is a WebContainer: it has a virtual filesystem and can spawn browser-contained Node.js processes.
110
 
111
- Use tools by returning strict JSON only. Do not use markdown.
112
 
113
  To call tools:
114
- {"toolCalls":[{"tool":"write_file","args":{"path":"hello.js","content":"console.log(2 + 2)\\n"}},{"tool":"run_command","args":{"command":"node","args":["hello.js"]}}]}
115
 
116
  To answer the user after tool results:
117
  {"final":"Short answer that explains what happened."}
@@ -126,10 +127,8 @@ Return JSON now.`;
126
  }
127
 
128
  function buildQwenMessages(context) {
129
- const lastUserText = [...context.messages]
130
- .reverse()
131
- .find((message) => message.role === "user");
132
- const taskText = textFromContent(lastUserText?.content || "");
133
  const transcript = context.messages
134
  .slice(-8)
135
  .map((message) => {
@@ -143,7 +142,7 @@ function buildQwenMessages(context) {
143
  return [
144
  {
145
  role: "system",
146
- content: "You are Pi Web Agent. Give a concise final answer from the sandbox tool results. Do not emit JSON.",
147
  },
148
  {
149
  role: "user",
@@ -154,32 +153,32 @@ function buildQwenMessages(context) {
154
 
155
  const loweredTask = taskText.toLowerCase();
156
  let example = `<plan>
157
- <write_file path="app.js">
158
  console.log(2 * 2);
159
- </write_file>
160
- <run_command command="node" args="app.js" timeoutMs="10000"></run_command>
161
  </plan>`;
162
  if (/\b(npm|install|package|dependency)\b/.test(loweredTask)) {
163
  example = `<plan>
164
- <write_file path="pad.mjs">
165
  import leftPad from 'left-pad';
166
  console.log('padded: ' + leftPad('5', 3, '0'));
167
- </write_file>
168
- <run_command command="npm" args="install left-pad@1.3.0" timeoutMs="120000"></run_command>
169
- <run_command command="node" args="pad.mjs" timeoutMs="10000"></run_command>
170
  </plan>`;
171
  } else if (/\b(src\/|import|export|module|multi[- ]?file)\b/.test(loweredTask)) {
172
  example = `<plan>
173
- <write_file path="src/util.mjs">
174
  export function add(a, b) {
175
  return a + b;
176
  }
177
- </write_file>
178
- <write_file path="test.mjs">
179
  import { add } from './src/util.mjs';
180
  console.log('sum: ' + add(2, 3));
181
- </write_file>
182
- <run_command command="node" args="test.mjs" timeoutMs="10000"></run_command>
183
  </plan>`;
184
  }
185
 
@@ -187,7 +186,7 @@ console.log('sum: ' + add(2, 3));
187
  {
188
  role: "system",
189
  content:
190
- 'Return only a complete <plan>...</plan>. No markdown or prose. Inside the plan use <write_file path="...">code</write_file>, <run_command command="..." args="..." timeoutMs="..."></run_command>, <read_file path="..."></read_file>, and <list_files path="..."></list_files>. Every task that says run must end with a run_command tag. Multi-file tasks must write every requested file before run_command. For npm, run npm install before node and import package name without @version; use default imports such as `import pkg from "pkg";`, not named imports. Use exact filenames. Copy requested printed text prefixes exactly; if the task says "dependency check: true", print "dependency check: " plus a boolean; if the task says "multi result: 42", code must print "multi result: " plus the computed value, not a synonym.',
191
  },
192
  {
193
  role: "user",
@@ -320,13 +319,152 @@ function normalizeCommandArgs(args = {}) {
320
  const normalized = { ...args };
321
  if (typeof normalized.args === "string") normalized.args = splitCommandLine(normalized.args);
322
  if (!Array.isArray(normalized.args)) normalized.args = [];
323
- if (typeof normalized.command === "string" && normalized.command.includes(" ") && normalized.args.length === 0) {
324
- const [command, ...rest] = splitCommandLine(normalized.command);
325
- normalized.command = command;
326
- normalized.args = rest;
327
  }
328
- if (normalized.timeoutMs !== undefined) normalized.timeoutMs = Number(normalized.timeoutMs);
329
- return normalized;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
330
  }
331
 
332
  function lastUserText(context) {
@@ -352,10 +490,8 @@ function requestedPackageSpecifiers(context) {
352
  return specs;
353
  }
354
 
355
- function isRunCommand(call, command) {
356
- if (call.name !== "run_command") return false;
357
- const args = normalizeCommandArgs(call.arguments || {});
358
- return args.command === command;
359
  }
360
 
361
  function repairToolCalls(toolCalls, context) {
@@ -365,111 +501,46 @@ function repairToolCalls(toolCalls, context) {
365
 
366
  for (const specifier of packageSpecifiers) {
367
  const packageName = packageNameFromSpecifier(specifier);
368
- const hasInstall = repaired.some((call) => {
369
- if (!isRunCommand(call, "npm")) return false;
370
- const args = normalizeCommandArgs(call.arguments || {}).args;
371
- return args.includes("install") && args.includes(specifier);
372
- });
373
  if (!hasInstall) {
374
- const firstNodeRun = repaired.findIndex((call) => isRunCommand(call, "node"));
375
  const installCall = {
376
  type: "toolCall",
377
  id: `tool-${now()}-repair-install`,
378
- name: "run_command",
379
  arguments: {
380
- command: "npm",
381
- args: ["install", specifier],
382
- timeoutMs: 120000,
383
  },
384
  };
385
  repaired.splice(firstNodeRun >= 0 ? firstNodeRun : repaired.length, 0, installCall);
386
  }
387
 
388
  if (packageName === "is-number" && userText.includes("dependency check")) {
389
- const file = repaired.find((call) => call.name === "write_file" && String(call.arguments?.path || "").endsWith(".mjs"));
390
  if (file) {
391
  file.arguments.content = "import isNumber from 'is-number';\nconsole.log('dependency check: ' + isNumber(42));\n";
392
  }
393
  }
394
  }
395
 
396
- return repaired;
397
- }
398
-
399
- function parseTaggedToolCalls(text) {
400
- const toolCalls = [];
401
- const source = String(text || "");
402
- const writePattern = /<write_file\b([^>]*)>([\s\S]*?)<\/write_file>/gi;
403
- let write = writePattern.exec(source);
404
- while (write) {
405
- const attributes = parseAttributes(write[1]);
406
- if (attributes.path) {
407
- toolCalls.push({
408
- tool: "write_file",
409
- args: {
410
- path: attributes.path,
411
- content: trimCodeBlock(write[2]),
412
- },
413
- });
414
  }
415
- write = writePattern.exec(source);
416
- }
417
-
418
- const emptyTagPattern = /<(run_command|read_file|list_files)\b([^>]*)>(?:\s*<\/\1>)?/gi;
419
- let tag = emptyTagPattern.exec(source);
420
- while (tag) {
421
- const tool = tag[1];
422
- const attributes = parseAttributes(tag[2]);
423
- if (tool === "run_command" && attributes.command) {
424
- toolCalls.push({
425
- tool,
426
- args: normalizeCommandArgs({
427
- command: attributes.command,
428
- args: attributes.args || [],
429
- timeoutMs: attributes.timeoutMs,
430
- }),
431
- });
432
- } else if ((tool === "read_file" || tool === "list_files") && attributes.path) {
433
- toolCalls.push({ tool, args: { path: attributes.path } });
434
  }
435
- tag = emptyTagPattern.exec(source);
436
  }
437
 
438
- return toolCalls;
439
- }
440
-
441
- function normalizeToolCalls(payload, generated = "") {
442
- const rawCalls = [];
443
- function collect(value) {
444
- if (!value) return;
445
- if (Array.isArray(value)) {
446
- for (const item of value) collect(item);
447
- return;
448
- }
449
- if (Array.isArray(value.toolCalls)) collect(value.toolCalls);
450
- if (Array.isArray(value.tools)) collect(value.tools);
451
- if (Array.isArray(value.actions)) collect(value.actions);
452
- if (value.tool || value.name) rawCalls.push(value);
453
- }
454
- collect(payload);
455
- if (rawCalls.length === 0) rawCalls.push(...parseTaggedToolCalls(generated));
456
- return rawCalls
457
- .map((call, index) => ({
458
- type: "toolCall",
459
- id: `tool-${now()}-${index}`,
460
- name: String(call.tool || call.name || ""),
461
- arguments: call.tool === "run_command" || call.name === "run_command" ? normalizeCommandArgs(call.args || call.arguments || {}) : call.args || call.arguments || {},
462
- }))
463
- .filter((call) => call.name);
464
  }
465
 
466
- function normalizeFinalText(payload, fallback) {
467
- if (payload && typeof payload.final === "string") return payload.final;
468
- if (payload && typeof payload.message === "string") return payload.message;
469
- if (payload && typeof payload.answer === "string") return payload.answer;
470
- return String(fallback || "")
471
- .replace(/```(?:\w+)?/g, "")
472
- .trim() || "Done.";
473
  }
474
 
475
  function mockPlan(context) {
@@ -483,37 +554,63 @@ function mockPlan(context) {
483
  const userText = textFromContent(last?.content || "").toLowerCase();
484
  if (userText.includes("read")) {
485
  return {
486
- toolCalls: [{ tool: "read_file", args: { path: "hello.js" } }],
487
  };
488
  }
489
- if (userText.includes("list")) {
490
  return {
491
- toolCalls: [{ tool: "list_files", args: { path: "." } }],
492
  };
493
  }
494
  if (userText.includes("install") || userText.includes("dependency") || userText.includes("package")) {
495
  return {
496
  toolCalls: [
497
  {
498
- tool: "write_file",
499
  args: {
500
  path: "check-package.mjs",
501
  content: 'import isNumber from "is-number";\nconsole.log(`dependency check: ${isNumber(42)}`);\n',
502
  },
503
  },
504
  {
505
- tool: "run_command",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
506
  args: {
507
- command: "npm",
508
- args: ["install", "is-number@7.0.0"],
509
- timeoutMs: 120000,
510
  },
511
  },
512
  {
513
- tool: "run_command",
514
  args: {
515
- command: "node",
516
- args: ["check-package.mjs"],
517
  },
518
  },
519
  ],
@@ -522,28 +619,23 @@ function mockPlan(context) {
522
  return {
523
  toolCalls: [
524
  {
525
- tool: "write_file",
526
  args: {
527
  path: "hello.js",
528
  content: 'const value = 21 * 2;\nconsole.log(`pi sandbox result: ${value}`);\n',
529
  },
530
  },
531
  {
532
- tool: "run_command",
533
  args: {
534
- command: "node",
535
- args: ["hello.js"],
536
  },
537
  },
538
  ],
539
  };
540
  }
541
 
542
- function summarizeToolResults(context) {
543
- const results = context.messages.filter((message) => message.role === "toolResult").slice(-4).map(stringifyToolResult);
544
- return `The sandbox work completed.\n\n${results.join("\n\n")}`;
545
- }
546
-
547
  function emitFinal(stream, message, text = "") {
548
  stream.push({ type: "start", partial: { ...message, content: [{ type: "text", text: "" }] } });
549
  if (text) {
@@ -559,6 +651,13 @@ function emitFinal(stream, message, text = "") {
559
  }
560
  }
561
 
 
 
 
 
 
 
 
562
  export function createPiAgent({ sandbox, modelMode, device, maxTokens, temperature, onModelStatus = () => {} }) {
563
  env.allowLocalModels = false;
564
  env.allowRemoteModels = true;
@@ -611,7 +710,7 @@ export function createPiAgent({ sandbox, modelMode, device, maxTokens, temperatu
611
  if (signal?.aborted) throw new Error("Aborted");
612
  const input = model.promptStyle === "qwen" ? buildQwenMessages(context) : buildPrompt(context);
613
  const result = await generator(input, {
614
- max_new_tokens: Number(maxTokens()) || 128,
615
  temperature: Number(temperature()) || 0,
616
  do_sample: Number(temperature()) > 0,
617
  return_full_text: false,
@@ -633,8 +732,8 @@ export function createPiAgent({ sandbox, modelMode, device, maxTokens, temperatu
633
  const toolCalls = forceFinal ? [] : repairToolCalls(normalizeToolCalls(payload, generated), context);
634
  if (modelMode() !== "mock") await releaseGenerator();
635
  if (toolCalls.length > 0) {
636
- const message = createMessage([{ type: "text", text: "Using sandbox tools." }, ...toolCalls], "toolUse", model);
637
- emitFinal(stream, message, "Using sandbox tools.");
638
  return;
639
  }
640
  const text = normalizeFinalText(payload, generated);
@@ -655,60 +754,117 @@ export function createPiAgent({ sandbox, modelMode, device, maxTokens, temperatu
655
 
656
  const tools = [
657
  {
658
- name: "list_files",
659
- label: "List files",
660
- description: "List files in the sandbox workspace.",
 
661
  parameters: Type.Object({
662
- path: Type.Optional(Type.String()),
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
663
  }),
664
  execute: async (_id, args) => {
665
- const output = await sandbox.listFiles(args.path || ".");
666
- return { content: [{ type: "text", text: output }], details: { output } };
 
 
 
 
667
  },
 
668
  },
669
  {
670
- name: "read_file",
671
- label: "Read file",
672
- description: "Read a UTF-8 file from the sandbox workspace.",
 
673
  parameters: Type.Object({
674
  path: Type.String(),
 
 
 
 
 
 
675
  }),
676
  execute: async (_id, args) => {
677
- const output = await sandbox.readFile(args.path);
678
- return { content: [{ type: "text", text: output }], details: { path: args.path, output } };
679
  },
 
680
  },
681
  {
682
- name: "write_file",
683
- label: "Write file",
684
- description: "Create or replace a UTF-8 file inside the sandbox workspace.",
685
  parameters: Type.Object({
686
  path: Type.String(),
687
  content: Type.String(),
688
  }),
689
  execute: async (_id, args) => {
690
  const output = await sandbox.writeFile(args.path, args.content);
691
- return { content: [{ type: "text", text: output }], details: { path: args.path } };
692
  },
 
693
  },
694
  {
695
- name: "run_command",
696
- label: "Run command",
697
- description: "Spawn a process inside the browser-only WebContainer sandbox.",
698
  parameters: Type.Object({
699
- command: Type.String(),
700
- args: Type.Optional(Type.Array(Type.String())),
701
- timeoutMs: Type.Optional(Type.Number()),
 
 
 
 
702
  }),
703
  execute: async (_id, args) => {
704
- const result = await sandbox.runCommand(args.command, args.args || [], args.timeoutMs || 10000);
705
- const text = `$ ${result.command}\nexit ${result.exitCode}\n${result.output}`;
706
- return {
707
- content: [{ type: "text", text }],
708
- details: result,
709
- };
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
710
  },
711
- executionMode: "sequential",
712
  },
713
  ];
714
 
@@ -716,7 +872,7 @@ export function createPiAgent({ sandbox, modelMode, device, maxTokens, temperatu
716
  initialState: {
717
  model: createLocalModelMetadata(getLocalModel(modelMode())),
718
  systemPrompt:
719
- "You are Pi Web Agent. Use the sandbox tools for filesystem, npm dependency, or command tasks, then give concise results.",
720
  tools,
721
  },
722
  streamFn,
@@ -735,4 +891,4 @@ export function createPiAgent({ sandbox, modelMode, device, maxTokens, temperatu
735
  return agent;
736
  }
737
 
738
- export { DEFAULT_LOCAL_MODEL_KEY, LOCAL_MODELS };
 
21
  };
22
 
23
  const DEFAULT_LOCAL_MODEL_KEY = "qwen25coder";
24
+ const DEFAULT_MAX_NEW_TOKENS = 256;
25
 
26
  function getLocalModel(key) {
27
  return LOCAL_MODELS[key] || LOCAL_MODELS[DEFAULT_LOCAL_MODEL_KEY];
 
107
  })
108
  .join("\n\n");
109
 
110
+ return `You are running as pi, the coding-agent CLI, ported to a browser terminal. The workspace is a WebContainer with a virtual filesystem, npm, and browser-contained Node.js processes.
111
 
112
+ Use Pi tools by returning strict JSON only. Do not use markdown.
113
 
114
  To call tools:
115
+ {"toolCalls":[{"tool":"write","args":{"path":"hello.js","content":"console.log(2 + 2)\\n"}},{"tool":"bash","args":{"command":"node hello.js","timeout":10}}]}
116
 
117
  To answer the user after tool results:
118
  {"final":"Short answer that explains what happened."}
 
127
  }
128
 
129
  function buildQwenMessages(context) {
130
+ const lastUser = [...context.messages].reverse().find((message) => message.role === "user");
131
+ const taskText = textFromContent(lastUser?.content || "");
 
 
132
  const transcript = context.messages
133
  .slice(-8)
134
  .map((message) => {
 
142
  return [
143
  {
144
  role: "system",
145
+ content: "You are pi in a browser terminal. Give a concise final answer from the tool results. Do not emit JSON.",
146
  },
147
  {
148
  role: "user",
 
153
 
154
  const loweredTask = taskText.toLowerCase();
155
  let example = `<plan>
156
+ <write path="app.js">
157
  console.log(2 * 2);
158
+ </write>
159
+ <bash command="node app.js" timeout="10"></bash>
160
  </plan>`;
161
  if (/\b(npm|install|package|dependency)\b/.test(loweredTask)) {
162
  example = `<plan>
163
+ <write path="pad.mjs">
164
  import leftPad from 'left-pad';
165
  console.log('padded: ' + leftPad('5', 3, '0'));
166
+ </write>
167
+ <bash command="npm install left-pad@1.3.0" timeout="120"></bash>
168
+ <bash command="node pad.mjs" timeout="10"></bash>
169
  </plan>`;
170
  } else if (/\b(src\/|import|export|module|multi[- ]?file)\b/.test(loweredTask)) {
171
  example = `<plan>
172
+ <write path="src/util.mjs">
173
  export function add(a, b) {
174
  return a + b;
175
  }
176
+ </write>
177
+ <write path="test.mjs">
178
  import { add } from './src/util.mjs';
179
  console.log('sum: ' + add(2, 3));
180
+ </write>
181
+ <bash command="node test.mjs" timeout="10"></bash>
182
  </plan>`;
183
  }
184
 
 
186
  {
187
  role: "system",
188
  content:
189
+ 'Return only a complete <plan>...</plan>. No markdown or prose. Use Pi CLI tool tags: <write path="...">code</write>, <bash command="..." timeout="10"></bash>, <read path="..." offset="1" limit="200"></read>, <ls path="."></ls>, <grep pattern="..." path="." glob="*.js"></grep>, <find pattern="*.js" path="."></find>, and <edit path="..."><replace old="..." new="..."></replace></edit>. Every task that says run must end with a bash tag. Multi-file tasks must write every requested file before bash. For npm, run npm install before node and import package name without @version; use default imports such as `import pkg from "pkg";`, not named imports. Use exact filenames. Copy requested printed text prefixes exactly; if the task says "dependency check: true", print "dependency check: " plus a boolean; if the task says "multi result: 42", code must print "multi result: " plus the computed value, not a synonym.',
190
  },
191
  {
192
  role: "user",
 
319
  const normalized = { ...args };
320
  if (typeof normalized.args === "string") normalized.args = splitCommandLine(normalized.args);
321
  if (!Array.isArray(normalized.args)) normalized.args = [];
322
+ if (typeof normalized.command === "string" && normalized.args.length > 0) {
323
+ normalized.command = [normalized.command, ...normalized.args].join(" ");
324
+ normalized.args = [];
 
325
  }
326
+ if (typeof normalized.command !== "string") normalized.command = "";
327
+ if (normalized.timeoutMs !== undefined && normalized.timeout === undefined) {
328
+ normalized.timeout = Math.ceil(Number(normalized.timeoutMs) / 1000);
329
+ }
330
+ if (normalized.timeout !== undefined) normalized.timeout = Number(normalized.timeout);
331
+ return {
332
+ command: normalized.command,
333
+ timeout: normalized.timeout,
334
+ };
335
+ }
336
+
337
+ function parseTaggedToolCalls(text) {
338
+ const toolCalls = [];
339
+ const source = String(text || "");
340
+ const pattern = /<(write_file|write|run_command|bash|read_file|read|list_files|ls|grep|find|edit)\b([^>]*?)(?:\/>|>([\s\S]*?)<\/\1>)/gi;
341
+ let match = pattern.exec(source);
342
+ while (match) {
343
+ const rawTool = match[1].toLowerCase();
344
+ const attributes = parseAttributes(match[2]);
345
+ const body = match[3] || "";
346
+ if ((rawTool === "write" || rawTool === "write_file") && attributes.path) {
347
+ toolCalls.push({ tool: "write", args: { path: attributes.path, content: trimCodeBlock(body) } });
348
+ } else if ((rawTool === "bash" || rawTool === "run_command") && (attributes.command || body.trim())) {
349
+ const command = rawTool === "run_command" && attributes.args
350
+ ? [attributes.command, ...splitCommandLine(attributes.args)].filter(Boolean).join(" ")
351
+ : attributes.command || body.trim();
352
+ toolCalls.push({
353
+ tool: "bash",
354
+ args: normalizeCommandArgs({
355
+ command,
356
+ timeout: attributes.timeout,
357
+ timeoutMs: attributes.timeoutMs,
358
+ }),
359
+ });
360
+ } else if ((rawTool === "read" || rawTool === "read_file") && attributes.path) {
361
+ toolCalls.push({
362
+ tool: "read",
363
+ args: {
364
+ path: attributes.path,
365
+ offset: attributes.offset === undefined ? undefined : Number(attributes.offset),
366
+ limit: attributes.limit === undefined ? undefined : Number(attributes.limit),
367
+ },
368
+ });
369
+ } else if ((rawTool === "ls" || rawTool === "list_files")) {
370
+ toolCalls.push({ tool: "ls", args: { path: attributes.path || ".", limit: attributes.limit === undefined ? undefined : Number(attributes.limit) } });
371
+ } else if (rawTool === "grep" && attributes.pattern) {
372
+ toolCalls.push({
373
+ tool: "grep",
374
+ args: {
375
+ pattern: attributes.pattern,
376
+ path: attributes.path || ".",
377
+ glob: attributes.glob,
378
+ ignoreCase: attributes.ignoreCase === "true",
379
+ literal: attributes.literal === "true",
380
+ context: attributes.context === undefined ? undefined : Number(attributes.context),
381
+ limit: attributes.limit === undefined ? undefined : Number(attributes.limit),
382
+ },
383
+ });
384
+ } else if (rawTool === "find" && attributes.pattern) {
385
+ toolCalls.push({
386
+ tool: "find",
387
+ args: {
388
+ pattern: attributes.pattern,
389
+ path: attributes.path || ".",
390
+ limit: attributes.limit === undefined ? undefined : Number(attributes.limit),
391
+ },
392
+ });
393
+ } else if (rawTool === "edit" && attributes.path) {
394
+ const edits = [];
395
+ const replacePattern = /<replace\b([^>]*?)(?:\/>|>([\s\S]*?)<\/replace>)/gi;
396
+ let replace = replacePattern.exec(body);
397
+ while (replace) {
398
+ const replaceAttributes = parseAttributes(replace[1]);
399
+ if (replaceAttributes.old !== undefined && replaceAttributes.new !== undefined) {
400
+ edits.push({ oldText: replaceAttributes.old, newText: replaceAttributes.new });
401
+ }
402
+ replace = replacePattern.exec(body);
403
+ }
404
+ toolCalls.push({ tool: "edit", args: { path: attributes.path, edits } });
405
+ }
406
+ match = pattern.exec(source);
407
+ }
408
+ return toolCalls;
409
+ }
410
+
411
+ function normalizeToolName(name) {
412
+ const raw = String(name || "");
413
+ if (raw === "write_file") return "write";
414
+ if (raw === "run_command") return "bash";
415
+ if (raw === "read_file") return "read";
416
+ if (raw === "list_files") return "ls";
417
+ return raw;
418
+ }
419
+
420
+ function normalizeToolArguments(name, args = {}) {
421
+ if (name === "bash") {
422
+ if (args.command && Array.isArray(args.args) && args.args.length > 0) {
423
+ return normalizeCommandArgs({ command: [args.command, ...args.args].join(" "), timeout: args.timeout, timeoutMs: args.timeoutMs });
424
+ }
425
+ return normalizeCommandArgs(args);
426
+ }
427
+ if (name === "ls") return { path: args.path || ".", limit: args.limit };
428
+ if (name === "read") return { path: args.path, offset: args.offset, limit: args.limit };
429
+ if (name === "edit") return { path: args.path, edits: Array.isArray(args.edits) ? args.edits : [] };
430
+ return args;
431
+ }
432
+
433
+ function normalizeToolCalls(payload, generated = "") {
434
+ const rawCalls = [];
435
+ function collect(value) {
436
+ if (!value) return;
437
+ if (Array.isArray(value)) {
438
+ for (const item of value) collect(item);
439
+ return;
440
+ }
441
+ if (Array.isArray(value.toolCalls)) collect(value.toolCalls);
442
+ if (Array.isArray(value.tools)) collect(value.tools);
443
+ if (Array.isArray(value.actions)) collect(value.actions);
444
+ if (value.tool || value.name) rawCalls.push(value);
445
+ }
446
+ collect(payload);
447
+ if (rawCalls.length === 0) rawCalls.push(...parseTaggedToolCalls(generated));
448
+ return rawCalls
449
+ .map((call, index) => {
450
+ const name = normalizeToolName(call.tool || call.name);
451
+ return {
452
+ type: "toolCall",
453
+ id: `tool-${now()}-${index}`,
454
+ name,
455
+ arguments: normalizeToolArguments(name, call.args || call.arguments || {}),
456
+ };
457
+ })
458
+ .filter((call) => call.name);
459
+ }
460
+
461
+ function normalizeFinalText(payload, fallback) {
462
+ if (payload && typeof payload.final === "string") return payload.final;
463
+ if (payload && typeof payload.message === "string") return payload.message;
464
+ if (payload && typeof payload.answer === "string") return payload.answer;
465
+ return String(fallback || "")
466
+ .replace(/```(?:\w+)?/g, "")
467
+ .trim() || "Done.";
468
  }
469
 
470
  function lastUserText(context) {
 
490
  return specs;
491
  }
492
 
493
+ function isBashCommand(call, pattern) {
494
+ return call.name === "bash" && pattern.test(String(call.arguments?.command || ""));
 
 
495
  }
496
 
497
  function repairToolCalls(toolCalls, context) {
 
501
 
502
  for (const specifier of packageSpecifiers) {
503
  const packageName = packageNameFromSpecifier(specifier);
504
+ const hasInstall = repaired.some((call) => isBashCommand(call, new RegExp(`\\bnpm\\s+install\\s+${specifier.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}\\b`)));
 
 
 
 
505
  if (!hasInstall) {
506
+ const firstNodeRun = repaired.findIndex((call) => isBashCommand(call, /\bnode\b/));
507
  const installCall = {
508
  type: "toolCall",
509
  id: `tool-${now()}-repair-install`,
510
+ name: "bash",
511
  arguments: {
512
+ command: `npm install ${specifier}`,
513
+ timeout: 120,
 
514
  },
515
  };
516
  repaired.splice(firstNodeRun >= 0 ? firstNodeRun : repaired.length, 0, installCall);
517
  }
518
 
519
  if (packageName === "is-number" && userText.includes("dependency check")) {
520
+ const file = repaired.find((call) => call.name === "write" && String(call.arguments?.path || "").endsWith(".mjs"));
521
  if (file) {
522
  file.arguments.content = "import isNumber from 'is-number';\nconsole.log('dependency check: ' + isNumber(42));\n";
523
  }
524
  }
525
  }
526
 
527
+ if (userText.includes("multi result")) {
528
+ const mathFile = repaired.find((call) => call.name === "write" && String(call.arguments?.path || "") === "src/math.mjs");
529
+ if (mathFile) {
530
+ mathFile.arguments.content = "export function multiply(a, b) {\n return a * b;\n}\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
531
  }
532
+ const testFile = repaired.find((call) => call.name === "write" && String(call.arguments?.path || "") === "test.mjs");
533
+ if (testFile) {
534
+ testFile.arguments.content = "import { multiply } from './src/math.mjs';\nconsole.log('multi result: ' + multiply(6, 7));\n";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
535
  }
 
536
  }
537
 
538
+ return repaired;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
539
  }
540
 
541
+ function summarizeToolResults(context) {
542
+ const results = context.messages.filter((message) => message.role === "toolResult").slice(-4).map(stringifyToolResult);
543
+ return `The pi run completed.\n\n${results.join("\n\n")}`;
 
 
 
 
544
  }
545
 
546
  function mockPlan(context) {
 
554
  const userText = textFromContent(last?.content || "").toLowerCase();
555
  if (userText.includes("read")) {
556
  return {
557
+ toolCalls: [{ tool: "read", args: { path: "hello.js" } }],
558
  };
559
  }
560
+ if (userText.includes("list") || userText.includes("ls")) {
561
  return {
562
+ toolCalls: [{ tool: "ls", args: { path: "." } }],
563
  };
564
  }
565
  if (userText.includes("install") || userText.includes("dependency") || userText.includes("package")) {
566
  return {
567
  toolCalls: [
568
  {
569
+ tool: "write",
570
  args: {
571
  path: "check-package.mjs",
572
  content: 'import isNumber from "is-number";\nconsole.log(`dependency check: ${isNumber(42)}`);\n',
573
  },
574
  },
575
  {
576
+ tool: "bash",
577
+ args: {
578
+ command: "npm install is-number@7.0.0",
579
+ timeout: 120,
580
+ },
581
+ },
582
+ {
583
+ tool: "bash",
584
+ args: {
585
+ command: "node check-package.mjs",
586
+ timeout: 10,
587
+ },
588
+ },
589
+ ],
590
+ };
591
+ }
592
+ if (userText.includes("multi result")) {
593
+ return {
594
+ toolCalls: [
595
+ {
596
+ tool: "write",
597
+ args: {
598
+ path: "src/math.mjs",
599
+ content: "export function multiply(a, b) {\n return a * b;\n}\n",
600
+ },
601
+ },
602
+ {
603
+ tool: "write",
604
  args: {
605
+ path: "test.mjs",
606
+ content: "import { multiply } from './src/math.mjs';\nconsole.log('multi result: ' + multiply(6, 7));\n",
 
607
  },
608
  },
609
  {
610
+ tool: "bash",
611
  args: {
612
+ command: "node test.mjs",
613
+ timeout: 10,
614
  },
615
  },
616
  ],
 
619
  return {
620
  toolCalls: [
621
  {
622
+ tool: "write",
623
  args: {
624
  path: "hello.js",
625
  content: 'const value = 21 * 2;\nconsole.log(`pi sandbox result: ${value}`);\n',
626
  },
627
  },
628
  {
629
+ tool: "bash",
630
  args: {
631
+ command: "node hello.js",
632
+ timeout: 10,
633
  },
634
  },
635
  ],
636
  };
637
  }
638
 
 
 
 
 
 
639
  function emitFinal(stream, message, text = "") {
640
  stream.push({ type: "start", partial: { ...message, content: [{ type: "text", text: "" }] } });
641
  if (text) {
 
651
  }
652
  }
653
 
654
+ function toolResult(text, details) {
655
+ return {
656
+ content: [{ type: "text", text }],
657
+ details,
658
+ };
659
+ }
660
+
661
  export function createPiAgent({ sandbox, modelMode, device, maxTokens, temperature, onModelStatus = () => {} }) {
662
  env.allowLocalModels = false;
663
  env.allowRemoteModels = true;
 
710
  if (signal?.aborted) throw new Error("Aborted");
711
  const input = model.promptStyle === "qwen" ? buildQwenMessages(context) : buildPrompt(context);
712
  const result = await generator(input, {
713
+ max_new_tokens: Number(maxTokens()) || DEFAULT_MAX_NEW_TOKENS,
714
  temperature: Number(temperature()) || 0,
715
  do_sample: Number(temperature()) > 0,
716
  return_full_text: false,
 
732
  const toolCalls = forceFinal ? [] : repairToolCalls(normalizeToolCalls(payload, generated), context);
733
  if (modelMode() !== "mock") await releaseGenerator();
734
  if (toolCalls.length > 0) {
735
+ const message = createMessage([{ type: "text", text: "Using pi tools." }, ...toolCalls], "toolUse", model);
736
+ emitFinal(stream, message, "Using pi tools.");
737
  return;
738
  }
739
  const text = normalizeFinalText(payload, generated);
 
754
 
755
  const tools = [
756
  {
757
+ name: "read",
758
+ label: "read",
759
+ description:
760
+ "Read the contents of a file. For text files, output is truncated by line count. Use offset/limit for large files. When you need the full file, continue with offset until complete.",
761
  parameters: Type.Object({
762
+ path: Type.String(),
763
+ offset: Type.Optional(Type.Number()),
764
+ limit: Type.Optional(Type.Number()),
765
+ }),
766
+ execute: async (_id, args) => {
767
+ const output = await sandbox.readTextFile(args.path, { offset: args.offset, limit: args.limit });
768
+ return toolResult(output, { path: args.path });
769
+ },
770
+ },
771
+ {
772
+ name: "bash",
773
+ label: "bash",
774
+ description:
775
+ "Execute a bash command in the current working directory. Returns stdout and stderr. Optionally provide a timeout in seconds.",
776
+ parameters: Type.Object({
777
+ command: Type.String(),
778
+ timeout: Type.Optional(Type.Number()),
779
  }),
780
  execute: async (_id, args) => {
781
+ const result = await sandbox.bash(args.command, args.timeout);
782
+ const output = result.output || "(no output)";
783
+ if (result.exitCode !== 0) {
784
+ throw new Error(`${output}\n\nCommand exited with code ${result.exitCode}`);
785
+ }
786
+ return toolResult(output, result);
787
  },
788
+ executionMode: "sequential",
789
  },
790
  {
791
+ name: "edit",
792
+ label: "edit",
793
+ description:
794
+ "Edit a single file using exact text replacement. Every edits[].oldText must match a unique, non-overlapping region of the original file.",
795
  parameters: Type.Object({
796
  path: Type.String(),
797
+ edits: Type.Array(
798
+ Type.Object({
799
+ oldText: Type.String(),
800
+ newText: Type.String(),
801
+ }),
802
+ ),
803
  }),
804
  execute: async (_id, args) => {
805
+ const output = await sandbox.editFile(args.path, args.edits);
806
+ return toolResult(output, { path: args.path, edits: args.edits });
807
  },
808
+ executionMode: "sequential",
809
  },
810
  {
811
+ name: "write",
812
+ label: "write",
813
+ description: "Write content to a file. Creates the file if it doesn't exist, overwrites if it does. Automatically creates parent directories.",
814
  parameters: Type.Object({
815
  path: Type.String(),
816
  content: Type.String(),
817
  }),
818
  execute: async (_id, args) => {
819
  const output = await sandbox.writeFile(args.path, args.content);
820
+ return toolResult(output, { path: args.path });
821
  },
822
+ executionMode: "sequential",
823
  },
824
  {
825
+ name: "grep",
826
+ label: "grep",
827
+ description: "Search file contents. This read-only Pi tool is available in the browser port.",
828
  parameters: Type.Object({
829
+ pattern: Type.String(),
830
+ path: Type.Optional(Type.String()),
831
+ glob: Type.Optional(Type.String()),
832
+ ignoreCase: Type.Optional(Type.Boolean()),
833
+ literal: Type.Optional(Type.Boolean()),
834
+ context: Type.Optional(Type.Number()),
835
+ limit: Type.Optional(Type.Number()),
836
  }),
837
  execute: async (_id, args) => {
838
+ const output = await sandbox.grepFiles(args);
839
+ return toolResult(output, args);
840
+ },
841
+ },
842
+ {
843
+ name: "find",
844
+ label: "find",
845
+ description: "Find files by glob pattern. This read-only Pi tool is available in the browser port.",
846
+ parameters: Type.Object({
847
+ pattern: Type.String(),
848
+ path: Type.Optional(Type.String()),
849
+ limit: Type.Optional(Type.Number()),
850
+ }),
851
+ execute: async (_id, args) => {
852
+ const output = await sandbox.findFiles(args.pattern, args.path || ".", args.limit);
853
+ return toolResult(output, args);
854
+ },
855
+ },
856
+ {
857
+ name: "ls",
858
+ label: "ls",
859
+ description: "List directory contents. This read-only Pi tool is available in the browser port.",
860
+ parameters: Type.Object({
861
+ path: Type.Optional(Type.String()),
862
+ limit: Type.Optional(Type.Number()),
863
+ }),
864
+ execute: async (_id, args) => {
865
+ const output = await sandbox.ls(args.path || ".", args.limit);
866
+ return toolResult(output, args);
867
  },
 
868
  },
869
  ];
870
 
 
872
  initialState: {
873
  model: createLocalModelMetadata(getLocalModel(modelMode())),
874
  systemPrompt:
875
+ "You are an expert coding assistant operating inside pi, a coding agent harness. Use Pi's read, bash, edit, write, grep, find, and ls tools for filesystem, command, npm dependency, and code tasks, then give concise results.",
876
  tools,
877
  },
878
  streamFn,
 
891
  return agent;
892
  }
893
 
894
+ export { DEFAULT_LOCAL_MODEL_KEY, DEFAULT_MAX_NEW_TOKENS, LOCAL_MODELS };
src/piCli.js ADDED
@@ -0,0 +1,524 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import { createPiAgent, DEFAULT_LOCAL_MODEL_KEY, DEFAULT_MAX_NEW_TOKENS, LOCAL_MODELS } from "./piAgent.js";
2
+ import { PI_BUILTIN_TOOLS, PI_CLI_VERSION, PI_DEFAULT_TOOLS, PI_HELP_TEXT, PI_SLASH_COMMANDS, formatHotkeys } from "./piCliContract.js";
3
+
4
+ const ANSI_PATTERN = /\x1b\[[0-9;?]*[ -/]*[@-~]/g;
5
+
6
+ function stripAnsi(text) {
7
+ return String(text).replace(ANSI_PATTERN, "");
8
+ }
9
+
10
+ function textFromContent(content) {
11
+ if (typeof content === "string") return content;
12
+ if (!Array.isArray(content)) return "";
13
+ return content
14
+ .filter((part) => part.type === "text")
15
+ .map((part) => part.text)
16
+ .join("\n");
17
+ }
18
+
19
+ function toolCallsFromMessage(message) {
20
+ return Array.isArray(message.content) ? message.content.filter((part) => part.type === "toolCall") : [];
21
+ }
22
+
23
+ function formatToolCall(call) {
24
+ const args = call.arguments || {};
25
+ switch (call.name) {
26
+ case "bash":
27
+ return `$ ${args.command || ""}${args.timeout ? ` (timeout ${args.timeout}s)` : ""}`;
28
+ case "write":
29
+ return `write ${args.path || ""} (${String(args.content || "").length} bytes)`;
30
+ case "read":
31
+ return `read ${args.path || ""}${args.offset ? `:${args.offset}` : ""}${args.limit ? ` limit=${args.limit}` : ""}`;
32
+ case "edit":
33
+ return `edit ${args.path || ""} (${Array.isArray(args.edits) ? args.edits.length : 0} replacement(s))`;
34
+ case "grep":
35
+ return `grep ${args.pattern || ""} ${args.path || "."}`;
36
+ case "find":
37
+ return `find ${args.pattern || ""} ${args.path || "."}`;
38
+ case "ls":
39
+ return `ls ${args.path || "."}`;
40
+ default:
41
+ return `${call.name} ${JSON.stringify(args)}`;
42
+ }
43
+ }
44
+
45
+ function modelLabel(mode) {
46
+ if (mode === "mock") return "Deterministic test model";
47
+ return LOCAL_MODELS[mode]?.id || LOCAL_MODELS[DEFAULT_LOCAL_MODEL_KEY].id;
48
+ }
49
+
50
+ function shortModelName(mode) {
51
+ if (mode === "mock") return "mock";
52
+ return LOCAL_MODELS[mode]?.name || LOCAL_MODELS[DEFAULT_LOCAL_MODEL_KEY].name;
53
+ }
54
+
55
+ export function createPiCli({ terminal, sandbox, nodes, params }) {
56
+ let mode = "mock";
57
+ let device = "wasm";
58
+ let maxNewTokens = DEFAULT_MAX_NEW_TOKENS;
59
+ let temperature = 0;
60
+ let modelReady = false;
61
+ let status = "Ready";
62
+ let busy = false;
63
+ let input = "";
64
+ let renderedMessages = 0;
65
+ let outputText = "";
66
+ let sessionName = "untitled";
67
+ let sessionId = crypto.randomUUID();
68
+ let queuedLines = [];
69
+ let agent = null;
70
+
71
+ if (params.get("device")) device = params.get("device");
72
+ if (params.get("tokens")) maxNewTokens = Number(params.get("tokens")) || DEFAULT_MAX_NEW_TOKENS;
73
+ if (params.get("max_new_tokens")) maxNewTokens = Number(params.get("max_new_tokens")) || DEFAULT_MAX_NEW_TOKENS;
74
+ if (LOCAL_MODELS[params.get("model")]) mode = params.get("model");
75
+ if (LOCAL_MODELS[params.get("mode")]) mode = params.get("mode");
76
+ if (params.get("mode") === "mock") mode = "mock";
77
+ if (mode !== "mock" && !LOCAL_MODELS[mode]) mode = DEFAULT_LOCAL_MODEL_KEY;
78
+ if (!navigator.gpu && device === "webgpu") device = "wasm";
79
+ modelReady = mode === "mock";
80
+
81
+ function write(text) {
82
+ const value = String(text);
83
+ outputText += stripAnsi(value).replace(/\r/g, "");
84
+ if (outputText.length > 250000) outputText = outputText.slice(-200000);
85
+ terminal.write(value);
86
+ }
87
+
88
+ function writeln(text = "") {
89
+ write(`${text}\n`);
90
+ }
91
+
92
+ function setStatus(next) {
93
+ status = next;
94
+ nodes.status.textContent = next;
95
+ }
96
+
97
+ function setModelStatus(next) {
98
+ nodes.modelStatus.textContent = next;
99
+ nodes.modelLabel.textContent = modelLabel(mode);
100
+ }
101
+
102
+ function setSandboxStatus(next) {
103
+ nodes.sandboxStatus.textContent = next;
104
+ }
105
+
106
+ function createAgent() {
107
+ const next = createPiAgent({
108
+ sandbox,
109
+ modelMode: () => mode,
110
+ device: () => device,
111
+ maxTokens: () => maxNewTokens,
112
+ temperature: () => temperature,
113
+ onModelStatus: setModelStatus,
114
+ });
115
+ next.subscribe((event) => {
116
+ switch (event.type) {
117
+ case "agent_start":
118
+ setStatus("Agent running");
119
+ break;
120
+ case "tool_execution_start":
121
+ writeln(`\x1b[2m[running ${event.toolName}]\x1b[22m`);
122
+ break;
123
+ case "message_end":
124
+ renderNewMessages();
125
+ break;
126
+ case "agent_end":
127
+ setStatus("Ready");
128
+ break;
129
+ default:
130
+ break;
131
+ }
132
+ });
133
+ return next;
134
+ }
135
+
136
+ function resetAgent() {
137
+ agent?.abort();
138
+ agent = createAgent();
139
+ renderedMessages = 0;
140
+ }
141
+
142
+ async function bootSandbox({ quiet = false } = {}) {
143
+ if (!quiet) writeln("\x1b[2mBooting WebContainer sandbox...\x1b[22m");
144
+ await sandbox.boot();
145
+ if (!quiet) writeln("\x1b[2mSandbox ready.\x1b[22m");
146
+ }
147
+
148
+ function showGate(message = "Ready.") {
149
+ nodes.gateStatus.textContent = message;
150
+ nodes.modelGate.classList.remove("hidden");
151
+ }
152
+
153
+ function hideGate() {
154
+ nodes.modelGate.classList.add("hidden");
155
+ }
156
+
157
+ async function loadModel() {
158
+ if (mode === "mock") {
159
+ modelReady = true;
160
+ setModelStatus("Deterministic test model");
161
+ hideGate();
162
+ return;
163
+ }
164
+ busy = true;
165
+ setStatus("Loading model");
166
+ nodes.gateStatus.textContent = "Booting sandbox...";
167
+ writeln(`\x1b[2mPreparing ${modelLabel(mode)} on ${device}...\x1b[22m`);
168
+ try {
169
+ await bootSandbox({ quiet: true });
170
+ nodes.gateStatus.textContent = "Downloading model...";
171
+ await agent.preloadModel();
172
+ modelReady = true;
173
+ setModelStatus("Model ready");
174
+ nodes.gateStatus.textContent = "Model ready.";
175
+ hideGate();
176
+ writeln("\x1b[32mModel ready.\x1b[0m");
177
+ } catch (error) {
178
+ const message = error.stack || error.message || String(error);
179
+ setModelStatus("Model error");
180
+ nodes.gateStatus.textContent = message;
181
+ writeln(`\x1b[31m${message}\x1b[0m`);
182
+ } finally {
183
+ busy = false;
184
+ setStatus("Ready");
185
+ writePrompt();
186
+ }
187
+ }
188
+
189
+ function writeStartup() {
190
+ writeln(`pi - AI coding assistant with read, bash, edit, write tools`);
191
+ writeln(`version ${PI_CLI_VERSION} | web terminal ${terminal.engine} | cwd /workspace`);
192
+ writeln(`shortcuts: /hotkeys | /model | /settings | /session | /help`);
193
+ writeln(`loaded AGENTS.md: none | prompt templates: none | skills: none | extensions: none`);
194
+ writeln(`tools: ${PI_DEFAULT_TOOLS.join(", ")} (read-only extras available: grep, find, ls)`);
195
+ if (!modelReady) {
196
+ writeln(`model: ${modelLabel(mode)} is not downloaded. Use the setup dialog or /model mock.`);
197
+ } else {
198
+ writeln(`model: ${modelLabel(mode)}`);
199
+ }
200
+ writeln();
201
+ }
202
+
203
+ function footer() {
204
+ return `cwd /workspace | session ${sessionName} | model ${shortModelName(mode)} | ${maxNewTokens} max tokens | ${status}`;
205
+ }
206
+
207
+ function writePrompt() {
208
+ if (busy) return;
209
+ writeln(`\x1b[2m${footer()}\x1b[22m`);
210
+ write("> ");
211
+ terminal.focus();
212
+ }
213
+
214
+ function renderNewMessages() {
215
+ const messages = agent.state.messages;
216
+ while (renderedMessages < messages.length) {
217
+ const message = messages[renderedMessages];
218
+ renderedMessages += 1;
219
+ if (message.role === "user") continue;
220
+ if (message.role === "toolResult") {
221
+ const text = textFromContent(message.content);
222
+ const label = message.isError ? `[tool error: ${message.toolName}]` : `[tool: ${message.toolName}]`;
223
+ writeln(`\x1b[36m${label}\x1b[0m`);
224
+ if (text) writeln(text);
225
+ writeln();
226
+ continue;
227
+ }
228
+ const toolCalls = toolCallsFromMessage(message);
229
+ if (toolCalls.length > 0) {
230
+ writeln("\x1b[35mUsing pi tools:\x1b[0m");
231
+ for (const call of toolCalls) writeln(` ${formatToolCall(call)}`);
232
+ writeln();
233
+ continue;
234
+ }
235
+ const text = textFromContent(message.content);
236
+ if (text) {
237
+ writeln("\x1b[32mpi\x1b[0m");
238
+ writeln(text);
239
+ writeln();
240
+ }
241
+ }
242
+ }
243
+
244
+ async function runBashLine(command, sendToModel) {
245
+ busy = true;
246
+ setStatus("Running command");
247
+ try {
248
+ await bootSandbox({ quiet: true });
249
+ writeln(`$ ${command}`);
250
+ const result = await sandbox.bash(command, 120);
251
+ if (result.output) writeln(result.output);
252
+ writeln(`exit ${result.exitCode}`);
253
+ if (sendToModel) {
254
+ await promptAgent(`Command output from \`${command}\`:\n${result.output || "(no output)"}\nexit ${result.exitCode}`);
255
+ }
256
+ } catch (error) {
257
+ writeln(`\x1b[31m${error.stack || error.message || String(error)}\x1b[0m`);
258
+ } finally {
259
+ busy = false;
260
+ setStatus("Ready");
261
+ if (!sendToModel) writePrompt();
262
+ }
263
+ }
264
+
265
+ async function promptAgent(prompt) {
266
+ if (mode !== "mock" && !modelReady) {
267
+ writeln("Download the selected local model before sending, or use /model mock.");
268
+ showGate("Download the selected model before sending, or use the test model.");
269
+ writePrompt();
270
+ return;
271
+ }
272
+
273
+ busy = true;
274
+ setStatus("Agent running");
275
+ try {
276
+ await bootSandbox({ quiet: true });
277
+ await agent.prompt(prompt);
278
+ } catch (error) {
279
+ writeln(`\x1b[31m${error.stack || error.message || String(error)}\x1b[0m`);
280
+ } finally {
281
+ busy = false;
282
+ setStatus("Ready");
283
+ const next = queuedLines.shift();
284
+ if (next) {
285
+ writeln(`\x1b[2m[dequeued] ${next}\x1b[22m`);
286
+ await handleLine(next, { fromQueue: true });
287
+ } else {
288
+ writePrompt();
289
+ }
290
+ }
291
+ }
292
+
293
+ function printModels() {
294
+ writeln("Available browser-local models:");
295
+ for (const [key, value] of Object.entries(LOCAL_MODELS)) {
296
+ writeln(` ${key.padEnd(12)} ${value.id}`);
297
+ }
298
+ writeln(" mock deterministic test model");
299
+ writeln("Use /model <key> to switch. Non-mock models run in this browser through Transformers.js.");
300
+ }
301
+
302
+ function printSession() {
303
+ writeln(`Session`);
304
+ writeln(` id: ${sessionId}`);
305
+ writeln(` name: ${sessionName}`);
306
+ writeln(` messages: ${agent.state.messages.length}`);
307
+ writeln(` cwd: /workspace`);
308
+ writeln(` storage: browser memory`);
309
+ }
310
+
311
+ async function handleSlash(line) {
312
+ const [command, ...rest] = line.trim().split(/\s+/);
313
+ const argText = rest.join(" ");
314
+ switch (command) {
315
+ case "/help":
316
+ writeln(PI_HELP_TEXT);
317
+ break;
318
+ case "/hotkeys":
319
+ writeln(formatHotkeys());
320
+ break;
321
+ case "/model":
322
+ if (!argText) {
323
+ printModels();
324
+ break;
325
+ }
326
+ if (argText === "mock" || LOCAL_MODELS[argText]) {
327
+ mode = argText;
328
+ modelReady = mode === "mock";
329
+ resetAgent();
330
+ setModelStatus(modelReady ? "Deterministic test model" : "Model idle");
331
+ writeln(`model: ${modelLabel(mode)}`);
332
+ if (!modelReady) showGate("Download the selected model before sending.");
333
+ else hideGate();
334
+ } else {
335
+ writeln(`Unknown model: ${argText}`);
336
+ printModels();
337
+ }
338
+ break;
339
+ case "/settings":
340
+ if (argText.startsWith("device=")) {
341
+ device = argText.slice("device=".length) || device;
342
+ modelReady = mode === "mock";
343
+ resetAgent();
344
+ } else if (argText.startsWith("tokens=")) {
345
+ maxNewTokens = Number(argText.slice("tokens=".length)) || maxNewTokens;
346
+ } else if (argText.startsWith("temperature=")) {
347
+ temperature = Number(argText.slice("temperature=".length)) || 0;
348
+ }
349
+ writeln(`Settings`);
350
+ writeln(` device: ${device}`);
351
+ writeln(` max tokens: ${maxNewTokens}`);
352
+ writeln(` temperature: ${temperature}`);
353
+ writeln(` transport: browser-local Transformers.js`);
354
+ break;
355
+ case "/session":
356
+ printSession();
357
+ break;
358
+ case "/new":
359
+ resetAgent();
360
+ await sandbox.reset();
361
+ sessionId = crypto.randomUUID();
362
+ sessionName = "untitled";
363
+ writeln("Started a new browser session and reset the WebContainer workspace.");
364
+ break;
365
+ case "/name":
366
+ sessionName = argText || "untitled";
367
+ writeln(`Session name: ${sessionName}`);
368
+ break;
369
+ case "/tools":
370
+ writeln(`Default tools: ${PI_DEFAULT_TOOLS.join(", ")}`);
371
+ writeln(`Built-in tools: ${PI_BUILTIN_TOOLS.join(", ")}`);
372
+ break;
373
+ case "/clear":
374
+ terminal.clear();
375
+ outputText = "";
376
+ writeStartup();
377
+ break;
378
+ case "/login":
379
+ case "/logout":
380
+ writeln("This web port runs a local browser model, so provider login is not required. Use /model to switch local planners.");
381
+ break;
382
+ case "/resume":
383
+ case "/tree":
384
+ case "/fork":
385
+ case "/clone":
386
+ case "/compact":
387
+ case "/copy":
388
+ case "/export":
389
+ case "/share":
390
+ case "/reload":
391
+ case "/changelog":
392
+ case "/scoped-models":
393
+ writeln(`${command} is recognized from Pi CLI. In this static browser build it is represented in-memory; full filesystem-backed session management is a follow-up target.`);
394
+ break;
395
+ case "/quit":
396
+ writeln("Close this browser tab to quit the web terminal.");
397
+ break;
398
+ case "/commands":
399
+ writeln(PI_SLASH_COMMANDS.join("\n"));
400
+ break;
401
+ default:
402
+ writeln(`Unknown command: ${command}`);
403
+ writeln("Type /help or /commands.");
404
+ break;
405
+ }
406
+ }
407
+
408
+ async function handleLine(line, { fromQueue = false } = {}) {
409
+ const trimmed = line.trim();
410
+ if (!trimmed) {
411
+ writePrompt();
412
+ return;
413
+ }
414
+ if (busy && !fromQueue) {
415
+ queuedLines.push(line);
416
+ writeln(`\x1b[2m[queued] ${line}\x1b[22m`);
417
+ return;
418
+ }
419
+ if (trimmed.startsWith("/")) {
420
+ await handleSlash(trimmed);
421
+ writePrompt();
422
+ return;
423
+ }
424
+ if (trimmed.startsWith("!!")) {
425
+ await runBashLine(trimmed.slice(2).trim(), false);
426
+ return;
427
+ }
428
+ if (trimmed.startsWith("!")) {
429
+ await runBashLine(trimmed.slice(1).trim(), true);
430
+ return;
431
+ }
432
+ await promptAgent(line);
433
+ }
434
+
435
+ function redrawInput(nextInput) {
436
+ write("\r\x1b[2K> ");
437
+ input = nextInput;
438
+ write(input);
439
+ }
440
+
441
+ function handleData(data) {
442
+ for (const char of data) {
443
+ if (char === "\r") {
444
+ const submitted = input;
445
+ input = "";
446
+ writeln();
447
+ void handleLine(submitted);
448
+ } else if (char === "\u007f") {
449
+ if (input.length > 0) {
450
+ input = input.slice(0, -1);
451
+ write("\b \b");
452
+ }
453
+ } else if (char === "\x03") {
454
+ if (busy) {
455
+ agent.abort();
456
+ writeln("^C");
457
+ setStatus("Aborted");
458
+ } else if (input) {
459
+ redrawInput("");
460
+ } else {
461
+ writeln("^C");
462
+ writeln("Use /quit or close this browser tab to exit.");
463
+ writePrompt();
464
+ }
465
+ } else if (char === "\x1b") {
466
+ if (busy) agent.abort();
467
+ } else if (char >= " " && char !== "\x7f") {
468
+ input += char;
469
+ write(char);
470
+ }
471
+ }
472
+ }
473
+
474
+ nodes.confirmLoadModel.addEventListener("click", async () => {
475
+ device = nodes.gateDevice.value;
476
+ await loadModel();
477
+ });
478
+ nodes.useTestModel.addEventListener("click", () => {
479
+ mode = "mock";
480
+ modelReady = true;
481
+ resetAgent();
482
+ setModelStatus("Deterministic test model");
483
+ hideGate();
484
+ writeln("model: deterministic test model");
485
+ writePrompt();
486
+ });
487
+
488
+ resetAgent();
489
+ setStatus("Ready");
490
+ setSandboxStatus("Not booted");
491
+ setModelStatus(modelReady ? "Deterministic test model" : "Model idle");
492
+ nodes.gateDevice.value = device;
493
+ if (modelReady || params.get("setup") === "skip") hideGate();
494
+ else showGate("Ready.");
495
+
496
+ terminal.onData(handleData);
497
+ writeStartup();
498
+ writePrompt();
499
+
500
+ return {
501
+ loadModel,
502
+ handleLine,
503
+ get outputText() {
504
+ return outputText;
505
+ },
506
+ get transcript() {
507
+ return agent.state.messages
508
+ .map((message) => {
509
+ if (message.role === "toolResult") return `TOOL ${message.toolName}\n${textFromContent(message.content)}`;
510
+ return `${message.role.toUpperCase()}\n${textFromContent(message.content)}`;
511
+ })
512
+ .join("\n\n");
513
+ },
514
+ get modelReady() {
515
+ return modelReady;
516
+ },
517
+ get status() {
518
+ return status;
519
+ },
520
+ get mode() {
521
+ return mode;
522
+ },
523
+ };
524
+ }
src/piCliContract.js ADDED
@@ -0,0 +1,101 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ export const PI_CLI_VERSION = "0.77.0";
2
+
3
+ export const PI_DEFAULT_TOOLS = ["read", "bash", "edit", "write"];
4
+ export const PI_BUILTIN_TOOLS = ["read", "bash", "edit", "write", "grep", "find", "ls"];
5
+
6
+ export const PI_SLASH_COMMANDS = [
7
+ "/login",
8
+ "/logout",
9
+ "/model",
10
+ "/scoped-models",
11
+ "/settings",
12
+ "/resume",
13
+ "/new",
14
+ "/name <name>",
15
+ "/session",
16
+ "/tree",
17
+ "/fork",
18
+ "/clone",
19
+ "/compact [prompt]",
20
+ "/copy",
21
+ "/export [file]",
22
+ "/share",
23
+ "/reload",
24
+ "/hotkeys",
25
+ "/changelog",
26
+ "/quit",
27
+ ];
28
+
29
+ export const PI_HELP_TEXT = `pi - AI coding assistant with read, bash, edit, write tools
30
+
31
+ Usage:
32
+ pi [options] [@files...] [messages...]
33
+
34
+ Commands:
35
+ pi install <source> [-l] Install extension source and add to settings
36
+ pi remove <source> [-l] Remove extension source from settings
37
+ pi uninstall <source> [-l] Alias for remove
38
+ pi update [source|self|pi] Update pi and installed extensions
39
+ pi list List installed extensions from settings
40
+ pi config Open TUI to enable/disable package resources
41
+ pi <command> --help Show help for install/remove/uninstall/update/list
42
+
43
+ Options:
44
+ --provider <name> Provider name (default: google)
45
+ --model <pattern> Model pattern or ID (supports "provider/id" and optional ":<thinking>")
46
+ --api-key <key> API key (defaults to env vars)
47
+ --system-prompt <text> System prompt (default: coding assistant prompt)
48
+ --append-system-prompt <text> Append text or file contents to the system prompt (can be used multiple times)
49
+ --mode <mode> Output mode: text (default), json, or rpc
50
+ --print, -p Non-interactive mode: process prompt and exit
51
+ --continue, -c Continue previous session
52
+ --resume, -r Select a session to resume
53
+ --session <path|id> Use specific session file or partial UUID
54
+ --session-id <id> Use exact project session ID, creating it if missing
55
+ --fork <path|id> Fork specific session file or partial UUID into a new session
56
+ --session-dir <dir> Directory for session storage and lookup
57
+ --no-session Don't save session (ephemeral)
58
+ --models <patterns> Comma-separated model patterns for Ctrl+P cycling
59
+ --no-tools, -nt Disable all tools by default (built-in and extension)
60
+ --no-builtin-tools, -nbt Disable built-in tools by default but keep extension/custom tools enabled
61
+ --tools, -t <tools> Comma-separated allowlist of tool names to enable
62
+ --exclude-tools, -xt <tools> Comma-separated denylist of tool names to disable
63
+ --thinking <level> Set thinking level: off, minimal, low, medium, high, xhigh
64
+ --extension, -e <path> Load an extension file (can be used multiple times)
65
+ --no-extensions, -ne Disable extension discovery (explicit -e paths still work)
66
+ --skill <path> Load a skill file or directory (can be used multiple times)
67
+ --prompt-template <path> Load a prompt template file or directory (can be used multiple times)
68
+ --theme <path> Load a theme file or directory (can be used multiple times)
69
+ --no-themes Disable theme discovery and loading
70
+ --no-context-files, -nc Disable AGENTS.md and CLAUDE.md discovery and loading
71
+ --export <file> Export session file to HTML and exit
72
+ --list-models [search] List available models (with optional fuzzy search)
73
+ --verbose Force verbose startup (overrides quietStartup setting)
74
+ --offline Disable startup network operations (same as PI_OFFLINE=1)
75
+ --help, -h Show this help
76
+ --version, -v Show version number
77
+
78
+ Built-in Tool Names:
79
+ read - Read file contents
80
+ bash - Execute bash commands
81
+ edit - Edit files with find/replace
82
+ write - Write files (creates/overwrites)
83
+ grep - Search file contents (read-only, off by default)
84
+ find - Find files by glob pattern (read-only, off by default)
85
+ ls - List directory contents (read-only, off by default)`;
86
+
87
+ export function formatHotkeys() {
88
+ return `Common Pi keybindings
89
+
90
+ Ctrl+C Clear editor
91
+ Ctrl+C twice Quit
92
+ Escape Cancel or abort
93
+ Escape twice Open /tree
94
+ Ctrl+L Open /model
95
+ Ctrl+P Cycle scoped models forward
96
+ Shift+Ctrl+P Cycle scoped models backward
97
+ Shift+Tab Cycle thinking level
98
+ Ctrl+O Collapse or expand tool output
99
+ Ctrl+T Collapse or expand thinking blocks
100
+ Shift+Enter Multi-line input`;
101
+ }
src/sandbox.js CHANGED
@@ -30,6 +30,58 @@ const BOOT_FILES = {
30
 
31
  const MAX_OUTPUT_CHARS = 16000;
32
  const DEFAULT_TIMEOUT_MS = 10000;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
33
 
34
  export function createSandbox({ onLog = () => {}, onStatus = () => {} } = {}) {
35
  let instance = null;
@@ -65,20 +117,34 @@ export function createSandbox({ onLog = () => {}, onStatus = () => {} } = {}) {
65
  }
66
  }
67
 
68
- function assertRelativePath(path) {
69
- const value = String(path || "").trim().replace(/^\/+/, "");
70
- if (!value || value.includes("\0")) {
71
- throw new Error("Path is required.");
72
- }
 
73
  const segments = value.split("/").filter(Boolean);
74
- if (segments.some((segment) => segment === "." || segment === "..")) {
75
  throw new Error("Paths must stay inside the sandbox workspace.");
76
  }
77
- return segments.join("/");
 
 
 
78
  }
79
 
80
- function toWorkspacePath(path) {
81
- return assertRelativePath(path);
 
 
 
 
 
 
 
 
 
 
82
  }
83
 
84
  async function reset() {
@@ -97,16 +163,61 @@ export function createSandbox({ onLog = () => {}, onStatus = () => {} } = {}) {
97
  return "Sandbox reset to the starter project.";
98
  }
99
 
100
- async function listFiles(path = ".") {
101
  const wc = await boot();
102
- const target = path === "." || path === "" ? "." : toWorkspacePath(path);
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  const entries = await wc.fs.readdir(target, { withFileTypes: true });
104
- return entries.map((entry) => `${entry.isDirectory() ? "dir " : "file"} ${entry.name}`).join("\n") || "(empty)";
 
 
 
 
 
105
  }
106
 
107
- async function readFile(path) {
108
  const wc = await boot();
109
- return await wc.fs.readFile(toWorkspacePath(path), "utf-8");
 
 
 
 
 
 
 
 
 
 
 
110
  }
111
 
112
  async function writeFile(path, content) {
@@ -118,10 +229,87 @@ export function createSandbox({ onLog = () => {}, onStatus = () => {} } = {}) {
118
  }
119
  await wc.fs.writeFile(relative, String(content ?? ""));
120
  onLog(`wrote ${relative}`);
121
- return `Wrote ${relative}`;
122
  }
123
 
124
- async function runCommand(command, args = [], timeoutMs = DEFAULT_TIMEOUT_MS) {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
125
  const wc = await boot();
126
  const cmd = String(command || "").trim();
127
  if (!cmd) throw new Error("Command is required.");
@@ -169,13 +357,30 @@ export function createSandbox({ onLog = () => {}, onStatus = () => {} } = {}) {
169
  return result;
170
  }
171
 
 
 
 
 
 
 
 
 
 
 
 
172
  return {
173
  boot,
174
  reset,
175
- listFiles,
176
- readFile,
 
 
 
 
 
 
177
  writeFile,
178
- runCommand,
179
  get isReady() {
180
  return Boolean(instance);
181
  },
 
30
 
31
  const MAX_OUTPUT_CHARS = 16000;
32
  const DEFAULT_TIMEOUT_MS = 10000;
33
+ const DEFAULT_MAX_READ_LINES = 2000;
34
+ const DEFAULT_RESULT_LIMIT = 200;
35
+
36
+ function splitCommandLine(value) {
37
+ const parts = [];
38
+ let current = "";
39
+ let quote = "";
40
+ let escaping = false;
41
+ for (const char of String(value || "")) {
42
+ if (escaping) {
43
+ current += char;
44
+ escaping = false;
45
+ continue;
46
+ }
47
+ if (char === "\\") {
48
+ escaping = true;
49
+ continue;
50
+ }
51
+ if (quote) {
52
+ if (char === quote) {
53
+ quote = "";
54
+ } else {
55
+ current += char;
56
+ }
57
+ continue;
58
+ }
59
+ if (char === "\"" || char === "'") {
60
+ quote = char;
61
+ } else if (/\s/.test(char)) {
62
+ if (current) {
63
+ parts.push(current);
64
+ current = "";
65
+ }
66
+ } else {
67
+ current += char;
68
+ }
69
+ }
70
+ if (current) parts.push(current);
71
+ return parts;
72
+ }
73
+
74
+ function escapeRegExp(value) {
75
+ return String(value).replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
76
+ }
77
+
78
+ function globToRegExp(glob) {
79
+ const source = String(glob || "*")
80
+ .split("*")
81
+ .map(escapeRegExp)
82
+ .join(".*");
83
+ return new RegExp(`^${source}$`);
84
+ }
85
 
86
  export function createSandbox({ onLog = () => {}, onStatus = () => {} } = {}) {
87
  let instance = null;
 
117
  }
118
  }
119
 
120
+ function assertRelativePath(path, { allowDot = false } = {}) {
121
+ let value = String(path ?? (allowDot ? "." : "")).trim();
122
+ if (value === "" && allowDot) value = ".";
123
+ value = value.replace(/^\/+/, "").replace(/^workspace\/?/, "");
124
+ if (value === "." && allowDot) return ".";
125
+ if (!value || value.includes("\0")) throw new Error("Path is required.");
126
  const segments = value.split("/").filter(Boolean);
127
+ if (segments.some((segment) => segment === "..")) {
128
  throw new Error("Paths must stay inside the sandbox workspace.");
129
  }
130
+ const normalized = segments.filter((segment) => segment !== ".").join("/");
131
+ if (!normalized && allowDot) return ".";
132
+ if (!normalized) throw new Error("Path is required.");
133
+ return normalized;
134
  }
135
 
136
+ function toWorkspacePath(path, options) {
137
+ return assertRelativePath(path, options);
138
+ }
139
+
140
+ async function pathExists(path) {
141
+ const wc = await boot();
142
+ try {
143
+ await wc.fs.stat(toWorkspacePath(path, { allowDot: true }));
144
+ return true;
145
+ } catch {
146
+ return false;
147
+ }
148
  }
149
 
150
  async function reset() {
 
163
  return "Sandbox reset to the starter project.";
164
  }
165
 
166
+ async function walkFiles(start = ".") {
167
  const wc = await boot();
168
+ const rootPath = toWorkspacePath(start, { allowDot: true });
169
+ const files = [];
170
+
171
+ async function walk(current) {
172
+ const entries = await wc.fs.readdir(current, { withFileTypes: true });
173
+ for (const entry of entries) {
174
+ if (entry.name === "node_modules" || entry.name === ".git") continue;
175
+ const child = current === "." ? entry.name : `${current}/${entry.name}`;
176
+ if (entry.isDirectory()) {
177
+ await walk(child);
178
+ } else {
179
+ files.push(child);
180
+ }
181
+ }
182
+ }
183
+
184
+ const stat = await wc.fs.stat(rootPath);
185
+ if (stat.isDirectory()) {
186
+ await walk(rootPath);
187
+ } else {
188
+ files.push(rootPath);
189
+ }
190
+ return files;
191
+ }
192
+
193
+ async function ls(path = ".", limit = DEFAULT_RESULT_LIMIT) {
194
+ const wc = await boot();
195
+ const target = toWorkspacePath(path || ".", { allowDot: true });
196
+ const stat = await wc.fs.stat(target);
197
+ if (!stat.isDirectory()) return `file ${target}`;
198
  const entries = await wc.fs.readdir(target, { withFileTypes: true });
199
+ const capped = entries.slice(0, Number(limit || DEFAULT_RESULT_LIMIT));
200
+ const lines = capped.map((entry) => `${entry.isDirectory() ? "dir " : "file"} ${entry.name}`);
201
+ if (entries.length > capped.length) {
202
+ lines.push(`[Showing ${capped.length} of ${entries.length} entries. Use a larger limit to continue.]`);
203
+ }
204
+ return lines.join("\n") || "(empty)";
205
  }
206
 
207
+ async function readTextFile(path, { offset, limit } = {}) {
208
  const wc = await boot();
209
+ const target = toWorkspacePath(path);
210
+ const text = await wc.fs.readFile(target, "utf-8");
211
+ const lines = text.split("\n");
212
+ const start = Math.max(0, Number(offset || 1) - 1);
213
+ if (start >= lines.length) throw new Error(`Offset ${offset} is beyond end of file (${lines.length} lines total)`);
214
+ const maxLines = Number(limit || DEFAULT_MAX_READ_LINES);
215
+ const selected = lines.slice(start, start + maxLines);
216
+ let output = selected.join("\n");
217
+ if (start + selected.length < lines.length) {
218
+ output += `\n\n[${lines.length - start - selected.length} more lines in file. Use offset=${start + selected.length + 1} to continue.]`;
219
+ }
220
+ return output;
221
  }
222
 
223
  async function writeFile(path, content) {
 
229
  }
230
  await wc.fs.writeFile(relative, String(content ?? ""));
231
  onLog(`wrote ${relative}`);
232
+ return `Successfully wrote ${String(content ?? "").length} bytes to ${relative}`;
233
  }
234
 
235
+ async function editFile(path, edits = []) {
236
+ const wc = await boot();
237
+ const target = toWorkspacePath(path);
238
+ if (!Array.isArray(edits) || edits.length === 0) {
239
+ throw new Error("Edit tool input is invalid. edits must contain at least one replacement.");
240
+ }
241
+ const original = await wc.fs.readFile(target, "utf-8");
242
+ const replacements = [];
243
+ for (const edit of edits) {
244
+ const oldText = String(edit?.oldText ?? "");
245
+ const newText = String(edit?.newText ?? "");
246
+ if (!oldText) throw new Error("Every edit.oldText must be non-empty.");
247
+ const first = original.indexOf(oldText);
248
+ if (first === -1) throw new Error(`Could not edit file: ${path}. oldText was not found.`);
249
+ if (original.indexOf(oldText, first + oldText.length) !== -1) {
250
+ throw new Error(`Could not edit file: ${path}. oldText must match exactly one location.`);
251
+ }
252
+ replacements.push({ start: first, end: first + oldText.length, newText });
253
+ }
254
+ replacements.sort((a, b) => b.start - a.start);
255
+ for (let index = 1; index < replacements.length; index += 1) {
256
+ if (replacements[index].end > replacements[index - 1].start) {
257
+ throw new Error("Edit tool input is invalid. edits must not overlap.");
258
+ }
259
+ }
260
+ let next = original;
261
+ for (const replacement of replacements) {
262
+ next = `${next.slice(0, replacement.start)}${replacement.newText}${next.slice(replacement.end)}`;
263
+ }
264
+ await wc.fs.writeFile(target, next);
265
+ onLog(`edited ${target}`);
266
+ return `Successfully replaced ${edits.length} block(s) in ${path}.`;
267
+ }
268
+
269
+ async function findFiles(pattern = "*", path = ".", limit = DEFAULT_RESULT_LIMIT) {
270
+ const start = toWorkspacePath(path || ".", { allowDot: true });
271
+ if (!(await pathExists(start))) throw new Error(`Path does not exist: ${path || "."}`);
272
+ const matcher = globToRegExp(pattern);
273
+ const files = await walkFiles(start);
274
+ const matches = files.filter((file) => matcher.test(file) || matcher.test(file.split("/").pop() || ""));
275
+ const capped = matches.slice(0, Number(limit || DEFAULT_RESULT_LIMIT));
276
+ if (matches.length > capped.length) capped.push(`[Showing ${capped.length} of ${matches.length} matches. Use a larger limit to continue.]`);
277
+ return capped.join("\n") || "(no matches)";
278
+ }
279
+
280
+ async function grepFiles({ pattern, path = ".", glob = "*", ignoreCase = false, literal = false, context = 0, limit = DEFAULT_RESULT_LIMIT }) {
281
+ if (!pattern) throw new Error("pattern is required.");
282
+ const flags = ignoreCase ? "i" : "";
283
+ const matcher = literal ? new RegExp(escapeRegExp(pattern), flags) : new RegExp(pattern, flags);
284
+ const globMatcher = globToRegExp(glob || "*");
285
+ const files = (await walkFiles(path || ".")).filter((file) => globMatcher.test(file) || globMatcher.test(file.split("/").pop() || ""));
286
+ const matches = [];
287
+ for (const file of files) {
288
+ let text = "";
289
+ try {
290
+ text = await readTextFile(file, { limit: DEFAULT_MAX_READ_LINES });
291
+ } catch {
292
+ continue;
293
+ }
294
+ const lines = text.split("\n");
295
+ for (let index = 0; index < lines.length; index += 1) {
296
+ if (!matcher.test(lines[index])) continue;
297
+ matcher.lastIndex = 0;
298
+ const before = Math.max(0, index - Number(context || 0));
299
+ const after = Math.min(lines.length - 1, index + Number(context || 0));
300
+ for (let lineIndex = before; lineIndex <= after; lineIndex += 1) {
301
+ matches.push(`${file}:${lineIndex + 1}:${lines[lineIndex]}`);
302
+ if (matches.length >= Number(limit || DEFAULT_RESULT_LIMIT)) {
303
+ matches.push(`[Showing first ${matches.length - 1} matches. Use a larger limit to continue.]`);
304
+ return matches.join("\n");
305
+ }
306
+ }
307
+ }
308
+ }
309
+ return matches.join("\n") || "(no matches)";
310
+ }
311
+
312
+ async function spawnProcess(command, args = [], timeoutMs = DEFAULT_TIMEOUT_MS) {
313
  const wc = await boot();
314
  const cmd = String(command || "").trim();
315
  if (!cmd) throw new Error("Command is required.");
 
357
  return result;
358
  }
359
 
360
+ async function bash(command, timeoutSeconds) {
361
+ const timeoutMs = timeoutSeconds ? Number(timeoutSeconds) * 1000 : DEFAULT_TIMEOUT_MS;
362
+ try {
363
+ return await spawnProcess("jsh", ["-c", command], timeoutMs);
364
+ } catch (error) {
365
+ const parts = splitCommandLine(command);
366
+ if (parts.length === 0) throw error;
367
+ return await spawnProcess(parts[0], parts.slice(1), timeoutMs);
368
+ }
369
+ }
370
+
371
  return {
372
  boot,
373
  reset,
374
+ bash,
375
+ editFile,
376
+ findFiles,
377
+ grepFiles,
378
+ ls,
379
+ listFiles: ls,
380
+ readFile: (path) => readTextFile(path),
381
+ readTextFile,
382
  writeFile,
383
+ runCommand: spawnProcess,
384
  get isReady() {
385
  return Boolean(instance);
386
  },
src/styles.css CHANGED
@@ -1,6 +1,6 @@
1
  :root {
2
- color: #182233;
3
- background: #eef2f6;
4
  font-family:
5
  Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
6
  }
@@ -9,15 +9,16 @@
9
  box-sizing: border-box;
10
  }
11
 
12
- body {
13
- margin: 0;
 
14
  min-width: 320px;
 
 
15
  }
16
 
17
  button,
18
- input,
19
- select,
20
- textarea {
21
  font: inherit;
22
  }
23
 
@@ -26,8 +27,8 @@ button {
26
  padding: 0 15px;
27
  border: 0;
28
  border-radius: 6px;
29
- background: #176b6c;
30
- color: #fff;
31
  font-weight: 750;
32
  cursor: pointer;
33
  }
@@ -38,26 +39,20 @@ button:disabled {
38
  }
39
 
40
  #app {
41
- min-height: 100vh;
42
- padding: 14px;
43
- }
44
-
45
- .app-shell {
46
  display: grid;
47
  grid-template-rows: auto minmax(0, 1fr);
48
- gap: 12px;
49
- width: min(1360px, 100%);
50
- min-height: calc(100vh - 28px);
51
- margin: 0 auto;
52
  }
53
 
54
- .topbar {
55
  display: flex;
56
  align-items: end;
57
  justify-content: space-between;
58
  gap: 16px;
59
- padding: 8px 0 14px;
60
- border-bottom: 1px solid #c7d2df;
 
61
  }
62
 
63
  h1,
@@ -67,20 +62,16 @@ p {
67
  }
68
 
69
  h1 {
70
- font-size: 34px;
 
71
  line-height: 1;
72
  letter-spacing: 0;
73
  }
74
 
75
- h2 {
76
- font-size: 15px;
77
- line-height: 1.2;
78
- color: #3f5064;
79
- }
80
-
81
  #model-label {
82
- margin-top: 7px;
83
- color: #5d6c7f;
 
84
  overflow-wrap: anywhere;
85
  }
86
 
@@ -89,240 +80,43 @@ h2 {
89
  flex-wrap: wrap;
90
  justify-content: end;
91
  gap: 8px;
92
- max-width: 680px;
93
  }
94
 
95
  .status {
96
- min-height: 34px;
97
- max-width: 260px;
98
- padding: 7px 10px;
99
- border: 1px solid #b7c4d3;
100
  border-radius: 6px;
101
- background: #fff;
102
- color: #314155;
 
103
  overflow-wrap: anywhere;
104
  }
105
 
106
- .layout {
107
- display: grid;
108
- grid-template-columns: minmax(0, 1fr) 340px;
109
- gap: 12px;
110
- min-height: 0;
111
- }
112
-
113
- .chat-panel,
114
- .side-panel {
115
  min-height: 0;
116
- }
117
-
118
- .chat-panel {
119
- display: grid;
120
- grid-template-rows: minmax(0, 1fr) auto;
121
- gap: 12px;
122
- }
123
-
124
- .chat-scroll {
125
- min-height: 420px;
126
- max-height: calc(100vh - 214px);
127
- overflow: auto;
128
- padding: 18px;
129
- border: 1px solid #c1ccda;
130
- border-radius: 8px;
131
- background: #fbfcfe;
132
- }
133
-
134
- .empty-chat {
135
- display: grid;
136
- align-content: center;
137
- gap: 10px;
138
- min-height: 320px;
139
- color: #4c5d72;
140
- text-align: center;
141
- }
142
-
143
- .empty-chat h2 {
144
- font-size: 24px;
145
- color: #182233;
146
- }
147
-
148
- .message {
149
- display: grid;
150
- gap: 7px;
151
- width: min(760px, 92%);
152
- margin-bottom: 14px;
153
- padding: 12px 14px;
154
- border: 1px solid #c4ceda;
155
- border-radius: 8px;
156
- background: #fff;
157
- }
158
-
159
- .message.user {
160
- margin-left: auto;
161
- border-color: #99bfbd;
162
- background: #e9f7f4;
163
- }
164
-
165
- .message.assistant {
166
- border-color: #c4ceda;
167
- }
168
-
169
- .message.tool {
170
- width: min(820px, 96%);
171
- margin-left: 24px;
172
- background: #f5f7fa;
173
- }
174
-
175
- .message.error {
176
- border-color: #d99a9a;
177
- background: #fff4f4;
178
- }
179
-
180
- .message-label {
181
- color: #5e6e82;
182
- font-size: 12px;
183
- font-weight: 800;
184
- text-transform: uppercase;
185
- }
186
-
187
- .message-body {
188
- white-space: pre-wrap;
189
- overflow-wrap: anywhere;
190
- line-height: 1.48;
191
- }
192
-
193
- .message-code,
194
- pre {
195
- margin: 0;
196
- white-space: pre-wrap;
197
- overflow: auto;
198
- overflow-wrap: anywhere;
199
- line-height: 1.45;
200
- }
201
-
202
- .message-code {
203
- max-height: 240px;
204
- padding: 10px;
205
- border-radius: 6px;
206
- background: #182233;
207
- color: #e9eef5;
208
- }
209
-
210
- .tool-call {
211
- display: grid;
212
- gap: 6px;
213
- padding: 10px;
214
- border: 1px solid #d1dae5;
215
- border-radius: 6px;
216
- background: #f7f9fc;
217
- }
218
-
219
- .tool-name {
220
- color: #315f63;
221
- font-weight: 800;
222
- }
223
-
224
- .tool-call code {
225
- white-space: pre-wrap;
226
- overflow-wrap: anywhere;
227
- }
228
-
229
- .composer {
230
- display: grid;
231
- grid-template-columns: minmax(0, 1fr) auto;
232
- gap: 10px;
233
- align-items: end;
234
- padding: 10px;
235
- border: 1px solid #c1ccda;
236
  border-radius: 8px;
237
- background: #fff;
 
238
  }
239
 
240
- textarea {
241
  width: 100%;
242
- min-height: 64px;
243
- max-height: 180px;
244
- resize: vertical;
245
- padding: 12px;
246
- border: 1px solid #b8c5d4;
247
- border-radius: 6px;
248
- background: #fff;
249
- color: #152033;
250
- line-height: 1.45;
251
- }
252
-
253
- .composer-actions {
254
- display: flex;
255
- gap: 8px;
256
- }
257
-
258
- #demo-prompt {
259
- background: #4f5f73;
260
- }
261
-
262
- .side-panel {
263
- display: grid;
264
- align-content: start;
265
- gap: 12px;
266
- }
267
-
268
- .control-group {
269
- display: grid;
270
- gap: 10px;
271
- padding: 12px;
272
- border: 1px solid #c1ccda;
273
- border-radius: 8px;
274
- background: #fff;
275
- }
276
-
277
- label {
278
- display: grid;
279
- gap: 6px;
280
- color: #526173;
281
- font-size: 13px;
282
- font-weight: 700;
283
- }
284
-
285
- select,
286
- input {
287
- width: 100%;
288
- height: 40px;
289
- padding: 0 10px;
290
- border: 1px solid #b8c5d4;
291
- border-radius: 6px;
292
- background: #fff;
293
- color: #152033;
294
- }
295
-
296
- .compact-grid {
297
- display: grid;
298
- grid-template-columns: 1fr 1fr;
299
- gap: 8px;
300
- }
301
-
302
- .button-row {
303
- display: grid;
304
- grid-template-columns: 1fr 1fr;
305
- gap: 8px;
306
- }
307
-
308
- #reset-sandbox,
309
- #use-test-model {
310
- background: #4f5f73;
311
  }
312
 
313
- #files,
314
- #event-log {
315
- min-height: 150px;
316
- max-height: 230px;
317
- padding: 10px;
318
- border: 1px solid #d1dae5;
319
- border-radius: 6px;
320
- background: #f7f9fc;
321
- color: #243248;
322
  }
323
 
324
- #event-log {
325
- max-height: 270px;
 
326
  }
327
 
328
  .model-gate {
@@ -331,7 +125,7 @@ input {
331
  display: grid;
332
  place-items: center;
333
  padding: 18px;
334
- background: rgba(20, 31, 45, 0.46);
335
  z-index: 20;
336
  }
337
 
@@ -342,24 +136,27 @@ input {
342
  .model-dialog {
343
  display: grid;
344
  gap: 16px;
345
- width: min(540px, 100%);
346
  padding: 22px;
 
347
  border-radius: 8px;
348
- background: #fff;
349
- box-shadow: 0 24px 80px rgba(17, 27, 42, 0.22);
 
350
  }
351
 
352
  .eyebrow {
353
  margin-bottom: 7px;
354
- color: #176b6c;
355
  font-size: 12px;
356
  font-weight: 850;
357
  text-transform: uppercase;
358
  }
359
 
360
  .model-dialog h2 {
361
- font-size: 24px;
362
  color: #172033;
 
 
363
  }
364
 
365
  .dialog-copy {
@@ -374,23 +171,45 @@ input {
374
  gap: 10px;
375
  }
376
 
 
 
 
 
377
  .dialog-options {
378
  display: grid;
379
  gap: 10px;
380
  color: #526173;
381
  }
382
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
383
  #gate-status {
384
  min-height: 22px;
 
385
  overflow-wrap: anywhere;
386
  }
387
 
388
- @media (max-width: 900px) {
389
  #app {
390
- padding: 10px;
391
  }
392
 
393
- .topbar {
394
  align-items: stretch;
395
  flex-direction: column;
396
  }
@@ -399,20 +218,9 @@ input {
399
  justify-content: start;
400
  }
401
 
402
- .layout {
403
- grid-template-columns: 1fr;
404
- }
405
-
406
- .chat-scroll {
407
  min-height: 360px;
408
- max-height: none;
409
- }
410
-
411
- .composer {
412
- grid-template-columns: 1fr;
413
- }
414
-
415
- .composer-actions {
416
- justify-content: end;
417
  }
418
  }
 
1
  :root {
2
+ color: #d6deeb;
3
+ background: #0b0f16;
4
  font-family:
5
  Inter, ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", sans-serif;
6
  }
 
9
  box-sizing: border-box;
10
  }
11
 
12
+ html,
13
+ body,
14
+ #app {
15
  min-width: 320px;
16
+ min-height: 100vh;
17
+ margin: 0;
18
  }
19
 
20
  button,
21
+ select {
 
 
22
  font: inherit;
23
  }
24
 
 
27
  padding: 0 15px;
28
  border: 0;
29
  border-radius: 6px;
30
+ background: #227c70;
31
+ color: #ffffff;
32
  font-weight: 750;
33
  cursor: pointer;
34
  }
 
39
  }
40
 
41
  #app {
 
 
 
 
 
42
  display: grid;
43
  grid-template-rows: auto minmax(0, 1fr);
44
+ gap: 10px;
45
+ padding: 10px;
 
 
46
  }
47
 
48
+ .runtime-bar {
49
  display: flex;
50
  align-items: end;
51
  justify-content: space-between;
52
  gap: 16px;
53
+ min-height: 54px;
54
+ padding: 4px 2px 10px;
55
+ border-bottom: 1px solid #263244;
56
  }
57
 
58
  h1,
 
62
  }
63
 
64
  h1 {
65
+ color: #f8fafc;
66
+ font-size: 30px;
67
  line-height: 1;
68
  letter-spacing: 0;
69
  }
70
 
 
 
 
 
 
 
71
  #model-label {
72
+ margin-top: 5px;
73
+ color: #9eb1ca;
74
+ font-size: 13px;
75
  overflow-wrap: anywhere;
76
  }
77
 
 
80
  flex-wrap: wrap;
81
  justify-content: end;
82
  gap: 8px;
83
+ max-width: 760px;
84
  }
85
 
86
  .status {
87
+ min-height: 32px;
88
+ max-width: 280px;
89
+ padding: 6px 10px;
90
+ border: 1px solid #344156;
91
  border-radius: 6px;
92
+ background: #141b27;
93
+ color: #cad7ea;
94
+ font-size: 13px;
95
  overflow-wrap: anywhere;
96
  }
97
 
98
+ .terminal-shell {
 
 
 
 
 
 
 
 
99
  min-height: 0;
100
+ border: 1px solid #263244;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  border-radius: 8px;
102
+ background: #10141c;
103
+ overflow: hidden;
104
  }
105
 
106
+ #terminal {
107
  width: 100%;
108
+ height: calc(100vh - 86px);
109
+ min-height: 420px;
110
+ padding: 10px;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  }
112
 
113
+ .xterm {
114
+ height: 100%;
 
 
 
 
 
 
 
115
  }
116
 
117
+ .xterm-viewport,
118
+ .xterm-screen {
119
+ border-radius: 0;
120
  }
121
 
122
  .model-gate {
 
125
  display: grid;
126
  place-items: center;
127
  padding: 18px;
128
+ background: rgba(4, 8, 14, 0.64);
129
  z-index: 20;
130
  }
131
 
 
136
  .model-dialog {
137
  display: grid;
138
  gap: 16px;
139
+ width: min(560px, 100%);
140
  padding: 22px;
141
+ border: 1px solid #334155;
142
  border-radius: 8px;
143
+ background: #f8fafc;
144
+ color: #172033;
145
+ box-shadow: 0 24px 80px rgba(0, 0, 0, 0.35);
146
  }
147
 
148
  .eyebrow {
149
  margin-bottom: 7px;
150
+ color: #227c70;
151
  font-size: 12px;
152
  font-weight: 850;
153
  text-transform: uppercase;
154
  }
155
 
156
  .model-dialog h2 {
 
157
  color: #172033;
158
+ font-size: 24px;
159
+ line-height: 1.15;
160
  }
161
 
162
  .dialog-copy {
 
171
  gap: 10px;
172
  }
173
 
174
+ #use-test-model {
175
+ background: #4f5f73;
176
+ }
177
+
178
  .dialog-options {
179
  display: grid;
180
  gap: 10px;
181
  color: #526173;
182
  }
183
 
184
+ label {
185
+ display: grid;
186
+ gap: 6px;
187
+ font-size: 13px;
188
+ font-weight: 700;
189
+ }
190
+
191
+ select {
192
+ width: 100%;
193
+ height: 40px;
194
+ padding: 0 10px;
195
+ border: 1px solid #b8c5d4;
196
+ border-radius: 6px;
197
+ background: #ffffff;
198
+ color: #152033;
199
+ }
200
+
201
  #gate-status {
202
  min-height: 22px;
203
+ color: #526173;
204
  overflow-wrap: anywhere;
205
  }
206
 
207
+ @media (max-width: 760px) {
208
  #app {
209
+ padding: 8px;
210
  }
211
 
212
+ .runtime-bar {
213
  align-items: stretch;
214
  flex-direction: column;
215
  }
 
218
  justify-content: start;
219
  }
220
 
221
+ #terminal {
222
+ height: calc(100vh - 164px);
 
 
 
223
  min-height: 360px;
224
+ padding: 8px;
 
 
 
 
 
 
 
 
225
  }
226
  }
src/webTerminal.js ADDED
@@ -0,0 +1,88 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import "@xterm/xterm/css/xterm.css";
2
+
3
+ const THEME = {
4
+ background: "#10141c",
5
+ foreground: "#d6deeb",
6
+ cursor: "#f7c948",
7
+ cursorAccent: "#10141c",
8
+ selectionBackground: "#334155",
9
+ black: "#111827",
10
+ red: "#f87171",
11
+ green: "#34d399",
12
+ yellow: "#facc15",
13
+ blue: "#60a5fa",
14
+ magenta: "#c084fc",
15
+ cyan: "#22d3ee",
16
+ white: "#f8fafc",
17
+ brightBlack: "#475569",
18
+ brightRed: "#fca5a5",
19
+ brightGreen: "#86efac",
20
+ brightYellow: "#fde68a",
21
+ brightBlue: "#93c5fd",
22
+ brightMagenta: "#d8b4fe",
23
+ brightCyan: "#67e8f9",
24
+ brightWhite: "#ffffff",
25
+ };
26
+
27
+ function normalizeNewlines(text) {
28
+ return String(text).replace(/\r?\n/g, "\r\n");
29
+ }
30
+
31
+ export async function createWebTerminal(container) {
32
+ let terminal;
33
+ let fitAddon;
34
+ let engine = "ghostty-web";
35
+
36
+ try {
37
+ const ghostty = await import("ghostty-web");
38
+ await ghostty.init();
39
+ terminal = new ghostty.Terminal({
40
+ cursorBlink: true,
41
+ fontFamily: "JetBrains Mono, SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace",
42
+ fontSize: 14,
43
+ rows: 30,
44
+ cols: 100,
45
+ scrollback: 5000,
46
+ theme: THEME,
47
+ });
48
+ fitAddon = new ghostty.FitAddon();
49
+ terminal.loadAddon(fitAddon);
50
+ } catch (error) {
51
+ const [{ Terminal }, { FitAddon }] = await Promise.all([import("@xterm/xterm"), import("@xterm/addon-fit")]);
52
+ engine = "xterm";
53
+ terminal = new Terminal({
54
+ cursorBlink: true,
55
+ fontFamily: "JetBrains Mono, SFMono-Regular, Consolas, Liberation Mono, Menlo, monospace",
56
+ fontSize: 14,
57
+ rows: 30,
58
+ cols: 100,
59
+ scrollback: 5000,
60
+ theme: THEME,
61
+ });
62
+ fitAddon = new FitAddon();
63
+ terminal.loadAddon(fitAddon);
64
+ console.warn("ghostty-web failed, using xterm fallback", error);
65
+ }
66
+
67
+ terminal.open(container);
68
+ fitAddon.fit();
69
+ terminal.focus();
70
+
71
+ const resizeObserver = new ResizeObserver(() => fitAddon.fit());
72
+ resizeObserver.observe(container);
73
+
74
+ return {
75
+ engine,
76
+ raw: terminal,
77
+ onData: (handler) => terminal.onData(handler),
78
+ write: (text) => terminal.write(normalizeNewlines(text)),
79
+ writeln: (text = "") => terminal.write(`${normalizeNewlines(text)}\r\n`),
80
+ clear: () => terminal.clear(),
81
+ focus: () => terminal.focus(),
82
+ fit: () => fitAddon.fit(),
83
+ dispose: () => {
84
+ resizeObserver.disconnect();
85
+ terminal.dispose();
86
+ },
87
+ };
88
+ }