@urun-sh/openai 0.2.52 → 0.2.54

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.
@@ -25,11 +25,36 @@ interface UrunSessionLike {
25
25
  stream(name: string): UrunStreamLike;
26
26
  close?(): Promise<void> | void;
27
27
  }
28
- /** Lane message shape emitted by the serve runtime (core session.ts:83). */
28
+ /**
29
+ * One OpenAI chat-completions-chunk-style tool_call delta fragment as the
30
+ * serve runtime streams it (`{"t":"delta","tool_calls":[...]}`): keyed by
31
+ * `index`; `id`/`function.name` typically arrive only on the first fragment
32
+ * of an index, later fragments carry only the `function.arguments`
33
+ * continuation.
34
+ */
35
+ interface LaneToolCallDelta {
36
+ index: number;
37
+ id?: string;
38
+ type?: 'function';
39
+ function?: {
40
+ name?: string;
41
+ arguments?: string;
42
+ };
43
+ }
44
+ /**
45
+ * Lane message shape emitted by the serve runtime (core session.ts:83).
46
+ * A `delta` message carries AT LEAST ONE of `delta` (visible text),
47
+ * `reasoning` (thinking text) or `tool_calls` (structured tool-call
48
+ * fragments); both directions are additive — an old server simply never
49
+ * sends the new fields, and unknown extra fields must be ignored, never a
50
+ * decode error.
51
+ */
29
52
  type LaneMessage = {
30
53
  t: 'delta';
31
54
  request_id?: string;
32
- delta: string;
55
+ delta?: string;
56
+ reasoning?: string;
57
+ tool_calls?: LaneToolCallDelta[];
33
58
  } | {
34
59
  t: 'response';
35
60
  request_id?: string;
@@ -53,6 +78,7 @@ declare class UrunResponses {
53
78
  input: unknown;
54
79
  stream?: boolean;
55
80
  tools?: unknown;
81
+ tool_choice?: unknown;
56
82
  temperature?: number;
57
83
  max_output_tokens?: number;
58
84
  }) => Promise<ResponsesStream>;
@@ -20,10 +20,22 @@ interface UrunSessionLike {
20
20
  close?(): Promise<void> | void;
21
21
  }
22
22
 
23
+ interface LaneToolCallDelta {
24
+ index: number;
25
+ id?: string;
26
+ type?: 'function';
27
+ function?: {
28
+ name?: string;
29
+ arguments?: string;
30
+ };
31
+ }
32
+
23
33
  type LaneMessage = {
24
34
  t: 'delta';
25
35
  request_id?: string;
26
- delta: string;
36
+ delta?: string;
37
+ reasoning?: string;
38
+ tool_calls?: LaneToolCallDelta[];
27
39
  } | {
28
40
  t: 'response';
29
41
  request_id?: string;
@@ -47,6 +59,7 @@ declare class UrunResponses {
47
59
  input: unknown;
48
60
  stream?: boolean;
49
61
  tools?: unknown;
62
+ tool_choice?: unknown;
50
63
  temperature?: number;
51
64
  max_output_tokens?: number;
52
65
  }) => Promise<ResponsesStream>;
@@ -0,0 +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 u of s.tool_calls){let p=typeof u.index=="number"?u.index:0,a=r.get(p)??{};u.id&&(a.id=u.id),u.function?.name&&(a.name=u.function.name),r.set(p,a),yield{type:"response.function_call_arguments.delta",item_id:`fc_${n}_${p}`,tool_index:p,call_id:a.id,name:a.name,delta:u.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",l=class{constructor(n){this.session=n}session;get consumerId(){return this.session.consumerId}write(n){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 l(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,l as b,k as c};
@@ -0,0 +1,27 @@
1
+ import{b as V}from"./chunk-PS4BLX7J.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
+ data: ${JSON.stringify(p)}
3
+
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]
5
+
6
+ `),o.end();return}let I=null;for await(let s of a.track(A,_)){if(f.push(s),s.type==="error"){w(o,502,JSON.stringify(s),"upstream_error");return}s.type==="response.completed"&&(I=s.response)}if(I==null){w(o,502,"upstream produced no response.completed event","upstream_error");return}let q=gt(f,I),P=K(v,Q(I).length,q);if(P){w(o,502,D(_,P),"upstream_error");return}d&&t.remember(i,u,q),J(o,200,{...I,id:i})}async function bt(e,n,t,o){let a=e.messages;if(!Array.isArray(a)){w(t,400,"chat/completions requires a messages array");return}let c=String(e.model??"urun"),u=`chatcmpl-${Math.random().toString(36).slice(2,14)}`,i;try{i=Ot(a)}catch(r){if(r instanceof ot){w(t,400,r.message);return}throw r}let d=dt(e);o.model(d);let _=Array.isArray(e.tools)&&e.tools.length>0,v;try{v=await n.createResponse({model:e.model,input:i,stream:!0,tools:St(e.tools),tool_choice:e.tool_choice,temperature:e.temperature,max_output_tokens:e.max_completion_tokens??e.max_tokens})}catch(r){if(r instanceof V){pt(t,"openai",r);return}throw r}if(e.stream===!0){ct(t);let r=[],g=new z,T="";t.write(`data: ${JSON.stringify(F(u,c,{role:"assistant"},null))}
7
+
8
+ `);for await(let m of o.track(v,d)){r.push(m);let x=Z(m);if(m.type==="response.output_text.delta"&&typeof m.delta=="string")T+=m.delta,t.write(`data: ${JSON.stringify(F(u,c,{content:m.delta},null))}
9
+
10
+ `);else if(m.type==="response.reasoning_text.delta"&&typeof m.delta=="string")t.write(`data: ${JSON.stringify(F(u,c,{reasoning_content:m.delta},null))}
11
+
12
+ `);else if(x){let{call:O,isNew:j}=g.add(x),B=j?{index:x.tool_index,id:O.id??`call_${x.tool_index}`,type:"function",function:{name:O.name??"",arguments:x.delta}}:{index:x.tool_index,function:{arguments:x.delta}};t.write(`data: ${JSON.stringify(F(u,c,{tool_calls:[B]},null))}
13
+
14
+ `)}else if(m.type==="error"){t.write(`data: ${JSON.stringify({error:m})}
15
+
16
+ `),t.end();return}}let S=it(W(r)),M=K(_,g.size+S.length,T);if(M){t.write(`data: ${JSON.stringify({error:{type:"urun_error",code:"tool_call_parser_missing",message:D(d,M)}})}
17
+
18
+ `),t.end();return}g.size===0&&S.length>0&&t.write(`data: ${JSON.stringify(F(u,c,{tool_calls:S},null))}
19
+
20
+ `);let N=g.size>0||S.length>0;t.write(`data: ${JSON.stringify(F(u,c,{},N?"tool_calls":"stop"))}
21
+
22
+ `),t.write(`data: [DONE]
23
+
24
+ `),t.end();return}let A="",f="",I=[],q=new z;for await(let r of o.track(v,d)){I.push(r),r.type==="response.output_text.delta"&&typeof r.delta=="string"&&(A+=r.delta),r.type==="response.reasoning_text.delta"&&typeof r.delta=="string"&&(f+=r.delta);let g=Z(r);if(g&&q.add(g),r.type==="error"){w(t,502,JSON.stringify(r),"upstream_error");return}}let P=W(I),s=it(P),C=s.length>0?s:it({output:q.items()}),R=K(_,C.length,A);if(R){w(t,502,D(d,R),"upstream_error");return}let b=C.map(({index:r,...g})=>g),E={role:"assistant",content:A||null},$=f||_t(P);$&&(E.reasoning_content=$),b.length>0&&(E.tool_calls=b),J(t,200,{id:u,object:"chat.completion",created:Math.floor(Date.now()/1e3),model:c,choices:[{index:0,message:E,finish_reason:b.length>0?"tool_calls":"stop"}],usage:{prompt_tokens:0,completion_tokens:0,total_tokens:0}})}function $t(e){return typeof e=="string"?e:Array.isArray(e)?e.filter(n=>n.type==="text").map(n=>String(n.text??"")).join(""):""}var tt=class extends Error{};function rt(e){return new tt(`unsupported anthropic content block type "${e}" \u2014 the proxy translates text, tool_use and tool_result blocks`)}function Mt(e){if(Array.isArray(e))return e.map(n=>{let t=n;return{type:"function",name:t.name,description:t.description,parameters:t.input_schema}})}function Ct(e){if(e==null)return;let n=e.type;if(n==="auto")return"auto";if(n==="none")return"none";if(n==="any")return"required";if(n==="tool")return{type:"function",name:e.name};throw new tt(`unsupported anthropic tool_choice type ${JSON.stringify(String(n))} \u2014 the proxy maps auto, none, any and tool`)}function Tt(e){if(typeof e=="string")return e;if(e==null)return"";if(!Array.isArray(e))throw rt(typeof e);let n="";for(let t of e){let o=String(t.type??"");if(o!=="text")throw rt(`tool_result > ${o}`);n+=String(t.text??"")}return n}function Nt(e){let{role:n,content:t}=e;if(typeof t=="string")return[{role:n,content:t}];if(t==null)return[];if(!Array.isArray(t))throw rt(typeof t);let o=[],a="",c=()=>{a&&(o.push({role:n,content:a}),a="")};for(let u of t){let i=String(u.type??"");if(i==="text")a+=String(u.text??"");else if(i==="tool_use")c(),o.push({type:"function_call",call_id:u.id,name:u.name,arguments:JSON.stringify(u.input??{})});else if(i==="tool_result")c(),o.push({type:"function_call_output",call_id:u.tool_use_id,output:Tt(u.content)});else{if(i==="thinking"||i==="redacted_thinking")continue;throw rt(i)}}return c(),o}function at(e){return Q(e).map((n,t)=>{let o;try{o=JSON.parse(n.arguments||"{}")}catch{throw new Error(`upstream function_call "${n.name??""}" arguments are not valid JSON`)}return{type:"tool_use",id:n.call_id??n.id??`toolu_${t}`,name:n.name??"",input:o}})}async function Bt(e,n,t,o){let a=e.messages;if(!Array.isArray(a)){w(t,400,"messages requires a messages array");return}let c=String(e.model??"urun"),u=`msg_${Math.random().toString(36).slice(2,14)}`,i=[],d;try{e.system&&i.push({role:"system",content:$t(e.system)});for(let r of a)i.push(...Nt(r));d=Ct(e.tool_choice)}catch(r){if(r instanceof tt){w(t,400,r.message);return}throw r}let _=dt(e);o.model(_);let v=Array.isArray(e.tools)&&e.tools.length>0,A;try{A=await n.createResponse({model:e.model,input:i,stream:!0,tools:Mt(e.tools),tool_choice:d,temperature:e.temperature,max_output_tokens:e.max_tokens})}catch(r){if(r instanceof V){pt(t,"anthropic",r);return}throw r}let f=(r,g)=>{t.write(`event: ${r}
25
+ data: ${JSON.stringify({type:r,...g})}
26
+
27
+ `)};if(e.stream===!0){let r=o.track(A,_);ct(t),f("message_start",{message:{id:u,type:"message",role:"assistant",content:[],model:c,stop_reason:null,usage:{input_tokens:0,output_tokens:0}}});let g=0,T="",S=0,M="none",N=()=>M,m=-1,x=-1,O=new z,j=[],B=()=>{M!=="none"&&(M="none",f("content_block_stop",{index:m}))},y=(l,k)=>{B(),M=l,m=S++,f("content_block_start",{index:m,content_block:k})};for await(let l of r){j.push(l);let k=Z(l);if(l.type==="response.reasoning_text.delta"&&typeof l.delta=="string")N()!=="thinking"&&y("thinking",{type:"thinking",thinking:""}),f("content_block_delta",{index:m,delta:{type:"thinking_delta",thinking:l.delta}});else if(l.type==="response.output_text.delta"&&typeof l.delta=="string")N()!=="text"&&y("text",{type:"text",text:""}),g+=1,T+=l.delta,f("content_block_delta",{index:m,delta:{type:"text_delta",text:l.delta}});else if(k){let{call:X}=O.add(k);(N()!=="tool"||k.tool_index!==x)&&(x=k.tool_index,y("tool",{type:"tool_use",id:X.id??`call_${k.tool_index}`,name:X.name??"",input:{}})),k.delta&&f("content_block_delta",{index:m,delta:{type:"input_json_delta",partial_json:k.delta}})}else if(l.type==="error"){f("error",{error:{type:"api_error",message:JSON.stringify(l)}}),t.end();return}}let L=W(j),H=Q(L),U=K(v,O.size+H.length,T);if(U){f("error",{error:{type:"api_error",message:D(_,U)}}),t.end();return}B();let p=[];if(O.size===0)try{p=at(L)}catch(l){f("error",{error:{type:"api_error",message:String(l instanceof Error?l.message:l)}}),t.end();return}S===0&&p.length===0&&(y("text",{type:"text",text:""}),B()),p.forEach(l=>{let k=S++;f("content_block_start",{index:k,content_block:{...l,input:{}}}),f("content_block_delta",{index:k,delta:{type:"input_json_delta",partial_json:JSON.stringify(l.input??{})}}),f("content_block_stop",{index:k})});let h=O.size>0||p.length>0;f("message_delta",{delta:{stop_reason:h?"tool_use":"end_turn"},usage:{output_tokens:g}}),f("message_stop",{}),t.end();return}let I="",q="",P=[],s=new z;for await(let r of o.track(A,_)){P.push(r),r.type==="response.output_text.delta"&&typeof r.delta=="string"&&(I+=r.delta),r.type==="response.reasoning_text.delta"&&typeof r.delta=="string"&&(q+=r.delta);let g=Z(r);if(g&&s.add(g),r.type==="error"){w(t,502,JSON.stringify(r),"upstream_error");return}}let C=W(P),R;try{R=at(C),R.length===0&&s.size>0&&(R=at({output:s.items()}))}catch(r){w(t,502,String(r instanceof Error?r.message:r),"upstream_error");return}let b=K(v,R.length,I);if(b){w(t,502,D(_,b),"upstream_error");return}let E=[],$=q||_t(C);$&&E.push({type:"thinking",thinking:$}),(I||R.length===0)&&E.push({type:"text",text:I}),E.push(...R),J(t,200,{id:u,type:"message",role:"assistant",content:E,model:c,stop_reason:R.length>0?"tool_use":"end_turn",usage:{input_tokens:0,output_tokens:0}})}function zt(e){let{clients:n,apiKey:t,identity:o}=e,a=new lt,c=new ut;return yt((u,i)=>{(async()=>{let d=new URL(u.url??"/","http://localhost");if(u.method==="GET"&&d.pathname==="/healthz"){J(i,200,{ok:!0});return}if(u.method==="GET"&&d.pathname==="/stats"){J(i,200,o?{identity:o,...c.snapshot()}:c.snapshot());return}if(t&&(u.headers.authorization??"")!==`Bearer ${t}`){w(i,401,"invalid local proxy api key","authentication_error");return}if(u.method==="GET"&&d.pathname==="/v1/models"){J(i,200,await n.listModels());return}if(u.method!=="POST"){w(i,404,`no route for ${u.method} ${d.pathname}`);return}let _;try{_=await wt(u)}catch(A){if(A instanceof nt){w(i,413,A.message,"request_too_large");return}w(i,400,"request body is not valid JSON");return}let v=Buffer.byteLength(JSON.stringify(_));if(d.pathname==="/v1/responses"){c.request("responses",v,v),await Et(_,n,a,i,c);return}if(d.pathname==="/v1/chat/completions"){c.request("chat_completions",v,v),await bt(_,n,i,c);return}if(d.pathname==="/v1/messages"){c.request("messages",v,v),await Bt(_,n,i,c);return}w(i,404,`no route for POST ${d.pathname}`)})().catch(d=>{i.headersSent?i.end():w(i,500,String(d),"proxy_error")})})}export{zt as a};
package/dist/index.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";var D=Object.create;var f=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var $=Object.getOwnPropertyNames;var j=Object.getPrototypeOf,H=Object.prototype.hasOwnProperty;var N=(n,e)=>{for(var t in e)f(n,t,{get:e[t],enumerable:!0})},b=(n,e,t,r)=>{if(e&&typeof e=="object"||typeof e=="function")for(let o of $(e))!H.call(n,o)&&o!==t&&f(n,o,{get:()=>e[o],enumerable:!(r=q(e,o))||r.enumerable});return n};var v=(n,e,t)=>(t=n!=null?D(j(n)):{},b(e||!n||!n.__esModule?f(t,"default",{value:n,enumerable:!0}):t,n)),W=n=>b(f({},"__esModule",{value:!0}),n);var Q={};N(Q,{SUPPORTED_REALTIME_CLIENT_EVENTS:()=>S,SUPPORTED_RESPONSES_EVENTS:()=>_,UrunRealtime:()=>y,UrunResponses:()=>w,isSupportedClientEvent:()=>P,isSupportedResponsesEvent:()=>O,listModels:()=>L,nodeAudioBackend:()=>x,toErrorEvent:()=>d,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),typeof n.temperature=="number"&&(r.temperature=n.temperature),typeof n.max_output_tokens=="number"&&(r.max_output_tokens=n.max_output_tokens),r}function d(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*h(n,e){let t=`${F}:${e}`,r=`resp_${e}`;yield{type:"response.created",response:{id:r,status:"in_progress"}};for await(let o of n.stream(t).messages()){let s=o;if(s.t==="delta")yield{type:"response.output_text.delta",item_id:r,delta:s.delta};else if(s.t==="response"){yield{type:"response.completed",response:{id:r,status:"completed",...s.body}};return}else if(s.t==="error"){yield d(s);return}}}var K="llm",p=class{constructor(e){this.session=e}session;get consumerId(){return this.session.consumerId}write(e){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),h(this.session,t)}sendResponseCreate(e,t,r){let o=E(e,t,r,this.consumerId);return this.write(o),h(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,i=new Int16Array(0);return{track:t,onData:u=>{let a=new Int16Array(i.length+u.length);a.set(i,0),a.set(u,i.length);let l=0;for(;a.length-l>=m;){let g=a.subarray(l,l+m);l+=m;let B=Buffer.from(g.buffer,g.byteOffset,g.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)}i=a.slice(l)}}},createSink:t=>{let r={onframe:null};return t.onReceiveRtp.subscribe(s=>{let i;try{i=e.decode(s.payload)}catch{return}let u=new Int16Array(i.length/2);for(let a=0;a<u.length;a++)u[a]=i.readInt16LE(a*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 I=0;function X(){return I+=1,`rt_${Date.now().toString(36)}_${I.toString(36)}`}var y=class{constructor(e,t={}){this.session=e;this.opts=t;this.transport=new p(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,i=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=a=>{a!=null&&(clearTimeout(i),s?.(),r(a))};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(d(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 T=0;function G(){return T+=1,`req_${Date.now().toString(36)}_${T.toString(36)}`}var w=class{transport;constructor(e){this.transport=new p(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 S=["session.update","conversation.item.create","response.create","response.cancel","input_audio_buffer.append","input_audio_buffer.commit","input_audio_buffer.clear"],_=["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 S.includes(n)}function O(n){return _.includes(n)}0&&(module.exports={SUPPORTED_REALTIME_CLIENT_EVENTS,SUPPORTED_RESPONSES_EVENTS,UrunRealtime,UrunResponses,isSupportedClientEvent,isSupportedResponsesEvent,listModels,nodeAudioBackend,toErrorEvent,weriftAudioBackend});
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 v=(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:()=>w,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*_(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}session;get consumerId(){return this.session.consumerId}write(e){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),_(this.session,t)}sendResponseCreate(e,t,r){let o=E(e,t,r,this.consumerId);return this.write(o),_(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 g=i.subarray(c,c+m);c+=m;let B=Buffer.from(g.buffer,g.byteOffset,g.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 I=0;function X(){return I+=1,`rt_${Date.now().toString(36)}_${I.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 T=0;function G(){return T+=1,`req_${Date.now().toString(36)}_${T.toString(36)}`}var w=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-CQ3l8Wft.cjs';
2
- export { U as UrunResponses } from './ResponsesClient-CQ3l8Wft.cjs';
1
+ import { a as UrunSessionLike, L as LaneMessage } from './ResponsesClient-DF39QXq1.cjs';
2
+ export { U as UrunResponses } from './ResponsesClient-DF39QXq1.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-CQ3l8Wft.js';
2
- export { U as UrunResponses } from './ResponsesClient-CQ3l8Wft.js';
1
+ import { a as UrunSessionLike, L as LaneMessage } from './ResponsesClient-DF39QXq1.js';
2
+ export { U as UrunResponses } from './ResponsesClient-DF39QXq1.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-FSS2A7IU.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
+ import{b as _}from"./chunk-OLE2YJO3.js";import{a as f,b as v,c as g}from"./chunk-DYBS3NLC.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,3 +1,4 @@
1
- "use strict";var re=Object.create;var E=Object.defineProperty;var oe=Object.getOwnPropertyDescriptor;var ie=Object.getOwnPropertyNames;var ae=Object.getPrototypeOf,pe=Object.prototype.hasOwnProperty;var ue=(e,t)=>{for(var n in t)E(e,n,{get:t[n],enumerable:!0})},K=(e,t,n,s)=>{if(t&&typeof t=="object"||typeof t=="function")for(let r of ie(t))!pe.call(e,r)&&r!==n&&E(e,r,{get:()=>t[r],enumerable:!(s=oe(t,r))||s.enumerable});return e};var le=(e,t,n)=>(n=e!=null?re(ae(e)):{},K(t||!e||!e.__esModule?E(n,"default",{value:e,enumerable:!0}):n,e)),ce=e=>K(E({},"__esModule",{value:!0}),e);var Me={};ue(Me,{SessionPool:()=>k,URUN_API:()=>M,coalesceSameRole:()=>Z,createUrunExtension:()=>te,default:()=>Le,makeSessionFactory:()=>Q,makeStreamSimple:()=>ee,resolveSessionEnv:()=>z,toResponsesInput:()=>V});module.exports=ce(Me);var de=()=>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,l=de();var X=require("@earendil-works/pi-ai");function q(e,t,n,s){let r=e.response??{},o={request_id:n,consumer_id:s,stream:!0,kind:"chat",messages:t};return typeof r.instructions=="string"&&(o.instructions=r.instructions),Array.isArray(r.modalities)&&(o.modalities=r.modalities),typeof r.temperature=="number"&&(o.temperature=r.temperature),typeof r.max_output_tokens=="number"&&(o.max_output_tokens=r.max_output_tokens),r.tools!==void 0&&(o.tools=r.tools),o}function W(e,t,n){let s={request_id:t,consumer_id:n,stream:!!e.stream,kind:"responses",input:e.input};return e.model&&(s.model=e.model),e.tools!==void 0&&(s.tools=e.tools),typeof e.temperature=="number"&&(s.temperature=e.temperature),typeof e.max_output_tokens=="number"&&(s.max_output_tokens=e.max_output_tokens),s}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 t=e,n=t.body??{};return{type:"error",error:{type:"urun_error",code:t.code??null,message:n.message??"unknown error"}}}return{type:"error",error:{type:"urun_error",code:null,message:String(e)}}}var me="llm-resp";async function*I(e,t){let n=`${me}:${t}`,s=`resp_${t}`;yield{type:"response.created",response:{id:s,status:"in_progress"}};for await(let r of e.stream(n).messages()){let o=r;if(o.t==="delta")yield{type:"response.output_text.delta",item_id:s,delta:o.delta};else if(o.t==="response"){yield{type:"response.completed",response:{id:s,status:"completed",...o.body}};return}else if(o.t==="error"){yield G(o);return}}}var fe="llm",x=class{constructor(t){this.session=t}session;get consumerId(){return this.session.consumerId}write(t){this.session.doc(fe).set({requests:{[t.request_id]:{payload:t,consumer_id:t.consumer_id,stream:t.stream}}})}sendResponses(t,n){let s=W(t,n,this.consumerId);return this.write(s),I(this.session,n)}sendResponseCreate(t,n,s){let r=q(t,n,s,this.consumerId);return this.write(r),I(this.session,s)}};var J=0;function ge(){return J+=1,`req_${Date.now().toString(36)}_${J.toString(36)}`}var R=class{transport;constructor(t){this.transport=new x(t)}responses={create:async t=>{let n=ge(),s=this.transport.sendResponses(t,n);return Object.assign((async function*(){yield*s})(),{requestId:n})}}};var L="https://api.urun.sh/v1";async function B(e){let t=e.fetchImpl??fetch,n=`${e.apiUrl.replace(/\/+$/,"")}/apps`,s=await t(n,{headers:{Authorization:`Bearer ${e.apiKey}`,Accept:"application/json"}});if(!s.ok)throw new Error(`org apps listing failed: GET ${n} \u2192 ${s.status}`);let r=await s.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 Y(e){let t=await B(e),n=t.filter(s=>s.function_name===e.fnName&&s.deployment_status==="active").map(s=>s.app_slug);if(n.length===0)throw new Error(`urun pi extension: the org has no active deployed app exposing "${e.fnName}" (GET ${e.apiUrl}/apps returned ${t.length} app(s), none servable) \u2014 deploy one with \`urun serve <model>\` first`);return n.sort()}var M="urun-serve",ye="serve",he=131072,we=16384,H=3,ve=42e4,_e=6e4,be=15e3;function Ae(e){let t=(e.URUN_API_KEY??"").trim();if(!t)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:t,apiUrl:(e.URUN_API_URL??"").trim()||L,fnName:(e.URUN_FUNCTION??"").trim()||ye}}function z(e){let t=(e.URUN_BASE_URL??"").trim(),n=(e.URUN_ORG_ID??"").trim();if(!t)throw new Error("urun pi extension: URUN_BASE_URL is required to open a session");if(/\/v1\/*$/.test(new URL(t).pathname))throw new Error(`urun pi extension: URUN_BASE_URL must be the session-gateway base (e.g. https://api.urun.sh), got ${t} \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 s=(e.URUN_JWT??"").trim();if(s)return{baseUrl:t,orgId:n,auth:{lane:"jwt",jwt:s}};let r=(e.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 o=(e.URUN_GATEWAY_URL??"").trim()||void 0;return{baseUrl:t,orgId:n,auth:{lane:"api-key",apiKey:r,gatewayUrl:o}}}function Q(e){return async(t,n,s)=>{let{baseUrl:r,orgId:o,auth:a}=z(t),{App:u,createClientToken:d}=await e(),i=(a.lane==="jwt"?u(n,{baseUrl:r,orgId:o,jwt:a.jwt}):u(n,{baseUrl:r,orgId:o,getAccessToken:async()=>(await d(a.apiKey,{baseUrl:a.gatewayUrl,expiresIn:300,allowedFunctions:[`${n}/${s}`]})).token}))[s];if(typeof i!="function")throw new Error(`urun pi extension: app "${n}" has no function "${s}"`);let m=i(),c=m.connect;return typeof c=="function"&&await c.call(m),m}}var Ee=Q(async()=>{let{createRequire:e}=await import("module"),t=e(l);if(typeof globalThis.RTCPeerConnection>"u")try{t.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 t("@urun-sh/core")});function xe(e){try{Promise.resolve(e.close?.()).catch(()=>{})}catch{}}var k=class{constructor(t,n,s){this.open=t;this.env=n;this.fnName=s}open;env;fnName;pool=new Map;acquire(t){let n=this.pool.get(t);if(!n){let s=Promise.resolve(this.open(this.env,t,this.fnName)).then(r=>({session:r,responses:new R(r)}));n=s,this.pool.set(t,s),s.catch(()=>{this.pool.get(t)===s&&this.pool.delete(t)})}return n}evict(t){let n=this.pool.get(t);n&&(this.pool.delete(t),n.then(s=>xe(s.session),()=>{}))}closeAll(){for(let t of[...this.pool.keys()])this.evict(t)}};function V(e){let t=[];e.systemPrompt&&t.push({role:"system",content:e.systemPrompt});for(let n of e.messages){let s=n.role==="assistant"?"assistant":"user";t.push({role:s,content:Re(n.content)})}return Z(t)}function Z(e){let t=[];for(let n of e){let s=t[t.length-1];s&&s.role===n.role?s.content=[s.content,n.content].filter(r=>r.length>0).join(`
1
+ "use strict";var xe=Object.create;var M=Object.defineProperty;var ke=Object.getOwnPropertyDescriptor;var be=Object.getOwnPropertyNames;var Ae=Object.getPrototypeOf,Se=Object.prototype.hasOwnProperty;var Ee=(t,e)=>{for(var n in e)M(t,n,{get:e[n],enumerable:!0})},ee=(t,e,n,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let r of be(e))!Se.call(t,r)&&r!==n&&M(t,r,{get:()=>e[r],enumerable:!(o=ke(e,r))||o.enumerable});return t};var te=(t,e,n)=>(n=t!=null?xe(Ae(t)):{},ee(e||!t||!t.__esModule?M(n,"default",{value:t,enumerable:!0}):n,t)),Re=t=>ee(M({},"__esModule",{value:!0}),t);var tt={};Ee(tt,{SessionPool:()=>O,URUN_API:()=>Y,coalesceSameRole:()=>he,createFileDiagnosticSink:()=>me,createUrunExtension:()=>_e,default:()=>et,makeSessionFactory:()=>fe,makeStreamSimple:()=>we,piDiagnosticLogPath:()=>ge,resolveSessionEnv:()=>de,toResponsesInput:()=>ye});module.exports=Re(tt);var Te=()=>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,_=Te();var ce=require("@earendil-works/pi-ai"),R=require("fs"),ue=te(require("os"),1),j=require("path");function ne(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 oe(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 re(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 Ue="llm-resp";async function*G(t,e){let n=`${Ue}:${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 re(i);return}}}var Ie="llm",N=class{constructor(e){this.session=e}session;get consumerId(){return this.session.consumerId}write(e){this.session.doc(Ie).set({requests:{[e.request_id]:{payload:e,consumer_id:e.consumer_id,stream:e.stream}}})}sendResponses(e,n){let o=oe(e,n,this.consumerId);return this.write(o),G(this.session,n)}sendResponseCreate(e,n,o){let r=ne(e,n,o,this.consumerId);return this.write(r),G(this.session,o)}};var se=0;function Pe(){return se+=1,`req_${Date.now().toString(36)}_${se.toString(36)}`}var D=class{transport;constructor(e){this.transport=new N(e)}responses={create:async e=>{let n=Pe(),o=this.transport.sendResponses(e,n);return Object.assign((async function*(){yield*o})(),{requestId:n})}}};var B="https://api.urun.sh/v1";async function ie(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 ae(t){let e=await ie(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",Ce="serve",Le=131072,$e=16384,le=3,Me=42e4,Ne=6e4,De=15e3;function Oe(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()||B,fnName:(t.URUN_FUNCTION??"").trim()||Ce}}function de(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 me(t){let e=null;return n=>{e===null&&((0,R.mkdirSync)((0,j.dirname)(t),{recursive:!0}),e=(0,R.openSync)(t,"a"));let o=n.detail?` ${JSON.stringify(n.detail)}`:"";(0,R.writeSync)(e,`${new Date().toISOString()} [${n.level}] [urun] ${n.message}${o}
2
+ `)}}function ge(t=ue.default.homedir()){return(0,j.join)(t,".urun","logs","pi-extension.log")}function fe(t){let e=me(ge());return async(n,o,r)=>{let{baseUrl:l,orgId:i,auth:p}=de(n),{App:m,createClientToken:a}=await t(),v=(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 v!="function")throw new Error(`urun pi extension: app "${o}" has no function "${r}"`);let h=v(),T=h.connect;return typeof T=="function"&&await T.call(h),h}}var je=fe(async()=>{let{createRequire:t}=await import("module"),e=t(_);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 Fe(t){try{Promise.resolve(t.close?.()).catch(()=>{})}catch{}}var O=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 D(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=>Fe(o.session),()=>{}))}closeAll(){for(let e of[...this.pool.keys()])this.evict(e)}};function ye(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:qe(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:Ke(n.content)})}return he(e)}function he(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(`
2
3
 
3
- `):t.push({...n})}return t}function Re(e){return typeof e=="string"?e:Array.isArray(e)?e.map(t=>t&&typeof t=="object"&&"text"in t?String(t.text):"").join(""):""}function ke(e){let t=e instanceof Error?e.message:String(e),n=e?.code;return/\b529\b/.test(t)||/overloaded/i.test(t)||n===529||n==="529"}function Se(e){return new Promise(t=>setTimeout(t,e))}function Ue(e,t,n,s){return new Promise((r,o)=>{let a=!1,u=i=>{a||(a=!0,clearTimeout(d),s?.removeEventListener("abort",p),i())},d=setTimeout(()=>u(()=>o(n())),t),p=()=>u(()=>o(new Error("aborted")));if(s?.aborted){p();return}s?.addEventListener("abort",p,{once:!0}),Promise.resolve(e).then(i=>u(()=>r(i)),i=>u(()=>o(i)))})}async function*Pe(e,t){let n=e[Symbol.asyncIterator](),s,r=new Promise((o,a)=>{s=()=>a(new Error("aborted")),t.addEventListener("abort",s,{once:!0})});try{for(;;){if(t.aborted)throw new Error("aborted");let o=await Promise.race([n.next(),r]);if(o.done)return;yield o.value}}finally{s&&t.removeEventListener("abort",s),n.return?.(void 0)}}function Te(e,t){let n=e?.sendMessage;if(typeof n=="function")try{n.call(e,{customType:"urun-status",content:t,display:!0},{triggerTurn:!1})}catch{}}function ee(e,t={},n){let s=t.connectDeadlineMs??ve,r=t.stallTimeoutMs??_e,o=t.phaseHeartbeatMs??be;return(a,u,d)=>{let p=(0,X.createAssistantMessageEventStream)(),i={role:"assistant",content:[{type:"text",text:""}],api:a.api,provider:a.provider,model:a.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=i.content[0],c=new AbortController,f=d?.signal,$=!1,S=()=>{$=!0,c.abort()};f&&(f.aborted?S():f.addEventListener("abort",S,{once:!0}));let U=!1,h,N=()=>{h&&clearTimeout(h),h=setTimeout(()=>{U=!0,c.abort()},r)},P=()=>{h&&clearTimeout(h),h=void 0};return(async()=>{p.push({type:"start",partial:i}),p.push({type:"text_start",contentIndex:0,partial:i});let C=!1,_,D=()=>{_&&clearInterval(_),_=void 0},ne=Date.now();_=setInterval(()=>{let g=Math.round((Date.now()-ne)/1e3);Te(n,`uRun: still opening the "${a.id}" session\u2026 (${g}s \u2014 serve apps scale to zero, first turn can cold-start ~6min)`)},o);try{let{responses:g}=await Ue(e.acquire(a.id),s,()=>new Error(`uRun session for "${a.id}" did not connect within ${Math.round(s/1e3)}s \u2014 likely cold-starting (scaled to zero) or queued behind capacity. Retry shortly.`),c.signal);D();let T=V(u),O,b;for(let A=1;A<=H;A++)try{let w=await g.responses.create({model:a.id,input:T,stream:!0,max_output_tokens:a.maxTokens});N();for await(let se of Pe(w,c.signal)){N();let y=se;if(y.type==="response.output_text.delta"){let v=typeof y.delta=="string"?y.delta:"";v&&(m.text+=v,p.push({type:"text_delta",contentIndex:0,delta:v,partial:i}))}else if(y.type==="response.completed"){O=y.response;break}else if(y.type==="error"){let v=y.error,F=new Error(`uRun serve error: ${v?.message??"unknown error"}`);throw F.code=v?.code??null,F}}b=void 0;break}catch(w){if(b=w,c.signal.aborted)throw w;if(A<H&&ke(w)&&m.text.length===0){await Se(A*500);continue}throw w}if(b)throw b;P(),p.push({type:"text_end",contentIndex:0,content:m.text,partial:i});let j=O?.status==="incomplete"?"length":"stop";i.stopReason=j,p.push({type:"done",reason:j,message:i}),p.end(i)}catch(g){if(C=!0,P(),$||f?.aborted&&!U)i.stopReason="aborted",i.errorMessage="aborted by user",p.push({type:"error",reason:"aborted",error:i});else{let T=U?`uRun stream stalled \u2014 no output for ${Math.round(r/1e3)}s; the model may be hung. Retry, or Ctrl-C to abort.`:g instanceof Error?g.message:String(g);i.stopReason="error",i.errorMessage=T,p.push({type:"error",reason:"error",error:i})}p.end(i)}finally{P(),D(),f&&f.removeEventListener("abort",S),C&&e.evict(a.id)}})(),p}}function Ie(e){return{id:e,name:`uRun ${e}`,api:M,reasoning:!1,input:["text"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:he,maxTokens:we}}function te(e={}){return async t=>{let n=e.env??process.env,{apiKey:s,apiUrl:r,fnName:o}=Ae(n),a=await Y({apiUrl:r,apiKey:s,fnName:o,fetchImpl:e.fetchImpl}),u=new k(e.openSession??Ee,n,o);t.on("session_shutdown",()=>u.closeAll());let d={name:"uRun",api:M,baseUrl:"urun://session",apiKey:"$URUN_API_KEY",models:a.map(Ie),streamSimple:ee(u,e.timing??{},t)};t.registerProvider("urun",d)}}var Le=te();0&&(module.exports={SessionPool,URUN_API,coalesceSameRole,createUrunExtension,makeSessionFactory,makeStreamSimple,resolveSessionEnv,toResponsesInput});
4
+ `):e.push({...n})}return e}function Ke(t){return typeof t=="string"?t:Array.isArray(t)?t.map(e=>e&&typeof e=="object"&&"text"in e?String(e.text):"").join(""):""}function qe(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 We(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 Je(t){let e=t?.output;return Array.isArray(e)?e.filter(n=>n.type==="function_call"):[]}function Ge(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 Be=["<tool_call>","<function="];function Ye(t,e){let n=Be.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)`)}function He(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 Xe(t){return new Promise(e=>setTimeout(e,t))}function ze(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*Qe(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 Ve(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 we(t,e={},n){let o=e.connectDeadlineMs??Me,r=e.stallTimeoutMs??Ne,l=e.phaseHeartbeatMs??De;return(i,p,m)=>{let a=(0,ce.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()},v=new AbortController,h=m?.signal,T=!1,P=()=>{T=!0,v.abort()};h&&(h.aborted?P():h.addEventListener("abort",P,{once:!0}));let F=!1,S,H=()=>{S&&clearTimeout(S),S=setTimeout(()=>{F=!0,v.abort()},r)},K=()=>{S&&clearTimeout(S),S=void 0},x=null,k=null,f=null,X="",C=!1,q=()=>{if(!k)return;let d=k;k=null,a.push({type:"thinking_end",contentIndex:s.content.indexOf(d),content:d.thinking,partial:s})},z=()=>{if(!x)return;let d=x;x=null,a.push({type:"text_end",contentIndex:s.content.indexOf(d),content:d.text,partial:s})},W=()=>{if(!f)return;let{call:d,args:y,contentIndex:b}=f;f=null,d.arguments=pe(d.name,y),a.push({type:"toolcall_end",contentIndex:b,toolCall:d,partial:s})},ve=d=>{let y={type:"toolCall",id:String(d.call_id??d.id??`call_${s.content.length}`),name:String(d.name??""),arguments:{}};s.content.push(y);let b=s.content.length-1;a.push({type:"toolcall_start",contentIndex:b,partial:s});let U=typeof d.arguments=="string"?d.arguments:"";U&&a.push({type:"toolcall_delta",contentIndex:b,delta:U,partial:s}),y.arguments=pe(y.name,U),a.push({type:"toolcall_end",contentIndex:b,toolCall:y,partial:s})};return(async()=>{a.push({type:"start",partial:s});let d=!1,y,b=()=>{y&&clearInterval(y),y=void 0},U=Date.now();y=setInterval(()=>{let A=Math.round((Date.now()-U)/1e3);Ve(n,`uRun: still opening the "${i.id}" session\u2026 (${A}s \u2014 serve apps scale to zero, first turn can cold-start ~6min)`)},l);try{let{responses:A}=await ze(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.`),v.signal);b();let J=ye(p),L,$;for(let u=1;u<=le;u++)try{let w=await A.responses.create({model:i.id,input:J,stream:!0,tools:We(p.tools),max_output_tokens:i.maxTokens});H();for await(let I of Qe(w,v.signal)){H();let g=I;if(g.type==="response.output_text.delta"){let c=typeof g.delta=="string"?g.delta:"";c&&(C=!0,q(),W(),x||(x={type:"text",text:""},s.content.push(x),a.push({type:"text_start",contentIndex:s.content.length-1,partial:s})),x.text+=c,X+=c,a.push({type:"text_delta",contentIndex:s.content.indexOf(x),delta:c,partial:s}))}else if(g.type==="response.reasoning_text.delta"){let c=typeof g.delta=="string"?g.delta:"";c&&(C=!0,k||(k={type:"thinking",thinking:""},s.content.push(k),a.push({type:"thinking_start",contentIndex:s.content.length-1,partial:s})),k.thinking+=c,a.push({type:"thinking_delta",contentIndex:s.content.indexOf(k),delta:c,partial:s}))}else if(g.type==="response.function_call_arguments.delta"&&typeof g.tool_index=="number"){let c=g;if(C=!0,q(),z(),!f||f.toolIndex!==c.tool_index){W();let Z={type:"toolCall",id:c.call_id??`call_${c.tool_index}`,name:c.name??"",arguments:{}};s.content.push(Z),f={call:Z,args:"",contentIndex:s.content.length-1,toolIndex:c.tool_index},a.push({type:"toolcall_start",contentIndex:f.contentIndex,partial:s})}c.call_id&&(f.call.id=c.call_id),c.name&&(f.call.name=c.name);let E=typeof c.delta=="string"?c.delta:"";E&&(f.args+=E,a.push({type:"toolcall_delta",contentIndex:f.contentIndex,delta:E,partial:s}))}else if(g.type==="response.completed"){L=g.response;break}else if(g.type==="error"){let c=g.error,E=new Error(`uRun serve error: ${c?.message??"unknown error"}`);throw E.code=c?.code??null,E}}$=void 0;break}catch(w){if($=w,v.signal.aborted)throw w;if(u<le&&He(w)&&!C){await Xe(u*500);continue}throw w}if($)throw $;if(K(),q(),z(),W(),!s.content.some(u=>u.type==="toolCall"))for(let u of Je(L))ve(u);if(!s.content.some(u=>u.type==="thinking")){let u=Ge(L);if(u){let w={type:"thinking",thinking:""};s.content.push(w);let I=s.content.length-1;a.push({type:"thinking_start",contentIndex:I,partial:s}),w.thinking=u,a.push({type:"thinking_delta",contentIndex:I,delta:u,partial:s}),a.push({type:"thinking_end",contentIndex:I,content:u,partial:s})}}let Q=s.content.filter(u=>u.type==="toolCall").length;if((p.tools?.length??0)>0&&Q===0){let u=Ye(i.id,X);if(u)throw u}let V=Q>0?"toolUse":L?.status==="incomplete"?"length":"stop";s.stopReason=V,a.push({type:"done",reason:V,message:s}),a.end(s)}catch(A){if(d=!0,K(),T||h?.aborted&&!F)s.stopReason="aborted",s.errorMessage="aborted by user",a.push({type:"error",reason:"aborted",error:s});else{let J=F?`uRun stream stalled \u2014 no output for ${Math.round(r/1e3)}s; the model may be hung. Retry, or Ctrl-C to abort.`:A instanceof Error?A.message:String(A);s.stopReason="error",s.errorMessage=J,a.push({type:"error",reason:"error",error:s})}a.end(s)}finally{K(),b(),h&&h.removeEventListener("abort",P),d&&t.evict(i.id)}})(),a}}function Ze(t){return{id:t,name:`uRun ${t}`,api:Y,reasoning:!0,input:["text"],cost:{input:0,output:0,cacheRead:0,cacheWrite:0},contextWindow:Le,maxTokens:$e}}function _e(t={}){return async e=>{let n=t.env??process.env,{apiKey:o,apiUrl:r,fnName:l}=Oe(n),i=await ae({apiUrl:r,apiKey:o,fnName:l,fetchImpl:t.fetchImpl}),p=new O(t.openSession??je,n,l);e.on("session_shutdown",()=>p.closeAll());let m={name:"uRun",api:Y,baseUrl:"urun://session",apiKey:"$URUN_API_KEY",models:i.map(Ze),streamSimple:we(p,t.timing??{},e)};e.registerProvider("urun",m)}}var et=_e();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-CQ3l8Wft.cjs';
3
+ import { a as UrunSessionLike, U as UrunResponses } from '../ResponsesClient-DF39QXq1.cjs';
4
4
 
5
5
  /**
6
6
  * Pi coding-agent extension: register the `urun` model provider, with one pi
@@ -40,13 +40,16 @@ import { a as UrunSessionLike, U as UrunResponses } from '../ResponsesClient-CQ3
40
40
  * empty provider.
41
41
  * 2. `streamSimple` (pi's custom-API hook, keyed by `api: "urun-serve"`):
42
42
  * opens ONE uRun session per app slug, POOLED and reused across turns,
43
- * translates pi's Context into Responses `input` items, drives
44
- * `UrunResponses.responses.create({stream: true})`, and maps
45
- * `response.output_text.delta` events into pi `text_delta` events.
46
- * Text-only, matching the precedent extension's fidelity (no tool-call
47
- * streaming through the serve lane; pi's toolResult turns are folded
48
- * into user-role input items the Responses `function_call_output` item
49
- * form needs call ids this lane never emits).
43
+ * translates pi's Context into Responses `input` items (tool loop
44
+ * included: assistant `toolCall` content → `function_call` items,
45
+ * `toolResult` turns `function_call_output` items), forwards
46
+ * `context.tools` upstream, drives
47
+ * `UrunResponses.responses.create({stream: true})`, and maps the lane's
48
+ * decoded events onto pi-ai's REAL AssistantMessageEvent union:
49
+ * output_text text_*, reasoning_text thinking_*, function-call
50
+ * argument fragments → toolcall_* (stopReason "toolUse" ends a
51
+ * tool-calling turn, which is what makes pi's agent loop execute the
52
+ * tools and feed results back).
50
53
  * 3. ABORT/CANCEL (loud contract): the Responses lane has NO request-cancel
51
54
  * primitive (`SdkTransport.sendResponses` writes an envelope and the
52
55
  * decode loop just reads the reply lane), so Ctrl-C / the stall watchdog
@@ -117,6 +120,13 @@ declare function resolveSessionEnv(env: NodeJS.ProcessEnv): {
117
120
  interface SessionFactory {
118
121
  (env: NodeJS.ProcessEnv, appSlug: string, fnName: string): Promise<UrunSessionLike> | UrunSessionLike;
119
122
  }
123
+ /** The structured diagnostic shape core's transports emit (typed locally). */
124
+ interface CoreDiagnosticLike {
125
+ level: string;
126
+ kind: string;
127
+ message: string;
128
+ detail?: Record<string, unknown>;
129
+ }
120
130
  /**
121
131
  * The subset of `@urun-sh/core` a session factory needs — typed locally so
122
132
  * core stays OUT of this module's static import graph (the npm lane resolves
@@ -128,6 +138,7 @@ interface CoreModuleLike {
128
138
  orgId: string;
129
139
  jwt?: string;
130
140
  getAccessToken?: () => Promise<string>;
141
+ diagnosticSink?: (diagnostic: CoreDiagnosticLike) => void;
131
142
  }) => Record<string, (args?: Record<string, unknown>) => UrunSessionLike>;
132
143
  createClientToken: (apiKey: string, opts: {
133
144
  baseUrl?: string;
@@ -149,6 +160,16 @@ interface CoreModuleLike {
149
160
  * self-contained bundle INLINES core (and, through core's own dynamic
150
161
  * werift import, the WebRTC backend) — that lane has no node_modules.
151
162
  */
163
+ /**
164
+ * A diagnostic sink appending formatted lines to `path` — SYNCHRONOUS writes
165
+ * (a crashing pi must still leave the lines on disk), lazy directory
166
+ * creation, one open descriptor per sink. An open/write failure THROWS: core's
167
+ * `_emitDiagnostic` catches it, complains once on the console, and keeps the
168
+ * structured event flowing — loud once, never TUI spam, never silent.
169
+ */
170
+ declare function createFileDiagnosticSink(path: string): (diagnostic: CoreDiagnosticLike) => void;
171
+ /** Where the pi lane's quiet diagnostics land (the compat log convention). */
172
+ declare function piDiagnosticLogPath(home?: string): string;
152
173
  declare function makeSessionFactory(loadCore: () => Promise<CoreModuleLike> | CoreModuleLike): SessionFactory;
153
174
  /** One pooled backhaul: the session plus its Responses client (cli.ts shape). */
154
175
  interface PoolEntry {
@@ -174,22 +195,36 @@ declare class SessionPool {
174
195
  /** Release everything (pi session_shutdown). */
175
196
  closeAll(): void;
176
197
  }
177
- /** A Responses input item (message form; content stays a plain string). */
178
- interface ResponsesInputItem {
198
+ /** A Responses input item: role message or function-call round-trip item. */
199
+ type ResponsesInputItem = {
179
200
  role: 'system' | 'user' | 'assistant';
180
201
  content: string;
181
- }
202
+ } | {
203
+ type: 'function_call';
204
+ call_id: string;
205
+ name: string;
206
+ arguments: string;
207
+ } | {
208
+ type: 'function_call_output';
209
+ call_id: string;
210
+ output: string;
211
+ };
182
212
  /**
183
- * Pi `Context` -> Responses `input` items. Pi models tool results as
184
- * `role:"toolResult"`; the Responses item form for those
185
- * (`{type:'function_call_output', call_id, …}`) needs call ids this text-only
186
- * lane never emits, so tool results are folded into `user`-role items, then
187
- * any consecutive same-role runs are coalesced into one item so a chat
188
- * template that assumes strict role alternation never sees two turns of the
189
- * same role back-to-back (same rationale as the precedent extension).
213
+ * Pi `Context` -> Responses `input` items, in ENCOUNTER ORDER (the tool
214
+ * loop's canonical Responses shapes the same translation the compat proxy
215
+ * performs):
216
+ * - assistant `toolCall` content `{type:'function_call', call_id, name,
217
+ * arguments}` (arguments re-serialized: pi stores the PARSED object);
218
+ * - `role:"toolResult"` turns `{type:'function_call_output', call_id,
219
+ * output}` keyed by pi's `toolCallId`;
220
+ * - assistant `thinking` content is the producing model's internal state —
221
+ * not re-submittable — and is skipped by design (same rule as the proxy);
222
+ * - text runs become role messages where they sit; adjacent same-role
223
+ * messages are coalesced so chat templates that assume strict role
224
+ * alternation never see two turns of one role back-to-back.
190
225
  */
191
226
  declare function toResponsesInput(context: Context): ResponsesInputItem[];
192
- /** Fold consecutive same-role items into one, joining with a blank line. */
227
+ /** Fold consecutive same-role message items into one, joining with a blank line. */
193
228
  declare function coalesceSameRole(items: ResponsesInputItem[]): ResponsesInputItem[];
194
229
  /** Tunable timeouts (overridable so tests can drive them deterministically). */
195
230
  interface StreamTiming {
@@ -219,4 +254,4 @@ declare function createUrunExtension(opts?: UrunExtensionOptions): (pi: Extensio
219
254
  /** The pi extension factory (default export — what pi's loader invokes). */
220
255
  declare const _default: (pi: ExtensionAPI) => Promise<void>;
221
256
 
222
- export { type CoreModuleLike, type ResponsesInputItem, type SessionFactory, SessionPool, type StreamTiming, URUN_API, type UrunExtensionOptions, coalesceSameRole, createUrunExtension, _default as default, makeSessionFactory, makeStreamSimple, resolveSessionEnv, toResponsesInput };
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 };
@@ -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-CQ3l8Wft.js';
3
+ import { a as UrunSessionLike, U as UrunResponses } from '../ResponsesClient-DF39QXq1.js';
4
4
 
5
5
  declare const URUN_API: Api;
6
6
 
@@ -21,12 +21,20 @@ interface SessionFactory {
21
21
  (env: NodeJS.ProcessEnv, appSlug: string, fnName: string): Promise<UrunSessionLike> | UrunSessionLike;
22
22
  }
23
23
 
24
+ interface CoreDiagnosticLike {
25
+ level: string;
26
+ kind: string;
27
+ message: string;
28
+ detail?: Record<string, unknown>;
29
+ }
30
+
24
31
  interface CoreModuleLike {
25
32
  App: (id: string, opts: {
26
33
  baseUrl: string;
27
34
  orgId: string;
28
35
  jwt?: string;
29
36
  getAccessToken?: () => Promise<string>;
37
+ diagnosticSink?: (diagnostic: CoreDiagnosticLike) => void;
30
38
  }) => Record<string, (args?: Record<string, unknown>) => UrunSessionLike>;
31
39
  createClientToken: (apiKey: string, opts: {
32
40
  baseUrl?: string;
@@ -37,6 +45,9 @@ interface CoreModuleLike {
37
45
  }>;
38
46
  }
39
47
 
48
+ declare function createFileDiagnosticSink(path: string): (diagnostic: CoreDiagnosticLike) => void;
49
+
50
+ declare function piDiagnosticLogPath(home?: string): string;
40
51
  declare function makeSessionFactory(loadCore: () => Promise<CoreModuleLike> | CoreModuleLike): SessionFactory;
41
52
 
42
53
  interface PoolEntry {
@@ -57,10 +68,19 @@ declare class SessionPool {
57
68
  closeAll(): void;
58
69
  }
59
70
 
60
- interface ResponsesInputItem {
71
+ type ResponsesInputItem = {
61
72
  role: 'system' | 'user' | 'assistant';
62
73
  content: string;
63
- }
74
+ } | {
75
+ type: 'function_call';
76
+ call_id: string;
77
+ name: string;
78
+ arguments: string;
79
+ } | {
80
+ type: 'function_call_output';
81
+ call_id: string;
82
+ output: string;
83
+ };
64
84
 
65
85
  declare function toResponsesInput(context: Context): ResponsesInputItem[];
66
86
 
@@ -85,4 +105,4 @@ declare function createUrunExtension(opts?: UrunExtensionOptions): (pi: Extensio
85
105
 
86
106
  declare const _default: (pi: ExtensionAPI) => Promise<void>;
87
107
 
88
- export { type CoreModuleLike, type ResponsesInputItem, type SessionFactory, SessionPool, type StreamTiming, URUN_API, type UrunExtensionOptions, coalesceSameRole, createUrunExtension, _default as default, makeSessionFactory, makeStreamSimple, resolveSessionEnv, toResponsesInput };
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 };