@north-light/cli 0.3.501 → 0.3.503
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/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/grants.d.ts +2 -2
- package/dist/api/dto/run-events.d.ts +3 -1
- package/dist/builtin-memory/crouter-sdk/release-notes.md +10 -0
- package/dist/clients/attach/viewer.js +433 -433
- package/dist/core/canvas/migrations.js +1 -1
- package/dist/core/fault-classifier.d.ts +2 -0
- package/dist/core/fault-classifier.js +1 -1
- package/dist/core/grants/mirror.d.ts +16 -2
- package/dist/core/grants/mirror.js +3 -3
- package/dist/core/grants/sync.js +1 -1
- package/dist/core/llm/app-rungs.d.ts +16 -0
- package/dist/core/llm/app-rungs.js +1 -0
- package/dist/core/llm/run.d.ts +10 -1
- package/dist/core/llm/run.js +2 -2
- package/dist/core/model-routes.d.ts +2 -0
- package/dist/core/model-routes.js +1 -1
- package/dist/core/peer/ingest.d.ts +5 -1
- package/dist/core/peer/ingest.js +1 -1
- package/dist/core/peer/outbox-store.d.ts +5 -1
- package/dist/core/peer/outbox-store.js +5 -4
- package/dist/core/providers/token-cache.d.ts +1 -1
- package/dist/core/providers/token-cache.js +1 -1
- package/dist/core/runs/operations.js +5 -5
- package/dist/core/runtime/broker/model-adapter.js +2 -2
- package/dist/core/runtime/launch.d.ts +13 -1
- package/dist/core/runtime/launch.js +1 -1
- package/dist/core/runtime/spawn.d.ts +4 -1
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/daemon/api/app-listener.js +13 -13
- package/dist/daemon/api/handlers/llm.js +3 -3
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/objects.js +3 -3
- package/dist/daemon/api/handlers/runs.js +1 -1
- package/dist/daemon/cron/armed-context.js +1 -1
- package/dist/daemon/peer/outbox.js +1 -1
- package/dist/daemon/runs/append-section.js +2 -2
- package/docs/sdk/release-notes.md +10 -0
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +12 -12
|
@@ -1 +1 @@
|
|
|
1
|
-
var Re=Object.defineProperty;var a=(e,t)=>Re(e,"name",{value:t,configurable:!0});import{prepared as X}from"../../../core/sqlite-statements.js";import{envProfileId as Oe}from"../../../shared/env.js";import{pausedCanvasProfiles as Ie}from"../../../core/profiles/manifest.js";import{existsSync as N,realpathSync as Z,statSync as q}from"node:fs";import{isAbsolute as G,resolve as T}from"node:path";import{appendSituationalContext as $e,formatSituationalProse as Ae}from"../../../core/runtime/situational-context.js";import{closeNode as Ce}from"../../../core/runtime/close.js";import{reviveNode as Ne}from"../../../core/runtime/revive.js";import{nowIso as B}from"../../../core/fs-utils.js";import{assertLaunchModelRegistered as x,forkNode as Te,resolveForkSource as Ee,spawnChildPrepared as Pe}from"../../../core/runtime/spawn.js";import{forkSourceNode as De,newNodeId as ee}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as ne,childrenOf as je,completeCreateRequest as te,findCreateRequest as Le,getNode as k,recordCreateRequestNode as Me,reserveCreateRequest as oe,reserveCreateRequestNode as Fe,listNodes as re,recordRespawnAttempt as Ge,subscribersOf as Be,subscriptionsOf as ie,setMessageWait as xe,updateNode as C}from"../../../core/canvas/canvas.js";import{subtreeIds as Ke}from"../../../core/canvas/nav-model.js";import{withCanvasWrite as K}from"../../../core/canvas/db.js";import{nodeObject as We}from"../../../core/graph/objects.js";import{recordActedOn as Ve}from"../../../core/graph/edges.js";import{publish as ze}from"../../../core/graph/events.js";import{readerFor as Je}from"../reader.js";import{relocateSessionCwd as Ue,unbindSession as Ye}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as He}from"../../../core/canvas/attention.js";import{isSafeNodeId as Qe}from"../../../core/canvas/paths.js";import{contextDir as de,nodeAgentDir as W}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as Xe}from"../../cron/authority.js";import{cronBirthPlacement as Ze}from"../../cron/armed-context.js";import{existsBeneath as qe,isAbsentOrRefused as en,isBeneathRefusal as nn,readdirBeneath as tn}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as on,readNodeSession as rn,readNodeSnapshot as dn,transcriptMarkdown as sn}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as an}from"../../../core/substrate/subject.js";import{reviveAll as ln}from"../../../core/runtime/revive-all.js";import{promoteAsync as cn,requestYieldAsync as fn,reshapeNodeAsync as V}from"../../../core/runtime/promote.js";import{recycleNode as un}from"../../../core/runtime/recycle.js";import{relaunchRoot as pn}from"../../../core/runtime/reset.js";import{assertReopenGate as mn}from"../../../core/runtime/reopen.js";import{writeYieldMessage as hn,readGoal as wn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as yn,hasRoadmap as _n}from"../../../core/runtime/roadmap.js";import{renameWindow as gn}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as bn,explicitModelIntent as vn,normalizeModel as kn,readMergedLaunchConfigAsync as se}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as Sn}from"../../../core/model-routes.js";import{persistDormantModel as Rn,setModelLive as On}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as ae}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as In}from"../../../core/runtime/broker-request.js";import{boundFleet as E}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as $n}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as An}from"../../../core/runtime/structured-output.js";import{OUTCOME_PAYLOAD_MAX_BYTES as le}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as Cn}from"../../../core/human/action-binding.js";import{resolveHumanAction as Nn}from"../../../core/human-actions.js";import{parseDurationMs as Tn}from"../../../core/wake.js";import{claimWarmNode as En,refillWarmPool as ce,resumeWarmClaim as Pn,warmPoolEnabled as Dn}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as z,isLaunchKind as jn,resolveLaunchTarget as Ln}from"../../../core/runtime/launch-target.js";import{fullName as Mn}from"../../../core/canvas/labels.js";import{reportsForNode as fe}from"./reports.js";import{requireUsableProfile as Fn}from"./profiles.js";import{assertProfileActive as Gn,loadExactProfileManifest as Bn}from"../../../core/profiles/manifest.js";import{getCron as ue}from"../../../core/canvas/crons.js";import{cronWakeOrigin as xn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as Kn}from"../../control.js";import{notFound as P,usage as h}from"../../../core/errors.js";import{assertScope as Wn,validateScopes as pe}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as Vn,toNodeDetailDTO as J,toNodeSummaryDTO as zn,toReviveResultDTO as Jn}from"../map.js";import{ApiError as m}from"../../../api/index.js";import{InputError as w}from"../../../core/io.js";import{brokerMayReach as U,canReadNode as me,resolvedScopes as Un}from"../router.js";import{forwardVerb as Yn,queryWithoutMachine as Hn,relayError as Qn,unknownError as Xn,withMachine as Zn}from"../../peer/forward.js";import{fileRoot as qn}from"../../../core/spaces/file-root.js";import{activeGrant as et,terminalGrant as nt}from"../../../core/grants/mirror.js";import{readConfig as tt}from"../../../core/config.js";import{hasConfiguredProviderCredential as ot,NO_PROVIDER_CREDENTIAL_MESSAGE as he}from"../../../core/runtime/provider-credential-gate.js";function y(e){const t=k(e);if(t===null)throw P(`unknown node: ${e}`,{received:e});return t}a(y,"requireMeta");function Y(e){return{subscribesTo:ie(e),subscribers:Be(e),children:je(e)}}a(Y,"edgesFor");function g(e){const t=y(e);return J(t,Y(e))}a(g,"detailOf");function rt(e){let t=fe(e).length;try{t+=tn(W(e),de(e)).length}catch(n){if(!en(n))throw n}return t}a(rt,"countFiles");function it(e){if(typeof e!="object"||e===null)throw h("a node create requires a JSON body");const t=e;if(t.kind!==void 0&&(typeof t.kind!="string"||t.kind.trim()===""))throw h("kind must be a non-empty string when provided");if(t.description!==void 0&&(typeof t.description!="string"||t.description.trim()===""))throw h("description must be a non-empty string when provided");if(t.creator!==void 0&&(typeof t.creator!="string"||t.creator.trim()===""))throw h("creator must be a non-empty node id when provided");if(t.scopes!==void 0&&pe(t.scopes),t.isolated!==void 0&&typeof t.isolated!="boolean")throw new m(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const n=t.root_lifecycle;if(n!==void 0&&n!=="resident"&&n!=="terminal")throw h("root_lifecycle must be 'resident' or 'terminal'");if(t.request_key!==void 0&&(typeof t.request_key!="string"||t.request_key.trim()===""||t.request_key.length>128))throw h("request_key must be a non-empty string of at most 128 characters when provided");return t}a(it,"parseCreateBody");function dt(e){if(e===void 0)return;const t=Tn(e),n=t===null?null:new Date(Date.now()+t);if(t===null||!Number.isFinite(t)||t<=0||n===null||!Number.isFinite(n.getTime()))throw new m(422,"invalid_deadline","`deadline` must be a positive representable duration");return n.toISOString()}a(dt,"parseDeadline");function st(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new m(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!Cn.test(e.action))throw new m(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let t;try{t=JSON.stringify(e.payload)}catch{throw new m(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(t===void 0)throw new m(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(t,"utf8")>le)throw new m(413,"payload_too_large",`serialized payload exceeds ${le} bytes`)}return e}}a(st,"parseOutcomeDelivery");function at(e,t){const n=Nn(e.action,t);if(!("kind"in n))return{actionName:e.action,argv:n.argv,cwd:n.cwd,configOrigin:n.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw n.kind==="unknown_action"?new m(422,"unknown_action",`no action named ${e.action} is declared from ${t}`):new m(422,"invalid_action",`${e.action} is declared in ${n.configOrigin} but unusable: ${n.reason}`,{reason:n.reason,configOrigin:n.configOrigin})}a(at,"resolveOutcomeDelivery");function lt(e,t,n){const r={kind:e.kind,cwd:n,prompt:e.prompt??""};return e.mode!==void 0&&(r.mode=e.mode),e.name!==void 0&&(r.name=e.name),e.description!==void 0&&(r.description=e.description),t!==void 0&&(r.parent=t),e.creator!==void 0&&(r.creator=e.creator),e.scopes!==void 0&&(r.scopes=e.scopes),e.isolated!==void 0&&(r.isolated=e.isolated),e.root===!0&&(r.root=!0),e.root_lifecycle!==void 0&&(r.rootLifecycle=e.root_lifecycle),(e.worktree===!0||typeof e.worktree=="string")&&(r.worktree=!0),typeof e.worktree=="string"&&(r.worktreeBase=e.worktree),e.worktree!==void 0&&(r.worktreeCwd=T(e.pin_cwd??e.cwd??n)),e.fork_from!==void 0&&(r.forkFrom=e.fork_from),e.model!==void 0&&(r.model=e.model),e.profile!==void 0&&(r.profile=e.profile),e.situational_context!==void 0&&(r.situationalContext=e.situational_context),e.node_id!==void 0&&(r.nodeId=e.node_id),r}a(lt,"buildRecipe");function ct(e,t,n){return!Dn()||e.prefer_warm!==!0||e.root!==!0||e.parent!=null||e.root_lifecycle==="terminal"||(e.prompt??"")!==""||e.model!==void 0||e.fork_from!==void 0||e.worktree!==void 0||e.node_id!==void 0||e.scopes!==void 0||e.isolated!==void 0?null:{kind:e.kind,mode:e.mode??"base",cwd:t,profileId:n,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}a(ct,"warmRequestFor");import{resolveCreateKind as ir}from"../../../core/runtime/launch-target.js";function we(e){const t=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Sn(e.model,t,e.modelExact===!0)}a(we,"requestFromLaunch");function ft(e,t){if(t===null)return e;if(e.scopes===void 0)return{...e,scopes:[...t]};const n=e.scopes.filter(r=>!O(t,r));if(n.length===0)return e;throw new m(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${n.join(", ")}`,{scopes:n,ceiling:t})}a(ft,"withinCeiling");async function ye(e,t,n){const r=(await bn(t.kind,t.mode,{lifecycle:t.lifecycle,hasManager:e.parent!==null,model:t.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await x(we(r),{cwd:e.cwd,profileId:e.profile_id??null},n)}a(ye,"assertNodeModelChangeRegistered");function _e(e,t){const n=e.principal;if(n.class!=="broker"&&n.class!=="cron")return;const r=qn({app:n.app,resolved:Un(n),launched:n.scopes},t,"read");if("root"in r)return;const o="missing"in r?r.missing:null;throw new m(403,"scope_missing",o?`the child's directory ${t} needs missing scope ${o}`:`no permission of this run names the child's directory ${t}`,void 0,void 0,o?{scope:o}:void 0)}a(_e,"assertCallerReaches");const H=new Map;async function ut(e,t={},n={}){const r=ft(it(e.body),e.ceiling);if(e.principal.class==="broker"){const c=e.principal;if(r.prefer_warm===!0&&c.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const i=y(r.parent);if(i.grantee!==c.app)throw new m(403,"other_app_run","cannot create a child under another app's node");if(!U(c,r.parent,i.grantee??"app:terminal"))throw P(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==c.node)throw new m(403,"other_app_run","cannot create for another node");if(r.fork_from!==void 0){let i=null;try{i=De(Ee(r.fork_from))}catch{}if(i?.grantee!==c.app||!U(c,i.node_id,i.grantee))throw new m(403,"other_app_run","cannot fork another app's conversation")}r.creator=c.node}if(e.principal.class==="cron"){const c=e.principal;for(const l of["parent","creator","fork_from","node_id"])if(r[l]!=null)throw new m(403,"permission_error",`a cron cannot set ${l} on a node it starts`);r.prefer_warm=!1;const i=Xe({grantee:c.app,sub:c.sub,grant_id:c.grant,scopes:c.scopes});if(!i.allowed)throw new m(i.reason==="scope_missing"?403:401,i.reason==="scope_missing"?"scope_missing":"grant_revoked",i.message);if(r.scopes!==void 0){const l=r.scopes.find(p=>!O(i.effectiveScopes,p)||!O(c.scopes,p));if(l!==void 0)throw new m(403,"scope_missing",`scope ${l} is not held by this cron`,void 0,void 0,{scope:l})}else c.scopes!==null&&(r.scopes=[...c.scopes]);r.node_id=ee(),c.isolated&&(r.isolated=!0,r.cwd=W(r.node_id,c.app))}r.creator!==void 0&&Wn(y(r.creator),"crtr:act");const o=r.request_key?.trim();if(o===void 0||r.node_id!==void 0&&Qe(r.node_id)&&k(r.node_id)!==null&&Le(o)?.nodeId!==r.node_id)return D(e,r,t,n);const s=H.get(o);if(s!==void 0)return s;const d=pt(e,r,o,t,n);H.set(o,d);try{return await d}finally{H.delete(o)}}a(ut,"handleCreate");async function pt(e,t,n,r,o){const s=oe(n);if(s.nodeId!==null&&k(s.nodeId)!==null){if(s.state!=="warm_claimed"){const d=k(s.nodeId);if(e.principal.class!=="person"&&!me(e.principal,d.grantee??"app:terminal",s.nodeId))throw new m(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:g(s.nodeId)}}return D(e,t,r,o,s)}try{return await D(e,t,r,o,s)}catch(d){const c=oe(n);throw(c.nodeId===null||k(c.nodeId)===null)&&ne(n,c.nodeId),d}}a(pt,"handleKeyedCreateRequest");async function D(e,t,n,r,o=void 0){const s=r.deadlineAt??dt(t.deadline),d=st(t.outcome_delivery),c=e.principal.class==="cron"?Ze({grantee:e.principal.app,sub:e.principal.sub,grant_id:e.principal.grant,scopes:e.principal.scopes,cron_id:e.principal.cron,origin_run_id:e.principal.origin_run,isolated:e.principal.isolated,creator:ue(e.principal.cron)?.created_by??null},t.node_id):null;c!==null&&(t.root=c.root===!0);const i=c?.parent??t.parent??void 0;if(i==null&&t.root!==!0)throw h("a node create requires a parent (or root: true for an independent root)");let l=null;if(t.output_schema!==void 0){try{l=JSON.parse(t.output_schema)}catch{throw h("output_schema must be a JSON schema string")}if(l===null||typeof l!="object"||Array.isArray(l))throw h("output_schema must be a JSON schema object");await An(l)}const{profileId:p,kind:u,cwd:f,launch:_}=await Ln(t,{validateKind:Se});_e(e,f),t.worktree!==void 0&&_e(e,T(t.pin_cwd??t.cwd??f));const S={...t,kind:u},I=d===void 0?void 0:at(d,f);if(await x(we(_),{cwd:f,profileId:p},n.modelRegistry),!await ot(p))throw new m(412,"no_provider_credential",he,{error:"no_provider_credential",message:he,next:"The person running this runtime logs a provider in with `crtr sys setup`, or stores a provider key on the profile."});let L=null;{const $=o===void 0||o.nodeId===null||o.state==="warm_claimed"?ct(S,f,p):null,M=l===null&&r.beforeBrokerLaunch===void 0?void 0:v=>{l!==null&&$n(v,"terminal",l),r.beforeBrokerLaunch?.(v)};if(o?.state==="warm_claimed"&&o.nodeId!==null){const v=$===null?null:await Pn($,o.nodeId,M);if(v===null)throw ne(o.requestKey,o.nodeId),new m(503,"create_resume_failed",`could not resume warm claim ${o.nodeId}; retry the create`);return te(o.requestKey,v),{status:201,body:g(v)}}if($!==null){const v=await En($,{...s===void 0?{}:{deadlineAt:s},...I===void 0?{}:{outcomeDelivery:I},...o===void 0?{}:{requestKey:o.requestKey}},M);if(v!==null)return o!==void 0&&te(o.requestKey,v),ce($),{status:201,body:g(v)};L=$}const F=o?.nodeId??t.node_id??(o===void 0?void 0:ee());o!==void 0&&o.nodeId===null&&Fe(o.requestKey,F);const R=lt(F===void 0?S:{...S,node_id:F},i,f);c!==null&&(c.rootLifecycle!==void 0&&(R.rootLifecycle=c.rootLifecycle),c.scopes!==void 0&&S.scopes===void 0&&(R.scopes=c.scopes),c.run!==void 0&&(R.run=c.run),c.withinCreate!==void 0&&(R.withinCreate=c.withinCreate)),s!==void 0&&(R.deadlineAt=s),I!==void 0&&(R.outcomeDelivery=I),R.readiness=t.root===!0?"await":"launch";const Q=await Pe(R,M,()=>{L!==null&&ce(L)});return o!==void 0&&Me(o.requestKey,Q.node.node_id),{status:201,body:g(Q.node.node_id)}}}a(D,"handleCreateRequest");function b(e,t){const n=e.query.getAll(t);if(n.length>1)throw h(`${t} must appear at most once`);return n[0]}a(b,"singleQueryValue");function ge(e,t){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw h(`${t} must be true or false`)}}a(ge,"optionalBoolean");function j(e,t,n){if(e!==void 0){if(n.includes(e))return e;throw h(`${t} must be one of: ${n.join(", ")}`)}}a(j,"oneOf");function mt(e){const t=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","hanging","include"]);for(const[_]of e.query)if(!t.has(_))throw h(`unknown nodes query parameter: ${_}`);const n=j(b(e,"status"),"status",["active","idle","done","dead","canceled"]),r=j(b(e,"lifecycle"),"lifecycle",["terminal","resident"]),o=b(e,"kind"),s=j(b(e,"mode"),"mode",["base","orchestrator"]),d=b(e,"profile_id"),c=b(e,"profile_prefix"),i=b(e,"parent"),l=ge(b(e,"top_level"),"top_level"),p=b(e,"under"),u=ge(b(e,"hanging"),"hanging"),f=j(b(e,"include"),"include",["activity"]);if(i!==void 0&&l===!0)throw h("parent and top_level=true cannot be combined");return{...n!==void 0?{status:n}:{},...r!==void 0?{lifecycle:r}:{},...o!==void 0?{kind:o}:{},...s!==void 0?{mode:s}:{},...d!==void 0?{profile_id:d}:{},...c!==void 0?{profile_prefix:c}:{},...i!==void 0?{parent:i}:{},...l!==void 0?{top_level:l}:{},...p!==void 0?{under:p}:{},...u!==void 0?{hanging:u}:{},...f!==void 0?{include:f}:{}}}a(mt,"parseListQuery");function ht(e){const t=mt(e);let n=t.status!==void 0?re({status:t.status}):re();if(e.principal.class!=="person"&&(n=n.filter(d=>me(e.principal,d.grantee??"app:terminal",d.node_id))),t.lifecycle!==void 0&&(n=n.filter(d=>d.lifecycle===t.lifecycle)),t.kind!==void 0&&(n=n.filter(d=>d.kind===t.kind)),t.mode!==void 0&&(n=n.filter(d=>d.mode===t.mode)),t.profile_id!==void 0&&(n=n.filter(d=>d.profile_id===t.profile_id)),t.profile_prefix!==void 0&&(n=n.filter(d=>d.profile_id?.startsWith(t.profile_prefix))),t.parent!==void 0&&(n=n.filter(d=>d.parent===t.parent)),t.top_level===!0&&(n=n.filter(d=>d.parent===null)),t.under!==void 0){const d=new Set(Ke(t.under));n=n.filter(c=>d.has(c.node_id))}t.hanging===!0&&(n=n.filter(d=>d.parent!==null&&k(d.parent)===null));const r=t.include==="activity"?He(n.map(d=>d.node_id)):null,o=n.length>0?Ie():new Set;return{status:200,body:n.map(d=>{const c=zn(d,d.profile_id!==null&&o.has(d.profile_id));if(r!==null){const i=fe(d.node_id);c.activity={latest_report:i[0]??null,final_report:d.final_report===null?null:i.find(l=>l.name===d.final_report)??null,pending_human_count:r[d.node_id]??0}}return c})}}a(ht,"handleList");async function wt(e){const t=e.params.id,n=await Yn(e,t,{method:"GET",path:`/v1/nodes/${encodeURIComponent(t)}`,query:Hn(e)});if(n.kind==="unknown")throw Xn(t,n.unreachable);if(n.kind==="remote"){if(n.status>=400)throw Qn(n.status,n.body);return{status:n.status,body:Zn(n.body,n.machine)}}return y(t),{status:200,body:g(t)}}a(wt,"handleDetail");async function yt(e){const t=e.params.id;y(t);const n=await dn(t);return{status:200,body:{node_id:t,snapshot:{messages:n.snapshot.messages,...n.snapshot.messageIds===void 0?{}:{messageIds:n.snapshot.messageIds},messageVisibility:n.snapshot.messageVisibility,turnVisibility:n.snapshot.turnVisibility,stats:n.snapshot.stats,state:n.snapshot.state,display:n.snapshot.display,...n.snapshot.queued===void 0?{}:{queued:n.snapshot.queued},...n.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:n.snapshot.toolGroupSummaries},...n.snapshot.turnReplies===void 0?{}:{turnReplies:n.snapshot.turnReplies},...n.snapshot.workingActivity===void 0?{}:{workingActivity:n.snapshot.workingActivity}},commands:n.commands.map(o=>({name:o.name,description:o.description,source:o.source})),captured_at:B()}}}a(yt,"handleSnapshot");async function _t(e){const t=e.params.id,n=an(t);if(n===null)throw P(`unknown node: ${t}`,{received:t});return{status:200,body:n}}a(_t,"handleSubject");function gt(e){for(const[s]of e.query)if(s!=="cursor"&&s!=="limit")throw h(`unknown messages query parameter: ${s}`);const t=e.query.getAll("cursor"),n=e.query.getAll("limit");if(t.length>1)throw h("cursor must appear at most once");if(n.length>1)throw h("limit must appear at most once");if(n.length===0)return t.length===0?{}:{cursor:t[0]};const r=n[0],o=Number(r);if(!Number.isSafeInteger(o)||r==="")throw h("limit must be an integer from 1 through 500");return t.length===0?{limit:o}:{cursor:t[0],limit:o}}a(gt,"parseMessagesQuery");async function bt(e){const t=e.params.id,n=await on(t,gt(e));return{status:200,body:{node_id:t,messages:n.messages,...n.messageIds===void 0?{}:{message_ids:n.messageIds},message_visibility:n.messageVisibility,next_cursor:n.nextCursor,captured_at:B()}}}a(bt,"handleMessages");function vt(e){const t=e.params.id;y(t);const n=rn(t);return{status:200,body:{node_id:t,session_file:n.sessionFile,session_jsonl:n.sessionJsonl,system_prompt:n.systemPrompt,captured_at:B()}}}a(vt,"handleSession");async function kt(e){const t=e.params.id;return y(t),{status:200,body:{node_id:t,markdown:await sn(t)}}}a(kt,"handleTranscript");function St(e){const t=e.params.id;y(t);const n=a((o,s)=>({node_id:o,label:k(o)?.name??o,dir:de(o),self:s,files:rt(o)}),"root"),r=[n(t,!0),...ie(t).map(o=>n(o.node_id,!1))].filter(o=>Rt(o.node_id,o.dir)||o.files>0);return{status:200,body:{node_id:t,roots:r}}}a(St,"handleContext");function Rt(e,t){try{return qe(W(e),t)}catch(n){if(nn(n))return!1;throw n}}a(Rt,"hasDir");async function Ot(e){const t=y(e.params.id),n=e.principal.class==="broker"?e.principal.scopes:e.ceiling,r=n===null?void 0:t.scopes==null?[...n]:[...new Set([...t.scopes.filter(s=>O(n,s)),...n.filter(s=>O(t.scopes,s))])],o=await Te(t.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:g(o.node.node_id)}}a(Ot,"handleFork");const It=1e4;async function $t(e){const t=e.params.id;y(t);const n=e.body,r=n?.resume??!0,o=n?.reopen??!1;mn(t,o);const s=!r&&n?.cron_id!==void 0?ue(n.cron_id):null,d=await Ne(t,{resume:r,capacity:"refuse",...s!==null?{wakeReason:xn(s,"schedule_revive")}:{}});d.outcome!=="already-live"&&Ge(t,{failures:0,notBefore:null});const c=k(t)?.status??"active",i=(d.launch??E().get(t)?.handle)?.exited,l=d.outcome!=="frozen"&&await ae(t,i,It);return{status:200,body:Jn(t,d,c,l)}}a($t,"handleRevive");async function At(e){const t=e.params.id;return{status:200,body:{newNodeId:(await pn(t))?.newNodeId??null}}}a(At,"handleRelaunchRoot");function Ct(e){const t=e.params.id;y(t);const n=e.body;if(n?.caller_pid!==void 0&&(!Number.isInteger(n.caller_pid)||n.caller_pid<=0))throw h("caller_pid must be a positive integer when provided");const r=Kn(),o=Ce(t,{rootEvent:n?.finish===!0?"finish":"cancel",callerPid:n?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...r===null?{}:{registerDetached:r.registerDetached}});return{status:200,body:Vn(o)}}a(Ct,"handleClose");async function Nt(e){const t=e.params.id;y(t);const n=await un(t);return{status:200,body:{recycled:n.recycled,finalized:n.finalized,new_root:n.newRoot,delivered:n.delivered}}}a(Nt,"handleRecycle");async function Tt(e){const t=e.params.id;return y(t),await V(t,{lifecycle:"terminal"}),A(e,t,["lifecycle"]),{status:200,body:g(t)}}a(Tt,"handleDemote");async function Et(e,t={}){const n=e.params.id,r=y(n),o=e.body??{};o.kind!==void 0&&await z(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await ye(r,{kind:o.kind??r.kind,mode:"orchestrator",lifecycle:o.resident===!0?"resident":r.lifecycle,model:o.model},t.modelRegistry);const s=await cn(n,{...o.kind!==void 0?{kind:o.kind}:{},...o.resident===!0?{resident:!0}:{},...o.model!==void 0?{model:o.model}:{}});A(e,n,["mode",...o.kind!==void 0?["kind"]:[],...o.resident===!0?["lifecycle"]:[],...o.model!==void 0?["model"]:[]]);const d=J(s.meta,Y(n));return d.roadmap_written=s.roadmapWritten,d.roadmap_ref=s.roadmapRef,d.goal_path=s.goalPath,{status:200,body:d}}a(Et,"handlePromote");async function Pt(e,t={}){const n=e.params.id,r=y(n),o=e.body??{};o.kind!==void 0&&await z(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await ye(r,{kind:o.kind??r.kind,mode:o.promote===!0?"orchestrator":r.mode,lifecycle:r.lifecycle,model:o.model},t.modelRegistry);const s=o.note??"Refresh: continue against your roadmap or goal.";hn(n,s);const d=await fn(n,{...o.promote===!0?{promote:!0}:{},...o.kind!==void 0?{kind:o.kind}:{},...o.model!==void 0?{model:o.model}:{}});return{status:200,body:J(d.meta,Y(n))}}a(Pt,"handleYield");function Dt(e){const t=e.params.id;y(t);const n=e.body;if(n===void 0||typeof n.controller!="string"||n.controller.trim()==="")throw h("a wait requires a controller node id");const r=k(n.controller);if(r===null)throw P(`unknown controller: ${n.controller}`,{received:n.controller});if(r.status!=="active"&&r.status!=="idle")throw new m(422,"unprocessable",`controller ${n.controller} is ${r.status}`);return xe(t,n.controller),{status:200,body:g(t)}}a(Dt,"handleWait");async function jt(e){const t=e.principal,n=await ln(t.class==="broker"?o=>o.grantee===t.app&&U(t,o.node_id,o.grantee):void 0);return{status:200,body:{revived:[...n.revived],failed:[...n.failed],frozen:[...n.frozen]}}}a(jt,"handleReviveAll");const Lt=new Set(["interrupt","steer","after-turn","next-turn"]);function Mt(e){if(e===null)return null;const t=a(r=>{throw new w({error:"invalid_listen",message:r,received:e,field:"listen",next:'Send an object mapping levels "1".."10" to interrupt|steer|after-turn|next-turn (e.g. {"3":"next-turn"}), or null to reset to the global default.'})},"bad");if(typeof e!="object"||Array.isArray(e))return t("listen must be an object or null");const n=Object.entries(e);if(n.length===0)return t("listen must name at least one level");for(const[r,o]of n)/^(?:[1-9]|10)$/.test(r)||t(`listen level must be 1..10: ${r}`),(typeof o!="string"||!Lt.has(o))&&t(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(o)}`);return JSON.stringify(Object.fromEntries(n))}a(Mt,"listenJson");function A(e,t,n,r){n.length===0&&r===void 0||K(o=>{if(r?.(o),n.length===0)return;const s=We(o,t),d=Je(o,e),c=d.class==="person"?d.person:d.class==="app"?d.app:d.node;Ve(o,c,s),ze(o,{event:"configured",object:s,actor:c,attrs:{changed:n.join(",")}})})}a(A,"recordConfigured");function be(e){const t=E().get(e);if(t===void 0)return!1;try{return process.kill(t.pid,"SIGTERM"),!0}catch{return!1}}a(be,"restartLiveBroker");function ve(e,t){try{return Z(e)===Z(t)}catch{return!1}}a(ve,"sameDirectory");async function Ft(e,t={}){const n=e.params.id,r=e.body;let o;if(r===void 0)o={};else if(typeof r=="object"&&r!==null&&!Array.isArray(r))o=r;else throw new w({error:"cwd_invalid",message:"cwd repair requires a non-null object with a non-empty cwd string",received:r,field:"cwd",next:"Send a config patch with a non-empty absolute cwd string."});if(o.profile!==void 0){if(typeof o.profile!="string"||o.profile==="")throw new w({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:o.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(o).some(u=>u!=="profile"&&u!=="restart"&&o[u]!==void 0))throw new w({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const i=y(n),l=Fn(e,o.profile);Gn(l.profileId);const p=Bn(l.profileId).manifest.grantee??"app:terminal";if(p!==(i.grantee??"app:terminal"))throw new w({error:"profile_grantee_mismatch",message:`profile ${l.profileId} belongs to ${p}, node ${n} to ${i.grantee}`,received:o.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(i.profile_id??null)!==l.profileId&&(jn(i.kind)?(await z(i.kind,i.cwd,l.profileId),await V(n,{profileId:l.profileId})):C(n,{profile_id:l.profileId}),A(e,n,["profile"])),o.restart===!0&&be(n),{status:200,body:g(n)}}if(Object.prototype.hasOwnProperty.call(o,"cwd")){const i=o.cwd;if(typeof i!="string"||i==="")throw new w({error:"cwd_invalid",message:"cwd must be a non-empty string",received:i,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(o).some(f=>f!=="cwd"&&f!=="keep_session"&&f!=="restart"&&o[f]!==void 0))throw new w({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:o,field:"cwd",next:"Send cwd as the only config field."});const l=y(n),p=N(l.cwd);if(o.keep_session===!0||p&&G(i)&&N(i)&&ve(l.cwd,i)){if(!G(i))throw new w({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const f=T(i);let _=!1;try{_=q(f).isDirectory()}catch{}if(!_)throw new w({error:"cwd_missing",message:`cwd is not an existing directory: ${f}`,received:i,field:"cwd",next:"Send an existing absolute directory."});if(p&&!ve(l.cwd,f))throw new w({error:"cwd_not_same_directory",message:`${f} is not the same directory as the recorded ${l.cwd}; --keep-session only relocates an alias`,received:i,field:"cwd",next:"Drop --keep-session to repair a gone cwd, or pass the real path of the recorded directory."});if(l.managed_worktree?.state==="open")throw new w({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot relocate its cwd`,received:i,field:"cwd",next:"Reconcile the managed worktree first."});const S=l.cwd;return S!==f&&(K(I=>{C(n,{cwd:f}),X(I,"UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(f,n,S),Ue(n,S,f)}),A(e,n,["cwd"])),o.restart===!0&&be(n),{status:200,body:g(n)}}if(E().has(n)){const f=`${n} cannot repair its cwd while its broker is live`;throw new m(409,"cwd_node_live",f,{error:"cwd_node_live",message:f,received:i,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(l.fork_from!=null)throw new w({error:"cwd_node_forked",message:`${n} is a fork and cannot repair its cwd; recorded cwd: ${l.cwd}`,received:i,field:"cwd",next:`Restore ${l.cwd}, then revive the fork normally.`});if(l.managed_worktree?.state==="open")throw new w({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot repair its cwd`,received:i,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(N(l.cwd))throw new w({error:"cwd_still_present",message:`${n} recorded cwd still exists: ${l.cwd}; cwd repair is not a relocation command`,received:i,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!G(i))throw new w({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const u=T(i);if(!N(u))throw new w({error:"cwd_missing",message:`cwd does not exist: ${u}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!q(u).isDirectory())throw new w({error:"cwd_not_a_directory",message:`cwd is not a directory: ${u}`,received:i,field:"cwd",next:"Send an existing absolute directory."})}catch(f){throw f instanceof w?f:new w({error:"cwd_missing",message:`cwd does not exist: ${u}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return K(()=>{C(n,{cwd:u}),Ye(n)}),A(e,n,["cwd"]),{status:200,body:g(n)}}let s=y(n);const d=o.listen===void 0?void 0:Mt(o.listen);if(o.scopes!==void 0){const i=pe(o.scopes),l=s.grantee==="app:terminal"?nt():s.grant_id?et(s.grant_id):null,p=s.grantee==="app:terminal"&&!tt("user").runtime?.issuer;if(!i.every(u=>O(s.scopes,u)&&(l?O(l.resolved,u):p)))throw new w({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:i,field:"scopes",next:"Send only scopes the node currently holds."});if(i.includes("crtr:act")&&!O(i,"crtr:llm"))throw new m(400,"invalid_scope","crtr:act requires crtr:llm");s=C(n,{scopes:i})}if(o.situational_context!==void 0&&$e(n,Ae(o.situational_context)),o.model!==void 0){const i=(await se(s.cwd,s.profile_id??null)).modelLadders,l=vn(o.model,i),p=kn(o.model,i);await x({kind:"concrete",spec:p},{cwd:s.cwd,profileId:s.profile_id??null},t.modelRegistry);const u=E();let f=!1;if(u.isClaimed(n)&&await ae(n,u.get(n)?.handle.exited)&&(f=await On(n,p,l).then(()=>!0,_=>{if(_ instanceof In)return!1;throw _})),!f){if(u.isClaimed(n)){const _=`${n}'s broker did not accept the model switch; the model was not changed`;throw new m(409,"broker_not_ready",_,{error:"broker_not_ready",message:_,received:o.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!p.includes("/"))throw h(`model must resolve to a provider/id spec: ${o.model}`);Rn(n,p,l)}s=y(n)}if(o.kind!==void 0||o.mode!==void 0||o.lifecycle!==void 0){o.kind!==void 0&&await Se(o.kind);const i=o.kind??s.kind,l=o.mode??s.mode,p=o.lifecycle??s.lifecycle;let u;l==="orchestrator"&&!_n(n)&&(u=a(()=>{const f=wn(n);yn(n,f!==null&&f.trim()!==""?{goal:f.trim()}:{})},"beforePersist")),s=await V(n,{...o.kind!==void 0?{kind:i}:{},...o.mode!==void 0?{mode:l}:{},...o.lifecycle!==void 0?{lifecycle:p}:{}},u)}o.name!==void 0&&(s=C(n,{name:o.name}),s.window&&gn(s.window,Mn(s)));const c=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(i=>o[i]!==void 0);return A(e,n,c,d===void 0?void 0:i=>{X(i,"UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(d,n)}),{status:200,body:g(n)}}a(Ft,"handleConfig");async function ke(){return(await se(process.cwd(),Oe()||null)).kinds}a(ke,"daemonKinds");async function Se(e){const t=Object.keys(await ke());if(!t.includes(e))throw h(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${t.sort().join(", ")}.`})}a(Se,"assertKindServer");async function Gt(){const e=await ke();return{status:200,body:{kinds:Object.keys(e).sort().map(n=>({kind:n,when_to_use:e[n]?.whenToUse??null,available_to:e[n]?.availableTo??null}))}}}a(Gt,"handleListKinds");const tr=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:ut},{method:"GET",pattern:"/v1/nodes",handler:ht},{method:"GET",pattern:"/v1/kinds",handler:a(()=>Gt(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:jt},{method:"GET",pattern:"/v1/nodes/:id",handler:wt},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:yt},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:_t},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:bt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:vt},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:kt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:St},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Ot},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:$t},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:At},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Ct},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Nt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Tt},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Et},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Pt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Dt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:Ft}];export{Ft as handleConfig,ut as handleCreate,Ot as handleFork,ht as handleList,Et as handlePromote,Pt as handleYield,tr as nodeRoutes,ir as resolveCreateKind};
|
|
1
|
+
var Re=Object.defineProperty;var a=(e,t)=>Re(e,"name",{value:t,configurable:!0});import{prepared as X}from"../../../core/sqlite-statements.js";import{envProfileId as Ie}from"../../../shared/env.js";import{pausedCanvasProfiles as Oe}from"../../../core/profiles/manifest.js";import{existsSync as N,realpathSync as Z,statSync as q}from"node:fs";import{isAbsolute as G,resolve as T}from"node:path";import{appendSituationalContext as $e,formatSituationalProse as Ae}from"../../../core/runtime/situational-context.js";import{closeNode as Ce}from"../../../core/runtime/close.js";import{reviveNode as Ne}from"../../../core/runtime/revive.js";import{nowIso as B}from"../../../core/fs-utils.js";import{assertLaunchModelRegistered as x,forkNode as Te,resolveForkSource as Ee,spawnChildPrepared as Pe}from"../../../core/runtime/spawn.js";import{forkSourceNode as De,newNodeId as ee}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as ne,childrenOf as Le,completeCreateRequest as te,findCreateRequest as Me,getNode as R,recordCreateRequestNode as je,reserveCreateRequest as oe,reserveCreateRequestNode as Fe,listNodes as re,recordRespawnAttempt as Ge,subscribersOf as Be,subscriptionsOf as ie,setMessageWait as xe,updateNode as C}from"../../../core/canvas/canvas.js";import{subtreeIds as Ke}from"../../../core/canvas/nav-model.js";import{withCanvasWrite as K}from"../../../core/canvas/db.js";import{nodeObject as We}from"../../../core/graph/objects.js";import{recordActedOn as Ve}from"../../../core/graph/edges.js";import{publish as ze}from"../../../core/graph/events.js";import{readerFor as Je}from"../reader.js";import{relocateSessionCwd as Ue,unbindSession as Ye}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as He}from"../../../core/canvas/attention.js";import{isSafeNodeId as Qe}from"../../../core/canvas/paths.js";import{contextDir as de,nodeAgentDir as W}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as Xe}from"../../cron/authority.js";import{cronBirthPlacement as Ze}from"../../cron/armed-context.js";import{existsBeneath as qe,isAbsentOrRefused as en,isBeneathRefusal as nn,readdirBeneath as tn}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as on,readNodeSession as rn,readNodeSnapshot as dn,transcriptMarkdown as sn}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as an}from"../../../core/substrate/subject.js";import{reviveAll as ln}from"../../../core/runtime/revive-all.js";import{promoteAsync as cn,requestYieldAsync as fn,reshapeNodeAsync as V}from"../../../core/runtime/promote.js";import{recycleNode as un}from"../../../core/runtime/recycle.js";import{relaunchRoot as pn}from"../../../core/runtime/reset.js";import{assertReopenGate as mn}from"../../../core/runtime/reopen.js";import{writeYieldMessage as hn,readGoal as wn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as yn,hasRoadmap as _n}from"../../../core/runtime/roadmap.js";import{renameWindow as gn}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as bn,explicitModelIntent as vn,normalizeModel as kn,readMergedLaunchConfigAsync as se}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as Sn}from"../../../core/model-routes.js";import{persistDormantModel as Rn,setModelLive as In}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as ae}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as On}from"../../../core/runtime/broker-request.js";import{boundFleet as E}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as $n}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as An}from"../../../core/runtime/structured-output.js";import{OUTCOME_PAYLOAD_MAX_BYTES as le}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as Cn}from"../../../core/human/action-binding.js";import{resolveHumanAction as Nn}from"../../../core/human-actions.js";import{parseDurationMs as Tn}from"../../../core/wake.js";import{claimWarmNode as En,refillWarmPool as ce,resumeWarmClaim as Pn,warmPoolEnabled as Dn}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as z,isLaunchKind as Ln,resolveLaunchTarget as Mn}from"../../../core/runtime/launch-target.js";import{fullName as jn}from"../../../core/canvas/labels.js";import{reportsForNode as fe}from"./reports.js";import{requireUsableProfile as Fn}from"./profiles.js";import{assertProfileActive as Gn,loadExactProfileManifest as Bn}from"../../../core/profiles/manifest.js";import{getCron as ue}from"../../../core/canvas/crons.js";import{cronWakeOrigin as xn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as Kn}from"../../control.js";import{notFound as P,usage as h}from"../../../core/errors.js";import{assertScope as Wn,validateScopes as pe}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as Vn,toNodeDetailDTO as J,toNodeSummaryDTO as zn,toReviveResultDTO as Jn}from"../map.js";import{ApiError as m}from"../../../api/index.js";import{InputError as w}from"../../../core/io.js";import{brokerMayReach as U,canReadNode as me,resolvedScopes as Un}from"../router.js";import{forwardVerb as Yn,queryWithoutMachine as Hn,relayError as Qn,unknownError as Xn,withMachine as Zn}from"../../peer/forward.js";import{fileRoot as qn}from"../../../core/spaces/file-root.js";import{activeGrant as et,terminalGrant as nt}from"../../../core/grants/mirror.js";import{appRungForGrant as tt}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as ot}from"../../../core/model-routes.js";import{readConfig as rt}from"../../../core/config.js";import{hasConfiguredProviderCredential as it,NO_PROVIDER_CREDENTIAL_MESSAGE as he}from"../../../core/runtime/provider-credential-gate.js";function y(e){const t=R(e);if(t===null)throw P(`unknown node: ${e}`,{received:e});return t}a(y,"requireMeta");function Y(e){return{subscribesTo:ie(e),subscribers:Be(e),children:Le(e)}}a(Y,"edgesFor");function g(e){const t=y(e);return J(t,Y(e))}a(g,"detailOf");function dt(e){let t=fe(e).length;try{t+=tn(W(e),de(e)).length}catch(n){if(!en(n))throw n}return t}a(dt,"countFiles");function st(e){if(typeof e!="object"||e===null)throw h("a node create requires a JSON body");const t=e;if(t.kind!==void 0&&(typeof t.kind!="string"||t.kind.trim()===""))throw h("kind must be a non-empty string when provided");if(t.description!==void 0&&(typeof t.description!="string"||t.description.trim()===""))throw h("description must be a non-empty string when provided");if(t.creator!==void 0&&(typeof t.creator!="string"||t.creator.trim()===""))throw h("creator must be a non-empty node id when provided");if(t.scopes!==void 0&&pe(t.scopes),t.isolated!==void 0&&typeof t.isolated!="boolean")throw new m(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const n=t.root_lifecycle;if(n!==void 0&&n!=="resident"&&n!=="terminal")throw h("root_lifecycle must be 'resident' or 'terminal'");if(t.request_key!==void 0&&(typeof t.request_key!="string"||t.request_key.trim()===""||t.request_key.length>128))throw h("request_key must be a non-empty string of at most 128 characters when provided");return t}a(st,"parseCreateBody");function at(e){if(e===void 0)return;const t=Tn(e),n=t===null?null:new Date(Date.now()+t);if(t===null||!Number.isFinite(t)||t<=0||n===null||!Number.isFinite(n.getTime()))throw new m(422,"invalid_deadline","`deadline` must be a positive representable duration");return n.toISOString()}a(at,"parseDeadline");function lt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new m(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!Cn.test(e.action))throw new m(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let t;try{t=JSON.stringify(e.payload)}catch{throw new m(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(t===void 0)throw new m(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(t,"utf8")>le)throw new m(413,"payload_too_large",`serialized payload exceeds ${le} bytes`)}return e}}a(lt,"parseOutcomeDelivery");function ct(e,t){const n=Nn(e.action,t);if(!("kind"in n))return{actionName:e.action,argv:n.argv,cwd:n.cwd,configOrigin:n.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw n.kind==="unknown_action"?new m(422,"unknown_action",`no action named ${e.action} is declared from ${t}`):new m(422,"invalid_action",`${e.action} is declared in ${n.configOrigin} but unusable: ${n.reason}`,{reason:n.reason,configOrigin:n.configOrigin})}a(ct,"resolveOutcomeDelivery");function ft(e,t,n){const r={kind:e.kind,cwd:n,prompt:e.prompt??""};return e.mode!==void 0&&(r.mode=e.mode),e.name!==void 0&&(r.name=e.name),e.description!==void 0&&(r.description=e.description),t!==void 0&&(r.parent=t),e.creator!==void 0&&(r.creator=e.creator),e.scopes!==void 0&&(r.scopes=e.scopes),e.isolated!==void 0&&(r.isolated=e.isolated),e.root===!0&&(r.root=!0),e.root_lifecycle!==void 0&&(r.rootLifecycle=e.root_lifecycle),(e.worktree===!0||typeof e.worktree=="string")&&(r.worktree=!0),typeof e.worktree=="string"&&(r.worktreeBase=e.worktree),e.worktree!==void 0&&(r.worktreeCwd=T(e.pin_cwd??e.cwd??n)),e.fork_from!==void 0&&(r.forkFrom=e.fork_from),e.model!==void 0&&(r.model=e.model),e.profile!==void 0&&(r.profile=e.profile),e.situational_context!==void 0&&(r.situationalContext=e.situational_context),e.node_id!==void 0&&(r.nodeId=e.node_id),r}a(ft,"buildRecipe");function ut(e,t,n){return!Dn()||e.prefer_warm!==!0||e.root!==!0||e.parent!=null||e.root_lifecycle==="terminal"||(e.prompt??"")!==""||e.model!==void 0||e.fork_from!==void 0||e.worktree!==void 0||e.node_id!==void 0||e.scopes!==void 0||e.isolated!==void 0?null:{kind:e.kind,mode:e.mode??"base",cwd:t,profileId:n,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}a(ut,"warmRequestFor");import{resolveCreateKind as lr}from"../../../core/runtime/launch-target.js";function we(e){const t=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Sn(e.model,t,e.modelExact===!0)}a(we,"requestFromLaunch");function pt(e,t){if(t===null)return e;if(e.scopes===void 0)return{...e,scopes:[...t]};const n=e.scopes.filter(r=>!O(t,r));if(n.length===0)return e;throw new m(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${n.join(", ")}`,{scopes:n,ceiling:t})}a(pt,"withinCeiling");async function ye(e,t,n){const r=(await bn(t.kind,t.mode,{lifecycle:t.lifecycle,hasManager:e.parent!==null,model:t.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await x(we(r),{cwd:e.cwd,profileId:e.profile_id??null},n)}a(ye,"assertNodeModelChangeRegistered");function _e(e,t){const n=e.principal;if(n.class!=="broker"&&n.class!=="cron")return;const r=qn({app:n.app,resolved:Un(n),launched:n.scopes},t,"read");if("root"in r)return;const o="missing"in r?r.missing:null;throw new m(403,"scope_missing",o?`the child's directory ${t} needs missing scope ${o}`:`no permission of this run names the child's directory ${t}`,void 0,void 0,o?{scope:o}:void 0)}a(_e,"assertCallerReaches");const H=new Map;async function mt(e,t={},n={}){const r=pt(st(e.body),e.ceiling);if(e.principal.class==="broker"){const c=e.principal;if(r.prefer_warm===!0&&c.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const i=y(r.parent);if(i.grantee!==c.app)throw new m(403,"other_app_run","cannot create a child under another app's node");if(!U(c,r.parent,i.grantee??"app:terminal"))throw P(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==c.node)throw new m(403,"other_app_run","cannot create for another node");if(r.fork_from!==void 0){let i=null;try{i=De(Ee(r.fork_from))}catch{}if(i?.grantee!==c.app||!U(c,i.node_id,i.grantee))throw new m(403,"other_app_run","cannot fork another app's conversation")}r.creator=c.node}if(e.principal.class==="cron"){const c=e.principal;for(const l of["parent","creator","fork_from","node_id"])if(r[l]!=null)throw new m(403,"permission_error",`a cron cannot set ${l} on a node it starts`);r.prefer_warm=!1;const i=Xe({grantee:c.app,sub:c.sub,grant_id:c.grant,scopes:c.scopes});if(!i.allowed)throw new m(i.reason==="scope_missing"?403:401,i.reason==="scope_missing"?"scope_missing":"grant_revoked",i.message);if(r.scopes!==void 0){const l=r.scopes.find(u=>!O(i.effectiveScopes,u)||!O(c.scopes,u));if(l!==void 0)throw new m(403,"scope_missing",`scope ${l} is not held by this cron`,void 0,void 0,{scope:l})}else c.scopes!==null&&(r.scopes=[...c.scopes]);r.node_id=ee(),c.isolated&&(r.isolated=!0,r.cwd=W(r.node_id,c.app))}r.creator!==void 0&&Wn(y(r.creator),"crtr:act");const o=r.request_key?.trim();if(o===void 0||r.node_id!==void 0&&Qe(r.node_id)&&R(r.node_id)!==null&&Me(o)?.nodeId!==r.node_id)return D(e,r,t,n);const s=H.get(o);if(s!==void 0)return s;const d=ht(e,r,o,t,n);H.set(o,d);try{return await d}finally{H.delete(o)}}a(mt,"handleCreate");async function ht(e,t,n,r,o){const s=oe(n);if(s.nodeId!==null&&R(s.nodeId)!==null){if(s.state!=="warm_claimed"){const d=R(s.nodeId);if(e.principal.class!=="person"&&!me(e.principal,d.grantee??"app:terminal",s.nodeId))throw new m(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:g(s.nodeId)}}return D(e,t,r,o,s)}try{return await D(e,t,r,o,s)}catch(d){const c=oe(n);throw(c.nodeId===null||R(c.nodeId)===null)&&ne(n,c.nodeId),d}}a(ht,"handleKeyedCreateRequest");async function D(e,t,n,r,o=void 0){const s=r.deadlineAt??at(t.deadline),d=lt(t.outcome_delivery),c=e.principal.class==="cron"?Ze({grantee:e.principal.app,sub:e.principal.sub,grant_id:e.principal.grant,scopes:e.principal.scopes,cron_id:e.principal.cron,origin_run_id:e.principal.origin_run,isolated:e.principal.isolated,creator:ue(e.principal.cron)?.created_by??null},t.node_id):null;c!==null&&(t.root=c.root===!0);const i=c?.parent??t.parent??void 0;if(i==null&&t.root!==!0)throw h("a node create requires a parent (or root: true for an independent root)");let l=null;if(t.output_schema!==void 0){try{l=JSON.parse(t.output_schema)}catch{throw h("output_schema must be a JSON schema string")}if(l===null||typeof l!="object"||Array.isArray(l))throw h("output_schema must be a JSON schema object");await An(l)}const{profileId:u,kind:p,cwd:f,launch:b}=await Mn(t,{validateKind:Se});_e(e,f),t.worktree!==void 0&&_e(e,T(t.pin_cwd??t.cwd??f));const v={...t,kind:p},_=d===void 0?void 0:ct(d,f);if(await x(we(b),{cwd:f,profileId:u},n.modelRegistry),!await it(u))throw new m(412,"no_provider_credential",he,{error:"no_provider_credential",message:he,next:"The person running this runtime logs a provider in with `crtr sys setup`, or stores a provider key on the profile."});let M=null;{const $=o===void 0||o.nodeId===null||o.state==="warm_claimed"?ut(v,f,u):null,j=l===null&&r.beforeBrokerLaunch===void 0?void 0:S=>{l!==null&&$n(S,"terminal",l),r.beforeBrokerLaunch?.(S)};if(o?.state==="warm_claimed"&&o.nodeId!==null){const S=$===null?null:await Pn($,o.nodeId,j);if(S===null)throw ne(o.requestKey,o.nodeId),new m(503,"create_resume_failed",`could not resume warm claim ${o.nodeId}; retry the create`);return te(o.requestKey,S),{status:201,body:g(S)}}if($!==null){const S=await En($,{...s===void 0?{}:{deadlineAt:s},..._===void 0?{}:{outcomeDelivery:_},...o===void 0?{}:{requestKey:o.requestKey}},j);if(S!==null)return o!==void 0&&te(o.requestKey,S),ce($),{status:201,body:g(S)};M=$}const F=o?.nodeId??t.node_id??(o===void 0?void 0:ee());o!==void 0&&o.nodeId===null&&Fe(o.requestKey,F);const I=ft(F===void 0?v:{...v,node_id:F},i,f);c!==null&&(c.rootLifecycle!==void 0&&(I.rootLifecycle=c.rootLifecycle),c.scopes!==void 0&&v.scopes===void 0&&(I.scopes=c.scopes),c.run!==void 0&&(I.run=c.run),c.withinCreate!==void 0&&(I.withinCreate=c.withinCreate)),s!==void 0&&(I.deadlineAt=s),_!==void 0&&(I.outcomeDelivery=_),I.readiness=t.root===!0?"await":"launch";const Q=await Pe(I,j,()=>{M!==null&&ce(M)});return o!==void 0&&je(o.requestKey,Q.node.node_id),{status:201,body:g(Q.node.node_id)}}}a(D,"handleCreateRequest");function k(e,t){const n=e.query.getAll(t);if(n.length>1)throw h(`${t} must appear at most once`);return n[0]}a(k,"singleQueryValue");function ge(e,t){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw h(`${t} must be true or false`)}}a(ge,"optionalBoolean");function L(e,t,n){if(e!==void 0){if(n.includes(e))return e;throw h(`${t} must be one of: ${n.join(", ")}`)}}a(L,"oneOf");function wt(e){const t=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","hanging","include"]);for(const[b]of e.query)if(!t.has(b))throw h(`unknown nodes query parameter: ${b}`);const n=L(k(e,"status"),"status",["active","idle","done","dead","canceled"]),r=L(k(e,"lifecycle"),"lifecycle",["terminal","resident"]),o=k(e,"kind"),s=L(k(e,"mode"),"mode",["base","orchestrator"]),d=k(e,"profile_id"),c=k(e,"profile_prefix"),i=k(e,"parent"),l=ge(k(e,"top_level"),"top_level"),u=k(e,"under"),p=ge(k(e,"hanging"),"hanging"),f=L(k(e,"include"),"include",["activity"]);if(i!==void 0&&l===!0)throw h("parent and top_level=true cannot be combined");return{...n!==void 0?{status:n}:{},...r!==void 0?{lifecycle:r}:{},...o!==void 0?{kind:o}:{},...s!==void 0?{mode:s}:{},...d!==void 0?{profile_id:d}:{},...c!==void 0?{profile_prefix:c}:{},...i!==void 0?{parent:i}:{},...l!==void 0?{top_level:l}:{},...u!==void 0?{under:u}:{},...p!==void 0?{hanging:p}:{},...f!==void 0?{include:f}:{}}}a(wt,"parseListQuery");function yt(e){const t=wt(e);let n=t.status!==void 0?re({status:t.status}):re();if(e.principal.class!=="person"&&(n=n.filter(d=>me(e.principal,d.grantee??"app:terminal",d.node_id))),t.lifecycle!==void 0&&(n=n.filter(d=>d.lifecycle===t.lifecycle)),t.kind!==void 0&&(n=n.filter(d=>d.kind===t.kind)),t.mode!==void 0&&(n=n.filter(d=>d.mode===t.mode)),t.profile_id!==void 0&&(n=n.filter(d=>d.profile_id===t.profile_id)),t.profile_prefix!==void 0&&(n=n.filter(d=>d.profile_id?.startsWith(t.profile_prefix))),t.parent!==void 0&&(n=n.filter(d=>d.parent===t.parent)),t.top_level===!0&&(n=n.filter(d=>d.parent===null)),t.under!==void 0){const d=new Set(Ke(t.under));n=n.filter(c=>d.has(c.node_id))}t.hanging===!0&&(n=n.filter(d=>d.parent!==null&&R(d.parent)===null));const r=t.include==="activity"?He(n.map(d=>d.node_id)):null,o=n.length>0?Oe():new Set;return{status:200,body:n.map(d=>{const c=zn(d,d.profile_id!==null&&o.has(d.profile_id));if(r!==null){const i=fe(d.node_id);c.activity={latest_report:i[0]??null,final_report:d.final_report===null?null:i.find(l=>l.name===d.final_report)??null,pending_human_count:r[d.node_id]??0}}return c})}}a(yt,"handleList");async function _t(e){const t=e.params.id,n=await Yn(e,t,{method:"GET",path:`/v1/nodes/${encodeURIComponent(t)}`,query:Hn(e)});if(n.kind==="unknown")throw Xn(t,n.unreachable);if(n.kind==="remote"){if(n.status>=400)throw Qn(n.status,n.body);return{status:n.status,body:Zn(n.body,n.machine)}}return y(t),{status:200,body:g(t)}}a(_t,"handleDetail");async function gt(e){const t=e.params.id;y(t);const n=await dn(t);return{status:200,body:{node_id:t,snapshot:{messages:n.snapshot.messages,...n.snapshot.messageIds===void 0?{}:{messageIds:n.snapshot.messageIds},messageVisibility:n.snapshot.messageVisibility,turnVisibility:n.snapshot.turnVisibility,stats:n.snapshot.stats,state:n.snapshot.state,display:n.snapshot.display,...n.snapshot.queued===void 0?{}:{queued:n.snapshot.queued},...n.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:n.snapshot.toolGroupSummaries},...n.snapshot.turnReplies===void 0?{}:{turnReplies:n.snapshot.turnReplies},...n.snapshot.workingActivity===void 0?{}:{workingActivity:n.snapshot.workingActivity}},commands:n.commands.map(o=>({name:o.name,description:o.description,source:o.source})),captured_at:B()}}}a(gt,"handleSnapshot");async function bt(e){const t=e.params.id,n=an(t);if(n===null)throw P(`unknown node: ${t}`,{received:t});return{status:200,body:n}}a(bt,"handleSubject");function vt(e){for(const[s]of e.query)if(s!=="cursor"&&s!=="limit")throw h(`unknown messages query parameter: ${s}`);const t=e.query.getAll("cursor"),n=e.query.getAll("limit");if(t.length>1)throw h("cursor must appear at most once");if(n.length>1)throw h("limit must appear at most once");if(n.length===0)return t.length===0?{}:{cursor:t[0]};const r=n[0],o=Number(r);if(!Number.isSafeInteger(o)||r==="")throw h("limit must be an integer from 1 through 500");return t.length===0?{limit:o}:{cursor:t[0],limit:o}}a(vt,"parseMessagesQuery");async function kt(e){const t=e.params.id,n=await on(t,vt(e));return{status:200,body:{node_id:t,messages:n.messages,...n.messageIds===void 0?{}:{message_ids:n.messageIds},message_visibility:n.messageVisibility,next_cursor:n.nextCursor,captured_at:B()}}}a(kt,"handleMessages");function St(e){const t=e.params.id;y(t);const n=rn(t);return{status:200,body:{node_id:t,session_file:n.sessionFile,session_jsonl:n.sessionJsonl,system_prompt:n.systemPrompt,captured_at:B()}}}a(St,"handleSession");async function Rt(e){const t=e.params.id;return y(t),{status:200,body:{node_id:t,markdown:await sn(t)}}}a(Rt,"handleTranscript");function It(e){const t=e.params.id;y(t);const n=a((o,s)=>({node_id:o,label:R(o)?.name??o,dir:de(o),self:s,files:dt(o)}),"root"),r=[n(t,!0),...ie(t).map(o=>n(o.node_id,!1))].filter(o=>Ot(o.node_id,o.dir)||o.files>0);return{status:200,body:{node_id:t,roots:r}}}a(It,"handleContext");function Ot(e,t){try{return qe(W(e),t)}catch(n){if(nn(n))return!1;throw n}}a(Ot,"hasDir");async function $t(e){const t=y(e.params.id),n=e.principal.class==="broker"?e.principal.scopes:e.ceiling,r=n===null?void 0:t.scopes==null?[...n]:[...new Set([...t.scopes.filter(s=>O(n,s)),...n.filter(s=>O(t.scopes,s))])],o=await Te(t.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:g(o.node.node_id)}}a($t,"handleFork");const At=1e4;async function Ct(e){const t=e.params.id;y(t);const n=e.body,r=n?.resume??!0,o=n?.reopen??!1;mn(t,o);const s=!r&&n?.cron_id!==void 0?ue(n.cron_id):null,d=await Ne(t,{resume:r,capacity:"refuse",...s!==null?{wakeReason:xn(s,"schedule_revive")}:{}});d.outcome!=="already-live"&&Ge(t,{failures:0,notBefore:null});const c=R(t)?.status??"active",i=(d.launch??E().get(t)?.handle)?.exited,l=d.outcome!=="frozen"&&await ae(t,i,At);return{status:200,body:Jn(t,d,c,l)}}a(Ct,"handleRevive");async function Nt(e){const t=e.params.id;return{status:200,body:{newNodeId:(await pn(t))?.newNodeId??null}}}a(Nt,"handleRelaunchRoot");function Tt(e){const t=e.params.id;y(t);const n=e.body;if(n?.caller_pid!==void 0&&(!Number.isInteger(n.caller_pid)||n.caller_pid<=0))throw h("caller_pid must be a positive integer when provided");const r=Kn(),o=Ce(t,{rootEvent:n?.finish===!0?"finish":"cancel",callerPid:n?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...r===null?{}:{registerDetached:r.registerDetached}});return{status:200,body:Vn(o)}}a(Tt,"handleClose");async function Et(e){const t=e.params.id;y(t);const n=await un(t);return{status:200,body:{recycled:n.recycled,finalized:n.finalized,new_root:n.newRoot,delivered:n.delivered}}}a(Et,"handleRecycle");async function Pt(e){const t=e.params.id;return y(t),await V(t,{lifecycle:"terminal"}),A(e,t,["lifecycle"]),{status:200,body:g(t)}}a(Pt,"handleDemote");async function Dt(e,t={}){const n=e.params.id,r=y(n),o=e.body??{};o.kind!==void 0&&await z(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await ye(r,{kind:o.kind??r.kind,mode:"orchestrator",lifecycle:o.resident===!0?"resident":r.lifecycle,model:o.model},t.modelRegistry);const s=await cn(n,{...o.kind!==void 0?{kind:o.kind}:{},...o.resident===!0?{resident:!0}:{},...o.model!==void 0?{model:o.model}:{}});A(e,n,["mode",...o.kind!==void 0?["kind"]:[],...o.resident===!0?["lifecycle"]:[],...o.model!==void 0?["model"]:[]]);const d=J(s.meta,Y(n));return d.roadmap_written=s.roadmapWritten,d.roadmap_ref=s.roadmapRef,d.goal_path=s.goalPath,{status:200,body:d}}a(Dt,"handlePromote");async function Lt(e,t={}){const n=e.params.id,r=y(n),o=e.body??{};o.kind!==void 0&&await z(o.kind,r.cwd,r.profile_id??null),o.model!==void 0&&await ye(r,{kind:o.kind??r.kind,mode:o.promote===!0?"orchestrator":r.mode,lifecycle:r.lifecycle,model:o.model},t.modelRegistry);const s=o.note??"Refresh: continue against your roadmap or goal.";hn(n,s);const d=await fn(n,{...o.promote===!0?{promote:!0}:{},...o.kind!==void 0?{kind:o.kind}:{},...o.model!==void 0?{model:o.model}:{}});return{status:200,body:J(d.meta,Y(n))}}a(Lt,"handleYield");function Mt(e){const t=e.params.id;y(t);const n=e.body;if(n===void 0||typeof n.controller!="string"||n.controller.trim()==="")throw h("a wait requires a controller node id");const r=R(n.controller);if(r===null)throw P(`unknown controller: ${n.controller}`,{received:n.controller});if(r.status!=="active"&&r.status!=="idle")throw new m(422,"unprocessable",`controller ${n.controller} is ${r.status}`);return xe(t,n.controller),{status:200,body:g(t)}}a(Mt,"handleWait");async function jt(e){const t=e.principal,n=await ln(t.class==="broker"?o=>o.grantee===t.app&&U(t,o.node_id,o.grantee):void 0);return{status:200,body:{revived:[...n.revived],failed:[...n.failed],frozen:[...n.frozen]}}}a(jt,"handleReviveAll");const Ft=new Set(["interrupt","steer","after-turn","next-turn"]);function Gt(e){if(e===null)return null;const t=a(r=>{throw new w({error:"invalid_listen",message:r,received:e,field:"listen",next:'Send an object mapping levels "1".."10" to interrupt|steer|after-turn|next-turn (e.g. {"3":"next-turn"}), or null to reset to the global default.'})},"bad");if(typeof e!="object"||Array.isArray(e))return t("listen must be an object or null");const n=Object.entries(e);if(n.length===0)return t("listen must name at least one level");for(const[r,o]of n)/^(?:[1-9]|10)$/.test(r)||t(`listen level must be 1..10: ${r}`),(typeof o!="string"||!Ft.has(o))&&t(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(o)}`);return JSON.stringify(Object.fromEntries(n))}a(Gt,"listenJson");function A(e,t,n,r){n.length===0&&r===void 0||K(o=>{if(r?.(o),n.length===0)return;const s=We(o,t),d=Je(o,e),c=d.class==="person"?d.person:d.class==="app"?d.app:d.node;Ve(o,c,s),ze(o,{event:"configured",object:s,actor:c,attrs:{changed:n.join(",")}})})}a(A,"recordConfigured");function be(e){const t=E().get(e);if(t===void 0)return!1;try{return process.kill(t.pid,"SIGTERM"),!0}catch{return!1}}a(be,"restartLiveBroker");function ve(e,t){try{return Z(e)===Z(t)}catch{return!1}}a(ve,"sameDirectory");async function Bt(e,t={}){const n=e.params.id,r=e.body;let o;if(r===void 0)o={};else if(typeof r=="object"&&r!==null&&!Array.isArray(r))o=r;else throw new w({error:"cwd_invalid",message:"cwd repair requires a non-null object with a non-empty cwd string",received:r,field:"cwd",next:"Send a config patch with a non-empty absolute cwd string."});if(o.profile!==void 0){if(typeof o.profile!="string"||o.profile==="")throw new w({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:o.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(o).some(p=>p!=="profile"&&p!=="restart"&&o[p]!==void 0))throw new w({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const i=y(n),l=Fn(e,o.profile);Gn(l.profileId);const u=Bn(l.profileId).manifest.grantee??"app:terminal";if(u!==(i.grantee??"app:terminal"))throw new w({error:"profile_grantee_mismatch",message:`profile ${l.profileId} belongs to ${u}, node ${n} to ${i.grantee}`,received:o.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(i.profile_id??null)!==l.profileId&&(Ln(i.kind)?(await z(i.kind,i.cwd,l.profileId),await V(n,{profileId:l.profileId})):C(n,{profile_id:l.profileId}),A(e,n,["profile"])),o.restart===!0&&be(n),{status:200,body:g(n)}}if(Object.prototype.hasOwnProperty.call(o,"cwd")){const i=o.cwd;if(typeof i!="string"||i==="")throw new w({error:"cwd_invalid",message:"cwd must be a non-empty string",received:i,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(o).some(f=>f!=="cwd"&&f!=="keep_session"&&f!=="restart"&&o[f]!==void 0))throw new w({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:o,field:"cwd",next:"Send cwd as the only config field."});const l=y(n),u=N(l.cwd);if(o.keep_session===!0||u&&G(i)&&N(i)&&ve(l.cwd,i)){if(!G(i))throw new w({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const f=T(i);let b=!1;try{b=q(f).isDirectory()}catch{}if(!b)throw new w({error:"cwd_missing",message:`cwd is not an existing directory: ${f}`,received:i,field:"cwd",next:"Send an existing absolute directory."});if(u&&!ve(l.cwd,f))throw new w({error:"cwd_not_same_directory",message:`${f} is not the same directory as the recorded ${l.cwd}; --keep-session only relocates an alias`,received:i,field:"cwd",next:"Drop --keep-session to repair a gone cwd, or pass the real path of the recorded directory."});if(l.managed_worktree?.state==="open")throw new w({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot relocate its cwd`,received:i,field:"cwd",next:"Reconcile the managed worktree first."});const v=l.cwd;return v!==f&&(K(_=>{C(n,{cwd:f}),X(_,"UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(f,n,v),Ue(n,v,f)}),A(e,n,["cwd"])),o.restart===!0&&be(n),{status:200,body:g(n)}}if(E().has(n)){const f=`${n} cannot repair its cwd while its broker is live`;throw new m(409,"cwd_node_live",f,{error:"cwd_node_live",message:f,received:i,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(l.fork_from!=null)throw new w({error:"cwd_node_forked",message:`${n} is a fork and cannot repair its cwd; recorded cwd: ${l.cwd}`,received:i,field:"cwd",next:`Restore ${l.cwd}, then revive the fork normally.`});if(l.managed_worktree?.state==="open")throw new w({error:"cwd_node_managed_worktree_open",message:`${n} owns an open managed worktree and cannot repair its cwd`,received:i,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(N(l.cwd))throw new w({error:"cwd_still_present",message:`${n} recorded cwd still exists: ${l.cwd}; cwd repair is not a relocation command`,received:i,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!G(i))throw new w({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${i}`,received:i,field:"cwd",next:"Send an absolute path."});const p=T(i);if(!N(p))throw new w({error:"cwd_missing",message:`cwd does not exist: ${p}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!q(p).isDirectory())throw new w({error:"cwd_not_a_directory",message:`cwd is not a directory: ${p}`,received:i,field:"cwd",next:"Send an existing absolute directory."})}catch(f){throw f instanceof w?f:new w({error:"cwd_missing",message:`cwd does not exist: ${p}`,received:i,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return K(()=>{C(n,{cwd:p}),Ye(n)}),A(e,n,["cwd"]),{status:200,body:g(n)}}let s=y(n);const d=o.listen===void 0?void 0:Gt(o.listen);if(o.scopes!==void 0){const i=pe(o.scopes),l=s.grantee==="app:terminal"?nt():s.grant_id?et(s.grant_id):null,u=s.grantee==="app:terminal"&&!rt("user").runtime?.issuer;if(!i.every(p=>O(s.scopes,p)&&(l?O(l.resolved,p):u)))throw new w({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:i,field:"scopes",next:"Send only scopes the node currently holds."});if(i.includes("crtr:act")&&!O(i,"crtr:llm"))throw new m(400,"invalid_scope","crtr:act requires crtr:llm");s=C(n,{scopes:i})}if(o.situational_context!==void 0&&$e(n,Ae(o.situational_context)),o.model!==void 0){const i=(await se(s.cwd,s.profile_id??null)).modelLadders,l=vn(o.model,i),u=tt(s.grant_id,o.model,l===void 0),p=u?{family:ot,strength:u.strength}:l,f=u?u.model:kn(o.model,i);await x({kind:"concrete",spec:f},{cwd:s.cwd,profileId:s.profile_id??null},t.modelRegistry);const b=E();let v=!1;if(b.isClaimed(n)&&await ae(n,b.get(n)?.handle.exited)&&(v=await In(n,f,p).then(()=>!0,_=>{if(_ instanceof On)return!1;throw _})),!v){if(b.isClaimed(n)){const _=`${n}'s broker did not accept the model switch; the model was not changed`;throw new m(409,"broker_not_ready",_,{error:"broker_not_ready",message:_,received:o.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!f.includes("/"))throw h(`model must resolve to a provider/id spec: ${o.model}`);Rn(n,f,p)}s=y(n)}if(o.kind!==void 0||o.mode!==void 0||o.lifecycle!==void 0){o.kind!==void 0&&await Se(o.kind);const i=o.kind??s.kind,l=o.mode??s.mode,u=o.lifecycle??s.lifecycle;let p;l==="orchestrator"&&!_n(n)&&(p=a(()=>{const f=wn(n);yn(n,f!==null&&f.trim()!==""?{goal:f.trim()}:{})},"beforePersist")),s=await V(n,{...o.kind!==void 0?{kind:i}:{},...o.mode!==void 0?{mode:l}:{},...o.lifecycle!==void 0?{lifecycle:u}:{}},p)}o.name!==void 0&&(s=C(n,{name:o.name}),s.window&&gn(s.window,jn(s)));const c=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(i=>o[i]!==void 0);return A(e,n,c,d===void 0?void 0:i=>{X(i,"UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(d,n)}),{status:200,body:g(n)}}a(Bt,"handleConfig");async function ke(){return(await se(process.cwd(),Ie()||null)).kinds}a(ke,"daemonKinds");async function Se(e){const t=Object.keys(await ke());if(!t.includes(e))throw h(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${t.sort().join(", ")}.`})}a(Se,"assertKindServer");async function xt(){const e=await ke();return{status:200,body:{kinds:Object.keys(e).sort().map(n=>({kind:n,when_to_use:e[n]?.whenToUse??null,available_to:e[n]?.availableTo??null}))}}}a(xt,"handleListKinds");const dr=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:mt},{method:"GET",pattern:"/v1/nodes",handler:yt},{method:"GET",pattern:"/v1/kinds",handler:a(()=>xt(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:jt},{method:"GET",pattern:"/v1/nodes/:id",handler:_t},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:gt},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:bt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:kt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:St},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:Rt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:It},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:$t},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Ct},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:Nt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Tt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Et},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Pt},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Dt},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Lt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Mt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:Bt}];export{Bt as handleConfig,mt as handleCreate,$t as handleFork,yt as handleList,Dt as handlePromote,Lt as handleYield,dr as nodeRoutes,lr as resolveCreateKind};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
content unavailable: ${s.unavailable}`,data:{...f,content:"markdown"in s?"live":"unavailable"}}})}c(Je,"read");function Q(e,t,n,r){if(e!=null){if(!n.includes(e)){r.push({field:t,problem:`must be one of ${n.join(", ")}`,received:e});return}return e}}c(Q,"oneOf");function be(e,t,n){if(t!=null){if(typeof t!="string"||!We(e,t)){n.push({field:"type",problem:`must be a kind: one of ${Ce(e).join(", ")}`,received:t});return}return t}}c(be,"kindName");function je(e,t,n,r){if(e==null)return r;const o=Number(e);return!Number.isInteger(o)||o<1||o>100?(n.push({field:t,problem:"must be an integer from 1 to 100",received:e}),r):o}c(je,"limitOf");function ke(e){const t=e.query,n=[],r=be(T(),t.get("type"),n),o=Q(t.get("privacy"),"privacy",Ae,n),i=je(t.get("limit"),"limit",n,50),s=t.get("cursor");s!==null&&!/^\d+$/.test(s)&&n.push({field:"cursor",problem:"is not a cursor from a previous page",received:s});const a=t.get("deleted");return a!==null&&!["0","1","true","false"].includes(a)&&n.push({field:"deleted",problem:"must be true or false",received:a}),n.length>0&&W("object list request",n),k(l=>{const u=v(l,e),f={...r?{type:r}:{},...o?{privacy:o}:{},...t.get("kind")!==null?{kind:t.get("kind")}:{},...a==="1"||a==="true"?{deleted:!0}:{}},m=t.get("owner");if(m!==null){const h=pe(l,u,m);if(h===null)return{items:[],next_cursor:null};f.owner=h}const b=t.get("name"),j=[];let p=s===null?0:Number(s),w=!0;for(;j.length<i&&w;){const h=De(l,u,f,{limit:100,after_rowid:p});w=h.length===100;for(const E of h)if(p=E.rowid,(b===null||E.name.startsWith(b))&&j.push(E),j.length===i)break}const d=j.at(-1);return{items:j.map(h=>he(l,h)),next_cursor:j.length===i&&d?String(d.rowid):null}})}c(ke,"listLocal");const Qe={ms:3e4},Ye="self",Y=c((e,t)=>e.map(n=>({...n,machine:t})),"labelItems");async function _e(e,t,n,r){const o=F.current;try{const i=await o.call(t.id,{method:"GET",path:"/v1/objects",query:n},o.envelope(e.principal),r);if(Ke(i))return{state:"unreachable",items:[],next:null};if(i.status===426)return{state:"too_old",items:[],next:null};const s=i.body;return i.status!==200||!Array.isArray(s?.items)?{state:"unreachable",items:[],next:null}:{state:"ok",items:Y(s.items,t),next:s.next_cursor??null}}catch{return{state:"unreachable",items:[],next:null}}}c(_e,"remotePage");async function Xe(e){const t=new Promise(n=>e.addEventListener("abort",()=>n(null),{once:!0}));return Promise.race([F.current.machines().catch(()=>null),t])}c(Xe,"machinesWithin");async function xe(e){const t=e.query.get("machine");if(!le(e.principal)||!F.current.joined()||t===Ye)return ke(ve(e));const r=F.current.self(),o=t!==null&&S(t)!==r,i=o?null:ke(ve(e)),s=new AbortController,a=setTimeout(()=>s.abort(),Qe.ms);a.unref?.();try{const l=await Xe(s.signal);if(l===null){if(o)throw new y(503,"runtime_unreachable",`The directory did not answer, so ${S(t)} cannot be listed.`,{machine:S(t)});return i}const u=c(d=>({id:d,name:l.find(h=>h.machine_id===d)?.name??d}),"labelOf"),f=u(r),m=l.filter(d=>d.machine_id!==r&&d.kind!=="device"),b=V(e);if(t!==null){if(!o)return{items:Y(i.items,f),next_cursor:i.next_cursor,machines:[{machine_id:r,name:f.name,state:"ok",more:i.next_cursor!==null}]};const d=S(t);if(!m.some(E=>E.machine_id===d))throw new y(404,"not_found",`no machine ${d} on your account`,{machine:d});const h=await _e(e,u(d),b,s.signal);return{items:h.items,next_cursor:h.next,machines:[{machine_id:d,name:u(d).name,state:h.state,more:h.next!==null}]}}const{cursor:j,...p}=b,w=await Promise.all(m.map(d=>_e(e,u(d.machine_id),p,s.signal)));return{items:[...Y(i.items,f),...w.flatMap(d=>d.items)],next_cursor:i.next_cursor,machines:[{machine_id:r,name:f.name,state:"ok",more:i.next_cursor!==null},...m.map((d,h)=>({machine_id:d.machine_id,name:d.name,state:w[h].state,more:w[h].next!==null}))]}}finally{clearTimeout(a)}}c(xe,"list");function ve(e){const t=new URLSearchParams(e.query);return t.delete("machine"),{...e,query:t}}c(ve,"withoutMachine");function et(e){const t=[],n=R(e.body)?e.body:{};R(e.body)||t.push({field:"body",problem:"must be an object",received:e.body});const r=n.text;(typeof r!="string"||r.trim()==="")&&t.push({field:"text",problem:"is required",received:r});const o=n.grep;if(o!==void 0)if(typeof o!="string")t.push({field:"grep",problem:"must be a regular expression string",received:o});else try{new RegExp(o)}catch(a){t.push({field:"grep",problem:`is not a valid regular expression: ${a.message}`,received:o})}n.body!==void 0&&typeof n.body!="boolean"&&t.push({field:"body",problem:"must be a boolean",received:n.body});const i=be(T(),n.type,t);n.kind!==void 0&&typeof n.kind!="string"&&t.push({field:"kind",problem:"must be a string",received:n.kind}),n.owner!==void 0&&typeof n.owner!="string"&&t.push({field:"owner",problem:"must be a string",received:n.owner});const s=je(n.limit,"limit",t,50);return t.length>0&&W("object search request",t),k(a=>{const l=v(a,e),u=typeof n.owner=="string"?pe(a,l,n.owner):null;if(typeof n.owner=="string"&&u===null)return{items:[]};const f=ie(a,l,{text:r,body:n.body===!0||typeof o=="string"}),m=new Set(f.map(p=>p.object.rowid));return{items:(typeof o=="string"?ie(a,l,{text:o,grep:!0}).filter(p=>m.has(p.object.rowid)):f).filter(p=>(!i||p.object.type===i)&&(n.kind===void 0||p.object.kind===n.kind)&&(!u||p.object.owner===u.rowid)).slice(0,s).map(p=>({object:he(a,p.object),...p.line!==void 0?{matches:[{line:p.line,text:p.text??""}]}:{}}))}})}c(et,"search");const Oe=["interrupt","steer","after-turn","next-turn"],tt=/^(\*|>|[A-Za-z0-9_-]+)(\.(\*|>|[A-Za-z0-9_-]+))*$/;function nt(e,t){if(e!==void 0){if(!Array.isArray(e)||e.length===0||e.some(n=>typeof n!="string"||!tt.test(n)||n.includes(">")&&!n.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}}c(nt,"patternsOf");function rt(e,t){if(e===void 0)return;if(!R(e)||Object.keys(e).length===0){t.push({field:"config",problem:"must map levels 1-10 to a delivery",received:e});return}const n=[];for(const[r,o]of Object.entries(e)){const i=Number(r);!Number.isInteger(i)||i<1||i>10?t.push({field:`config.${r}`,problem:"level must be an integer from 1 to 10"}):Oe.includes(o)?n.push({threshold:i,delivery:o}):t.push({field:`config.${r}`,problem:`delivery must be one of ${Oe.join(", ")}`,received:o})}return n.sort((r,o)=>o.threshold-r.threshold)}c(rt,"configOf");function Ee(e){const t=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})}c(Ee,"refuseStubWatch");function X(e,t){const n=L(e,t)??(()=>{const r=Ne(e,Ie(e,{class:"person"},()=>[]),t);return"object"in r?r.object:null})();return n===null||n.deleted_at!==null||!(n.type.includes(".")||n.type==="node")?null:n}c(X,"findWatcher");const O=c(()=>{throw new y(404,"not_found","watcher not found")},"watcherNotFound");async function qe(e,t,n){if(typeof t!="string"||n===void 0||n===null)return null;if(typeof n!="string")throw new y(400,"invalid_request","invalid watcher_machine");if(X(e,t)!==null)return null;const r=F.current;let o;try{o=await r.machines()}catch{throw new y(503,"runtime_unreachable","The directory did not answer, so the watcher machine cannot be checked.")}const i=S(n);return(i===r.self()||!o.some(s=>S(s.machine_id)===i))&&O(),i}c(qe,"remoteWatcherMachine");function Te(e,t,n,r){if(t.publishToken||t.principal.class==="anonymous")return O();const o=v(e,t);if(o.class==="person")return O();let i;try{i=q(e,o,r)}catch{return O()}const s=i.owner===null?null:de(e,i.owner);return s===null||!ne(e,o,s)||!Le(e,o,"link",n)?O():(D(e,t,n),{actor:o.app,object:i})}c(Te,"linkWatcher");function Re(e,t,n){if(t.publishToken)return!0;if(t.principal.class==="anonymous"||!n.type.includes("."))return!1;const r=v(e,t),o=n.owner===null?null:de(e,n.owner);return o!==null&&ne(e,r,o)&&Fe(e,r,n)}c(Re,"ownsWatcher");async function ot(e){const t=_(e),n=R(e.body)?e.body:{};if(typeof n.watcher=="string"&&Ee(t),typeof n.watcher!="string"){const o=await K(e,t,{method:"POST",path:`${J(t)}/watch`,body:e.body},()=>Z(t,e));if(o.kind==="unknown")throw fe(t,o.unreachable);if(o.kind==="remote"){if(o.status>=400)throw B(o.status,o.body);const i=o.body.patterns;return ge(e,o.body,o.machine.id,"ask",i),H(o.body,o.machine)}}const r=await qe(T(),n.watcher,n.watcher_machine);return it(e,r)}c(ot,"watch");function it(e,t=null){const n=[],r=e.body===void 0?{}:R(e.body)?e.body:(n.push({field:"body",problem:"must be an object"}),{}),o=nt(r.patterns,n),i=rt(r.config,n);return r.filter!==void 0&&!R(r.filter)&&n.push({field:"filter",problem:"must be an object",received:r.filter}),r.watcher!==void 0&&typeof r.watcher!="string"&&n.push({field:"watcher",problem:"must be a custom-object ref",received:r.watcher}),r.watcher_machine!==void 0&&typeof r.watcher_machine!="string"&&n.push({field:"watcher_machine",problem:"must be a machine id",received:r.watcher_machine}),n.length>0&&W("watch request",n),k(s=>{const a=typeof r.watcher=="string";if((e.publishToken||e.principal.class==="anonymous")&&!a)throw new y(404,"not_found","watcher not found");const l=o??[">"],u={patterns:l,...i?{config:i}:{},...r.filter!==void 0?{filter:r.filter}:{}};if(a){const j=r.watcher,p=t===null?null:st(s,e,j,t),w=p??(e.publishToken?re(s,j):X(s,j));if(w===null)return O();if(p===null&&Re(s,e,w)){const E=oe(s,e,w);D(s,e,w);const x=C(s,w),N=q(s,x,_(e));if(!te(s,x,N))throw new y(404,"not_found","object not found");return P(s,w,N,"act",u),M(s,{event:"watched",object:N,actor:E,attrs:{}},A(s)),{object:$(s,N,g(s,N)),patterns:l}}const{actor:d,object:h}=Te(s,e,w,_(e));return P(s,w,h,"act",{...u,linkApp:d}),M(s,{event:"watched",object:h,actor:d,attrs:{}},A(s)),{object:$(s,h,g(s,h)),patterns:l}}const f=v(s,e),m=U(s,e)??ee(f),b=q(s,f,_(e));return P(s,m,b,"ask",u),M(s,{event:"watched",object:b,actor:m,attrs:{}},A(s)),{object:$(s,b,g(s,b)),patterns:l}})}c(it,"watchLocal");function st(e,t,n,r){return t.publishToken||t.principal.class==="anonymous"?O():Be(e,n,r)}c(st,"ensureNodeStubFor");async function at(e){const t=_(e);if(e.query.get("watcher")&&Ee(t),!e.query.get("watcher")){const r=await K(e,t,{method:"DELETE",path:`${J(t)}/watch`,query:V(e)},()=>Z(t,e));if(r.kind==="unknown")throw fe(t,r.unreachable);if(r.kind==="remote"){if(r.status>=400)throw B(r.status,r.body);const o=r.body.object?.id;return k(i=>{const s=ue(i,e),a=o===void 0?null:L(i,o);s!==null&&a!==null&&me(i,a)&&se(i,s,a,e.query.get("pattern")??void 0)}),H(r.body,r.machine)}}const n=await qe(T(),e.query.get("watcher")??void 0,e.query.get("watcher_machine")??void 0);return ut(e,n)}c(at,"unwatchRoute");function ut(e,t=null){const n=e.query.get("pattern"),r=e.query.get("watcher");return k(o=>{if((e.publishToken||e.principal.class==="anonymous")&&!r)throw new y(404,"not_found","watcher not found");const i=c((u,f)=>Se(o,`SELECT count(*) AS n FROM watch_subscriptions s JOIN watches w ON w.rowid = s.watch
|
|
3
|
-
|
|
1
|
+
var Re=Object.defineProperty;var l=(e,t)=>Re(e,"name",{value:t,configurable:!0});import{prepared as $e}from"../../../core/sqlite-statements.js";import{ApiError as y}from"../../../api/errors.js";import{PRIVACY_LEVELS_DTO as Ie}from"../../../api/dto/objects.js";import{openDb as T,withCanvasWrite as _}from"../../../core/canvas/db.js";import{actorOf as ee}from"../../../core/graph/documents.js";import{readerForObject as D,readerFor as Se}from"../../../core/graph/reader.js";import{resolveName as Ae}from"../../../core/graph/names.js";import{canRead as te,customReachable as Ne,holdsObjectsScope as Fe,mayActAs as ne}from"../../../core/graph/access.js";import{customObjectRef as re,authorizeCustom as oe,fenceArgv as M}from"./custom-objects.js";import{edgesOf as Le}from"../../../core/graph/edges.js";import{publish as G}from"../../../core/graph/events.js";import{objectDTO as g}from"../../../core/graph/kinds/dto.js";import{isKind as We,kindNames as Pe,kindOf as z}from"../../../core/graph/kinds/registry.js";import{listObjects as Ce,searchObjects as ie}from"../../../core/graph/objects.js";import{checkoutsForCwd as De}from"../../../core/graph/repo-sync/repos.js";import{recordWatch as W,unwatch as Me,watchersOf as Ge,watchesOf as ze}from"../../../core/graph/watches.js";import{readerFor as v,resolveRef as H}from"../reader.js";import{readDelegationFor as se,runReadLeaf as He}from"../../plugin-objects/read-leaf.js";import{invalidRequest as P,isRecord as R}from"./validate.js";import{callerNode as ue,callerStub as U,forwardVerb as ae,originates as ce,queryWithoutMachine as V,relayError as C,remoteStub as Ue,unknownError as le,forwarding as F,withMachine as B}from"../../peer/forward.js";import{getById as L,getByRowid as fe}from"../../../core/graph/objects.js";import{ensureNodeStub as Ve,isStub as K,stubOf as Be,withKindDecl as $}from"../../../core/peer/stubs.js";import{isUnreachable as Ke}from"../../../core/peer/client.js";import{normalizeMachineId as I}from"../../../core/peer/directory.js";const S=l(e=>t=>De(e,t),"reposFnFor");function de(e,t){return{...g(e,t),...z(e,t.type).listItem?.(e,t)}}l(de,"listItem");function Ze(e){return`no object named ${e} on this runtime; it may be on another runtime, or the name may be misspelled`}l(Ze,"remoteMessage");function me(e,t,r){try{return q(e,t,r)}catch(n){if(n instanceof y&&n.code==="not_found"&&!n.details?.deleted)return null;throw n}}l(me,"ownerFilter");function q(e,t,r){const n=H(e,t,r);if("remote"in n)throw new y(404,"not_found",Ze(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(q,"liveRef");const k=l(e=>decodeURIComponent(e.params.ref),"refParam"),he=l(e=>{const t=e.trim().replace(/^\[\[(.*)\]\]$/,"$1").trim(),r=t.indexOf("/");return r>0?t.slice(0,r):t},"idOf");function pe(e){const t=L(T(),he(e));return t!==null&&K(T(),t)?t.id:null}l(pe,"stubIdOf");function Je(e,t){const r=pe(e);return r!==null?{stub:r,hit:!0}:_(n=>{try{const o=H(n,v(n,t),e);if("remote"in o)return{stub:null,hit:!1};const i="deleted"in o?o.deleted:o;return{stub:K(n,i)?i.id:null,hit:!0}}catch{return{stub:null,hit:!1}}})}l(Je,"resolvedLocally");async function Z(e,t,r){const n=Je(t,e);return n.stub!==null?ae(e,n.stub,r):n.hit||!ce(e.principal)?{kind:"local"}:ae(e,he(t),r)}l(Z,"forwardRef");const J=l(e=>`/v1/objects/${encodeURIComponent(e)}`,"objectPath");function we(e,t,r,n,o){const i=t?.object;!i?.id||!i.type||_(s=>{const u=ue(s,e);if(u===null)return;const c=Ue(s,i.id,i.type,r,{kind:i.kind??null,name:i.name??i.id,...i.preview===void 0?{}:{preview:i.preview},owner:i.owner??null,...i.kind_decl===void 0?{}:{kind_decl:i.kind_decl},...i.privacy===void 0?{}:{privacy:i.privacy}});W(s,u,c,n,o===void 0?{}:{patterns:o})})}l(we,"watchRemote");async function Qe(e){const t=k(e),r=["1","true"].includes(e.query.get("fields")??""),n=await Z(e,t,{method:"GET",path:J(t),query:V(e)});if(n.kind==="unknown")return{state:"unknown",ref:t,unreachable:n.unreachable};if(n.kind==="remote"){if(n.status>=400)throw C(n.status,n.body);return we(e,n.body,n.machine.id,"read"),B(n.body,n.machine)}const o=l(u=>{const c=U(u,e);return c===null?v(u,e):D(u,c,S(u))},"readerOf"),i=_(u=>{const c=o(u),a=H(u,c,t);if("remote"in a)return{state:"remote",remote:a.remote};if("deleted"in a)return{state:"deleted",deleted:g(u,a.deleted)};const f=se(u,a);if(f!==null)return{delegate:f,hitId:a.id};const{data:p,text:b}=z(u,a.type).read(u,c,a,{fields:r,reposFn:S(u)});return{state:"object",type:a.type,object:$(u,a,g(u,a)),text:b,data:p}});if(!("delegate"in i))return i;const s=await He(i.delegate,e.principal);return _(u=>{const c=o(u),a=L(u,i.hitId);if(a===null)throw new y(404,"not_found","object not found");if(a.deleted_at!==null)return{state:"deleted",deleted:g(u,a)};if(!te(u,c,a))throw new y(404,"not_found","object not found");const{data:f,text:p}=z(u,a.type).read(u,c,a,{fields:r,reposFn:S(u)});return se(u,a)===null?{state:"object",type:a.type,object:$(u,a,g(u,a)),text:p,data:f}:{state:"object",type:a.type,object:$(u,a,g(u,a)),text:"markdown"in s?s.markdown:`${p}
|
|
2
|
+
content unavailable: ${s.unavailable}`,data:{...f,content:"markdown"in s?"live":"unavailable"}}})}l(Qe,"read");function Q(e,t,r,n){if(e!=null){if(!r.includes(e)){n.push({field:t,problem:`must be one of ${r.join(", ")}`,received:e});return}return e}}l(Q,"oneOf");function ye(e,t,r){if(t!=null){if(typeof t!="string"||!We(e,t)){r.push({field:"type",problem:`must be a kind: one of ${Pe(e).join(", ")}`,received:t});return}return t}}l(ye,"kindName");function ge(e,t,r,n){if(e==null)return n;const o=Number(e);return!Number.isInteger(o)||o<1||o>100?(r.push({field:t,problem:"must be an integer from 1 to 100",received:e}),n):o}l(ge,"limitOf");function be(e){const t=e.query,r=[],n=ye(T(),t.get("type"),r),o=Q(t.get("privacy"),"privacy",Ie,r),i=ge(t.get("limit"),"limit",r,50),s=t.get("cursor");s!==null&&!/^\d+$/.test(s)&&r.push({field:"cursor",problem:"is not a cursor from a previous page",received:s});const u=t.get("deleted");return u!==null&&!["0","1","true","false"].includes(u)&&r.push({field:"deleted",problem:"must be true or false",received:u}),r.length>0&&P("object list request",r),_(c=>{const a=v(c,e),f={...n?{type:n}:{},...o?{privacy:o}:{},...t.get("kind")!==null?{kind:t.get("kind")}:{},...u==="1"||u==="true"?{deleted:!0}:{}},p=t.get("owner");if(p!==null){const m=me(c,a,p);if(m===null)return{items:[],next_cursor:null};f.owner=m}const b=t.get("name"),j=[];let h=s===null?0:Number(s),w=!0;for(;j.length<i&&w;){const m=Ce(c,a,f,{limit:100,after_rowid:h});w=m.length===100;for(const E of m)if(h=E.rowid,(b===null||E.name.startsWith(b))&&j.push(E),j.length===i)break}const d=j.at(-1);return{items:j.map(m=>de(c,m)),next_cursor:j.length===i&&d?String(d.rowid):null}})}l(be,"listLocal");const Ye={ms:3e4},Xe="self",Y=l((e,t)=>e.map(r=>({...r,machine:t})),"labelItems");async function je(e,t,r,n){const o=F.current;try{const i=await o.call(t.id,{method:"GET",path:"/v1/objects",query:r},o.envelope(e.principal),n);if(Ke(i))return{state:"unreachable",items:[],next:null};if(i.status===426)return{state:"too_old",items:[],next:null};const s=i.body;return i.status!==200||!Array.isArray(s?.items)?{state:"unreachable",items:[],next:null}:{state:"ok",items:Y(s.items,t),next:s.next_cursor??null}}catch{return{state:"unreachable",items:[],next:null}}}l(je,"remotePage");async function xe(e){const t=new Promise(r=>e.addEventListener("abort",()=>r(null),{once:!0}));return Promise.race([F.current.machines().catch(()=>null),t])}l(xe,"machinesWithin");async function et(e){const t=e.query.get("machine");if(!ce(e.principal)||!F.current.joined()||t===Xe)return be(_e(e));const n=F.current.self(),o=t!==null&&I(t)!==n,i=o?null:be(_e(e)),s=new AbortController,u=setTimeout(()=>s.abort(),Ye.ms);u.unref?.();try{const c=await xe(s.signal);if(c===null){if(o)throw new y(503,"runtime_unreachable",`The directory did not answer, so ${I(t)} cannot be listed.`,{machine:I(t)});return i}const a=l(d=>({id:d,name:c.find(m=>m.machine_id===d)?.name??d}),"labelOf"),f=a(n),p=c.filter(d=>d.machine_id!==n&&d.kind!=="device"),b=V(e);if(t!==null){if(!o)return{items:Y(i.items,f),next_cursor:i.next_cursor,machines:[{machine_id:n,name:f.name,state:"ok",more:i.next_cursor!==null}]};const d=I(t);if(!p.some(E=>E.machine_id===d))throw new y(404,"not_found",`no machine ${d} on your account`,{machine:d});const m=await je(e,a(d),b,s.signal);return{items:m.items,next_cursor:m.next,machines:[{machine_id:d,name:a(d).name,state:m.state,more:m.next!==null}]}}const{cursor:j,...h}=b,w=await Promise.all(p.map(d=>je(e,a(d.machine_id),h,s.signal)));return{items:[...Y(i.items,f),...w.flatMap(d=>d.items)],next_cursor:i.next_cursor,machines:[{machine_id:n,name:f.name,state:"ok",more:i.next_cursor!==null},...p.map((d,m)=>({machine_id:d.machine_id,name:d.name,state:w[m].state,more:w[m].next!==null}))]}}finally{clearTimeout(u)}}l(et,"list");function _e(e){const t=new URLSearchParams(e.query);return t.delete("machine"),{...e,query:t}}l(_e,"withoutMachine");function tt(e){const t=[],r=R(e.body)?e.body:{};R(e.body)||t.push({field:"body",problem:"must be an object",received:e.body});const n=r.text;(typeof n!="string"||n.trim()==="")&&t.push({field:"text",problem:"is required",received:n});const o=r.grep;if(o!==void 0)if(typeof o!="string")t.push({field:"grep",problem:"must be a regular expression string",received:o});else try{new RegExp(o)}catch(u){t.push({field:"grep",problem:`is not a valid regular expression: ${u.message}`,received:o})}r.body!==void 0&&typeof r.body!="boolean"&&t.push({field:"body",problem:"must be a boolean",received:r.body});const i=ye(T(),r.type,t);r.kind!==void 0&&typeof r.kind!="string"&&t.push({field:"kind",problem:"must be a string",received:r.kind}),r.owner!==void 0&&typeof r.owner!="string"&&t.push({field:"owner",problem:"must be a string",received:r.owner});const s=ge(r.limit,"limit",t,50);return t.length>0&&P("object search request",t),_(u=>{const c=v(u,e),a=typeof r.owner=="string"?me(u,c,r.owner):null;if(typeof r.owner=="string"&&a===null)return{items:[]};const f=ie(u,c,{text:n,body:r.body===!0||typeof o=="string"}),p=new Set(f.map(h=>h.object.rowid));return{items:(typeof o=="string"?ie(u,c,{text:o,grep:!0}).filter(h=>p.has(h.object.rowid)):f).filter(h=>(!i||h.object.type===i)&&(r.kind===void 0||h.object.kind===r.kind)&&(!a||h.object.owner===a.rowid)).slice(0,s).map(h=>({object:de(u,h.object),...h.line!==void 0?{matches:[{line:h.line,text:h.text??""}]}:{}}))}})}l(tt,"search");const ke=["interrupt","steer","after-turn","next-turn"],nt=/^(\*|>|[A-Za-z0-9_-]+)(\.(\*|>|[A-Za-z0-9_-]+))*$/;function rt(e,t){if(e!==void 0){if(!Array.isArray(e)||e.length===0||e.some(r=>typeof r!="string"||!nt.test(r)||r.includes(">")&&!r.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(rt,"patternsOf");function ot(e,t){if(e===void 0)return;if(!R(e)||Object.keys(e).length===0){t.push({field:"config",problem:"must map levels 1-10 to a delivery",received:e});return}const r=[];for(const[n,o]of Object.entries(e)){const i=Number(n);!Number.isInteger(i)||i<1||i>10?t.push({field:`config.${n}`,problem:"level must be an integer from 1 to 10"}):ke.includes(o)?r.push({threshold:i,delivery:o}):t.push({field:`config.${n}`,problem:`delivery must be one of ${ke.join(", ")}`,received:o})}return r.sort((n,o)=>o.threshold-n.threshold)}l(ot,"configOf");function ve(e){const t=pe(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(ve,"refuseStubWatch");function X(e,t){const r=L(e,t)??(()=>{const n=Ae(e,Se(e,{class:"person"},()=>[]),t);return"object"in n?n.object:null})();return r===null||r.deleted_at!==null||!(r.type.includes(".")||r.type==="node")?null:r}l(X,"findWatcher");const O=l(()=>{throw new y(404,"not_found","watcher not found")},"watcherNotFound");async function Oe(e,t,r){if(typeof t!="string"||r===void 0||r===null)return null;if(typeof r!="string")throw new y(400,"invalid_request","invalid watcher_machine");if(X(e,t)!==null)return null;const n=F.current;let o;try{o=await n.machines()}catch{throw new y(503,"runtime_unreachable","The directory did not answer, so the watcher machine cannot be checked.")}const i=I(r);return(i===n.self()||!o.some(s=>I(s.machine_id)===i))&&O(),i}l(Oe,"remoteWatcherMachine");function Ee(e,t,r,n){if(t.publishToken||t.principal.class==="anonymous")return O();const o=v(e,t);if(o.class==="person")return O();let i;try{i=q(e,o,n)}catch{return O()}const s=i.owner===null?null:fe(e,i.owner);return s===null||!ne(e,o,s)||!Fe(e,o,"link",r)?O():(M(e,t,r),{actor:o.app,object:i})}l(Ee,"linkWatcher");function qe(e,t,r){if(t.publishToken)return!0;if(t.principal.class==="anonymous"||!r.type.includes("."))return!1;const n=v(e,t),o=r.owner===null?null:fe(e,r.owner);return o!==null&&ne(e,n,o)&&Ne(e,n,r)}l(qe,"ownsWatcher");async function it(e){const t=k(e),r=R(e.body)?e.body:{};if(typeof r.watcher=="string"&&ve(t),typeof r.watcher!="string"){const o=await Z(e,t,{method:"POST",path:`${J(t)}/watch`,body:e.body});if(o.kind==="unknown")throw le(t,o.unreachable);if(o.kind==="remote"){if(o.status>=400)throw C(o.status,o.body);const i=o.body.patterns;return we(e,o.body,o.machine.id,"ask",i),B(o.body,o.machine)}}const n=await Oe(T(),r.watcher,r.watcher_machine);return st(e,n)}l(it,"watch");function st(e,t=null){const r=[],n=e.body===void 0?{}:R(e.body)?e.body:(r.push({field:"body",problem:"must be an object"}),{}),o=rt(n.patterns,r),i=ot(n.config,r);return n.filter!==void 0&&!R(n.filter)&&r.push({field:"filter",problem:"must be an object",received:n.filter}),n.watcher!==void 0&&typeof n.watcher!="string"&&r.push({field:"watcher",problem:"must be a custom-object ref",received:n.watcher}),n.watcher_machine!==void 0&&typeof n.watcher_machine!="string"&&r.push({field:"watcher_machine",problem:"must be a machine id",received:n.watcher_machine}),r.length>0&&P("watch request",r),_(s=>{const u=typeof n.watcher=="string";if((e.publishToken||e.principal.class==="anonymous")&&!u)throw new y(404,"not_found","watcher not found");const c=o??[">"],a={patterns:c,...i?{config:i}:{},...n.filter!==void 0?{filter:n.filter}:{}};if(u){const j=n.watcher,h=t===null?null:ut(s,e,j,t),w=h??(e.publishToken?re(s,j):X(s,j));if(w===null)return O();if(h===null&&qe(s,e,w)){const E=oe(s,e,w);M(s,e,w);const x=D(s,w),N=q(s,x,k(e));if(!te(s,x,N))throw new y(404,"not_found","object not found");return W(s,w,N,"act",a),G(s,{event:"watched",object:N,actor:E,attrs:{}},S(s)),{object:$(s,N,g(s,N)),patterns:c}}const{actor:d,object:m}=Ee(s,e,w,k(e));return W(s,w,m,"act",{...a,linkApp:d}),G(s,{event:"watched",object:m,actor:d,attrs:{}},S(s)),{object:$(s,m,g(s,m)),patterns:c}}const f=v(s,e),p=U(s,e)??ee(f),b=q(s,f,k(e));return W(s,p,b,"ask",a),G(s,{event:"watched",object:b,actor:p,attrs:{}},S(s)),{object:$(s,b,g(s,b)),patterns:c}})}l(st,"watchLocal");function ut(e,t,r,n){return t.publishToken||t.principal.class==="anonymous"?O():Ve(e,r,n)}l(ut,"ensureNodeStubFor");function Te(e,t,r,n){const o=l(()=>$e(e,`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,r.rowid).n,"count"),i=o();return Me(e,t,r,n??void 0),{object:g(e,r),removed:i-o()}}l(Te,"dropWatch");async function at(e){const t=k(e);if(e.query.get("watcher")&&ve(t),!e.query.get("watcher")){const n=await Z(e,t,{method:"DELETE",path:`${J(t)}/watch`,query:V(e)});if(n.kind==="unknown")throw le(t,n.unreachable);if(n.kind==="remote"){const o=n.status===404?n.body.error?.details:void 0,i=o?.deleted===!0?o.id:void 0;if(n.status>=400&&i===void 0)throw C(n.status,n.body);const s=i??n.body.object?.id,u=_(c=>{const a=ue(c,e),f=s===void 0?null:L(c,s);return a===null||f===null||!K(c,f)?null:Te(c,a,f,e.query.get("pattern"))});if(i!==void 0){if(u===null)throw C(n.status,n.body);return{...u,machine:n.machine}}return B(n.body,n.machine)}}const r=await Oe(T(),e.query.get("watcher")??void 0,e.query.get("watcher_machine")??void 0);return ct(e,r)}l(at,"unwatchRoute");function ct(e,t=null){const r=e.query.get("pattern"),n=e.query.get("watcher");return _(o=>{if((e.publishToken||e.principal.class==="anonymous")&&!n)throw new y(404,"not_found","watcher not found");const i=l((c,a)=>Te(o,c,a,r),"drop");if(n){const c=t===null?null:(()=>{const f=L(o,n);return f!==null&&Be(o,f)!==null?f:null})();if(t!==null&&c===null)return O();const a=c??(e.publishToken?re(o,n):X(o,n));return a===null?O():c===null&&qe(o,e,a)?(oe(o,e,a),M(o,e,a),i(a,q(o,D(o,a),k(e)))):i(a,Ee(o,e,a,k(e)).object)}const s=v(o,e),u=U(o,e)??ee(s);return i(u,q(o,s,k(e)))})}l(ct,"unwatchLocal");function lt(e){const t=[],r=Q(e.query.get("type"),"type",["acted-on","links-to","watches"],t),n=Q(e.query.get("direction"),"direction",["out","in"],t);return t.length>0&&P("edges request",t),_(o=>{const i=v(o,e),s=q(o,i,k(e)),u=[];if(r!=="watches")for(const c of Le(o,i,s,{...r?{type:r}:{},direction:n??"both"}))u.push({type:c.type,src:g(o,c.src),dst:g(o,c.dst),...c.written_as?{written_as:c.written_as}:{}});if(r===void 0||r==="watches"){const c=[...n!=="in"?ze(o,i,s):[],...n!=="out"?Ge(o,i,s):[]];for(const a of c)u.push({type:"watches",src:g(o,a.watcher),dst:g(o,a.object)})}return{items:u}})}l(lt,"edges");const A=l(e=>async t=>({status:200,body:await e(t)}),"ok"),Wt=[{method:"POST",pattern:"/v1/objects/search",handler:A(tt)},{method:"GET",pattern:"/v1/objects/:ref/edges",handler:A(lt)},{method:"POST",pattern:"/v1/objects/:ref/watch",handler:A(it)},{method:"DELETE",pattern:"/v1/objects/:ref/watch",handler:A(at)},{method:"GET",pattern:"/v1/objects/:ref",handler:A(Qe)},{method:"GET",pattern:"/v1/objects",handler:A(et)}];export{Ye as listBudget,Wt as objectRoutes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var R=Object.defineProperty;var m=(a,t)=>R(a,"name",{value:t,configurable:!0});import{callerGrant as h}from"../principal.js";import{grantVersion as g}from"../../../core/grants/mirror.js";import{waitGrantChange as
|
|
1
|
+
var R=Object.defineProperty;var m=(a,t)=>R(a,"name",{value:t,configurable:!0});import{callerGrant as h}from"../principal.js";import{grantVersion as g,payerOfGrant as S}from"../../../core/grants/mirror.js";import{waitGrantChange as O}from"../../../core/grants/watch.js";import{RunError as n,idempotencyKeyOf as b,cancelRun as $,deleteRun as N,interruptRun as A,listRuns as j,messageRun as x,renameRun as B,requestedScopes as J,startRun as z,traceRun as C,waitRun as E}from"../../../core/runs/operations.js";import{canReadRun as v,requireRun as l,runCallerApp as G}from"../router.js";import{waitSeconds as y}from"../long-poll-wait.js";import{outputSchemaProblem as K}from"../../../core/runtime/structured-output.js";function f(a){if(!a||typeof a!="object"||Array.isArray(a))throw new n(400,"invalid_request","a JSON object is required");return a}m(f,"object");function q(a,t,i,d,u){if(a===null)return u;if(!/^(0|[1-9]\d*)$/.test(a)||!Number.isSafeInteger(Number(a))||Number(a)<i||Number(a)>d)throw new n(400,"invalid_request",`invalid ${t}`,t);return Number(a)}m(q,"integer");const T=256*1024;async function X(a,t,i,d,u,_){switch(a.name){case"grant.get":{if("class"in t)throw new n(403,"permission_error","an app token is required");const e=y("grant.get",d),s=d.get("since");if(s!==null&&!/^[A-Za-z0-9_-]{1,64}$/.test(s))throw new n(400,"invalid_request","invalid since","since");let o=h(t);return e&&s!==null&&g(o)===s&&(await O(t.grant,e),o=h(t)),{status:200,body:{sub:t.sub,grantee:t.grantee,client_id:t.client_id,grant:t.grant,rev:o.rev,resolved_scopes:o.resolved_scopes,spend_cap:o.spend_cap,exp:t.exp,payer:S(t.grant),dependencies:o.dependencies??{},version:g(o)}}}case"run.start":{if("class"in t)throw new n(403,"permission_error","an app token is required");const e=f(u),s=["mode","parent","fork_from","node_id","env","tools","system_prompt"];for(const r of s)if(e[r]!==void 0)throw new n(403,"owner_only",`${r} is owner-only`,r);const o=["payer","model_policy","kind"];for(const r of o)if(e[r]!==void 0)throw new n(400,"invalid_request",`${r} is not available`,r);for(const r of Object.keys(e))if(!["prompt","scopes","metadata","profile","isolated","cwd","worktree","output_schema","message","model","deadline"].includes(r))throw new n(400,"invalid_request",`unknown field ${r}`,r);if(e.model!==void 0&&(typeof e.model!="string"||!e.model.trim()))throw new n(400,"invalid_request","model must be a non-empty string","model");if(e.deadline!==void 0&&(typeof e.deadline!="string"||!e.deadline.trim()))throw new n(400,"invalid_request","deadline must be a duration string such as 10m","deadline");if(e.profile!==void 0&&(typeof e.profile!="string"||!e.profile))throw new n(400,"invalid_request","profile must be a profile id","profile");if(e.isolated!==void 0&&typeof e.isolated!="boolean")throw new n(400,"invalid_request","isolated must be a boolean","isolated");if(e.cwd!==void 0&&(e.isolated!==!0||typeof e.cwd!="string"||!e.cwd))throw new n(400,"invalid_request","cwd is available only for an isolated run and must be an absolute path inside its root folder","cwd");if(e.worktree!==void 0&&e.isolated!==!0)throw new n(400,"invalid_request","worktree is not available","worktree");if(e.isolated===!0&&e.worktree!==void 0)throw new n(400,"invalid_request","worktree is unavailable for an isolated run","worktree");if(typeof e.prompt!="string"||!e.prompt.trim())throw new n(400,"invalid_request","prompt is required","prompt");if(e.message!==void 0&&(typeof e.message!="string"||!e.message.trim()))throw new n(400,"invalid_request","message must be a non-empty string","message");const w=e.metadata===void 0?{}:f(e.metadata);if(Buffer.byteLength(JSON.stringify(w))>4096)throw new n(400,"invalid_request","metadata exceeds 4 KB","metadata");let c;if(e.output_schema!==void 0){const r=e.output_schema;if(!r||typeof r!="object"||Array.isArray(r))throw new n(400,"invalid_request","output_schema must be a JSON Schema object","output_schema");if(Buffer.byteLength(JSON.stringify(r))>T)throw new n(400,"invalid_request","output_schema exceeds 256 KB","output_schema");const p=await K(r);if(p!==null)throw new n(400,"invalid_request",`output_schema is not usable: ${p}`,"output_schema");c=r}const k=J(t.resolved,e.scopes,t.grantee);return{status:201,body:await z(t,{prompt:e.prompt,scopes:k,metadata:w,profile:e.profile,isolated:e.isolated,cwd:e.cwd,...e.model===void 0?{}:{model:e.model},...e.deadline===void 0?{}:{deadline:e.deadline},...c===void 0?{}:{output_schema:c},...e.message===void 0?{}:{message:e.message}},b(_))}}case"run.list":{const e=d.get("status")??void 0;if(e&&!["running","waiting_on_user","idle","settled"].includes(e))throw new n(400,"invalid_request","invalid status","status");const s=d.get("app");if(s!==null&&!/^(?:app:)?[a-z0-9][a-z0-9-]*$/.test(s))throw new n(400,"invalid_request","invalid app","app");const o=s===null?G(t):s.startsWith("app:")?s:`app:${s}`;if(o!==null&&!v(t,o))throw new n(404,"not_found","run not found");return{status:200,body:j(o,{status:e,after:d.get("after")??void 0,limit:q(d.get("limit"),"limit",1,100,50),..."class"in t&&(t.class==="broker"||t.class==="cron")&&o!==null?{visible:m(w=>v(t,o,w),"visible")}:{}})}}case"run.get":{const e=y("run.get",d),s=l(t,i),o=await E(i,s.grantee,e);return l(t,i),{status:200,body:o}}case"run.message":{const e=f(u);if(typeof e.message!="string"||!e.message.trim())throw new n(400,"invalid_request","message is required","message");if(e.start_turn!==void 0&&typeof e.start_turn!="boolean")throw new n(400,"invalid_request","start_turn must be a boolean","start_turn");return{status:202,body:await x(l(t,i,!0),e.message,void 0,e.start_turn,b(_))}}case"run.interrupt":{const e=f(u===void 0?{}:u);if(e.children!==void 0&&e.children!=="stop"&&e.children!=="continue")throw new n(400,"invalid_request","invalid children","children");return{status:200,body:await A(l(t,i,!0),e.children)}}case"run.cancel":{const e=f(u===void 0?{}:u);if(e.keep_schedules!==void 0&&typeof e.keep_schedules!="boolean")throw new n(400,"invalid_request","invalid keep_schedules","keep_schedules");return{status:200,body:await $(l(t,i,!0),{keepSchedules:e.keep_schedules})}}case"run.rename":{const e=f(u);for(const s of Object.keys(e))if(s!=="name")throw new n(400,"invalid_request",`unknown field ${s}`,s);return{status:200,body:B(l(t,i,!0),e.name)}}case"run.delete":{const{uploads_pending:e}=await N(l(t,i,!0,!0));return{status:200,body:{run_id:i,uploads_pending:e}}}case"trace.get":{const e=d.get("format")??void 0;if(e&&e!=="entries")throw new n(400,"invalid_request","unknown trace format","format");const s=l(t,i);return{status:200,body:C(i,s.grantee,e)}}default:throw new n(404,"not_found","unknown operation")}}m(X,"handleRunOperation");export{X as handleRunOperation,q as integer};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var p=Object.defineProperty;var o=(e
|
|
1
|
+
var p=Object.defineProperty;var o=(r,e)=>p(r,"name",{value:e,configurable:!0});import{envHomeOverride as m}from"../../shared/env.js";import{loadProfileManifest as h,lookupProfile as v}from"../../core/profiles/manifest.js";import{readProfileEnvVars as g}from"../../core/profiles/env-store.js";import{readAppEnvVars as R}from"../../core/profiles/app-env-store.js";import{ADMITTED_HOST_PATH_ENV as f,buildOperationalEnvBase as w}from"../../core/runtime/spawn-env.js";import{getNode as c}from"../../core/canvas/canvas.js";import{contextDir as y}from"../../core/canvas/paths.js";import{appendRunEvent as O}from"../../core/runs/events.js";import{payerOfGrant as b}from"../../core/grants/mirror.js";import{scopeAllowed as E}from"../../core/scopes.js";import{cronPrincipalOf as C}from"./authority.js";function _(r){if(r.profile==null)return null;let e;try{e=v(r.profile)}catch{return null}if(e.kind==="resolved")return e.entry.profileId;if(e.kind==="absent")return null;throw new l(`the armed profile "${r.profile}" is still on this host but its manifest could not be read (${e.manifestPath}) \u2014 running as root would silently give this cron a different identity, env store, and purview. Repair the manifest, or re-arm the cron under a profile that resolves.`)}o(_,"resolveLiveProfile");function M(r){return{...C(r),cron_id:r.cron_id,origin_run_id:r.origin_run_id,isolated:r.isolated,creator:r.created_by}}o(M,"cronBirthPrincipalOf");function $(r,e){const n=r.creator===null?null:c(r.creator);return n!==null&&r.origin_run_id!==null&&n.run_id===r.origin_run_id&&c(r.origin_run_id)?.deleting_at==null&&n.grantee===r.grantee&&(n.sub??"user:local")===r.sub&&(n.grant_id??null)===r.grant_id&&(r.scopes===null?n.scopes==null:r.scopes.every(t=>E(n.scopes,t)))?{parent:n.node_id,...r.scopes===null?{}:{scopes:[...r.scopes]}}:{root:!0,rootLifecycle:"terminal",...r.scopes===null?{}:{scopes:[...r.scopes]},run:{grantee:r.grantee,sub:r.sub,grant_id:r.grant_id,client_id:null,metadata_json:JSON.stringify({cron_id:r.cron_id}),run_id:e,event_cursor:1,usage_json:JSON.stringify({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0})},withinCreate:o((t,s)=>{O(t,e,e,"run.started",{scopes:s.scopes??null,payer:b(r.grant_id),usage:JSON.parse(s.usage_json)})},"withinCreate")}}o($,"cronBirthPlacement");function B(r){try{return _(r)}catch{return null}}o(B,"resolveLiveProfileOrRoot");function V(r){if(r.profile!=null)try{return h(r.profile).manifest.name}catch{return}}o(V,"resolveLiveProfileName");class l extends Error{static{o(this,"ArmedContextError")}constructor(e){super(e),this.name="ArmedContextError"}}function N(r){if(r==null)return{};let e;try{e=JSON.parse(r)}catch(i){throw new l(`the armed env snapshot is not valid JSON (${i.message}) \u2014 this cron's stored env_json is corrupt, so the run would silently drop every armed variable. Re-arm the cron with a valid --env.`)}if(typeof e!="object"||e===null||Array.isArray(e))throw new l("the armed env snapshot is not a JSON object \u2014 this cron's stored env_json is corrupt. Re-arm the cron with a valid --env.");const n={};for(const[i,t]of Object.entries(e)){if(typeof t!="string")throw new l(`the armed env snapshot's value for "${i}" is not a string \u2014 this cron's stored env_json is corrupt, so the run would silently drop that variable. Re-arm the cron with a valid --env.`);n[i]=t}return n}o(N,"parseArmedEnv");function F(r,e){const n=N(r.env_json),i=r.grantee==="app:terminal",t=i?_(r):null,s=w({targetCwd:r.cwd,targetProfileId:t,skipSpawnAllow:!i}),a={...s,...R(r.grantee),...i?g(t):{},...n,...t!==null?{CRTR_PROFILE_ID:t}:{},CRTR_CRON_ID:r.cron_id,CRTR_CRON_NAME:r.name,CRTR_RUN_ID:e},u=m();if(u!==void 0&&u!==""&&(a.CRTR_HOME=u),r.anchor_node!=null){a.CRTR_ANCHOR=r.anchor_node;const d=c(r.anchor_node);d!==null&&(a.CRTR_CONTEXT_DIR=y(d.node_id,d.grantee))}return a[f]=s[f],{profileId:t,env:a}}o(F,"buildArmedRunContext");export{l as ArmedContextError,F as buildArmedRunContext,$ as cronBirthPlacement,M as cronBirthPrincipalOf,_ as resolveLiveProfile,V as resolveLiveProfileName,B as resolveLiveProfileOrRoot};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var C=Object.defineProperty;var l=(n,f)=>C(n,"name",{value:f,configurable:!0});import{openDb as I,withCanvasWrite as j}from"../../core/canvas/db.js";import{emitEvent as B}from"../../core/events/emit.js";import{isUnreachable as O,peerCall as D}from"../../core/peer/client.js";import{listMachines as U,machineReach as F,normalizeMachineId as g,ownMachineId as N}from"../../core/peer/directory.js";import{relayConnected as W}from"../../core/peer/events.js";import{ingestPeerEvents as q,isCatalogLag as S}from"../../core/peer/ingest.js";import{CATALOG_LAG_RETRY_MS as G,dueRows as X,expireOld as Y,markDone as z,markExpired as E,markRetry as A,markWaiting as L,onPeerEnqueued as H,pendingFor as J,pruneOutbox as K,OUTBOX_MAX_AGE_MS as V}from"../../core/peer/outbox-store.js";const T={first:1e3,max:10*6e4},P=5*6e4,$=5*6e4,R=50,Q=20,Z={db:I,call:l((n,f)=>D(n,f),"call"),reach:F,machines:U,self:N,now:Date.now},M=l(n=>Math.min(T.first*2**Math.max(0,n-1),T.max),"stableBackoffMs");function ee(n){const f=new Set;async function p(c,o,i){const t=n.db(),a=n.now(),s=await n.call(c,{method:"POST",path:"/v1/peer/events",body:{events:o.map(e=>JSON.parse(e.payload_json))}}),d=l((e,x=o)=>{for(const m of x){const u=m.attempts+1,w=m.first_failed_at??a;i&&e?L(t,m.id,u):i?a-w>=P?L(t,m.id,u):A(t,m.id,u,a+Math.min(M(u),P-(a-w)),w):a-w>=V?E(t,m.id):A(t,m.id,u,a+M(u),w)}},"fail");if(O(s)){d(s.unreachable.reason==="machine_offline");return}const r=s.body;if(s.status!==200||r===null||!Array.isArray(r.accepted)){d(!1);return}const _=new Set(r.accepted),k=new Map((Array.isArray(r.rejected)?r.rejected:[]).map(e=>[e.key,e.code??""])),y=[];for(const e of o)_.has(e.idempotency_key)?z(t,e.id):k.has(e.idempotency_key)?S(k.get(e.idempotency_key))&&a-e.created_at<G?y.push(e):E(t,e.id):A(t,e.id,e.attempts+1,a+M(e.attempts+1),e.first_failed_at??a);d(!1,y)}l(p,"sendBatch");async function b(c){const o=c.filter(i=>!f.has(i.id));for(const i of o)f.add(i.id);try{const i=new Map;for(const t of o)i.set(t.peer,[...i.get(t.peer)??[],t]);await Promise.all([...i].map(async([t,a])=>{const d=(await n.reach(t).catch(()=>null))?.reach.kind==="relay";for(let r=0;r<a.length;r+=R)await p(t,a.slice(r,r+R),d)}))}finally{for(const i of o)f.delete(i.id)}}l(b,"pushRows");let h=0;return{async run(){const c=n.db(),o=n.now();o-h>=60*6e4&&(h=o,Y(c,o),K(c,o)),await b(X(c,o))},flush:l(c=>b(J(n.db(),c,n.now())),"flush"),async pull(){const c=n.self(),o=(await n.machines()).filter(t=>g(t.machine_id)!==c&&t.kind!=="device"&&t.reach.kind==="stable");let i=0;for(const t of o){const a=g(t.machine_id);for(let s=0;s<Q;s++){const d=await n.call(a,{method:"POST",path:"/v1/peer/outbox/claim",body:{limit:100}}),r=!O(d)&&d.status===200?d.body?.rows:void 0;if(!Array.isArray(r)||r.length===0)break;const _=j(e=>q(e,a,r.map(x=>x.payload)));i+=_.accepted.length;const k=new Set([..._.accepted,..._.rejected.filter(e=>!S(e.code)).map(e=>e.key)]),y=r.filter(e=>k.has(e.key)).map(e=>({key:e.key,claim_token:e.claim_token}));if(y.length>0&&await n.call(a,{method:"POST",path:"/v1/peer/outbox/ack",body:{acks:y}}),r.length<100)break}}return i}}}l(ee,"createOutboxLane");function le(n){if(!n.joined)return()=>{};const f=n.deps??Z,p=ee(f),b=l(a=>s=>{B({level:"warn",event:`daemon.peer.${a}_failed`,error:s})},"quiet"),h=l((a,s)=>n.register(a().then(()=>{},b(s))),"guarded"),v=H(a=>h(()=>p.flush(a),"outbox_flush")),c=setInterval(()=>h(()=>p.run(),"outbox_run"),n.tickMs??5e3);c.unref();const o=l(()=>h(async()=>{(await f.machines()).find(s=>g(s.machine_id)===f.self())?.reach.kind==="relay"&&await p.pull()},"outbox_pull"),"pull"),i=W.on(o),t=setInterval(o,$);return t.unref(),o(),()=>{v(),i(),clearInterval(c),clearInterval(t)}}l(le,"startPeerOutbox");export{$ as PULL_INTERVAL_MS,P as RELAY_RETRY_WINDOW_MS,T as STABLE_BACKOFF_MS,ee as createOutboxLane,Z as liveOutboxDeps,M as stableBackoffMs,le as startPeerOutbox};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var T=Object.defineProperty;var u=(t,e)=>T(t,"name",{value:e,configurable:!0});import{prepared as d}from"../../core/sqlite-statements.js";import{appendRunEvent as p}from"../../core/runs/events.js";import{openQuestionIds as h}from"../../core/runs/questions.js";import{getNode as x}from"../../core/canvas/canvas.js";import{
|
|
2
|
-
`):""}u(
|
|
1
|
+
var T=Object.defineProperty;var u=(t,e)=>T(t,"name",{value:e,configurable:!0});import{prepared as d}from"../../core/sqlite-statements.js";import{appendRunEvent as p}from"../../core/runs/events.js";import{openQuestionIds as h}from"../../core/runs/questions.js";import{getNode as x}from"../../core/canvas/canvas.js";import{payerOfGrant as N}from"../../core/grants/mirror.js";import{runSchemaRepromptPending as S}from"../../core/runtime/stop-guard.js";const k="crtr-turn-input",w="crtr-system-prompt",D="crtr-turn-end",E=u(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"zero");function O(t){return typeof t=="string"?t:Array.isArray(t)?t.filter(e=>typeof e?.text=="string").map(e=>e.text).join(`
|
|
2
|
+
`):""}u(O,"text");function j(t){if(t==null)return;const{code:e,message:r}=t;if(e!=="content_refused"&&e!=="model_error"||typeof r!="string")throw new Error("invalid crtr-turn-end error");return{code:e,message:r}}u(j,"turnEndError");function A(t){return{input_tokens:t.input??0,output_tokens:t.output??0,cache_read_tokens:t.cacheRead??0,cache_write_tokens:t.cacheWrite??0,cost_usd:t.cost?.total??0}}u(A,"usageParts");function Y(t,e,r,g,R){let l=R;for(const n of g){if(n.type==="custom"&&n.customType===k){const o=n.data?.message_ids;if(!Array.isArray(o)||!o.every(i=>typeof i=="string"))throw new Error("invalid crtr-turn-input message_ids");l=[...new Set([...l,...o])]}if(n.type==="custom"&&n.customType===w){const o=n.data?.text;if(typeof o!="string")throw new Error("invalid crtr-system-prompt text");p(t,e,r,"node.system_prompt.set",{entry_id:n.id,text:o})}if(n.type==="custom"&&n.customType===D){const o=n.data,i=o?.stop_reason;if(typeof i!="string")throw new Error("invalid crtr-turn-end stop_reason");const a=j(o?.error),s=d(t,"SELECT body_json FROM run_events WHERE run_id = ? AND node_id = ? AND type = 'node.turn.started' ORDER BY sequence_number DESC LIMIT 1").get(e,r);if(!s)throw new Error("crtr-turn-end without node.turn.started");const{input:_}=JSON.parse(s.body_json),f=d(t,"SELECT status, pi_pid FROM node_rows WHERE run_id = ? AND node_id != ?").all(e,r),c=r===e?x(e):null,m=f.some(y=>y.pi_pid!==null&&y.status==="active")||c!==null&&S(c)?"running":h(e,t).length?"waiting_on_user":"idle";p(t,e,r,"node.turn.completed",{entry_id:n.id,message_ids:_.message_ids,run_status:m,stop_reason:i,...a?{error:a}:{}}),r===e&&d(t,"UPDATE nodes SET last_turn_error_json = ? WHERE node_id = ?").run(a?JSON.stringify(a):null,e)}if(n.type==="message"){const o=n.message;if(o.role==="user"){const i=d(t,"SELECT type, body_json FROM run_events WHERE run_id = ? AND node_id = ? AND type IN ('node.turn.started', 'node.turn.completed') ORDER BY sequence_number DESC LIMIT 1").get(e,r),a=i?.type==="node.turn.started"?JSON.parse(i.body_json).input.message_ids:[];p(t,e,r,"node.turn.started",{entry_id:n.id,input:{text:O(o.content),message_ids:[...new Set([...a,...l])]}}),l=[]}if(o.role==="assistant"){let i=!1;const a=u(()=>{if(i)return;i=!0;const s=o.content.filter(_=>_.type==="text").map(_=>_.text).join("");p(t,e,r,"node.output_text.done",{entry_id:n.id,text:s,stop_reason:o.stopReason})},"doneText");for(const s of o.content)s.type==="thinking"&&p(t,e,r,"node.thinking.done",{entry_id:n.id,text:s.thinking}),s.type==="text"&&a(),s.type==="toolCall"&&(a(),p(t,e,r,"node.tool_call.started",{entry_id:n.id,tool_call_id:s.id,name:s.name,arguments:s.arguments}));if(a(),o.usage){const s=A(o.usage),_=d(t,"SELECT usage_json, grant_id FROM nodes WHERE node_id = ?").get(e),f=_.usage_json?JSON.parse(_.usage_json):E(),c=E();for(const m of Object.keys(c))c[m]=f[m]+s[m];d(t,"UPDATE nodes SET usage_json = ? WHERE node_id = ?").run(JSON.stringify(c),e),p(t,e,r,"usage",{entry_id:n.id,served_model:o.model,payer:N(_.grant_id),...s,usage:c})}d(t,"DELETE FROM run_events WHERE run_id = ? AND node_id = ? AND type IN ('node.thinking.delta', 'node.output_text.delta')").run(e,r)}o.role==="toolResult"&&p(t,e,r,"node.tool_call.completed",{entry_id:n.id,tool_call_id:o.toolCallId,name:o.toolName,result:o.content,status:o.isError?"error":"ok"})}}return l}u(Y,"appendConversationEvents");export{w as SYSTEM_PROMPT_TYPE,D as TURN_END_TYPE,k as TURN_INPUT_TYPE,Y as appendConversationEvents};
|
|
@@ -7,6 +7,16 @@ description: Behavior changes in @north-light/sdk that an app must act on, newes
|
|
|
7
7
|
|
|
8
8
|
Changes to `@north-light/sdk` that can change what an existing app sees. Newest first.
|
|
9
9
|
|
|
10
|
+
## 0.3.502
|
|
11
|
+
|
|
12
|
+
An app can be app-paid: the directory registers the app's inference endpoint, and the runtime serves the app's `llm` calls and its runs' model calls from that endpoint instead of the person's subscription. Additive: an app registered as user-paid sees no change.
|
|
13
|
+
|
|
14
|
+
### `payer: "app"` on `grant.get`, `run.start`, `run.get` and `run.started` (additive)
|
|
15
|
+
|
|
16
|
+
- `payer` is now `"user" | "app"` (it was always `"user"`). It reports the payer of the caller's grant, and every grant stays `"user"` until the directory sends `app` for it.
|
|
17
|
+
- Under an app-paid grant, `llm` with `payer: "user"` is refused `invalid_request` naming `payer`; with `payer: "app"` on a user-paid grant, `payer_not_app` (as before).
|
|
18
|
+
- An app-paid grant's usage rows are `payer: "app"` at list price and never count toward the grant's `spend_cap`.
|
|
19
|
+
|
|
10
20
|
## 0.3.500
|
|
11
21
|
|
|
12
22
|
An app-paid app can serve its model calls from its own service. Additive: no request or response an existing app sends or reads changes.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.503",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -138,7 +138,7 @@
|
|
|
138
138
|
},
|
|
139
139
|
"license": "UNLICENSED",
|
|
140
140
|
"dependencies": {
|
|
141
|
-
"@north-light/identity": "0.3.
|
|
141
|
+
"@north-light/identity": "0.3.503",
|
|
142
142
|
"@earendil-works/pi-agent-core": "1.1.0",
|
|
143
143
|
"@earendil-works/pi-ai": "1.1.0",
|
|
144
144
|
"@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.503",
|
|
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.503",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "UNLICENSED",
|
|
12
12
|
"workspaces": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@earendil-works/pi-ai": "1.1.0",
|
|
19
19
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
20
20
|
"@earendil-works/pi-tui": "1.1.0",
|
|
21
|
-
"@north-light/identity": "0.3.
|
|
21
|
+
"@north-light/identity": "0.3.503",
|
|
22
22
|
"cron-parser": "^5.6.0",
|
|
23
23
|
"esbuild": "^0.27.7",
|
|
24
24
|
"jose": "^6.2.12",
|
|
@@ -12116,17 +12116,17 @@
|
|
|
12116
12116
|
},
|
|
12117
12117
|
"packages/crouter-api": {
|
|
12118
12118
|
"name": "@north-light/api",
|
|
12119
|
-
"version": "0.3.
|
|
12119
|
+
"version": "0.3.503",
|
|
12120
12120
|
"license": "UNLICENSED"
|
|
12121
12121
|
},
|
|
12122
12122
|
"packages/crouter-env-docker": {
|
|
12123
12123
|
"name": "@north-light/env-docker",
|
|
12124
|
-
"version": "0.3.
|
|
12124
|
+
"version": "0.3.503",
|
|
12125
12125
|
"license": "UNLICENSED"
|
|
12126
12126
|
},
|
|
12127
12127
|
"packages/crouter-identity": {
|
|
12128
12128
|
"name": "@north-light/identity",
|
|
12129
|
-
"version": "0.3.
|
|
12129
|
+
"version": "0.3.503",
|
|
12130
12130
|
"license": "UNLICENSED",
|
|
12131
12131
|
"dependencies": {
|
|
12132
12132
|
"jose": "^6.2.1"
|
|
@@ -12134,20 +12134,20 @@
|
|
|
12134
12134
|
},
|
|
12135
12135
|
"packages/crouter-plugin": {
|
|
12136
12136
|
"name": "@north-light/plugin",
|
|
12137
|
-
"version": "0.3.
|
|
12137
|
+
"version": "0.3.503",
|
|
12138
12138
|
"license": "UNLICENSED",
|
|
12139
12139
|
"dependencies": {
|
|
12140
|
-
"@north-light/api": "0.3.
|
|
12141
|
-
"@north-light/identity": "0.3.
|
|
12140
|
+
"@north-light/api": "0.3.503",
|
|
12141
|
+
"@north-light/identity": "0.3.503"
|
|
12142
12142
|
}
|
|
12143
12143
|
},
|
|
12144
12144
|
"packages/crouter-sdk": {
|
|
12145
12145
|
"name": "@north-light/sdk",
|
|
12146
|
-
"version": "0.3.
|
|
12146
|
+
"version": "0.3.503",
|
|
12147
12147
|
"license": "UNLICENSED",
|
|
12148
12148
|
"dependencies": {
|
|
12149
|
-
"@north-light/api": "0.3.
|
|
12150
|
-
"@north-light/identity": "0.3.
|
|
12149
|
+
"@north-light/api": "0.3.503",
|
|
12150
|
+
"@north-light/identity": "0.3.503",
|
|
12151
12151
|
"jose": "^6.2.1"
|
|
12152
12152
|
},
|
|
12153
12153
|
"bin": {
|