@soba-so/sdk 0.0.6 → 0.0.7

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/index.mjs CHANGED
@@ -1,4 +1,4 @@
1
- var s=class extends Error{code;type;status;retryable;retryAfterMs;runId;constructor(e){super(e.message,e.cause===void 0?void 0:{cause:e.cause}),this.name="SobaError",this.code=e.code,this.type=e.type??e.code,this.status=e.status,this.retryable=e.retryable??F.has(e.code),this.retryAfterMs=e.retryAfterMs,this.runId=e.runId}},F=new Set(["rate_limited","server_error","connection","timeout","stream_truncated"]),j={400:"invalid_request",401:"unauthorized",402:"payment_required",403:"forbidden",404:"not_found",409:"no_compute",422:"user_required",429:"rate_limited"};function W(t){let e=j[t];return e||(t>=500?"server_error":t>=400?"invalid_request":"unknown")}async function k(t){let e=t.status,n="";try{n=await t.text()}catch{}let r=B(n);return new s({code:r?.code??W(e),type:r?.type,message:r?.message??K(e,t.statusText,n),status:e,retryAfterMs:J(t.headers.get("retry-after")),runId:t.headers.get("soba-run-id")??void 0})}function B(t){if(!t)return null;let e;try{e=JSON.parse(t)}catch{return null}if(!e||typeof e!="object")return null;let n=e.error;if(!n||typeof n!="object")return null;let r=n;return{message:typeof r.message=="string"&&r.message?r.message:void 0,type:typeof r.type=="string"&&r.type?r.type:void 0,code:G.has(r.code)?r.code:void 0}}var G=new Set(["invalid_request","user_required","unauthorized","payment_required","forbidden","not_found","no_compute","rate_limited","server_error","connection","timeout","stream_truncated","run_failed","canceled","unknown"]);function K(t,e,n){let r=n.trim().slice(0,200),o=r?`: ${r}`:"";return`Soba returned ${t}${e?` ${e}`:""}${o}`}function J(t){if(!t)return;let e=Number(t);if(Number.isFinite(e)&&e>=0)return Math.round(e*1e3);let n=Date.parse(t);if(!Number.isNaN(n))return Math.max(0,n-Date.now())}function f(t){if(t instanceof s)return t;let e=t;return e?.name==="AbortError"||e?.name==="TimeoutError"?new s({code:"canceled",message:e.message||"The request was aborted.",retryable:!1,cause:t}):new s({code:"connection",message:e?.message?`Could not reach Soba: ${e.message}`:"Could not reach Soba.",cause:t})}var w="0.0.6";var H=8e3,Y=3e4;async function g(t,e){let n=Q(t.baseURL,e.path,e.query),r=e.retry===!1?1:Math.max(0,t.maxRetries)+1,o;for(let i=0;i<r;i++){i>0&&await Z(X(i,o),e.signal);let a=new AbortController,c=S(e.signal,a),m=setTimeout(()=>{a.abort(new s({code:"timeout",message:`Soba did not answer within ${t.connectTimeoutMs}ms.`}))},t.connectTimeoutMs),d;try{d=await t.fetch(n,{method:e.method,headers:z(t,e),body:e.body===void 0?void 0:JSON.stringify(e.body),signal:a.signal})}catch(l){if(c(),o=f(a.signal.aborted?a.signal.reason??l:l),!o.retryable||i===r-1)throw o;continue}finally{clearTimeout(m)}if(d.ok)return d;if(c(),o=await k(d),!o.retryable||i===r-1)throw o}throw o??new s({code:"unknown",message:"The request failed with no error."})}async function C(t,e){let n=await g(t,{accept:"application/json",...e}),r=await n.text();if(r)try{return JSON.parse(r)}catch(o){throw new s({code:"server_error",message:`Soba returned a body that is not JSON: ${r.slice(0,200)}`,status:n.status,cause:o})}}function z(t,e){let n={authorization:`Bearer ${t.apiKey}`,accept:e.accept??"application/json","user-agent":V(),...t.headers};return e.body!==void 0&&(n["content-type"]="application/json"),n}function V(){let t=typeof process>"u"?"":` node/${process.versions?.node??"?"}`;return`soba-sdk/${w}${t}`}function Q(t,e,n){let r=t.replace(/\/+$/,""),o=new URL(`${r}${e.startsWith("/")?e:`/${e}`}`);for(let[i,a]of Object.entries(n??{}))a!==void 0&&o.searchParams.set(i,String(a));return o.toString()}function X(t,e){if(e?.retryAfterMs!==void 0)return Math.min(e.retryAfterMs,Y);let n=Math.min(H,500*2**(t-1));return Math.round(n*(.5+Math.random()/2))}function Z(t,e){return new Promise((n,r)=>{if(e?.aborted)return r(f(e.reason));let o=setTimeout(()=>{e?.removeEventListener("abort",i),n()},t);function i(){clearTimeout(o),r(f(e?.reason))}e?.addEventListener("abort",i,{once:!0})})}function S(t,e){if(!t)return()=>{};if(t.aborted)return e.abort(t.reason),()=>{};let n=()=>e.abort(t.reason);return t.addEventListener("abort",n,{once:!0}),()=>t.removeEventListener("abort",n)}var _=["open-weights","frontier"];function ee(t){return _.includes(t)}function te(t){return t==="user-hardware"||t==="user-subscription"||t==="open-weights"||t==="frontier"}function T(t){return t.type==="done"||t.type==="error"}var ne=["search","fetch","read","write","edit","bash","files","agent","todo","think","sources","tool"];var P=new Set(["delta","thinking","status","done","error"]);function R(t){let e;try{e=JSON.parse(t)}catch{return null}if(!e||typeof e!="object"||Array.isArray(e))return null;let n=e,r=u(n.runId);if(typeof n.type=="string"&&P.has(n.type)){let o=I(n);return o?{kind:"event",runId:r,event:o}:null}switch(n.type){case"event":{if(!n.event||typeof n.event!="object")return null;let o=I(n.event);return o?{kind:"event",runId:r,event:o}:null}case"usage":{let o=U(n.usage);return o?{kind:"usage",runId:r,usage:o}:null}case"tool_call":{let o=u(n.callId),i=u(n.name);return!o||!i?null:{kind:"tool_call",runId:r,callId:o,name:i,input:n.input}}case"approval_request":{let o=u(n.approvalId),i=u(n.tool);return!o||!i?null:{kind:"approval",runId:r,approvalId:o,tool:i,input:n.input,cwd:u(n.cwd)}}default:return null}}function I(t){let e=typeof t.type=="string"&&P.has(t.type)?t.type:null;if(!e)return null;let n={type:e},r=u(t.text);r!==void 0&&(n.text=r);let o=u(t.message);o!==void 0&&(n.message=o);let i=u(t.tool);i!==void 0&&(n.tool=i);let a=u(t.tier);a!==void 0&&(n.tier=a);let c=U(t.usage);return c&&(n.usage=c),n}function U(t){if(!t||typeof t!="object")return null;let e=t,n={model:u(e.model)??"unknown",inputTokens:y(e.inputTokens),outputTokens:y(e.outputTokens),cacheReadTokens:y(e.cacheReadTokens),cacheWriteTokens:y(e.cacheWriteTokens),webSearches:y(e.webSearches)},r=u(e.costClass);r!==void 0&&(n.costClass=r);let o=u(e.provider);return o!==void 0&&(n.provider=o),typeof e.costMicros=="number"&&Number.isFinite(e.costMicros)&&(n.costMicros=e.costMicros),n}function u(t){return typeof t=="string"&&t.length>0?t:void 0}function y(t){return typeof t=="number"&&Number.isFinite(t)?t:0}async function*O(t){let e=t.body;if(!e)throw new s({code:"connection",message:"The run response arrived with no body to stream.",status:t.status});let n=t.headers.get("content-type")??"",r=n.includes("ndjson")||n.includes("jsonlines"),o=e.getReader(),i=new TextDecoder,a="",c=[];try{for(;;){let d=await o.read();if(d.done)break;for(a+=i.decode(d.value,{stream:!0});;){let l=a.indexOf(`
1
+ var s=class extends Error{code;type;status;retryable;retryAfterMs;runId;constructor(e){super(e.message,e.cause===void 0?void 0:{cause:e.cause}),this.name="SobaError",this.code=e.code,this.type=e.type??e.code,this.status=e.status,this.retryable=e.retryable??F.has(e.code),this.retryAfterMs=e.retryAfterMs,this.runId=e.runId}},F=new Set(["rate_limited","server_error","connection","timeout","stream_truncated"]),j={400:"invalid_request",401:"unauthorized",402:"payment_required",403:"forbidden",404:"not_found",409:"no_compute",422:"user_required",429:"rate_limited"};function W(t){let e=j[t];return e||(t>=500?"server_error":t>=400?"invalid_request":"unknown")}async function k(t){let e=t.status,n="";try{n=await t.text()}catch{}let r=B(n);return new s({code:r?.code??W(e),type:r?.type,message:r?.message??K(e,t.statusText,n),status:e,retryAfterMs:J(t.headers.get("retry-after")),runId:t.headers.get("soba-run-id")??void 0})}function B(t){if(!t)return null;let e;try{e=JSON.parse(t)}catch{return null}if(!e||typeof e!="object")return null;let n=e.error;if(!n||typeof n!="object")return null;let r=n;return{message:typeof r.message=="string"&&r.message?r.message:void 0,type:typeof r.type=="string"&&r.type?r.type:void 0,code:G.has(r.code)?r.code:void 0}}var G=new Set(["invalid_request","user_required","unauthorized","payment_required","forbidden","not_found","no_compute","rate_limited","server_error","connection","timeout","stream_truncated","run_failed","canceled","unknown"]);function K(t,e,n){let r=n.trim().slice(0,200),o=r?`: ${r}`:"";return`Soba returned ${t}${e?` ${e}`:""}${o}`}function J(t){if(!t)return;let e=Number(t);if(Number.isFinite(e)&&e>=0)return Math.round(e*1e3);let n=Date.parse(t);if(!Number.isNaN(n))return Math.max(0,n-Date.now())}function f(t){if(t instanceof s)return t;let e=t;return e?.name==="AbortError"||e?.name==="TimeoutError"?new s({code:"canceled",message:e.message||"The request was aborted.",retryable:!1,cause:t}):new s({code:"connection",message:e?.message?`Could not reach Soba: ${e.message}`:"Could not reach Soba.",cause:t})}var w="0.0.7";var H=8e3,Y=3e4;async function g(t,e){let n=Q(t.baseURL,e.path,e.query),r=e.retry===!1?1:Math.max(0,t.maxRetries)+1,o;for(let i=0;i<r;i++){i>0&&await Z(X(i,o),e.signal);let a=new AbortController,c=S(e.signal,a),m=setTimeout(()=>{a.abort(new s({code:"timeout",message:`Soba did not answer within ${t.connectTimeoutMs}ms.`}))},t.connectTimeoutMs),d;try{d=await t.fetch(n,{method:e.method,headers:z(t,e),body:e.body===void 0?void 0:JSON.stringify(e.body),signal:a.signal})}catch(l){if(c(),o=f(a.signal.aborted?a.signal.reason??l:l),!o.retryable||i===r-1)throw o;continue}finally{clearTimeout(m)}if(d.ok)return d;if(c(),o=await k(d),!o.retryable||i===r-1)throw o}throw o??new s({code:"unknown",message:"The request failed with no error."})}async function C(t,e){let n=await g(t,{accept:"application/json",...e}),r=await n.text();if(r)try{return JSON.parse(r)}catch(o){throw new s({code:"server_error",message:`Soba returned a body that is not JSON: ${r.slice(0,200)}`,status:n.status,cause:o})}}function z(t,e){let n={authorization:`Bearer ${t.apiKey}`,accept:e.accept??"application/json","user-agent":V(),...t.headers};return e.body!==void 0&&(n["content-type"]="application/json"),n}function V(){let t=typeof process>"u"?"":` node/${process.versions?.node??"?"}`;return`soba-sdk/${w}${t}`}function Q(t,e,n){let r=t.replace(/\/+$/,""),o=new URL(`${r}${e.startsWith("/")?e:`/${e}`}`);for(let[i,a]of Object.entries(n??{}))a!==void 0&&o.searchParams.set(i,String(a));return o.toString()}function X(t,e){if(e?.retryAfterMs!==void 0)return Math.min(e.retryAfterMs,Y);let n=Math.min(H,500*2**(t-1));return Math.round(n*(.5+Math.random()/2))}function Z(t,e){return new Promise((n,r)=>{if(e?.aborted)return r(f(e.reason));let o=setTimeout(()=>{e?.removeEventListener("abort",i),n()},t);function i(){clearTimeout(o),r(f(e?.reason))}e?.addEventListener("abort",i,{once:!0})})}function S(t,e){if(!t)return()=>{};if(t.aborted)return e.abort(t.reason),()=>{};let n=()=>e.abort(t.reason);return t.addEventListener("abort",n,{once:!0}),()=>t.removeEventListener("abort",n)}var _=["open-weights","frontier"];function ee(t){return _.includes(t)}function te(t){return t==="user-hardware"||t==="user-subscription"||t==="open-weights"||t==="frontier"}function T(t){return t.type==="done"||t.type==="error"}var ne=["search","fetch","read","write","edit","bash","files","agent","todo","think","sources","tool"];var P=new Set(["delta","thinking","status","done","error"]);function R(t){let e;try{e=JSON.parse(t)}catch{return null}if(!e||typeof e!="object"||Array.isArray(e))return null;let n=e,r=u(n.runId);if(typeof n.type=="string"&&P.has(n.type)){let o=I(n);return o?{kind:"event",runId:r,event:o}:null}switch(n.type){case"event":{if(!n.event||typeof n.event!="object")return null;let o=I(n.event);return o?{kind:"event",runId:r,event:o}:null}case"usage":{let o=U(n.usage);return o?{kind:"usage",runId:r,usage:o}:null}case"tool_call":{let o=u(n.callId),i=u(n.name);return!o||!i?null:{kind:"tool_call",runId:r,callId:o,name:i,input:n.input}}case"approval_request":{let o=u(n.approvalId),i=u(n.tool);return!o||!i?null:{kind:"approval",runId:r,approvalId:o,tool:i,input:n.input,cwd:u(n.cwd)}}default:return null}}function I(t){let e=typeof t.type=="string"&&P.has(t.type)?t.type:null;if(!e)return null;let n={type:e},r=u(t.text);r!==void 0&&(n.text=r);let o=u(t.message);o!==void 0&&(n.message=o);let i=u(t.tool);i!==void 0&&(n.tool=i);let a=u(t.tier);a!==void 0&&(n.tier=a);let c=U(t.usage);return c&&(n.usage=c),n}function U(t){if(!t||typeof t!="object")return null;let e=t,n={model:u(e.model)??"unknown",inputTokens:y(e.inputTokens),outputTokens:y(e.outputTokens),cacheReadTokens:y(e.cacheReadTokens),cacheWriteTokens:y(e.cacheWriteTokens),webSearches:y(e.webSearches)},r=u(e.costClass);r!==void 0&&(n.costClass=r);let o=u(e.provider);return o!==void 0&&(n.provider=o),typeof e.costMicros=="number"&&Number.isFinite(e.costMicros)&&(n.costMicros=e.costMicros),n}function u(t){return typeof t=="string"&&t.length>0?t:void 0}function y(t){return typeof t=="number"&&Number.isFinite(t)?t:0}async function*O(t){let e=t.body;if(!e)throw new s({code:"connection",message:"The run response arrived with no body to stream.",status:t.status});let n=t.headers.get("content-type")??"",r=n.includes("ndjson")||n.includes("jsonlines"),o=e.getReader(),i=new TextDecoder,a="",c=[];try{for(;;){let d=await o.read();if(d.done)break;for(a+=i.decode(d.value,{stream:!0});;){let l=a.indexOf(`
2
2
  `);if(l===-1)break;let b=q(a.slice(0,l));if(a=a.slice(l+1),r){let p=b.trim()?R(b):null;p&&(yield p);continue}if(b===""){let p=c.join(`
3
3
  `);if(c=[],p==="[DONE]")return;let A=p?R(p):null;A&&(yield A);continue}M(b,c)}}!r&&a&&M(q(a),c);let m=r?a.trim():c.join(`
4
4
  `);if(m&&m!=="[DONE]"){let d=R(m);d&&(yield d)}}finally{o.cancel().catch(()=>{})}}function M(t,e){if(t.startsWith(":"))return;let n=t.indexOf(":");if(n===-1||t.slice(0,n)!=="data")return;let r=t.slice(n+1);e.push(r.startsWith(" ")?r.slice(1):r)}function q(t){return t.endsWith("\r")?t.slice(0,-1):t}function re(t){return t}function L(t){let e=new Map;for(let n of t??[]){if(!n?.name)throw new s({code:"invalid_request",message:"Every tool needs a name."});if(typeof n.execute!="function")throw new s({code:"invalid_request",message:`Tool "${n.name}" has no execute function. A tool Soba cannot call is not a tool.`});if(e.has(n.name))throw new s({code:"invalid_request",message:`Two tools are named "${n.name}". Tool names must be unique within a run.`});e.set(n.name,n)}return e}function D(t){return[...t.values()].map(e=>({name:e.name,description:e.description??"",inputSchema:e.inputSchema??{type:"object"}}))}function N(t){if(t===void 0)return null;if(typeof t=="string")return t;try{return JSON.parse(JSON.stringify(t))}catch{return String(t)}}function v(t){return t instanceof Error?t.message||t.name:typeof t=="string"?t:String(t)}var h=class{#e;#n;#r;#a=!1;#t;#o=new AbortController;#s=new AbortController;#i=new Set;#u;constructor(e){this.#t=e,this.#e=e.response.headers.get("soba-run-id")??"",this.#u=S(e.signal,this.#o)}get runId(){return this.#e}get tier(){return this.#n}get usage(){return this.#r}[Symbol.asyncIterator](){return this.#d()}async text(){let e="";for await(let n of this)if(n.type==="delta"&&n.text&&(e+=n.text),n.type==="error")throw new s({code:"run_failed",message:n.message??"The run ended with an error.",runId:this.#e,retryable:!1});return e}async cancel(){if(this.#o.abort(new s({code:"canceled",message:"The run was cancelled."})),this.#s.abort(new s({code:"canceled",message:"The run was cancelled."})),!!this.#e)try{await g(this.#t.config,{method:"POST",path:`/runs/${encodeURIComponent(this.#e)}/cancel`,retry:!1})}catch(e){this.#t.onWarning("Could not tell Soba the run was cancelled.",e)}}async*#d(){if(this.#a)throw new s({code:"invalid_request",message:"This run has already been consumed. A run's events can only be read once.",runId:this.#e});this.#a=!0;let e=!1;try{for await(let n of O(this.#t.response)){if(n.runId&&!this.#e&&(this.#e=n.runId),n.kind==="event"){let r=n.event;if(r.tier&&(this.#n=r.tier),r.usage&&(this.#r=r.usage),e=T(r),yield r,e)return;continue}if(n.kind==="usage"){this.#r=n.usage;continue}this.#l(this.#p(n))}throw new s({code:"stream_truncated",message:"The run stream ended without a `done` or `error` event.",runId:this.#e})}finally{e||this.#s.abort(new s({code:"canceled",message:"The run ended before this tool finished."})),await Promise.allSettled([...this.#i]),this.#o.abort(),this.#u()}}#l(e){this.#i.add(e),e.finally(()=>this.#i.delete(e)).catch(()=>{})}async#p(e){if(e.kind==="tool_call")return this.#f(e);if(e.kind==="approval")return this.#g(e)}async#f(e){let n=this.#t.tools.get(e.name),r,o=!1;if(!n)r=`No tool named "${e.name}" is registered by this app.`,o=!0;else{let i={runId:this.#e,user:this.#t.user,callId:e.callId,signal:this.#s.signal};try{r=await n.execute(e.input,i)}catch(a){r=v(a),o=!0}}await this.#c(`/runs/${encodeURIComponent(this.#e)}/tool_result`,{callId:e.callId,result:N(r),isError:o})}async#g(e){let n="deny",r;if(!this.#t.approve)r="This app did not supply an approver, so escalations are denied.";else try{let o={runId:this.#e,approvalId:e.approvalId,tool:e.tool,input:e.input};e.cwd&&(o.cwd=e.cwd),n=await this.#t.approve(o)==="allow"?"allow":"deny"}catch(o){r=v(o)}await this.#c(`/runs/${encodeURIComponent(this.#e)}/approval`,{approvalId:e.approvalId,decision:n,...r?{reason:r}:{}})}async#c(e,n){if(!this.#e){this.#t.onWarning("Soba sent a frame before the run had an id, so it could not be answered.",n);return}try{await(await g(this.#t.config,{method:"POST",path:e,body:n})).text()}catch(r){this.#t.onWarning(`Could not deliver an answer to ${e}.`,f(r))}}};var $="https://api.soba.so/v1",oe=3e4,se=2,x=class{#e;#n;users;usage;connect;plans;constructor(e={}){let n=e.apiKey??E("SOBA_KEY")??E("SOBA_API_KEY");if(!n)throw new s({code:"unauthorized",message:"No Soba API key. Pass `apiKey`, or set SOBA_KEY. Keys are shaped sk_soba_<id>.<secret> and come from your dashboard."});if(ie()&&!e.dangerouslyAllowBrowser)throw new s({code:"invalid_request",message:"A Soba app key is a server credential and this looks like a browser. Call Soba from your server, or pass dangerouslyAllowBrowser if you are certain."});if(this.#n=e.onWarning??(()=>{}),this.#e={apiKey:n,baseURL:e.baseURL??E("SOBA_BASE_URL")??$,headers:e.headers??{},fetch:e.fetch??globalThis.fetch,connectTimeoutMs:e.connectTimeoutMs??oe,maxRetries:e.maxRetries??se},typeof this.#e.fetch!="function")throw new s({code:"invalid_request",message:"No global fetch. Run on Node 22 or newer, or pass your own `fetch`."});this.users={get:r=>this.request("GET",`/users/${encodeURIComponent(r)}`),compute:async r=>(await this.request("GET",`/users/${encodeURIComponent(r)}/compute`)).machines},this.usage={list:r=>this.request("GET","/usage",{query:{...r}})},this.connect=()=>this.request("GET","/connect"),this.plans={list:r=>this.request("GET","/plans",{...r?.user?{query:{user:r.user}}:{}})}}get baseURL(){return this.#e.baseURL}async run(e){if(!e.user)throw new s({code:"user_required",status:422,message:"`user` is required. A run with no user cannot be attributed or metered, so it cannot be defaulted."});if(!e.prompt&&!e.messages?.length)throw new s({code:"invalid_request",status:400,message:"A run needs a `prompt` or a non-empty `messages`."});let n=L(e.tools),r={user:e.user,model:e.model??"auto"};e.prompt&&(r.prompt=e.prompt),e.messages?.length&&(r.messages=e.messages),e.system&&(r.system=e.system),e.runtime&&(r.runtime=e.runtime),n.size&&(r.tools=D(n)),e.route&&(r.route=e.route),e.policy&&(r.policy=e.policy),e.metadata&&(r.metadata=e.metadata);let o=await g(this.#e,{method:"POST",path:"/runs",body:r,accept:"text/event-stream",signal:e.signal});return new h({config:this.#e,response:o,user:e.user,tools:n,approve:e.approve,onWarning:this.#n,signal:e.signal})}async request(e,n,r={}){return C(this.#e,{method:e,path:n,...r})}};function E(t){if(typeof process>"u")return;let e=process.env?.[t];return e||void 0}function ie(){let t=globalThis;return typeof t.window=="object"&&typeof t.window?.document=="object"}export{$ as DEFAULT_BASE_URL,_ as METERED_CLASSES,h as Run,x as Soba,s as SobaError,ne as TOOL_SLUGS,w as VERSION,te as isCostClass,ee as isMetered,T as isTerminal,re as tool};
@@ -174,6 +174,8 @@ export interface MachineListItem {
174
174
  }
175
175
  /** The app's name and connect key, for a page rendering the panel's frame. */
176
176
  export interface ConnectContextResponse {
177
+ /** How this app wants the connect component themed. */
178
+ theme?: "light" | "dark" | "system";
177
179
  app: {
178
180
  name: string;
179
181
  };
package/dist/version.d.ts CHANGED
@@ -1 +1 @@
1
- export declare const VERSION = "0.0.6";
1
+ export declare const VERSION = "0.0.7";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@soba-so/sdk",
3
- "version": "0.0.6",
3
+ "version": "0.0.7",
4
4
  "description": "One request that comes back finished, executed on compute the end user owns.",
5
5
  "license": "UNLICENSED",
6
6
  "homepage": "https://soba.so/docs/runs",
@@ -18,10 +18,6 @@
18
18
  "!dist/**/*.map",
19
19
  "README.md"
20
20
  ],
21
- "scripts": {
22
- "build": "node ../../scripts/build-sdk.mjs",
23
- "prepublishOnly": "node ../../scripts/build-sdk.mjs"
24
- },
25
21
  "engines": {
26
22
  "node": ">=22"
27
23
  },
@@ -34,9 +30,12 @@
34
30
  "byoc"
35
31
  ],
36
32
  "devDependencies": {
37
- "@soba-so/protocol": "workspace:*"
33
+ "@soba-so/protocol": "0.1.0"
38
34
  },
39
35
  "publishConfig": {
40
36
  "access": "public"
37
+ },
38
+ "scripts": {
39
+ "build": "node ../../scripts/build-sdk.mjs"
41
40
  }
42
- }
41
+ }