@urun-sh/openai 0.2.55 → 0.2.57

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,4 +1,8 @@
1
- "use strict";var be=Object.create;var D=Object.defineProperty;var Ae=Object.getOwnPropertyDescriptor;var Se=Object.getOwnPropertyNames;var Re=Object.getPrototypeOf,Ee=Object.prototype.hasOwnProperty;var Te=(t,e)=>{for(var n in e)D(t,n,{get:e[n],enumerable:!0})},Z=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Se(e))!Ee.call(t,r)&&r!==n&&D(t,r,{get:()=>e[r],enumerable:!(o=Ae(e,r))||o.enumerable});return t};var ee=(t,e,n)=>(n=t!=null?be(Re(t)):{},Z(e||!t||!t.__esModule?D(n,"default",{value:t,enumerable:!0}):n,t)),Ie=t=>Z(D({},"__esModule",{value:!0}),t);var nt={};Te(nt,{SessionPool:()=>K,URUN_API:()=>Y,coalesceSameRole:()=>we,createFileDiagnosticSink:()=>ge,createUrunExtension:()=>ve,default:()=>tt,makeSessionFactory:()=>ye,makeStreamSimple:()=>_e,piDiagnosticLogPath:()=>fe,resolveSessionEnv:()=>me,toResponsesInput:()=>he});module.exports=Ie(nt);var Ue=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,x=Ue();var ue=require("@earendil-works/pi-ai"),C=require("fs"),de=ee(require("os"),1),W=require("path");function te(t,e,n,o){let r=t.response??{},l={request_id:n,consumer_id:o,stream:!0,kind:"chat",messages:e};return typeof r.instructions=="string"&&(l.instructions=r.instructions),Array.isArray(r.modalities)&&(l.modalities=r.modalities),typeof r.temperature=="number"&&(l.temperature=r.temperature),typeof r.max_output_tokens=="number"&&(l.max_output_tokens=r.max_output_tokens),r.tools!==void 0&&(l.tools=r.tools),l}function ne(t,e,n){let o={request_id:e,consumer_id:n,stream:!!t.stream,kind:"responses",input:t.input};return t.model&&(o.model=t.model),t.tools!==void 0&&(o.tools=t.tools),t.tool_choice!==void 0&&(o.tool_choice=t.tool_choice),typeof t.temperature=="number"&&(o.temperature=t.temperature),typeof t.max_output_tokens=="number"&&(o.max_output_tokens=t.max_output_tokens),o}function oe(t){if(t instanceof Error)return{type:"error",error:{type:"urun_error",code:t.name||null,message:t.message}};if(t&&typeof t=="object"&&t.t==="error"){let e=t,n=e.body??{};return{type:"error",error:{type:"urun_error",code:e.code??null,message:n.message??"unknown error"}}}return{type:"error",error:{type:"urun_error",code:null,message:String(t)}}}var Pe="llm-resp";async function*B(t,e){let n=`${Pe}:${e}`,o=`resp_${e}`;yield{type:"response.created",response:{id:o,status:"in_progress"}};let r=new Map;for await(let l of t.stream(n).messages()){let i=l;if(i.t==="delta"){if(typeof i.delta=="string"&&(yield{type:"response.output_text.delta",item_id:o,delta:i.delta}),typeof i.reasoning=="string"&&(yield{type:"response.reasoning_text.delta",item_id:o,delta:i.reasoning}),Array.isArray(i.tool_calls))for(let p of i.tool_calls){let m=typeof p.index=="number"?p.index:0,a=r.get(m)??{};p.id&&(a.id=p.id),p.function?.name&&(a.name=p.function.name),r.set(m,a),yield{type:"response.function_call_arguments.delta",item_id:`fc_${e}_${m}`,tool_index:m,call_id:a.id,name:a.name,delta:p.function?.arguments??""}}}else if(i.t==="response"){yield{type:"response.completed",response:{id:o,status:"completed",...i.body}};return}else if(i.t==="error"){yield oe(i);return}}}var Ce="llm",j=class{constructor(e){this.session=e;this.sessionTag=e.sessionId??globalThis.crypto.randomUUID()}session;sessionTag;get consumerId(){return this.session.consumerId}write(e){e.session_tag=this.sessionTag,this.session.doc(Ce).set({requests:{[e.request_id]:{payload:e,consumer_id:e.consumer_id,stream:e.stream}}})}sendResponses(e,n){let o=ne(e,n,this.consumerId);return this.write(o),B(this.session,n)}sendResponseCreate(e,n,o){let r=te(e,n,o,this.consumerId);return this.write(r),B(this.session,o)}};var re=0;function $e(){return re+=1,`req_${Date.now().toString(36)}_${re.toString(36)}`}var F=class{transport;constructor(e){this.transport=new j(e)}responses={create:async e=>{let n=$e(),o=this.transport.sendResponses(e,n);return Object.assign((async function*(){yield*o})(),{requestId:n})}}};var H="https://api.urun.sh/v1";async function se(t){let e=t.fetchImpl??fetch,n=`${t.apiUrl.replace(/\/+$/,"")}/apps`,o=await e(n,{headers:{Authorization:`Bearer ${t.apiKey}`,Accept:"application/json"}});if(!o.ok)throw new Error(`org apps listing failed: GET ${n} \u2192 ${o.status}`);let r=await o.json();if(!Array.isArray(r.apps))throw new Error(`org apps listing returned no "apps" array (GET ${n})`);if(r.truncated===!0)throw new Error(`org apps listing was truncated (GET ${n} returned ${r.apps.length} of more) \u2014 model discovery would silently omit deployed apps`);return r.apps}async function ie(t){let e=await se(t),n=e.filter(o=>o.function_name===t.fnName&&o.deployment_status==="active").map(o=>o.app_slug);if(n.length===0)throw new Error(`urun pi extension: the org has no active deployed app exposing "${t.fnName}" (GET ${t.apiUrl}/apps returned ${e.length} app(s), none servable) \u2014 deploy one with \`urun serve <model>\` first`);return n.sort()}var Y="urun-serve",Le="serve",Me=131072,Ne=16384,ae=3,Oe=42e4,De=6e4,le=2,je=15e3;function Fe(t){let e=(t.URUN_API_KEY??"").trim();if(!e)throw new Error("urun pi extension: URUN_API_KEY is required \u2014 model discovery lists the org's deployed serve apps via the org API (URUN_JWT alone cannot list apps)");return{apiKey:e,apiUrl:(t.URUN_API_URL??"").trim()||H,fnName:(t.URUN_FUNCTION??"").trim()||Le}}function me(t){let e=(t.URUN_BASE_URL??"").trim(),n=(t.URUN_ORG_ID??"").trim();if(!e)throw new Error("urun pi extension: URUN_BASE_URL is required to open a session");if(/\/v1\/*$/.test(new URL(e).pathname))throw new Error(`urun pi extension: URUN_BASE_URL must be the session-gateway base (e.g. https://api.urun.sh), got ${e} \u2014 a trailing /v1 is the org API form (URUN_API_URL); session allocation 404s against it. Drop the /v1.`);if(!n)throw new Error("urun pi extension: URUN_ORG_ID is required to open a session");let o=(t.URUN_JWT??"").trim();if(o)return{baseUrl:e,orgId:n,auth:{lane:"jwt",jwt:o}};let r=(t.URUN_API_KEY??"").trim();if(!r)throw new Error("urun pi extension: URUN_JWT or URUN_API_KEY is required to open a session");let l=(t.URUN_GATEWAY_URL??"").trim()||void 0;return{baseUrl:e,orgId:n,auth:{lane:"api-key",apiKey:r,gatewayUrl:l}}}function ge(t){let e=null;return n=>{e===null&&((0,C.mkdirSync)((0,W.dirname)(t),{recursive:!0}),e=(0,C.openSync)(t,"a"));let o=n.detail?` ${JSON.stringify(n.detail)}`:"";(0,C.writeSync)(e,`${new Date().toISOString()} [${n.level}] [urun] ${n.message}${o}
2
- `)}}function fe(t=de.default.homedir()){return(0,W.join)(t,".urun","logs","pi-extension.log")}function ye(t){let e=ge(fe());return async(n,o,r)=>{let{baseUrl:l,orgId:i,auth:p}=me(n),{App:m,createClientToken:a}=await t(),_=(p.lane==="jwt"?m(o,{baseUrl:l,orgId:i,jwt:p.jwt,diagnosticSink:e}):m(o,{baseUrl:l,orgId:i,diagnosticSink:e,getAccessToken:async()=>(await a(p.apiKey,{baseUrl:p.gatewayUrl,expiresIn:300,allowedFunctions:[`${o}/${r}`]})).token}))[r];if(typeof _!="function")throw new Error(`urun pi extension: app "${o}" has no function "${r}"`);let y=_();if(typeof y.end!="function")throw new Error(`urun pi extension: app "${o}" function "${r}" returned a session without end()`);let T=y.connect;return typeof T=="function"&&await T.call(y),y}}var Ke=ye(async()=>{let{createRequire:t}=await import("module"),e=t(x);if(typeof globalThis.RTCPeerConnection>"u")try{e.resolve("werift")}catch{throw new Error('urun pi extension: token streams require a WebRTC data channel, and this Node runtime has no RTCPeerConnection and no "werift" backend installed (@urun-sh/core\'s optional Node WebRTC backend \u2014 it was probably stripped by a --no-optional install). Install werift (`npm i werift`) and retry.')}return e("@urun-sh/core")});function qe(t){try{Promise.resolve(t.end()).catch(()=>{})}catch{}}var K=class{constructor(e,n,o){this.open=e;this.env=n;this.fnName=o}open;env;fnName;pool=new Map;acquire(e){let n=this.pool.get(e);if(!n){let o=Promise.resolve(this.open(this.env,e,this.fnName)).then(r=>({session:r,responses:new F(r)}));n=o,this.pool.set(e,o),o.catch(()=>{this.pool.get(e)===o&&this.pool.delete(e)})}return n}evict(e){let n=this.pool.get(e);n&&(this.pool.delete(e),n.then(o=>qe(o.session),()=>{}))}closeAll(){for(let e of[...this.pool.keys()])this.evict(e)}};function he(t){let e=[];t.systemPrompt&&e.push({role:"system",content:t.systemPrompt});for(let n of t.messages){if(n.role==="toolResult"){e.push({type:"function_call_output",call_id:n.toolCallId,output:Je(n.content)});continue}if(n.role==="assistant"&&Array.isArray(n.content)){let r="",l=()=>{r&&(e.push({role:"assistant",content:r}),r="")};for(let i of n.content)if(i.type==="text")r+=String(i.text??"");else if(i.type==="toolCall")l(),e.push({type:"function_call",call_id:String(i.id??""),name:String(i.name??""),arguments:JSON.stringify(i.arguments??{})});else{if(i.type==="thinking")continue;throw new Error(`urun pi extension: unsupported assistant content part "${String(i.type)}"`)}l();continue}let o=n.role==="assistant"?"assistant":"user";e.push({role:o,content:We(n.content)})}return we(e)}function we(t){let e=[];for(let n of t){let o=e[e.length-1];o&&"role"in o&&"role"in n&&o.role===n.role?o.content=[o.content,n.content].filter(r=>r.length>0).join(`
1
+ "use strict";var $e=Object.create;var F=Object.defineProperty;var Ce=Object.getOwnPropertyDescriptor;var Le=Object.getOwnPropertyNames;var Me=Object.getPrototypeOf,Oe=Object.prototype.hasOwnProperty;var Ne=(t,e)=>{for(var n in e)F(t,n,{get:e[n],enumerable:!0})},se=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of Le(e))!Oe.call(t,r)&&r!==n&&F(t,r,{get:()=>e[r],enumerable:!(o=Ce(e,r))||o.enumerable});return t};var ie=(t,e,n)=>(n=t!=null?$e(Me(t)):{},se(e||!t||!t.__esModule?F(n,"default",{value:t,enumerable:!0}):n,t)),De=t=>se(F({},"__esModule",{value:!0}),t);var dt={};Ne(dt,{SessionPool:()=>H,URUN_API:()=>ee,coalesceSameRole:()=>Ee,createFileDiagnosticSink:()=>be,createUrunExtension:()=>Ie,default:()=>ct,makeSessionFactory:()=>Se,makeStreamSimple:()=>Te,notify:()=>Z,piDiagnosticLogPath:()=>J,resolveSessionEnv:()=>xe,toResponsesInput:()=>Re});module.exports=De(dt);var Fe=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,k=Fe();var ve=require("@earendil-works/pi-ai"),C=require("fs"),ke=require("path");function ae(t,e,n,o){let r=t.response??{},l={request_id:n,consumer_id:o,stream:!0,kind:"chat",messages:e};return typeof r.instructions=="string"&&(l.instructions=r.instructions),Array.isArray(r.modalities)&&(l.modalities=r.modalities),typeof r.temperature=="number"&&(l.temperature=r.temperature),typeof r.max_output_tokens=="number"&&(l.max_output_tokens=r.max_output_tokens),r.tools!==void 0&&(l.tools=r.tools),l}function le(t,e,n){let o={request_id:e,consumer_id:n,stream:!!t.stream,kind:"responses",input:t.input};return t.model&&(o.model=t.model),t.tools!==void 0&&(o.tools=t.tools),t.tool_choice!==void 0&&(o.tool_choice=t.tool_choice),typeof t.temperature=="number"&&(o.temperature=t.temperature),typeof t.max_output_tokens=="number"&&(o.max_output_tokens=t.max_output_tokens),o}function pe(t){if(t instanceof Error)return{type:"error",error:{type:"urun_error",code:t.name||null,message:t.message}};if(t&&typeof t=="object"&&t.t==="error"){let e=t,n=e.body??{};return{type:"error",error:{type:"urun_error",code:e.code??null,message:n.message??"unknown error"}}}return{type:"error",error:{type:"urun_error",code:null,message:String(t)}}}var je="llm-resp";async function*X(t,e){let n=`${je}:${e}`,o=`resp_${e}`;yield{type:"response.created",response:{id:o,status:"in_progress"}};let r=new Map;for await(let l of t.stream(n).messages()){let i=l;if(i.t==="delta"){if(typeof i.delta=="string"&&(yield{type:"response.output_text.delta",item_id:o,delta:i.delta}),typeof i.reasoning=="string"&&(yield{type:"response.reasoning_text.delta",item_id:o,delta:i.reasoning}),Array.isArray(i.tool_calls))for(let p of i.tool_calls){let g=typeof p.index=="number"?p.index:0,a=r.get(g)??{};p.id&&(a.id=p.id),p.function?.name&&(a.name=p.function.name),r.set(g,a),yield{type:"response.function_call_arguments.delta",item_id:`fc_${e}_${g}`,tool_index:g,call_id:a.id,name:a.name,delta:p.function?.arguments??""}}}else if(i.t==="response"){yield{type:"response.completed",response:{id:o,status:"completed",...i.body}};return}else if(i.t==="error"){yield pe(i);return}}}var Ke="llm",j=class{constructor(e){this.session=e;this.sessionTag=e.sessionId??globalThis.crypto.randomUUID()}session;sessionTag;get consumerId(){return this.session.consumerId}write(e){e.session_tag=this.sessionTag,this.session.doc(Ke).set({requests:{[e.request_id]:{payload:e,consumer_id:e.consumer_id,stream:e.stream}}})}sendResponses(e,n){let o=le(e,n,this.consumerId);return this.write(o),X(this.session,n)}sendResponseCreate(e,n,o){let r=ae(e,n,o,this.consumerId);return this.write(r),X(this.session,o)}};var ue=0;function qe(){return ue+=1,`req_${Date.now().toString(36)}_${ue.toString(36)}`}var K=class{transport;constructor(e){this.transport=new j(e)}responses={create:async e=>{let n=qe(),o=this.transport.sendResponses(e,n);return Object.assign((async function*(){yield*o})(),{requestId:n})}}};var q=require("fs"),de=ie(require("os"),1),W=require("path"),fe=require("util");function J(t=de.default.homedir()){return(0,W.join)(t,".urun","logs","pi-extension.log")}var ce=!1;function ge(t,e){let n=J();try{(0,q.mkdirSync)((0,W.dirname)(n),{recursive:!0}),(0,q.appendFileSync)(n,`${new Date().toISOString()} [console.${t}] [urun] ${(0,fe.format)(...e)}
2
+ `)}catch(o){if(!ce){ce=!0;try{process.stderr.write(`[urun] pi-extension quiet console: cannot write ${n} (${String(o)}); further urun-side console output will be dropped
3
+ `)}catch{}}}}var f=t=>(...e)=>ge(t,e),z={log:f("log"),info:f("info"),warn:f("warn"),error:f("error"),debug:f("debug"),trace:f("trace"),dir:f("dir"),table:f("table"),group:f("group"),groupCollapsed:f("groupCollapsed"),groupEnd:f("groupEnd"),count:f("count"),countReset:f("countReset"),time:f("time"),timeLog:f("timeLog"),timeEnd:f("timeEnd"),assert:(t,...e)=>{t||ge("assert",e.length>0?e:["Assertion failed"])}};function Q(t){try{process.stderr.write(t)}catch{}}var V="https://api.urun.sh/v1";async function me(t){let e=t.fetchImpl??fetch,n=`${t.apiUrl.replace(/\/+$/,"")}/apps`,o=await e(n,{headers:{Authorization:`Bearer ${t.apiKey}`,Accept:"application/json"}});if(!o.ok)throw new Error(`org apps listing failed: GET ${n} \u2192 ${o.status}`);let r=await o.json();if(!Array.isArray(r.apps))throw new Error(`org apps listing returned no "apps" array (GET ${n})`);if(r.truncated===!0)throw new Error(`org apps listing was truncated (GET ${n} returned ${r.apps.length} of more) \u2014 model discovery would silently omit deployed apps`);return r.apps}async function he(t){let e=await me(t),n=e.filter(o=>o.function_name===t.fnName&&o.deployment_status==="active").map(o=>o.app_slug);if(n.length===0)throw new Error(`urun pi extension: the org has no active deployed app exposing "${t.fnName}" (GET ${t.apiUrl}/apps returned ${e.length} app(s), none servable) \u2014 deploy one with \`urun serve <model>\` first`);return n.sort()}var ee="urun-serve",We="serve",Je=131072,He=16384,ye=3,Ge=42e4,Be=6e4,we=2,Ye=15e3;function Xe(t){let e=(t.URUN_API_KEY??"").trim();if(!e)throw new Error("urun pi extension: URUN_API_KEY is required \u2014 model discovery lists the org's deployed serve apps via the org API (URUN_JWT alone cannot list apps)");return{apiKey:e,apiUrl:(t.URUN_API_URL??"").trim()||V,fnName:(t.URUN_FUNCTION??"").trim()||We}}function xe(t){let e=(t.URUN_BASE_URL??"").trim(),n=(t.URUN_ORG_ID??"").trim();if(!e)throw new Error("urun pi extension: URUN_BASE_URL is required to open a session");if(/\/v1\/*$/.test(new URL(e).pathname))throw new Error(`urun pi extension: URUN_BASE_URL must be the session-gateway base (e.g. https://api.urun.sh), got ${e} \u2014 a trailing /v1 is the org API form (URUN_API_URL); session allocation 404s against it. Drop the /v1.`);if(!n)throw new Error("urun pi extension: URUN_ORG_ID is required to open a session");let o=(t.URUN_JWT??"").trim();if(o)return{baseUrl:e,orgId:n,auth:{lane:"jwt",jwt:o}};let r=(t.URUN_API_KEY??"").trim();if(!r)throw new Error("urun pi extension: URUN_JWT or URUN_API_KEY is required to open a session");let l=(t.URUN_GATEWAY_URL??"").trim()||void 0;return{baseUrl:e,orgId:n,auth:{lane:"api-key",apiKey:r,gatewayUrl:l}}}function be(t){let e=null;return n=>{e===null&&((0,C.mkdirSync)((0,ke.dirname)(t),{recursive:!0}),e=(0,C.openSync)(t,"a"));let o=n.detail?` ${JSON.stringify(n.detail)}`:"";(0,C.writeSync)(e,`${new Date().toISOString()} [${n.level}] [urun] ${n.message}${o}
4
+ `)}}function Se(t){let e=be(J());return async(n,o,r)=>{let{baseUrl:l,orgId:i,auth:p}=xe(n),{App:g,createClientToken:a}=await t(),h=(p.lane==="jwt"?g(o,{baseUrl:l,orgId:i,jwt:p.jwt,diagnosticSink:e}):g(o,{baseUrl:l,orgId:i,diagnosticSink:e,getAccessToken:async()=>(await a(p.apiKey,{baseUrl:p.gatewayUrl,expiresIn:300,allowedFunctions:[`${o}/${r}`]})).token}))[r];if(typeof h!="function")throw new Error(`urun pi extension: app "${o}" has no function "${r}"`);let w=h();if(typeof w.end!="function")throw new Error(`urun pi extension: app "${o}" function "${r}" returned a session without end()`);let I=w.connect;return typeof I=="function"&&await I.call(w),w}}var ze=Se(async()=>{let{createRequire:t}=await import("module"),e=t(k);if(typeof globalThis.RTCPeerConnection>"u")try{e.resolve("werift")}catch{throw new Error('urun pi extension: token streams require a WebRTC data channel, and this Node runtime has no RTCPeerConnection and no "werift" backend installed (@urun-sh/core\'s optional Node WebRTC backend \u2014 it was probably stripped by a --no-optional install). Install werift (`npm i werift`) and retry.')}return e("@urun-sh/core")});function Qe(t,e){try{return Promise.resolve(t.end()).then(()=>{},n=>e(n))}catch(n){return e(n),Promise.resolve()}}function Ve(t){if(t?.hasUI===!1)return!0;if(t?.hasUI===!0)return!1;let e=process.argv.slice(2);if(e.includes("-p")||e.includes("--print"))return!0;let n=e.indexOf("--mode");return n!==-1&&(e[n+1]==="json"||e[n+1]==="rpc")?!0:!process.stdin.isTTY||!process.stdout.isTTY}function Ae(t,e){return`uRun: releasing the pooled "${t}" session failed \u2014 the backend session may stay allocated until the platform reclaims it: ${e instanceof Error?e.message:String(e)}`}var H=class{constructor(e,n,o,r=(l,i)=>z.warn(Ae(l,i))){this.open=e;this.env=n;this.fnName=o;this.onReleaseError=r}open;env;fnName;onReleaseError;pool=new Map;releasing=new Set;acquire(e){let n=this.pool.get(e);if(!n){let o=Promise.resolve(this.open(this.env,e,this.fnName)).then(r=>({session:r,responses:new K(r)}));n=o,this.pool.set(e,o),o.catch(()=>{this.pool.get(e)===o&&this.pool.delete(e)})}return n}evict(e){let n=this.pool.get(e);if(!n)return Promise.resolve();this.pool.delete(e);let o=n.then(r=>Qe(r.session,l=>this.onReleaseError(e,l)),()=>{});return this.releasing.add(o),o.then(()=>this.releasing.delete(o)),o}closeAll(){let e=[...this.pool.keys()].map(n=>this.evict(n));return Promise.all([...e,...this.releasing]).then(()=>{})}};function Re(t){let e=[];t.systemPrompt&&e.push({role:"system",content:t.systemPrompt});for(let n of t.messages){if(n.role==="toolResult"){e.push({type:"function_call_output",call_id:n.toolCallId,output:et(n.content)});continue}if(n.role==="assistant"&&Array.isArray(n.content)){let r="",l=()=>{r&&(e.push({role:"assistant",content:r}),r="")};for(let i of n.content)if(i.type==="text")r+=String(i.text??"");else if(i.type==="toolCall")l(),e.push({type:"function_call",call_id:String(i.id??""),name:String(i.name??""),arguments:JSON.stringify(i.arguments??{})});else{if(i.type==="thinking")continue;throw new Error(`urun pi extension: unsupported assistant content part "${String(i.type)}"`)}l();continue}let o=n.role==="assistant"?"assistant":"user";e.push({role:o,content:Ze(n.content)})}return Ee(e)}function Ee(t){let e=[];for(let n of t){let o=e[e.length-1];o&&"role"in o&&"role"in n&&o.role===n.role?o.content=[o.content,n.content].filter(r=>r.length>0).join(`
3
5
 
4
- `):e.push({...n})}return e}function We(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>e&&typeof e=="object"&&"text"in e?String(e.text):"").join(""):""}function Je(t){if(typeof t=="string")return t;if(!Array.isArray(t))return"";let e="";for(let n of t){let o=String(n.type??"");if(o!=="text")throw new Error(`urun pi extension: unsupported toolResult content part "${o}" \u2014 the serve lane carries text tool results only`);e+=String(n.text??"")}return e}function Ge(t){if(!(!Array.isArray(t)||t.length===0))return t.map(e=>({type:"function",name:e.name,description:e.description,parameters:e.parameters}))}function pe(t,e){if(!e.trim())return{};try{return JSON.parse(e)}catch{throw new Error(`uRun serve error: tool call "${t}" arguments are not valid JSON: ${e}`)}}function Be(t){let e=t?.output;return Array.isArray(e)?e.filter(n=>n.type==="function_call"):[]}function He(t){let e=t?.output;if(!Array.isArray(e))return"";let n="";for(let o of e)if(!(o.type!=="reasoning"||!Array.isArray(o.content)))for(let r of o.content)r.type==="reasoning_text"&&(n+=String(r.text??""));return n}var Ye=["<tool_call>","<function="];function Xe(t,e){let n=Ye.find(o=>e.includes(o));if(n)return new Error(`serving row emitted a prose tool call (literal ${JSON.stringify(n)} in the assistant text) for a request that carried tools, and no structured tool_calls arrived \u2014 the tool-call parser is not configured on the model row "${t}" (see catalog parser_defaults)`)}var q=class extends Error{};function ze(t){let e=t instanceof Error?t.message:String(t),n=t?.code;return/\b529\b/.test(e)||/overloaded/i.test(e)||n===529||n==="529"}function Qe(t){return new Promise(e=>setTimeout(e,t))}function Ve(t,e,n,o){return new Promise((r,l)=>{let i=!1,p=s=>{i||(i=!0,clearTimeout(m),o?.removeEventListener("abort",a),s())},m=setTimeout(()=>p(()=>l(n())),e),a=()=>p(()=>l(new Error("aborted")));if(o?.aborted){a();return}o?.addEventListener("abort",a,{once:!0}),Promise.resolve(t).then(s=>p(()=>r(s)),s=>p(()=>l(s)))})}async function*Ze(t,e){let n=t[Symbol.asyncIterator](),o,r=new Promise((l,i)=>{o=()=>i(new Error("aborted")),e.addEventListener("abort",o,{once:!0})});try{for(;;){if(e.aborted)throw new Error("aborted");let l=await Promise.race([n.next(),r]);if(l.done)return;yield l.value}}finally{o&&e.removeEventListener("abort",o),n.return?.(void 0)}}function ce(t,e){let n=t?.sendMessage;if(typeof n=="function")try{n.call(t,{customType:"urun-status",content:e,display:!0},{triggerTurn:!1})}catch{}}function _e(t,e={},n){let o=e.connectDeadlineMs??Oe,r=e.stallTimeoutMs??De,l=e.phaseHeartbeatMs??je;return(i,p,m)=>{let a=(0,ue.createAssistantMessageEventStream)(),s={role:"assistant",content:[],api:i.api,provider:i.provider,model:i.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()},_=new AbortController,y=m?.signal,T=!1,N=()=>{T=!0,_.abort()};y&&(y.aborted?N():y.addEventListener("abort",N,{once:!0}));let $=!1,I,X=()=>{I&&clearTimeout(I),I=setTimeout(()=>{$=!0,_.abort()},r)},O=()=>{I&&clearTimeout(I),I=void 0},k=null,b=null,h=null,z="",L=!1,J=()=>{if(!b)return;let d=b;b=null,a.push({type:"thinking_end",contentIndex:s.content.indexOf(d),content:d.thinking,partial:s})},Q=()=>{if(!k)return;let d=k;k=null,a.push({type:"text_end",contentIndex:s.content.indexOf(d),content:d.text,partial:s})},G=()=>{if(!h)return;let{call:d,args:w,contentIndex:A}=h;h=null,d.arguments=pe(d.name,w),a.push({type:"toolcall_end",contentIndex:A,toolCall:d,partial:s})},xe=d=>{let w={type:"toolCall",id:String(d.call_id??d.id??`call_${s.content.length}`),name:String(d.name??""),arguments:{}};s.content.push(w);let A=s.content.length-1;a.push({type:"toolcall_start",contentIndex:A,partial:s});let M=typeof d.arguments=="string"?d.arguments:"";M&&a.push({type:"toolcall_delta",contentIndex:A,delta:M,partial:s}),w.arguments=pe(w.name,M),a.push({type:"toolcall_end",contentIndex:A,toolCall:w,partial:s})};return(async()=>{a.push({type:"start",partial:s});let d=!1,w,A=()=>{w&&clearInterval(w),w=void 0},M=Date.now();w=setInterval(()=>{let v=Math.round((Date.now()-M)/1e3);ce(n,`uRun: still opening the "${i.id}" session\u2026 (${v}s \u2014 serve apps scale to zero, first turn can cold-start ~6min)`)},l);let ke=async v=>{let{responses:S}=await Ve(t.acquire(i.id),o,()=>new Error(`uRun session for "${i.id}" did not connect within ${Math.round(o/1e3)}s \u2014 likely cold-starting (scaled to zero) or queued behind capacity. Retry shortly.`),_.signal);A();let U,R;for(let c=1;c<=ae;c++)try{let f=await S.responses.create({model:i.id,input:v,stream:!0,tools:Ge(p.tools),max_output_tokens:i.maxTokens});X();for await(let E of Ze(f,_.signal)){X();let g=E;if(g.type==="response.output_text.delta"){let u=typeof g.delta=="string"?g.delta:"";u&&(L=!0,J(),G(),k||(k={type:"text",text:""},s.content.push(k),a.push({type:"text_start",contentIndex:s.content.length-1,partial:s})),k.text+=u,z+=u,a.push({type:"text_delta",contentIndex:s.content.indexOf(k),delta:u,partial:s}))}else if(g.type==="response.reasoning_text.delta"){let u=typeof g.delta=="string"?g.delta:"";u&&(L=!0,b||(b={type:"thinking",thinking:""},s.content.push(b),a.push({type:"thinking_start",contentIndex:s.content.length-1,partial:s})),b.thinking+=u,a.push({type:"thinking_delta",contentIndex:s.content.indexOf(b),delta:u,partial:s}))}else if(g.type==="response.function_call_arguments.delta"&&typeof g.tool_index=="number"){let u=g;if(L=!0,J(),Q(),!h||h.toolIndex!==u.tool_index){G();let V={type:"toolCall",id:u.call_id??`call_${u.tool_index}`,name:u.name??"",arguments:{}};s.content.push(V),h={call:V,args:"",contentIndex:s.content.length-1,toolIndex:u.tool_index},a.push({type:"toolcall_start",contentIndex:h.contentIndex,partial:s})}u.call_id&&(h.call.id=u.call_id),u.name&&(h.call.name=u.name);let P=typeof u.delta=="string"?u.delta:"";P&&(h.args+=P,a.push({type:"toolcall_delta",contentIndex:h.contentIndex,delta:P,partial:s}))}else if(g.type==="response.completed"){U=g.response;break}else if(g.type==="error"){let u=g.error,P=new Error(`uRun serve error: ${u?.message??"unknown error"}`);throw P.code=u?.code??null,P}}if(!U)throw new q(`uRun backhaul for "${i.id}" closed before the turn completed \u2014 the serving session ended mid-turn (its pod was restarted, drained or deleted).`);R=void 0;break}catch(f){if(R=f,_.signal.aborted)throw f;if(c<ae&&ze(f)&&!L){await Qe(c*500);continue}throw f}if(R)throw R;return U};try{let v=he(p),S;for(let c=1;c<=le;c++)try{S=await ke(v);break}catch(f){let E=$||f instanceof q;if(c>=le||!E||L||T)throw f;O(),t.evict(i.id),$=!1,_=new AbortController,ce(n,`uRun: the "${i.id}" session ended mid-turn \u2014 re-homing to a fresh assignment and replaying the turn\u2026`)}if(O(),J(),Q(),G(),!s.content.some(c=>c.type==="toolCall"))for(let c of Be(S))xe(c);if(!s.content.some(c=>c.type==="thinking")){let c=He(S);if(c){let f={type:"thinking",thinking:""};s.content.push(f);let E=s.content.length-1;a.push({type:"thinking_start",contentIndex:E,partial:s}),f.thinking=c,a.push({type:"thinking_delta",contentIndex:E,delta:c,partial:s}),a.push({type:"thinking_end",contentIndex:E,content:c,partial:s})}}let U=s.content.filter(c=>c.type==="toolCall").length;if((p.tools?.length??0)>0&&U===0){let c=Xe(i.id,z);if(c)throw c}let R=U>0?"toolUse":S?.status==="incomplete"?"length":"stop";s.stopReason=R,a.push({type:"done",reason:R,message:s}),a.end(s)}catch(v){if(d=!0,O(),T||y?.aborted&&!$)s.stopReason="aborted",s.errorMessage="aborted by user",a.push({type:"error",reason:"aborted",error:s});else{let S=$?`uRun stream stalled \u2014 no output for ${Math.round(r/1e3)}s; the model may be hung. Retry, or Ctrl-C to abort.`:v instanceof Error?v.message:String(v);s.stopReason="error",s.errorMessage=S,a.push({type:"error",reason:"error",error:s})}a.end(s)}finally{O(),A(),y&&y.removeEventListener("abort",N),d&&t.evict(i.id)}})(),a}}function et(t){return{id:t,name:`uRun ${t}`,api:Y,reasoning:!0,input:["text"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:Me,maxTokens:Ne}}function ve(t={}){return async e=>{let n=t.env??process.env,{apiKey:o,apiUrl:r,fnName:l}=Fe(n),i=await ie({apiUrl:r,apiKey:o,fnName:l,fetchImpl:t.fetchImpl}),p=new K(t.openSession??Ke,n,l);e.on("session_shutdown",()=>p.closeAll());let m={name:"uRun",api:Y,baseUrl:"urun://session",apiKey:"$URUN_API_KEY",models:i.map(et),streamSimple:_e(p,t.timing??{},e)};e.registerProvider("urun",m)}}var tt=ve();0&&(module.exports={SessionPool,URUN_API,coalesceSameRole,createFileDiagnosticSink,createUrunExtension,makeSessionFactory,makeStreamSimple,piDiagnosticLogPath,resolveSessionEnv,toResponsesInput});
6
+ `):e.push({...n})}return e}function Ze(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>e&&typeof e=="object"&&"text"in e?String(e.text):"").join(""):""}function et(t){if(typeof t=="string")return t;if(!Array.isArray(t))return"";let e="";for(let n of t){let o=String(n.type??"");if(o!=="text")throw new Error(`urun pi extension: unsupported toolResult content part "${o}" \u2014 the serve lane carries text tool results only`);e+=String(n.text??"")}return e}function tt(t){if(!(!Array.isArray(t)||t.length===0))return t.map(e=>({type:"function",name:e.name,description:e.description,parameters:e.parameters}))}function _e(t,e){if(!e.trim())return{};try{return JSON.parse(e)}catch{throw new Error(`uRun serve error: tool call "${t}" arguments are not valid JSON: ${e}`)}}function nt(t){let e=t?.output;return Array.isArray(e)?e.filter(n=>n.type==="function_call"):[]}function ot(t){let e=t?.output;if(!Array.isArray(e))return"";let n="";for(let o of e)if(!(o.type!=="reasoning"||!Array.isArray(o.content)))for(let r of o.content)r.type==="reasoning_text"&&(n+=String(r.text??""));return n}var rt=["<tool_call>","<function="];function st(t,e){let n=rt.find(o=>e.includes(o));if(n)return new Error(`serving row emitted a prose tool call (literal ${JSON.stringify(n)} in the assistant text) for a request that carried tools, and no structured tool_calls arrived \u2014 the tool-call parser is not configured on the model row "${t}" (see catalog parser_defaults)`)}var G=class extends Error{};function it(t){let e=t instanceof Error?t.message:String(t),n=t?.code;return/\b529\b/.test(e)||/overloaded/i.test(e)||n===529||n==="529"}function at(t){return new Promise(e=>setTimeout(e,t))}function lt(t,e,n,o){return new Promise((r,l)=>{let i=!1,p=s=>{i||(i=!0,clearTimeout(g),o?.removeEventListener("abort",a),s())},g=setTimeout(()=>p(()=>l(n())),e),a=()=>p(()=>l(new Error("aborted")));if(o?.aborted){a();return}o?.addEventListener("abort",a,{once:!0}),Promise.resolve(t).then(s=>p(()=>r(s)),s=>p(()=>l(s)))})}async function*pt(t,e){let n=t[Symbol.asyncIterator](),o,r=new Promise((l,i)=>{o=()=>i(new Error("aborted")),e.addEventListener("abort",o,{once:!0})});try{for(;;){if(e.aborted)throw new Error("aborted");let l=await Promise.race([n.next(),r]);if(l.done)return;yield l.value}}finally{o&&e.removeEventListener("abort",o),n.return?.(void 0)}}function Z(t,e){if(t?.hasUI===!1){Q(`${e}
7
+ `);return}let n=t?.sendMessage;if(typeof n=="function")try{n.call(t,{customType:"urun-status",content:e,display:!0},{triggerTurn:!1})}catch{}}function Te(t,e={},n){let o=e.connectDeadlineMs??Ge,r=e.stallTimeoutMs??Be,l=e.phaseHeartbeatMs??Ye;return(i,p,g)=>{let a=(0,ve.createAssistantMessageEventStream)(),s={role:"assistant",content:[],api:i.api,provider:i.provider,model:i.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()},h=new AbortController,w=g?.signal,I=!1,N=()=>{I=!0,h.abort()};w&&(w.aborted?N():w.addEventListener("abort",N,{once:!0}));let L=!1,P,te=()=>{P&&clearTimeout(P),P=setTimeout(()=>{L=!0,h.abort()},r)},D=()=>{P&&clearTimeout(P),P=void 0},b=null,S=null,_=null,ne="",M=!1,B=()=>{if(!S)return;let d=S;S=null,a.push({type:"thinking_end",contentIndex:s.content.indexOf(d),content:d.thinking,partial:s})},oe=()=>{if(!b)return;let d=b;b=null,a.push({type:"text_end",contentIndex:s.content.indexOf(d),content:d.text,partial:s})},Y=()=>{if(!_)return;let{call:d,args:v,contentIndex:A}=_;_=null,d.arguments=_e(d.name,v),a.push({type:"toolcall_end",contentIndex:A,toolCall:d,partial:s})},Pe=d=>{let v={type:"toolCall",id:String(d.call_id??d.id??`call_${s.content.length}`),name:String(d.name??""),arguments:{}};s.content.push(v);let A=s.content.length-1;a.push({type:"toolcall_start",contentIndex:A,partial:s});let O=typeof d.arguments=="string"?d.arguments:"";O&&a.push({type:"toolcall_delta",contentIndex:A,delta:O,partial:s}),v.arguments=_e(v.name,O),a.push({type:"toolcall_end",contentIndex:A,toolCall:v,partial:s})};return(async()=>{a.push({type:"start",partial:s});let d=!1,v,A=()=>{v&&clearInterval(v),v=void 0},O=Date.now();v=setInterval(()=>{let x=Math.round((Date.now()-O)/1e3);Z(n,`uRun: still opening the "${i.id}" session\u2026 (${x}s \u2014 serve apps scale to zero, first turn can cold-start ~6min)`)},l);let Ue=async x=>{let{responses:R}=await lt(t.acquire(i.id),o,()=>new Error(`uRun session for "${i.id}" did not connect within ${Math.round(o/1e3)}s \u2014 likely cold-starting (scaled to zero) or queued behind capacity. Retry shortly.`),h.signal);A();let U,E;for(let u=1;u<=ye;u++)try{let y=await R.responses.create({model:i.id,input:x,stream:!0,tools:tt(p.tools),max_output_tokens:i.maxTokens});te();for await(let T of pt(y,h.signal)){te();let m=T;if(m.type==="response.output_text.delta"){let c=typeof m.delta=="string"?m.delta:"";c&&(M=!0,B(),Y(),b||(b={type:"text",text:""},s.content.push(b),a.push({type:"text_start",contentIndex:s.content.length-1,partial:s})),b.text+=c,ne+=c,a.push({type:"text_delta",contentIndex:s.content.indexOf(b),delta:c,partial:s}))}else if(m.type==="response.reasoning_text.delta"){let c=typeof m.delta=="string"?m.delta:"";c&&(M=!0,S||(S={type:"thinking",thinking:""},s.content.push(S),a.push({type:"thinking_start",contentIndex:s.content.length-1,partial:s})),S.thinking+=c,a.push({type:"thinking_delta",contentIndex:s.content.indexOf(S),delta:c,partial:s}))}else if(m.type==="response.function_call_arguments.delta"&&typeof m.tool_index=="number"){let c=m;if(M=!0,B(),oe(),!_||_.toolIndex!==c.tool_index){Y();let re={type:"toolCall",id:c.call_id??`call_${c.tool_index}`,name:c.name??"",arguments:{}};s.content.push(re),_={call:re,args:"",contentIndex:s.content.length-1,toolIndex:c.tool_index},a.push({type:"toolcall_start",contentIndex:_.contentIndex,partial:s})}c.call_id&&(_.call.id=c.call_id),c.name&&(_.call.name=c.name);let $=typeof c.delta=="string"?c.delta:"";$&&(_.args+=$,a.push({type:"toolcall_delta",contentIndex:_.contentIndex,delta:$,partial:s}))}else if(m.type==="response.completed"){U=m.response;break}else if(m.type==="error"){let c=m.error,$=new Error(`uRun serve error: ${c?.message??"unknown error"}`);throw $.code=c?.code??null,$}}if(!U)throw new G(`uRun backhaul for "${i.id}" closed before the turn completed \u2014 the serving session ended mid-turn (its pod was restarted, drained or deleted).`);E=void 0;break}catch(y){if(E=y,h.signal.aborted)throw y;if(u<ye&&it(y)&&!M){await at(u*500);continue}throw y}if(E)throw E;return U};try{let x=Re(p),R;for(let u=1;u<=we;u++)try{R=await Ue(x);break}catch(y){let T=L||y instanceof G;if(u>=we||!T||M||I)throw y;D(),t.evict(i.id),L=!1,h=new AbortController,Z(n,`uRun: the "${i.id}" session ended mid-turn \u2014 re-homing to a fresh assignment and replaying the turn\u2026`)}if(D(),B(),oe(),Y(),!s.content.some(u=>u.type==="toolCall"))for(let u of nt(R))Pe(u);if(!s.content.some(u=>u.type==="thinking")){let u=ot(R);if(u){let y={type:"thinking",thinking:""};s.content.push(y);let T=s.content.length-1;a.push({type:"thinking_start",contentIndex:T,partial:s}),y.thinking=u,a.push({type:"thinking_delta",contentIndex:T,delta:u,partial:s}),a.push({type:"thinking_end",contentIndex:T,content:u,partial:s})}}let U=s.content.filter(u=>u.type==="toolCall").length;if((p.tools?.length??0)>0&&U===0){let u=st(i.id,ne);if(u)throw u}let E=U>0?"toolUse":R?.status==="incomplete"?"length":"stop";s.stopReason=E,a.push({type:"done",reason:E,message:s}),a.end(s)}catch(x){if(d=!0,D(),I||w?.aborted&&!L)s.stopReason="aborted",s.errorMessage="aborted by user",a.push({type:"error",reason:"aborted",error:s});else{let R=L?`uRun stream stalled \u2014 no output for ${Math.round(r/1e3)}s; the model may be hung. Retry, or Ctrl-C to abort.`:x instanceof Error?x.message:String(x);s.stopReason="error",s.errorMessage=R,a.push({type:"error",reason:"error",error:s})}a.end(s)}finally{D(),A(),w&&w.removeEventListener("abort",N),d&&t.evict(i.id)}})(),a}}function ut(t){return{id:t,name:`uRun ${t}`,api:ee,reasoning:!0,input:["text"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:Je,maxTokens:He}}function Ie(t={}){return async e=>{let n=t.env??process.env,{apiKey:o,apiUrl:r,fnName:l}=Xe(n),i=await he({apiUrl:r,apiKey:o,fnName:l,fetchImpl:t.fetchImpl}),p=new H(t.openSession??ze,n,l,(a,s)=>{let h=Ae(a,s);Ve(e)?Q(`${h}
8
+ `):z.warn(h)});e.on("session_shutdown",()=>p.closeAll());let g={name:"uRun",api:ee,baseUrl:"urun://session",apiKey:"$URUN_API_KEY",models:i.map(ut),streamSimple:Te(p,t.timing??{},e)};e.registerProvider("urun",g)}}var ct=Ie();0&&(module.exports={SessionPool,URUN_API,coalesceSameRole,createFileDiagnosticSink,createUrunExtension,makeSessionFactory,makeStreamSimple,notify,piDiagnosticLogPath,resolveSessionEnv,toResponsesInput});
@@ -1,6 +1,9 @@
1
1
  import { ExtensionAPI } from '@earendil-works/pi-coding-agent';
2
2
  import { Api, Model, Context, SimpleStreamOptions, AssistantMessageEventStream } from '@earendil-works/pi-ai';
3
- import { a as UrunSessionLike, U as UrunResponses } from '../ResponsesClient-DrccxHTc.cjs';
3
+ import { a as UrunSessionLike, U as UrunResponses } from '../ResponsesClient-BDl1OIRP.cjs';
4
+
5
+ /** Where the pi lane's quiet diagnostics land (the compat log convention). */
6
+ declare function piDiagnosticLogPath(home?: string): string;
4
7
 
5
8
  /**
6
9
  * Pi coding-agent extension: register the `urun` model provider, with one pi
@@ -179,8 +182,7 @@ interface CoreModuleLike {
179
182
  * structured event flowing — loud once, never TUI spam, never silent.
180
183
  */
181
184
  declare function createFileDiagnosticSink(path: string): (diagnostic: CoreDiagnosticLike) => void;
182
- /** Where the pi lane's quiet diagnostics land (the compat log convention). */
183
- declare function piDiagnosticLogPath(home?: string): string;
185
+
184
186
  declare function makeSessionFactory(loadCore: () => Promise<CoreModuleLike> | CoreModuleLike): SessionFactory;
185
187
  /** One pooled backhaul: the session plus its Responses client (cli.ts shape). */
186
188
  interface PoolEntry {
@@ -198,13 +200,42 @@ declare class SessionPool {
198
200
  private readonly open;
199
201
  private readonly env;
200
202
  private readonly fnName;
203
+ /**
204
+ * Loud close-failure surface (#291). Default is TUI-safe: the compat log
205
+ * lane via the quiet console (#308 — a raw stderr write here would
206
+ * corrupt pi's terminal); the pi wiring in createUrunExtension overrides
207
+ * it with the mode-aware reporter (headless `pi -p` users get stderr —
208
+ * no TUI exists there to corrupt). Never silent either way.
209
+ */
210
+ private readonly onReleaseError;
201
211
  private readonly pool;
202
- constructor(open: SessionFactory, env: NodeJS.ProcessEnv, fnName: string);
212
+ /** In-flight releases (evictions already started), awaited by closeAll(). */
213
+ private readonly releasing;
214
+ constructor(open: SessionFactory, env: NodeJS.ProcessEnv, fnName: string,
215
+ /**
216
+ * Loud close-failure surface (#291). Default is TUI-safe: the compat log
217
+ * lane via the quiet console (#308 — a raw stderr write here would
218
+ * corrupt pi's terminal); the pi wiring in createUrunExtension overrides
219
+ * it with the mode-aware reporter (headless `pi -p` users get stderr —
220
+ * no TUI exists there to corrupt). Never silent either way.
221
+ */
222
+ onReleaseError?: (appSlug: string, err: unknown) => void);
203
223
  acquire(appSlug: string): Promise<PoolEntry>;
204
- /** Drop + release one entry (turn ended badly / user aborted). */
205
- evict(appSlug: string): void;
206
- /** Release everything (pi session_shutdown). */
207
- closeAll(): void;
224
+ /**
225
+ * Drop + release one entry (turn ended badly / user aborted). Returns the
226
+ * release's completion; mid-session callers fire-and-forget it (`void`),
227
+ * closeAll() awaits it. The returned promise never rejects — a failed
228
+ * release is reported through {@link onReleaseError}.
229
+ */
230
+ evict(appSlug: string): Promise<void>;
231
+ /**
232
+ * Release everything and settle in-flight releases (pi session_shutdown).
233
+ * pi AWAITS session_shutdown handlers (`emitSessionShutdownEvent`), so
234
+ * returning the completion is what makes a one-shot `pi -p` actually
235
+ * release the backend session BEFORE the process exits — the old
236
+ * fire-and-forget return left the release racing process teardown (#292).
237
+ */
238
+ closeAll(): Promise<void>;
208
239
  }
209
240
  /** A Responses input item: role message or function-call round-trip item. */
210
241
  type ResponsesInputItem = {
@@ -237,6 +268,12 @@ type ResponsesInputItem = {
237
268
  declare function toResponsesInput(context: Context): ResponsesInputItem[];
238
269
  /** Fold consecutive same-role message items into one, joining with a blank line. */
239
270
  declare function coalesceSameRole(items: ResponsesInputItem[]): ResponsesInputItem[];
271
+ /**
272
+ * Push a human aliveness line via pi's display-only side-channel
273
+ * (`pi.sendMessage`, no new turn). Feature-detected + swallowed so a pi build
274
+ * (or test stub) without it never breaks a turn.
275
+ */
276
+ declare function notify(pi: ExtensionAPI | undefined, text: string): void;
240
277
  /** Tunable timeouts (overridable so tests can drive them deterministically). */
241
278
  interface StreamTiming {
242
279
  connectDeadlineMs?: number;
@@ -265,4 +302,4 @@ declare function createUrunExtension(opts?: UrunExtensionOptions): (pi: Extensio
265
302
  /** The pi extension factory (default export — what pi's loader invokes). */
266
303
  declare const _default: (pi: ExtensionAPI) => Promise<void>;
267
304
 
268
- export { type CoreDiagnosticLike, type CoreModuleLike, type OwnedSession, type ResponsesInputItem, type SessionFactory, SessionPool, type StreamTiming, URUN_API, type UrunExtensionOptions, coalesceSameRole, createFileDiagnosticSink, createUrunExtension, _default as default, makeSessionFactory, makeStreamSimple, piDiagnosticLogPath, resolveSessionEnv, toResponsesInput };
305
+ export { type CoreDiagnosticLike, type CoreModuleLike, type OwnedSession, type ResponsesInputItem, type SessionFactory, SessionPool, type StreamTiming, URUN_API, type UrunExtensionOptions, coalesceSameRole, createFileDiagnosticSink, createUrunExtension, _default as default, makeSessionFactory, makeStreamSimple, notify, piDiagnosticLogPath, resolveSessionEnv, toResponsesInput };
@@ -1,6 +1,8 @@
1
1
  import { ExtensionAPI } from '@earendil-works/pi-coding-agent';
2
2
  import { Api, Model, Context, SimpleStreamOptions, AssistantMessageEventStream } from '@earendil-works/pi-ai';
3
- import { a as UrunSessionLike, U as UrunResponses } from '../ResponsesClient-DrccxHTc.js';
3
+ import { a as UrunSessionLike, U as UrunResponses } from '../ResponsesClient-BDl1OIRP.js';
4
+
5
+ declare function piDiagnosticLogPath(home?: string): string;
4
6
 
5
7
  declare const URUN_API: Api;
6
8
 
@@ -51,7 +53,6 @@ interface CoreModuleLike {
51
53
 
52
54
  declare function createFileDiagnosticSink(path: string): (diagnostic: CoreDiagnosticLike) => void;
53
55
 
54
- declare function piDiagnosticLogPath(home?: string): string;
55
56
  declare function makeSessionFactory(loadCore: () => Promise<CoreModuleLike> | CoreModuleLike): SessionFactory;
56
57
 
57
58
  interface PoolEntry {
@@ -63,13 +64,19 @@ declare class SessionPool {
63
64
  private readonly open;
64
65
  private readonly env;
65
66
  private readonly fnName;
67
+
68
+ private readonly onReleaseError;
66
69
  private readonly pool;
67
- constructor(open: SessionFactory, env: NodeJS.ProcessEnv, fnName: string);
70
+
71
+ private readonly releasing;
72
+ constructor(open: SessionFactory, env: NodeJS.ProcessEnv, fnName: string,
73
+
74
+ onReleaseError?: (appSlug: string, err: unknown) => void);
68
75
  acquire(appSlug: string): Promise<PoolEntry>;
69
76
 
70
- evict(appSlug: string): void;
77
+ evict(appSlug: string): Promise<void>;
71
78
 
72
- closeAll(): void;
79
+ closeAll(): Promise<void>;
73
80
  }
74
81
 
75
82
  type ResponsesInputItem = {
@@ -90,6 +97,8 @@ declare function toResponsesInput(context: Context): ResponsesInputItem[];
90
97
 
91
98
  declare function coalesceSameRole(items: ResponsesInputItem[]): ResponsesInputItem[];
92
99
 
100
+ declare function notify(pi: ExtensionAPI | undefined, text: string): void;
101
+
93
102
  interface StreamTiming {
94
103
  connectDeadlineMs?: number;
95
104
  stallTimeoutMs?: number;
@@ -109,4 +118,4 @@ declare function createUrunExtension(opts?: UrunExtensionOptions): (pi: Extensio
109
118
 
110
119
  declare const _default: (pi: ExtensionAPI) => Promise<void>;
111
120
 
112
- export { type CoreDiagnosticLike, type CoreModuleLike, type OwnedSession, type ResponsesInputItem, type SessionFactory, SessionPool, type StreamTiming, URUN_API, type UrunExtensionOptions, coalesceSameRole, createFileDiagnosticSink, createUrunExtension, _default as default, makeSessionFactory, makeStreamSimple, piDiagnosticLogPath, resolveSessionEnv, toResponsesInput };
121
+ export { type CoreDiagnosticLike, type CoreModuleLike, type OwnedSession, type ResponsesInputItem, type SessionFactory, SessionPool, type StreamTiming, URUN_API, type UrunExtensionOptions, coalesceSameRole, createFileDiagnosticSink, createUrunExtension, _default as default, makeSessionFactory, makeStreamSimple, notify, piDiagnosticLogPath, resolveSessionEnv, toResponsesInput };
@@ -1,4 +1,8 @@
1
- import{c as G}from"../chunk-HQVV5UN5.js";import{a as F,c as H}from"../chunk-5CEMLB6H.js";import{createAssistantMessageEventStream as oe}from"@earendil-works/pi-ai";import{mkdirSync as re,openSync as se,writeSync as ie}from"fs";import ae from"os";import{dirname as le,join as ce}from"path";async function Y(t){let e=await H(t),n=e.filter(o=>o.function_name===t.fnName&&o.deployment_status==="active").map(o=>o.app_slug);if(n.length===0)throw new Error(`urun pi extension: the org has no active deployed app exposing "${t.fnName}" (GET ${t.apiUrl}/apps returned ${e.length} app(s), none servable) \u2014 deploy one with \`urun serve <model>\` first`);return n.sort()}var V="urun-serve",ue="serve",pe=131072,de=16384,B=3,fe=42e4,ge=6e4,X=2,me=15e3;function ye(t){let e=(t.URUN_API_KEY??"").trim();if(!e)throw new Error("urun pi extension: URUN_API_KEY is required \u2014 model discovery lists the org's deployed serve apps via the org API (URUN_JWT alone cannot list apps)");return{apiKey:e,apiUrl:(t.URUN_API_URL??"").trim()||F,fnName:(t.URUN_FUNCTION??"").trim()||ue}}function he(t){let e=(t.URUN_BASE_URL??"").trim(),n=(t.URUN_ORG_ID??"").trim();if(!e)throw new Error("urun pi extension: URUN_BASE_URL is required to open a session");if(/\/v1\/*$/.test(new URL(e).pathname))throw new Error(`urun pi extension: URUN_BASE_URL must be the session-gateway base (e.g. https://api.urun.sh), got ${e} \u2014 a trailing /v1 is the org API form (URUN_API_URL); session allocation 404s against it. Drop the /v1.`);if(!n)throw new Error("urun pi extension: URUN_ORG_ID is required to open a session");let o=(t.URUN_JWT??"").trim();if(o)return{baseUrl:e,orgId:n,auth:{lane:"jwt",jwt:o}};let i=(t.URUN_API_KEY??"").trim();if(!i)throw new Error("urun pi extension: URUN_JWT or URUN_API_KEY is required to open a session");let u=(t.URUN_GATEWAY_URL??"").trim()||void 0;return{baseUrl:e,orgId:n,auth:{lane:"api-key",apiKey:i,gatewayUrl:u}}}function we(t){let e=null;return n=>{e===null&&(re(le(t),{recursive:!0}),e=se(t,"a"));let o=n.detail?` ${JSON.stringify(n.detail)}`:"";ie(e,`${new Date().toISOString()} [${n.level}] [urun] ${n.message}${o}
2
- `)}}function _e(t=ae.homedir()){return ce(t,".urun","logs","pi-extension.log")}function xe(t){let e=we(_e());return async(n,o,i)=>{let{baseUrl:u,orgId:s,auth:d}=he(n),{App:x,createClientToken:a}=await t(),w=(d.lane==="jwt"?x(o,{baseUrl:u,orgId:s,jwt:d.jwt,diagnosticSink:e}):x(o,{baseUrl:u,orgId:s,diagnosticSink:e,getAccessToken:async()=>(await a(d.apiKey,{baseUrl:d.gatewayUrl,expiresIn:300,allowedFunctions:[`${o}/${i}`]})).token}))[i];if(typeof w!="function")throw new Error(`urun pi extension: app "${o}" has no function "${i}"`);let m=w();if(typeof m.end!="function")throw new Error(`urun pi extension: app "${o}" function "${i}" returned a session without end()`);let E=m.connect;return typeof E=="function"&&await E.call(m),m}}var ve=xe(async()=>{let{createRequire:t}=await import("module"),e=t(import.meta.url);if(typeof globalThis.RTCPeerConnection>"u")try{e.resolve("werift")}catch{throw new Error('urun pi extension: token streams require a WebRTC data channel, and this Node runtime has no RTCPeerConnection and no "werift" backend installed (@urun-sh/core\'s optional Node WebRTC backend \u2014 it was probably stripped by a --no-optional install). Install werift (`npm i werift`) and retry.')}return e("@urun-sh/core")});function ke(t){try{Promise.resolve(t.end()).catch(()=>{})}catch{}}var K=class{constructor(e,n,o){this.open=e;this.env=n;this.fnName=o}open;env;fnName;pool=new Map;acquire(e){let n=this.pool.get(e);if(!n){let o=Promise.resolve(this.open(this.env,e,this.fnName)).then(i=>({session:i,responses:new G(i)}));n=o,this.pool.set(e,o),o.catch(()=>{this.pool.get(e)===o&&this.pool.delete(e)})}return n}evict(e){let n=this.pool.get(e);n&&(this.pool.delete(e),n.then(o=>ke(o.session),()=>{}))}closeAll(){for(let e of[...this.pool.keys()])this.evict(e)}};function Re(t){let e=[];t.systemPrompt&&e.push({role:"system",content:t.systemPrompt});for(let n of t.messages){if(n.role==="toolResult"){e.push({type:"function_call_output",call_id:n.toolCallId,output:Ae(n.content)});continue}if(n.role==="assistant"&&Array.isArray(n.content)){let i="",u=()=>{i&&(e.push({role:"assistant",content:i}),i="")};for(let s of n.content)if(s.type==="text")i+=String(s.text??"");else if(s.type==="toolCall")u(),e.push({type:"function_call",call_id:String(s.id??""),name:String(s.name??""),arguments:JSON.stringify(s.arguments??{})});else{if(s.type==="thinking")continue;throw new Error(`urun pi extension: unsupported assistant content part "${String(s.type)}"`)}u();continue}let o=n.role==="assistant"?"assistant":"user";e.push({role:o,content:be(n.content)})}return Te(e)}function Te(t){let e=[];for(let n of t){let o=e[e.length-1];o&&"role"in o&&"role"in n&&o.role===n.role?o.content=[o.content,n.content].filter(i=>i.length>0).join(`
1
+ import{c as X}from"../chunk-62IL5R2N.js";import{a as K,d as z}from"../chunk-VXTNG2TP.js";import{createAssistantMessageEventStream as ye}from"@earendil-works/pi-ai";import{mkdirSync as he,openSync as we,writeSync as ve}from"fs";import{dirname as xe}from"path";import{appendFileSync as ue,mkdirSync as de}from"fs";import pe from"os";import{dirname as fe,join as ge}from"path";import{format as me}from"util";function W(t=pe.homedir()){return ge(t,".urun","logs","pi-extension.log")}var Q=!1;function ee(t,e){let n=W();try{de(fe(n),{recursive:!0}),ue(n,`${new Date().toISOString()} [console.${t}] [urun] ${me(...e)}
2
+ `)}catch(o){if(!Q){Q=!0;try{process.stderr.write(`[urun] pi-extension quiet console: cannot write ${n} (${String(o)}); further urun-side console output will be dropped
3
+ `)}catch{}}}}var f=t=>(...e)=>ee(t,e),J={log:f("log"),info:f("info"),warn:f("warn"),error:f("error"),debug:f("debug"),trace:f("trace"),dir:f("dir"),table:f("table"),group:f("group"),groupCollapsed:f("groupCollapsed"),groupEnd:f("groupEnd"),count:f("count"),countReset:f("countReset"),time:f("time"),timeLog:f("timeLog"),timeEnd:f("timeEnd"),assert:(t,...e)=>{t||ee("assert",e.length>0?e:["Assertion failed"])}};function q(t){try{process.stderr.write(t)}catch{}}async function te(t){let e=await z(t),n=e.filter(o=>o.function_name===t.fnName&&o.deployment_status==="active").map(o=>o.app_slug);if(n.length===0)throw new Error(`urun pi extension: the org has no active deployed app exposing "${t.fnName}" (GET ${t.apiUrl}/apps returned ${e.length} app(s), none servable) \u2014 deploy one with \`urun serve <model>\` first`);return n.sort()}var ie="urun-serve",_e="serve",ke=131072,Re=16384,ne=3,Te=42e4,be=6e4,oe=2,Ee=15e3;function Se(t){let e=(t.URUN_API_KEY??"").trim();if(!e)throw new Error("urun pi extension: URUN_API_KEY is required \u2014 model discovery lists the org's deployed serve apps via the org API (URUN_JWT alone cannot list apps)");return{apiKey:e,apiUrl:(t.URUN_API_URL??"").trim()||K,fnName:(t.URUN_FUNCTION??"").trim()||_e}}function Ae(t){let e=(t.URUN_BASE_URL??"").trim(),n=(t.URUN_ORG_ID??"").trim();if(!e)throw new Error("urun pi extension: URUN_BASE_URL is required to open a session");if(/\/v1\/*$/.test(new URL(e).pathname))throw new Error(`urun pi extension: URUN_BASE_URL must be the session-gateway base (e.g. https://api.urun.sh), got ${e} \u2014 a trailing /v1 is the org API form (URUN_API_URL); session allocation 404s against it. Drop the /v1.`);if(!n)throw new Error("urun pi extension: URUN_ORG_ID is required to open a session");let o=(t.URUN_JWT??"").trim();if(o)return{baseUrl:e,orgId:n,auth:{lane:"jwt",jwt:o}};let i=(t.URUN_API_KEY??"").trim();if(!i)throw new Error("urun pi extension: URUN_JWT or URUN_API_KEY is required to open a session");let l=(t.URUN_GATEWAY_URL??"").trim()||void 0;return{baseUrl:e,orgId:n,auth:{lane:"api-key",apiKey:i,gatewayUrl:l}}}function Ue(t){let e=null;return n=>{e===null&&(he(xe(t),{recursive:!0}),e=we(t,"a"));let o=n.detail?` ${JSON.stringify(n.detail)}`:"";ve(e,`${new Date().toISOString()} [${n.level}] [urun] ${n.message}${o}
4
+ `)}}function Ie(t){let e=Ue(W());return async(n,o,i)=>{let{baseUrl:l,orgId:s,auth:p}=Ae(n),{App:_,createClientToken:a}=await t(),m=(p.lane==="jwt"?_(o,{baseUrl:l,orgId:s,jwt:p.jwt,diagnosticSink:e}):_(o,{baseUrl:l,orgId:s,diagnosticSink:e,getAccessToken:async()=>(await a(p.apiKey,{baseUrl:p.gatewayUrl,expiresIn:300,allowedFunctions:[`${o}/${i}`]})).token}))[i];if(typeof m!="function")throw new Error(`urun pi extension: app "${o}" has no function "${i}"`);let h=m();if(typeof h.end!="function")throw new Error(`urun pi extension: app "${o}" function "${i}" returned a session without end()`);let A=h.connect;return typeof A=="function"&&await A.call(h),h}}var Pe=Ie(async()=>{let{createRequire:t}=await import("module"),e=t(import.meta.url);if(typeof globalThis.RTCPeerConnection>"u")try{e.resolve("werift")}catch{throw new Error('urun pi extension: token streams require a WebRTC data channel, and this Node runtime has no RTCPeerConnection and no "werift" backend installed (@urun-sh/core\'s optional Node WebRTC backend \u2014 it was probably stripped by a --no-optional install). Install werift (`npm i werift`) and retry.')}return e("@urun-sh/core")});function Ce(t,e){try{return Promise.resolve(t.end()).then(()=>{},n=>e(n))}catch(n){return e(n),Promise.resolve()}}function Ne(t){if(t?.hasUI===!1)return!0;if(t?.hasUI===!0)return!1;let e=process.argv.slice(2);if(e.includes("-p")||e.includes("--print"))return!0;let n=e.indexOf("--mode");return n!==-1&&(e[n+1]==="json"||e[n+1]==="rpc")?!0:!process.stdin.isTTY||!process.stdout.isTTY}function ae(t,e){return`uRun: releasing the pooled "${t}" session failed \u2014 the backend session may stay allocated until the platform reclaims it: ${e instanceof Error?e.message:String(e)}`}var j=class{constructor(e,n,o,i=(l,s)=>J.warn(ae(l,s))){this.open=e;this.env=n;this.fnName=o;this.onReleaseError=i}open;env;fnName;onReleaseError;pool=new Map;releasing=new Set;acquire(e){let n=this.pool.get(e);if(!n){let o=Promise.resolve(this.open(this.env,e,this.fnName)).then(i=>({session:i,responses:new X(i)}));n=o,this.pool.set(e,o),o.catch(()=>{this.pool.get(e)===o&&this.pool.delete(e)})}return n}evict(e){let n=this.pool.get(e);if(!n)return Promise.resolve();this.pool.delete(e);let o=n.then(i=>Ce(i.session,l=>this.onReleaseError(e,l)),()=>{});return this.releasing.add(o),o.then(()=>this.releasing.delete(o)),o}closeAll(){let e=[...this.pool.keys()].map(n=>this.evict(n));return Promise.all([...e,...this.releasing]).then(()=>{})}};function $e(t){let e=[];t.systemPrompt&&e.push({role:"system",content:t.systemPrompt});for(let n of t.messages){if(n.role==="toolResult"){e.push({type:"function_call_output",call_id:n.toolCallId,output:Me(n.content)});continue}if(n.role==="assistant"&&Array.isArray(n.content)){let i="",l=()=>{i&&(e.push({role:"assistant",content:i}),i="")};for(let s of n.content)if(s.type==="text")i+=String(s.text??"");else if(s.type==="toolCall")l(),e.push({type:"function_call",call_id:String(s.id??""),name:String(s.name??""),arguments:JSON.stringify(s.arguments??{})});else{if(s.type==="thinking")continue;throw new Error(`urun pi extension: unsupported assistant content part "${String(s.type)}"`)}l();continue}let o=n.role==="assistant"?"assistant":"user";e.push({role:o,content:Oe(n.content)})}return Le(e)}function Le(t){let e=[];for(let n of t){let o=e[e.length-1];o&&"role"in o&&"role"in n&&o.role===n.role?o.content=[o.content,n.content].filter(i=>i.length>0).join(`
3
5
 
4
- `):e.push({...n})}return e}function be(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>e&&typeof e=="object"&&"text"in e?String(e.text):"").join(""):""}function Ae(t){if(typeof t=="string")return t;if(!Array.isArray(t))return"";let e="";for(let n of t){let o=String(n.type??"");if(o!=="text")throw new Error(`urun pi extension: unsupported toolResult content part "${o}" \u2014 the serve lane carries text tool results only`);e+=String(n.text??"")}return e}function Ee(t){if(!(!Array.isArray(t)||t.length===0))return t.map(e=>({type:"function",name:e.name,description:e.description,parameters:e.parameters}))}function z(t,e){if(!e.trim())return{};try{return JSON.parse(e)}catch{throw new Error(`uRun serve error: tool call "${t}" arguments are not valid JSON: ${e}`)}}function Ue(t){let e=t?.output;return Array.isArray(e)?e.filter(n=>n.type==="function_call"):[]}function Se(t){let e=t?.output;if(!Array.isArray(e))return"";let n="";for(let o of e)if(!(o.type!=="reasoning"||!Array.isArray(o.content)))for(let i of o.content)i.type==="reasoning_text"&&(n+=String(i.text??""));return n}var Ie=["<tool_call>","<function="];function Pe(t,e){let n=Ie.find(o=>e.includes(o));if(n)return new Error(`serving row emitted a prose tool call (literal ${JSON.stringify(n)} in the assistant text) for a request that carried tools, and no structured tool_calls arrived \u2014 the tool-call parser is not configured on the model row "${t}" (see catalog parser_defaults)`)}var L=class extends Error{};function Ce(t){let e=t instanceof Error?t.message:String(t),n=t?.code;return/\b529\b/.test(e)||/overloaded/i.test(e)||n===529||n==="529"}function Ne(t){return new Promise(e=>setTimeout(e,t))}function Me(t,e,n,o){return new Promise((i,u)=>{let s=!1,d=r=>{s||(s=!0,clearTimeout(x),o?.removeEventListener("abort",a),r())},x=setTimeout(()=>d(()=>u(n())),e),a=()=>d(()=>u(new Error("aborted")));if(o?.aborted){a();return}o?.addEventListener("abort",a,{once:!0}),Promise.resolve(t).then(r=>d(()=>i(r)),r=>d(()=>u(r)))})}async function*Oe(t,e){let n=t[Symbol.asyncIterator](),o,i=new Promise((u,s)=>{o=()=>s(new Error("aborted")),e.addEventListener("abort",o,{once:!0})});try{for(;;){if(e.aborted)throw new Error("aborted");let u=await Promise.race([n.next(),i]);if(u.done)return;yield u.value}}finally{o&&e.removeEventListener("abort",o),n.return?.(void 0)}}function Q(t,e){let n=t?.sendMessage;if(typeof n=="function")try{n.call(t,{customType:"urun-status",content:e,display:!0},{triggerTurn:!1})}catch{}}function Le(t,e={},n){let o=e.connectDeadlineMs??fe,i=e.stallTimeoutMs??ge,u=e.phaseHeartbeatMs??me;return(s,d,x)=>{let a=oe(),r={role:"assistant",content:[],api:s.api,provider:s.provider,model:s.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()},w=new AbortController,m=x?.signal,E=!1,M=()=>{E=!0,w.abort()};m&&(m.aborted?M():m.addEventListener("abort",M,{once:!0}));let P=!1,U,J=()=>{U&&clearTimeout(U),U=setTimeout(()=>{P=!0,w.abort()},i)},O=()=>{U&&clearTimeout(U),U=void 0},v=null,k=null,y=null,W="",C=!1,$=()=>{if(!k)return;let p=k;k=null,a.push({type:"thinking_end",contentIndex:r.content.indexOf(p),content:p.thinking,partial:r})},q=()=>{if(!v)return;let p=v;v=null,a.push({type:"text_end",contentIndex:r.content.indexOf(p),content:p.text,partial:r})},D=()=>{if(!y)return;let{call:p,args:h,contentIndex:R}=y;y=null,p.arguments=z(p.name,h),a.push({type:"toolcall_end",contentIndex:R,toolCall:p,partial:r})},Z=p=>{let h={type:"toolCall",id:String(p.call_id??p.id??`call_${r.content.length}`),name:String(p.name??""),arguments:{}};r.content.push(h);let R=r.content.length-1;a.push({type:"toolcall_start",contentIndex:R,partial:r});let N=typeof p.arguments=="string"?p.arguments:"";N&&a.push({type:"toolcall_delta",contentIndex:R,delta:N,partial:r}),h.arguments=z(h.name,N),a.push({type:"toolcall_end",contentIndex:R,toolCall:h,partial:r})};return(async()=>{a.push({type:"start",partial:r});let p=!1,h,R=()=>{h&&clearInterval(h),h=void 0},N=Date.now();h=setInterval(()=>{let _=Math.round((Date.now()-N)/1e3);Q(n,`uRun: still opening the "${s.id}" session\u2026 (${_}s \u2014 serve apps scale to zero, first turn can cold-start ~6min)`)},u);let ee=async _=>{let{responses:T}=await Me(t.acquire(s.id),o,()=>new Error(`uRun session for "${s.id}" did not connect within ${Math.round(o/1e3)}s \u2014 likely cold-starting (scaled to zero) or queued behind capacity. Retry shortly.`),w.signal);R();let S,b;for(let l=1;l<=B;l++)try{let g=await T.responses.create({model:s.id,input:_,stream:!0,tools:Ee(d.tools),max_output_tokens:s.maxTokens});J();for await(let A of Oe(g,w.signal)){J();let f=A;if(f.type==="response.output_text.delta"){let c=typeof f.delta=="string"?f.delta:"";c&&(C=!0,$(),D(),v||(v={type:"text",text:""},r.content.push(v),a.push({type:"text_start",contentIndex:r.content.length-1,partial:r})),v.text+=c,W+=c,a.push({type:"text_delta",contentIndex:r.content.indexOf(v),delta:c,partial:r}))}else if(f.type==="response.reasoning_text.delta"){let c=typeof f.delta=="string"?f.delta:"";c&&(C=!0,k||(k={type:"thinking",thinking:""},r.content.push(k),a.push({type:"thinking_start",contentIndex:r.content.length-1,partial:r})),k.thinking+=c,a.push({type:"thinking_delta",contentIndex:r.content.indexOf(k),delta:c,partial:r}))}else if(f.type==="response.function_call_arguments.delta"&&typeof f.tool_index=="number"){let c=f;if(C=!0,$(),q(),!y||y.toolIndex!==c.tool_index){D();let j={type:"toolCall",id:c.call_id??`call_${c.tool_index}`,name:c.name??"",arguments:{}};r.content.push(j),y={call:j,args:"",contentIndex:r.content.length-1,toolIndex:c.tool_index},a.push({type:"toolcall_start",contentIndex:y.contentIndex,partial:r})}c.call_id&&(y.call.id=c.call_id),c.name&&(y.call.name=c.name);let I=typeof c.delta=="string"?c.delta:"";I&&(y.args+=I,a.push({type:"toolcall_delta",contentIndex:y.contentIndex,delta:I,partial:r}))}else if(f.type==="response.completed"){S=f.response;break}else if(f.type==="error"){let c=f.error,I=new Error(`uRun serve error: ${c?.message??"unknown error"}`);throw I.code=c?.code??null,I}}if(!S)throw new L(`uRun backhaul for "${s.id}" closed before the turn completed \u2014 the serving session ended mid-turn (its pod was restarted, drained or deleted).`);b=void 0;break}catch(g){if(b=g,w.signal.aborted)throw g;if(l<B&&Ce(g)&&!C){await Ne(l*500);continue}throw g}if(b)throw b;return S};try{let _=Re(d),T;for(let l=1;l<=X;l++)try{T=await ee(_);break}catch(g){let A=P||g instanceof L;if(l>=X||!A||C||E)throw g;O(),t.evict(s.id),P=!1,w=new AbortController,Q(n,`uRun: the "${s.id}" session ended mid-turn \u2014 re-homing to a fresh assignment and replaying the turn\u2026`)}if(O(),$(),q(),D(),!r.content.some(l=>l.type==="toolCall"))for(let l of Ue(T))Z(l);if(!r.content.some(l=>l.type==="thinking")){let l=Se(T);if(l){let g={type:"thinking",thinking:""};r.content.push(g);let A=r.content.length-1;a.push({type:"thinking_start",contentIndex:A,partial:r}),g.thinking=l,a.push({type:"thinking_delta",contentIndex:A,delta:l,partial:r}),a.push({type:"thinking_end",contentIndex:A,content:l,partial:r})}}let S=r.content.filter(l=>l.type==="toolCall").length;if((d.tools?.length??0)>0&&S===0){let l=Pe(s.id,W);if(l)throw l}let b=S>0?"toolUse":T?.status==="incomplete"?"length":"stop";r.stopReason=b,a.push({type:"done",reason:b,message:r}),a.end(r)}catch(_){if(p=!0,O(),E||m?.aborted&&!P)r.stopReason="aborted",r.errorMessage="aborted by user",a.push({type:"error",reason:"aborted",error:r});else{let T=P?`uRun stream stalled \u2014 no output for ${Math.round(i/1e3)}s; the model may be hung. Retry, or Ctrl-C to abort.`:_ instanceof Error?_.message:String(_);r.stopReason="error",r.errorMessage=T,a.push({type:"error",reason:"error",error:r})}a.end(r)}finally{O(),R(),m&&m.removeEventListener("abort",M),p&&t.evict(s.id)}})(),a}}function $e(t){return{id:t,name:`uRun ${t}`,api:V,reasoning:!0,input:["text"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:pe,maxTokens:de}}function De(t={}){return async e=>{let n=t.env??process.env,{apiKey:o,apiUrl:i,fnName:u}=ye(n),s=await Y({apiUrl:i,apiKey:o,fnName:u,fetchImpl:t.fetchImpl}),d=new K(t.openSession??ve,n,u);e.on("session_shutdown",()=>d.closeAll());let x={name:"uRun",api:V,baseUrl:"urun://session",apiKey:"$URUN_API_KEY",models:s.map($e),streamSimple:Le(d,t.timing??{},e)};e.registerProvider("urun",x)}}var Xe=De();export{K as SessionPool,V as URUN_API,Te as coalesceSameRole,we as createFileDiagnosticSink,De as createUrunExtension,Xe as default,xe as makeSessionFactory,Le as makeStreamSimple,_e as piDiagnosticLogPath,he as resolveSessionEnv,Re as toResponsesInput};
6
+ `):e.push({...n})}return e}function Oe(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>e&&typeof e=="object"&&"text"in e?String(e.text):"").join(""):""}function Me(t){if(typeof t=="string")return t;if(!Array.isArray(t))return"";let e="";for(let n of t){let o=String(n.type??"");if(o!=="text")throw new Error(`urun pi extension: unsupported toolResult content part "${o}" \u2014 the serve lane carries text tool results only`);e+=String(n.text??"")}return e}function De(t){if(!(!Array.isArray(t)||t.length===0))return t.map(e=>({type:"function",name:e.name,description:e.description,parameters:e.parameters}))}function re(t,e){if(!e.trim())return{};try{return JSON.parse(e)}catch{throw new Error(`uRun serve error: tool call "${t}" arguments are not valid JSON: ${e}`)}}function Fe(t){let e=t?.output;return Array.isArray(e)?e.filter(n=>n.type==="function_call"):[]}function Ke(t){let e=t?.output;if(!Array.isArray(e))return"";let n="";for(let o of e)if(!(o.type!=="reasoning"||!Array.isArray(o.content)))for(let i of o.content)i.type==="reasoning_text"&&(n+=String(i.text??""));return n}var We=["<tool_call>","<function="];function Je(t,e){let n=We.find(o=>e.includes(o));if(n)return new Error(`serving row emitted a prose tool call (literal ${JSON.stringify(n)} in the assistant text) for a request that carried tools, and no structured tool_calls arrived \u2014 the tool-call parser is not configured on the model row "${t}" (see catalog parser_defaults)`)}var M=class extends Error{};function qe(t){let e=t instanceof Error?t.message:String(t),n=t?.code;return/\b529\b/.test(e)||/overloaded/i.test(e)||n===529||n==="529"}function je(t){return new Promise(e=>setTimeout(e,t))}function He(t,e,n,o){return new Promise((i,l)=>{let s=!1,p=r=>{s||(s=!0,clearTimeout(_),o?.removeEventListener("abort",a),r())},_=setTimeout(()=>p(()=>l(n())),e),a=()=>p(()=>l(new Error("aborted")));if(o?.aborted){a();return}o?.addEventListener("abort",a,{once:!0}),Promise.resolve(t).then(r=>p(()=>i(r)),r=>p(()=>l(r)))})}async function*Ye(t,e){let n=t[Symbol.asyncIterator](),o,i=new Promise((l,s)=>{o=()=>s(new Error("aborted")),e.addEventListener("abort",o,{once:!0})});try{for(;;){if(e.aborted)throw new Error("aborted");let l=await Promise.race([n.next(),i]);if(l.done)return;yield l.value}}finally{o&&e.removeEventListener("abort",o),n.return?.(void 0)}}function se(t,e){if(t?.hasUI===!1){q(`${e}
7
+ `);return}let n=t?.sendMessage;if(typeof n=="function")try{n.call(t,{customType:"urun-status",content:e,display:!0},{triggerTurn:!1})}catch{}}function Ge(t,e={},n){let o=e.connectDeadlineMs??Te,i=e.stallTimeoutMs??be,l=e.phaseHeartbeatMs??Ee;return(s,p,_)=>{let a=ye(),r={role:"assistant",content:[],api:s.api,provider:s.provider,model:s.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()},m=new AbortController,h=_?.signal,A=!1,L=()=>{A=!0,m.abort()};h&&(h.aborted?L():h.addEventListener("abort",L,{once:!0}));let C=!1,U,H=()=>{U&&clearTimeout(U),U=setTimeout(()=>{C=!0,m.abort()},i)},O=()=>{U&&clearTimeout(U),U=void 0},k=null,R=null,w=null,Y="",N=!1,D=()=>{if(!R)return;let d=R;R=null,a.push({type:"thinking_end",contentIndex:r.content.indexOf(d),content:d.thinking,partial:r})},G=()=>{if(!k)return;let d=k;k=null,a.push({type:"text_end",contentIndex:r.content.indexOf(d),content:d.text,partial:r})},F=()=>{if(!w)return;let{call:d,args:v,contentIndex:T}=w;w=null,d.arguments=re(d.name,v),a.push({type:"toolcall_end",contentIndex:T,toolCall:d,partial:r})},le=d=>{let v={type:"toolCall",id:String(d.call_id??d.id??`call_${r.content.length}`),name:String(d.name??""),arguments:{}};r.content.push(v);let T=r.content.length-1;a.push({type:"toolcall_start",contentIndex:T,partial:r});let $=typeof d.arguments=="string"?d.arguments:"";$&&a.push({type:"toolcall_delta",contentIndex:T,delta:$,partial:r}),v.arguments=re(v.name,$),a.push({type:"toolcall_end",contentIndex:T,toolCall:v,partial:r})};return(async()=>{a.push({type:"start",partial:r});let d=!1,v,T=()=>{v&&clearInterval(v),v=void 0},$=Date.now();v=setInterval(()=>{let x=Math.round((Date.now()-$)/1e3);se(n,`uRun: still opening the "${s.id}" session\u2026 (${x}s \u2014 serve apps scale to zero, first turn can cold-start ~6min)`)},l);let ce=async x=>{let{responses:b}=await He(t.acquire(s.id),o,()=>new Error(`uRun session for "${s.id}" did not connect within ${Math.round(o/1e3)}s \u2014 likely cold-starting (scaled to zero) or queued behind capacity. Retry shortly.`),m.signal);T();let I,E;for(let c=1;c<=ne;c++)try{let y=await b.responses.create({model:s.id,input:x,stream:!0,tools:De(p.tools),max_output_tokens:s.maxTokens});H();for await(let S of Ye(y,m.signal)){H();let g=S;if(g.type==="response.output_text.delta"){let u=typeof g.delta=="string"?g.delta:"";u&&(N=!0,D(),F(),k||(k={type:"text",text:""},r.content.push(k),a.push({type:"text_start",contentIndex:r.content.length-1,partial:r})),k.text+=u,Y+=u,a.push({type:"text_delta",contentIndex:r.content.indexOf(k),delta:u,partial:r}))}else if(g.type==="response.reasoning_text.delta"){let u=typeof g.delta=="string"?g.delta:"";u&&(N=!0,R||(R={type:"thinking",thinking:""},r.content.push(R),a.push({type:"thinking_start",contentIndex:r.content.length-1,partial:r})),R.thinking+=u,a.push({type:"thinking_delta",contentIndex:r.content.indexOf(R),delta:u,partial:r}))}else if(g.type==="response.function_call_arguments.delta"&&typeof g.tool_index=="number"){let u=g;if(N=!0,D(),G(),!w||w.toolIndex!==u.tool_index){F();let B={type:"toolCall",id:u.call_id??`call_${u.tool_index}`,name:u.name??"",arguments:{}};r.content.push(B),w={call:B,args:"",contentIndex:r.content.length-1,toolIndex:u.tool_index},a.push({type:"toolcall_start",contentIndex:w.contentIndex,partial:r})}u.call_id&&(w.call.id=u.call_id),u.name&&(w.call.name=u.name);let P=typeof u.delta=="string"?u.delta:"";P&&(w.args+=P,a.push({type:"toolcall_delta",contentIndex:w.contentIndex,delta:P,partial:r}))}else if(g.type==="response.completed"){I=g.response;break}else if(g.type==="error"){let u=g.error,P=new Error(`uRun serve error: ${u?.message??"unknown error"}`);throw P.code=u?.code??null,P}}if(!I)throw new M(`uRun backhaul for "${s.id}" closed before the turn completed \u2014 the serving session ended mid-turn (its pod was restarted, drained or deleted).`);E=void 0;break}catch(y){if(E=y,m.signal.aborted)throw y;if(c<ne&&qe(y)&&!N){await je(c*500);continue}throw y}if(E)throw E;return I};try{let x=$e(p),b;for(let c=1;c<=oe;c++)try{b=await ce(x);break}catch(y){let S=C||y instanceof M;if(c>=oe||!S||N||A)throw y;O(),t.evict(s.id),C=!1,m=new AbortController,se(n,`uRun: the "${s.id}" session ended mid-turn \u2014 re-homing to a fresh assignment and replaying the turn\u2026`)}if(O(),D(),G(),F(),!r.content.some(c=>c.type==="toolCall"))for(let c of Fe(b))le(c);if(!r.content.some(c=>c.type==="thinking")){let c=Ke(b);if(c){let y={type:"thinking",thinking:""};r.content.push(y);let S=r.content.length-1;a.push({type:"thinking_start",contentIndex:S,partial:r}),y.thinking=c,a.push({type:"thinking_delta",contentIndex:S,delta:c,partial:r}),a.push({type:"thinking_end",contentIndex:S,content:c,partial:r})}}let I=r.content.filter(c=>c.type==="toolCall").length;if((p.tools?.length??0)>0&&I===0){let c=Je(s.id,Y);if(c)throw c}let E=I>0?"toolUse":b?.status==="incomplete"?"length":"stop";r.stopReason=E,a.push({type:"done",reason:E,message:r}),a.end(r)}catch(x){if(d=!0,O(),A||h?.aborted&&!C)r.stopReason="aborted",r.errorMessage="aborted by user",a.push({type:"error",reason:"aborted",error:r});else{let b=C?`uRun stream stalled \u2014 no output for ${Math.round(i/1e3)}s; the model may be hung. Retry, or Ctrl-C to abort.`:x instanceof Error?x.message:String(x);r.stopReason="error",r.errorMessage=b,a.push({type:"error",reason:"error",error:r})}a.end(r)}finally{O(),T(),h&&h.removeEventListener("abort",L),d&&t.evict(s.id)}})(),a}}function Be(t){return{id:t,name:`uRun ${t}`,api:ie,reasoning:!0,input:["text"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:ke,maxTokens:Re}}function Xe(t={}){return async e=>{let n=t.env??process.env,{apiKey:o,apiUrl:i,fnName:l}=Se(n),s=await te({apiUrl:i,apiKey:o,fnName:l,fetchImpl:t.fetchImpl}),p=new j(t.openSession??Pe,n,l,(a,r)=>{let m=ae(a,r);Ne(e)?q(`${m}
8
+ `):J.warn(m)});e.on("session_shutdown",()=>p.closeAll());let _={name:"uRun",api:ie,baseUrl:"urun://session",apiKey:"$URUN_API_KEY",models:s.map(Be),streamSimple:Ge(p,t.timing??{},e)};e.registerProvider("urun",_)}}var pt=Xe();export{j as SessionPool,ie as URUN_API,Le as coalesceSameRole,Ue as createFileDiagnosticSink,Xe as createUrunExtension,pt as default,Ie as makeSessionFactory,Ge as makeStreamSimple,se as notify,W as piDiagnosticLogPath,Ae as resolveSessionEnv,$e as toResponsesInput};