@urun-sh/openai 0.2.53 → 0.2.55

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@urun-sh/openai",
3
- "version": "0.2.53",
3
+ "version": "0.2.55",
4
4
  "description": "OpenAI-compatible Realtime + Responses SDK over uRun session primitives (not websockets).",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -1,62 +0,0 @@
1
- /** The narrow subset of @urun-sh/core's Session the SDK depends on. */
2
- interface UrunDocLike {
3
- set(patch: Record<string, unknown>): void;
4
- get(path?: string, defaultValue?: unknown): unknown;
5
- on(event: 'change', handler: (snapshot: Record<string, unknown>) => void): () => void;
6
- }
7
- interface UrunStreamLike {
8
- messages(): AsyncIterable<unknown>;
9
- attach(track: unknown): Promise<void>;
10
- detach(): Promise<void>;
11
- readonly track: unknown;
12
- /**
13
- * Subscribe to the named media track (de)appearing. The downstream audio track
14
- * is consumed ASYNCHRONOUSLY after the WebRTC handshake, so `track` may be null
15
- * at `enableAudio()` time; this fires with the real `MediaStreamTrack` the
16
- * moment the consumer attaches (core `SessionStream.on('track')`). Optional so
17
- * non-media test doubles need not implement it.
18
- */
19
- on?(event: 'track', handler: (track: unknown) => void): () => void;
20
- }
21
- interface UrunSessionLike {
22
- /** Per-leg consumer identity (core: transport.consumerId). */
23
- readonly consumerId: string;
24
- doc(key: string): UrunDocLike;
25
- stream(name: string): UrunStreamLike;
26
- close?(): Promise<void> | void;
27
- }
28
- /** Lane message shape emitted by the serve runtime (core session.ts:83). */
29
- type LaneMessage = {
30
- t: 'delta';
31
- request_id?: string;
32
- delta: string;
33
- } | {
34
- t: 'response';
35
- request_id?: string;
36
- body: unknown;
37
- } | {
38
- t: 'error';
39
- request_id?: string;
40
- body: unknown;
41
- code?: string;
42
- };
43
-
44
- interface ResponsesStream extends AsyncIterable<unknown> {
45
- readonly requestId: string;
46
- }
47
- declare class UrunResponses {
48
- private readonly transport;
49
- constructor(session: UrunSessionLike);
50
- readonly responses: {
51
- create: (params: {
52
- model?: string;
53
- input: unknown;
54
- stream?: boolean;
55
- tools?: unknown;
56
- temperature?: number;
57
- max_output_tokens?: number;
58
- }) => Promise<ResponsesStream>;
59
- };
60
- }
61
-
62
- export { type LaneMessage as L, UrunResponses as U, type UrunSessionLike as a };
@@ -1 +0,0 @@
1
- function m(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,t=n.body??{};return{type:"error",error:{type:"urun_error",code:n.code??null,message:t.message??"unknown error"}}}return{type:"error",error:{type:"urun_error",code:null,message:String(e)}}}function c(e,n,t,r){let s=e.response??{},o={request_id:t,consumer_id:r,stream:!0,kind:"chat",messages:n};return typeof s.instructions=="string"&&(o.instructions=s.instructions),Array.isArray(s.modalities)&&(o.modalities=s.modalities),typeof s.temperature=="number"&&(o.temperature=s.temperature),typeof s.max_output_tokens=="number"&&(o.max_output_tokens=s.max_output_tokens),s.tools!==void 0&&(o.tools=s.tools),o}function d(e,n,t){let r={request_id:n,consumer_id:t,stream:!!e.stream,kind:"responses",input:e.input};return e.model&&(r.model=e.model),e.tools!==void 0&&(r.tools=e.tools),typeof e.temperature=="number"&&(r.temperature=e.temperature),typeof e.max_output_tokens=="number"&&(r.max_output_tokens=e.max_output_tokens),r}var g="llm-resp";async function*a(e,n){let t=`${g}:${n}`,r=`resp_${n}`;yield{type:"response.created",response:{id:r,status:"in_progress"}};for await(let s of e.stream(t).messages()){let o=s;if(o.t==="delta")yield{type:"response.output_text.delta",item_id:r,delta:o.delta};else if(o.t==="response"){yield{type:"response.completed",response:{id:r,status:"completed",...o.body}};return}else if(o.t==="error"){yield m(o);return}}}var _="llm",p=class{constructor(n){this.session=n}session;get consumerId(){return this.session.consumerId}write(n){this.session.doc(_).set({requests:{[n.request_id]:{payload:n,consumer_id:n.consumer_id,stream:n.stream}}})}sendResponses(n,t){let r=d(n,t,this.consumerId);return this.write(r),a(this.session,t)}sendResponseCreate(n,t,r){let s=c(n,t,r,this.consumerId);return this.write(s),a(this.session,r)}};var l=0;function k(){return l+=1,`req_${Date.now().toString(36)}_${l.toString(36)}`}var y=class{transport;constructor(n){this.transport=new p(n)}responses={create:async n=>{let t=k(),r=this.transport.sendResponses(n,t);return Object.assign((async function*(){yield*r})(),{requestId:t})}}};export{m as a,p as b,y as c};
@@ -1,21 +0,0 @@
1
- import{b as I}from"./chunk-PS4BLX7J.js";import{createServer as H}from"http";var T=class e{startedAt=Date.now();requests={};models={};ttftMs=[];tokRates=[];tokensOut=0;charsOut=0;localInBytes=0;naiveInBytes=0;request(n,t,r){this.requests[n]=(this.requests[n]??0)+1,this.localInBytes+=t,this.naiveInBytes+=r}modelEntry(n){let t=this.models[n];if(t)return t;let r=Object.keys(this.models).length>=Q?"(other)":n;return this.models[r]??={requests:0,tokens_out:0}}model(n){this.modelEntry(n).requests+=1}track(n,t){let r=this,i=performance.now(),c=null,u=0;return(async function*(){for await(let p of n)p.type==="response.output_text.delta"&&typeof p.delta=="string"&&(c===null&&(c=performance.now(),r.ttftMs.push(c-i),r.ttftMs.length>512&&r.ttftMs.shift()),u+=1,r.tokensOut+=1,r.charsOut+=p.delta.length,t!==void 0&&(r.modelEntry(t).tokens_out+=1)),yield p;let o=(performance.now()-(c??i))/1e3;u>0&&o>0&&(r.tokRates.push(u/o),r.tokRates.length>512&&r.tokRates.shift())})()}static p50(n){if(!n.length)return null;let t=[...n].sort((r,i)=>r-i);return t[Math.floor(t.length/2)]}snapshot(){let n=Object.values(this.requests).reduce((t,r)=>t+r,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 C(e){e.writeHead(200,{"content-type":"text/event-stream","cache-control":"no-cache",connection:"keep-alive"})}function w(e,n,t){e.writeHead(n,{"content-type":"application/json"}),e.end(JSON.stringify(t))}function _(e,n,t,r="invalid_request_error"){w(e,n,{error:{message:t,type:r}})}function j(e,n,t){if(n==="anthropic"){w(e,404,{type:"error",error:{type:"not_found_error",message:t.message}});return}w(e,404,{error:{message:t.message,type:"invalid_request_error",code:"model_not_found"}})}var Q=256,V=128;function D(e){return typeof e.model!="string"||!e.model.trim()?"(default)":e.model.trim().slice(0,V)}var z=64*1024*1024,B=class extends Error{};async function W(e){let n=[],t=0;for await(let i of e){if(t+=i.length,t>z)throw new B(`request body exceeds ${z} bytes`);n.push(i)}let r=Buffer.concat(n).toString("utf8");return r?JSON.parse(r):{}}function $(e,n,t,r){return{id:e,object:"chat.completion.chunk",created:Math.floor(Date.now()/1e3),model:n,choices:[{index:0,delta:t,finish_reason:r}]}}var Z=256;function tt(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 q=class{conversations=new Map;thread(n,t){let r=tt(t);if(n==null)return r;let i=this.conversations.get(String(n));if(!i)throw new Error(`unknown previous_response_id ${String(n)} (proxy restarts drop stored responses)`);return[...i,...r]}remember(n,t,r){this.conversations.set(n,[...t,{role:"assistant",content:r}]);for(let i of this.conversations.keys()){if(this.conversations.size<=Z)break;this.conversations.delete(i)}}};function K(e){let n=e?.output;return Array.isArray(n)?n.filter(t=>t.type==="function_call"):[]}function M(e){return e.find(n=>n.type==="response.completed")?.response??null}function et(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 J=class extends Error{};function nt(e,n){return Array.isArray(n)?n.map(t=>{let r=t;if(r.type==="text")return{type:e==="assistant"?"output_text":"input_text",text:r.text};if(r.type==="image_url"){let i=r.image_url??{};return{type:"input_image",image_url:i.url,detail:i.detail}}throw new J(`unsupported chat content part type "${String(r.type)}" \u2014 the proxy translates text and image_url parts`)}):n}function rt(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 r of t.tool_calls){let i=r.function??{};n.push({type:"function_call",call_id:r.id,name:i.name,arguments:i.arguments})}continue}n.push({...t,content:nt(t.role,t.content)})}return n}function F(e){return K(e).map((n,t)=>({index:t,id:n.call_id??n.id??`call_${t}`,type:"function",function:{name:n.name??"",arguments:n.arguments??"{}"}}))}function U(e,n){let t=n?.output_text;return typeof t=="string"?t:e.filter(r=>r.type==="response.output_text.delta"&&typeof r.delta=="string").map(r=>r.delta).join("")}async function st(e,n,t,r,i){let c=e.stream===!0,u;try{u=t.thread(e.previous_response_id,e.input)}catch(s){_(r,400,String(s instanceof Error?s.message:s));return}e.previous_response_id!=null&&(i.naiveInBytes+=Buffer.byteLength(JSON.stringify(u))-Buffer.byteLength(JSON.stringify(e.input)));let o=`resp_${Math.random().toString(36).slice(2,14)}`,p=e.store!==!1,y=D(e);i.model(y);let l;try{l=await n.createResponse({model:e.model,input:u,stream:c,tools:e.tools,temperature:e.temperature,max_output_tokens:e.max_output_tokens})}catch(s){if(s instanceof I){j(r,"openai",s);return}throw s}let g=[];if(c){C(r);let s=d=>{r.write(`event: ${String(d.type??"message")}
2
- data: ${JSON.stringify(d)}
3
-
4
- `)},a=d=>d.response&&typeof d.response=="object"?{...d,response:{...d.response,id:o}}:d,m=`item_${o.slice(5)}`,R=!1,x=!1,f=!1,A="",S=d=>{f&&(f=!1,s({type:"response.output_text.done",item_id:m,output_index:0,content_index:0,text:A}),s({type:"response.content_part.done",item_id:m,output_index:0,content_index:0,part:{type:"output_text",text:A}}),s({type:"response.output_item.done",output_index:0,item:{id:m,type:"message",role:"assistant",status:d,content:[{type:"output_text",text:A}]}}))};for await(let d of i.track(l,y)){g.push(d);let O=String(d.type??"");if(O==="response.created"||O==="response.in_progress"){R=!0,s(a(d));continue}if(O==="response.output_item.added"){x=!0,s(a(d));continue}if(O==="response.output_text.delta"&&!x){R||(R=!0,s({type:"response.created",response:{id:o,object:"response",status:"in_progress"}})),f||(f=!0,s({type:"response.output_item.added",output_index:0,item:{id:m,type:"message",role:"assistant",status:"in_progress",content:[]}}),s({type:"response.content_part.added",item_id:m,output_index:0,content_index:0,part:{type:"output_text",text:""}})),A+=String(d.delta??""),s({type:O,item_id:m,output_index:0,content_index:0,delta:d.delta});continue}if(O==="response.completed"&&!x){let Y=f;S("completed"),K(d.response).forEach((E,G)=>{let b=(Y?1:0)+G,N=E.id??E.call_id??`fc_${b}`,P=E.arguments??"",L={id:N,type:"function_call",call_id:E.call_id??N,name:E.name??""};s({type:"response.output_item.added",output_index:b,item:{...L,arguments:"",status:"in_progress"}}),s({type:"response.function_call_arguments.delta",item_id:N,output_index:b,delta:P}),s({type:"response.function_call_arguments.done",item_id:N,output_index:b,arguments:P}),s({type:"response.output_item.done",output_index:b,item:{...L,arguments:P,status:"completed"}})}),s(a(d));continue}s(a(d))}S("incomplete"),p&&t.remember(o,u,U(g,M(g))),r.write(`data: [DONE]
5
-
6
- `),r.end();return}let h=null;for await(let s of i.track(l,y)){if(g.push(s),s.type==="error"){_(r,502,JSON.stringify(s),"upstream_error");return}s.type==="response.completed"&&(h=s.response)}if(h==null){_(r,502,"upstream produced no response.completed event","upstream_error");return}let k=U(g,h);p&&t.remember(o,u,k),w(r,200,{...h,id:o})}async function ot(e,n,t,r){let i=e.messages;if(!Array.isArray(i)){_(t,400,"chat/completions requires a messages array");return}let c=String(e.model??"urun"),u=`chatcmpl-${Math.random().toString(36).slice(2,14)}`,o;try{o=rt(i)}catch(s){if(s instanceof J){_(t,400,s.message);return}throw s}let p=D(e);r.model(p);let y;try{y=await n.createResponse({model:e.model,input:o,stream:!0,tools:et(e.tools),temperature:e.temperature,max_output_tokens:e.max_completion_tokens??e.max_tokens})}catch(s){if(s instanceof I){j(t,"openai",s);return}throw s}if(e.stream===!0){C(t);let s=[];t.write(`data: ${JSON.stringify($(u,c,{role:"assistant"},null))}
7
-
8
- `);for await(let m of r.track(y,p))if(s.push(m),m.type==="response.output_text.delta"&&typeof m.delta=="string")t.write(`data: ${JSON.stringify($(u,c,{content:m.delta},null))}
9
-
10
- `);else if(m.type==="error"){t.write(`data: ${JSON.stringify({error:m})}
11
-
12
- `),t.end();return}let a=F(M(s));a.length>0&&t.write(`data: ${JSON.stringify($(u,c,{tool_calls:a},null))}
13
-
14
- `),t.write(`data: ${JSON.stringify($(u,c,{},a.length>0?"tool_calls":"stop"))}
15
-
16
- `),t.write(`data: [DONE]
17
-
18
- `),t.end();return}let l="",g=[];for await(let s of r.track(y,p))if(g.push(s),s.type==="response.output_text.delta"&&typeof s.delta=="string"&&(l+=s.delta),s.type==="error"){_(t,502,JSON.stringify(s),"upstream_error");return}let h=F(M(g)).map(({index:s,...a})=>a),k={role:"assistant",content:l||null};h.length>0&&(k.tool_calls=h),w(t,200,{id:u,object:"chat.completion",created:Math.floor(Date.now()/1e3),model:c,choices:[{index:0,message:k,finish_reason:h.length>0?"tool_calls":"stop"}],usage:{prompt_tokens:0,completion_tokens:0,total_tokens:0}})}function it(e){return typeof e=="string"?e:Array.isArray(e)?e.filter(n=>n.type==="text").map(n=>String(n.text??"")).join(""):""}var v=class extends Error{constructor(n){super(`unsupported anthropic content block type "${n}" \u2014 the proxy translates text, tool_use and tool_result blocks`)}};function at(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 ut(e){if(typeof e=="string")return e;if(e==null)return"";if(!Array.isArray(e))throw new v(typeof e);let n="";for(let t of e){let r=String(t.type??"");if(r!=="text")throw new v(`tool_result > ${r}`);n+=String(t.text??"")}return n}function ct(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 new v(typeof t);let r=[],i="",c=()=>{i&&(r.push({role:n,content:i}),i="")};for(let u of t){let o=String(u.type??"");if(o==="text")i+=String(u.text??"");else if(o==="tool_use")c(),r.push({type:"function_call",call_id:u.id,name:u.name,arguments:JSON.stringify(u.input??{})});else if(o==="tool_result")c(),r.push({type:"function_call_output",call_id:u.tool_use_id,output:ut(u.content)});else{if(o==="thinking"||o==="redacted_thinking")continue;throw new v(o)}}return c(),r}function X(e){return K(e).map((n,t)=>{let r;try{r=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:r}})}async function pt(e,n,t,r){let i=e.messages;if(!Array.isArray(i)){_(t,400,"messages requires a messages array");return}let c=String(e.model??"urun"),u=`msg_${Math.random().toString(36).slice(2,14)}`,o=[];try{e.system&&o.push({role:"system",content:it(e.system)});for(let a of i)o.push(...ct(a))}catch(a){if(a instanceof v){_(t,400,a.message);return}throw a}let p=D(e);r.model(p);let y;try{y=await n.createResponse({model:e.model,input:o,stream:!0,tools:at(e.tools),temperature:e.temperature,max_output_tokens:e.max_tokens})}catch(a){if(a instanceof I){j(t,"anthropic",a);return}throw a}let l=(a,m)=>{t.write(`event: ${a}
19
- data: ${JSON.stringify({type:a,...m})}
20
-
21
- `)};if(e.stream===!0){let a=r.track(y,p);C(t),l("message_start",{message:{id:u,type:"message",role:"assistant",content:[],model:c,stop_reason:null,usage:{input_tokens:0,output_tokens:0}}}),l("content_block_start",{index:0,content_block:{type:"text",text:""}});let m=0,R=[];for await(let f of a)if(R.push(f),f.type==="response.output_text.delta"&&typeof f.delta=="string")m+=1,l("content_block_delta",{index:0,delta:{type:"text_delta",text:f.delta}});else if(f.type==="error"){l("error",{error:{type:"api_error",message:JSON.stringify(f)}}),t.end();return}let x;try{x=X(M(R))}catch(f){l("error",{error:{type:"api_error",message:String(f instanceof Error?f.message:f)}}),t.end();return}l("content_block_stop",{index:0}),x.forEach((f,A)=>{let S=1+A;l("content_block_start",{index:S,content_block:{...f,input:{}}}),l("content_block_delta",{index:S,delta:{type:"input_json_delta",partial_json:JSON.stringify(f.input??{})}}),l("content_block_stop",{index:S})}),l("message_delta",{delta:{stop_reason:x.length>0?"tool_use":"end_turn"},usage:{output_tokens:m}}),l("message_stop",{}),t.end();return}let g="",h=[];for await(let a of r.track(y,p))if(h.push(a),a.type==="response.output_text.delta"&&typeof a.delta=="string"&&(g+=a.delta),a.type==="error"){_(t,502,JSON.stringify(a),"upstream_error");return}let k;try{k=X(M(h))}catch(a){_(t,502,String(a instanceof Error?a.message:a),"upstream_error");return}let s=[];(g||k.length===0)&&s.push({type:"text",text:g}),s.push(...k),w(t,200,{id:u,type:"message",role:"assistant",content:s,model:c,stop_reason:k.length>0?"tool_use":"end_turn",usage:{input_tokens:0,output_tokens:0}})}function yt(e){let{clients:n,apiKey:t,identity:r}=e,i=new q,c=new T;return H((u,o)=>{(async()=>{let p=new URL(u.url??"/","http://localhost");if(u.method==="GET"&&p.pathname==="/healthz"){w(o,200,{ok:!0});return}if(u.method==="GET"&&p.pathname==="/stats"){w(o,200,r?{identity:r,...c.snapshot()}:c.snapshot());return}if(t&&(u.headers.authorization??"")!==`Bearer ${t}`){_(o,401,"invalid local proxy api key","authentication_error");return}if(u.method==="GET"&&p.pathname==="/v1/models"){w(o,200,await n.listModels());return}if(u.method!=="POST"){_(o,404,`no route for ${u.method} ${p.pathname}`);return}let y;try{y=await W(u)}catch(g){if(g instanceof B){_(o,413,g.message,"request_too_large");return}_(o,400,"request body is not valid JSON");return}let l=Buffer.byteLength(JSON.stringify(y));if(p.pathname==="/v1/responses"){c.request("responses",l,l),await st(y,n,i,o,c);return}if(p.pathname==="/v1/chat/completions"){c.request("chat_completions",l,l),await ot(y,n,o,c);return}if(p.pathname==="/v1/messages"){c.request("messages",l,l),await pt(y,n,o,c);return}_(o,404,`no route for POST ${p.pathname}`)})().catch(p=>{o.headersSent?o.end():_(o,500,String(p),"proxy_error")})})}export{yt as a};