@urun-sh/openai 0.2.52 → 0.2.53
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/pi-extension/standalone.cjs +22 -22
- package/dist/proxy/cli.cjs +1 -1
- package/dist/proxy/cli.js +1 -1
- package/package.json +3 -3
package/dist/proxy/cli.cjs
CHANGED
|
@@ -19,7 +19,7 @@ data: ${JSON.stringify(g)}
|
|
|
19
19
|
`),t.end();return}let l="",f=[];for await(let p of r.track(d,u))if(f.push(p),p.type==="response.output_text.delta"&&typeof p.delta=="string"&&(l+=p.delta),p.type==="error"){_(t,502,JSON.stringify(p),"upstream_error");return}let w=we(L(f)).map(({index:p,...c})=>c),x={role:"assistant",content:l||null};w.length>0&&(x.tool_calls=w),R(t,200,{id:a,object:"chat.completion",created:Math.floor(Date.now()/1e3),model:s,choices:[{index:0,message:x,finish_reason:w.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 A=class extends Error{constructor(n){super(`unsupported anthropic content block type "${n}" \u2014 the proxy translates text, tool_use and tool_result blocks`)}};function wt(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 xt(e){if(typeof e=="string")return e;if(e==null)return"";if(!Array.isArray(e))throw new A(typeof e);let n="";for(let t of e){let r=String(t.type??"");if(r!=="text")throw new A(`tool_result > ${r}`);n+=String(t.text??"")}return n}function vt(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 A(typeof t);let r=[],o="",s=()=>{o&&(r.push({role:n,content:o}),o="")};for(let a of t){let i=String(a.type??"");if(i==="text")o+=String(a.text??"");else if(i==="tool_use")s(),r.push({type:"function_call",call_id:a.id,name:a.name,arguments:JSON.stringify(a.input??{})});else if(i==="tool_result")s(),r.push({type:"function_call_output",call_id:a.tool_use_id,output:xt(a.content)});else{if(i==="thinking"||i==="redacted_thinking")continue;throw new A(i)}}return s(),r}function ve(e){return te(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 kt(e,n,t,r){let o=e.messages;if(!Array.isArray(o)){_(t,400,"messages requires a messages array");return}let s=String(e.model??"urun"),a=`msg_${Math.random().toString(36).slice(2,14)}`,i=[];try{e.system&&i.push({role:"system",content:_t(e.system)});for(let c of o)i.push(...vt(c))}catch(c){if(c instanceof A){_(t,400,c.message);return}throw c}let u=ee(e);r.model(u);let d;try{d=await n.createResponse({model:e.model,input:i,stream:!0,tools:wt(e.tools),temperature:e.temperature,max_output_tokens:e.max_tokens})}catch(c){if(c instanceof k){Z(t,"anthropic",c);return}throw c}let l=(c,y)=>{t.write(`event: ${c}
|
|
20
20
|
data: ${JSON.stringify({type:c,...y})}
|
|
21
21
|
|
|
22
|
-
`)};if(e.stream===!0){let c=r.track(d,u);Q(t),l("message_start",{message:{id:a,type:"message",role:"assistant",content:[],model:s,stop_reason:null,usage:{input_tokens:0,output_tokens:0}}}),l("content_block_start",{index:0,content_block:{type:"text",text:""}});let y=0,S=[];for await(let h of c)if(S.push(h),h.type==="response.output_text.delta"&&typeof h.delta=="string")y+=1,l("content_block_delta",{index:0,delta:{type:"text_delta",text:h.delta}});else if(h.type==="error"){l("error",{error:{type:"api_error",message:JSON.stringify(h)}}),t.end();return}let b;try{b=ve(L(S))}catch(h){l("error",{error:{type:"api_error",message:String(h instanceof Error?h.message:h)}}),t.end();return}l("content_block_stop",{index:0}),b.forEach((h,E)=>{let P=1+E;l("content_block_start",{index:P,content_block:{...h,input:{}}}),l("content_block_delta",{index:P,delta:{type:"input_json_delta",partial_json:JSON.stringify(h.input??{})}}),l("content_block_stop",{index:P})}),l("message_delta",{delta:{stop_reason:b.length>0?"tool_use":"end_turn"},usage:{output_tokens:y}}),l("message_stop",{}),t.end();return}let f="",w=[];for await(let c of r.track(d,u))if(w.push(c),c.type==="response.output_text.delta"&&typeof c.delta=="string"&&(f+=c.delta),c.type==="error"){_(t,502,JSON.stringify(c),"upstream_error");return}let x;try{x=ve(L(w))}catch(c){_(t,502,String(c instanceof Error?c.message:c),"upstream_error");return}let p=[];(f||x.length===0)&&p.push({type:"text",text:f}),p.push(...x),R(t,200,{id:a,type:"message",role:"assistant",content:p,model:s,stop_reason:x.length>0?"tool_use":"end_turn",usage:{input_tokens:0,output_tokens:0}})}function Re(e){let{clients:n,apiKey:t,identity:r}=e,o=new V,s=new X;return(0,ke.createServer)((a,i)=>{(async()=>{let u=new URL(a.url??"/","http://localhost");if(a.method==="GET"&&u.pathname==="/healthz"){R(i,200,{ok:!0});return}if(a.method==="GET"&&u.pathname==="/stats"){R(i,200,r?{identity:r,...s.snapshot()}:s.snapshot());return}if(t&&(a.headers.authorization??"")!==`Bearer ${t}`){_(i,401,"invalid local proxy api key","authentication_error");return}if(a.method==="GET"&&u.pathname==="/v1/models"){R(i,200,await n.listModels());return}if(a.method!=="POST"){_(i,404,`no route for ${a.method} ${u.pathname}`);return}let d;try{d=await ct(a)}catch(f){if(f instanceof q){_(i,413,f.message,"request_too_large");return}_(i,400,"request body is not valid JSON");return}let l=Buffer.byteLength(JSON.stringify(d));if(u.pathname==="/v1/responses"){s.request("responses",l,l),await gt(d,n,o,i,s);return}if(u.pathname==="/v1/chat/completions"){s.request("chat_completions",l,l),await ht(d,n,i,s);return}if(u.pathname==="/v1/messages"){s.request("messages",l,l),await kt(d,n,i,s);return}_(i,404,`no route for POST ${u.pathname}`)})().catch(u=>{i.headersSent?i.end():_(i,500,String(u),"proxy_error")})})}var Ae=D(require("os"),1),Se=D(require("path"),1),Ee=require("url"),Pe=require("util");var be="0.2.
|
|
22
|
+
`)};if(e.stream===!0){let c=r.track(d,u);Q(t),l("message_start",{message:{id:a,type:"message",role:"assistant",content:[],model:s,stop_reason:null,usage:{input_tokens:0,output_tokens:0}}}),l("content_block_start",{index:0,content_block:{type:"text",text:""}});let y=0,S=[];for await(let h of c)if(S.push(h),h.type==="response.output_text.delta"&&typeof h.delta=="string")y+=1,l("content_block_delta",{index:0,delta:{type:"text_delta",text:h.delta}});else if(h.type==="error"){l("error",{error:{type:"api_error",message:JSON.stringify(h)}}),t.end();return}let b;try{b=ve(L(S))}catch(h){l("error",{error:{type:"api_error",message:String(h instanceof Error?h.message:h)}}),t.end();return}l("content_block_stop",{index:0}),b.forEach((h,E)=>{let P=1+E;l("content_block_start",{index:P,content_block:{...h,input:{}}}),l("content_block_delta",{index:P,delta:{type:"input_json_delta",partial_json:JSON.stringify(h.input??{})}}),l("content_block_stop",{index:P})}),l("message_delta",{delta:{stop_reason:b.length>0?"tool_use":"end_turn"},usage:{output_tokens:y}}),l("message_stop",{}),t.end();return}let f="",w=[];for await(let c of r.track(d,u))if(w.push(c),c.type==="response.output_text.delta"&&typeof c.delta=="string"&&(f+=c.delta),c.type==="error"){_(t,502,JSON.stringify(c),"upstream_error");return}let x;try{x=ve(L(w))}catch(c){_(t,502,String(c instanceof Error?c.message:c),"upstream_error");return}let p=[];(f||x.length===0)&&p.push({type:"text",text:f}),p.push(...x),R(t,200,{id:a,type:"message",role:"assistant",content:p,model:s,stop_reason:x.length>0?"tool_use":"end_turn",usage:{input_tokens:0,output_tokens:0}})}function Re(e){let{clients:n,apiKey:t,identity:r}=e,o=new V,s=new X;return(0,ke.createServer)((a,i)=>{(async()=>{let u=new URL(a.url??"/","http://localhost");if(a.method==="GET"&&u.pathname==="/healthz"){R(i,200,{ok:!0});return}if(a.method==="GET"&&u.pathname==="/stats"){R(i,200,r?{identity:r,...s.snapshot()}:s.snapshot());return}if(t&&(a.headers.authorization??"")!==`Bearer ${t}`){_(i,401,"invalid local proxy api key","authentication_error");return}if(a.method==="GET"&&u.pathname==="/v1/models"){R(i,200,await n.listModels());return}if(a.method!=="POST"){_(i,404,`no route for ${a.method} ${u.pathname}`);return}let d;try{d=await ct(a)}catch(f){if(f instanceof q){_(i,413,f.message,"request_too_large");return}_(i,400,"request body is not valid JSON");return}let l=Buffer.byteLength(JSON.stringify(d));if(u.pathname==="/v1/responses"){s.request("responses",l,l),await gt(d,n,o,i,s);return}if(u.pathname==="/v1/chat/completions"){s.request("chat_completions",l,l),await ht(d,n,i,s);return}if(u.pathname==="/v1/messages"){s.request("messages",l,l),await kt(d,n,i,s);return}_(i,404,`no route for POST ${u.pathname}`)})().catch(u=>{i.headersSent?i.end():_(i,500,String(u),"proxy_error")})})}var Ae=D(require("os"),1),Se=D(require("path"),1),Ee=require("url"),Pe=require("util");var be="0.2.53";var Ue=4141,bt=be,F={claude:{bin:"claude",env:"anthropic"},codex:{bin:"codex",env:"openai"},pi:{bin:"pi",env:"openai"},aider:{bin:"aider",env:"openai"},opencode:{bin:"opencode",env:"openai"},crush:{bin:"crush",env:"openai"}};function oe(e,n="openai"){if(n==="anthropic")return{ANTHROPIC_BASE_URL:`http://127.0.0.1:${e}`,ANTHROPIC_API_KEY:"urun-local"};let t=`http://127.0.0.1:${e}/v1`;return{OPENAI_BASE_URL:t,OPENAI_API_BASE:t,OPENAI_API_KEY:"urun-local"}}function Ie(e,n,t){let r={...e,...oe(n,t)};return delete r.URUN_API_KEY,delete r.URUN_JWT,r}function Oe(e,n,t){let r=["-c","model_providers.urun.name=urun","-c",`model_providers.urun.base_url="http://127.0.0.1:${e}/v1"`,"-c",'model_providers.urun.wire_api="responses"',"-c",'model_provider="urun"'],o=t.indexOf("--"),s=o===-1?t:t.slice(0,o),a=s.some(l=>l==="-m"||l==="--model"||l.startsWith("--model=")),i=t[0]==="exec",u=s.includes("--skip-git-repo-check"),d=i&&!u?["exec","--skip-git-repo-check",...t.slice(1)]:t;return[...r,...a?[]:["-m",n],...d]}function $e(e,n){return n.some(r=>r==="--model"||r==="--provider"||r.startsWith("--model=")||r.startsWith("--provider="))?n:["--provider","urun","--model",e,...n]}function Ne(e,n,t){let r=(e.URUN_PI_EXTENSION_ENTRY??"").trim();if(r){if(!t(r))throw new Error(`URUN_PI_EXTENSION_ENTRY points at ${r}, which does not exist \u2014 the launcher that injected it (the vendored urun CLI shim) must materialize the pi extension bundle before spawning pi`);return r}let o=(0,Ee.fileURLToPath)(new URL("../pi-extension/standalone.cjs",n));if(!t(o))throw new Error(`pi extension entry not found at ${o} \u2014 the pi lane loads the self-contained @urun-sh/openai dist/pi-extension/standalone.cjs from the installed package (run \`urun compat pi\` via the npm-installed CLI, e.g. \`npx @urun-sh/openai\`), or pass an entry to pi yourself: \`pi -e <path-to-@urun-sh/openai>/dist/pi-extension/standalone.cjs\``);return o}function Le(e){let n=Number(e);if(!Number.isInteger(n)||n<0)throw new Error(`--port needs a non-negative integer (0 = OS-assigned ephemeral), got ${e}`);return n}function Ce(e){if(e[0]!=="--port")return null;let n=Le(e[1]);return e.splice(0,2),n}function se(e){let n=e.indexOf("--port");if(n===-1)return Ue;let t=Le(e[n+1]);return e.splice(n,2),t}function Te(e){if(e===0)throw new Error("`env` cannot use --port 0: it starts no proxy, so the OS never assigns the ephemeral port \u2014 pass the actual port of the running proxy");return e}function ne(e,n){let t=(e[n]??"").trim();if(!t)throw new Error(`${n} is not set. The proxy needs URUN_BASE_URL, URUN_ORG_ID, URUN_APP and either URUN_API_KEY (the org key; the proxy vends short-lived function-scoped client tokens from it via the SDK) or URUN_JWT (an explicit pre-vended token override) \u2014 plus optional URUN_FUNCTION, default "serve" \u2014 to open the backhaul session.`);return t}function C(e){let n=At(ne(e,"URUN_BASE_URL")),t=ne(e,"URUN_ORG_ID"),r=ne(e,"URUN_APP"),o=(e.URUN_FUNCTION??"serve").trim()||"serve",s=(e.URUN_API_URL??"").trim(),a=s?Y(s,"URUN_API_URL"):ge,i=(e.URUN_JWT??"").trim();if(i)return{baseUrl:n,orgId:t,appId:r,fnName:o,apiUrl:a,auth:{lane:"jwt",jwt:i}};let u=(e.URUN_API_KEY??"").trim();if(u){let d=(e.URUN_GATEWAY_URL??"").trim(),l=d?Y(d):void 0;return{baseUrl:n,orgId:t,appId:r,fnName:o,apiUrl:a,auth:{lane:"api-key",apiKey:u,gatewayUrl:l}}}throw new Error("neither URUN_API_KEY nor URUN_JWT is set. Set URUN_API_KEY (the org API key \u2014 the proxy vends short-lived, function-scoped client tokens from it via the SDK, so the key never reaches the agent process) or URUN_JWT (an explicit pre-vended token; when set it always wins). URUN_BASE_URL, URUN_ORG_ID and URUN_APP are also required.")}function At(e,n="URUN_BASE_URL"){if(/\/v1\/*$/.test(new URL(e).pathname))throw new Error(`${n} must be the session-gateway base (e.g. https://api.urun.sh), got ${e} \u2014 a trailing /v1 is the org control-plane API form (that belongs in URUN_API_URL); session allocation 404s against it. Drop the /v1.`);return e}function Y(e,n="URUN_GATEWAY_URL"){let t=new URL(e),r=t.hostname==="localhost"||t.hostname==="127.0.0.1"||t.hostname==="[::1]";if(t.protocol!=="https:"&&!r)throw new Error(`${n} must be https (got ${e}) \u2014 the org API key rides the request's Authorization header`);return e}function ie(e){return{app:e.appId,org:e.orgId,fn:e.fnName,base_url:e.baseUrl,proxy_version:bt}}function St(e,n){return e.app===n.app&&e.org===n.org&&e.fn===n.fn&&e.base_url===n.base_url&&e.proxy_version===n.proxy_version}var Et=250;async function ae(e,n=Et){try{let t=await fetch(`http://127.0.0.1:${e}/stats`,{signal:AbortSignal.timeout(n)});if(!t.ok)return null;let r=(await t.json()).identity;if(r==null||typeof r!="object")return null;let{app:o,org:s,fn:a,base_url:i,proxy_version:u}=r;return typeof o!="string"||typeof s!="string"||typeof a!="string"||typeof i!="string"||typeof u!="string"?null:{app:o,org:s,fn:a,base_url:i,proxy_version:u}}catch{return null}}async function je(e,n,t=Ue){if(e!=null)return{mode:"spawn",port:e};let r=await ae(t);return r!==null&&St(r,n)?{mode:"reuse",port:t,identity:r}:{mode:"spawn",port:0}}function Me(e,n=Ae.default.homedir()){return Se.default.join(n,".urun","logs",`compat-proxy-${e}.log`)}var re=["log","info","warn","error","debug","trace"];function De(e,n=process,t=console){let r=n.stdout.write,o=n.stderr.write,s=(i,...u)=>e.write(i,...u);n.stdout.write=s,n.stderr.write=s;let a=Object.fromEntries(re.map(i=>[i,t[i]]));for(let i of re)t[i]=(...u)=>{e.write(`${(0,Pe.format)(...u)}
|
|
23
23
|
`)};return()=>{n.stdout.write=r,n.stderr.write=o;for(let i of re)t[i]=a[i]}}function Be(e,n){let t="pass --port 0 for an OS-assigned ephemeral port";return n?`port ${e} is held by another urun-openai proxy serving app ${n.app} (org ${n.org}, fn ${n.fn}, version ${n.proxy_version}) \u2014 reuse it by pointing your agent at http://127.0.0.1:${e}, or ${t}`:`port ${e} is already in use and does not answer the urun-openai /stats identity probe \u2014 ${t}`}function Je(e,n,t){let r=e[t];if(typeof r!="function")throw new Error(`app "${n}" has no function "${t}" (set URUN_FUNCTION)`);let o=r();if(typeof o.end!="function")throw new Error(`app "${n}" function "${t}" returned a session without end()`);return o}function Ke(e,n){let{baseUrl:t,orgId:r,fnName:o,auth:s}=e;if(s.lane==="jwt"){let l=(0,T.App)(n,{baseUrl:t,orgId:r,jwt:s.jwt}),f=Je(l,n,o);return{session:f,responses:new N(f)}}let{apiKey:a,gatewayUrl:i}=s,u=(0,T.App)(n,{baseUrl:t,orgId:r,getAccessToken:async()=>(await(0,T.createClientToken)(a,{baseUrl:i,expiresIn:300,allowedFunctions:[`${n}/${o}`]})).token}),d=Je(u,n,o);return{session:d,responses:new N(d)}}function Ye(e){let n=(m.default.env.URUN_CATALOG_URL??"").trim(),t=n?Y(n,"URUN_CATALOG_URL"):"",r=(m.default.env.URUN_CATALOG_ANON_KEY??"").trim();(!t||!r)&&m.default.stderr.write(`urun compat: catalog oracle off (URUN_CATALOG_URL/URUN_CATALOG_ANON_KEY unset) \u2014 an undeployed uRun CATALOG model name falls through to the default app instead of a loud 404; deployed apps still resolve exactly, and /stats.models records every mapping
|
|
24
24
|
`);let o=e.auth,s=new J({defaultApp:e.appId,fnName:e.fnName,openSession:a=>Ke(e,a),closeSession:async a=>{await a.session.end()},listApps:o.lane==="api-key"?()=>he({apiUrl:e.apiUrl,apiKey:o.apiKey}):null,listCatalog:t&&r?()=>ye({catalogUrl:t,anonKey:r}):null});return s.seed(e.appId,Ke(e,e.appId)),s}function Fe(e){return{createResponse:async n=>{let{entry:t}=await e.sessionFor(n.model);return t.responses.responses.create(n)},listModels:()=>e.modelList()}}async function Pt(e,n,t){let r=(0,pe.spawn)(e,n,{stdio:"inherit",env:t});return new Promise(o=>{r.once("exit",s=>o(s??1)),r.once("error",s=>{m.default.stderr.write(`failed to launch ${e}: ${String(s)}
|
|
25
25
|
`),o(127)})})}function Ut(){return Ne(m.default.env,v,I.existsSync)}function We(e){for(let[n,t]of Object.entries(oe(e)))m.default.stdout.write(`export ${n}=${t}
|
package/dist/proxy/cli.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import{a as S}from"../chunk-OLE2YJO3.js";import{a as k}from"../chunk-KJ25VEMG.js";import{c as w}from"../chunk-FSS2A7IU.js";import{a as A,c as I,d as O}from"../chunk-PS4BLX7J.js";import{spawn as V}from"child_process";import{createWriteStream as ce,existsSync as ue,mkdirSync as de}from"fs";import le from"path";import p from"process";import{App as F,createClientToken as me}from"@urun-sh/core";import te from"os";import ne from"path";import{fileURLToPath as re}from"url";import{format as oe}from"util";var $="0.2.
|
|
2
|
+
import{a as S}from"../chunk-OLE2YJO3.js";import{a as k}from"../chunk-KJ25VEMG.js";import{c as w}from"../chunk-FSS2A7IU.js";import{a as A,c as I,d as O}from"../chunk-PS4BLX7J.js";import{spawn as V}from"child_process";import{createWriteStream as ce,existsSync as ue,mkdirSync as de}from"fs";import le from"path";import p from"process";import{App as F,createClientToken as me}from"@urun-sh/core";import te from"os";import ne from"path";import{fileURLToPath as re}from"url";import{format as oe}from"util";var $="0.2.53";var L=4141,se=$,x={claude:{bin:"claude",env:"anthropic"},codex:{bin:"codex",env:"openai"},pi:{bin:"pi",env:"openai"},aider:{bin:"aider",env:"openai"},opencode:{bin:"opencode",env:"openai"},crush:{bin:"crush",env:"openai"}};function E(e,t="openai"){if(t==="anthropic")return{ANTHROPIC_BASE_URL:`http://127.0.0.1:${e}`,ANTHROPIC_API_KEY:"urun-local"};let n=`http://127.0.0.1:${e}/v1`;return{OPENAI_BASE_URL:n,OPENAI_API_BASE:n,OPENAI_API_KEY:"urun-local"}}function T(e,t,n){let r={...e,...E(t,n)};return delete r.URUN_API_KEY,delete r.URUN_JWT,r}function j(e,t,n){let r=["-c","model_providers.urun.name=urun","-c",`model_providers.urun.base_url="http://127.0.0.1:${e}/v1"`,"-c",'model_providers.urun.wire_api="responses"',"-c",'model_provider="urun"'],o=n.indexOf("--"),s=o===-1?n:n.slice(0,o),a=s.some(u=>u==="-m"||u==="--model"||u.startsWith("--model=")),i=n[0]==="exec",c=s.includes("--skip-git-repo-check"),l=i&&!c?["exec","--skip-git-repo-check",...n.slice(1)]:n;return[...r,...a?[]:["-m",t],...l]}function C(e,t){return t.some(r=>r==="--model"||r==="--provider"||r.startsWith("--model=")||r.startsWith("--provider="))?t:["--provider","urun","--model",e,...t]}function G(e,t,n){let r=(e.URUN_PI_EXTENSION_ENTRY??"").trim();if(r){if(!n(r))throw new Error(`URUN_PI_EXTENSION_ENTRY points at ${r}, which does not exist \u2014 the launcher that injected it (the vendored urun CLI shim) must materialize the pi extension bundle before spawning pi`);return r}let o=re(new URL("../pi-extension/standalone.cjs",t));if(!n(o))throw new Error(`pi extension entry not found at ${o} \u2014 the pi lane loads the self-contained @urun-sh/openai dist/pi-extension/standalone.cjs from the installed package (run \`urun compat pi\` via the npm-installed CLI, e.g. \`npx @urun-sh/openai\`), or pass an entry to pi yourself: \`pi -e <path-to-@urun-sh/openai>/dist/pi-extension/standalone.cjs\``);return o}function K(e){let t=Number(e);if(!Number.isInteger(t)||t<0)throw new Error(`--port needs a non-negative integer (0 = OS-assigned ephemeral), got ${e}`);return t}function D(e){if(e[0]!=="--port")return null;let t=K(e[1]);return e.splice(0,2),t}function _(e){let t=e.indexOf("--port");if(t===-1)return L;let n=K(e[t+1]);return e.splice(t,2),n}function W(e){if(e===0)throw new Error("`env` cannot use --port 0: it starts no proxy, so the OS never assigns the ephemeral port \u2014 pass the actual port of the running proxy");return e}function U(e,t){let n=(e[t]??"").trim();if(!n)throw new Error(`${t} is not set. The proxy needs URUN_BASE_URL, URUN_ORG_ID, URUN_APP and either URUN_API_KEY (the org key; the proxy vends short-lived function-scoped client tokens from it via the SDK) or URUN_JWT (an explicit pre-vended token override) \u2014 plus optional URUN_FUNCTION, default "serve" \u2014 to open the backhaul session.`);return n}function h(e){let t=ie(U(e,"URUN_BASE_URL")),n=U(e,"URUN_ORG_ID"),r=U(e,"URUN_APP"),o=(e.URUN_FUNCTION??"serve").trim()||"serve",s=(e.URUN_API_URL??"").trim(),a=s?g(s,"URUN_API_URL"):A,i=(e.URUN_JWT??"").trim();if(i)return{baseUrl:t,orgId:n,appId:r,fnName:o,apiUrl:a,auth:{lane:"jwt",jwt:i}};let c=(e.URUN_API_KEY??"").trim();if(c){let l=(e.URUN_GATEWAY_URL??"").trim(),u=l?g(l):void 0;return{baseUrl:t,orgId:n,appId:r,fnName:o,apiUrl:a,auth:{lane:"api-key",apiKey:c,gatewayUrl:u}}}throw new Error("neither URUN_API_KEY nor URUN_JWT is set. Set URUN_API_KEY (the org API key \u2014 the proxy vends short-lived, function-scoped client tokens from it via the SDK, so the key never reaches the agent process) or URUN_JWT (an explicit pre-vended token; when set it always wins). URUN_BASE_URL, URUN_ORG_ID and URUN_APP are also required.")}function ie(e,t="URUN_BASE_URL"){if(/\/v1\/*$/.test(new URL(e).pathname))throw new Error(`${t} must be the session-gateway base (e.g. https://api.urun.sh), got ${e} \u2014 a trailing /v1 is the org control-plane API form (that belongs in URUN_API_URL); session allocation 404s against it. Drop the /v1.`);return e}function g(e,t="URUN_GATEWAY_URL"){let n=new URL(e),r=n.hostname==="localhost"||n.hostname==="127.0.0.1"||n.hostname==="[::1]";if(n.protocol!=="https:"&&!r)throw new Error(`${t} must be https (got ${e}) \u2014 the org API key rides the request's Authorization header`);return e}function P(e){return{app:e.appId,org:e.orgId,fn:e.fnName,base_url:e.baseUrl,proxy_version:se}}function ae(e,t){return e.app===t.app&&e.org===t.org&&e.fn===t.fn&&e.base_url===t.base_url&&e.proxy_version===t.proxy_version}var pe=250;async function R(e,t=pe){try{let n=await fetch(`http://127.0.0.1:${e}/stats`,{signal:AbortSignal.timeout(t)});if(!n.ok)return null;let r=(await n.json()).identity;if(r==null||typeof r!="object")return null;let{app:o,org:s,fn:a,base_url:i,proxy_version:c}=r;return typeof o!="string"||typeof s!="string"||typeof a!="string"||typeof i!="string"||typeof c!="string"?null:{app:o,org:s,fn:a,base_url:i,proxy_version:c}}catch{return null}}async function Y(e,t,n=L){if(e!=null)return{mode:"spawn",port:e};let r=await R(n);return r!==null&&ae(r,t)?{mode:"reuse",port:n,identity:r}:{mode:"spawn",port:0}}function J(e,t=te.homedir()){return ne.join(t,".urun","logs",`compat-proxy-${e}.log`)}var v=["log","info","warn","error","debug","trace"];function M(e,t=process,n=console){let r=t.stdout.write,o=t.stderr.write,s=(i,...c)=>e.write(i,...c);t.stdout.write=s,t.stderr.write=s;let a=Object.fromEntries(v.map(i=>[i,n[i]]));for(let i of v)n[i]=(...c)=>{e.write(`${oe(...c)}
|
|
3
3
|
`)};return()=>{t.stdout.write=r,t.stderr.write=o;for(let i of v)n[i]=a[i]}}function B(e,t){let n="pass --port 0 for an OS-assigned ephemeral port";return t?`port ${e} is held by another urun-openai proxy serving app ${t.app} (org ${t.org}, fn ${t.fn}, version ${t.proxy_version}) \u2014 reuse it by pointing your agent at http://127.0.0.1:${e}, or ${n}`:`port ${e} is already in use and does not answer the urun-openai /stats identity probe \u2014 ${n}`}function q(e,t,n){let r=e[n];if(typeof r!="function")throw new Error(`app "${t}" has no function "${n}" (set URUN_FUNCTION)`);let o=r();if(typeof o.end!="function")throw new Error(`app "${t}" function "${n}" returned a session without end()`);return o}function H(e,t){let{baseUrl:n,orgId:r,fnName:o,auth:s}=e;if(s.lane==="jwt"){let u=F(t,{baseUrl:n,orgId:r,jwt:s.jwt}),m=q(u,t,o);return{session:m,responses:new w(m)}}let{apiKey:a,gatewayUrl:i}=s,c=F(t,{baseUrl:n,orgId:r,getAccessToken:async()=>(await me(a,{baseUrl:i,expiresIn:300,allowedFunctions:[`${t}/${o}`]})).token}),l=q(c,t,o);return{session:l,responses:new w(l)}}function fe(e){let t=(p.env.URUN_CATALOG_URL??"").trim(),n=t?g(t,"URUN_CATALOG_URL"):"",r=(p.env.URUN_CATALOG_ANON_KEY??"").trim();(!n||!r)&&p.stderr.write(`urun compat: catalog oracle off (URUN_CATALOG_URL/URUN_CATALOG_ANON_KEY unset) \u2014 an undeployed uRun CATALOG model name falls through to the default app instead of a loud 404; deployed apps still resolve exactly, and /stats.models records every mapping
|
|
4
4
|
`);let o=e.auth,s=new O({defaultApp:e.appId,fnName:e.fnName,openSession:a=>H(e,a),closeSession:async a=>{await a.session.end()},listApps:o.lane==="api-key"?()=>I({apiUrl:e.apiUrl,apiKey:o.apiKey}):null,listCatalog:n&&r?()=>S({catalogUrl:n,anonKey:r}):null});return s.seed(e.appId,H(e,e.appId)),s}function ye(e){return{createResponse:async t=>{let{entry:n}=await e.sessionFor(t.model);return n.responses.responses.create(t)},listModels:()=>e.modelList()}}async function he(e,t,n){let r=V(e,t,{stdio:"inherit",env:n});return new Promise(o=>{r.once("exit",s=>o(s??1)),r.once("error",s=>{p.stderr.write(`failed to launch ${e}: ${String(s)}
|
|
5
5
|
`),o(127)})})}function ge(){return G(p.env,import.meta.url,ue)}function X(e){for(let[t,n]of Object.entries(E(e)))p.stdout.write(`export ${t}=${n}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@urun-sh/openai",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.53",
|
|
4
4
|
"description": "OpenAI-compatible Realtime + Responses SDK over uRun session primitives (not websockets).",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -50,7 +50,7 @@
|
|
|
50
50
|
"build:bin": "bun build --compile --external @roamhq/wrtc --external werift --external opusscript src/proxy/cli.ts --outfile dist/bin/urun-openai"
|
|
51
51
|
},
|
|
52
52
|
"peerDependencies": {
|
|
53
|
-
"@urun-sh/core": "^0.2.
|
|
53
|
+
"@urun-sh/core": "^0.2.53"
|
|
54
54
|
},
|
|
55
55
|
"dependencies": {
|
|
56
56
|
"openai": "4.104.0"
|
|
@@ -77,4 +77,4 @@
|
|
|
77
77
|
"bin": {
|
|
78
78
|
"urun-openai": "./dist/proxy/cli.cjs"
|
|
79
79
|
}
|
|
80
|
-
}
|
|
80
|
+
}
|