@urun-sh/openai 0.2.54 → 0.2.55
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.
- package/dist/{ResponsesClient-DF39QXq1.d.cts → ResponsesClient-DrccxHTc.d.cts} +21 -1
- package/dist/{ResponsesClient-DF39QXq1.d.ts → ResponsesClient-DrccxHTc.d.ts} +4 -1
- package/dist/{chunk-EEKOQKWE.js → chunk-47ZLHRBM.js} +1 -1
- package/dist/{chunk-PS4BLX7J.js → chunk-5CEMLB6H.js} +1 -1
- package/dist/{chunk-DYBS3NLC.js → chunk-HQVV5UN5.js} +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +1 -1
- package/dist/pi-extension/index.cjs +3 -3
- package/dist/pi-extension/index.d.cts +21 -10
- package/dist/pi-extension/index.d.ts +8 -4
- package/dist/pi-extension/index.js +3 -3
- package/dist/pi-extension/standalone.cjs +48 -48
- package/dist/proxy/cli.cjs +27 -25
- package/dist/proxy/cli.js +17 -15
- package/dist/proxy/index.cjs +7 -7
- package/dist/proxy/index.js +1 -1
- package/package.json +1 -1
|
@@ -21,9 +21,29 @@ interface UrunStreamLike {
|
|
|
21
21
|
interface UrunSessionLike {
|
|
22
22
|
/** Per-leg consumer identity (core: transport.consumerId). */
|
|
23
23
|
readonly consumerId: string;
|
|
24
|
+
/**
|
|
25
|
+
* The uRun session's stable id, when the SDK session exposes one. Used as
|
|
26
|
+
* the serve-side session-affinity tag (urun-python #1556) so consecutive
|
|
27
|
+
* turns continue the engine's retained sequence state. Optional: a session
|
|
28
|
+
* object without it gets a per-transport tag minted once instead (the
|
|
29
|
+
* transport's lifetime IS the session's lifetime).
|
|
30
|
+
*/
|
|
31
|
+
readonly sessionId?: string;
|
|
24
32
|
doc(key: string): UrunDocLike;
|
|
25
33
|
stream(name: string): UrunStreamLike;
|
|
26
|
-
|
|
34
|
+
/**
|
|
35
|
+
* Core's OWN terminal release (`Session.end()`): ends the owner session and
|
|
36
|
+
* awaits the control-plane release. Optional here because the transport
|
|
37
|
+
* legs (decode/encode/Responses) never terminate a session — the OWNERS do,
|
|
38
|
+
* and each requires it loudly (proxy `sessionOf`, pi `makeSessionFactory`).
|
|
39
|
+
*
|
|
40
|
+
* NOTE (was a silent no-op until #298): this used to be declared as
|
|
41
|
+
* `close?()`, which `@urun-sh/core`'s Session does not have at all — every
|
|
42
|
+
* `session.close?.()` optional-chained to nothing, so "releasing" a session
|
|
43
|
+
* only dropped the local handle while the backend session and its capacity
|
|
44
|
+
* lease stayed alive. Core's surface is `end()` / `disconnect()`.
|
|
45
|
+
*/
|
|
46
|
+
end?(): Promise<unknown>;
|
|
27
47
|
}
|
|
28
48
|
/**
|
|
29
49
|
* One OpenAI chat-completions-chunk-style tool_call delta fragment as the
|
|
@@ -15,9 +15,12 @@ interface UrunStreamLike {
|
|
|
15
15
|
interface UrunSessionLike {
|
|
16
16
|
|
|
17
17
|
readonly consumerId: string;
|
|
18
|
+
|
|
19
|
+
readonly sessionId?: string;
|
|
18
20
|
doc(key: string): UrunDocLike;
|
|
19
21
|
stream(name: string): UrunStreamLike;
|
|
20
|
-
|
|
22
|
+
|
|
23
|
+
end?(): Promise<unknown>;
|
|
21
24
|
}
|
|
22
25
|
|
|
23
26
|
interface LaneToolCallDelta {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{b as V}from"./chunk-
|
|
1
|
+
import{b as V}from"./chunk-5CEMLB6H.js";import{createServer as yt}from"http";var ut=class e{startedAt=Date.now();requests={};models={};ttftMs=[];tokRates=[];tokensOut=0;charsOut=0;localInBytes=0;naiveInBytes=0;request(n,t,o){this.requests[n]=(this.requests[n]??0)+1,this.localInBytes+=t,this.naiveInBytes+=o}modelEntry(n){let t=this.models[n];if(t)return t;let o=Object.keys(this.models).length>=ht?"(other)":n;return this.models[o]??={requests:0,tokens_out:0}}model(n){this.modelEntry(n).requests+=1}track(n,t){let o=this,a=performance.now(),c=null,u=0;return(async function*(){for await(let d of n)d.type==="response.output_text.delta"&&typeof d.delta=="string"&&(c===null&&(c=performance.now(),o.ttftMs.push(c-a),o.ttftMs.length>512&&o.ttftMs.shift()),u+=1,o.tokensOut+=1,o.charsOut+=d.delta.length,t!==void 0&&(o.modelEntry(t).tokens_out+=1)),yield d;let i=(performance.now()-(c??a))/1e3;u>0&&i>0&&(o.tokRates.push(u/i),o.tokRates.length>512&&o.tokRates.shift())})()}static p50(n){if(!n.length)return null;let t=[...n].sort((o,a)=>o-a);return t[Math.floor(t.length/2)]}snapshot(){let n=Object.values(this.requests).reduce((t,o)=>t+o,0);return{uptime_s:Math.round((Date.now()-this.startedAt)/1e3),requests:this.requests,models:this.models,tokens_out:this.tokensOut,chars_out:this.charsOut,ttft_ms:{p50:e.p50(this.ttftMs),last:this.ttftMs.at(-1)??null},tok_per_s:{p50:e.p50(this.tokRates),last:this.tokRates.at(-1)??null},traffic:{local_request_bytes:this.localInBytes,naive_baseline:{request_bytes:this.naiveInBytes,connections:n},persistent_connections:1,history_bytes_saved:Math.max(0,this.naiveInBytes-this.localInBytes),history_bytes_saved_pct:this.naiveInBytes>0?Math.round((1-this.localInBytes/this.naiveInBytes)*1e3)/10:null}}}};function ct(e){e.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"})}function J(e,n,t){e.writeHead(n,{"content-type":"application/json"}),e.end(JSON.stringify(t))}function w(e,n,t,o="invalid_request_error"){J(e,n,{error:{message:t,type:o}})}function pt(e,n,t){if(n==="anthropic"){J(e,404,{type:"error",error:{type:"not_found_error",message:t.message}});return}J(e,404,{error:{message:t.message,type:"invalid_request_error",code:"model_not_found"}})}var ht=256,kt=128;function dt(e){return typeof e.model!="string"||!e.model.trim()?"(default)":e.model.trim().slice(0,kt)}var mt=64*1024*1024,nt=class extends Error{};async function wt(e){let n=[],t=0;for await(let a of e){if(t+=a.length,t>mt)throw new nt(`request body exceeds ${mt} bytes`);n.push(a)}let o=Buffer.concat(n).toString("utf8");return o?JSON.parse(o):{}}function F(e,n,t,o){return{id:e,object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:n,choices:[{index:0,delta:t,finish_reason:o}]}}var xt=256;function Rt(e){if(typeof e=="string")return[{role:"user",content:e}];if(Array.isArray(e))return e;throw new Error("responses input must be a string or an array of messages/items")}var lt=class{conversations=new Map;thread(n,t){let o=Rt(t);if(n==null)return o;let a=this.conversations.get(String(n));if(!a)throw new Error(`unknown previous_response_id ${String(n)} (proxy restarts drop stored responses)`);return[...a,...o]}remember(n,t,o){this.conversations.set(n,[...t,{role:"assistant",content:o}]);for(let a of this.conversations.keys()){if(this.conversations.size<=xt)break;this.conversations.delete(a)}}};function Q(e){let n=e?.output;return Array.isArray(n)?n.filter(t=>t.type==="function_call"):[]}function W(e){return e.find(n=>n.type==="response.completed")?.response??null}function _t(e){let n=e?.output;if(!Array.isArray(n))return"";let t="";for(let o of n)if(!(o.type!=="reasoning"||!Array.isArray(o.content)))for(let a of o.content)a.type==="reasoning_text"&&(t+=String(a.text??""));return t}function Z(e){return e.type!=="response.function_call_arguments.delta"||typeof e.tool_index!="number"?null:{tool_index:e.tool_index,call_id:typeof e.call_id=="string"?e.call_id:void 0,name:typeof e.name=="string"?e.name:void 0,delta:typeof e.delta=="string"?e.delta:""}}var z=class{calls=new Map;add(n){let t=this.calls.get(n.tool_index),o=!t;return t||(t={args:""},this.calls.set(n.tool_index,t)),n.call_id&&(t.id=n.call_id),n.name&&(t.name=n.name),t.args+=n.delta,{call:t,isNew:o}}get size(){return this.calls.size}items(){return[...this.calls.entries()].map(([n,t])=>({type:"function_call",call_id:t.id??`call_${n}`,name:t.name??"",arguments:t.args}))}},vt=["<tool_call>","<function="];function At(e){return vt.find(n=>e.includes(n))}function D(e,n){return`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 "${e}" (see catalog parser_defaults)`}function K(e,n,t){if(!(!e||n>0))return At(t)}function St(e){if(Array.isArray(e))return e.map(n=>{let t=n.function;return!t||typeof t!="object"?n:{type:"function",name:t.name,description:t.description,parameters:t.parameters,strict:t.strict}})}var ot=class extends Error{};function It(e,n){return Array.isArray(n)?n.map(t=>{let o=t;if(o.type==="text")return{type:e==="assistant"?"output_text":"input_text",text:o.text};if(o.type==="image_url"){let a=o.image_url??{};return{type:"input_image",image_url:a.url,detail:a.detail}}throw new ot(`unsupported chat content part type "${String(o.type)}" \u2014 the proxy translates text and image_url parts`)}):n}function Ot(e){let n=[];for(let t of e){if(t.role==="tool"){n.push({type:"function_call_output",call_id:t.tool_call_id,output:typeof t.content=="string"?t.content:JSON.stringify(t.content??"")});continue}if(t.role==="assistant"&&Array.isArray(t.tool_calls)){typeof t.content=="string"&&t.content&&n.push({role:"assistant",content:t.content});for(let o of t.tool_calls){let a=o.function??{};n.push({type:"function_call",call_id:o.id,name:a.name,arguments:a.arguments})}continue}n.push({...t,content:It(t.role,t.content)})}return n}function it(e){return Q(e).map((n,t)=>({index:t,id:n.call_id??n.id??`call_${t}`,type:"function",function:{name:n.name??"",arguments:n.arguments??"{}"}}))}function gt(e,n){let t=n?.output_text;return typeof t=="string"?t:e.filter(o=>o.type==="response.output_text.delta"&&typeof o.delta=="string").map(o=>o.delta).join("")}async function Et(e,n,t,o,a){let c=e.stream===!0,u;try{u=t.thread(e.previous_response_id,e.input)}catch(s){w(o,400,String(s instanceof Error?s.message:s));return}e.previous_response_id!=null&&(a.naiveInBytes+=Buffer.byteLength(JSON.stringify(u))-Buffer.byteLength(JSON.stringify(e.input)));let i=`resp_${Math.random().toString(36).slice(2,14)}`,d=e.store!==!1,_=dt(e);a.model(_);let v=Array.isArray(e.tools)&&e.tools.length>0,A;try{A=await n.createResponse({model:e.model,input:u,stream:c,tools:e.tools,tool_choice:e.tool_choice,temperature:e.temperature,max_output_tokens:e.max_output_tokens})}catch(s){if(s instanceof V){pt(o,"openai",s);return}throw s}let f=[];if(c){ct(o);let s=p=>{o.write(`event: ${String(p.type??"message")}
|
|
2
2
|
data: ${JSON.stringify(p)}
|
|
3
3
|
|
|
4
4
|
`)},C=p=>p.response&&typeof p.response=="object"?{...p,response:{...p.response,id:i}}:p,R=`item_${i.slice(5)}`,b=`rs_${i.slice(5)}`,E=!1,$=!1,r=0,g=()=>{E||(E=!0,s({type:"response.created",response:{id:i,object:"response",status:"in_progress"}}))},T=!1,S=0,M="",N=()=>{T&&(T=!1,s({type:"response.reasoning_text.done",item_id:b,output_index:S,content_index:0,text:M}),s({type:"response.output_item.done",output_index:S,item:{id:b,type:"reasoning",summary:[],content:[{type:"reasoning_text",text:M}],status:"completed"}}))},m=!1,x=0,O="",j=p=>{m&&(m=!1,s({type:"response.output_text.done",item_id:R,output_index:x,content_index:0,text:O}),s({type:"response.content_part.done",item_id:R,output_index:x,content_index:0,part:{type:"output_text",text:O}}),s({type:"response.output_item.done",output_index:x,item:{id:R,type:"message",role:"assistant",status:p,content:[{type:"output_text",text:O}]}}))},B=new z,y=null,L=-1,H=p=>{if(!y)return;let h=y;y=null,s({type:"response.function_call_arguments.done",item_id:h.fcId,output_index:h.outputIndex,arguments:h.args}),s({type:"response.output_item.done",output_index:h.outputIndex,item:{id:h.fcId,type:"function_call",call_id:h.callId??h.fcId,name:h.name??"",arguments:h.args,status:p}})},U=!1;for await(let p of a.track(A,_)){f.push(p);let h=String(p.type??"");if(h==="response.created"||h==="response.in_progress"){E=!0,s(C(p));continue}if(h==="response.output_item.added"){$=!0,s(C(p));continue}if(h==="response.reasoning_text.delta"&&!$){g(),T||(T=!0,S=r++,s({type:"response.output_item.added",output_index:S,item:{id:b,type:"reasoning",summary:[],content:[],status:"in_progress"}})),M+=String(p.delta??""),s({type:"response.reasoning_text.delta",item_id:b,output_index:S,content_index:0,delta:p.delta});continue}if(h==="response.output_text.delta"&&!$){g(),N(),m||(m=!0,x=r++,s({type:"response.output_item.added",output_index:x,item:{id:R,type:"message",role:"assistant",status:"in_progress",content:[]}}),s({type:"response.content_part.added",item_id:R,output_index:x,content_index:0,part:{type:"output_text",text:""}})),O+=String(p.delta??""),s({type:h,item_id:R,output_index:x,content_index:0,delta:p.delta});continue}let l=$?null:Z(p);if(l){if(g(),N(),j("completed"),B.add(l),l.tool_index!==L){H("completed"),L=l.tool_index;let k=r++;y={fcId:`fc_${i.slice(5)}_${l.tool_index}`,outputIndex:k,callId:l.call_id,name:l.name,args:""},s({type:"response.output_item.added",output_index:k,item:{id:y.fcId,type:"function_call",call_id:y.callId??y.fcId,name:y.name??"",arguments:"",status:"in_progress"}})}y&&(l.call_id&&(y.callId=l.call_id),l.name&&(y.name=l.name),y.args+=l.delta,s({type:"response.function_call_arguments.delta",item_id:y.fcId,output_index:y.outputIndex,delta:l.delta}));continue}if(h==="response.completed"&&!$){let k=Q(p.response),X=K(v,B.size+k.length,O);if(X){U=!0,s({type:"error",error:{type:"urun_error",code:"tool_call_parser_missing",message:D(_,X)}});break}N(),j("completed"),H("completed"),B.size===0&&k.forEach(Y=>{let G=r++,et=Y.id??Y.call_id??`fc_${G}`,st=Y.arguments??"",ft={id:et,type:"function_call",call_id:Y.call_id??et,name:Y.name??""};s({type:"response.output_item.added",output_index:G,item:{...ft,arguments:"",status:"in_progress"}}),s({type:"response.function_call_arguments.delta",item_id:et,output_index:G,delta:st}),s({type:"response.function_call_arguments.done",item_id:et,output_index:G,arguments:st}),s({type:"response.output_item.done",output_index:G,item:{...ft,arguments:st,status:"completed"}})}),s(C(p));continue}s(C(p))}N(),j("incomplete"),H("incomplete"),d&&!U&&t.remember(i,u,gt(f,W(f))),o.write(`data: [DONE]
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var f="https://api.urun.sh/v1";function l(a){return a.toLowerCase().replace(/[^\p{L}\p{N}-]/gu,"-").replace(/^-+|-+$/g,"")}var r=class extends Error{};async function m(a){let e=a.fetchImpl??fetch,t=`${a.apiUrl.replace(/\/+$/,"")}/apps`,s=await e(t,{headers:{Authorization:`Bearer ${a.apiKey}`,Accept:"application/json"}});if(!s.ok)throw new Error(`org apps listing failed: GET ${t} \u2192 ${s.status}`);let i=await s.json();if(!Array.isArray(i.apps))throw new Error(`org apps listing returned no "apps" array (GET ${t})`);if(i.truncated===!0)throw new Error(`org apps listing was truncated (GET ${t} returned ${i.apps.length} of more) \u2014 model discovery would silently omit deployed apps`);return i.apps}var u=6e4,c=class{constructor(e){this.opts=e}opts;pool=new Map;appsCache=null;seed(e,t){this.pool.set(e,Promise.resolve(t))}async deployedApps(){if(!this.opts.listApps)return[];let e=this.opts.appsTtlMs??u;if(this.appsCache&&Date.now()-this.appsCache.at<e)return this.appsCache.apps;let t=await this.opts.listApps();return this.appsCache={at:Date.now(),apps:t},t}servable(e){return e.filter(t=>t.function_name===this.opts.fnName&&t.deployment_status==="active").map(t=>t.app_slug)}async availableIds(){let e=new Set([this.opts.defaultApp]);if(this.opts.listApps)for(let t of this.servable(await this.deployedApps()))e.add(t);for(let t of this.pool.keys())e.add(t);return[this.opts.defaultApp,...[...e].filter(t=>t!==this.opts.defaultApp).sort()]}async resolveApp(e){let t=(e??"").trim();if(!t||t==="urun")return this.opts.defaultApp;let s=l(t);if(s===this.opts.defaultApp)return this.opts.defaultApp;if(this.pool.has(s))return s;if(this.opts.listApps){let i=await this.deployedApps(),p=this.servable(i);if(p.includes(s))return s;let o=p.filter(n=>n.startsWith(`${s}-`));if(o.length===1)return o[0];if(o.length>1)throw new r(`model "${t}" is ambiguous across deployed apps ${o.join(", ")} \u2014 name the exact app slug (or catalog id:variant)`);let d=i.find(n=>n.app_slug===s||n.app_slug.startsWith(`${s}-`));if(d)throw new r(`model "${t}" maps to app "${d.app_slug}", which is not an active "${this.opts.fnName}" app \u2014 deploy it with \`urun serve ${t}\`; available models: ${(await this.availableIds()).join(", ")}`)}if(this.opts.listCatalog){let p=(await this.opts.listCatalog()).find(o=>t===o.model_id||t===`${o.model_id}:${o.variant}`||s===l(o.model_id)||s===l(`${o.model_id}-${o.variant}`));if(p)throw new r(`model "${t}" is in the uRun catalog but not deployed \u2014 deploy it with \`urun serve ${p.model_id}\`; available models: ${(await this.availableIds()).join(", ")}`)}return this.opts.defaultApp}async sessionFor(e){let t=await this.resolveApp(e),s=this.pool.get(t);return s||(s=Promise.resolve(this.opts.openSession(t)),this.pool.set(t,s),s.catch(()=>this.pool.delete(t))),{app:t,entry:await s}}async evict(e,t){let s=this.pool.get(e);!s||await s.then(p=>p,()=>null)!==t||this.pool.get(e)!==s||(this.pool.delete(e),await this.opts.closeSession(t).catch(()=>{}))}async modelList(){return{object:"list",data:(await this.availableIds()).map(t=>({id:t,object:"model",created:0,owned_by:"urun"}))}}async closeAll(){let e=[...this.pool.values()];this.pool.clear();let t=[];if(await Promise.all(e.map(async s=>{try{await this.opts.closeSession(await s)}catch(i){t.push(String(i instanceof Error?i.message:i))}})),t.length>0)throw new Error(`failed to close ${t.length} pooled session(s): ${t.join("; ")}`)}};export{f as a,r as b,m as c,c as d};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
function g(e){if(e instanceof Error)return{type:"error",error:{type:"urun_error",code:e.name||null,message:e.message}};if(e&&typeof e=="object"&&e.t==="error"){let n=e,o=n.body??{};return{type:"error",error:{type:"urun_error",code:n.code??null,message:o.message??"unknown error"}}}return{type:"error",error:{type:"urun_error",code:null,message:String(e)}}}function y(e,n,o,t){let r=e.response??{},i={request_id:o,consumer_id:t,stream:!0,kind:"chat",messages:n};return typeof r.instructions=="string"&&(i.instructions=r.instructions),Array.isArray(r.modalities)&&(i.modalities=r.modalities),typeof r.temperature=="number"&&(i.temperature=r.temperature),typeof r.max_output_tokens=="number"&&(i.max_output_tokens=r.max_output_tokens),r.tools!==void 0&&(i.tools=r.tools),i}function _(e,n,o){let t={request_id:n,consumer_id:o,stream:!!e.stream,kind:"responses",input:e.input};return e.model&&(t.model=e.model),e.tools!==void 0&&(t.tools=e.tools),e.tool_choice!==void 0&&(t.tool_choice=e.tool_choice),typeof e.temperature=="number"&&(t.temperature=e.temperature),typeof e.max_output_tokens=="number"&&(t.max_output_tokens=e.max_output_tokens),t}var w="llm-resp";async function*d(e,n){let o=`${w}:${n}`,t=`resp_${n}`;yield{type:"response.created",response:{id:t,status:"in_progress"}};let r=new Map;for await(let i of e.stream(o).messages()){let s=i;if(s.t==="delta"){if(typeof s.delta=="string"&&(yield{type:"response.output_text.delta",item_id:t,delta:s.delta}),typeof s.reasoning=="string"&&(yield{type:"response.reasoning_text.delta",item_id:t,delta:s.reasoning}),Array.isArray(s.tool_calls))for(let
|
|
1
|
+
function g(e){if(e instanceof Error)return{type:"error",error:{type:"urun_error",code:e.name||null,message:e.message}};if(e&&typeof e=="object"&&e.t==="error"){let n=e,o=n.body??{};return{type:"error",error:{type:"urun_error",code:n.code??null,message:o.message??"unknown error"}}}return{type:"error",error:{type:"urun_error",code:null,message:String(e)}}}function y(e,n,o,t){let r=e.response??{},i={request_id:o,consumer_id:t,stream:!0,kind:"chat",messages:n};return typeof r.instructions=="string"&&(i.instructions=r.instructions),Array.isArray(r.modalities)&&(i.modalities=r.modalities),typeof r.temperature=="number"&&(i.temperature=r.temperature),typeof r.max_output_tokens=="number"&&(i.max_output_tokens=r.max_output_tokens),r.tools!==void 0&&(i.tools=r.tools),i}function _(e,n,o){let t={request_id:n,consumer_id:o,stream:!!e.stream,kind:"responses",input:e.input};return e.model&&(t.model=e.model),e.tools!==void 0&&(t.tools=e.tools),e.tool_choice!==void 0&&(t.tool_choice=e.tool_choice),typeof e.temperature=="number"&&(t.temperature=e.temperature),typeof e.max_output_tokens=="number"&&(t.max_output_tokens=e.max_output_tokens),t}var w="llm-resp";async function*d(e,n){let o=`${w}:${n}`,t=`resp_${n}`;yield{type:"response.created",response:{id:t,status:"in_progress"}};let r=new Map;for await(let i of e.stream(o).messages()){let s=i;if(s.t==="delta"){if(typeof s.delta=="string"&&(yield{type:"response.output_text.delta",item_id:t,delta:s.delta}),typeof s.reasoning=="string"&&(yield{type:"response.reasoning_text.delta",item_id:t,delta:s.reasoning}),Array.isArray(s.tool_calls))for(let a of s.tool_calls){let p=typeof a.index=="number"?a.index:0,u=r.get(p)??{};a.id&&(u.id=a.id),a.function?.name&&(u.name=a.function.name),r.set(p,u),yield{type:"response.function_call_arguments.delta",item_id:`fc_${n}_${p}`,tool_index:p,call_id:u.id,name:u.name,delta:a.function?.arguments??""}}}else if(s.t==="response"){yield{type:"response.completed",response:{id:t,status:"completed",...s.body}};return}else if(s.t==="error"){yield g(s);return}}}var b="llm",m=class{constructor(n){this.session=n;this.sessionTag=n.sessionId??globalThis.crypto.randomUUID()}session;sessionTag;get consumerId(){return this.session.consumerId}write(n){n.session_tag=this.sessionTag,this.session.doc(b).set({requests:{[n.request_id]:{payload:n,consumer_id:n.consumer_id,stream:n.stream}}})}sendResponses(n,o){let t=_(n,o,this.consumerId);return this.write(t),d(this.session,o)}sendResponseCreate(n,o,t){let r=y(n,o,t,this.consumerId);return this.write(r),d(this.session,t)}};var f=0;function v(){return f+=1,`req_${Date.now().toString(36)}_${f.toString(36)}`}var k=class{transport;constructor(n){this.transport=new m(n)}responses={create:async n=>{let o=v(),t=this.transport.sendResponses(n,o);return Object.assign((async function*(){yield*t})(),{requestId:o})}}};export{g as a,m as b,k as c};
|
package/dist/index.cjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
"use strict";var D=Object.create;var f=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var q=Object.getPrototypeOf,H=Object.prototype.hasOwnProperty;var N=(n,e)=>{for(var t in e)f(n,t,{get:e[t],enumerable:!0})},S=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of j(e))!H.call(n,o)&&o!==t&&f(n,o,{get:()=>e[o],enumerable:!(r=$(e,o))||r.enumerable});return n};var
|
|
1
|
+
"use strict";var D=Object.create;var f=Object.defineProperty;var $=Object.getOwnPropertyDescriptor;var j=Object.getOwnPropertyNames;var q=Object.getPrototypeOf,H=Object.prototype.hasOwnProperty;var N=(n,e)=>{for(var t in e)f(n,t,{get:e[t],enumerable:!0})},S=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of j(e))!H.call(n,o)&&o!==t&&f(n,o,{get:()=>e[o],enumerable:!(r=$(e,o))||r.enumerable});return n};var _=(n,e,t)=>(t=n!=null?D(q(n)):{},S(e||!n||!n.__esModule?f(t,"default",{value:n,enumerable:!0}):t,n)),W=n=>S(f({},"__esModule",{value:!0}),n);var Q={};N(Q,{SUPPORTED_REALTIME_CLIENT_EVENTS:()=>h,SUPPORTED_RESPONSES_EVENTS:()=>b,UrunRealtime:()=>y,UrunResponses:()=>g,isSupportedClientEvent:()=>P,isSupportedResponsesEvent:()=>O,listModels:()=>L,nodeAudioBackend:()=>x,toErrorEvent:()=>p,weriftAudioBackend:()=>R});module.exports=W(Q);function E(n,e,t,r){let o=n.response??{},s={request_id:t,consumer_id:r,stream:!0,kind:"chat",messages:e};return typeof o.instructions=="string"&&(s.instructions=o.instructions),Array.isArray(o.modalities)&&(s.modalities=o.modalities),typeof o.temperature=="number"&&(s.temperature=o.temperature),typeof o.max_output_tokens=="number"&&(s.max_output_tokens=o.max_output_tokens),o.tools!==void 0&&(s.tools=o.tools),s}function A(n,e,t){let r={request_id:e,consumer_id:t,stream:!!n.stream,kind:"responses",input:n.input};return n.model&&(r.model=n.model),n.tools!==void 0&&(r.tools=n.tools),n.tool_choice!==void 0&&(r.tool_choice=n.tool_choice),typeof n.temperature=="number"&&(r.temperature=n.temperature),typeof n.max_output_tokens=="number"&&(r.max_output_tokens=n.max_output_tokens),r}function p(n){if(n instanceof Error)return{type:"error",error:{type:"urun_error",code:n.name||null,message:n.message}};if(n&&typeof n=="object"&&n.t==="error"){let e=n,t=e.body??{};return{type:"error",error:{type:"urun_error",code:e.code??null,message:t.message??"unknown error"}}}return{type:"error",error:{type:"urun_error",code:null,message:String(n)}}}var F="llm-resp";async function*v(n,e){let t=`${F}:${e}`,r=`resp_${e}`;yield{type:"response.created",response:{id:r,status:"in_progress"}};let o=new Map;for await(let s of n.stream(t).messages()){let a=s;if(a.t==="delta"){if(typeof a.delta=="string"&&(yield{type:"response.output_text.delta",item_id:r,delta:a.delta}),typeof a.reasoning=="string"&&(yield{type:"response.reasoning_text.delta",item_id:r,delta:a.reasoning}),Array.isArray(a.tool_calls))for(let u of a.tool_calls){let i=typeof u.index=="number"?u.index:0,c=o.get(i)??{};u.id&&(c.id=u.id),u.function?.name&&(c.name=u.function.name),o.set(i,c),yield{type:"response.function_call_arguments.delta",item_id:`fc_${e}_${i}`,tool_index:i,call_id:c.id,name:c.name,delta:u.function?.arguments??""}}}else if(a.t==="response"){yield{type:"response.completed",response:{id:r,status:"completed",...a.body}};return}else if(a.t==="error"){yield p(a);return}}}var K="llm",l=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(K).set({requests:{[e.request_id]:{payload:e,consumer_id:e.consumer_id,stream:e.stream}}})}sendResponses(e,t){let r=A(e,t,this.consumerId);return this.write(r),v(this.session,t)}sendResponseCreate(e,t,r){let o=E(e,t,r,this.consumerId);return this.write(o),v(this.session,r)}};var k=class{constructor(e,t){this.backend=e;this.opts=t}backend;opts;source=null;sink=null;outHandlers=new Set;async startOutbound(){return this.source=this.backend.createSource(),this.source.track}appendInputAudio(e){if(!this.source)throw new Error("startOutbound() not called");let t=Buffer.from(e,"base64"),r=Math.floor(t.byteLength/2),o=new Int16Array(r);for(let s=0;s<r;s++)o[s]=t.readInt16LE(s*2);this.source.onData(o)}async startInbound(e){if(e==null)throw new Error('startInbound: no downstream audio track \u2014 the runtime audio producer has not been consumed yet (session.stream("rt-audio-out").track is null)');this.sink=this.backend.createSink(e),this.sink.onframe=t=>{let r=Buffer.from(t.samples.buffer,t.samples.byteOffset,t.samples.byteLength).toString("base64");for(let o of this.outHandlers)o(r)}}onOutputAudio(e){return this.outHandlers.add(e),()=>this.outHandlers.delete(e)}},V=24e3,m=480,Y=111;async function z(){let n=await import("opusscript"),e=n.default??n;return new e(V,1,2048)}async function R(){let n=await import("werift"),e=await z();return{createSource:()=>{let t=new n.MediaStreamTrack({kind:"audio"}),r=Math.random()*4294967295>>>0,o=Math.random()*65535&65535,s=Math.random()*4294967295>>>0,a=new Int16Array(0);return{track:t,onData:u=>{let i=new Int16Array(a.length+u.length);i.set(a,0),i.set(u,a.length);let c=0;for(;i.length-c>=m;){let w=i.subarray(c,c+m);c+=m;let B=Buffer.from(w.buffer,w.byteOffset,w.byteLength),C=e.encode(B,m);o=o+1&65535,s=s+m>>>0;let M=new n.RtpHeader({version:2,payloadType:Y,sequenceNumber:o,timestamp:s,ssrc:r,marker:!1}),U=new n.RtpPacket(M,C);t.writeRtp(U)}a=i.slice(c)}}},createSink:t=>{let r={onframe:null};return t.onReceiveRtp.subscribe(s=>{let a;try{a=e.decode(s.payload)}catch{return}let u=new Int16Array(a.length/2);for(let i=0;i<u.length;i++)u[i]=a.readInt16LE(i*2);r.onframe?.({samples:u})}),r}}}async function x(){let n=await import("@roamhq/wrtc");return{createSource:()=>{let e=new n.nonstandard.RTCAudioSource;return{track:e.createTrack(),onData:r=>e.onData({samples:r,sampleRate:24e3})}},createSink:e=>{let t={onframe:null},r=new n.nonstandard.RTCAudioSink(e);return r.ondata=o=>{t.onframe?.(o)},t}}}var T=0;function X(){return T+=1,`rt_${Date.now().toString(36)}_${T.toString(36)}`}var y=class{constructor(e,t={}){this.session=e;this.opts=t;this.transport=new l(e)}session;opts;transport;handlers=new Set;conversation=[];active=null;audio=null;currentRequestId=null;async enableAudio(){if(!this.opts.audioBackend)throw new Error("audioBackend required for audio");this.audio=new k(this.opts.audioBackend,{sampleRate:24e3});let e=await this.audio.startOutbound();await this.session.stream("rt-audio-in").attach(e),this.audio.onOutputAudio(r=>this.emit({type:"response.audio.delta",delta:r}));let t=await this.awaitDownstreamAudioTrack();await this.audio.startInbound(t)}awaitDownstreamAudioTrack(e=1e4){let t=this.session.stream("rt-audio-out");return t.track!=null?Promise.resolve(t.track):new Promise((r,o)=>{let s,a=setTimeout(()=>{s?.(),o(new Error(`enableAudio: no downstream audio track within ${e}ms (runtime produced no voice OUT / SFU audio consumer never attached)`))},e),u=i=>{i!=null&&(clearTimeout(a),s?.(),r(i))};s=t.on?.("track",u),t.track!=null&&u(t.track)})}on(e,t){return this.handlers.add(t),()=>this.handlers.delete(t)}emit(e){for(let t of this.handlers)t(e)}send(e){switch(e.type){case"conversation.item.create":{let t=(e.item?.content??[]).map(r=>r.text??"").join("");this.conversation.push({role:e.item?.role??"user",content:t});return}case"response.create":{let t=X();this.currentRequestId=t;let r=this.transport.sendResponseCreate({type:"response.create",response:e.response},this.conversation,t);this.active=(async()=>{try{for await(let o of r)this.emit(o)}catch(o){this.emit(p(o))}})();return}case"input_audio_buffer.append":this.audio?.appendInputAudio(e.audio);return;case"input_audio_buffer.commit":case"input_audio_buffer.clear":return;case"response.cancel":return;default:return}}async drain(){this.active&&await this.active}};var I=0;function G(){return I+=1,`req_${Date.now().toString(36)}_${I.toString(36)}`}var g=class{transport;constructor(e){this.transport=new l(e)}responses={create:async e=>{let t=G(),r=this.transport.sendResponses(e,t);return Object.assign((async function*(){yield*r})(),{requestId:t})}}};async function J(n){let t=await(n.fetchImpl??fetch)(`${n.catalogUrl}/model_catalog?select=model_id,variant`,{headers:{apikey:n.anonKey,Authorization:`Bearer ${n.anonKey}`}});if(!t.ok)throw new Error(`model_catalog fetch failed: ${t.status}`);return await t.json()}async function L(n){return{object:"list",data:(await J(n)).map(t=>({id:`${t.model_id}:${t.variant}`,object:"model",created:0,owned_by:"urun"}))}}var h=["session.update","conversation.item.create","response.create","response.cancel","input_audio_buffer.append","input_audio_buffer.commit","input_audio_buffer.clear"],b=["response.created","response.output_text.delta","response.output_item.added","response.function_call_arguments.delta","response.image_generation_call.partial_image","response.completed","error"];function P(n){return h.includes(n)}function O(n){return b.includes(n)}0&&(module.exports={SUPPORTED_REALTIME_CLIENT_EVENTS,SUPPORTED_RESPONSES_EVENTS,UrunRealtime,UrunResponses,isSupportedClientEvent,isSupportedResponsesEvent,listModels,nodeAudioBackend,toErrorEvent,weriftAudioBackend});
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as UrunSessionLike, L as LaneMessage } from './ResponsesClient-
|
|
2
|
-
export { U as UrunResponses } from './ResponsesClient-
|
|
1
|
+
import { a as UrunSessionLike, L as LaneMessage } from './ResponsesClient-DrccxHTc.cjs';
|
|
2
|
+
export { U as UrunResponses } from './ResponsesClient-DrccxHTc.cjs';
|
|
3
3
|
export { RealtimeClientEvent, RealtimeServerEvent } from 'openai/resources/beta/realtime/realtime';
|
|
4
4
|
export { ResponseStreamEvent } from 'openai/resources/responses/responses';
|
|
5
5
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { a as UrunSessionLike, L as LaneMessage } from './ResponsesClient-
|
|
2
|
-
export { U as UrunResponses } from './ResponsesClient-
|
|
1
|
+
import { a as UrunSessionLike, L as LaneMessage } from './ResponsesClient-DrccxHTc.js';
|
|
2
|
+
export { U as UrunResponses } from './ResponsesClient-DrccxHTc.js';
|
|
3
3
|
export { RealtimeClientEvent, RealtimeServerEvent } from 'openai/resources/beta/realtime/realtime';
|
|
4
4
|
export { ResponseStreamEvent } from 'openai/resources/responses/responses';
|
|
5
5
|
|
package/dist/index.js
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
import{b as _}from"./chunk-OLE2YJO3.js";import{a as f,b as v,c as g}from"./chunk-
|
|
1
|
+
import{b as _}from"./chunk-OLE2YJO3.js";import{a as f,b as v,c as g}from"./chunk-HQVV5UN5.js";var p=class{constructor(t,e){this.backend=t;this.opts=e}backend;opts;source=null;sink=null;outHandlers=new Set;async startOutbound(){return this.source=this.backend.createSource(),this.source.track}appendInputAudio(t){if(!this.source)throw new Error("startOutbound() not called");let e=Buffer.from(t,"base64"),n=Math.floor(e.byteLength/2),r=new Int16Array(n);for(let a=0;a<n;a++)r[a]=e.readInt16LE(a*2);this.source.onData(r)}async startInbound(t){if(t==null)throw new Error('startInbound: no downstream audio track \u2014 the runtime audio producer has not been consumed yet (session.stream("rt-audio-out").track is null)');this.sink=this.backend.createSink(t),this.sink.onframe=e=>{let n=Buffer.from(e.samples.buffer,e.samples.byteOffset,e.samples.byteLength).toString("base64");for(let r of this.outHandlers)r(n)}}onOutputAudio(t){return this.outHandlers.add(t),()=>this.outHandlers.delete(t)}},T=24e3,c=480,x=111;async function I(){let o=await import("opusscript"),t=o.default??o;return new t(T,1,2048)}async function P(){let o=await import("werift"),t=await I();return{createSource:()=>{let e=new o.MediaStreamTrack({kind:"audio"}),n=Math.random()*4294967295>>>0,r=Math.random()*65535&65535,a=Math.random()*4294967295>>>0,i=new Int16Array(0);return{track:e,onData:u=>{let s=new Int16Array(i.length+u.length);s.set(i,0),s.set(u,i.length);let d=0;for(;s.length-d>=c;){let l=s.subarray(d,d+c);d+=c;let A=Buffer.from(l.buffer,l.byteOffset,l.byteLength),E=t.encode(A,c);r=r+1&65535,a=a+c>>>0;let b=new o.RtpHeader({version:2,payloadType:x,sequenceNumber:r,timestamp:a,ssrc:n,marker:!1}),R=new o.RtpPacket(b,E);e.writeRtp(R)}i=s.slice(d)}}},createSink:e=>{let n={onframe:null};return e.onReceiveRtp.subscribe(a=>{let i;try{i=t.decode(a.payload)}catch{return}let u=new Int16Array(i.length/2);for(let s=0;s<u.length;s++)u[s]=i.readInt16LE(s*2);n.onframe?.({samples:u})}),n}}}async function B(){let o=await import("@roamhq/wrtc");return{createSource:()=>{let t=new o.nonstandard.RTCAudioSource;return{track:t.createTrack(),onData:n=>t.onData({samples:n,sampleRate:24e3})}},createSink:t=>{let e={onframe:null},n=new o.nonstandard.RTCAudioSink(t);return n.ondata=r=>{e.onframe?.(r)},e}}}var h=0;function O(){return h+=1,`rt_${Date.now().toString(36)}_${h.toString(36)}`}var w=class{constructor(t,e={}){this.session=t;this.opts=e;this.transport=new v(t)}session;opts;transport;handlers=new Set;conversation=[];active=null;audio=null;currentRequestId=null;async enableAudio(){if(!this.opts.audioBackend)throw new Error("audioBackend required for audio");this.audio=new p(this.opts.audioBackend,{sampleRate:24e3});let t=await this.audio.startOutbound();await this.session.stream("rt-audio-in").attach(t),this.audio.onOutputAudio(n=>this.emit({type:"response.audio.delta",delta:n}));let e=await this.awaitDownstreamAudioTrack();await this.audio.startInbound(e)}awaitDownstreamAudioTrack(t=1e4){let e=this.session.stream("rt-audio-out");return e.track!=null?Promise.resolve(e.track):new Promise((n,r)=>{let a,i=setTimeout(()=>{a?.(),r(new Error(`enableAudio: no downstream audio track within ${t}ms (runtime produced no voice OUT / SFU audio consumer never attached)`))},t),u=s=>{s!=null&&(clearTimeout(i),a?.(),n(s))};a=e.on?.("track",u),e.track!=null&&u(e.track)})}on(t,e){return this.handlers.add(e),()=>this.handlers.delete(e)}emit(t){for(let e of this.handlers)e(t)}send(t){switch(t.type){case"conversation.item.create":{let e=(t.item?.content??[]).map(n=>n.text??"").join("");this.conversation.push({role:t.item?.role??"user",content:e});return}case"response.create":{let e=O();this.currentRequestId=e;let n=this.transport.sendResponseCreate({type:"response.create",response:t.response},this.conversation,e);this.active=(async()=>{try{for await(let r of n)this.emit(r)}catch(r){this.emit(f(r))}})();return}case"input_audio_buffer.append":this.audio?.appendInputAudio(t.audio);return;case"input_audio_buffer.commit":case"input_audio_buffer.clear":return;case"response.cancel":return;default:return}}async drain(){this.active&&await this.active}};var S=["session.update","conversation.item.create","response.create","response.cancel","input_audio_buffer.append","input_audio_buffer.commit","input_audio_buffer.clear"],y=["response.created","response.output_text.delta","response.output_item.added","response.function_call_arguments.delta","response.image_generation_call.partial_image","response.completed","error"];function L(o){return S.includes(o)}function C(o){return y.includes(o)}export{S as SUPPORTED_REALTIME_CLIENT_EVENTS,y as SUPPORTED_RESPONSES_EVENTS,w as UrunRealtime,g as UrunResponses,L as isSupportedClientEvent,C as isSupportedResponsesEvent,_ as listModels,B as nodeAudioBackend,f as toErrorEvent,P as weriftAudioBackend};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var
|
|
2
|
-
`)}}function
|
|
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(`
|
|
3
3
|
|
|
4
|
-
`):e.push({...n})}return e}function
|
|
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});
|
|
@@ -1,6 +1,6 @@
|
|
|
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-
|
|
3
|
+
import { a as UrunSessionLike, U as UrunResponses } from '../ResponsesClient-DrccxHTc.cjs';
|
|
4
4
|
|
|
5
5
|
/**
|
|
6
6
|
* Pi coding-agent extension: register the `urun` model provider, with one pi
|
|
@@ -53,12 +53,13 @@ import { a as UrunSessionLike, U as UrunResponses } from '../ResponsesClient-DF3
|
|
|
53
53
|
* 3. ABORT/CANCEL (loud contract): the Responses lane has NO request-cancel
|
|
54
54
|
* primitive (`SdkTransport.sendResponses` writes an envelope and the
|
|
55
55
|
* decode loop just reads the reply lane), so Ctrl-C / the stall watchdog
|
|
56
|
-
* stop consuming AND evict+
|
|
57
|
-
* WebRTC transport is what stops
|
|
58
|
-
* keeps its session for the next
|
|
59
|
-
* always reopens
|
|
60
|
-
*
|
|
61
|
-
*
|
|
56
|
+
* stop consuming AND evict+END the pooled session (core's own
|
|
57
|
+
* `Session.end()`) — tearing down the WebRTC transport is what stops
|
|
58
|
+
* server-side generation. A clean turn keeps its session for the next
|
|
59
|
+
* turn; a failed/aborted/stalled turn always reopens — and a turn whose
|
|
60
|
+
* session DIED re-homes once and replays (see REHOME_ATTEMPTS).
|
|
61
|
+
* 4. cleanup: pooled sessions are released (core's `Session.end()`) on
|
|
62
|
+
* pi's `session_shutdown` lifecycle event.
|
|
62
63
|
*
|
|
63
64
|
* RUNTIME DEPENDENCY STORY (owner requirement — stated honestly): token
|
|
64
65
|
* streams are named-DATA session streams, i.e. SCTP data channels over
|
|
@@ -118,8 +119,18 @@ declare function resolveSessionEnv(env: NodeJS.ProcessEnv): {
|
|
|
118
119
|
* `@urun-sh/core`.
|
|
119
120
|
*/
|
|
120
121
|
interface SessionFactory {
|
|
121
|
-
(env: NodeJS.ProcessEnv, appSlug: string, fnName: string): Promise<
|
|
122
|
+
(env: NodeJS.ProcessEnv, appSlug: string, fnName: string): Promise<OwnedSession> | OwnedSession;
|
|
122
123
|
}
|
|
124
|
+
/**
|
|
125
|
+
* A session this lane OWNS: core's transport surface plus core's own terminal
|
|
126
|
+
* release, `Session.end()` (the same requirement the compat proxy asserts in
|
|
127
|
+
* `sessionOf`). A session without it could never be released — it would leak
|
|
128
|
+
* the backend session and its capacity lease until the platform's abandonment
|
|
129
|
+
* backstop reclaimed it — so the factory refuses to hand one back.
|
|
130
|
+
*/
|
|
131
|
+
type OwnedSession = UrunSessionLike & {
|
|
132
|
+
end: () => Promise<unknown>;
|
|
133
|
+
};
|
|
123
134
|
/** The structured diagnostic shape core's transports emit (typed locally). */
|
|
124
135
|
interface CoreDiagnosticLike {
|
|
125
136
|
level: string;
|
|
@@ -173,7 +184,7 @@ declare function piDiagnosticLogPath(home?: string): string;
|
|
|
173
184
|
declare function makeSessionFactory(loadCore: () => Promise<CoreModuleLike> | CoreModuleLike): SessionFactory;
|
|
174
185
|
/** One pooled backhaul: the session plus its Responses client (cli.ts shape). */
|
|
175
186
|
interface PoolEntry {
|
|
176
|
-
session:
|
|
187
|
+
session: OwnedSession;
|
|
177
188
|
responses: UrunResponses;
|
|
178
189
|
}
|
|
179
190
|
/**
|
|
@@ -254,4 +265,4 @@ declare function createUrunExtension(opts?: UrunExtensionOptions): (pi: Extensio
|
|
|
254
265
|
/** The pi extension factory (default export — what pi's loader invokes). */
|
|
255
266
|
declare const _default: (pi: ExtensionAPI) => Promise<void>;
|
|
256
267
|
|
|
257
|
-
export { type CoreDiagnosticLike, type CoreModuleLike, type ResponsesInputItem, type SessionFactory, SessionPool, type StreamTiming, URUN_API, type UrunExtensionOptions, coalesceSameRole, createFileDiagnosticSink, createUrunExtension, _default as default, makeSessionFactory, makeStreamSimple, piDiagnosticLogPath, resolveSessionEnv, toResponsesInput };
|
|
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 };
|
|
@@ -1,6 +1,6 @@
|
|
|
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-
|
|
3
|
+
import { a as UrunSessionLike, U as UrunResponses } from '../ResponsesClient-DrccxHTc.js';
|
|
4
4
|
|
|
5
5
|
declare const URUN_API: Api;
|
|
6
6
|
|
|
@@ -18,9 +18,13 @@ declare function resolveSessionEnv(env: NodeJS.ProcessEnv): {
|
|
|
18
18
|
};
|
|
19
19
|
|
|
20
20
|
interface SessionFactory {
|
|
21
|
-
(env: NodeJS.ProcessEnv, appSlug: string, fnName: string): Promise<
|
|
21
|
+
(env: NodeJS.ProcessEnv, appSlug: string, fnName: string): Promise<OwnedSession> | OwnedSession;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
type OwnedSession = UrunSessionLike & {
|
|
25
|
+
end: () => Promise<unknown>;
|
|
26
|
+
};
|
|
27
|
+
|
|
24
28
|
interface CoreDiagnosticLike {
|
|
25
29
|
level: string;
|
|
26
30
|
kind: string;
|
|
@@ -51,7 +55,7 @@ declare function piDiagnosticLogPath(home?: string): string;
|
|
|
51
55
|
declare function makeSessionFactory(loadCore: () => Promise<CoreModuleLike> | CoreModuleLike): SessionFactory;
|
|
52
56
|
|
|
53
57
|
interface PoolEntry {
|
|
54
|
-
session:
|
|
58
|
+
session: OwnedSession;
|
|
55
59
|
responses: UrunResponses;
|
|
56
60
|
}
|
|
57
61
|
|
|
@@ -105,4 +109,4 @@ declare function createUrunExtension(opts?: UrunExtensionOptions): (pi: Extensio
|
|
|
105
109
|
|
|
106
110
|
declare const _default: (pi: ExtensionAPI) => Promise<void>;
|
|
107
111
|
|
|
108
|
-
export { type CoreDiagnosticLike, type CoreModuleLike, type ResponsesInputItem, type SessionFactory, SessionPool, type StreamTiming, URUN_API, type UrunExtensionOptions, coalesceSameRole, createFileDiagnosticSink, createUrunExtension, _default as default, makeSessionFactory, makeStreamSimple, piDiagnosticLogPath, resolveSessionEnv, toResponsesInput };
|
|
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 };
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import{c as
|
|
2
|
-
`)}}function
|
|
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(`
|
|
3
3
|
|
|
4
|
-
`):e.push({...n})}return e}function
|
|
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};
|