@north-light/cli 0.3.531 → 0.3.532
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/clients/attach/viewer.js +508 -508
- package/dist/core/llm/run.js +2 -2
- package/dist/core/peer/home.d.ts +6 -0
- package/dist/core/peer/home.js +2 -2
- package/dist/daemon/api/handlers/objects.js +3 -3
- package/dist/daemon/peer/forward.d.ts +7 -0
- package/dist/daemon/peer/forward.js +1 -1
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
package/dist/core/llm/run.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var be=Object.defineProperty;var u=(e,t)=>be(e,"name",{value:t,configurable:!0});import{randomUUID as ve}from"node:crypto";import{streamSimple as we}from"@earendil-works/pi-ai/compat";import{expandModelCandidates as ie,parseModelSpec as se,probeRouteAvailability as
|
|
1
|
+
var be=Object.defineProperty;var u=(e,t)=>be(e,"name",{value:t,configurable:!0});import{randomUUID as ve}from"node:crypto";import{streamSimple as we}from"@earendil-works/pi-ai/compat";import{APP_FAMILY as xe,expandModelCandidates as ie,parseModelSpec as se,probeRouteAvailability as ke}from"../model-routes.js";import{readMergedLaunchConfig as ae}from"../config.js";import{openModelRegistry as Me}from"../runtime/model-registry.js";import{MAX_RATE_LIMIT_COOLDOWN_MS as de,coolingUntilFor as le,isManagedProvider as H,markSubscriptionRateLimited as je,markSubscriptionSuccess as Ae,readSubscriptionPool as qe,retryAfterMsFromHeaders as K,retryAfterMsFromError as $e,refreshSubscriptionCredential as Re,subscriptionNeedsSuccessWrite as Ie}from"../subscription-state.js";import{classifyRateLimit as Ce,describeRateLimitScope as ce,rateLimitHeaders as Se}from"../rate-limit-scope.js";import{RunError as i}from"../runs/operations.js";import{recognizeProviderError as V}from"../provider-error-recognition.js";import{isSafetyRefusal as Oe}from"./refusal.js";import{assertUnderCap as Le,recordModelUsage as ue}from"../usage/ledger.js";import{outboundToken as Ee}from"../providers/mint.js";import{discardFile as Fe}from"../providers/token-cache.js";import{ProviderError as Ne}from"../providers/errors.js";import{appCandidates as De}from"./app-rungs.js";function Pe(e){return typeof e=="string"||e===null||Array.isArray(e)&&e.every(t=>t&&typeof t=="object"&&(t.type==="text"&&typeof t.text=="string"||t.type==="image_url"&&typeof t.image_url?.url=="string"&&/^data:image\/(png|jpeg|gif|webp);base64,[A-Za-z0-9+/]+={0,2}$/.test(t.image_url.url)))}u(Pe,"validContent");function fe(e){return Array.isArray(e)?e.map(t=>{if(t.type==="text")return t;const[,n,r]=/^data:(image\/(?:png|jpeg|gif|webp));base64,(.*)$/.exec(t.image_url.url);return{type:"image",mimeType:n,data:r}}):e??""}u(fe,"imageContent");function Te(e,t){const n=(e instanceof Error?e.message:String(e)).split("; stack=",1)[0],r=V({message:n}).kind;return r!=="connection"&&r!=="connection-only"?e:new i(503,"upstream_model_unavailable",n.slice(0,500),void 0,{served_model:t})}u(Te,"refreshFailure");function ct(e){if(!e||typeof e!="object"||Array.isArray(e))throw new i(400,"invalid_request","body must be an object");const t=e;if(!Array.isArray(t.messages)||!t.messages.every(n=>n&&typeof n=="object"&&["system","user","assistant","tool"].includes(n.role)&&Pe(n.content)))throw new i(400,"invalid_request","messages must be chat messages","messages");if(t.messages.some(n=>["system","assistant"].includes(n.role)&&typeof n.content!="string"&&n.content!==null))throw new i(400,"invalid_request","system and assistant content must be text","messages");if(t.model!==void 0&&typeof t.model!="string")throw new i(400,"invalid_request","model must be a string","model");if(t.model_policy!==void 0&&!["exact","substitute"].includes(t.model_policy))throw new i(400,"invalid_request","invalid model_policy","model_policy");if(t.payer!==void 0&&!["user","app"].includes(t.payer))throw new i(400,"invalid_request","invalid payer","payer");if(t.reasoning_effort!==void 0&&!["minimal","low","medium","high","xhigh","max"].includes(t.reasoning_effort))throw new i(400,"invalid_request","invalid reasoning_effort","reasoning_effort");if(t.stream!==void 0&&typeof t.stream!="boolean")throw new i(400,"invalid_request","stream must be boolean","stream");if(t.tools!==void 0&&(!Array.isArray(t.tools)||!t.tools.every(n=>n?.type==="function"&&typeof n.function?.name=="string"&&n.function.name.length>0&&(n.function.description===void 0||typeof n.function.description=="string")&&(n.function.parameters===void 0||n.function.parameters!==null&&typeof n.function.parameters=="object"&&!Array.isArray(n.function.parameters)&&n.function.parameters.type==="object"))))throw new i(400,"invalid_request","invalid tools","tools");if(t.tool_choice!==void 0&&t.tool_choice!=="auto"&&t.tool_choice!=="none"&&t.tool_choice!=="required"&&(typeof t.tool_choice!="object"||t.tool_choice===null||t.tool_choice.type!=="function"||typeof t.tool_choice.function?.name!="string"))throw new i(400,"invalid_request","invalid tool_choice","tool_choice");if(t.messages.some(n=>n.role==="assistant"&&n.tool_calls!==void 0&&(!Array.isArray(n.tool_calls)||!n.tool_calls.every(r=>r&&typeof r.id=="string"&&typeof r.function?.name=="string"&&typeof r.function.arguments=="string"&&Ue(r.function.arguments)))))throw new i(400,"invalid_request","invalid assistant tool_calls","messages");if(t.stop!==void 0&&!(typeof t.stop=="string"||Array.isArray(t.stop)&&t.stop.every(n=>typeof n=="string")))throw new i(400,"invalid_request","invalid stop","stop");if(t.seed!==void 0&&!Number.isSafeInteger(t.seed))throw new i(400,"invalid_request","invalid seed","seed");for(const[n,r]of[["temperature",t.temperature],["top_p",t.top_p],["max_tokens",t.max_tokens]])if(r!==void 0&&(typeof r!="number"||!Number.isFinite(r)||n==="temperature"&&(r<0||r>2)||n==="top_p"&&(r<0||r>1)||n==="max_tokens"&&(!Number.isSafeInteger(r)||r<1)))throw new i(400,"invalid_request",`invalid ${n}`,n);if(t.response_format!==void 0){const n=t.response_format;if(!n||typeof n!="object"||Array.isArray(n)||!["text","json_object","json_schema"].includes(n.type)||n.type==="json_schema"&&(typeof n.json_schema?.name!="string"||!n.json_schema.name||!n.json_schema.schema||typeof n.json_schema.schema!="object"||Array.isArray(n.json_schema.schema)))throw new i(400,"invalid_request","invalid response_format","response_format")}if(t.metadata!==void 0&&Buffer.byteLength(JSON.stringify(t.metadata)??"")>4096)throw new i(400,"invalid_request","metadata exceeds 4 KB","metadata");return t}u(ct,"parseLlmRequest");function Ue(e){try{const t=JSON.parse(e);return t!==null&&typeof t=="object"&&!Array.isArray(t)}catch{return!1}}u(Ue,"isJsonObject");function Je(e){const t=Date.now(),n=e.messages.map(a=>a.role==="system"?{role:"system",content:a.content??"",timestamp:t}:a.role==="tool"?{role:"toolResult",toolCallId:a.tool_call_id??"",toolName:"",content:typeof a.content=="string"||a.content===null?[{type:"text",text:a.content??""}]:fe(a.content),isError:!1,timestamp:t}:a.role==="assistant"?{role:"assistant",content:[...a.content?[{type:"text",text:a.content}]:[],...(a.tool_calls??[]).map(g=>({type:"toolCall",id:g.id,name:g.function.name,arguments:JSON.parse(g.function.arguments)}))],api:"openai-completions",provider:"openai",model:e.model??"",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:t}:{role:"user",content:fe(a.content),timestamp:t}),r=n.findIndex(a=>a.role!=="system"),k=n.slice(0,r<0?n.length:r).map(a=>a.content),_=k.join(`
|
|
2
2
|
|
|
3
|
-
`),l=e.tools?.map(({function:s})=>({name:s.name,description:s.description??"",parameters:s.parameters??{type:"object",properties:{}}}));return{...y?{systemPrompt:y}:{},messages:n.slice(w.length),...l?{tools:l}:{}}}u(Ue,"contextOf");function me(e,t,n,r){if(!e){const y=ae(n,r),l=Object.values({...y.modelRoutes??{},...y.legacyModelRoutes??{}}),s=l.length?[y.modelLadders.defaultProvider,...y.modelRouting?.familyOrder??[],...l.map(g=>g.family)].find(g=>l.some(E=>E.family===g)):y.modelLadders.defaultProvider??"anthropic";return{kind:"logical",family:s,strength:"strong",spec:`${s}/strong`}}const w=/^([^/]+)\/(ultra|strong|medium|light)$/.exec(e);return w?{kind:"logical",family:w[1],strength:w[2],spec:e}:{kind:t==="exact"?"exact":"concrete",spec:e}}u(me,"requestFor");function Je(e,t){const{input:n,output:r,cacheRead:w,cacheWrite:y}=e.cost;return n===0&&r===0&&w===0&&y===0?null:Number.isFinite(t)&&t>=0?t:null}u(Je,"usdEquivalent");function We(e,t){return e.compat?.allowedFallbackModels?.find(r=>r.provider===e.provider&&r.model===t)}u(We,"allowedFallback");function ct(e){return e?{payer:e.payer??"user",sub:e.sub,grantee:e.grantee,inference_endpoint:e.inference_endpoint??null}:void 0}u(ct,"llmCallerOf");function He(e){return e instanceof Ne?e.code==="server_error"?new i(503,"upstream_model_unavailable",e.message):new i(404,"model_unavailable",e.message):e}u(He,"mintFailure");const Ke=/\bmodel is not supported when using Codex with a ChatGPT account\b/i;function ze(e,t,n){if(!(e!=="openai-codex"||t===void 0||!Ke.test(t)))return new i(404,"model_unavailable",t,void 0,{served_model:n})}u(ze,"codexAccountModelRejection");async function ut(e,t,n,r,w,y){const l=y?.payer==="app"?y:void 0;if(e.payer==="app"&&!l)throw new i(403,"payer_not_app","this grant is not app-paid");if(e.payer==="user"&&l)throw new i(400,"invalid_request","this grant is app-paid; payer cannot be user","payer");if(l&&!l.inference_endpoint)throw new i(404,"model_unavailable",`${l.grantee} is app-paid but its grant carries no inference endpoint`);const s=l?.inference_endpoint??void 0;l||await Oe(w);const g=await ke(),E=u(c=>c.routeId!=="concrete"&&c.routeId!=="exact","configured"),ee=u(c=>{const h=g.find(c.providerId,c.modelId);return h!==void 0&&(!e.reasoning_effort||h.reasoning)&&(e.seed===void 0&&e.response_format===void 0||h.api==="openai-completions")&&(e.stop===void 0||["openai-completions","anthropic-messages"].includes(h.api))},"matchesFeatures"),pe=u(()=>{const c=me(e.model,e.model_policy,r?.cwd,r?.profileId),h=ie(c.kind==="exact"?{kind:"concrete",spec:c.spec}:c,r?.cwd,r?.profileId).filter(E);let a;if(c.kind==="logical")a=e.model_policy==="exact"?h.filter(m=>m.family===c.family&&m.strength===c.strength).slice(0,1):h;else{const m=se(c.spec),q=h.filter(j=>j.providerId===m?.providerId&&j.modelId===m.modelId&&(e.model_policy!=="exact"||j.thinkingLevel===m.thinkingLevel)&&ee(j));if(e.model_policy==="exact")a=q.slice(0,1);else if(q.length)a=q;else{const j=ae(r?.cwd,r?.profileId),x=[...Object.values(j.modelRoutes??{}).flatMap(v=>Object.entries(v.models)),...[j.modelLadders.anthropic,j.modelLadders.openai].flatMap(v=>Object.entries(v))].find(([,v])=>v===c.spec)?.[0],f=me(void 0,"substitute",r?.cwd,r?.profileId);a=x&&f.kind==="logical"?ie({...f,strength:x,spec:c.spec},r?.cwd,r?.profileId).filter(v=>E(v)&&v.strength===x):[]}}return a},"ownerCandidates");let R;if(s?R=De(s,e.model,e.model_policy==="exact").flatMap((c,h)=>{const a=se(c.model);return a?[{routeId:"app",credentialSource:"app",family:"app",strength:c.strength,...a,rank:h}]:[]}):R=pe(),R=R.filter(ee),R.length===0)throw e.model_policy==="exact"?new i(400,"substitution_refused","no eligible model route is configured"):new i(404,"model_unavailable","no eligible model route is configured");const te=`chatcmpl-${ve()}`;let I=1/0,b,z;for(const c of R){if(!l&&!xe(c,g).authenticated)continue;const h=g.find(c.providerId,c.modelId);if(!h)continue;const a=s?{...h,baseUrl:`${s.base_url}/${h.provider}`}:h,m=c.providerId,q=!l&&H(m)?Ae(m).filter(x=>!x.authFailure):[],j=q.filter(x=>le(x,a.id)<=Date.now());if(q.length&&!j.length){const x=Math.min(...q.map(f=>le(f,a.id)));x<I&&(I=x,z=`${a.provider}/${a.id}`);continue}const oe=l?[void 0,void 0]:q.length?j:[void 0];for(const[x,f]of oe.entries()){const v=Date.now();let ne=f?.access;if(f&&f.expires<=Date.now()&&H(m)){const o=g.getProvider(m)?.auth.oauth;if(!o)throw new i(503,"upstream_model_unavailable",`no OAuth refresh for ${m}`,void 0,{served_model:`${a.provider}/${a.id}`});ne=(await $e(m,f.label,async(k,re)=>{const W=await o.refresh({type:"oauth",refresh:k,access:"",expires:0,...re?{clientId:re}:{}},t??new AbortController().signal).catch(ge=>{throw Te(ge,`${a.provider}/${a.id}`)}),V=W.clientId;return{refresh:W.refresh,access:W.access,expires:W.expires,...typeof V=="string"&&V?{clientId:V}:{}}})).access}const he=Ue(e);let N;if(l&&s)try{N=await Le({audience:s.base_url,sub:l.sub,grantee:l.grantee,initiating_app:l.grantee,scope:["crtr:llm"]},{signal:t})}catch(o){throw He(o)}const C=f||l?void 0:await g.getApiKeyAndHeaders(a);if(C&&!C.ok)continue;const p=`${a.provider}/${a.id}`,S=e.model??p;let A=!1,L,M=3e4,$;const B=[],X=[],D=[];let d,F;const T=u((o,_=null)=>({id:te,object:"chat.completion.chunk",created:Math.floor(v/1e3),model:p,served_model:p,requested_model:S,substituted:S!==p&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(S),choices:[{index:0,delta:o,finish_reason:_}]}),"chunk"),P=u(o=>{B.push(o),n?.(o)},"emit"),_e=we(a,he,{apiKey:N?.access_token??ne??(C?.ok?C.apiKey:void 0),...C?.ok?{headers:C.headers}:{},signal:t,reasoning:e.reasoning_effort??c.thinkingLevel,...e.temperature!==void 0?{temperature:e.temperature}:{},...e.max_tokens!==void 0?{maxTokens:e.max_tokens}:{},...e.top_p!==void 0?{samplingParams:{top_p:e.top_p}}:{},...e.tool_choice==="none"?{toolChoice:"none"}:{},onPayload:u(o=>{if(!o||typeof o!="object")return;const _=e.tool_choice,k=_==="required"?a.api==="anthropic-messages"?{type:"any"}:"required":typeof _=="object"&&_!==null?a.api==="anthropic-messages"?{type:"tool",name:_.function.name}:_:void 0;return{...o,...k?{tool_choice:k}:{},...e.stop!==void 0?{[a.api==="anthropic-messages"?"stop_sequences":"stop"]:typeof e.stop=="string"?[e.stop]:e.stop}:{},...e.seed!==void 0?{seed:e.seed}:{},...e.response_format!==void 0?{response_format:e.response_format}:{}}},"onPayload"),fetch:u(async(o,_)=>{const k=await fetch(o,_);return L=k.status,k.status===429&&(A=!0,$=k.headers,M=K(k.headers)??15e3),k},"fetch"),onResponse:u(o=>{o.status===429&&(A=!0,$=o.headers,M=K(o.headers)??15e3)},"onResponse")});try{for await(const o of _e)o.type==="text_delta"&&(X.push(o.delta),P(T({content:o.delta}))),o.type==="thinking_delta"&&(D.push(o.delta),P(T({reasoning_content:o.delta}))),o.type==="done"&&(d=o.message),o.type==="error"&&(d=o.error)}catch(o){const _=qe(o);$===void 0&&o&&typeof o=="object"&&"headers"in o&&Object.keys(Ce(o.headers)).length&&($=o.headers);const k=Y({status:o&&typeof o=="object"&&"status"in o?o.status:void 0,message:o instanceof Error?o.message:String(o)});if(l)F=o;else{if(!A&&k.kind!=="rate-limit")throw B.length?new i(503,"upstream_model_unavailable",o instanceof Error?o.message:String(o),void 0,{served_model:p}):o;A=!0,M=_??M}}if(l){if(L===401){if(N&&Ee(N.key),x===0)continue;throw new i(404,"model_unavailable",`${s.base_url} refuses this runtime's tokens`,void 0,{served_model:p})}if(A&&K($)===void 0)throw new i(503,"upstream_model_unavailable",`${p} was rate-limited without a retry-after`,void 0,{served_model:p});if(!A&&(F!==void 0||L!==void 0&&L>=500))throw new i(503,"upstream_model_unavailable",F instanceof Error?F.message:d?.errorMessage??"inference endpoint failed",void 0,{served_model:p})}if(!A&&d?.stopReason==="error"&&Y({message:d.errorMessage}).kind==="rate-limit"&&(A=!0,M=15e3),A){const o=Ie($,a.id);if(K($)===void 0&&o.resetAt!==void 0&&(M=Math.max(M,o.resetAt-Date.now())),b={provider:m,model:a.id,...f?{account:f.label}:{},observation:o},console.error(`[llm] 429 from ${p}${f?` account "${f.label}"`:""}: scope=${ce(o.scope)} retry_after_ms=${M} headers=${JSON.stringify(o.headers)}`),f&&H(m)&&await je(m,f.label,M,v,Date.now(),o.scope),Date.now()+Math.min(M,de)<I&&(I=Date.now()+Math.min(M,de),z=p),X.length||D.length)throw new i(503,"service_unavailable","vendor rate limit after output began",void 0,{served_model:p});if(l)break;continue}const U=Se(d);if(L===400&&e.tool_choice!==void 0&&e.tool_choice!=="auto"&&e.tool_choice!=="none"&&/\btool[_ ]choice\b/i.test(d?.errorMessage??"")&&/not supported|does not support|unsupported|cannot|must be auto/i.test(d?.errorMessage??""))throw new i(400,"invalid_request",d.errorMessage,"tool_choice",{served_model:p});if(d?.stopReason==="error"){const o=ze(a.provider,d.errorMessage,p);if(o)throw o}if(!d||d.stopReason==="error"&&!U||d.stopReason==="aborted")throw new i(503,"upstream_model_unavailable",d?.errorMessage??"model request failed",void 0,{served_model:p});f&&H(m)&&Re(f,a.id)&&await Me(m,f.label,v,a.id);const G=d.content.filter(o=>o.type==="toolCall").map(o=>({id:o.id,type:"function",function:{name:o.name,arguments:JSON.stringify(o.arguments)}})),Z=U?"content_filter":d.stopReason==="toolUse"?"tool_calls":d.stopReason==="length"?"length":"stop",Q=d.responseModel?We(a,d.responseModel):void 0,O=Q?`${a.provider}/${Q.model}`:p,J={prompt_tokens:d.usage.input,completion_tokens:d.usage.output,total_tokens:d.usage.totalTokens,cache_read_tokens:d.usage.cacheRead,cache_write_tokens:d.usage.cacheWrite,usd_equivalent:Je(Q??a,d.usage.cost.total),served_model:O};l?await ue(l.grantee,"app",O,d.usage,J.usd_equivalent):w&&await ue(w.grantee,"user",O,d.usage,J.usd_equivalent);const ye={id:te,object:"chat.completion",created:Math.floor(v/1e3),model:O,served_model:O,requested_model:S,substituted:S!==O&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(S),choices:[{index:0,message:{role:"assistant",content:X.join("")||null,...D.length?{reasoning_content:D.join("")}:{},...G.length?{tool_calls:G}:{},...U?{refusal:d.errorMessage??"Content filtered"}:{}},finish_reason:Z}],usage:J,...e.metadata!==void 0?{metadata:e.metadata}:{}};for(const[o,_]of G.entries())P(T({tool_calls:[{index:o,..._}]}));return P({...T({},Z),...U?{choices:[{index:0,delta:{},finish_reason:Z,message:{refusal:d.errorMessage??"Content filtered"}}]}:{},usage:J}),{completion:ye,chunks:B}}}throw I!==1/0?new i(429,"all_routes_exhausted","all eligible model routes are rate-limited",void 0,{retry_after_s:Math.max(1,Math.ceil((I-Date.now())/1e3)),served_model:b?`${b.provider}/${b.model}`:z,...b?{rate_limit:{provider:b.provider,model:b.model,...b.account?{account:b.account}:{},scope:ce(b.observation.scope),...b.observation.claim?{claim:b.observation.claim}:{},headers:b.observation.headers}}:{}},void 0,!0):e.model_policy==="exact"?new i(400,"substitution_refused","the requested model is unavailable"):new i(404,"model_unavailable","no usable model route is available")}u(ut,"runLlm");export{ct as llmCallerOf,lt as parseLlmRequest,ut as runLlm};
|
|
3
|
+
`),s=e.tools?.map(({function:a})=>({name:a.name,description:a.description??"",parameters:a.parameters??{type:"object",properties:{}}}));return{..._?{systemPrompt:_}:{},messages:n.slice(k.length),...s?{tools:s}:{}}}u(Je,"contextOf");function me(e,t,n,r){const k=u(()=>{const s=ae(n,r),a=Object.values({...s.modelRoutes??{},...s.legacyModelRoutes??{}});return a.length?[s.modelLadders.defaultProvider,...s.modelRouting?.familyOrder??[],...a.map(g=>g.family)].find(g=>a.some(E=>E.family===g)):s.modelLadders.defaultProvider??"anthropic"},"ownerFamily");if(!e){const s=k();return{kind:"logical",family:s,strength:"strong",spec:`${s}/strong`}}const _=/^([^/]+)\/(ultra|strong|medium|light)$/.exec(e);if(_){if(_[1]===xe){const s=k();return{kind:"logical",family:s,strength:_[2],spec:`${s}/${_[2]}`}}return{kind:"logical",family:_[1],strength:_[2],spec:e}}return{kind:t==="exact"?"exact":"concrete",spec:e}}u(me,"requestFor");function We(e,t){const{input:n,output:r,cacheRead:k,cacheWrite:_}=e.cost;return n===0&&r===0&&k===0&&_===0?null:Number.isFinite(t)&&t>=0?t:null}u(We,"usdEquivalent");function He(e,t){return e.compat?.allowedFallbackModels?.find(r=>r.provider===e.provider&&r.model===t)}u(He,"allowedFallback");function ut(e){return e?{payer:e.payer??"user",sub:e.sub,grantee:e.grantee,inference_endpoint:e.inference_endpoint??null}:void 0}u(ut,"llmCallerOf");function Ke(e){return e instanceof Ne?e.code==="server_error"?new i(503,"upstream_model_unavailable",e.message):new i(404,"model_unavailable",e.message):e}u(Ke,"mintFailure");const ze=/\bmodel is not supported when using Codex with a ChatGPT account\b/i;function Be(e,t,n){if(!(e!=="openai-codex"||t===void 0||!ze.test(t)))return new i(404,"model_unavailable",t,void 0,{served_model:n})}u(Be,"codexAccountModelRejection");async function ft(e,t,n,r,k,_){const s=_?.payer==="app"?_:void 0;if(e.payer==="app"&&!s)throw new i(403,"payer_not_app","this grant is not app-paid");if(e.payer==="user"&&s)throw new i(400,"invalid_request","this grant is app-paid; payer cannot be user","payer");if(s&&!s.inference_endpoint)throw new i(404,"model_unavailable",`${s.grantee} is app-paid but its grant carries no inference endpoint`);const a=s?.inference_endpoint??void 0;s||await Le(k);const g=await Me(),E=u(c=>c.routeId!=="concrete"&&c.routeId!=="exact","configured"),ee=u(c=>{const h=g.find(c.providerId,c.modelId);return h!==void 0&&(!e.reasoning_effort||h.reasoning)&&(e.seed===void 0&&e.response_format===void 0||h.api==="openai-completions")&&(e.stop===void 0||["openai-completions","anthropic-messages"].includes(h.api))},"matchesFeatures"),pe=u(()=>{const c=me(e.model,e.model_policy,r?.cwd,r?.profileId),h=ie(c.kind==="exact"?{kind:"concrete",spec:c.spec}:c,r?.cwd,r?.profileId).filter(E);let d;if(c.kind==="logical")d=e.model_policy==="exact"?h.filter(m=>m.family===c.family&&m.strength===c.strength).slice(0,1):h;else{const m=se(c.spec),q=h.filter(M=>M.providerId===m?.providerId&&M.modelId===m.modelId&&(e.model_policy!=="exact"||M.thinkingLevel===m.thinkingLevel)&&ee(M));if(e.model_policy==="exact")d=q.slice(0,1);else if(q.length)d=q;else{const M=ae(r?.cwd,r?.profileId),w=[...Object.values(M.modelRoutes??{}).flatMap(v=>Object.entries(v.models)),...[M.modelLadders.anthropic,M.modelLadders.openai].flatMap(v=>Object.entries(v))].find(([,v])=>v===c.spec)?.[0],f=me(void 0,"substitute",r?.cwd,r?.profileId);d=w&&f.kind==="logical"?ie({...f,strength:w,spec:c.spec},r?.cwd,r?.profileId).filter(v=>E(v)&&v.strength===w):[]}}return d},"ownerCandidates");let R;if(a?R=De(a,e.model,e.model_policy==="exact").flatMap((c,h)=>{const d=se(c.model);return d?[{routeId:"app",credentialSource:"app",family:"app",strength:c.strength,...d,rank:h}]:[]}):R=pe(),R=R.filter(ee),R.length===0)throw e.model_policy==="exact"?new i(400,"substitution_refused","no eligible model route is configured"):new i(404,"model_unavailable","no eligible model route is configured");const te=`chatcmpl-${ve()}`;let I=1/0,b,z;for(const c of R){if(!s&&!ke(c,g).authenticated)continue;const h=g.find(c.providerId,c.modelId);if(!h)continue;const d=a?{...h,baseUrl:`${a.base_url}/${h.provider}`}:h,m=c.providerId,q=!s&&H(m)?qe(m).filter(w=>!w.authFailure):[],M=q.filter(w=>le(w,d.id)<=Date.now());if(q.length&&!M.length){const w=Math.min(...q.map(f=>le(f,d.id)));w<I&&(I=w,z=`${d.provider}/${d.id}`);continue}const oe=s?[void 0,void 0]:q.length?M:[void 0];for(const[w,f]of oe.entries()){const v=Date.now();let ne=f?.access;if(f&&f.expires<=Date.now()&&H(m)){const o=g.getProvider(m)?.auth.oauth;if(!o)throw new i(503,"upstream_model_unavailable",`no OAuth refresh for ${m}`,void 0,{served_model:`${d.provider}/${d.id}`});ne=(await Re(m,f.label,async(x,re)=>{const W=await o.refresh({type:"oauth",refresh:x,access:"",expires:0,...re?{clientId:re}:{}},t??new AbortController().signal).catch(ge=>{throw Te(ge,`${d.provider}/${d.id}`)}),Q=W.clientId;return{refresh:W.refresh,access:W.access,expires:W.expires,...typeof Q=="string"&&Q?{clientId:Q}:{}}})).access}const he=Je(e);let F;if(s&&a)try{F=await Ee({audience:a.base_url,sub:s.sub,grantee:s.grantee,initiating_app:s.grantee,scope:["crtr:llm"]},{signal:t})}catch(o){throw Ke(o)}const C=f||s?void 0:await g.getApiKeyAndHeaders(d);if(C&&!C.ok)continue;const p=`${d.provider}/${d.id}`,S=e.model??p;let A=!1,L,j=3e4,$;const B=[],X=[],N=[];let l,D;const P=u((o,y=null)=>({id:te,object:"chat.completion.chunk",created:Math.floor(v/1e3),model:p,served_model:p,requested_model:S,substituted:S!==p&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(S),choices:[{index:0,delta:o,finish_reason:y}]}),"chunk"),T=u(o=>{B.push(o),n?.(o)},"emit"),_e=we(d,he,{apiKey:F?.access_token??ne??(C?.ok?C.apiKey:void 0),...C?.ok?{headers:C.headers}:{},signal:t,reasoning:e.reasoning_effort??c.thinkingLevel,...e.temperature!==void 0?{temperature:e.temperature}:{},...e.max_tokens!==void 0?{maxTokens:e.max_tokens}:{},...e.top_p!==void 0?{samplingParams:{top_p:e.top_p}}:{},...e.tool_choice==="none"?{toolChoice:"none"}:{},onPayload:u(o=>{if(!o||typeof o!="object")return;const y=e.tool_choice,x=y==="required"?d.api==="anthropic-messages"?{type:"any"}:"required":typeof y=="object"&&y!==null?d.api==="anthropic-messages"?{type:"tool",name:y.function.name}:y:void 0;return{...o,...x?{tool_choice:x}:{},...e.stop!==void 0?{[d.api==="anthropic-messages"?"stop_sequences":"stop"]:typeof e.stop=="string"?[e.stop]:e.stop}:{},...e.seed!==void 0?{seed:e.seed}:{},...e.response_format!==void 0?{response_format:e.response_format}:{}}},"onPayload"),fetch:u(async(o,y)=>{const x=await fetch(o,y);return L=x.status,x.status===429&&(A=!0,$=x.headers,j=K(x.headers)??15e3),x},"fetch"),onResponse:u(o=>{o.status===429&&(A=!0,$=o.headers,j=K(o.headers)??15e3)},"onResponse")});try{for await(const o of _e)o.type==="text_delta"&&(X.push(o.delta),T(P({content:o.delta}))),o.type==="thinking_delta"&&(N.push(o.delta),T(P({reasoning_content:o.delta}))),o.type==="done"&&(l=o.message),o.type==="error"&&(l=o.error)}catch(o){const y=$e(o);$===void 0&&o&&typeof o=="object"&&"headers"in o&&Object.keys(Se(o.headers)).length&&($=o.headers);const x=V({status:o&&typeof o=="object"&&"status"in o?o.status:void 0,message:o instanceof Error?o.message:String(o)});if(s)D=o;else{if(!A&&x.kind!=="rate-limit")throw B.length?new i(503,"upstream_model_unavailable",o instanceof Error?o.message:String(o),void 0,{served_model:p}):o;A=!0,j=y??j}}if(s){if(L===401){if(F&&Fe(F.key),w===0)continue;throw new i(404,"model_unavailable",`${a.base_url} refuses this runtime's tokens`,void 0,{served_model:p})}if(A&&K($)===void 0)throw new i(503,"upstream_model_unavailable",`${p} was rate-limited without a retry-after`,void 0,{served_model:p});if(!A&&(D!==void 0||L!==void 0&&L>=500))throw new i(503,"upstream_model_unavailable",D instanceof Error?D.message:l?.errorMessage??"inference endpoint failed",void 0,{served_model:p})}if(!A&&l?.stopReason==="error"&&V({message:l.errorMessage}).kind==="rate-limit"&&(A=!0,j=15e3),A){const o=Ce($,d.id);if(K($)===void 0&&o.resetAt!==void 0&&(j=Math.max(j,o.resetAt-Date.now())),b={provider:m,model:d.id,...f?{account:f.label}:{},observation:o},console.error(`[llm] 429 from ${p}${f?` account "${f.label}"`:""}: scope=${ce(o.scope)} retry_after_ms=${j} headers=${JSON.stringify(o.headers)}`),f&&H(m)&&await je(m,f.label,j,v,Date.now(),o.scope),Date.now()+Math.min(j,de)<I&&(I=Date.now()+Math.min(j,de),z=p),X.length||N.length)throw new i(503,"service_unavailable","vendor rate limit after output began",void 0,{served_model:p});if(s)break;continue}const U=Oe(l);if(L===400&&e.tool_choice!==void 0&&e.tool_choice!=="auto"&&e.tool_choice!=="none"&&/\btool[_ ]choice\b/i.test(l?.errorMessage??"")&&/not supported|does not support|unsupported|cannot|must be auto/i.test(l?.errorMessage??""))throw new i(400,"invalid_request",l.errorMessage,"tool_choice",{served_model:p});if(l?.stopReason==="error"){const o=Be(d.provider,l.errorMessage,p);if(o)throw o}if(!l||l.stopReason==="error"&&!U||l.stopReason==="aborted")throw new i(503,"upstream_model_unavailable",l?.errorMessage??"model request failed",void 0,{served_model:p});f&&H(m)&&Ie(f,d.id)&&await Ae(m,f.label,v,d.id);const G=l.content.filter(o=>o.type==="toolCall").map(o=>({id:o.id,type:"function",function:{name:o.name,arguments:JSON.stringify(o.arguments)}})),Y=U?"content_filter":l.stopReason==="toolUse"?"tool_calls":l.stopReason==="length"?"length":"stop",Z=l.responseModel?He(d,l.responseModel):void 0,O=Z?`${d.provider}/${Z.model}`:p,J={prompt_tokens:l.usage.input,completion_tokens:l.usage.output,total_tokens:l.usage.totalTokens,cache_read_tokens:l.usage.cacheRead,cache_write_tokens:l.usage.cacheWrite,usd_equivalent:We(Z??d,l.usage.cost.total),served_model:O};s?await ue(s.grantee,"app",O,l.usage,J.usd_equivalent):k&&await ue(k.grantee,"user",O,l.usage,J.usd_equivalent);const ye={id:te,object:"chat.completion",created:Math.floor(v/1e3),model:O,served_model:O,requested_model:S,substituted:S!==O&&!/^([^/]+)\/(ultra|strong|medium|light)$/.test(S),choices:[{index:0,message:{role:"assistant",content:X.join("")||null,...N.length?{reasoning_content:N.join("")}:{},...G.length?{tool_calls:G}:{},...U?{refusal:l.errorMessage??"Content filtered"}:{}},finish_reason:Y}],usage:J,...e.metadata!==void 0?{metadata:e.metadata}:{}};for(const[o,y]of G.entries())T(P({tool_calls:[{index:o,...y}]}));return T({...P({},Y),...U?{choices:[{index:0,delta:{},finish_reason:Y,message:{refusal:l.errorMessage??"Content filtered"}}]}:{},usage:J}),{completion:ye,chunks:B}}}throw I!==1/0?new i(429,"all_routes_exhausted","all eligible model routes are rate-limited",void 0,{retry_after_s:Math.max(1,Math.ceil((I-Date.now())/1e3)),served_model:b?`${b.provider}/${b.model}`:z,...b?{rate_limit:{provider:b.provider,model:b.model,...b.account?{account:b.account}:{},scope:ce(b.observation.scope),...b.observation.claim?{claim:b.observation.claim}:{},headers:b.observation.headers}}:{}},void 0,!0):e.model_policy==="exact"?new i(400,"substitution_refused","the requested model is unavailable"):new i(404,"model_unavailable","no usable model route is available")}u(ft,"runLlm");export{ut as llmCallerOf,ct as parseLlmRequest,ft as runLlm};
|
package/dist/core/peer/home.d.ts
CHANGED
|
@@ -29,6 +29,12 @@ export declare const defaultHomeDeps: HomeDeps;
|
|
|
29
29
|
export declare function cachedLocation(db: CanvasDb, id: string): Promise<string | null>;
|
|
30
30
|
export declare function rememberLocation(db: CanvasDb, id: string, machine: string, now?: number): Promise<void>;
|
|
31
31
|
export declare function dropLocation(db: CanvasDb, id: string): Promise<void>;
|
|
32
|
+
/** The machines a lookup asks: every runtime of the account but this one (and `skip`), or `unknown` when the directory cannot list them.
|
|
33
|
+
* Empty for an unjoined daemon. */
|
|
34
|
+
export declare function peersToAsk(deps: HomeDeps, skip?: string): Promise<Machine[] | {
|
|
35
|
+
where: 'unknown';
|
|
36
|
+
unreachable: string[];
|
|
37
|
+
}>;
|
|
32
38
|
/** Ask every other machine "do you hold `id`?". First `here`/`moved` wins; unreachable machines are listed. */
|
|
33
39
|
export declare function locate(db: CanvasDb, id: string, deps?: HomeDeps, skip?: string): Promise<HomeAnswer>;
|
|
34
40
|
/** Where `id` lives. `hint` is the machine the request names (`?machine=`). */
|
package/dist/core/peer/home.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
2
|
-
ON CONFLICT(id) DO UPDATE SET machine_id = excluded.machine_id, learned_at = excluded.learned_at`).run(a,
|
|
1
|
+
var d=Object.defineProperty;var c=(e,n)=>d(e,"name",{value:n,configurable:!0});import{getById as p}from"../graph/objects.js";import{isUnreachable as _,peerCall as y}from"./client.js";import{directoryIssuer as E,listMachines as x,normalizeMachineId as w,ownMachineId as b}from"./directory.js";import{stubOf as O}from"./stubs.js";const l={call:c((e,n)=>y(e,n),"call"),machines:x,self:b,now:Date.now,joined:c(()=>E()!==null,"joined")};async function T(e,n){return(await e.prepare("SELECT machine_id FROM peer_locations WHERE id = ?").get(n))?.machine_id??null}c(T,"cachedLocation");async function I(e,n,a,i=Date.now()){await e.prepare(`INSERT INTO peer_locations (id, machine_id, learned_at) VALUES (?, ?, ?)
|
|
2
|
+
ON CONFLICT(id) DO UPDATE SET machine_id = excluded.machine_id, learned_at = excluded.learned_at`).run(n,a,i)}c(I,"rememberLocation");async function L(e,n){await e.prepare("DELETE FROM peer_locations WHERE id = ?").run(n)}c(L,"dropLocation");async function g(e,n){if(!e.joined())return[];let a;try{a=await e.machines()}catch(r){return{where:"unknown",unreachable:[`directory (${r instanceof Error?r.message:String(r)})`]}}const i=e.self();return a.filter(r=>r.machine_id!==i&&r.machine_id!==n&&r.kind!=="device")}c(g,"peersToAsk");async function f(e,n,a=l,i){const r=await g(a,i);if("where"in r)return r;const o=await Promise.all(r.map(async t=>{const h=await a.call(t.machine_id,{method:"POST",path:"/v1/peer/locate",body:{id:n}});if(_(h))return{m:t,state:"unreachable"};const s=h.body;return h.status===200&&s?.answer==="here"?{m:t,state:"here",machine:t.machine_id}:h.status===200&&s?.answer==="moved"&&typeof s.machine=="string"?{m:t,state:"here",machine:w(s.machine)}:h.status===200&&s?.answer==="no"?{m:t,state:"no"}:{m:t,state:"unreachable"}})),u=o.find(t=>t.state==="here");if(u&&"machine"in u)return await I(e,n,u.machine,a.now()),{where:"machine",machine:u.machine,source:"locate"};const m=o.filter(t=>t.state==="unreachable").map(t=>t.m.name||t.m.machine_id);return m.length>0?{where:"unknown",unreachable:m}:{where:"nowhere"}}c(f,"locate");async function C(e,n,a={}){const i=await p(e,n);if(i!==null){const o=await O(e,i);return o===null?{where:"here"}:{where:"machine",machine:o.home_machine,source:"stub"}}if(!(a.deps??l).joined())return{where:"nowhere"};if(a.hint)return{where:"machine",machine:w(a.hint),source:"hint"};const r=await T(e,n);return r!==null?{where:"machine",machine:r,source:"cache"}:f(e,n,a.deps)}c(C,"homeOf");async function N(e,n,a,i=l){return await L(e,n),f(e,n,i,a)}c(N,"relocate");export{T as cachedLocation,l as defaultHomeDeps,L as dropLocation,C as homeOf,f as locate,g as peersToAsk,N as relocate,I as rememberLocation};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var $e=Object.defineProperty;var l=(e,t)=>$e(e,"name",{value:t,configurable:!0});import{ApiError as y}from"../../../api/errors.js";import{PRIVACY_LEVELS_DTO as Ae}from"../../../api/dto/objects.js";import{openDb as
|
|
2
|
-
content unavailable: ${r.unavailable}`,data:{...f,content:"markdown"in r?"live":"unavailable"}}})}l(et,"read");function Y(e,t,a,n){if(e!=null){if(!a.includes(e)){n.push({field:t,problem:`must be one of ${a.join(", ")}`,received:e});return}return e}}l(Y,"oneOf");async function be(e,t,a){if(t!=null){if(typeof t!="string"||!await De(e,t)){a.push({field:"type",problem:`must be a kind: one of ${(await Me(e)).join(", ")}`,received:t});return}return t}}l(be,"kindName");function je(e,t,a,n){if(e==null)return n;const i=Number(e);return!Number.isInteger(i)||i<1||i>100?(a.push({field:t,problem:"must be an integer from 1 to 100",received:e}),n):i}l(je,"limitOf");async function _e(e){const t=e.query,a=[],n=await be(await T(),t.get("type"),a),i=Y(t.get("privacy"),"privacy",Ae,a),o=je(t.get("limit"),"limit",a,50),r=t.get("cursor");r!==null&&!/^\d+$/.test(r)&&a.push({field:"cursor",problem:"is not a cursor from a previous page",received:r});const s=t.get("deleted");return s!==null&&!["0","1","true","false"].includes(s)&&a.push({field:"deleted",problem:"must be true or false",received:s}),a.length>0&&C("object list request",a),await _(async c=>{const u=await v(c,e),f={...n?{type:n}:{},...i?{privacy:i}:{},...t.get("kind")!==null?{kind:t.get("kind")}:{},...s==="1"||s==="true"?{deleted:!0}:{}},h=t.get("owner");if(h!==null){const d=await he(c,u,h);if(d===null)return{items:[],next_cursor:null};f.owner=d}const g=t.get("name"),j=[];let m=r===null?0:Number(r),p=!0;for(;j.length<o&&p;){const d=await Ge(c,u,f,{limit:100,after_rowid:m});p=d.length===100;for(const E of d)if(m=E.rowid,(g===null||E.name.startsWith(g))&&j.push(E),j.length===o)break}const w=j.at(-1);return{items:await de(j,async d=>await me(c,d)),next_cursor:j.length===o&&w?String(w.rowid):null}})}l(_e,"listLocal");const tt={ms:3e4},nt="self",X=l((e,t)=>e.map(a=>({...a,machine:t})),"labelItems");async function ke(e,t,a,n){const i=S.current;try{const o=await i.call(t.id,{method:"GET",path:"/v1/objects",query:a},await i.envelope(e.principal),n);if(Ye(o))return{state:"unreachable",items:[],next:null};if(o.status===426)return{state:"too_old",items:[],next:null};const r=o.body;return o.status!==200||!Array.isArray(r?.items)?{state:"unreachable",items:[],next:null}:{state:"ok",items:X(r.items,t),next:r.next_cursor??null}}catch{return{state:"unreachable",items:[],next:null}}}l(ke,"remotePage");async function at(e){const t=new Promise(a=>e.addEventListener("abort",()=>a(null),{once:!0}));return Promise.race([S.current.machines().catch(()=>null),t])}l(at,"machinesWithin");async function it(e){const t=e.query.get("machine");if(!le(e.principal)||!S.current.joined()||t===nt)return await _e(ve(e));const n=S.current.self(),i=t!==null&&A(t)!==n,o=i?null:await _e(ve(e)),r=new AbortController,s=setTimeout(()=>r.abort(),tt.ms);s.unref?.();try{const c=await at(r.signal);if(c===null){if(i)throw new y(503,"runtime_unreachable",`The directory did not answer, so ${A(t)} cannot be listed.`,{machine:A(t)});return o}const u=l(w=>({id:w,name:c.find(d=>d.machine_id===w)?.name??w}),"labelOf"),f=u(n),h=c.filter(w=>w.machine_id!==n&&w.kind!=="device"),g=B(e);if(t!==null){if(!i)return{items:X(o.items,f),next_cursor:o.next_cursor,machines:[{machine_id:n,name:f.name,state:"ok",more:o.next_cursor!==null}]};const w=A(t);if(!h.some(E=>E.machine_id===w))throw new y(404,"not_found",`no machine ${w} on your account`,{machine:w});const d=await ke(e,u(w),g,r.signal);return{items:d.items,next_cursor:d.next,machines:[{machine_id:w,name:u(w).name,state:d.state,more:d.next!==null}]}}const{cursor:j,...m}=g,p=await Promise.all(h.map(w=>ke(e,u(w.machine_id),m,r.signal)));return{items:[...X(o.items,f),...p.flatMap(w=>w.items)],next_cursor:o.next_cursor,machines:[{machine_id:n,name:f.name,state:"ok",more:o.next_cursor!==null},...h.map((w,d)=>({machine_id:w.machine_id,name:w.name,state:p[d].state,more:p[d].next!==null}))]}}finally{clearTimeout(s)}}l(it,"list");function ve(e){const t=new URLSearchParams(e.query);return t.delete("machine"),{...e,query:t}}l(ve,"withoutMachine");async function rt(e){const t=[],a=I(e.body)?e.body:{};I(e.body)||t.push({field:"body",problem:"must be an object",received:e.body});const n=a.text;(typeof n!="string"||n.trim()==="")&&t.push({field:"text",problem:"is required",received:n});const i=a.grep;if(i!==void 0)if(typeof i!="string")t.push({field:"grep",problem:"must be a regular expression string",received:i});else try{new RegExp(i)}catch(s){t.push({field:"grep",problem:`is not a valid regular expression: ${s.message}`,received:i})}a.body!==void 0&&typeof a.body!="boolean"&&t.push({field:"body",problem:"must be a boolean",received:a.body});const o=await be(await T(),a.type,t);a.kind!==void 0&&typeof a.kind!="string"&&t.push({field:"kind",problem:"must be a string",received:a.kind}),a.owner!==void 0&&typeof a.owner!="string"&&t.push({field:"owner",problem:"must be a string",received:a.owner});const r=je(a.limit,"limit",t,50);return t.length>0&&C("object search request",t),await _(async s=>{const c=await v(s,e),u=typeof a.owner=="string"?await he(s,c,a.owner):null;if(typeof a.owner=="string"&&u===null)return{items:[]};const f=await oe(s,c,{text:n,body:a.body===!0||typeof i=="string"}),h=new Set(f.map(m=>m.object.rowid)),j=(typeof i=="string"?(await oe(s,c,{text:i,grep:!0})).filter(m=>h.has(m.object.rowid)):f).filter(m=>(!o||m.object.type===o)&&(a.kind===void 0||m.object.kind===a.kind)&&(!u||m.object.owner===u.rowid));return{items:await de(j.slice(0,r),async m=>({object:await me(s,m.object),...m.line!==void 0?{matches:[{line:m.line,text:m.text??""}]}:{}}))}})}l(rt,"search");const Oe=["interrupt","steer","after-turn","next-turn"],ot=/^(\*|>|[A-Za-z0-9_-]+)(\.(\*|>|[A-Za-z0-9_-]+))*$/;function st(e,t){if(e!==void 0){if(!Array.isArray(e)||e.length===0||e.some(a=>typeof a!="string"||!ot.test(a)||a.includes(">")&&!a.endsWith(">"))){t.push({field:"patterns",problem:"must be a non-empty list of event patterns (dot-separated words, `*` for one word, a final `>` for the rest)",received:e});return}return e}}l(st,"patternsOf");function ut(e,t){if(e===void 0)return;if(!I(e)||Object.keys(e).length===0){t.push({field:"config",problem:"must map levels 1-10 to a delivery",received:e});return}const a=[];for(const[n,i]of Object.entries(e)){const o=Number(n);!Number.isInteger(o)||o<1||o>10?t.push({field:`config.${n}`,problem:"level must be an integer from 1 to 10"}):Oe.includes(i)?a.push({threshold:o,delivery:i}):t.push({field:`config.${n}`,problem:`delivery must be one of ${Oe.join(", ")}`,received:i})}return a.sort((n,i)=>i.threshold-n.threshold)}l(ut,"configOf");async function Ee(e){const t=await ye(e);if(t!==null)throw new y(400,"invalid_request",`${t} lives on another machine; an explicit watcher cannot watch it from here`,{id:t})}l(Ee,"refuseStubWatch");async function x(e,t){const a=await W(e,t)??await(async()=>{const n=await Ne(e,await Fe(e,{class:"person"},async()=>[]),t);return"object"in n?n.object:null})();return a===null||a.deleted_at!==null||!(a.type.includes(".")||a.type==="node")?null:a}l(x,"findWatcher");const O=l(()=>{throw new y(404,"not_found","watcher not found")},"watcherNotFound");async function Re(e,t,a){if(typeof t!="string"||a===void 0||a===null)return null;if(typeof a!="string")throw new y(400,"invalid_request","invalid watcher_machine");if(await x(e,t)!==null)return null;const n=S.current;let i;try{i=await n.machines()}catch{throw new y(503,"runtime_unreachable","The directory did not answer, so the watcher machine cannot be checked.")}const o=A(a);return(o===n.self()||!i.some(r=>A(r.machine_id)===o))&&O(),o}l(Re,"remoteWatcherMachine");async function qe(e,t,a,n){if(t.publishToken||t.principal.class==="anonymous")return O();const i=await v(e,t);if(i.class==="person")return O();let o;try{o=await R(e,i,n)}catch{return O()}const r=o.owner===null?null:await we(e,o.owner);return r===null||!await ae(e,i,r)||!await Pe(e,i,"link",a)?O():(await G(e,t,a),{actor:i.app,object:o})}l(qe,"linkWatcher");async function Te(e,t,a){if(t.publishToken)return!0;if(t.principal.class==="anonymous"||!a.type.includes("."))return!1;const n=await v(e,t),i=a.owner===null?null:await we(e,a.owner);return i!==null&&await ae(e,n,i)&&await Le(e,n,a)}l(Te,"ownsWatcher");async function ct(e){const t=k(e),a=I(e.body)?e.body:{};if(typeof a.watcher=="string"&&await Ee(t),typeof a.watcher!="string"){const i=await J(e,t,{method:"POST",path:`${Q(t)}/watch`,body:e.body});if(i.kind==="unknown")throw fe(t,i.unreachable);if(i.kind==="remote"){if(i.status>=400)throw D(i.status,i.body);const o=i.body.patterns;return await ge(e,i.body,i.machine.id,"ask",o),K(i.body,i.machine)}}const n=await Re(await T(),a.watcher,a.watcher_machine);return await lt(e,n)}l(ct,"watch");async function lt(e,t=null){const a=[],n=e.body===void 0?{}:I(e.body)?e.body:(a.push({field:"body",problem:"must be an object"}),{}),i=st(n.patterns,a),o=ut(n.config,a);return n.filter!==void 0&&!I(n.filter)&&a.push({field:"filter",problem:"must be an object",received:n.filter}),n.watcher!==void 0&&typeof n.watcher!="string"&&a.push({field:"watcher",problem:"must be a custom-object ref",received:n.watcher}),n.watcher_machine!==void 0&&typeof n.watcher_machine!="string"&&a.push({field:"watcher_machine",problem:"must be a machine id",received:n.watcher_machine}),a.length>0&&C("watch request",a),await _(async r=>{const s=typeof n.watcher=="string";if((e.publishToken||e.principal.class==="anonymous")&&!s)throw new y(404,"not_found","watcher not found");const c=i??[">"],u={patterns:c,...o?{config:o}:{},...n.filter!==void 0?{filter:n.filter}:{}};if(s){const j=n.watcher,m=t===null?null:await ft(r,e,j,t),p=m??(e.publishToken?await ie(r,j):await x(r,j));if(p===null)return O();if(m===null&&await Te(r,e,p)){const E=await re(r,e,p);await G(r,e,p);const ee=await M(r,p),q=await R(r,ee,k(e));if(!await ne(r,ee,q))throw new y(404,"not_found","object not found");return await L(r,p,q,"act",u),await P(r,p,q),await U(r,{event:"watched",object:q,actor:E,attrs:{}},await F(r)),{object:await $(r,q,await b(r,q)),patterns:c}}const{actor:w,object:d}=await qe(r,e,p,k(e));return await L(r,p,d,"act",{...u,linkApp:w}),await P(r,p,d),await U(r,{event:"watched",object:d,actor:w,attrs:{}},await F(r)),{object:await $(r,d,await b(r,d)),patterns:c}}const f=await v(r,e),h=await V(r,e)??te(f),g=await R(r,f,k(e));return await L(r,h,g,"ask",u),await P(r,h,g),await U(r,{event:"watched",object:g,actor:h,attrs:{}},await F(r)),{object:await $(r,g,await b(r,g)),patterns:c}})}l(lt,"watchLocal");async function ft(e,t,a,n){return t.publishToken||t.principal.class==="anonymous"?O():await Je(e,a,n)}l(ft,"ensureNodeStubFor");async function Ie(e,t,a,n){const i=l(async()=>(await e.prepare(`SELECT count(*) AS n FROM watch_subscriptions s JOIN watches w ON w.rowid = s.watch
|
|
3
|
-
WHERE w.watcher = ? AND w.object = ?`).get(t.rowid,a.rowid)).n,"count"),o=await i();await ze(e,t,a,n??void 0);const r=await i();return r===0&&await Be(e,t,a),{object:await b(e,a),removed:o-r}}l(
|
|
1
|
+
var $e=Object.defineProperty;var l=(e,t)=>$e(e,"name",{value:t,configurable:!0});import{ApiError as y}from"../../../api/errors.js";import{PRIVACY_LEVELS_DTO as Ae}from"../../../api/dto/objects.js";import{openDb as q,withCanvasWrite as _}from"../../../core/canvas/db.js";import{actorOf as te}from"../../../core/graph/documents.js";import{readerForObject as U,readerFor as Fe}from"../../../core/graph/reader.js";import{resolveName as Se,stubsNamed as We,unwrapRef as ne}from"../../../core/graph/names.js";import{canRead as ae,customReachable as Le,holdsObjectsScope as Pe,mayActAs as ie}from"../../../core/graph/access.js";import{customObjectRef as re,authorizeCustom as oe,fenceArgv as z}from"./custom-objects.js";import{edgesOf as Ce}from"../../../core/graph/edges.js";import{publish as H}from"../../../core/graph/events.js";import{objectDTO as b}from"../../../core/graph/kinds/dto.js";import{isKind as De,kindNames as Me,kindOf as V}from"../../../core/graph/kinds/registry.js";import{listObjects as Ge,searchObjects as se}from"../../../core/graph/objects.js";import{checkoutsForCwd as Ue}from"../../../core/graph/repo-sync/repos.js";import{recordWatch as L,unwatch as ze,watchersOf as He,watchesOf as Ve}from"../../../core/graph/watches.js";import{armObjectWaitForWatch as P,settleObjectWaitForUnwatch as Be}from"../../../core/graph/object-waits.js";import{readerFor as v,resolveRef as B}from"../reader.js";import{readDelegationFor as ue,runReadLeaf as Ke}from"../../plugin-objects/read-leaf.js";import{invalidRequest as C,isRecord as I}from"./validate.js";import{callerNode as ce,callerStub as K,forwardNamed as Ze,forwardVerb as le,originates as fe,queryWithoutMachine as D,relayError as M,remoteStub as Je,unknownError as de,forwarding as S,withMachine as Z}from"../../peer/forward.js";import{getById as W,getByRowid as we}from"../../../core/graph/objects.js";import{ensureNodeStub as Qe,isStub as J,stubOf as Ye,withKindDecl as N}from"../../../core/peer/stubs.js";import{isUnreachable as Xe}from"../../../core/peer/client.js";import{normalizeMachineId as $}from"../../../core/peer/directory.js";import{mapAsync as me}from"../../../core/async-array.js";const A=l(async e=>async t=>await Ue(e,t),"reposFnFor");async function he(e,t){return{...await b(e,t),...await(await V(e,t.type)).listItem?.(e,t)}}l(he,"listItem");function xe(e){return`no object named ${e} on this runtime; it may be on another runtime, or the name may be misspelled`}l(xe,"remoteMessage");async function pe(e,t,a){try{return await R(e,t,a)}catch(n){if(n instanceof y&&n.code==="not_found"&&!n.details?.deleted)return null;throw n}}l(pe,"ownerFilter");async function R(e,t,a){const n=await B(e,t,a);if("remote"in n)throw new y(404,"not_found",xe(n.remote),{next:"Check the name with `crtr canvas search`."});if("deleted"in n)throw new y(404,"not_found",`${n.deleted.name} is deleted`,{id:n.deleted.id,deleted:!0});return n}l(R,"liveRef");const k=l(e=>decodeURIComponent(e.params.ref),"refParam"),ye=l(e=>{const t=ne(e),a=t.indexOf("/");return a>0?t.slice(0,a):t},"idOf");async function ge(e){const t=await W(await q(),ye(e));return t!==null&&await J(await q(),t)?t.id:null}l(ge,"stubIdOf");async function et(e,t){const a=await ge(e);return a!==null?{stub:a,hit:!0}:await _(async n=>{try{const i=await v(n,t),o=l(async()=>{const s=await We(n,i,e);if(s.length>1)throw new y(409,"ambiguous_name",`'${e}' names more than one remote object`,{candidates:s.map(c=>c.id),next:"Read one by its object id."});return{stub:s[0]?.id??null,hit:!1}},"named");let r;try{r=await B(n,i,e)}catch(s){if(s instanceof y&&s.code==="not_found")return await o();throw s}if("remote"in r)return await o();if("deleted"in r){const s=await o();return s.stub===null?{stub:null,hit:!0}:s}return{stub:await J(n,r)?r.id:null,hit:!0}}catch(i){if(i instanceof y&&i.code==="ambiguous_name")throw i;return{stub:null,hit:!1}}})}l(et,"resolvedLocally");async function Q(e,t,a){const n=await et(t,e);if(n.stub!==null)return le(e,n.stub,a);if(n.hit||!fe(e.principal))return{kind:"local"};const i=await le(e,ye(t),a);return i.kind==="local"&&ne(t).includes("/")?Ze(e,a,{method:"GET",path:G(t),query:D(e)}):i}l(Q,"forwardRef");const G=l(e=>`/v1/objects/${encodeURIComponent(e)}`,"objectPath");async function be(e,t,a,n,i){const o=t?.object;!o?.id||!o.type||await _(async r=>{const s=await ce(r,e);if(s===null)return;const c=await Je(r,o.id,o.type,a,{kind:o.kind??null,name:o.name??o.id,...o.preview===void 0?{}:{preview:o.preview},owner:o.owner??null,...o.kind_decl===void 0?{}:{kind_decl:o.kind_decl},...o.privacy===void 0?{}:{privacy:o.privacy}});await L(r,s,c,n,i===void 0?{}:{patterns:i}),n==="ask"&&await P(r,s,c)})}l(be,"watchRemote");async function tt(e){const t=k(e),a=["1","true"].includes(e.query.get("fields")??""),n=await Q(e,t,{method:"GET",path:G(t),query:D(e)});if(n.kind==="unknown")return{state:"unknown",ref:t,unreachable:n.unreachable};if(n.kind==="remote"){if(n.status>=400)throw M(n.status,n.body);return await be(e,n.body,n.machine.id,"read"),Z(n.body,n.machine)}const i=l(async s=>{const c=await K(s,e);return c===null?await v(s,e):await U(s,c,await A(s))},"readerOf"),o=await _(async s=>{const c=await i(s),u=await B(s,c,t);if("remote"in u)return{state:"remote",remote:u.remote};if("deleted"in u)return{state:"deleted",deleted:await b(s,u.deleted)};const f=await ue(s,u);if(f!==null)return{delegate:f,hitId:u.id};const{data:h,text:g}=await(await V(s,u.type)).read(s,c,u,{fields:a,reposFn:await A(s)});return{state:"object",type:u.type,object:await N(s,u,await b(s,u)),text:g,data:h}});if(!("delegate"in o))return o;const r=await Ke(o.delegate,e.principal);return await _(async s=>{const c=await i(s),u=await W(s,o.hitId);if(u===null)throw new y(404,"not_found","object not found");if(u.deleted_at!==null)return{state:"deleted",deleted:await b(s,u)};if(!await ae(s,c,u))throw new y(404,"not_found","object not found");const{data:f,text:h}=await(await V(s,u.type)).read(s,c,u,{fields:a,reposFn:await A(s)});return await ue(s,u)===null?{state:"object",type:u.type,object:await N(s,u,await b(s,u)),text:h,data:f}:{state:"object",type:u.type,object:await N(s,u,await b(s,u)),text:"markdown"in r?r.markdown:`${h}
|
|
2
|
+
content unavailable: ${r.unavailable}`,data:{...f,content:"markdown"in r?"live":"unavailable"}}})}l(tt,"read");function Y(e,t,a,n){if(e!=null){if(!a.includes(e)){n.push({field:t,problem:`must be one of ${a.join(", ")}`,received:e});return}return e}}l(Y,"oneOf");async function je(e,t,a){if(t!=null){if(typeof t!="string"||!await De(e,t)){a.push({field:"type",problem:`must be a kind: one of ${(await Me(e)).join(", ")}`,received:t});return}return t}}l(je,"kindName");function _e(e,t,a,n){if(e==null)return n;const i=Number(e);return!Number.isInteger(i)||i<1||i>100?(a.push({field:t,problem:"must be an integer from 1 to 100",received:e}),n):i}l(_e,"limitOf");async function ke(e){const t=e.query,a=[],n=await je(await q(),t.get("type"),a),i=Y(t.get("privacy"),"privacy",Ae,a),o=_e(t.get("limit"),"limit",a,50),r=t.get("cursor");r!==null&&!/^\d+$/.test(r)&&a.push({field:"cursor",problem:"is not a cursor from a previous page",received:r});const s=t.get("deleted");return s!==null&&!["0","1","true","false"].includes(s)&&a.push({field:"deleted",problem:"must be true or false",received:s}),a.length>0&&C("object list request",a),await _(async c=>{const u=await v(c,e),f={...n?{type:n}:{},...i?{privacy:i}:{},...t.get("kind")!==null?{kind:t.get("kind")}:{},...s==="1"||s==="true"?{deleted:!0}:{}},h=t.get("owner");if(h!==null){const w=await pe(c,u,h);if(w===null)return{items:[],next_cursor:null};f.owner=w}const g=t.get("name"),j=[];let m=r===null?0:Number(r),p=!0;for(;j.length<o&&p;){const w=await Ge(c,u,f,{limit:100,after_rowid:m});p=w.length===100;for(const E of w)if(m=E.rowid,(g===null||E.name.startsWith(g))&&j.push(E),j.length===o)break}const d=j.at(-1);return{items:await me(j,async w=>await he(c,w)),next_cursor:j.length===o&&d?String(d.rowid):null}})}l(ke,"listLocal");const nt={ms:3e4},at="self",X=l((e,t)=>e.map(a=>({...a,machine:t})),"labelItems");async function ve(e,t,a,n){const i=S.current;try{const o=await i.call(t.id,{method:"GET",path:"/v1/objects",query:a},await i.envelope(e.principal),n);if(Xe(o))return{state:"unreachable",items:[],next:null};if(o.status===426)return{state:"too_old",items:[],next:null};const r=o.body;return o.status!==200||!Array.isArray(r?.items)?{state:"unreachable",items:[],next:null}:{state:"ok",items:X(r.items,t),next:r.next_cursor??null}}catch{return{state:"unreachable",items:[],next:null}}}l(ve,"remotePage");async function it(e){const t=new Promise(a=>e.addEventListener("abort",()=>a(null),{once:!0}));return Promise.race([S.current.machines().catch(()=>null),t])}l(it,"machinesWithin");async function rt(e){const t=e.query.get("machine");if(!fe(e.principal)||!S.current.joined()||t===at)return await ke(Oe(e));const n=S.current.self(),i=t!==null&&$(t)!==n,o=i?null:await ke(Oe(e)),r=new AbortController,s=setTimeout(()=>r.abort(),nt.ms);s.unref?.();try{const c=await it(r.signal);if(c===null){if(i)throw new y(503,"runtime_unreachable",`The directory did not answer, so ${$(t)} cannot be listed.`,{machine:$(t)});return o}const u=l(d=>({id:d,name:c.find(w=>w.machine_id===d)?.name??d}),"labelOf"),f=u(n),h=c.filter(d=>d.machine_id!==n&&d.kind!=="device"),g=D(e);if(t!==null){if(!i)return{items:X(o.items,f),next_cursor:o.next_cursor,machines:[{machine_id:n,name:f.name,state:"ok",more:o.next_cursor!==null}]};const d=$(t);if(!h.some(E=>E.machine_id===d))throw new y(404,"not_found",`no machine ${d} on your account`,{machine:d});const w=await ve(e,u(d),g,r.signal);return{items:w.items,next_cursor:w.next,machines:[{machine_id:d,name:u(d).name,state:w.state,more:w.next!==null}]}}const{cursor:j,...m}=g,p=await Promise.all(h.map(d=>ve(e,u(d.machine_id),m,r.signal)));return{items:[...X(o.items,f),...p.flatMap(d=>d.items)],next_cursor:o.next_cursor,machines:[{machine_id:n,name:f.name,state:"ok",more:o.next_cursor!==null},...h.map((d,w)=>({machine_id:d.machine_id,name:d.name,state:p[w].state,more:p[w].next!==null}))]}}finally{clearTimeout(s)}}l(rt,"list");function Oe(e){const t=new URLSearchParams(e.query);return t.delete("machine"),{...e,query:t}}l(Oe,"withoutMachine");async function ot(e){const t=[],a=I(e.body)?e.body:{};I(e.body)||t.push({field:"body",problem:"must be an object",received:e.body});const n=a.text;(typeof n!="string"||n.trim()==="")&&t.push({field:"text",problem:"is required",received:n});const i=a.grep;if(i!==void 0)if(typeof i!="string")t.push({field:"grep",problem:"must be a regular expression string",received:i});else try{new RegExp(i)}catch(s){t.push({field:"grep",problem:`is not a valid regular expression: ${s.message}`,received:i})}a.body!==void 0&&typeof a.body!="boolean"&&t.push({field:"body",problem:"must be a boolean",received:a.body});const o=await je(await q(),a.type,t);a.kind!==void 0&&typeof a.kind!="string"&&t.push({field:"kind",problem:"must be a string",received:a.kind}),a.owner!==void 0&&typeof a.owner!="string"&&t.push({field:"owner",problem:"must be a string",received:a.owner});const r=_e(a.limit,"limit",t,50);return t.length>0&&C("object search request",t),await _(async s=>{const c=await v(s,e),u=typeof a.owner=="string"?await pe(s,c,a.owner):null;if(typeof a.owner=="string"&&u===null)return{items:[]};const f=await se(s,c,{text:n,body:a.body===!0||typeof i=="string"}),h=new Set(f.map(m=>m.object.rowid)),j=(typeof i=="string"?(await se(s,c,{text:i,grep:!0})).filter(m=>h.has(m.object.rowid)):f).filter(m=>(!o||m.object.type===o)&&(a.kind===void 0||m.object.kind===a.kind)&&(!u||m.object.owner===u.rowid));return{items:await me(j.slice(0,r),async m=>({object:await he(s,m.object),...m.line!==void 0?{matches:[{line:m.line,text:m.text??""}]}:{}}))}})}l(ot,"search");const Ee=["interrupt","steer","after-turn","next-turn"],st=/^(\*|>|[A-Za-z0-9_-]+)(\.(\*|>|[A-Za-z0-9_-]+))*$/;function ut(e,t){if(e!==void 0){if(!Array.isArray(e)||e.length===0||e.some(a=>typeof a!="string"||!st.test(a)||a.includes(">")&&!a.endsWith(">"))){t.push({field:"patterns",problem:"must be a non-empty list of event patterns (dot-separated words, `*` for one word, a final `>` for the rest)",received:e});return}return e}}l(ut,"patternsOf");function ct(e,t){if(e===void 0)return;if(!I(e)||Object.keys(e).length===0){t.push({field:"config",problem:"must map levels 1-10 to a delivery",received:e});return}const a=[];for(const[n,i]of Object.entries(e)){const o=Number(n);!Number.isInteger(o)||o<1||o>10?t.push({field:`config.${n}`,problem:"level must be an integer from 1 to 10"}):Ee.includes(i)?a.push({threshold:o,delivery:i}):t.push({field:`config.${n}`,problem:`delivery must be one of ${Ee.join(", ")}`,received:i})}return a.sort((n,i)=>i.threshold-n.threshold)}l(ct,"configOf");async function Re(e){const t=await ge(e);if(t!==null)throw new y(400,"invalid_request",`${t} lives on another machine; an explicit watcher cannot watch it from here`,{id:t})}l(Re,"refuseStubWatch");async function x(e,t){const a=await W(e,t)??await(async()=>{const n=await Se(e,await Fe(e,{class:"person"},async()=>[]),t);return"object"in n?n.object:null})();return a===null||a.deleted_at!==null||!(a.type.includes(".")||a.type==="node")?null:a}l(x,"findWatcher");const O=l(()=>{throw new y(404,"not_found","watcher not found")},"watcherNotFound");async function Te(e,t,a){if(typeof t!="string"||a===void 0||a===null)return null;if(typeof a!="string")throw new y(400,"invalid_request","invalid watcher_machine");if(await x(e,t)!==null)return null;const n=S.current;let i;try{i=await n.machines()}catch{throw new y(503,"runtime_unreachable","The directory did not answer, so the watcher machine cannot be checked.")}const o=$(a);return(o===n.self()||!i.some(r=>$(r.machine_id)===o))&&O(),o}l(Te,"remoteWatcherMachine");async function qe(e,t,a,n){if(t.publishToken||t.principal.class==="anonymous")return O();const i=await v(e,t);if(i.class==="person")return O();let o;try{o=await R(e,i,n)}catch{return O()}const r=o.owner===null?null:await we(e,o.owner);return r===null||!await ie(e,i,r)||!await Pe(e,i,"link",a)?O():(await z(e,t,a),{actor:i.app,object:o})}l(qe,"linkWatcher");async function Ie(e,t,a){if(t.publishToken)return!0;if(t.principal.class==="anonymous"||!a.type.includes("."))return!1;const n=await v(e,t),i=a.owner===null?null:await we(e,a.owner);return i!==null&&await ie(e,n,i)&&await Le(e,n,a)}l(Ie,"ownsWatcher");async function lt(e){const t=k(e),a=I(e.body)?e.body:{};if(typeof a.watcher=="string"&&await Re(t),typeof a.watcher!="string"){const i=await Q(e,t,{method:"POST",path:`${G(t)}/watch`,body:e.body});if(i.kind==="unknown")throw de(t,i.unreachable);if(i.kind==="remote"){if(i.status>=400)throw M(i.status,i.body);const o=i.body.patterns;return await be(e,i.body,i.machine.id,"ask",o),Z(i.body,i.machine)}}const n=await Te(await q(),a.watcher,a.watcher_machine);return await ft(e,n)}l(lt,"watch");async function ft(e,t=null){const a=[],n=e.body===void 0?{}:I(e.body)?e.body:(a.push({field:"body",problem:"must be an object"}),{}),i=ut(n.patterns,a),o=ct(n.config,a);return n.filter!==void 0&&!I(n.filter)&&a.push({field:"filter",problem:"must be an object",received:n.filter}),n.watcher!==void 0&&typeof n.watcher!="string"&&a.push({field:"watcher",problem:"must be a custom-object ref",received:n.watcher}),n.watcher_machine!==void 0&&typeof n.watcher_machine!="string"&&a.push({field:"watcher_machine",problem:"must be a machine id",received:n.watcher_machine}),a.length>0&&C("watch request",a),await _(async r=>{const s=typeof n.watcher=="string";if((e.publishToken||e.principal.class==="anonymous")&&!s)throw new y(404,"not_found","watcher not found");const c=i??[">"],u={patterns:c,...o?{config:o}:{},...n.filter!==void 0?{filter:n.filter}:{}};if(s){const j=n.watcher,m=t===null?null:await dt(r,e,j,t),p=m??(e.publishToken?await re(r,j):await x(r,j));if(p===null)return O();if(m===null&&await Ie(r,e,p)){const E=await oe(r,e,p);await z(r,e,p);const ee=await U(r,p),T=await R(r,ee,k(e));if(!await ae(r,ee,T))throw new y(404,"not_found","object not found");return await L(r,p,T,"act",u),await P(r,p,T),await H(r,{event:"watched",object:T,actor:E,attrs:{}},await A(r)),{object:await N(r,T,await b(r,T)),patterns:c}}const{actor:d,object:w}=await qe(r,e,p,k(e));return await L(r,p,w,"act",{...u,linkApp:d}),await P(r,p,w),await H(r,{event:"watched",object:w,actor:d,attrs:{}},await A(r)),{object:await N(r,w,await b(r,w)),patterns:c}}const f=await v(r,e),h=await K(r,e)??te(f),g=await R(r,f,k(e));return await L(r,h,g,"ask",u),await P(r,h,g),await H(r,{event:"watched",object:g,actor:h,attrs:{}},await A(r)),{object:await N(r,g,await b(r,g)),patterns:c}})}l(ft,"watchLocal");async function dt(e,t,a,n){return t.publishToken||t.principal.class==="anonymous"?O():await Qe(e,a,n)}l(dt,"ensureNodeStubFor");async function Ne(e,t,a,n){const i=l(async()=>(await e.prepare(`SELECT count(*) AS n FROM watch_subscriptions s JOIN watches w ON w.rowid = s.watch
|
|
3
|
+
WHERE w.watcher = ? AND w.object = ?`).get(t.rowid,a.rowid)).n,"count"),o=await i();await ze(e,t,a,n??void 0);const r=await i();return r===0&&await Be(e,t,a),{object:await b(e,a),removed:o-r}}l(Ne,"dropWatch");async function wt(e){const t=k(e);if(e.query.get("watcher")&&await Re(t),!e.query.get("watcher")){const n=await Q(e,t,{method:"DELETE",path:`${G(t)}/watch`,query:D(e)});if(n.kind==="unknown")throw de(t,n.unreachable);if(n.kind==="remote"){const i=n.status===404?n.body.error?.details:void 0,o=i?.deleted===!0?i.id:void 0;if(n.status>=400&&o===void 0)throw M(n.status,n.body);const r=o??n.body.object?.id,s=await _(async c=>{const u=await ce(c,e),f=r===void 0?null:await W(c,r);return u===null||f===null||!await J(c,f)?null:await Ne(c,u,f,e.query.get("pattern"))});if(o!==void 0){if(s===null)throw M(n.status,n.body);return{...s,machine:n.machine}}return Z(n.body,n.machine)}}const a=await Te(await q(),e.query.get("watcher")??void 0,e.query.get("watcher_machine")??void 0);return await mt(e,a)}l(wt,"unwatchRoute");async function mt(e,t=null){const a=e.query.get("pattern"),n=e.query.get("watcher");return await _(async i=>{if((e.publishToken||e.principal.class==="anonymous")&&!n)throw new y(404,"not_found","watcher not found");const o=l(async(c,u)=>await Ne(i,c,u,a),"drop");if(n){const c=t===null?null:await(async()=>{const f=await W(i,n);return f!==null&&await Ye(i,f)!==null?f:null})();if(t!==null&&c===null)return O();const u=c??(e.publishToken?await re(i,n):await x(i,n));return u===null?O():c===null&&await Ie(i,e,u)?(await oe(i,e,u),await z(i,e,u),await o(u,await R(i,await U(i,u),k(e)))):await o(u,(await qe(i,e,u,k(e))).object)}const r=await v(i,e),s=await K(i,e)??te(r);return await o(s,await R(i,r,k(e)))})}l(mt,"unwatchLocal");async function ht(e){const t=[],a=Y(e.query.get("type"),"type",["acted-on","links-to","watches"],t),n=Y(e.query.get("direction"),"direction",["out","in"],t);return t.length>0&&C("edges request",t),await _(async i=>{const o=await v(i,e),r=await R(i,o,k(e)),s=[];if(a!=="watches")for(const c of await Ce(i,o,r,{...a?{type:a}:{},direction:n??"both"}))s.push({type:c.type,src:await b(i,c.src),dst:await b(i,c.dst),...c.written_as?{written_as:c.written_as}:{}});if(a===void 0||a==="watches"){const c=[...n!=="in"?await Ve(i,o,r):[],...n!=="out"?await He(i,o,r):[]];for(const u of c)s.push({type:"watches",src:await b(i,u.watcher),dst:await b(i,u.object)})}return{items:s}})}l(ht,"edges");const F=l(e=>async t=>({status:200,body:await e(t)}),"ok"),Ut=[{method:"POST",pattern:"/v1/objects/search",handler:F(ot)},{method:"GET",pattern:"/v1/objects/:ref/edges",handler:F(ht)},{method:"POST",pattern:"/v1/objects/:ref/watch",handler:F(lt)},{method:"DELETE",pattern:"/v1/objects/:ref/watch",handler:F(wt)},{method:"GET",pattern:"/v1/objects/:ref",handler:F(tt)},{method:"GET",pattern:"/v1/objects",handler:F(rt)}];export{nt as listBudget,Ut as objectRoutes};
|
|
@@ -46,6 +46,13 @@ export declare const withMachine: (body: unknown, machine: MachineLabel) => unkn
|
|
|
46
46
|
* machine's id only for logging; it is the same call whatever machine answers.
|
|
47
47
|
*/
|
|
48
48
|
export declare function forwardVerb(ctx: RequestContext, id: string, request: PeerRequest): Promise<ForwardOutcome>;
|
|
49
|
+
/**
|
|
50
|
+
* Forward `request` for a ref that is a name rather than an id: no local object or stub holds it, and the id-keyed home resolver cannot
|
|
51
|
+
* place it. Every other machine of the account is probed with the read-only `probe` (a GET of the object); the machine that answers below
|
|
52
|
+
* 400 homes it, and `request` goes to that one machine (a GET `request` is its own probe). A `404` is a miss; any other refusal or error
|
|
53
|
+
* says nothing about whether the machine holds the name (as in `locate`), so with no hit it makes the answer `unknown`.
|
|
54
|
+
*/
|
|
55
|
+
export declare function forwardNamed(ctx: RequestContext, request: PeerRequest, probe: PeerRequest): Promise<ForwardOutcome>;
|
|
49
56
|
/** The envelope a forwarded call carried, rebuilt from its verified principal. */
|
|
50
57
|
export declare function envelopeOfForwarded(principal: Extract<RequestPrincipal, {
|
|
51
58
|
class: 'forwarded';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var $=Object.defineProperty;var i=(n,e)=>$(n,"name",{value:e,configurable:!0});import{ApiError as m}from"../../api/errors.js";import{openDb as g}from"../../core/canvas/db.js";import{getById as j,nodeObject as A}from"../../core/graph/objects.js";import{envelopeFor as D}from"../../core/peer/envelope.js";import{isUnreachable as w}from"../../core/peer/client.js";import{machineReach as E}from"../../core/peer/directory.js";import{defaultHomeDeps as O,homeOf as S,peersToAsk as F,relocate as N}from"../../core/peer/home.js";import{ensureStub as y,rehomeStub as q,stubOf as C}from"../../core/peer/stubs.js";import{peerCall as M}from"../../core/peer/client.js";const T={...O,call:i((n,e,o,t)=>M(n,e,{...o===void 0?{}:{envelope:o},...t===void 0?{}:{signal:t}}),"call"),envelope:i(async n=>await D(n),"envelope"),label:i(async n=>{try{const e=await E(n);return{id:n,name:e?.name??n}}catch{return{id:n,name:n}}},"label")},_={current:T},v=i(n=>n.class==="person"||n.class==="broker"||n.class==="cron","originates"),k=i(n=>{const e=n?.error;return typeof e=="object"&&e!==null&&typeof e.code=="string"?e.code:null},"errorCode");function K(n,e){const o=e?.error;return new m(n,o?.code??"error",o?.message??`the home machine answered ${n}`,o?.details)}i(K,"relayError");function L(n,e){return new m(503,"runtime_unreachable",`No machine of yours answers for ${n} (unreachable: ${e.join(", ")}).`,{id:n,unreachable:e})}i(L,"unknownError");const Q=i((n,e)=>n!==null&&typeof n=="object"&&!Array.isArray(n)?{...n,machine:e}:n,"withMachine");async function X(n,e,o){const t=_.current,a=await g(),c=await j(a,e),u=c===null?null:await C(a,c),p=n.principal;if(!v(p)){if(u!==null)throw new m(404,"not_here",`${e} is not homed on this machine (it is a stub of ${u.home_machine})`,{id:e,home_machine:u.home_machine});return{kind:"local"}}if(c!==null&&u===null)return{kind:"local"};const h={...t,call:i((r,d)=>t.call(r,d),"call")};let l=await S(a,e,{hint:n.query.get("machine"),deps:h});for(let r=0;r<2;r++){if(l.where==="nowhere"||l.where==="here"){if(u!==null)throw new m(404,"not_found",`${e} is no longer on any machine of yours`,{id:e});return{kind:"local"}}if(l.where==="unknown")return{kind:"unknown",unreachable:l.unreachable};const d=l.machine,s=await t.call(d,o,await t.envelope(p)),b=await t.label(d);if(w(s))return{kind:"unknown",unreachable:[`${b.name} (${s.unreachable.reason})`]};const x=l.source!=="locate";if(s.status===404&&r===0&&(k(s.body)==="not_here"||x&&k(s.body)==="not_found")){const f=await N(a,e,d,h);if(f.where==="machine"){l=f;continue}if(f.where==="unknown")return{kind:"unknown",unreachable:f.unreachable};if(k(s.body)==="not_found")return{kind:"remote",status:s.status,body:s.body,machine:b};if(u!==null)throw new m(404,"not_found",`${e} is no longer on any machine of yours`,{id:e});return{kind:"local"}}return{kind:"remote",status:s.status,body:s.body,machine:b}}return{kind:"unknown",unreachable:[]}}i(X,"forwardVerb");async function Y(n,e,o){const t=_.current,a=n.principal;if(!v(a))return{kind:"local"};const c=await F(t);if("where"in c)return{kind:"unknown",unreachable:c.unreachable};if(c.length===0)return{kind:"local"};const u=await t.envelope(a),p=await Promise.all(c.map(async r=>({m:r,out:await t.call(r.machine_id,o,u)}))),h=p.find(r=>!w(r.out)&&r.out.status<400);if(h){const r=e.method==="GET"?h.out:await t.call(h.m.machine_id,e,u),d=await t.label(h.m.machine_id);return w(r)?{kind:"unknown",unreachable:[`${d.name} (${r.unreachable.reason})`]}:{kind:"remote",status:r.status,body:r.body,machine:d}}const l=p.filter(r=>w(r.out)||r.out.status!==404).map(r=>r.m.name||r.m.machine_id);return l.length>0?{kind:"unknown",unreachable:l}:{kind:"local"}}i(Y,"forwardNamed");function W(n){if(n.actor.kind==="person")return{sub:n.sub,act:{sub:n.via}};const{app:e,node:o,node_scopes:t,place:a}=n.actor;return{sub:n.sub,act:{sub:n.via,act:{sub:e,node:o,node_scopes:t,place:a}}}}i(W,"envelopeOfForwarded");function Z(n){const e={};for(const[o,t]of n.query)o!=="machine"&&(e[o]=t);return e}i(Z,"queryWithoutMachine");async function nn(n,e){const o=e.principal;return o.class!=="forwarded"||o.actor.kind!=="app"||o.actor.node===null?null:await y(n,o.actor.node,"node",o.via,W(o))}i(nn,"callerStub");async function en(n,e){return e.principal.class==="broker"?await A(n,e.principal.node):null}i(en,"callerNode");async function on(n,e,o,t,a){await q(n,e,t);const c=a?.owner,u=c&&c.type==="app"?{id:"",type:"app",scheme:"app",external_id:c.external_id??(c.handle.startsWith("app:")?c.handle:`app:${c.handle}`),handle:c.handle}:null;return await y(n,e,o,t,void 0,a===void 0?void 0:{id:e,type:o,kind:a.kind??null,name:a.name??e,...a.preview===void 0?{}:{preview:a.preview},owner:u,...a.kind_decl===void 0?{}:{kind_decl:a.kind_decl},...a.privacy===void 0?{}:{privacy:a.privacy}})}i(on,"remoteStub");export{en as callerNode,nn as callerStub,T as defaultForwardDeps,W as envelopeOfForwarded,Y as forwardNamed,X as forwardVerb,_ as forwarding,v as originates,Z as queryWithoutMachine,K as relayError,on as remoteStub,L as unknownError,Q as withMachine};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.532",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -140,7 +140,7 @@
|
|
|
140
140
|
},
|
|
141
141
|
"license": "UNLICENSED",
|
|
142
142
|
"dependencies": {
|
|
143
|
-
"@north-light/identity": "0.3.
|
|
143
|
+
"@north-light/identity": "0.3.532",
|
|
144
144
|
"@earendil-works/pi-agent-core": "1.1.0",
|
|
145
145
|
"@earendil-works/pi-ai": "1.1.0",
|
|
146
146
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.532",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/cli",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.532",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "UNLICENSED",
|
|
12
12
|
"workspaces": [
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
"@milkdown/preset-gfm": "^7.22.3",
|
|
25
25
|
"@milkdown/prose": "^7.22.3",
|
|
26
26
|
"@milkdown/utils": "^7.22.3",
|
|
27
|
-
"@north-light/identity": "0.3.
|
|
27
|
+
"@north-light/identity": "0.3.532",
|
|
28
28
|
"cron-parser": "^5.6.0",
|
|
29
29
|
"esbuild": "^0.27.7",
|
|
30
30
|
"jose": "^6.2.12",
|
|
@@ -12468,17 +12468,17 @@
|
|
|
12468
12468
|
},
|
|
12469
12469
|
"packages/crouter-api": {
|
|
12470
12470
|
"name": "@north-light/api",
|
|
12471
|
-
"version": "0.3.
|
|
12471
|
+
"version": "0.3.532",
|
|
12472
12472
|
"license": "UNLICENSED"
|
|
12473
12473
|
},
|
|
12474
12474
|
"packages/crouter-env-docker": {
|
|
12475
12475
|
"name": "@north-light/env-docker",
|
|
12476
|
-
"version": "0.3.
|
|
12476
|
+
"version": "0.3.532",
|
|
12477
12477
|
"license": "UNLICENSED"
|
|
12478
12478
|
},
|
|
12479
12479
|
"packages/crouter-identity": {
|
|
12480
12480
|
"name": "@north-light/identity",
|
|
12481
|
-
"version": "0.3.
|
|
12481
|
+
"version": "0.3.532",
|
|
12482
12482
|
"license": "UNLICENSED",
|
|
12483
12483
|
"dependencies": {
|
|
12484
12484
|
"jose": "^6.2.1"
|
|
@@ -12486,20 +12486,20 @@
|
|
|
12486
12486
|
},
|
|
12487
12487
|
"packages/crouter-plugin": {
|
|
12488
12488
|
"name": "@north-light/plugin",
|
|
12489
|
-
"version": "0.3.
|
|
12489
|
+
"version": "0.3.532",
|
|
12490
12490
|
"license": "UNLICENSED",
|
|
12491
12491
|
"dependencies": {
|
|
12492
|
-
"@north-light/api": "0.3.
|
|
12493
|
-
"@north-light/identity": "0.3.
|
|
12492
|
+
"@north-light/api": "0.3.532",
|
|
12493
|
+
"@north-light/identity": "0.3.532"
|
|
12494
12494
|
}
|
|
12495
12495
|
},
|
|
12496
12496
|
"packages/crouter-sdk": {
|
|
12497
12497
|
"name": "@north-light/sdk",
|
|
12498
|
-
"version": "0.3.
|
|
12498
|
+
"version": "0.3.532",
|
|
12499
12499
|
"license": "UNLICENSED",
|
|
12500
12500
|
"dependencies": {
|
|
12501
|
-
"@north-light/api": "0.3.
|
|
12502
|
-
"@north-light/identity": "0.3.
|
|
12501
|
+
"@north-light/api": "0.3.532",
|
|
12502
|
+
"@north-light/identity": "0.3.532",
|
|
12503
12503
|
"jose": "^6.2.1"
|
|
12504
12504
|
},
|
|
12505
12505
|
"bin": {
|