@north-light/cli 0.3.575 → 0.3.577
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/builtin-memory/crouter-sdk/release-notes.md +8 -0
- package/dist/clients/attach/viewer.js +212 -212
- package/dist/core/canvas/executions.d.ts +4 -4
- package/dist/core/canvas/executions.js +1 -1
- package/dist/core/command-plugins/bundle.d.ts +6 -3
- package/dist/core/command-plugins/bundle.js +1 -1
- package/dist/core/io.js +4 -4
- package/dist/core/llm/run.js +2 -2
- package/dist/core/model-routes.d.ts +11 -0
- package/dist/core/model-routes.js +1 -1
- package/dist/core/peer/envelope.d.ts +2 -0
- package/dist/core/peer/envelope.js +1 -1
- package/dist/core/provider-error-recognition.d.ts +3 -0
- package/dist/core/provider-error-recognition.js +1 -1
- package/dist/core/providers/bundles.js +2 -2
- package/dist/core/providers/call.js +1 -1
- package/dist/core/providers/roots.d.ts +4 -0
- package/dist/core/providers/roots.js +1 -1
- package/dist/core/runtime/broker/daemon-ops.d.ts +4 -0
- package/dist/core/runtime/broker/daemon-ops.js +1 -1
- package/dist/core/runtime/broker-request.js +1 -1
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/revive.d.ts +6 -0
- package/dist/core/runtime/revive.js +2 -2
- package/dist/core/runtime/run-command.js +1 -1
- package/dist/core/runtime/runner/blaxel/client.d.ts +2 -0
- package/dist/core/runtime/runner/blaxel/client.js +1 -1
- package/dist/core/runtime/runner/blaxel/runner.js +2 -2
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/view-socket.d.ts +1 -1
- package/dist/core/subscription-state.d.ts +4 -0
- package/dist/core/subscription-state.js +1 -1
- package/dist/daemon/api/handlers/messages.js +2 -2
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/providers.js +1 -1
- package/dist/daemon/crtrd.js +11 -11
- package/dist/daemon/peer/forward.js +1 -1
- package/dist/daemon/reconcilers/broker-supervision.js +4 -4
- package/dist/daemon/reconcilers/live-obligation.d.ts +11 -0
- package/dist/daemon/reconcilers/live-obligation.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +2 -2
- package/dist/pi-extensions/canvas-stophook.js +1 -1
- package/docs/sdk/release-notes.md +8 -0
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -13
- package/scripts/sandbox-start.mjs +8 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
1
|
+
var g=Object.defineProperty;var o=(t,a)=>g(t,"name",{value:a,configurable:!0});import{withCanvasWrite as R,openDb as I}from"../../../canvas/db.js";import{mintNodeToken as k}from"../../../canvas/node-tokens.js";import{BlaxelApiError as T,isWorkloadUnavailable as b}from"./client.js";const x=4180,l="view",S="node /opt/crtr/current/scripts/sandbox-start.mjs --wake",C=3,N=/^crtr-sandbox-start: failed (\S+)/m,m=o(t=>`broker-${t}`,"brokerProcessName"),f=o(t=>t.sandboxName??`${t.nodeId}-${t.attempt}`,"sandboxNameFor"),y=o(async t=>await R(a=>k(a,t.executionId,t.nodeId,new Date().toISOString())),"defaultMint");async function P(t){return(await(await I()).prepare("SELECT DISTINCT sandbox_name FROM executions WHERE node_id = ? AND sandbox_name IS NOT NULL").all(t)).map(u=>u.sandbox_name)}o(P,"defaultSandboxNames");function $(t){const a=`${t.logs}
|
|
2
2
|
${t.stderr}
|
|
3
|
-
${t.stdout}`;return{state:"failed",reason:
|
|
3
|
+
${t.stdout}`;return{state:"failed",reason:N.exec(a)?.[1]??"start_failed",code:t.exitCode}}o($,"failureOf");function v(t){const{client:a}=t,u=(t.stopGraceS??10)*1e3,E=new Map;async function d(n){return await a.getSandbox(f(n))}return o(d,"sandboxOf"),{kind:"blaxel",async start(n){const r=await t.launchContext(n),e=f(n),s=await a.createSandbox({name:e,image:r.image,memoryMb:r.memoryMb,ports:[{name:l,target:x}]}),i=m(n.executionId);if((await a.getProcess(s,i))?.status==="running")return{pid:null,exited:null};await a.ensurePreview(e,l,x);const w=await(t.mintToken??y)(n),p={...r.secrets,CRTR_API_URL:r.apiUrl,CRTR_EXECUTION_ID:n.executionId,CRTR_NODE_TOKEN:w,CRTR_RELEASE:n.release,CRTR_RELEASE_URL:r.releaseUrl,CRTR_RELEASE_SHA256:r.releaseSha256};return await a.startProcess(s,{name:i,command:t.bootstrap(),env:p,waitForCompletion:!1}),{pid:null,exited:null}},async wake(n){const r=await d(n);if(r===null)return"no_broker";try{const e=await a.exec(r,`wake-${n.executionId}-${Date.now()}`,`${S} ${n.executionId}`,30);if(e.exitCode===0)return"signalled";if(e.exitCode===C)return"no_broker";throw new Error(`wake of ${n.executionId} failed (exit ${e.exitCode}): ${(e.stderr||e.logs).slice(0,300)}`)}catch(e){if(b(e))return"no_broker";throw e}},async stop(n,r){try{const e=await d(n);if(e===null)return{confirmed:!0};const s=m(n.executionId),i=o(async()=>(await a.getProcess(e,s))?.status==="running","running");if(!await i())return{confirmed:!0};await a.stopProcess(e,s);const c=Date.now()+u;for(;Date.now()<c;){if(!await i())return{confirmed:!0};await new Promise(w=>setTimeout(w,250))}return await a.killProcess(e,s),{confirmed:!await i()}}catch(e){return{confirmed:!1,error:e instanceof Error?e:new Error(String(e))}}},async status(n){try{const r=await d(n);if(r===null)return{state:"gone"};const e=await a.getProcess(r,m(n.executionId));return e===null?{state:"gone"}:e.status==="running"?{state:"running",pid:null}:e.status==="failed"||e.status==="completed"&&e.exitCode!==0?$(e):{state:"gone"}}catch(r){return b(r)?{state:"gone"}:{state:"unknown",error:r instanceof Error?r.message:String(r)}}},async delete(n){for(const r of await(t.sandboxNamesForNode??P)(n))await a.deleteSandbox(r)},async viewerAddress(n){const r=f(n),e=E.get(r);if(e&&e.expiresAt-Date.now()>5*6e4)return _(e.url,e.token);const s=await a.ensurePreview(r,l,x),i=new Date(Date.now()+60*6e4),{token:c}=await a.createPreviewToken(r,l,i);return E.set(r,{url:s,token:c,expiresAt:i.getTime()}),_(s,c)},async sandboxState(n){return(await d(n))?.state??null}}}o(v,"createBlaxelRunner");function _(t,a){return{kind:"wss",url:`${t.replace(/^https:/,"wss:")}/view`,headers:{"x-blaxel-preview-token":a}}}o(_,"viewer");export{x as BROKER_VIEW_PORT,T as BlaxelApiError,C as EXIT_NO_BROKER,N as FAILURE_LINE,S as WAKE_COMMAND,m as brokerProcessName,v as createBlaxelRunner,f as sandboxNameFor};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var me=Object.defineProperty;var d=(e,o)=>me(e,"name",{value:o,configurable:!0});import{accessSync as he,constants as pe}from"node:fs";import{isAbsolute as _e,resolve as ke,join as ve}from"node:path";import{appSpace as ge}from"../layout.js";import{ApiError as ne}from"../../api/errors.js";import{spawnNode as ye,forkSourceNode as be,currentNodeContext as xe,rootOfSpine as $e,newNodeId as Se,preflightNodeId as Ce}from"./nodes.js";import{resolveProfileOperand as Ee}from"../profiles/manifest.js";import{selectProfileForCwd as Re,selectProfileForCwdReadOnly as Oe}from"../profiles/select.js";import{buildLaunchSpecAsync as oe,buildPiArgv as Fe}from"./launch.js";import{runsOnBlaxel as Ie,sandboxWorktreeRequest as Be}from"../../daemon/api/environment-of.js";import{createManagedWorktreeAsync as De,rollbackManagedWorktreeAsync as Ne}from"../worktree-mutation-async.js";import{usage as w,brokerLaunchFailed as D}from"../errors.js";import{writeGoal as Pe}from"./kickoff.js";import{appendSituationalContext as Le,formatSituationalProse as Me}from"./situational-context.js";import{ensureRoadmap as Te}from"./roadmap.js";import{buildWakeBearings as Ae}from"./bearings.js";import{encodeKickoffOrigin as We,KICKOFF_ORIGIN_ENV as je}from"./stamp/protocol.js";import{ExecutionCapReached as ze,beginExecution as He,crtrHome as Ke,getNode as u,fullName as re,jobDir as Ge,recordExecutionPid as Ue,abortExecution as j,setFrozen as z}from"../canvas/index.js";import{contextDir as H,nodeAgentDir as K}from"../canvas/node-agent-paths.js";import{copyTreeBeneath as Ve}from"../spaces/open-beneath.js";import{conversationIdFromPath as N,conversationStore as S}from"../conversation-store/index.js";import{appMemoryTooSmall as Xe,boundFleet as qe,brokerThresholdsForDaemon as te}from"./fleet.js";import{admitBrokerMemory as Ye}from"./memory-admission.js";import{emitEvent as P}from"../events/emit.js";import{blaxelEnvironmentOf as Je}from"./blaxel-environment.js";import{openViewerWindow as Qe,focusOf as Ze,windowOfPane as en}from"./placement.js";import{awaitBrokerViewSocket as nn}from"./view-socket.js";import{readLogSnapshot as on}from"../events/read.js";import{transition as k}from"./lifecycle.js";import{beginBootFaultAttempt as rn}from"../canvas/recovery.js";import{headlessBrokerHost as G}from"./host.js";import{ensureDaemon as tn}from"../../daemon/manage.js";import{readConfig as an}from"../config.js";import{modelRequestFromConfig as dn,unregisteredConcreteModel as sn}from"../model-routes.js";import{openModelRegistry as ln}from"./model-registry.js";import{MODEL_SPEC_NEXT as cn}from"./model-selection.js";import{forkNodeLedger as un}from"./ledger.js";import{appRungForGrant as fn}from"../llm/app-rungs.js";import{APP_FAMILY as U}from"../model-routes.js";import{discoverLifecycleHookRegistry as wn}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as mn}from"../command-hooks/transport/exec-lifecycle.js";import{someAsync as hn}from"../async-array.js";import{checkStart as pn}from"./start-check.js";function v(e){return{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}d(v,"launchFailureOutcome");async function _n(e,o,a){try{return await G.launch(e,o,a)}catch(r){try{await k(e,"crash",{reason:"launch_failed",outcome:v(r)})}catch{}const i=r.message;throw D(i.startsWith("[broker]")?i:`[broker] refusing to launch ${e}: ${i}`,"Inspect the cause above, fix the launch recipe or environment, then retry.")}}d(_n,"launchBrokerOrCrash");function kn(e){return on({nodeId:e,component:"broker",pattern:"broker.startup."},!1).items.flatMap(a=>a.kind==="event"&&a.envelope.event.startsWith("broker.startup.")&&a.envelope.event!=="broker.startup.warning"?[a.envelope.event.slice(15)]:[]).at(-1)??null}d(kn,"lastStartupStep");function vn(e,o){const a=kn(e),r=a===null?"it had logged no startup step":`the last startup step it logged was \`${a}\``;if(o.reason==="exited"){const{code:i,signal:s}=o.status;return{text:`exited (code ${i??"null"}, signal ${s??"null"}) before binding its view socket; ${r}`,fields:{reason:"exited",code:i,signal:s,last_startup_step:a}}}return{text:`was still starting after ${Math.round(o.waitedMs/1e3)} s without binding its view socket, so the launcher stopped it; ${r}`,fields:{reason:"timeout",waited_ms:o.waitedMs,last_startup_step:a}}}d(vn,"notReadyDescription");async function gn(e,o){try{await k(e,"crash",{reason:"launch_failed",outcome:v(o)})}catch{}try{G.teardown(e)}catch{}}d(gn,"crashAndTearDown");async function yn(e){const o=(await S().list()).map(({conversation_id:i,path:s})=>({id:i,path:s})),a=o.filter(i=>i.id===e),r=a.length>0?a:o.filter(i=>i.id.startsWith(e));if(r.length===0)throw w(`--fork-from '${e}': no pi session with that id found.`,{next:"Pass a live node id, a real session uuid/prefix, or an absolute .jsonl session path."});if(r.length>1)throw w(`--fork-from '${e}': ambiguous \u2014 ${r.length} sessions match that id prefix; pass the full id or the .jsonl path.`,{next:"Pass the full session uuid or an absolute .jsonl path to disambiguate."});return r[0].path}d(yn,"resolveSessionUuid");async function ie(e){const o=e.trim();if(o==="")throw w("--fork-from requires a node id, session file, or session uuid.",{next:"Pass a live node id, an absolute .jsonl session path, or a session uuid/prefix."});if(o.includes("/")||o.endsWith(".jsonl")){const r=N(_e(o)?o:ke(process.cwd(),o));if(r===null)throw w(`--fork-from '${o}': invalid conversation path.`,{next:"Pass a conversation file path or id."});return(await S().header(r)).path}const a=await u(o);if(a!==null){const r=a.pi_session_file;if(r==null||r==="")throw w(`node ${o} has no pi session yet \u2014 it has not captured a session FILE to fork from (the broker forks a .jsonl path, not a bare id).`,{next:"Pick a node that has captured a session, or drop --fork-from."});const i=N(r);if(i===null)throw w(`node ${o} has no valid conversation id.`,{next:"Pick a node with a captured conversation."});return(await S().header(i)).path}return await yn(o)}d(ie,"resolveForkSource");async function bn(e,o,a,r={}){return e===null?null:e!==void 0&&e!==""?Ee(e).profileId:o!==null?(await u(o))?.profile_id??null:r.readOnlySelection===!0?Oe(a):Re(a)}d(bn,"resolveProfileId");function ae(e){const o=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return dn(e.model,o,e.modelExact===!0)}d(ae,"requestFromLaunch");async function de(e,o,a){const r=a??(e.modelIntent?`${e.modelIntent.family}/${e.modelIntent.strength}`:e.model),i=await fn(o,r,e.modelExact===!0);if(i===null)return e;const{CRTR_MODEL_INTENT:s,...l}=e.env??{};return{...e,model:i.model,modelIntent:{family:U,strength:i.strength},modelExact:void 0,env:{...l,CRTR_MODEL_INTENT:`${U}/${i.strength}`}}}d(de,"appPaidLaunch");async function se(e,o,a){if(e===void 0||e.kind==="logical"&&e.family!==U)return;const r=await sn(e.kind==="logical"?{kind:"concrete",spec:e.spec}:e,a??await ln(),o);if(r!==void 0)throw w(`model '${r.request.spec}' is not registered in this daemon.`,{received:r.request.spec,next:cn})}d(se,"assertLaunchModelRegistered");function xn(e,o,a){const r=e??o??null;if(!a&&r===null)throw new Error("spawnChild requires a calling node (CRTR_NODE_ID) or an explicit parent");return r}d(xn,"resolveSpawner");async function le(e,o,a){try{tn()}catch{}const r=xe(),i=e.root===!0,s=xn(e.parent,r.nodeId??null,i),l=e.mode??"base",g=e.rootLifecycle??(i?"resident":"terminal"),ce=i&&g==="resident",E=s===null?null:await u(s),V=e.creator===void 0||e.creator===null?null:await u(e.creator);e.nodeId!==void 0&&await Ce(e.nodeId);const y=e.forkFrom!==void 0?await ie(e.forkFrom):void 0,L=y===void 0?null:await be(y),M=await hn([E,V,L],async f=>f?.isolated===!0||f?.run_id!=null&&(await u(f.run_id))?.isolated===!0);if(M&&e.isolated===!1)throw new ne(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});const R=M||e.isolated===!0;if(R&&e.worktree===!0)throw new ne(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const C=e.worktree===!0,m=R||C?e.nodeId??await Se():e.nodeId,O=R?e.run!==void 0&&i&&!M?e.cwd:ve(ge(e.run?.grantee??E?.grantee??"app:terminal").nodes,m):e.cwd,h=await bn(e.profile,s,O),X=e.run?.grant_id??E?.grant_id??null,q=await de((await oe(e.kind,l,{lifecycle:g,hasManager:!i,model:e.model,modelOverride:e.model!==void 0,cwd:O,profileId:h})).launch,X,e.model);await se(ae(q),{cwd:O,profileId:h});const T=e.run??V??E??L;await pn({grantee:T?.grantee??"app:terminal",sub:T?.sub,grant_id:T?.grant_id});const Y=L?.node_id??null;let b,F=O;const A=C&&await Ie(h)?await Be(h,e.worktreeCwd??e.cwd,m,e.worktreeBase):void 0;try{C&&A===void 0&&(b=await De(e.worktreeCwd??e.cwd,m,e.worktreeBase),F=b.path);const f=C?await de((await oe(e.kind,l,{lifecycle:g,hasManager:!i,model:e.model,modelOverride:e.model!==void 0,cwd:F,profileId:h})).launch,X,e.model):q;A!==void 0&&(f.worktree=A),C&&await se(ae(f),{cwd:F,profileId:h});const n=await ye({kind:e.kind,mode:l,lifecycle:g,cwd:F,name:e.name??e.kind,description:e.description,parent:i?null:s,creator:e.creator,...e.actor===void 0?{}:{actor:e.actor},forkSourceNode:Y,spawnedBy:i?s??void 0:void 0,profile_id:h,...e.scopes===void 0?{}:{scopes:e.scopes},isolated:R,...e.run===void 0?{}:{run:e.run},...e.causedBy===void 0?{}:{causedBy:e.causedBy},...e.withinCreate===void 0?{}:{withinCreate:e.withinCreate},forkFrom:e.forkFrom,forkSourceFile:y,modelOverride:e.model===void 0?void 0:f.model,...b!==void 0?{managedWorktree:b}:{},...m!==void 0?{nodeId:m}:{},...e.reviewBinding===void 0?{}:{reviewBinding:e.reviewBinding},...e.deadlineAt===void 0?{}:{deadlineAt:e.deadlineAt},...e.outcomeDelivery===void 0?{}:{outcomeDelivery:e.outcomeDelivery},launch:f});if(a?.(n.node_id),e.forkFrom!==void 0)try{await un(n.node_id,Y??null)}catch(t){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(t)}),t}if(await Pe(n.node_id,e.prompt),e.situationalContext!==void 0&&await Le(n.node_id,Me(e.situationalContext)),o!==void 0)try{o(n.node_id)}catch(t){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(t)}),t}const W=e.prompt!=="",ue=`${W&&e.wakeOrigin!==void 0?`${Ae(e.wakeOrigin)}
|
|
1
|
+
var me=Object.defineProperty;var d=(e,o)=>me(e,"name",{value:o,configurable:!0});import{accessSync as he,constants as pe}from"node:fs";import{isAbsolute as _e,resolve as ke,join as ve}from"node:path";import{appSpace as ge}from"../layout.js";import{ApiError as ne}from"../../api/errors.js";import{spawnNode as ye,forkSourceNode as be,currentNodeContext as xe,rootOfSpine as $e,newNodeId as Se,preflightNodeId as Ce}from"./nodes.js";import{resolveProfileOperand as Ee}from"../profiles/manifest.js";import{selectProfileForCwd as Re,selectProfileForCwdReadOnly as Oe}from"../profiles/select.js";import{buildLaunchSpecAsync as oe,buildPiArgv as Fe}from"./launch.js";import{runsOnBlaxel as Ie,sandboxWorktreeRequest as Pe}from"../../daemon/api/environment-of.js";import{createManagedWorktreeAsync as Be,rollbackManagedWorktreeAsync as De}from"../worktree-mutation-async.js";import{usage as w,brokerLaunchFailed as B}from"../errors.js";import{writeGoal as Ne}from"./kickoff.js";import{appendSituationalContext as Le,formatSituationalProse as Me}from"./situational-context.js";import{ensureRoadmap as Te}from"./roadmap.js";import{buildWakeBearings as Ae}from"./bearings.js";import{encodeKickoffOrigin as We,KICKOFF_ORIGIN_ENV as je}from"./stamp/protocol.js";import{ExecutionCapReached as ze,beginExecution as He,crtrHome as Ke,getNode as u,fullName as re,jobDir as Ge,recordExecutionPid as Ue,abortExecution as j,setFrozen as z}from"../canvas/index.js";import{contextDir as H,nodeAgentDir as K}from"../canvas/node-agent-paths.js";import{copyTreeBeneath as Ve}from"../spaces/open-beneath.js";import{conversationIdFromPath as D,conversationStore as S}from"../conversation-store/index.js";import{appMemoryTooSmall as Xe,boundFleet as qe,brokerThresholdsForDaemon as te}from"./fleet.js";import{admitBrokerMemory as Ye}from"./memory-admission.js";import{emitEvent as N}from"../events/emit.js";import{blaxelEnvironmentOf as Je}from"./blaxel-environment.js";import{openViewerWindow as Qe,focusOf as Ze,windowOfPane as en}from"./placement.js";import{awaitBrokerViewSocket as nn}from"./view-socket.js";import{readLogSnapshot as on}from"../events/read.js";import{transition as k}from"./lifecycle.js";import{beginBootFaultAttempt as rn}from"../canvas/recovery.js";import{headlessBrokerHost as G}from"./host.js";import{ensureDaemon as tn}from"../../daemon/manage.js";import{readConfig as an}from"../config.js";import{modelRequestFromConfig as dn,unregisteredConcreteModel as sn,unroutableConcreteModel as ln}from"../model-routes.js";import{openModelRegistry as cn}from"./model-registry.js";import{MODEL_SPEC_NEXT as un}from"./model-selection.js";import{forkNodeLedger as fn}from"./ledger.js";import{appRungForGrant as wn}from"../llm/app-rungs.js";import{APP_FAMILY as U}from"../model-routes.js";import{discoverLifecycleHookRegistry as mn}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as hn}from"../command-hooks/transport/exec-lifecycle.js";import{someAsync as pn}from"../async-array.js";import{checkStart as _n}from"./start-check.js";function v(e){return{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}d(v,"launchFailureOutcome");async function kn(e,o,a){try{return await G.launch(e,o,a)}catch(r){try{await k(e,"crash",{reason:"launch_failed",outcome:v(r)})}catch{}const t=r.message;throw B(t.startsWith("[broker]")?t:`[broker] refusing to launch ${e}: ${t}`,"Inspect the cause above, fix the launch recipe or environment, then retry.")}}d(kn,"launchBrokerOrCrash");function vn(e){return on({nodeId:e,component:"broker",pattern:"broker.startup."},!1).items.flatMap(a=>a.kind==="event"&&a.envelope.event.startsWith("broker.startup.")&&a.envelope.event!=="broker.startup.warning"?[a.envelope.event.slice(15)]:[]).at(-1)??null}d(vn,"lastStartupStep");function gn(e,o){const a=vn(e),r=a===null?"it had logged no startup step":`the last startup step it logged was \`${a}\``;if(o.reason==="exited"){const{code:t,signal:s}=o.status;return{text:`exited (code ${t??"null"}, signal ${s??"null"}) before binding its view socket; ${r}`,fields:{reason:"exited",code:t,signal:s,last_startup_step:a}}}return{text:`was still starting after ${Math.round(o.waitedMs/1e3)} s without binding its view socket, so the launcher stopped it; ${r}`,fields:{reason:"timeout",waited_ms:o.waitedMs,last_startup_step:a}}}d(gn,"notReadyDescription");async function yn(e,o){try{await k(e,"crash",{reason:"launch_failed",outcome:v(o)})}catch{}try{G.teardown(e)}catch{}}d(yn,"crashAndTearDown");async function bn(e){const o=(await S().list()).map(({conversation_id:t,path:s})=>({id:t,path:s})),a=o.filter(t=>t.id===e),r=a.length>0?a:o.filter(t=>t.id.startsWith(e));if(r.length===0)throw w(`--fork-from '${e}': no pi session with that id found.`,{next:"Pass a live node id, a real session uuid/prefix, or an absolute .jsonl session path."});if(r.length>1)throw w(`--fork-from '${e}': ambiguous \u2014 ${r.length} sessions match that id prefix; pass the full id or the .jsonl path.`,{next:"Pass the full session uuid or an absolute .jsonl path to disambiguate."});return r[0].path}d(bn,"resolveSessionUuid");async function ie(e){const o=e.trim();if(o==="")throw w("--fork-from requires a node id, session file, or session uuid.",{next:"Pass a live node id, an absolute .jsonl session path, or a session uuid/prefix."});if(o.includes("/")||o.endsWith(".jsonl")){const r=D(_e(o)?o:ke(process.cwd(),o));if(r===null)throw w(`--fork-from '${o}': invalid conversation path.`,{next:"Pass a conversation file path or id."});return(await S().header(r)).path}const a=await u(o);if(a!==null){const r=a.pi_session_file;if(r==null||r==="")throw w(`node ${o} has no pi session yet \u2014 it has not captured a session FILE to fork from (the broker forks a .jsonl path, not a bare id).`,{next:"Pick a node that has captured a session, or drop --fork-from."});const t=D(r);if(t===null)throw w(`node ${o} has no valid conversation id.`,{next:"Pick a node with a captured conversation."});return(await S().header(t)).path}return await bn(o)}d(ie,"resolveForkSource");async function xn(e,o,a,r={}){return e===null?null:e!==void 0&&e!==""?Ee(e).profileId:o!==null?(await u(o))?.profile_id??null:r.readOnlySelection===!0?Oe(a):Re(a)}d(xn,"resolveProfileId");function ae(e){const o=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return dn(e.model,o,e.modelExact===!0)}d(ae,"requestFromLaunch");async function de(e,o,a){const r=a??(e.modelIntent?`${e.modelIntent.family}/${e.modelIntent.strength}`:e.model),t=await wn(o,r,e.modelExact===!0);if(t===null)return e;const{CRTR_MODEL_INTENT:s,...l}=e.env??{};return{...e,model:t.model,modelIntent:{family:U,strength:t.strength},modelExact:void 0,env:{...l,CRTR_MODEL_INTENT:`${U}/${t.strength}`}}}d(de,"appPaidLaunch");async function se(e,o,a){if(e===void 0||e.kind==="logical"&&e.family!==U)return;const r=await sn(e.kind==="logical"?{kind:"concrete",spec:e.spec}:e,a??await cn(),o);if(r!==void 0)throw w(`model '${r.request.spec}' is not registered in this daemon.`,{received:r.request.spec,next:un});const t=await ln(e,o);if(t!==void 0)throw w(`model '${t.spec}' is registered but no configured model route offers it, so no turn could be served.`,{received:t.spec,next:"Pick a model from your configured routes (`crtr sys config get modelLadders`), or add this one to a ladder or route."})}d(se,"assertLaunchModelRegistered");function $n(e,o,a){const r=e??o??null;if(!a&&r===null)throw new Error("spawnChild requires a calling node (CRTR_NODE_ID) or an explicit parent");return r}d($n,"resolveSpawner");async function le(e,o,a){try{tn()}catch{}const r=xe(),t=e.root===!0,s=$n(e.parent,r.nodeId??null,t),l=e.mode??"base",g=e.rootLifecycle??(t?"resident":"terminal"),ce=t&&g==="resident",E=s===null?null:await u(s),V=e.creator===void 0||e.creator===null?null:await u(e.creator);e.nodeId!==void 0&&await Ce(e.nodeId);const y=e.forkFrom!==void 0?await ie(e.forkFrom):void 0,L=y===void 0?null:await be(y),M=await pn([E,V,L],async f=>f?.isolated===!0||f?.run_id!=null&&(await u(f.run_id))?.isolated===!0);if(M&&e.isolated===!1)throw new ne(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});const R=M||e.isolated===!0;if(R&&e.worktree===!0)throw new ne(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const C=e.worktree===!0,m=R||C?e.nodeId??await Se():e.nodeId,O=R?e.run!==void 0&&t&&!M?e.cwd:ve(ge(e.run?.grantee??E?.grantee??"app:terminal").nodes,m):e.cwd,h=await xn(e.profile,s,O),X=e.run?.grant_id??E?.grant_id??null,q=await de((await oe(e.kind,l,{lifecycle:g,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:O,profileId:h})).launch,X,e.model);await se(ae(q),{cwd:O,profileId:h});const T=e.run??V??E??L;await _n({grantee:T?.grantee??"app:terminal",sub:T?.sub,grant_id:T?.grant_id});const Y=L?.node_id??null;let b,F=O;const A=C&&await Ie(h)?await Pe(h,e.worktreeCwd??e.cwd,m,e.worktreeBase):void 0;try{C&&A===void 0&&(b=await Be(e.worktreeCwd??e.cwd,m,e.worktreeBase),F=b.path);const f=C?await de((await oe(e.kind,l,{lifecycle:g,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:F,profileId:h})).launch,X,e.model):q;A!==void 0&&(f.worktree=A),C&&await se(ae(f),{cwd:F,profileId:h});const n=await ye({kind:e.kind,mode:l,lifecycle:g,cwd:F,name:e.name??e.kind,description:e.description,parent:t?null:s,creator:e.creator,...e.actor===void 0?{}:{actor:e.actor},forkSourceNode:Y,spawnedBy:t?s??void 0:void 0,profile_id:h,...e.scopes===void 0?{}:{scopes:e.scopes},isolated:R,...e.run===void 0?{}:{run:e.run},...e.causedBy===void 0?{}:{causedBy:e.causedBy},...e.withinCreate===void 0?{}:{withinCreate:e.withinCreate},forkFrom:e.forkFrom,forkSourceFile:y,modelOverride:e.model===void 0?void 0:f.model,...b!==void 0?{managedWorktree:b}:{},...m!==void 0?{nodeId:m}:{},...e.reviewBinding===void 0?{}:{reviewBinding:e.reviewBinding},...e.deadlineAt===void 0?{}:{deadlineAt:e.deadlineAt},...e.outcomeDelivery===void 0?{}:{outcomeDelivery:e.outcomeDelivery},launch:f});if(a?.(n.node_id),e.forkFrom!==void 0)try{await fn(n.node_id,Y??null)}catch(i){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),i}if(await Ne(n.node_id,e.prompt),e.situationalContext!==void 0&&await Le(n.node_id,Me(e.situationalContext)),o!==void 0)try{o(n.node_id)}catch(i){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),i}const W=e.prompt!=="",ue=`${W&&e.wakeOrigin!==void 0?`${Ae(e.wakeOrigin)}
|
|
2
2
|
|
|
3
|
-
`:""}${e.prompt}`;l==="orchestrator"&&await Te(n.node_id,{goal:e.prompt.trim()}),await
|
|
3
|
+
`:""}${e.prompt}`;l==="orchestrator"&&await Te(n.node_id,{goal:e.prompt.trim()}),await Sn(n);let J;if(y!==void 0)try{const i=D(y);if(i===null)throw new Error(`invalid fork source ${y}`);const c=await S().fork(i,n.node_id);J=(await S().header(c)).path}catch(i){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),i}const x=Fe(n,{prompt:ue,resumeSessionPath:J});if(x.env={...x.env,CRTR_SUBTREE:await $e(n.node_id)},W){const i=e.wakeOrigin!==void 0?{type:"runtime",kind:"wake",wake:e.wakeOrigin}:{type:"runtime",kind:"kickoff",...n.spawned_by!=null&&n.spawned_by!==""?{spawnedBy:n.spawned_by}:{}};x.env[je]=We(i)}const p=qe();if(await Je(n.profile_id??null)!==null)return await z(n.node_id,new Date().toISOString()),N({level:"info",event:"broker.frozen",node_id:n.node_id,fields:{reason:"remote_environment"}}),{node:await u(n.node_id),frozen:!0,window:null,session:null};const Q=await p.reserveSlot(n.node_id),_=Q?await Ye(n.node_id):null;if(_?.verdict==="too_small"){p.releaseReservation(n.node_id);const i=Xe(_);throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),i}if(!Q||_?.verdict==="denied")return _?.verdict==="denied"&&p.releaseReservation(n.node_id),await z(n.node_id,new Date().toISOString()),N({level:"info",event:"broker.frozen",node_id:n.node_id,fields:_?.verdict==="denied"?{reason:"app_memory",free_bytes:_.free_bytes,needed_bytes:_.needed_bytes}:{reason:"broker_cap",live_count:await p.occupancy(),hard_cap:te().automaticReviveCap}}),{node:await u(n.node_id),frozen:!0,window:null,session:null};const fe=await rn(n.node_id),{automaticReviveCap:we}=te();let $;try{$=await He(n.node_id,{daemonEpoch:p.epoch(),cap:we})}catch(i){if(!(i instanceof ze))throw i;return p.releaseReservation(n.node_id),await z(n.node_id,new Date().toISOString()),N({level:"info",event:"broker.frozen",node_id:n.node_id,fields:{reason:"broker_cap",live_count:i.live,hard_cap:i.cap}}),{node:await u(n.node_id),frozen:!0,window:null,session:null}}x.env={...x.env,CRTR_EXECUTION_ID:$};let I;try{I=await kn(n.node_id,x,{cwd:n.cwd,name:re(n),resuming:!1})}catch(i){throw await j($,{reason:"launch_failed"}),i}finally{p.releaseReservation(n.node_id)}if(I.pid===null){const i=new Error(`broker host returned no pid for ${n.node_id}`);throw await j($,{reason:"launch_failed"}),await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),B(`failed to launch the broker engine for ${n.node_id} (${n.name}) \u2014 the node was not started.`,`Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then verify the pi engine can start in this environment.`)}if(await Ue($,n.node_id,I.pid)==="shutdown")throw await j($,{reason:"superseded"}),G.teardown(n.node_id),B(`broker execution was superseded for ${n.node_id}`,"Retry spawning the node.");if(ce&&e.readiness==="await"){const i=await nn(n.node_id,I.exited);if(!i.ready){const c=gn(n.node_id,i);N({level:"error",event:"broker.launch.not_ready",node_id:n.node_id,fields:c.fields});const P=await fe.explanation();throw await yn(n.node_id,new Error(P??c.text)),B(P!==null?`the root broker ${n.node_id} could not start \u2014 ${P}`:`the root broker ${n.node_id} ${c.text} \u2014 it was not started.`,P!==null?"Resolve the cause named above, then retry.":`Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then retry.`)}}let Z=null,ee=null;if(!t&&s!==null&&an("user").auto_open_child_viewers)try{const i=await Ze(s);if(i!==null&&i.pane!==null&&i.pane!==""){const c=await Qe(n.node_id,i.session??"",{name:re(n),cwd:e.cwd,besidePane:i.pane,waitForBroker:!0,initialWhip:W});c!==null&&c.pane!==null&&c.pane!==""&&(ee=c.session,Z=en(c.pane))}}catch{}return{node:await u(n.node_id),frozen:!1,window:Z,session:ee}}catch(f){throw b!==void 0&&m!==void 0&&await u(m)===null&&await De(b),f}}d(le,"spawnChildPrepared");async function vo(e){return le(e)}d(vo,"spawnChild");async function Sn(e){const o=mn(e.cwd,e.profile_id).plans.get("node:start")??[];await hn(o,{node:{id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,cwd:e.cwd,nodeDir:await K(e.node_id),contextDir:await H(e.node_id),jobDir:Ge(e.node_id)},runtime:{isBirth:!0,canvasHome:Ke(),profile:e.profile_id??null}})}d(Sn,"invokeBirthLifecycleHooks");const Cn=new Set(["initial-prompt.md","yield-message.md","result.json","jobs"]);async function go(e,o,a){const r=await u(e);if(r===null)throw w(`unknown node: ${e}`,{received:e,next:"List nodes and pass the id of a node with a captured pi session."});const t=await ie(e),s=await H(e);try{await S().header(D(t)),he(s,pe.R_OK)}catch(l){throw new Error(`cannot fork ${e}: its conversation or context is unreadable \u2014 ${l.message}`)}return le({kind:r.kind,mode:"base",cwd:r.cwd,prompt:"",root:!0,readiness:"await",forkFrom:e,...a===void 0?{}:{actor:a},profile:r.profile_id,model:r.model_override??void 0,...o===void 0?{}:{scopes:o}},async l=>{const g=await H(l);Ve(await K(e),s,await K(l),g,Cn)})}d(go,"forkNode");export{de as appPaidLaunch,se as assertLaunchModelRegistered,go as forkNode,Sn as invokeBirthLifecycleHooks,ie as resolveForkSource,xn as resolveProfileId,$n as resolveSpawner,vo as spawnChild,le as spawnChildPrepared};
|
|
@@ -39,7 +39,7 @@ export declare function waitForBrokerViewSocket(nodeId: string, exited?: Promise
|
|
|
39
39
|
code: number | null;
|
|
40
40
|
signal: NodeJS.Signals | null;
|
|
41
41
|
}>, waitMs?: number): Promise<boolean>;
|
|
42
|
-
/** The port a sandboxed broker serves `/view` on (
|
|
42
|
+
/** The port a sandboxed broker serves `/view` on (bound to `::`; reached only through the private preview and its per-attach token). */
|
|
43
43
|
export declare const BROKER_VIEW_PORT = 4180;
|
|
44
44
|
/** The relay's end of one broker view connection: a view.sock {@link Socket}, or {@link connectWssView}'s link. Bytes in
|
|
45
45
|
* both directions are newline-terminated frames; `close` carries whether an error preceded it. */
|
|
@@ -34,6 +34,10 @@ export declare const REFRESH_EXCHANGE_TIMEOUT_MS = 10000;
|
|
|
34
34
|
export declare class RefreshBusyError extends Error {
|
|
35
35
|
constructor(provider: ManagedProviderId, label: string);
|
|
36
36
|
}
|
|
37
|
+
/** The vendor did not answer a refresh exchange within `REFRESH_EXCHANGE_TIMEOUT_MS`. */
|
|
38
|
+
export declare class RefreshTimeoutError extends Error {
|
|
39
|
+
constructor(provider: ManagedProviderId);
|
|
40
|
+
}
|
|
37
41
|
export declare function insertAccount(db: CanvasDb, person: string, provider: ManagedProviderId, row: ProviderRow, entry: StoredCredential): Promise<void>;
|
|
38
42
|
export declare function upsertModelCooldown(db: CanvasDb, person: string, provider: string, accountId: string, family: string, until: number, rateLimitedAt: number): Promise<void>;
|
|
39
43
|
export declare function readSubscriptionPool(provider: ManagedProviderId): Promise<SubscriptionCredential[]>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var _t=Object.defineProperty;var l=(t,a)=>_t(t,"name",{value:a,configurable:!0});import{createHash as ht,randomUUID as x}from"node:crypto";import{brokerConfigSnapshot as pt}from"./config.js";import{openDb as P,withCanvasWrite as N}from"./canvas/db.js";import{personIdAsync as y}from"./canvas/person.js";import{loadSecretsKey as K,open as X,seal as $}from"./secrets/index.js";import{modelCooldownFamily as wt}from"./rate-limit-scope.js";import{registerRotationReader as At}from"./model-routes.js";import{coolingUntilFor as bt,getProviderLabel as h,isInvalidRefreshTokenError as Y,DuplicateSubscriptionError as O,ANTHROPIC_PROVIDER_ID as yt,MAX_RATE_LIMIT_COOLDOWN_MS as B,INVALID_REFRESH_TOKEN_BACKOFF_MS as Et}from"./managed-providers.js";export*from"./managed-providers.js";const J="strong";function Q(t){return t==="ultra"||t==="strong"||t==="medium"||t==="light"?t:void 0}l(Q,"normalizeStrength");function _(t){return t.toLowerCase()}l(_,"key");function j(t){return typeof t=="string"&&t.trim()?t.trim():void 0}l(j,"optionalString");function Lt(t){const a=typeof t.label=="string"?t.label.trim():"",e=typeof t.refresh=="string"?t.refresh.trim():"",n=typeof t.access=="string"?t.access.trim():"",i=Number(t.expires);if(!a||!e||!n||!Number.isFinite(i))return;const r=j(t.accountId),s=j(t.clientId);return{label:a,refresh:e,access:n,expires:i,rateLimitedUntil:Number.isFinite(Number(t.rateLimitedUntil))?Number(t.rateLimitedUntil):0,lastAttemptAt:Number.isFinite(Number(t.lastAttemptAt))?Number(t.lastAttemptAt):0,lastRateLimitedAt:Number.isFinite(Number(t.lastRateLimitedAt))?Number(t.lastRateLimitedAt):0,...t.authFailure==="invalid_grant"?{authFailure:"invalid_grant"}:{},...r?{accountId:r}:{},...s?{clientId:s}:{},...Z(t.modelCooldowns)?{modelCooldowns:Z(t.modelCooldowns)}:{}}}l(Lt,"credential");function Z(t){if(!t||typeof t!="object"||Array.isArray(t))return;const a=Object.entries(t).filter(([e,n])=>e.trim()!==""&&Number.isFinite(Number(n))).map(([e,n])=>[e,Number(n)]);return a.length?Object.fromEntries(a):void 0}l(Z,"modelCooldowns");function F(t,a){if(!a.label?.trim())throw new Error(`${h(t)} subscription label cannot be empty`);const e=Lt(a);if(!e)throw new Error(`Refusing to persist incomplete ${h(t)} subscription "${a.label.trim()}"; pool rows require both OAuth tokens.`);return e}l(F,"assertCredential");function v(t,a){const e=t.accountId?.trim(),n=a.accountId?.trim();return!!(e&&n&&e!==n)}l(v,"differentAccount");function p(t){return t.accountId?.trim()||(t.refresh.trim()?`refresh:${ht("sha256").update(t.refresh.trim()).digest("hex")}`:void 0)}l(p,"identity");function tt(t,a){const e=j(a);return e?{...t,clientId:e}:t}l(tt,"withClientId");function et(t,a,e){const n=e.refresh?.trim()??"",i=e.access?.trim()??"",r=Number(e.expires);if(!n||!i||!Number.isFinite(r))throw new Error(`${h(t)} subscription "${a}" returned an incomplete credential; the stored credential was left unchanged.`);return{refresh:n,access:i,expires:r}}l(et,"assertTokens");const at=1e4,Rt="15s",gt="55P03";class nt extends Error{static{l(this,"RefreshBusyError")}constructor(a,e){super(`${h(a)} subscription "${e}" is being refreshed by another process; treating it as cooling for this call`),this.name="RefreshBusyError"}}const it="id,label,label_key,position,last_attempt_at,last_rate_limited_at,rate_limited_until,auth_failure,refresh_sealed,access_sealed,expires,vendor_account_id,client_id,key_id",I=l((t,a,e,n)=>`model_accounts|${t}|${a}|${e}|${n}`,"aadOf");function E(t){return{refresh:t.refresh,access:t.access,expires:t.expires,...t.accountId?{accountId:t.accountId}:{},...t.clientId?{clientId:t.clientId}:{}}}l(E,"stored");function It(t,a){return{providerId:t,id:a.id,label:a.label,labelKey:a.label_key,position:a.position,lastAttemptAt:a.last_attempt_at,lastRateLimitedAt:a.last_rate_limited_at,rateLimitedUntil:a.rate_limited_until,...a.auth_failure?{authFailure:a.auth_failure}:{}}}l(It,"rowOf");function rt(t,a,e,n=[]){if(!e.refresh_sealed||!e.access_sealed||e.expires===null||!e.key_id)throw new Error(`managed ${a} account ${e.id} has no credential record`);const i=K(),r=X(e.refresh_sealed,e.key_id,i,I(t,a,e.id,"refresh")),s=X(e.access_sealed,e.key_id,i,I(t,a,e.id,"access")),o=It(a,e),c={label:o.label,refresh:r,access:s,expires:e.expires,rateLimitedUntil:o.authFailure||!o.lastRateLimitedAt?o.rateLimitedUntil:Math.min(o.rateLimitedUntil,o.lastRateLimitedAt+B),lastAttemptAt:o.lastAttemptAt,lastRateLimitedAt:o.lastRateLimitedAt,...o.authFailure?{authFailure:o.authFailure}:{},...e.vendor_account_id?{accountId:e.vendor_account_id}:{},...e.client_id?{clientId:e.client_id}:{},...n.length?{modelCooldowns:Object.fromEntries(n.map(d=>[d.family,d.lastRateLimitedAt?Math.min(d.rateLimitedUntil,d.lastRateLimitedAt+B):d.rateLimitedUntil]))}:{}};return{row:o,entry:c}}l(rt,"toPublic");async function S(t,a,e){const n=new Map,i=await t.prepare("SELECT account_id,family,rate_limited_until,last_rate_limited_at FROM model_account_cooldowns WHERE person=? AND provider_id=? ORDER BY family").all(a,e);for(const r of i){const s=n.get(r.account_id)??[];s.push({family:r.family,rateLimitedUntil:r.rate_limited_until,lastRateLimitedAt:r.last_rate_limited_at}),n.set(r.account_id,s)}return n}l(S,"loadCooldowns");async function k(t,a,e,n=!1){const i=await t.prepare(`SELECT ${it} FROM model_accounts WHERE person=? AND provider_id=? ORDER BY position${n?" FOR UPDATE":""}`).all(a,e),r=await S(t,a,e);return i.map(s=>rt(a,e,s,r.get(s.id)))}l(k,"loadPool");async function st(t,a,e,n){const i=n.trim().toLowerCase(),r=Number.parseInt(i,10),s=Number.isFinite(r)&&String(r)===i&&r>=1,o=await t.prepare(`SELECT ${it} FROM model_accounts WHERE person=? AND provider_id=? AND ${s?"position=?":"label_key=?"} FOR UPDATE`).get(a,e,s?r-1:i);if(o)return rt(a,e,o,(await S(t,a,e)).get(o.id))}l(st,"lockedAccount");async function T(t){await t.exec(`SET LOCAL lock_timeout = '${Rt}'`)}l(T,"setLockTimeout");async function L(t,a){const e=await y();return N(async n=>(await T(n),await n.prepare("SELECT pg_advisory_xact_lock(hashtext(?))").get(`model_accounts|${e}|${t}`),a({db:n,person:e,rows:await k(n,e,t,!0)})))}l(L,"locked");async function C(t,a,e,n,i){const r=K(),s=$(i.refresh,r,I(a,e,n.id,"refresh")),o=$(i.access,r,I(a,e,n.id,"access"));await t.prepare("INSERT INTO model_accounts(person,provider_id,id,label,label_key,position,last_attempt_at,last_rate_limited_at,rate_limited_until,auth_failure,refresh_sealed,access_sealed,expires,vendor_account_id,client_id,key_id) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)").run(a,e,n.id,n.label,n.labelKey,n.position,n.lastAttemptAt,n.lastRateLimitedAt,n.rateLimitedUntil,n.authFailure??null,s.sealed,o.sealed,i.expires,i.accountId??null,i.clientId??null,s.keyId)}l(C,"insertAccount");async function M(t,a,e,n,i){const r=K(),s=$(i.refresh,r,I(a,e,n,"refresh")),o=$(i.access,r,I(a,e,n,"access"));await t.prepare("UPDATE model_accounts SET refresh_sealed=?,access_sealed=?,expires=?,vendor_account_id=?,client_id=?,key_id=? WHERE person=? AND provider_id=? AND id=?").run(s.sealed,o.sealed,i.expires,i.accountId??null,i.clientId??null,s.keyId,a,e,n)}l(M,"setCredential");async function b(t,a,e){await t.prepare("UPDATE model_accounts SET label=?,label_key=?,position=?,last_attempt_at=?,last_rate_limited_at=?,rate_limited_until=?,auth_failure=? WHERE person=? AND provider_id=? AND id=?").run(e.label,e.labelKey,e.position,e.lastAttemptAt,e.lastRateLimitedAt,e.rateLimitedUntil,e.authFailure??null,a,e.providerId,e.id)}l(b,"updateHealth");async function ot(t,a,e,n,i,r,s){await t.prepare("INSERT INTO model_account_cooldowns(person,provider_id,account_id,family,rate_limited_until,last_rate_limited_at) VALUES(?,?,?,?,?,?) ON CONFLICT(person,provider_id,account_id,family) DO UPDATE SET rate_limited_until=excluded.rate_limited_until,last_rate_limited_at=excluded.last_rate_limited_at").run(a,e,n,i,r,s)}l(ot,"upsertModelCooldown");async function D(t,a,e,n){n===void 0?await t.prepare("DELETE FROM model_account_cooldowns WHERE person=? AND provider_id=?").run(a,e):await t.prepare("DELETE FROM model_account_cooldowns WHERE person=? AND provider_id=? AND account_id=?").run(a,e,n)}l(D,"deleteModelCooldowns");const R=l(async({db:t,person:a},e)=>(await k(t,a,e)).map(({entry:n})=>n),"publicPool"),lt=l(t=>t?.code===gt,"lockWaitExpired");function ct(t,a){let e;return Promise.race([a,new Promise((n,i)=>{e=setTimeout(()=>i(new Error(`${t} did not answer within ${at} ms`)),at)})]).finally(()=>clearTimeout(e))}l(ct,"withExchangeTimeout");async function V(t){return(await xt(t)).map(({entry:a})=>a)}l(V,"readSubscriptionPool");async function xt(t){const a=await y();return(await k(await P(),a,t)).map(({row:e,entry:n})=>({id:e.id,entry:n}))}l(xt,"readSubscriptionPoolRows");async function jt(t,a){return L(t,async e=>{const{db:n,person:i,rows:r}=e,s=a.map(d=>F(t,d)),o=s.map((d,u)=>({entry:d,id:r[u]?.row.id??x()})),c=await S(n,i,t);await n.prepare("DELETE FROM model_accounts WHERE person=? AND provider_id=?").run(i,t),await D(n,i,t);for(const[d,{entry:u,id:m}]of o.entries()){await C(n,i,t,{providerId:t,id:m,label:u.label,labelKey:_(u.label),position:d,lastAttemptAt:u.lastAttemptAt,lastRateLimitedAt:u.lastRateLimitedAt,rateLimitedUntil:u.rateLimitedUntil,...u.authFailure?{authFailure:u.authFailure}:{}},E(u));for(const[f,A]of Object.entries(u.modelCooldowns??{}))await ot(n,i,t,m,f,A,c.get(m)?.find(U=>U.family===f)?.lastRateLimitedAt??u.lastRateLimitedAt)}return s})}l(jt,"writeSubscriptionPool");function W(t,a){const e=a.trim().toLowerCase(),n=Number.parseInt(e,10);return Number.isFinite(n)&&String(n)===e&&n>=1&&n<=t.length?n-1:t.findIndex(({entry:i})=>_(i.label)===e)}l(W,"resolve");const H=l((t,a)=>new O(`This ${h(t)} account is already added as \u201C${a}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`),"duplicateAccount");async function Nt(t,a){const e=F(t,a);return L(t,async n=>{const{db:i,person:r,rows:s}=n;if(s.some(({entry:d})=>_(d.label)===_(e.label)))throw new O(`${h(t)} subscription already exists: ${e.label}`);const o=p(e),c=s.find(({entry:d})=>p(d)===o);if(o&&c)throw H(t,c.entry.label);return await C(i,r,t,{providerId:t,id:x(),label:e.label,labelKey:_(e.label),position:s.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil,...e.authFailure?{authFailure:e.authFailure}:{}},E(e)),R(n,t)})}l(Nt,"addSubscription");async function Vt(t,a){const e=F(t,a);return(await V(t)).find(i=>_(i.label)===_(e.label))?Ft(t,e):Nt(t,e)}l(Vt,"upsertSubscription");async function Ft(t,a){const e=F(t,a);return L(t,async n=>{const{db:i,person:r,rows:s}=n,o=s.findIndex(({entry:f})=>_(f.label)===_(e.label)),c=s[o],d=s.find(({entry:f},A)=>A!==o&&p(f)===p(e));if(p(e)&&d)throw H(t,d.entry.label);if(!c)return await C(i,r,t,{providerId:t,id:x(),label:e.label,labelKey:_(e.label),position:s.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil},E(e)),R(n,t);const u=c.row,m=e.lastRateLimitedAt>=u.lastRateLimitedAt;return await M(i,r,t,u.id,E(e)),await b(i,r,{...u,authFailure:void 0,label:e.label,labelKey:_(e.label),lastAttemptAt:Math.max(u.lastAttemptAt,e.lastAttemptAt),lastRateLimitedAt:m?e.lastRateLimitedAt:u.lastRateLimitedAt,rateLimitedUntil:m?e.rateLimitedUntil:u.rateLimitedUntil}),v(c.entry,e)&&await D(i,r,t,u.id),R(n,t)})}l(Ft,"upsertSubscriptionWithUniqueAccount");async function Gt(t,a,e){return L(t,async n=>{const{db:i,person:r,rows:s}=n,o=W(s,a);if(o<0)throw new Error(`Unknown ${h(t)} subscription: ${a}`);const c=e.trim();if(!c)throw new Error(`${h(t)} subscription label cannot be empty`);if(s.some((d,u)=>u!==o&&_(d.entry.label)===_(c)))throw new O(`${h(t)} subscription already exists: ${c}`);return await b(i,r,{...s[o].row,label:c,labelKey:_(c)}),R(n,t)})}l(Gt,"renameSubscription");async function G(t,a,e){return L(t,async n=>{const{db:i,person:r,rows:s}=n,o=a(s);if(o<0)throw new Error(`Unknown ${h(t)} subscription: ${e}`);const c=s[o].row;return await i.prepare("DELETE FROM model_accounts WHERE person=? AND provider_id=? AND id=?").run(r,t,c.id),await D(i,r,t,c.id),R(n,t)})}l(G,"remove");async function St(t,a){return G(t,e=>W(e,a),a)}l(St,"removeManagedAccount");async function zt(t,a){return G(t,e=>e.findIndex(({row:n})=>n.id===a),a)}l(zt,"removeManagedAccountById");async function qt(t,a){return G(t,e=>W(e,a),a)}l(qt,"removeSubscription");async function Tt(t){return L(t,async({db:a,person:e,rows:n})=>(await a.prepare("DELETE FROM model_accounts WHERE person=? AND provider_id=?").run(e,t),await D(a,e,t),n.length))}l(Tt,"removeAllManagedAccounts");async function Xt(t,a){return a===void 0?(await Tt(t),[]):St(t,a)}l(Xt,"removeManagedProvider");async function Yt(t,a){return L(t,async e=>{const{db:n,person:i,rows:r}=e,s=W(r,a);if(s<0)throw new Error(`Unknown ${h(t)} subscription: ${a}`);const o=[r[s],...r.filter((c,d)=>d!==s)];for(const[c,d]of o.entries())await b(n,i,{...d.row,position:c});return R(e,t)})}l(Yt,"promoteSubscription");async function z(t,a,e){const n=await y();return await N(async i=>{await T(i);const r=await st(i,n,t,a);if(!r)throw new Error(`Unknown ${h(t)} subscription: ${a}`);await e(i,n,r.row)}),V(t)}l(z,"healthWrite");async function Jt(t,a,e=Date.now()){return z(t,a,(n,i,r)=>b(n,i,{...r,lastAttemptAt:Math.max(r.lastAttemptAt,e)}))}l(Jt,"markSubscriptionAttempt");async function Qt(t,a,e,n=Date.now(),i=Date.now(),r={kind:"account"}){return e=Math.min(Math.max(0,e),B),z(t,a,async(s,o,c)=>{if(r.kind==="account"){if(i<c.lastRateLimitedAt)return;await b(s,o,{...c,lastAttemptAt:Math.max(c.lastAttemptAt,n),lastRateLimitedAt:i,rateLimitedUntil:i+e});return}await b(s,o,{...c,lastAttemptAt:Math.max(c.lastAttemptAt,n)});const d=(await S(s,o,t)).get(c.id)?.find(u=>u.family===r.family);d&&i<d.lastRateLimitedAt||await ot(s,o,t,c.id,r.family,i+e,i)})}l(Qt,"markSubscriptionRateLimited");async function Zt(t,a,e=Date.now(),n){const i=wt(n);return z(t,a,async(r,s,o)=>{if(e>=o.lastRateLimitedAt&&await b(r,s,{...o,authFailure:void 0,lastAttemptAt:Math.max(o.lastAttemptAt,e),rateLimitedUntil:0}),i===void 0)return;const c=(await S(r,s,t)).get(o.id)?.find(d=>d.family===i);c&&e>=c.lastRateLimitedAt&&await r.prepare("DELETE FROM model_account_cooldowns WHERE person=? AND provider_id=? AND account_id=? AND family=?").run(s,t,o.id,i)})}l(Zt,"markSubscriptionSuccess");async function ut(t,a,e){const n=Date.now();await b(t,a,{...e,authFailure:"invalid_grant",lastAttemptAt:Math.max(e.lastAttemptAt,n),rateLimitedUntil:Math.max(e.rateLimitedUntil,n+Et)})}l(ut,"recordInvalidGrant");async function vt(t,a,e){const n=await y();let i;try{i=await N(async r=>{await T(r);const s=await st(r,n,t,a);if(!s)throw new Error(`${h(t)} subscription "${a}" no longer exists`);if(s.entry.expires>Date.now())return{entry:s.entry};if(s.row.authFailure)throw new Error(`${h(t)} subscription "${s.entry.label}" refresh refused with status=400 invalid_grant; it needs a new sign-in`);let o;try{o=await ct(`${h(t)} refresh`,e(s.entry.refresh,s.entry.clientId))}catch(d){if(!Y(d))throw d;return await ut(r,n,s.row),{refused:d}}const c=tt(et(t,s.entry.label,o),o.clientId??s.entry.clientId);return await M(r,n,t,s.row.id,E({...s.entry,...c})),{entry:{...s.entry,...c}}})}catch(r){throw lt(r)?new nt(t,a):r}if("refused"in i)throw i.refused;return i.entry}l(vt,"refreshSubscriptionCredential");async function te(t,a,e){const n=await y();let i;try{i=await N(async r=>{await T(r);const s=await k(r,n,t,!0),o=new Set;let c;for(;o.size<s.length;){const d=a(s.filter(({entry:m})=>!o.has(m.label)).map(({entry:m})=>m));if(!d)break;const u=s.find(({entry:m})=>m.label===d.label);o.add(u.entry.label);try{const m=await ct(`${h(t)} refresh`,e(u.entry));if(!m)return{entry:u.entry};const f=tt(et(t,u.entry.label,m),m.clientId??u.entry.clientId);return await M(r,n,t,u.row.id,E({...u.entry,...f})),{entry:{...u.entry,...f}}}catch(m){if(!Y(m))throw m;c=m,await ut(r,n,u.row)}}return c?{refused:c}:{}})}catch(r){throw lt(r)?new nt(t,a([])?.label??t):r}if("refused"in i)throw i.refused;return i.entry}l(te,"modifyElectedSubscription");async function Dt(t,a){const e=a.accountId?.trim(),n=a.email?.trim();if(t!==yt)return{...e?{accountId:e}:{},...n?{email:n}:{}};try{const i=await fetch("https://api.anthropic.com/api/oauth/profile",{headers:{Authorization:`Bearer ${a.access}`,Accept:"application/json"},signal:AbortSignal.timeout(3e3)});if(!i.ok)return e?{accountId:e}:{};const r=await i.json(),s=typeof r.account?.uuid=="string"&&r.account.uuid.trim()?r.account.uuid.trim():void 0,o=typeof r.account?.email=="string"&&r.account.email.trim()?r.account.email.trim():void 0;return{...s?{accountId:s}:{},...o?{email:o}:{}}}catch{return e?{accountId:e}:{}}}l(Dt,"enrichManagedLoginIdentity");async function ee(t,a,e){const n=await Dt(t,e);return L(t,async i=>{const{db:r,person:s,rows:o}=i,c=e.autoLabel?void 0:a?.trim(),d=p({refresh:e.refresh,accountId:n.accountId}),u=(c?o.find(({entry:w})=>_(w.label)===_(c)):void 0)??o.find(({entry:w})=>p(w)===d);let m=u?.entry.label??c;if(!m&&e.autoLabel){const w=n.email||a?.trim()||`Account ${o.length+1}`;m=w;for(let g=2;o.some(({entry:ft})=>_(ft.label)===_(m));g++)m=`${w} (${g})`}if(!m)throw new Error(`${h(t)} subscription label cannot be empty`);const f=F(t,{label:m,refresh:e.refresh,access:e.access,expires:e.expires,...n.accountId?{accountId:n.accountId}:{},...e.clientId?{clientId:e.clientId}:{},rateLimitedUntil:0,lastAttemptAt:Date.now(),lastRateLimitedAt:e.lastRateLimitedAt});if(!u){if(o.some(({entry:g})=>_(g.label)===_(f.label)))throw new O(`${h(t)} subscription already exists: ${f.label}`);const w=o.find(({entry:g})=>p(g)===p(f));if(p(f)&&w)throw H(t,w.entry.label);return await C(r,s,t,{providerId:t,id:x(),label:f.label,labelKey:_(f.label),position:o.length,lastAttemptAt:f.lastAttemptAt,lastRateLimitedAt:f.lastRateLimitedAt,rateLimitedUntil:f.rateLimitedUntil},E(f)),R(i,t)}const A=u.row,U=o.find(({entry:w})=>w.label!==u.entry.label&&p(w)===p(f));if(p(f)&&U)throw H(t,U.entry.label);const q=f.lastRateLimitedAt>=A.lastRateLimitedAt;return await M(r,s,t,A.id,E(f)),await b(r,s,{...A,authFailure:void 0,lastAttemptAt:Math.max(A.lastAttemptAt,f.lastAttemptAt),lastRateLimitedAt:q?f.lastRateLimitedAt:A.lastRateLimitedAt,rateLimitedUntil:q?0:A.rateLimitedUntil}),v(u.entry,f)&&await D(r,s,t,A.id),R(i,t)})}l(ee,"commitManagedLogin");const dt=new Map;function mt(t){return{defaultFallbackStrength:Q(t?.default_fallback_strength)??J,revertWhenAvailable:t?.revert_when_available===void 0||t.revert_when_available===null?!0:!!t.revert_when_available}}l(mt,"rotationFromRow");async function Ut(){const t=await y(),a=mt(await(await P()).prepare("SELECT default_fallback_strength,revert_when_available FROM model_settings WHERE person=?").get(t));return dt.set(t,a),a}l(Ut,"loadRotationConfig"),At(()=>$t());async function $t(){const t=pt();return t?t.rotation:Ut()}l($t,"readRotationConfig");async function ae(t){const a=await y(),e=await N(async n=>{await T(n),await n.prepare("INSERT INTO model_settings(person) VALUES(?) ON CONFLICT(person) DO NOTHING").run(a);const i=mt(await n.prepare("SELECT default_fallback_strength,revert_when_available FROM model_settings WHERE person=? FOR UPDATE").get(a)),r={defaultFallbackStrength:Q(t.defaultFallbackStrength)??i.defaultFallbackStrength??J,revertWhenAvailable:t.revertWhenAvailable??i.revertWhenAvailable??!0};return await n.prepare("UPDATE model_settings SET default_fallback_strength=?,revert_when_available=?,revision=revision+1 WHERE person=?").run(r.defaultFallbackStrength,r.revertWhenAvailable?1:0,a),r});return dt.set(a,e),e}l(ae,"writeRotationConfig");async function ne(){const t=await y();return(await(await P()).prepare("INSERT INTO model_settings(person,openai_device_id) VALUES(?,?) ON CONFLICT(person) DO UPDATE SET openai_device_id=COALESCE(model_settings.openai_device_id,EXCLUDED.openai_device_id) RETURNING openai_device_id").get(t,x())).openai_device_id}l(ne,"openAIDeviceId");async function ie(t,a=Date.now(),e){const n=await V(t),i=n.filter(s=>s.authFailure===void 0&&bt(s,e)<=a),r=h(t);return i.length===0?`${r} pool exhausted`:`${r} ${i[0]?.label??t} (${i.length}/${n.length} ready)`}l(ie,"formatStatusLine");export{at as REFRESH_EXCHANGE_TIMEOUT_MS,nt as RefreshBusyError,Nt as addSubscription,ee as commitManagedLogin,Dt as enrichManagedLoginIdentity,ie as formatStatusLine,C as insertAccount,Ut as loadRotationConfig,Jt as markSubscriptionAttempt,Qt as markSubscriptionRateLimited,Zt as markSubscriptionSuccess,te as modifyElectedSubscription,ne as openAIDeviceId,Yt as promoteSubscription,$t as readRotationConfig,V as readSubscriptionPool,xt as readSubscriptionPoolRows,vt as refreshSubscriptionCredential,Tt as removeAllManagedAccounts,St as removeManagedAccount,zt as removeManagedAccountById,Xt as removeManagedProvider,qt as removeSubscription,Gt as renameSubscription,ot as upsertModelCooldown,Vt as upsertSubscription,Ft as upsertSubscriptionWithUniqueAccount,ae as writeRotationConfig,jt as writeSubscriptionPool};
|
|
1
|
+
var _t=Object.defineProperty;var l=(t,a)=>_t(t,"name",{value:a,configurable:!0});import{createHash as ht,randomUUID as x}from"node:crypto";import{brokerConfigSnapshot as pt}from"./config.js";import{openDb as W,withCanvasWrite as N}from"./canvas/db.js";import{personIdAsync as y}from"./canvas/person.js";import{loadSecretsKey as K,open as X,seal as $}from"./secrets/index.js";import{modelCooldownFamily as wt}from"./rate-limit-scope.js";import{REFRESH_BUSY_PHRASE as At,REFRESH_TIMEOUT_PHRASE as bt}from"./provider-error-recognition.js";import{registerRotationReader as yt}from"./model-routes.js";import{coolingUntilFor as Et,getProviderLabel as h,isInvalidRefreshTokenError as Y,DuplicateSubscriptionError as O,ANTHROPIC_PROVIDER_ID as Lt,MAX_RATE_LIMIT_COOLDOWN_MS as B,INVALID_REFRESH_TOKEN_BACKOFF_MS as Rt}from"./managed-providers.js";export*from"./managed-providers.js";const J="strong";function Q(t){return t==="ultra"||t==="strong"||t==="medium"||t==="light"?t:void 0}l(Q,"normalizeStrength");function _(t){return t.toLowerCase()}l(_,"key");function j(t){return typeof t=="string"&&t.trim()?t.trim():void 0}l(j,"optionalString");function gt(t){const a=typeof t.label=="string"?t.label.trim():"",e=typeof t.refresh=="string"?t.refresh.trim():"",n=typeof t.access=="string"?t.access.trim():"",i=Number(t.expires);if(!a||!e||!n||!Number.isFinite(i))return;const r=j(t.accountId),s=j(t.clientId);return{label:a,refresh:e,access:n,expires:i,rateLimitedUntil:Number.isFinite(Number(t.rateLimitedUntil))?Number(t.rateLimitedUntil):0,lastAttemptAt:Number.isFinite(Number(t.lastAttemptAt))?Number(t.lastAttemptAt):0,lastRateLimitedAt:Number.isFinite(Number(t.lastRateLimitedAt))?Number(t.lastRateLimitedAt):0,...t.authFailure==="invalid_grant"?{authFailure:"invalid_grant"}:{},...r?{accountId:r}:{},...s?{clientId:s}:{},...Z(t.modelCooldowns)?{modelCooldowns:Z(t.modelCooldowns)}:{}}}l(gt,"credential");function Z(t){if(!t||typeof t!="object"||Array.isArray(t))return;const a=Object.entries(t).filter(([e,n])=>e.trim()!==""&&Number.isFinite(Number(n))).map(([e,n])=>[e,Number(n)]);return a.length?Object.fromEntries(a):void 0}l(Z,"modelCooldowns");function F(t,a){if(!a.label?.trim())throw new Error(`${h(t)} subscription label cannot be empty`);const e=gt(a);if(!e)throw new Error(`Refusing to persist incomplete ${h(t)} subscription "${a.label.trim()}"; pool rows require both OAuth tokens.`);return e}l(F,"assertCredential");function v(t,a){const e=t.accountId?.trim(),n=a.accountId?.trim();return!!(e&&n&&e!==n)}l(v,"differentAccount");function p(t){return t.accountId?.trim()||(t.refresh.trim()?`refresh:${ht("sha256").update(t.refresh.trim()).digest("hex")}`:void 0)}l(p,"identity");function tt(t,a){const e=j(a);return e?{...t,clientId:e}:t}l(tt,"withClientId");function et(t,a,e){const n=e.refresh?.trim()??"",i=e.access?.trim()??"",r=Number(e.expires);if(!n||!i||!Number.isFinite(r))throw new Error(`${h(t)} subscription "${a}" returned an incomplete credential; the stored credential was left unchanged.`);return{refresh:n,access:i,expires:r}}l(et,"assertTokens");const at=1e4,It="15s",xt="55P03";class nt extends Error{static{l(this,"RefreshBusyError")}constructor(a,e){super(`${h(a)} subscription "${e}" ${At}; treating it as cooling for this call`),this.name="RefreshBusyError"}}class Nt extends Error{static{l(this,"RefreshTimeoutError")}constructor(a){super(`${h(a)} ${bt} ${at} ms`),this.name="RefreshTimeoutError"}}const it="id,label,label_key,position,last_attempt_at,last_rate_limited_at,rate_limited_until,auth_failure,refresh_sealed,access_sealed,expires,vendor_account_id,client_id,key_id",I=l((t,a,e,n)=>`model_accounts|${t}|${a}|${e}|${n}`,"aadOf");function E(t){return{refresh:t.refresh,access:t.access,expires:t.expires,...t.accountId?{accountId:t.accountId}:{},...t.clientId?{clientId:t.clientId}:{}}}l(E,"stored");function Ft(t,a){return{providerId:t,id:a.id,label:a.label,labelKey:a.label_key,position:a.position,lastAttemptAt:a.last_attempt_at,lastRateLimitedAt:a.last_rate_limited_at,rateLimitedUntil:a.rate_limited_until,...a.auth_failure?{authFailure:a.auth_failure}:{}}}l(Ft,"rowOf");function rt(t,a,e,n=[]){if(!e.refresh_sealed||!e.access_sealed||e.expires===null||!e.key_id)throw new Error(`managed ${a} account ${e.id} has no credential record`);const i=K(),r=X(e.refresh_sealed,e.key_id,i,I(t,a,e.id,"refresh")),s=X(e.access_sealed,e.key_id,i,I(t,a,e.id,"access")),o=Ft(a,e),c={label:o.label,refresh:r,access:s,expires:e.expires,rateLimitedUntil:o.authFailure||!o.lastRateLimitedAt?o.rateLimitedUntil:Math.min(o.rateLimitedUntil,o.lastRateLimitedAt+B),lastAttemptAt:o.lastAttemptAt,lastRateLimitedAt:o.lastRateLimitedAt,...o.authFailure?{authFailure:o.authFailure}:{},...e.vendor_account_id?{accountId:e.vendor_account_id}:{},...e.client_id?{clientId:e.client_id}:{},...n.length?{modelCooldowns:Object.fromEntries(n.map(d=>[d.family,d.lastRateLimitedAt?Math.min(d.rateLimitedUntil,d.lastRateLimitedAt+B):d.rateLimitedUntil]))}:{}};return{row:o,entry:c}}l(rt,"toPublic");async function S(t,a,e){const n=new Map,i=await t.prepare("SELECT account_id,family,rate_limited_until,last_rate_limited_at FROM model_account_cooldowns WHERE person=? AND provider_id=? ORDER BY family").all(a,e);for(const r of i){const s=n.get(r.account_id)??[];s.push({family:r.family,rateLimitedUntil:r.rate_limited_until,lastRateLimitedAt:r.last_rate_limited_at}),n.set(r.account_id,s)}return n}l(S,"loadCooldowns");async function k(t,a,e,n=!1){const i=await t.prepare(`SELECT ${it} FROM model_accounts WHERE person=? AND provider_id=? ORDER BY position${n?" FOR UPDATE":""}`).all(a,e),r=await S(t,a,e);return i.map(s=>rt(a,e,s,r.get(s.id)))}l(k,"loadPool");async function st(t,a,e,n){const i=n.trim().toLowerCase(),r=Number.parseInt(i,10),s=Number.isFinite(r)&&String(r)===i&&r>=1,o=await t.prepare(`SELECT ${it} FROM model_accounts WHERE person=? AND provider_id=? AND ${s?"position=?":"label_key=?"} FOR UPDATE`).get(a,e,s?r-1:i);if(o)return rt(a,e,o,(await S(t,a,e)).get(o.id))}l(st,"lockedAccount");async function T(t){await t.exec(`SET LOCAL lock_timeout = '${It}'`)}l(T,"setLockTimeout");async function L(t,a){const e=await y();return N(async n=>(await T(n),await n.prepare("SELECT pg_advisory_xact_lock(hashtext(?))").get(`model_accounts|${e}|${t}`),a({db:n,person:e,rows:await k(n,e,t,!0)})))}l(L,"locked");async function C(t,a,e,n,i){const r=K(),s=$(i.refresh,r,I(a,e,n.id,"refresh")),o=$(i.access,r,I(a,e,n.id,"access"));await t.prepare("INSERT INTO model_accounts(person,provider_id,id,label,label_key,position,last_attempt_at,last_rate_limited_at,rate_limited_until,auth_failure,refresh_sealed,access_sealed,expires,vendor_account_id,client_id,key_id) VALUES(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)").run(a,e,n.id,n.label,n.labelKey,n.position,n.lastAttemptAt,n.lastRateLimitedAt,n.rateLimitedUntil,n.authFailure??null,s.sealed,o.sealed,i.expires,i.accountId??null,i.clientId??null,s.keyId)}l(C,"insertAccount");async function M(t,a,e,n,i){const r=K(),s=$(i.refresh,r,I(a,e,n,"refresh")),o=$(i.access,r,I(a,e,n,"access"));await t.prepare("UPDATE model_accounts SET refresh_sealed=?,access_sealed=?,expires=?,vendor_account_id=?,client_id=?,key_id=? WHERE person=? AND provider_id=? AND id=?").run(s.sealed,o.sealed,i.expires,i.accountId??null,i.clientId??null,s.keyId,a,e,n)}l(M,"setCredential");async function b(t,a,e){await t.prepare("UPDATE model_accounts SET label=?,label_key=?,position=?,last_attempt_at=?,last_rate_limited_at=?,rate_limited_until=?,auth_failure=? WHERE person=? AND provider_id=? AND id=?").run(e.label,e.labelKey,e.position,e.lastAttemptAt,e.lastRateLimitedAt,e.rateLimitedUntil,e.authFailure??null,a,e.providerId,e.id)}l(b,"updateHealth");async function ot(t,a,e,n,i,r,s){await t.prepare("INSERT INTO model_account_cooldowns(person,provider_id,account_id,family,rate_limited_until,last_rate_limited_at) VALUES(?,?,?,?,?,?) ON CONFLICT(person,provider_id,account_id,family) DO UPDATE SET rate_limited_until=excluded.rate_limited_until,last_rate_limited_at=excluded.last_rate_limited_at").run(a,e,n,i,r,s)}l(ot,"upsertModelCooldown");async function U(t,a,e,n){n===void 0?await t.prepare("DELETE FROM model_account_cooldowns WHERE person=? AND provider_id=?").run(a,e):await t.prepare("DELETE FROM model_account_cooldowns WHERE person=? AND provider_id=? AND account_id=?").run(a,e,n)}l(U,"deleteModelCooldowns");const R=l(async({db:t,person:a},e)=>(await k(t,a,e)).map(({entry:n})=>n),"publicPool"),lt=l(t=>t?.code===xt,"lockWaitExpired");function ct(t,a){let e;return Promise.race([a,new Promise((n,i)=>{e=setTimeout(()=>i(new Nt(t)),at)})]).finally(()=>clearTimeout(e))}l(ct,"withExchangeTimeout");async function V(t){return(await St(t)).map(({entry:a})=>a)}l(V,"readSubscriptionPool");async function St(t){const a=await y();return(await k(await W(),a,t)).map(({row:e,entry:n})=>({id:e.id,entry:n}))}l(St,"readSubscriptionPoolRows");async function qt(t,a){return L(t,async e=>{const{db:n,person:i,rows:r}=e,s=a.map(d=>F(t,d)),o=s.map((d,u)=>({entry:d,id:r[u]?.row.id??x()})),c=await S(n,i,t);await n.prepare("DELETE FROM model_accounts WHERE person=? AND provider_id=?").run(i,t),await U(n,i,t);for(const[d,{entry:u,id:m}]of o.entries()){await C(n,i,t,{providerId:t,id:m,label:u.label,labelKey:_(u.label),position:d,lastAttemptAt:u.lastAttemptAt,lastRateLimitedAt:u.lastRateLimitedAt,rateLimitedUntil:u.rateLimitedUntil,...u.authFailure?{authFailure:u.authFailure}:{}},E(u));for(const[f,A]of Object.entries(u.modelCooldowns??{}))await ot(n,i,t,m,f,A,c.get(m)?.find(D=>D.family===f)?.lastRateLimitedAt??u.lastRateLimitedAt)}return s})}l(qt,"writeSubscriptionPool");function H(t,a){const e=a.trim().toLowerCase(),n=Number.parseInt(e,10);return Number.isFinite(n)&&String(n)===e&&n>=1&&n<=t.length?n-1:t.findIndex(({entry:i})=>_(i.label)===e)}l(H,"resolve");const P=l((t,a)=>new O(`This ${h(t)} account is already added as \u201C${a}\u201D \u2014 it shares the same quota, so a second slot adds no redundancy.`),"duplicateAccount");async function Tt(t,a){const e=F(t,a);return L(t,async n=>{const{db:i,person:r,rows:s}=n;if(s.some(({entry:d})=>_(d.label)===_(e.label)))throw new O(`${h(t)} subscription already exists: ${e.label}`);const o=p(e),c=s.find(({entry:d})=>p(d)===o);if(o&&c)throw P(t,c.entry.label);return await C(i,r,t,{providerId:t,id:x(),label:e.label,labelKey:_(e.label),position:s.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil,...e.authFailure?{authFailure:e.authFailure}:{}},E(e)),R(n,t)})}l(Tt,"addSubscription");async function Xt(t,a){const e=F(t,a);return(await V(t)).find(i=>_(i.label)===_(e.label))?Ut(t,e):Tt(t,e)}l(Xt,"upsertSubscription");async function Ut(t,a){const e=F(t,a);return L(t,async n=>{const{db:i,person:r,rows:s}=n,o=s.findIndex(({entry:f})=>_(f.label)===_(e.label)),c=s[o],d=s.find(({entry:f},A)=>A!==o&&p(f)===p(e));if(p(e)&&d)throw P(t,d.entry.label);if(!c)return await C(i,r,t,{providerId:t,id:x(),label:e.label,labelKey:_(e.label),position:s.length,lastAttemptAt:e.lastAttemptAt,lastRateLimitedAt:e.lastRateLimitedAt,rateLimitedUntil:e.rateLimitedUntil},E(e)),R(n,t);const u=c.row,m=e.lastRateLimitedAt>=u.lastRateLimitedAt;return await M(i,r,t,u.id,E(e)),await b(i,r,{...u,authFailure:void 0,label:e.label,labelKey:_(e.label),lastAttemptAt:Math.max(u.lastAttemptAt,e.lastAttemptAt),lastRateLimitedAt:m?e.lastRateLimitedAt:u.lastRateLimitedAt,rateLimitedUntil:m?e.rateLimitedUntil:u.rateLimitedUntil}),v(c.entry,e)&&await U(i,r,t,u.id),R(n,t)})}l(Ut,"upsertSubscriptionWithUniqueAccount");async function Yt(t,a,e){return L(t,async n=>{const{db:i,person:r,rows:s}=n,o=H(s,a);if(o<0)throw new Error(`Unknown ${h(t)} subscription: ${a}`);const c=e.trim();if(!c)throw new Error(`${h(t)} subscription label cannot be empty`);if(s.some((d,u)=>u!==o&&_(d.entry.label)===_(c)))throw new O(`${h(t)} subscription already exists: ${c}`);return await b(i,r,{...s[o].row,label:c,labelKey:_(c)}),R(n,t)})}l(Yt,"renameSubscription");async function G(t,a,e){return L(t,async n=>{const{db:i,person:r,rows:s}=n,o=a(s);if(o<0)throw new Error(`Unknown ${h(t)} subscription: ${e}`);const c=s[o].row;return await i.prepare("DELETE FROM model_accounts WHERE person=? AND provider_id=? AND id=?").run(r,t,c.id),await U(i,r,t,c.id),R(n,t)})}l(G,"remove");async function Dt(t,a){return G(t,e=>H(e,a),a)}l(Dt,"removeManagedAccount");async function Jt(t,a){return G(t,e=>e.findIndex(({row:n})=>n.id===a),a)}l(Jt,"removeManagedAccountById");async function Qt(t,a){return G(t,e=>H(e,a),a)}l(Qt,"removeSubscription");async function $t(t){return L(t,async({db:a,person:e,rows:n})=>(await a.prepare("DELETE FROM model_accounts WHERE person=? AND provider_id=?").run(e,t),await U(a,e,t),n.length))}l($t,"removeAllManagedAccounts");async function Zt(t,a){return a===void 0?(await $t(t),[]):Dt(t,a)}l(Zt,"removeManagedProvider");async function vt(t,a){return L(t,async e=>{const{db:n,person:i,rows:r}=e,s=H(r,a);if(s<0)throw new Error(`Unknown ${h(t)} subscription: ${a}`);const o=[r[s],...r.filter((c,d)=>d!==s)];for(const[c,d]of o.entries())await b(n,i,{...d.row,position:c});return R(e,t)})}l(vt,"promoteSubscription");async function z(t,a,e){const n=await y();return await N(async i=>{await T(i);const r=await st(i,n,t,a);if(!r)throw new Error(`Unknown ${h(t)} subscription: ${a}`);await e(i,n,r.row)}),V(t)}l(z,"healthWrite");async function te(t,a,e=Date.now()){return z(t,a,(n,i,r)=>b(n,i,{...r,lastAttemptAt:Math.max(r.lastAttemptAt,e)}))}l(te,"markSubscriptionAttempt");async function ee(t,a,e,n=Date.now(),i=Date.now(),r={kind:"account"}){return e=Math.min(Math.max(0,e),B),z(t,a,async(s,o,c)=>{if(r.kind==="account"){if(i<c.lastRateLimitedAt)return;await b(s,o,{...c,lastAttemptAt:Math.max(c.lastAttemptAt,n),lastRateLimitedAt:i,rateLimitedUntil:i+e});return}await b(s,o,{...c,lastAttemptAt:Math.max(c.lastAttemptAt,n)});const d=(await S(s,o,t)).get(c.id)?.find(u=>u.family===r.family);d&&i<d.lastRateLimitedAt||await ot(s,o,t,c.id,r.family,i+e,i)})}l(ee,"markSubscriptionRateLimited");async function ae(t,a,e=Date.now(),n){const i=wt(n);return z(t,a,async(r,s,o)=>{if(e>=o.lastRateLimitedAt&&await b(r,s,{...o,authFailure:void 0,lastAttemptAt:Math.max(o.lastAttemptAt,e),rateLimitedUntil:0}),i===void 0)return;const c=(await S(r,s,t)).get(o.id)?.find(d=>d.family===i);c&&e>=c.lastRateLimitedAt&&await r.prepare("DELETE FROM model_account_cooldowns WHERE person=? AND provider_id=? AND account_id=? AND family=?").run(s,t,o.id,i)})}l(ae,"markSubscriptionSuccess");async function ut(t,a,e){const n=Date.now();await b(t,a,{...e,authFailure:"invalid_grant",lastAttemptAt:Math.max(e.lastAttemptAt,n),rateLimitedUntil:Math.max(e.rateLimitedUntil,n+Rt)})}l(ut,"recordInvalidGrant");async function ne(t,a,e){const n=await y();let i;try{i=await N(async r=>{await T(r);const s=await st(r,n,t,a);if(!s)throw new Error(`${h(t)} subscription "${a}" no longer exists`);if(s.entry.expires>Date.now())return{entry:s.entry};if(s.row.authFailure)throw new Error(`${h(t)} subscription "${s.entry.label}" refresh refused with status=400 invalid_grant; it needs a new sign-in`);let o;try{o=await ct(t,e(s.entry.refresh,s.entry.clientId))}catch(d){if(!Y(d))throw d;return await ut(r,n,s.row),{refused:d}}const c=tt(et(t,s.entry.label,o),o.clientId??s.entry.clientId);return await M(r,n,t,s.row.id,E({...s.entry,...c})),{entry:{...s.entry,...c}}})}catch(r){throw lt(r)?new nt(t,a):r}if("refused"in i)throw i.refused;return i.entry}l(ne,"refreshSubscriptionCredential");async function ie(t,a,e){const n=await y();let i;try{i=await N(async r=>{await T(r);const s=await k(r,n,t,!0),o=new Set;let c;for(;o.size<s.length;){const d=a(s.filter(({entry:m})=>!o.has(m.label)).map(({entry:m})=>m));if(!d)break;const u=s.find(({entry:m})=>m.label===d.label);o.add(u.entry.label);try{const m=await ct(t,e(u.entry));if(!m)return{entry:u.entry};const f=tt(et(t,u.entry.label,m),m.clientId??u.entry.clientId);return await M(r,n,t,u.row.id,E({...u.entry,...f})),{entry:{...u.entry,...f}}}catch(m){if(!Y(m))throw m;c=m,await ut(r,n,u.row)}}return c?{refused:c}:{}})}catch(r){throw lt(r)?new nt(t,a([])?.label??t):r}if("refused"in i)throw i.refused;return i.entry}l(ie,"modifyElectedSubscription");async function Ot(t,a){const e=a.accountId?.trim(),n=a.email?.trim();if(t!==Lt)return{...e?{accountId:e}:{},...n?{email:n}:{}};try{const i=await fetch("https://api.anthropic.com/api/oauth/profile",{headers:{Authorization:`Bearer ${a.access}`,Accept:"application/json"},signal:AbortSignal.timeout(3e3)});if(!i.ok)return e?{accountId:e}:{};const r=await i.json(),s=typeof r.account?.uuid=="string"&&r.account.uuid.trim()?r.account.uuid.trim():void 0,o=typeof r.account?.email=="string"&&r.account.email.trim()?r.account.email.trim():void 0;return{...s?{accountId:s}:{},...o?{email:o}:{}}}catch{return e?{accountId:e}:{}}}l(Ot,"enrichManagedLoginIdentity");async function re(t,a,e){const n=await Ot(t,e);return L(t,async i=>{const{db:r,person:s,rows:o}=i,c=e.autoLabel?void 0:a?.trim(),d=p({refresh:e.refresh,accountId:n.accountId}),u=(c?o.find(({entry:w})=>_(w.label)===_(c)):void 0)??o.find(({entry:w})=>p(w)===d);let m=u?.entry.label??c;if(!m&&e.autoLabel){const w=n.email||a?.trim()||`Account ${o.length+1}`;m=w;for(let g=2;o.some(({entry:ft})=>_(ft.label)===_(m));g++)m=`${w} (${g})`}if(!m)throw new Error(`${h(t)} subscription label cannot be empty`);const f=F(t,{label:m,refresh:e.refresh,access:e.access,expires:e.expires,...n.accountId?{accountId:n.accountId}:{},...e.clientId?{clientId:e.clientId}:{},rateLimitedUntil:0,lastAttemptAt:Date.now(),lastRateLimitedAt:e.lastRateLimitedAt});if(!u){if(o.some(({entry:g})=>_(g.label)===_(f.label)))throw new O(`${h(t)} subscription already exists: ${f.label}`);const w=o.find(({entry:g})=>p(g)===p(f));if(p(f)&&w)throw P(t,w.entry.label);return await C(r,s,t,{providerId:t,id:x(),label:f.label,labelKey:_(f.label),position:o.length,lastAttemptAt:f.lastAttemptAt,lastRateLimitedAt:f.lastRateLimitedAt,rateLimitedUntil:f.rateLimitedUntil},E(f)),R(i,t)}const A=u.row,D=o.find(({entry:w})=>w.label!==u.entry.label&&p(w)===p(f));if(p(f)&&D)throw P(t,D.entry.label);const q=f.lastRateLimitedAt>=A.lastRateLimitedAt;return await M(r,s,t,A.id,E(f)),await b(r,s,{...A,authFailure:void 0,lastAttemptAt:Math.max(A.lastAttemptAt,f.lastAttemptAt),lastRateLimitedAt:q?f.lastRateLimitedAt:A.lastRateLimitedAt,rateLimitedUntil:q?0:A.rateLimitedUntil}),v(u.entry,f)&&await U(r,s,t,A.id),R(i,t)})}l(re,"commitManagedLogin");const dt=new Map;function mt(t){return{defaultFallbackStrength:Q(t?.default_fallback_strength)??J,revertWhenAvailable:t?.revert_when_available===void 0||t.revert_when_available===null?!0:!!t.revert_when_available}}l(mt,"rotationFromRow");async function kt(){const t=await y(),a=mt(await(await W()).prepare("SELECT default_fallback_strength,revert_when_available FROM model_settings WHERE person=?").get(t));return dt.set(t,a),a}l(kt,"loadRotationConfig"),yt(()=>Ct());async function Ct(){const t=pt();return t?t.rotation:kt()}l(Ct,"readRotationConfig");async function se(t){const a=await y(),e=await N(async n=>{await T(n),await n.prepare("INSERT INTO model_settings(person) VALUES(?) ON CONFLICT(person) DO NOTHING").run(a);const i=mt(await n.prepare("SELECT default_fallback_strength,revert_when_available FROM model_settings WHERE person=? FOR UPDATE").get(a)),r={defaultFallbackStrength:Q(t.defaultFallbackStrength)??i.defaultFallbackStrength??J,revertWhenAvailable:t.revertWhenAvailable??i.revertWhenAvailable??!0};return await n.prepare("UPDATE model_settings SET default_fallback_strength=?,revert_when_available=?,revision=revision+1 WHERE person=?").run(r.defaultFallbackStrength,r.revertWhenAvailable?1:0,a),r});return dt.set(a,e),e}l(se,"writeRotationConfig");async function oe(){const t=await y();return(await(await W()).prepare("INSERT INTO model_settings(person,openai_device_id) VALUES(?,?) ON CONFLICT(person) DO UPDATE SET openai_device_id=COALESCE(model_settings.openai_device_id,EXCLUDED.openai_device_id) RETURNING openai_device_id").get(t,x())).openai_device_id}l(oe,"openAIDeviceId");async function le(t,a=Date.now(),e){const n=await V(t),i=n.filter(s=>s.authFailure===void 0&&Et(s,e)<=a),r=h(t);return i.length===0?`${r} pool exhausted`:`${r} ${i[0]?.label??t} (${i.length}/${n.length} ready)`}l(le,"formatStatusLine");export{at as REFRESH_EXCHANGE_TIMEOUT_MS,nt as RefreshBusyError,Nt as RefreshTimeoutError,Tt as addSubscription,re as commitManagedLogin,Ot as enrichManagedLoginIdentity,le as formatStatusLine,C as insertAccount,kt as loadRotationConfig,te as markSubscriptionAttempt,ee as markSubscriptionRateLimited,ae as markSubscriptionSuccess,ie as modifyElectedSubscription,oe as openAIDeviceId,vt as promoteSubscription,Ct as readRotationConfig,V as readSubscriptionPool,St as readSubscriptionPoolRows,ne as refreshSubscriptionCredential,$t as removeAllManagedAccounts,Dt as removeManagedAccount,Jt as removeManagedAccountById,Zt as removeManagedProvider,Qt as removeSubscription,Yt as renameSubscription,ot as upsertModelCooldown,Xt as upsertSubscription,Ut as upsertSubscriptionWithUniqueAccount,se as writeRotationConfig,qt as writeSubscriptionPool};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var ce=Object.defineProperty;var u=(t,e)=>ce(t,"name",{value:e,configurable:!0});import{randomBytes as ue}from"node:crypto";import{claimNodeMail as le,acknowledgeNodeMail as fe}from"../../../core/canvas/deliveries.js";import{nodeMailEntry as me}from"../../../core/feed/inbox.js";import{enqueueNodeMail as D,cancelPendingNodeMail as pe}from"../../../core/feed/messages.js";import{reviveNode as L}from"../../../core/runtime/revive.js";import{BrokerUnreachableError as U}from"../../../core/runtime/broker-request.js";import{isBrokerLive as
|
|
2
|
-
`)[0].slice(0,120)}u(
|
|
1
|
+
var ce=Object.defineProperty;var u=(t,e)=>ce(t,"name",{value:e,configurable:!0});import{randomBytes as ue}from"node:crypto";import{claimNodeMail as le,acknowledgeNodeMail as fe}from"../../../core/canvas/deliveries.js";import{nodeMailEntry as me}from"../../../core/feed/inbox.js";import{enqueueNodeMail as D,cancelPendingNodeMail as pe}from"../../../core/feed/messages.js";import{assertRecordedCwdExists as ye,reviveNode as L}from"../../../core/runtime/revive.js";import{BrokerUnreachableError as U}from"../../../core/runtime/broker-request.js";import{isBrokerLive as O}from"../../../core/runtime/model-swap.js";import{deliverLive as we,interruptLive as he}from"../../../core/runtime/interactive-deliver.js";import{isProfilePaused as be}from"../../../core/profiles/manifest.js";import{getNode as C,withFreshTerminalGuard as ge}from"../../../core/canvas/canvas.js";import{getById as G,nodeObject as F,ownerForGrantee as ve}from"../../../core/graph/objects.js";import{recordActedOn as _e}from"../../../core/graph/edges.js";import{recordWatch as H}from"../../../core/graph/watches.js";import{publish as V}from"../../../core/graph/events.js";import{readerFor as K}from"../reader.js";import{canRead as ke}from"../../../core/graph/access.js";import{withCanvasWrite as k}from"../../../core/canvas/db.js";import{getPendingStructuredRequestForNode as Q}from"../../../core/canvas/structured-requests.js";import{consumeDeadlineOnWake as X}from"../../../core/feed/messages.js";import{assertNotFinalized as M,assertFinalizedForReopen as Se,commitReopenResident as E}from"../../../core/runtime/reopen.js";import{admitLegacyStructuredOutput as $e}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as Ne}from"../../../core/runtime/structured-output.js";import{appendSituationalContext as P,formatSituationalProse as je}from"../../../core/runtime/situational-context.js";import{formatDataCard as Y}from"../../../shared/generated-context.js";import{hasNoNaturalCycle as Ae}from"../../../core/runtime/revive-all.js";import{recordPendingParkActivity as qe}from"../../park-pending.js";import{wantsExecution as Oe}from"../../reconcilers/node-lifecycle/wants-execution.js";import{hasFreshGroundState as Ce}from"../../../core/runtime/revive.js";import{CrtrError as xe,notFound as x,usage as c}from"../../../core/errors.js";import{isStartRefusal as Re}from"../../../core/runtime/start-check.js";import{emitEvent as Fe}from"../../../core/events/emit.js";import{assertScope as Me}from"../../../core/scopes.js";import{InputError as I}from"../../../core/io.js";import{ApiError as Ee}from"../../../api/index.js";import{describeObject as Pe,stubOf as Ie}from"../../../core/peer/stubs.js";import{machineNameOf as Z}from"../../../core/peer/names.js";import{callerNode as Te,callerStub as Be,forwardVerb as ee,relayError as te,remoteStub as ze,unknownError as re,withMachine as ne}from"../../peer/forward.js";import{ownerOnly as We}from"../router.js";import{personId as Je}from"../../../core/canvas/person.js";const De=["critical","urgent","normal","deferred"];function oe(t,e){if(typeof t!="object"||t===null||Array.isArray(t))throw c(`${e} must be an object { kind, facts?, body? }`);const a=t,n=a.kind;if(typeof n!="string"||n.trim()==="")throw c(`${e}.kind is required`);if(!n.includes(":"))throw c(`${e}.kind must be namespaced (contain ':'): ${n}`);const r={kind:n},o=a.facts;if(o!==void 0){if(typeof o!="object"||o===null||Array.isArray(o))throw c(`${e}.facts must be an object of string or number values`);const d={};for(const[l,m]of Object.entries(o)){if(typeof m!="string"&&typeof m!="number")throw c(`${e}.facts.${l} must be a string or number`);d[l]=m}r.facts=d}const s=a.body;if(s!==void 0){if(typeof s!="string")throw c(`${e}.body must be a string`);r.body=s}return r}u(oe,"parseCardRequest");function ae(t,e){try{return Y(t.kind,t.facts??{},t.body??"")}catch(a){throw c(`${e}: ${a instanceof Error?a.message:String(a)}`)}}u(ae,"renderCard");function Le(t){if(typeof t!="object"||t===null)throw c("a message requires a JSON body { body, tier?, fresh? }");const e=t,a=e.body,n=e.fresh===!0,r=e.tier,o=e.situational_context,s=e.output_schema,d=typeof a=="string"&&a.trim()!=="",l=typeof o=="string"&&o.trim()!=="",m=typeof s=="string"&&s.trim()!=="",v=e.situational_card,S=e.context_cards,b=v===void 0?void 0:oe(v,"situational_card");if(S!==void 0&&!Array.isArray(S))throw c("context_cards must be an array of { kind, facts?, body? }");const p=S?.map((N,$)=>oe(N,`context_cards[${$}]`));if(b!==void 0&&typeof o=="string"&&o!=="")throw c("situational_card and situational_context are mutually exclusive");const h=b!==void 0||p!==void 0&&p.length>0;if(!n&&!d&&!l&&!m&&!h)throw c("a message requires a non-empty body (or fresh: true, situational_context, a runtime card, or output_schema)");if(n&&p!==void 0&&p.length>0)throw c("context_cards cannot ride a fresh revive (no inbox entry carries them)");if(r!==void 0&&!De.includes(r))throw c(`invalid tier: ${String(r)} (expected critical|urgent|normal|deferred)`);const f={body:typeof a=="string"?a:""};r!==void 0&&(f.tier=r),n&&(f.fresh=!0),e.reopen===!0&&(f.reopen=!0),typeof o=="string"&&(f.situational_context=o),b!==void 0&&(f.situational_card=b),p!==void 0&&(f.context_cards=p),typeof s=="string"&&(f.output_schema=s),typeof e.from=="string"&&(f.from=e.from);const y=e.delivery;if(y!==void 0&&y!=="interactive")throw c(`invalid delivery: ${String(y)} (expected interactive)`);if(y==="interactive"){if(n||f.situational_context!==void 0||f.output_schema!==void 0)throw c("interactive delivery supports a body, runtime cards, and reopen only (no fresh, situational_context, or output_schema)");if(!d)throw c("interactive delivery requires a non-empty body");if(f.tier==="deferred")throw c("interactive delivery cannot be deferred");f.delivery="interactive"}return f}u(Le,"parseSendBody");function Ue(t){let e;try{e=JSON.parse(t)}catch{throw c("output_schema must be a JSON schema string")}if(typeof e!="object"||e===null||Array.isArray(e))throw c("output_schema must be a JSON schema object");return e}u(Ue,"parseSchema");function Ge(t){return t.split(`
|
|
2
|
+
`)[0].slice(0,120)}u(Ge,"label");function ie(t,e){return e===null?"":Y("reopen-final-report",{report:`${t}/${e}`},"This node previously completed work. Read this final report before acting on the new instruction.")}u(ie,"previousFinalReportCard");async function He(t,e,a){if(a!==null&&a!=="human"&&(await G(t,a))?.type==="node"){const o=await F(t,a);return{actor:o,senderNode:o}}if(a==="human")return{actor:await ve(t,Je()),senderNode:null};const n=await K(t,e);return{actor:n.class==="person"?n.person:n.class==="app"?n.app:n.node,senderNode:n.class==="node"?n.node:null}}u(He,"messageActor");async function se(t,e,a,n,r,o){const s=await F(t,a),{actor:d,senderNode:l}=await He(t,e,n),m=r===null?{}:{pointer:r};await _e(t,d,s),l!==null&&l.id!==s.id&&await H(t,l,s,"message",{endsOn:o&&r!==null?`result:${r}`:"final"}),await V(t,{event:"messaged",object:s,actor:d,attrs:{},...m}),l!==null&&await V(t,{event:"sent",object:l,actor:l,attrs:{to:s.id},...m})}u(se,"recordMessage");function Ve(t,e){return new I({error:"deferred_no_natural_cycle",message:`${t} is ${e} with no natural next cycle ahead of it \u2014 a deferred message would never be delivered.`,next:"Use --tier normal, urgent, or critical to wake it now, or --reopen (with a body or --fresh) to re-task it first."})}u(Ve,"deferredNoNaturalCycle");async function Ke(t){if(!await Ce(t))throw new Ee(422,"unprocessable",`node ${t} has no goal/roadmap on disk \u2014 a fresh revive would resume amnesiac.`)}u(Ke,"assertRecoverableForFresh");function Qe(t,e){return t instanceof I?{error:t.payload.error,message:t.payload.message,next:t.payload.next,message_id:e}:t instanceof xe?{error:t.code,message:t.message,message_id:e}:Re(t)?{error:t.code,message:t.message,message_id:e}:{error:"wake_failed",message:"the target could not be woken; see the daemon log",message_id:e}}u(Qe,"wakeFailure");async function Xe(t,e){const a=typeof t.body=="object"&&t.body!==null&&!Array.isArray(t.body)?{...t.body}:t.body;typeof a=="object"&&a!==null&&delete a.from;const n=await ee(t,e,{method:"POST",path:`/v1/nodes/${encodeURIComponent(e)}/messages`,body:a});if(n.kind==="local")return null;if(n.kind==="unknown")throw re(e,n.unreachable);if(n.status>=400)throw te(n.status,n.body);return await k(async r=>{const o=await Te(r,t);if(o===null)return;const s=n.body?.object,d=await ze(r,e,"node",n.machine.id,s);await H(r,o,d,"message",{endsOn:"final"})}),{status:n.status,body:ne(n.body,n.machine)}}u(Xe,"forwardMessage");async function Ye(t){const e=await Ze(t);if(t.principal.class!=="forwarded"||typeof e.body!="object"||e.body===null)return e;const a=await k(async n=>{const r=await F(n,t.params.id);return await ke(n,await K(n,t),r)?await Pe(n,r):{id:r.id,type:r.type,kind:null,name:r.id,owner:null}});return{...e,body:{...e.body,object:a}}}u(Ye,"handleMessage");async function Ze(t){const e=t.params.id,a=await Xe(t,e);if(a!==null)return a;const n=await C(e);if(n===null)throw x(`unknown node: ${e}`,{received:e});const r=Le(t.body),o=r.tier??"normal",s=be(n.profile_id);r.reopen&&!s&&!O(n)&&await ye(e,n);const d=t.principal.class==="forwarded"?await k(async i=>(await Be(i,t))?.id??null):r.from??null;if(d!==null){const i=await C(d);i!==null&&Me(i,"crtr:act")}const l=d===null?null:await k(async i=>{const w=await G(i,d);return w===null?null:(await Ie(i,w))?.home_machine??null}),m=l===null?void 0:`${d} on ${Z(l)}`,v=t.principal.class==="broker"?t.principal.node:null,S=l===null?{}:{from_machine:Z(l)},b=r.body.trim()!=="",p=r.situational_card!==void 0?ae(r.situational_card,"situational_card"):r.situational_context!==void 0?je(r.situational_context.trim()):"",h=p!=="",f=(r.context_cards??[]).map((i,w)=>ae(i,`context_cards[${w}]`)),y=r.output_schema!==void 0&&r.output_schema.trim()!==""?Ue(r.output_schema):null;y!==null&&await Ne(y);let N=!1;const $=u(async i=>{if(!(y===null||N)){if(await Q(e)!==null)throw new I({error:"structured_request_conflict",message:`node ${e} already has a pending structured request`,next:"Wait for the current request to settle before requesting another structured result."});await $e(e,"oneoff",y,i),N=!0}},"ensureSchema");if(r.fresh){const i=r.reopen?await Se(e):null;r.reopen||await M(e),await Ke(e),await $(),h&&await P(e,p),r.reopen&&await E(e,i,v);const w=await L(e,{resume:!1,capacity:"refuse"});return{status:201,body:{node_id:e,delivered:!1,revived:w.launch!==void 0}}}r.delivery==="interactive"&&!r.reopen&&await M(e);let T=!1,_="";if(r.delivery==="interactive"&&r.reopen&&(_=ie(e,await E(e,void 0,v)),T=!0),r.delivery==="interactive"&&await $(),r.delivery==="interactive"&&!s&&!n.run_id&&O(n))try{return h&&await P(e,p),await we(e,r.body,{cards:[..._===""?[]:[_],...h?[p]:[],...f],origin:d==="human"?{type:"human"}:{type:"runtime",kind:"inbox",entries:[{...d===null?{}:{from:d},...m===void 0?{}:{fromName:m},kind:"message",tier:o}]}}),await k(async w=>await se(w,t,e,d,null,!1)),await X(e),{status:201,body:{node_id:e,delivered:!0,revived:!1,delivered_via:"engine"}}}catch(i){if(!(i instanceof U))throw i}const B=u(async()=>{r.reopen||await M(e);const i=ue(16).toString("hex"),w=u(async q=>await se(q,t,e,d,i,y!==null),"withinEnqueue");await $(i),h&&await P(e,p),r.reopen&&!T&&(_=ie(e,await E(e,void 0,v)));const R=[..._===""?[]:[_],...f],J=R.length>0?{cards:R}:{};if(b||y!==null){const q=b?r.body:`A one-off structured-output request has been granted. Submit a result matching the requested schema with the \`submit_result\` tool (\`request_id: "${(await Q(e))?.request_id??"<request-id>"}"\`) before you stop; after it is accepted, continue normally.`;return await D(e,{senderNodeId:d,...m===void 0?{}:{senderName:m},urgency:o,wake:1,kind:"message",messageId:i,withinEnqueue:w,label:Ge(q),bodyJson:{body:q,...S,...h?{situational:!0}:{},...J}})}return await D(e,{senderNodeId:d,...m===void 0?{}:{senderName:m},urgency:o,wake:1,kind:"message",messageId:i,withinEnqueue:w,label:h?"(ambient context updated)":"(context delivered)",bodyJson:{...h?{situational:!0}:{},situationalOnly:!0,...J}})},"deliverImmediate"),g=await u(async()=>{if(o==="deferred"){const i=await ge(e,Ae,B);if(i.kind==="missing")throw x(`unknown node: ${e}`,{received:e});if(i.kind==="terminal")throw Ve(e,i.status);return i.result}return await B()},"deliver")();g.urgency!=="deferred"&&await k(async()=>qe(e));const j=await C(e);if(j===null)throw x(`unknown node: ${e}`,{received:e});n.frozen_at!==null&&await X(e);let z=!1,W=!1,A;if((r.reopen||j.lifecycle==="terminal"||!await Oe(j))&&g.urgency!=="deferred"&&!s&&!O(j))try{const i=await L(e,{resume:!0,capacity:"freeze"});z=i.launch!==void 0,W=i.outcome==="frozen"}catch(i){A=Qe(i,g.messageId),Fe({level:"error",event:"message.wake_failed",node_id:e,error:i,fields:{message_id:g.messageId,error_code:A.error}})}return{status:201,body:{node_id:e,delivered:!0,revived:z,...W?{not_revived_reason:"capacity_frozen"}:{},...A===void 0?{}:{wake_failed:A},delivered_at:g.createdAt,...g.urgency===o?{}:{delivered_tier:g.urgency},...r.delivery==="interactive"?{delivered_via:"inbox"}:{}}}}u(Ze,"handleMessageHere");async function et(t){const e=t.params.id,a=await ee(t,e,{method:"POST",path:`/v1/nodes/${encodeURIComponent(e)}/interrupt`,body:t.body});if(a.kind==="unknown")throw re(e,a.unreachable);if(a.kind==="remote"){if(a.status>=400)throw te(a.status,a.body);return{status:a.status,body:ne(a.body,a.machine)}}const n=await C(e);if(n===null)throw x(`unknown node: ${e}`,{received:e});const r=await pe(e,{senderNodeId:"human",kind:"message"});let o=!1;if(O(n))try{o=await he(e)!=="idle"}catch(d){if(!(d instanceof U))throw d}return{status:200,body:{node_id:e,outcome:o?"aborted_turn":r.length>0?"canceled_pending":"idle",aborted_turn:o,canceled_pending:r.length}}}u(et,"handleInterrupt");function de(t){if(typeof t.body!="object"||t.body===null||Array.isArray(t.body))throw c("mail requires an object body");const e=t.body;if(typeof e.execution_id!="string"||e.execution_id.trim()==="")throw c("execution_id is required");return e}u(de,"mailBody");async function tt(t){const e=de(t),a=e.channel;if(a!=="wake"&&a!=="passive"&&a!=="deferred_run")throw c("channel must be wake, passive, or deferred_run");const n=await le(t.params.id,e.execution_id,a);return{status:200,body:{action:n.action,deliveries:n.deliveries.map(o=>({delivery_id:o.deliveryId,attempts:o.attempts,handoff:o.handoff,entry:{...me(o),seq:o.message.seq}}))}}}u(tt,"handleMailClaim");async function rt(t){const e=de(t);if(!Array.isArray(e.deliveries))throw c("deliveries must be an array");const a=e.deliveries.map(o=>{if(typeof o!="object"||o===null||Array.isArray(o))throw c("each delivery must be an object");const s=o;if(typeof s.delivery_id!="string"||s.delivery_id==="")throw c("delivery_id is required");if(!Number.isSafeInteger(s.attempts)||s.attempts<1)throw c("attempts must be a positive integer");if(s.disposition!=="acknowledged"&&s.disposition!=="released")throw c("disposition must be acknowledged or released");return{delivery_id:s.delivery_id,attempts:s.attempts,disposition:s.disposition}}),n=await fe(t.params.id,e.execution_id,a.map(o=>({deliveryId:o.delivery_id,attempts:o.attempts,disposition:o.disposition})));return{status:200,body:{action:n.action,results:n.results.map(o=>({delivery_id:o.deliveryId,outcome:o.outcome}))}}}u(rt,"handleMailAcknowledge");const Gt=We([{method:"POST",pattern:"/v1/nodes/:id/mail/claim",handler:tt},{method:"POST",pattern:"/v1/nodes/:id/mail/acknowledge",handler:rt}]),Ht=[{method:"POST",pattern:"/v1/nodes/:id/messages",scope:"crtr:act",handler:Ye},{method:"POST",pattern:"/v1/nodes/:id/interrupt",scope:"crtr:act",handler:et}];export{Gt as brokerMailRoutes,Ye as handleMessage,Ht as messageRoutes};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var $e=Object.defineProperty;var s=(e,n)=>$e(e,"name",{value:n,configurable:!0});import{envProfileId as Ne}from"../../../shared/env.js";import{pausedCanvasProfiles as Ce}from"../../../core/profiles/manifest.js";import{existsSync as P,realpathSync as ee,statSync as ne}from"node:fs";import{isAbsolute as K,resolve as D}from"node:path";import{appendSituationalContext as Ee,formatSituationalProse as Te}from"../../../core/runtime/situational-context.js";import{closeNode as Pe}from"../../../core/runtime/close.js";import{reviveNode as De}from"../../../core/runtime/revive.js";import{nowIso as x}from"../../../core/fs-utils.js";import{appPaidLaunch as Le,assertLaunchModelRegistered as V,forkNode as je,resolveForkSource as te,spawnChildPrepared as Me}from"../../../core/runtime/spawn.js";import{forkSourceNode as ie,newNodeId as re}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as oe,childrenOf as Ge,completeCreateRequest as ae,findCreateRequest as de,getNode as R,recordCreateRequestNode as Fe,reserveCreateRequest as se,reserveCreateRequestNode as Be,listNodes as Ke,recordRespawnAttempt as xe,subscribersOf as Ve,subscriptionsOf as le,updateNode as C}from"../../../core/canvas/canvas.js";import{armControllerWait as We}from"../../../core/canvas/waits.js";import{withCanvasWrite as W}from"../../../core/canvas/db.js";import{markNodeRead as ze}from"../../../core/canvas/recovery.js";import{nodeObject as Je}from"../../../core/graph/objects.js";import{recordActedOn as Ue}from"../../../core/graph/edges.js";import{publish as Ye}from"../../../core/graph/events.js";import{readerFor as He}from"../reader.js";import{relocateSessionCwd as Qe,unbindSession as Xe}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as Ze}from"../../../core/canvas/attention.js";import{isSafeNodeId as qe}from"../../../core/canvas/paths.js";import{contextDir as ce,nodeAgentDir as z}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as en,cronRefusalError as nn}from"../../cron/authority.js";import{cronBirthPlacement as tn}from"../../cron/armed-context.js";import{existsBeneath as rn,isAbsentOrRefused as on,isBeneathRefusal as an,readdirBeneath as dn}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as sn,readNodeSession as ln,readNodeSnapshot as cn,transcriptMarkdown as un}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as fn}from"../../../core/substrate/subject.js";import{reviveAll as pn}from"../../../core/runtime/revive-all.js";import{promoteAsync as mn,requestYieldAsync as wn,reshapeNodeAsync as J}from"../../../core/runtime/promote.js";import{recycleNode as hn}from"../../../core/runtime/recycle.js";import{relaunchRoot as yn}from"../../../core/runtime/reset.js";import{assertReopenGate as _n}from"../../../core/runtime/reopen.js";import{requireCurrentExecution as gn}from"./broker-recovery.js";import{readOutputRequest as bn}from"../../../core/runtime/output-result.js";import{writeYieldMessage as vn,readGoal as kn,captureGoalIfAbsent as Sn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as Rn,hasRoadmap as In}from"../../../core/runtime/roadmap.js";import{renameWindow as On}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as An,explicitModelIntent as $n,normalizeModel as Nn,readMergedLaunchConfigAsync as ue}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as Cn}from"../../../core/model-routes.js";import{persistDormantModel as En,setModelLive as Tn}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as fe}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as Pn}from"../../../core/runtime/broker-request.js";import{boundFleet as L}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as Dn}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as Ln}from"../../../core/runtime/structured-output.js";import{OUTCOME_PAYLOAD_MAX_BYTES as pe}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as jn}from"../../../core/human/action-binding.js";import{resolveHumanAction as Mn}from"../../../core/human-actions.js";import{parseDurationMs as Gn}from"../../../core/wake.js";import{claimWarmNode as Fn,refillWarmPool as me,resumeWarmClaim as Bn,warmPoolEnabled as Kn}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as U,isLaunchKind as xn,resolveLaunchTarget as Vn}from"../../../core/runtime/launch-target.js";import{fullName as Wn}from"../../../core/canvas/labels.js";import{reportsForNode as we}from"./reports.js";import{requireUsableProfile as zn}from"./profiles.js";import{assertProfileActive as Jn,loadExactProfileManifest as Un}from"../../../core/profiles/manifest.js";import{getCron as he}from"../../../core/canvas/crons.js";import{cronWakeOrigin as Yn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as Hn}from"../../control.js";import{notFound as E,usage as w}from"../../../core/errors.js";import{assertScope as Qn,validateScopes as ye}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as Xn,toNodeDetailDTO as Y,toNodeSummaryDTO as Zn,toReviveResultDTO as qn}from"../map.js";import{ApiError as p}from"../../../api/index.js";import{InputError as y}from"../../../core/io.js";import{actsAsPerson as j,canReadNode as $,mayOnNode as et,readableNodeIds as nt,resolvedScopes as tt}from"../router.js";import{forwardVerb as it,queryWithoutMachine as rt,relayError as ot,unknownError as at,withMachine as dt}from"../../peer/forward.js";import{fileRoot as st}from"../../../core/spaces/file-root.js";import{activeGrant as lt,payerOfGrant as ct}from"../../../core/grants/mirror.js";import{nodeTerminalGrant as ut}from"../../../core/grants/terminal.js";import{appRungForGrant as ft}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as pt}from"../../../core/model-routes.js";import{listProfileEnvNames as mt}from"../../../core/profiles/env-store.js";import{hasConfiguredProviderCredential as wt,NO_PROVIDER_CREDENTIAL_MESSAGE as _e}from"../../../core/runtime/provider-credential-gate.js";import{filterAsync as ht,mapAsync as ge}from"../../../core/async-array.js";async function m(e){const n=await R(e);if(n===null)throw E(`unknown node: ${e}`,{received:e});return n}s(m,"requireMeta");async function H(e){return{subscribesTo:await le(e),subscribers:await Ve(e),children:await Ge(e)}}s(H,"edgesFor");async function b(e){const n=await m(e);return await Y(n,await H(e))}s(b,"detailOf");async function yt(e){let n=(await we(e)).length;try{n+=dn(await z(e),await ce(e)).length}catch(t){if(!on(t))throw t}return n}s(yt,"countFiles");function _t(e){if(typeof e!="object"||e===null)throw w("a node create requires a JSON body");const n=e;if(n.kind!==void 0&&(typeof n.kind!="string"||n.kind.trim()===""))throw w("kind must be a non-empty string when provided");if(n.description!==void 0&&(typeof n.description!="string"||n.description.trim()===""))throw w("description must be a non-empty string when provided");if(n.creator!==void 0&&(typeof n.creator!="string"||n.creator.trim()===""))throw w("creator must be a non-empty node id when provided");if(n.scopes!==void 0&&ye(n.scopes),n.isolated!==void 0&&typeof n.isolated!="boolean")throw new p(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const t=n.root_lifecycle;if(t!==void 0&&t!=="resident"&&t!=="terminal")throw w("root_lifecycle must be 'resident' or 'terminal'");if(n.request_key!==void 0&&(typeof n.request_key!="string"||n.request_key.trim()===""||n.request_key.length>128))throw w("request_key must be a non-empty string of at most 128 characters when provided");return n}s(_t,"parseCreateBody");function gt(e){if(e===void 0)return;const n=Gn(e),t=n===null?null:new Date(Date.now()+n);if(n===null||!Number.isFinite(n)||n<=0||t===null||!Number.isFinite(t.getTime()))throw new p(422,"invalid_deadline","`deadline` must be a positive representable duration");return t.toISOString()}s(gt,"parseDeadline");function bt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new p(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!jn.test(e.action))throw new p(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let n;try{n=JSON.stringify(e.payload)}catch{throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(n===void 0)throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(n,"utf8")>pe)throw new p(413,"payload_too_large",`serialized payload exceeds ${pe} bytes`)}return e}}s(bt,"parseOutcomeDelivery");function vt(e,n){const t=Mn(e.action,n);if(!("kind"in t))return{actionName:e.action,argv:t.argv,cwd:t.cwd,configOrigin:t.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw t.kind==="unknown_action"?new p(422,"unknown_action",`no action named ${e.action} is declared from ${n}`):new p(422,"invalid_action",`${e.action} is declared in ${t.configOrigin} but unusable: ${t.reason}`,{reason:t.reason,configOrigin:t.configOrigin})}s(vt,"resolveOutcomeDelivery");function kt(e,n,t){const r={kind:e.kind,cwd:t,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),n!==void 0&&(r.parent=n),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=D(e.pin_cwd??e.cwd??t)),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}s(kt,"buildRecipe");function St(e,n,t){return!Kn()||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:n,profileId:t,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}s(St,"warmRequestFor");import{resolveCreateKind as Ar}from"../../../core/runtime/launch-target.js";function be(e){const n=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Cn(e.model,n,e.modelExact===!0)}s(be,"requestFromLaunch");function Rt(e,n){if(n===null)return e;if(e.scopes===void 0)return{...e,scopes:[...n]};const t=e.scopes.filter(r=>!O(n,r));if(t.length===0)return e;throw new p(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${t.join(", ")}`,{scopes:t,ceiling:n})}s(Rt,"withinCeiling");async function ve(e,n,t){const r=(await An(n.kind,n.mode,{lifecycle:n.lifecycle,hasManager:e.parent!==null,model:n.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await V(be(r),{cwd:e.cwd,profileId:e.profile_id??null},t)}s(ve,"assertNodeModelChangeRegistered");async function ke(e,n){const t=e.principal;if(t.class!=="broker"&&t.class!=="cron")return;const r=st({app:t.app,resolved:await tt(t),launched:t.scopes},n,"read");if("root"in r)return;const i="missing"in r?r.missing:null;throw new p(403,"scope_missing",i?`the child's directory ${n} needs missing scope ${i}`:`no permission of this run names the child's directory ${n}`,void 0,void 0,i?{scope:i}:void 0)}s(ke,"assertCallerReaches");const Q=new Map;async function It(e,n={},t={}){const r=Rt(_t(e.body),e.ceiling);if(e.principal.class==="broker"){const d=e.principal;if(r.prefer_warm===!0&&d.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const o=await m(r.parent);if(o.grantee!==d.app)throw new p(403,"other_app_run","cannot create a child under another app's node");if(!await $(d,o.grantee??"app:terminal",r.parent))throw E(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==d.node)throw new p(403,"other_app_run","cannot create for another node");if(r.fork_from!==void 0){let o=null;try{o=await ie(await te(r.fork_from))}catch{}if(o?.grantee!==d.app||!await $(d,o.grantee,o.node_id))throw new p(403,"other_app_run","cannot fork another app's conversation")}r.creator=d.node}if(e.principal.class==="person"&&e.principal.sub!==void 0){const d=r.fork_from===void 0?null:await ie(await te(r.fork_from)).catch(()=>null);for(const o of[r.parent,r.creator,d?.node_id])if(o!=null&&await R(o)!==null&&!await et(e.principal,"edit",o))throw E(`unknown node: ${o}`,{received:o})}if(e.principal.class==="cron"){const d=e.principal;for(const l of["parent","creator","fork_from","node_id"])if(r[l]!=null)throw new p(403,"permission_error",`a cron cannot set ${l} on a node it starts`);r.prefer_warm=!1,r.node_id=await re(),d.isolated&&(r.isolated=!0,r.cwd=await z(r.node_id,d.app));const o=await en({grantee:d.app,sub:d.sub,grant_id:d.grant,scopes:d.scopes,from_exec:d.from_exec},{profile:r.profile,cwd:r.cwd,pin_cwd:r.pin_cwd,kind:r.kind,model:r.model,mode:r.mode});if(!o.allowed)throw nn(o);if(r.scopes!==void 0){const l=r.scopes.find(f=>!O(o.effectiveScopes,f)||!O(d.scopes,f));if(l!==void 0)throw new p(403,"scope_missing",`scope ${l} is not held by this cron`,void 0,void 0,{scope:l})}else d.scopes!==null&&(r.scopes=[...d.scopes])}r.creator!==void 0&&Qn(await m(r.creator),"crtr:act");const i=r.request_key?.trim();if(i===void 0||r.node_id!==void 0&&qe(r.node_id)&&await R(r.node_id)!==null&&(await de(i))?.nodeId!==r.node_id)return M(e,r,n,t);const a=Q.get(i);if(a!==void 0)return a;const c=At(e,r,i,n,t);Q.set(i,c);try{return await c}finally{Q.delete(i)}}s(It,"handleCreate");const Se="create_request_in_progress";async function Ot(e,n,t){const r=Date.now()+1e4;for(;t!==null;){const i=await R(t);if(i!==null){if(!j(e.principal)&&!await $(e.principal,i.grantee??"app:terminal",t))throw new p(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:await b(t)}}if(Date.now()>=r||(await de(n))?.nodeId!==t)break;await new Promise(a=>setTimeout(a,100))}throw new p(409,Se,"another create with this request_key is in progress; retry it")}s(Ot,"awaitForeignCreate");async function At(e,n,t,r,i){const a=await se(t);if(a.nodeId!==null&&await R(a.nodeId)!==null){if(a.state!=="warm_claimed"){const c=await R(a.nodeId);if(!j(e.principal)&&!await $(e.principal,c.grantee??"app:terminal",a.nodeId))throw new p(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:await b(a.nodeId)}}return M(e,n,r,i,a)}try{return await M(e,n,r,i,a)}catch(c){if(c instanceof p&&c.code===Se)throw c;const d=await se(t);throw(d.nodeId===null||await R(d.nodeId)===null)&&await oe(t,d.nodeId),c}}s(At,"handleKeyedCreateRequest");async function M(e,n,t,r,i=void 0){const a=r.deadlineAt??gt(n.deadline),c=bt(n.outcome_delivery),d=e.principal.class==="cron"?await tn({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:e.principal.kind==="exec"?null:(await he(e.principal.cron))?.created_by??null},n.node_id):null;d!==null&&(n.root=d.root===!0);const o=d?.parent??n.parent??void 0;if(o==null&&n.root!==!0)throw w("a node create requires a parent (or root: true for an independent root)");let l=null;if(n.output_schema!==void 0){try{l=JSON.parse(n.output_schema)}catch{throw w("output_schema must be a JSON schema string")}if(l===null||typeof l!="object"||Array.isArray(l))throw w("output_schema must be a JSON schema object");await Ln(l)}const{profileId:f,kind:h,cwd:u,launch:S}=await Vn(n,{validateKind:Ae});await ke(e,u),n.worktree!==void 0&&await ke(e,D(n.pin_cwd??n.cwd??u));const _={...n,kind:h},v=c===void 0?void 0:vt(c,u),Z=("grant"in e.principal?e.principal.grant:null)??(o==null?null:(await R(o))?.grant_id??null);if(await V(be(await Le(S,Z,n.model)),{cwd:u,profileId:f},t.modelRegistry),await ct(Z)!=="app"&&!await wt(f===null?[]:await mt(f)))throw new p(412,"no_provider_credential",_e,{error:"no_provider_credential",message:_e,next:"The person running this runtime logs a provider in with `crtr sys setup`, or stores a provider key on the profile."});let F=null;{const A=i===void 0||i.nodeId===null||i.state==="warm_claimed"?St(_,u,f):null,B=l===null&&r.beforeBrokerLaunch===void 0?void 0:async g=>{l!==null&&await Dn(g,"terminal",l),r.beforeBrokerLaunch?.(g)};if(i?.state==="warm_claimed"&&i.nodeId!==null){const g=A===null?null:await Bn(A,i.nodeId,B);if(g===null)throw await oe(i.requestKey,i.nodeId),new p(503,"create_resume_failed",`could not resume warm claim ${i.nodeId}; retry the create`);return await ae(i.requestKey,g),{status:201,body:await b(g)}}if(A!==null){const g=await Fn(A,{...a===void 0?{}:{deadlineAt:a},...v===void 0?{}:{outcomeDelivery:v},...i===void 0?{}:{requestKey:i.requestKey}},B);if(g!==null)return i!==void 0&&await ae(i.requestKey,g),me(A),{status:201,body:await b(g)};F=A}const T=i?.nodeId??n.node_id??(i===void 0?void 0:await re());if(i!==void 0&&i.nodeId===null){const g=await Be(i.requestKey,T);if(g!==T)return await Ot(e,i.requestKey,g)}const I=kt(T===void 0?_:{..._,node_id:T},o,u);d!==null&&(d.rootLifecycle!==void 0&&(I.rootLifecycle=d.rootLifecycle),d.scopes!==void 0&&_.scopes===void 0&&(I.scopes=d.scopes),d.run!==void 0&&(I.run=d.run),d.withinCreate!==void 0&&(I.withinCreate=d.withinCreate)),a!==void 0&&(I.deadlineAt=a),v!==void 0&&(I.outcomeDelivery=v),I.readiness=n.root===!0?"await":"launch";const q=await Me(I,B,()=>{F!==null&&me(F)});return i!==void 0&&await Fe(i.requestKey,q.node.node_id),{status:201,body:await b(q.node.node_id)}}}s(M,"handleCreateRequest");function k(e,n){const t=e.query.getAll(n);if(t.length>1)throw w(`${n} must appear at most once`);return t[0]}s(k,"singleQueryValue");function X(e,n){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw w(`${n} must be true or false`)}}s(X,"optionalBoolean");function G(e,n,t){if(e!==void 0){if(t.includes(e))return e;throw w(`${n} must be one of: ${t.join(", ")}`)}}s(G,"oneOf");function $t(e){const n=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","under_inclusive","hanging","include"]);for(const[_]of e.query)if(!n.has(_))throw w(`unknown nodes query parameter: ${_}`);const t=G(k(e,"status"),"status",["active","idle","done","dead","canceled"]),r=G(k(e,"lifecycle"),"lifecycle",["terminal","resident"]),i=k(e,"kind"),a=G(k(e,"mode"),"mode",["base","orchestrator"]),c=k(e,"profile_id"),d=k(e,"profile_prefix"),o=k(e,"parent"),l=X(k(e,"top_level"),"top_level"),f=k(e,"under"),h=X(k(e,"under_inclusive"),"under_inclusive"),u=X(k(e,"hanging"),"hanging"),S=G(k(e,"include"),"include",["activity"]);if(o!==void 0&&l===!0)throw w("parent and top_level=true cannot be combined");return{...t!==void 0?{status:t}:{},...r!==void 0?{lifecycle:r}:{},...i!==void 0?{kind:i}:{},...a!==void 0?{mode:a}:{},...c!==void 0?{profile_id:c}:{},...d!==void 0?{profile_prefix:d}:{},...o!==void 0?{parent:o}:{},...l!==void 0?{top_level:l}:{},...f!==void 0?{under:f}:{},...h!==void 0?{under_inclusive:h}:{},...u!==void 0?{hanging:u}:{},...S!==void 0?{include:S}:{}}}s($t,"parseListQuery");async function Nt(e){const n=$t(e);let t=await Ke({...n.status!==void 0?{status:n.status}:{},...n.lifecycle!==void 0?{lifecycle:n.lifecycle}:{},...n.kind!==void 0?{kind:n.kind}:{},...n.mode!==void 0?{mode:n.mode}:{},...n.profile_id!==void 0?{profileId:n.profile_id}:{},...n.profile_prefix!==void 0?{profilePrefix:n.profile_prefix}:{},...n.parent!==void 0?{parent:n.parent}:{},...n.top_level===!0?{topLevel:!0}:{},...n.under!==void 0?{under:n.under}:{},...n.under_inclusive===!0?{underInclusive:!0}:{},...n.hanging===!0?{hanging:!0}:{}});const r=await nt(e.principal);r!==null&&(t=t.filter(d=>r.has(d.node_id)));const i=n.include==="activity"?await Ze(t.map(d=>d.node_id)):null,a=t.length>0?Ce():new Set;return{status:200,body:await ge(t,async d=>{const o=await Zn(d,d.profile_id!==null&&a.has(d.profile_id));if(i!==null){const l=await we(d.node_id);o.activity={latest_report:l[0]??null,final_report:d.final_report===null?null:l.find(f=>f.name===d.final_report)??null,pending_human_count:i[d.node_id]??0}}return o})}}s(Nt,"handleList");async function Ct(e){const n=e.params.id,t=await it(e,n,{method:"GET",path:`/v1/nodes/${encodeURIComponent(n)}`,query:rt(e)});if(t.kind==="unknown")throw at(n,t.unreachable);if(t.kind==="remote"){if(t.status>=400)throw ot(t.status,t.body);return{status:t.status,body:dt(t.body,t.machine)}}return await m(n),{status:200,body:await b(n)}}s(Ct,"handleDetail");async function Et(e){const n=e.params.id;await m(n);const t=await cn(n);return{status:200,body:{node_id:n,snapshot:{messages:t.snapshot.messages,...t.snapshot.messageIds===void 0?{}:{messageIds:t.snapshot.messageIds},messageVisibility:t.snapshot.messageVisibility,turnVisibility:t.snapshot.turnVisibility,stats:t.snapshot.stats,state:t.snapshot.state,display:t.snapshot.display,...t.snapshot.queued===void 0?{}:{queued:t.snapshot.queued},...t.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:t.snapshot.toolGroupSummaries},...t.snapshot.turnReplies===void 0?{}:{turnReplies:t.snapshot.turnReplies},...t.snapshot.workingActivity===void 0?{}:{workingActivity:t.snapshot.workingActivity}},commands:t.commands.map(i=>({name:i.name,description:i.description,source:i.source})),captured_at:x()}}}s(Et,"handleSnapshot");async function Tt(e){const n=e.params.id,t=await fn(n);if(t===null)throw E(`unknown node: ${n}`,{received:n});return{status:200,body:t}}s(Tt,"handleSubject");function Pt(e){for(const[a]of e.query)if(a!=="cursor"&&a!=="limit")throw w(`unknown messages query parameter: ${a}`);const n=e.query.getAll("cursor"),t=e.query.getAll("limit");if(n.length>1)throw w("cursor must appear at most once");if(t.length>1)throw w("limit must appear at most once");if(t.length===0)return n.length===0?{}:{cursor:n[0]};const r=t[0],i=Number(r);if(!Number.isSafeInteger(i)||r==="")throw w("limit must be an integer from 1 through 500");return n.length===0?{limit:i}:{cursor:n[0],limit:i}}s(Pt,"parseMessagesQuery");async function Dt(e){const n=e.params.id,t=await sn(n,Pt(e));return{status:200,body:{node_id:n,messages:t.messages,...t.messageIds===void 0?{}:{message_ids:t.messageIds},message_visibility:t.messageVisibility,next_cursor:t.nextCursor,captured_at:x()}}}s(Dt,"handleMessages");async function Lt(e){const n=e.params.id;await m(n);const t=await ln(n);return{status:200,body:{node_id:n,session_file:t.sessionFile,session_jsonl:t.sessionJsonl,system_prompt:t.systemPrompt,captured_at:x()}}}s(Lt,"handleSession");async function jt(e){const n=e.params.id;return await m(n),{status:200,body:{node_id:n,markdown:await un(n)}}}s(jt,"handleTranscript");async function Mt(e){const n=e.params.id;await m(n);const t=s(async(i,a)=>({node_id:i,label:(await R(i))?.name??i,dir:await ce(i),self:a,files:await yt(i)}),"root"),r=await ht([await t(n,!0),...await ge(await le(n),async i=>await t(i.node_id,!1))],async i=>await Gt(i.node_id,i.dir)||i.files>0);return{status:200,body:{node_id:n,roots:r}}}s(Mt,"handleContext");async function Gt(e,n){try{return rn(await z(e),n)}catch(t){if(an(t))return!1;throw t}}s(Gt,"hasDir");async function Ft(e){const n=await m(e.params.id),t=e.principal.class==="broker"?e.principal.scopes:e.ceiling,r=t===null?void 0:n.scopes==null?[...t]:[...new Set([...n.scopes.filter(a=>O(t,a)),...t.filter(a=>O(n.scopes,a))])],i=await je(n.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:await b(i.node.node_id)}}s(Ft,"handleFork");const Bt=1e4;async function Kt(e){const n=e.params.id;await m(n);const t=e.body,r=t?.resume??!0,i=t?.reopen??!1;await _n(n,i,e.principal.class==="broker"?e.principal.node:null);const a=!r&&t?.cron_id!==void 0?await he(t.cron_id):null,c=await De(n,{resume:r,capacity:"refuse",...a!==null?{wakeReason:await Yn(a,"schedule_revive")}:{}});c.outcome!=="already-live"&&await xe(n,{failures:0,notBefore:null});const d=(await R(n))?.status??"active",o=(c.launch??L().get(n)?.handle)?.exited,l=c.outcome!=="frozen"&&await fe(n,o,Bt);return{status:200,body:qn(n,c,d,l)}}s(Kt,"handleRevive");async function xt(e){const n=e.params.id;return{status:200,body:{newNodeId:(await yn(n))?.newNodeId??null}}}s(xt,"handleRelaunchRoot");async function Vt(e){const n=e.params.id;await m(n);const t=e.body;if(t?.caller_pid!==void 0&&(!Number.isInteger(t.caller_pid)||t.caller_pid<=0))throw w("caller_pid must be a positive integer when provided");const r=Hn(),i=new Promise(c=>{e.res.once("close",()=>c())}),a=await Pe(n,{teardownAfter:i,rootEvent:t?.finish===!0?"finish":"cancel",callerPid:t?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...r===null?{}:{registerDetached:r.registerDetached}});return{status:200,body:Xn(a)}}s(Vt,"handleClose");async function Wt(e){if(!j(e.principal))throw new p(403,"permission_error","only the person marks a conversation read");const n=e.params.id;return await m(n),await ze(n),{status:204}}s(Wt,"handleMarkRead");async function zt(e){const n=e.params.id;await m(n);const t=await hn(n);return{status:200,body:{recycled:t.recycled,finalized:t.finalized,new_root:t.newRoot,delivered:t.delivered}}}s(zt,"handleRecycle");async function Jt(e){const n=e.params.id;return await m(n),await J(n,{lifecycle:"terminal"}),await N(e,n,["lifecycle"]),{status:200,body:await b(n)}}s(Jt,"handleDemote");async function Ut(e,n={}){const t=e.params.id,r=await m(t),i=e.body??{};i.kind!==void 0&&await U(i.kind,r.cwd,r.profile_id??null),i.model!==void 0&&await ve(r,{kind:i.kind??r.kind,mode:"orchestrator",lifecycle:i.resident===!0?"resident":r.lifecycle,model:i.model},n.modelRegistry);const a=await mn(t,{...i.kind!==void 0?{kind:i.kind}:{},...i.resident===!0?{resident:!0}:{},...i.model!==void 0?{model:i.model}:{}});await N(e,t,["mode",...i.kind!==void 0?["kind"]:[],...i.resident===!0?["lifecycle"]:[],...i.model!==void 0?["model"]:[]]);const c=await Y(a.meta,await H(t));return c.roadmap_written=a.roadmapWritten,c.roadmap_ref=a.roadmapRef,c.goal_path=a.goalPath,{status:200,body:c}}s(Ut,"handlePromote");async function Yt(e){const n=e.params.id;return await m(n),{status:200,body:{request:await bn(n)}}}s(Yt,"handleBrokerStructuredRequest");async function Ht(e){const n=e.params.id,t=e.body??{};if(await gn(n,t.expected_execution_id),typeof t.text!="string")throw new p(400,"invalid_request","text must be a string");return await m(n),{status:200,body:{captured:await Sn(n,t.text)}}}s(Ht,"handleBrokerGoal");async function Qt(e,n={}){const t=e.params.id,r=await m(t),i=e.body??{};i.kind!==void 0&&await U(i.kind,r.cwd,r.profile_id??null),i.model!==void 0&&await ve(r,{kind:i.kind??r.kind,mode:i.promote===!0?"orchestrator":r.mode,lifecycle:r.lifecycle,model:i.model},n.modelRegistry);const a=i.note??"Refresh: continue against your roadmap or goal.";await vn(t,a);const c=await wn(t,{...i.promote===!0?{promote:!0}:{},...i.kind!==void 0?{kind:i.kind}:{},...i.model!==void 0?{model:i.model}:{}});return{status:200,body:await Y(c.meta,await H(t))}}s(Qt,"handleYield");async function Xt(e){const n=e.params.id;await m(n);const t=e.body;if(t===void 0||typeof t.controller!="string"||t.controller.trim()==="")throw w("a wait requires a controller node id");const r=await R(t.controller);if(r===null)throw E(`unknown controller: ${t.controller}`,{received:t.controller});if(r.status!=="active"&&r.status!=="idle")throw new p(422,"unprocessable",`controller ${t.controller} is ${r.status}`);return await We(n,t.controller),{status:200,body:await b(n)}}s(Xt,"handleWait");async function Zt(e){const n=e.principal,t=await pn(n.class==="broker"?async i=>i.grantee===n.app&&await $(n,i.grantee,i.node_id):n.class==="person"&&!j(n)?async i=>await $(n,i.grantee??"app:terminal",i.node_id):void 0);return{status:200,body:{revived:[...t.revived],failed:[...t.failed],frozen:[...t.frozen]}}}s(Zt,"handleReviveAll");const qt=new Set(["interrupt","steer","after-turn","next-turn"]);function ei(e){if(e===null)return null;const n=s(r=>{throw new y({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 n("listen must be an object or null");const t=Object.entries(e);if(t.length===0)return n("listen must name at least one level");for(const[r,i]of t)/^(?:[1-9]|10)$/.test(r)||n(`listen level must be 1..10: ${r}`),(typeof i!="string"||!qt.has(i))&&n(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(i)}`);return JSON.stringify(Object.fromEntries(t))}s(ei,"listenJson");async function N(e,n,t,r){t.length===0&&r===void 0||await W(async i=>{if(r?.(i),t.length===0)return;const a=await Je(i,n),c=await He(i,e),d=c.class==="person"?c.person:c.class==="app"?c.app:c.node;await Ue(i,d,a),await Ye(i,{event:"configured",object:a,actor:d,attrs:{changed:t.join(",")}})})}s(N,"recordConfigured");function Re(e){const n=L().get(e);if(n===void 0)return!1;try{return process.kill(n.pid,"SIGTERM"),!0}catch{return!1}}s(Re,"restartLiveBroker");function Ie(e,n){try{return ee(e)===ee(n)}catch{return!1}}s(Ie,"sameDirectory");async function ni(e,n={}){const t=e.params.id,r=e.body;let i;if(r===void 0)i={};else if(typeof r=="object"&&r!==null&&!Array.isArray(r))i=r;else throw new y({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(i.profile!==void 0){if(typeof i.profile!="string"||i.profile==="")throw new y({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:i.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(i).some(h=>h!=="profile"&&h!=="restart"&&i[h]!==void 0))throw new y({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const o=await m(t),l=await zn(e,i.profile);Jn(l.profileId);const f=Un(l.profileId).manifest.grantee??"app:terminal";if(f!==(o.grantee??"app:terminal"))throw new y({error:"profile_grantee_mismatch",message:`profile ${l.profileId} belongs to ${f}, node ${t} to ${o.grantee}`,received:i.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(o.profile_id??null)!==l.profileId&&(xn(o.kind)?(await U(o.kind,o.cwd,l.profileId),await J(t,{profileId:l.profileId})):await C(t,{profile_id:l.profileId}),await N(e,t,["profile"])),i.restart===!0&&Re(t),{status:200,body:await b(t)}}if(Object.prototype.hasOwnProperty.call(i,"cwd")){const o=i.cwd;if(typeof o!="string"||o==="")throw new y({error:"cwd_invalid",message:"cwd must be a non-empty string",received:o,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(i).some(u=>u!=="cwd"&&u!=="keep_session"&&u!=="restart"&&i[u]!==void 0))throw new y({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:i,field:"cwd",next:"Send cwd as the only config field."});const l=await m(t),f=P(l.cwd);if(i.keep_session===!0||f&&K(o)&&P(o)&&Ie(l.cwd,o)){if(!K(o))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${o}`,received:o,field:"cwd",next:"Send an absolute path."});const u=D(o);let S=!1;try{S=ne(u).isDirectory()}catch{}if(!S)throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${u}`,received:o,field:"cwd",next:"Send an existing absolute directory."});if(f&&!Ie(l.cwd,u))throw new y({error:"cwd_not_same_directory",message:`${u} is not the same directory as the recorded ${l.cwd}; --keep-session only relocates an alias`,received:o,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 y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot relocate its cwd`,received:o,field:"cwd",next:"Reconcile the managed worktree first."});const _=l.cwd;return _!==u&&(await W(async v=>{await C(t,{cwd:u}),await v.prepare("UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(u,t,_),await Qe(t,_,u)}),await N(e,t,["cwd"])),i.restart===!0&&Re(t),{status:200,body:await b(t)}}if(await L().has(t)){const u=`${t} cannot repair its cwd while its broker is live`;throw new p(409,"cwd_node_live",u,{error:"cwd_node_live",message:u,received:o,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(l.fork_from!=null)throw new y({error:"cwd_node_forked",message:`${t} is a fork and cannot repair its cwd; recorded cwd: ${l.cwd}`,received:o,field:"cwd",next:`Restore ${l.cwd}, then revive the fork normally.`});if(l.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot repair its cwd`,received:o,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(P(l.cwd))throw new y({error:"cwd_still_present",message:`${t} recorded cwd still exists: ${l.cwd}; cwd repair is not a relocation command`,received:o,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!K(o))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${o}`,received:o,field:"cwd",next:"Send an absolute path."});const h=D(o);if(!P(h))throw new y({error:"cwd_missing",message:`cwd does not exist: ${h}`,received:o,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!ne(h).isDirectory())throw new y({error:"cwd_not_a_directory",message:`cwd is not a directory: ${h}`,received:o,field:"cwd",next:"Send an existing absolute directory."})}catch(u){throw u instanceof y?u:new y({error:"cwd_missing",message:`cwd does not exist: ${h}`,received:o,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return await W(async()=>{await C(t,{cwd:h}),await Xe(t)}),await N(e,t,["cwd"]),{status:200,body:await b(t)}}let a=await m(t);const c=i.listen===void 0?void 0:ei(i.listen);if(i.scopes!==void 0){const o=ye(i.scopes),l=a.grantee==="app:terminal"?await ut(a):a.grant_id?await lt(a.grant_id):null;if(!o.every(f=>O(a.scopes,f)&&l!==null&&O(l.resolved,f)))throw new y({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:o,field:"scopes",next:"Send only scopes the node currently holds."});if(o.includes("crtr:act")&&!O(o,"crtr:llm"))throw new p(400,"invalid_scope","crtr:act requires crtr:llm");a=await C(t,{scopes:o})}if(i.situational_context!==void 0&&await Ee(t,Te(i.situational_context)),i.model!==void 0){const o=(await ue(a.cwd,a.profile_id??null)).modelLadders,l=$n(i.model,o),f=await ft(a.grant_id,i.model,l===void 0),h=f?{family:pt,strength:f.strength}:l,u=f?f.model:Nn(i.model,o);await V({kind:"concrete",spec:u},{cwd:a.cwd,profileId:a.profile_id??null},n.modelRegistry);const S=L();let _=!1;if(await S.isClaimed(t)&&await fe(t,S.get(t)?.handle.exited)&&(_=await Tn(t,u,h).then(()=>!0,v=>{if(v instanceof Pn)return!1;throw v})),!_){if(await S.isClaimed(t)){const v=`${t}'s broker did not accept the model switch; the model was not changed`;throw new p(409,"broker_not_ready",v,{error:"broker_not_ready",message:v,received:i.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!u.includes("/"))throw w(`model must resolve to a provider/id spec: ${i.model}`);await En(t,u,h)}a=await m(t)}if(i.kind!==void 0||i.mode!==void 0||i.lifecycle!==void 0){i.kind!==void 0&&await Ae(i.kind);const o=i.kind??a.kind,l=i.mode??a.mode,f=i.lifecycle??a.lifecycle;let h;l==="orchestrator"&&!await In(t)&&(h=s(async()=>{const u=await kn(t);await Rn(t,u!==null&&u.trim()!==""?{goal:u.trim()}:{})},"beforePersist")),a=await J(t,{...i.kind!==void 0?{kind:o}:{},...i.mode!==void 0?{mode:l}:{},...i.lifecycle!==void 0?{lifecycle:f}:{}},h)}i.name!==void 0&&(a=await C(t,{name:i.name}),a.window&&On(a.window,Wn(a)));const d=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(o=>i[o]!==void 0);return await N(e,t,d,c===void 0?void 0:async o=>{await o.prepare("UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(c,t)}),{status:200,body:await b(t)}}s(ni,"handleConfig");async function Oe(){return(await ue(process.cwd(),Ne()||null)).kinds}s(Oe,"daemonKinds");async function Ae(e){const n=Object.keys(await Oe());if(!n.includes(e))throw w(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${n.sort().join(", ")}.`})}s(Ae,"assertKindServer");async function ti(){const e=await Oe();return{status:200,body:{kinds:Object.keys(e).sort().map(t=>({kind:t,when_to_use:e[t]?.whenToUse??null,available_to:e[t]?.availableTo??null}))}}}s(ti,"handleListKinds");const Rr=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:It},{method:"GET",pattern:"/v1/nodes",handler:Nt},{method:"GET",pattern:"/v1/kinds",handler:s(()=>ti(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:Zt},{method:"GET",pattern:"/v1/nodes/:id",handler:Ct},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:Et},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:Tt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:Dt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:Lt},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:jt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:Mt},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Ft},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Kt},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:xt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Vt},{method:"POST",pattern:"/v1/nodes/:id/read",handler:Wt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:zt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Jt},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Ut},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Qt},{method:"GET",pattern:"/v1/nodes/:id/broker/structured-request",handler:Yt},{method:"POST",pattern:"/v1/nodes/:id/broker/goal",handler:Ht},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Xt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:ni}];export{ni as handleConfig,It as handleCreate,Ft as handleFork,Nt as handleList,Ut as handlePromote,Qt as handleYield,Rr as nodeRoutes,Ar as resolveCreateKind};
|
|
1
|
+
var $e=Object.defineProperty;var s=(e,n)=>$e(e,"name",{value:n,configurable:!0});import{envProfileId as Ne}from"../../../shared/env.js";import{pausedCanvasProfiles as Ce}from"../../../core/profiles/manifest.js";import{existsSync as C,realpathSync as ee,statSync as ne}from"node:fs";import{isAbsolute as x,resolve as D}from"node:path";import{appendSituationalContext as Ee,formatSituationalProse as Te}from"../../../core/runtime/situational-context.js";import{closeNode as Pe}from"../../../core/runtime/close.js";import{reviveNode as De}from"../../../core/runtime/revive.js";import{nowIso as K}from"../../../core/fs-utils.js";import{appPaidLaunch as Le,assertLaunchModelRegistered as V,forkNode as je,resolveForkSource as te,spawnChildPrepared as Me}from"../../../core/runtime/spawn.js";import{forkSourceNode as ie,newNodeId as re}from"../../../core/runtime/nodes.js";import{abandonCreateRequest as oe,childrenOf as Ge,completeCreateRequest as ae,findCreateRequest as de,getNode as R,recordCreateRequestNode as Fe,reserveCreateRequest as se,reserveCreateRequestNode as Be,listNodes as xe,recordRespawnAttempt as Ke,subscribersOf as Ve,subscriptionsOf as le,updateNode as E}from"../../../core/canvas/canvas.js";import{armControllerWait as We}from"../../../core/canvas/waits.js";import{withCanvasWrite as W}from"../../../core/canvas/db.js";import{markNodeRead as ze}from"../../../core/canvas/recovery.js";import{nodeObject as Je}from"../../../core/graph/objects.js";import{recordActedOn as Ue}from"../../../core/graph/edges.js";import{publish as Ye}from"../../../core/graph/events.js";import{readerFor as He}from"../reader.js";import{relocateSessionCwd as Qe,unbindSession as Xe}from"../../../core/canvas/sessions.js";import{ticketCountsForNodes as Ze}from"../../../core/canvas/attention.js";import{isSafeNodeId as qe}from"../../../core/canvas/paths.js";import{contextDir as ce,nodeAgentDir as z}from"../../../core/canvas/node-agent-paths.js";import{checkCronBirth as en,cronRefusalError as nn}from"../../cron/authority.js";import{cronBirthPlacement as tn}from"../../cron/armed-context.js";import{existsBeneath as rn,isAbsentOrRefused as on,isBeneathRefusal as an,readdirBeneath as dn}from"../../../core/spaces/open-beneath.js";import{readNodeMessagesPage as sn,readNodeSession as ln,readNodeSnapshot as cn,transcriptMarkdown as un}from"../../../core/runtime/node-read.js";import{assembleNodeSubject as fn}from"../../../core/substrate/subject.js";import{reviveAll as pn}from"../../../core/runtime/revive-all.js";import{promoteAsync as mn,requestYieldAsync as wn,reshapeNodeAsync as J}from"../../../core/runtime/promote.js";import{recycleNode as hn}from"../../../core/runtime/recycle.js";import{relaunchRoot as yn}from"../../../core/runtime/reset.js";import{assertReopenGate as _n}from"../../../core/runtime/reopen.js";import{requireCurrentExecution as gn}from"./broker-recovery.js";import{readOutputRequest as bn}from"../../../core/runtime/output-result.js";import{writeYieldMessage as vn,readGoal as kn,captureGoalIfAbsent as Sn}from"../../../core/runtime/kickoff.js";import{ensureRoadmap as Rn,hasRoadmap as In}from"../../../core/runtime/roadmap.js";import{renameWindow as On}from"../../../core/runtime/placement.js";import{buildLaunchSpecAsync as An,explicitModelIntent as $n,normalizeModel as Nn,readMergedLaunchConfigAsync as ue}from"../../../core/runtime/launch.js";import{modelRequestFromConfig as Cn}from"../../../core/model-routes.js";import{persistDormantModel as En,setModelLive as Tn}from"../../../core/runtime/model-swap.js";import{waitForBrokerViewSocket as fe}from"../../../core/runtime/view-socket.js";import{BrokerUnreachableError as Pn}from"../../../core/runtime/broker-request.js";import{boundFleet as L}from"../../../core/runtime/fleet.js";import{admitLegacyStructuredOutput as Dn}from"../../structured-requests/sidecar.js";import{assertOutputSchemaAccepted as Ln}from"../../../core/runtime/structured-output.js";import{OUTCOME_PAYLOAD_MAX_BYTES as pe}from"../../../core/canvas/types.js";import{HUMAN_ACTION_NAME_PATTERN as jn}from"../../../core/human/action-binding.js";import{resolveHumanAction as Mn}from"../../../core/human-actions.js";import{parseDurationMs as Gn}from"../../../core/wake.js";import{claimWarmNode as Fn,refillWarmPool as me,resumeWarmClaim as Bn,warmPoolEnabled as xn}from"../../../core/runtime/warm-pool.js";import{assertLaunchKind as U,isLaunchKind as Kn,resolveLaunchTarget as Vn}from"../../../core/runtime/launch-target.js";import{fullName as Wn}from"../../../core/canvas/labels.js";import{reportsForNode as we}from"./reports.js";import{requireUsableProfile as zn}from"./profiles.js";import{assertProfileActive as Jn,loadExactProfileManifest as Un}from"../../../core/profiles/manifest.js";import{getCron as he}from"../../../core/canvas/crons.js";import{cronWakeOrigin as Yn}from"../../../core/runtime/bearings.js";import{boundDaemonControl as Hn}from"../../control.js";import{notFound as T,usage as w}from"../../../core/errors.js";import{assertScope as Qn,validateScopes as ye}from"../../../core/scopes.js";import{scopeAllowed as O}from"../../../shared/env.js";import{toCloseResultDTO as Xn,toNodeDetailDTO as Y,toNodeSummaryDTO as Zn,toReviveResultDTO as qn}from"../map.js";import{ApiError as p}from"../../../api/index.js";import{InputError as y}from"../../../core/io.js";import{runsOnBlaxel as et}from"../environment-of.js";import{actsAsPerson as j,canReadNode as $,mayOnNode as nt,readableNodeIds as tt,resolvedScopes as it}from"../router.js";import{forwardVerb as rt,queryWithoutMachine as ot,relayError as at,unknownError as dt,withMachine as st}from"../../peer/forward.js";import{fileRoot as lt}from"../../../core/spaces/file-root.js";import{activeGrant as ct,payerOfGrant as ut}from"../../../core/grants/mirror.js";import{nodeTerminalGrant as ft}from"../../../core/grants/terminal.js";import{appRungForGrant as pt}from"../../../core/llm/app-rungs.js";import{APP_FAMILY as mt}from"../../../core/model-routes.js";import{listProfileEnvNames as wt}from"../../../core/profiles/env-store.js";import{hasConfiguredProviderCredential as ht,NO_PROVIDER_CREDENTIAL_MESSAGE as _e}from"../../../core/runtime/provider-credential-gate.js";import{filterAsync as yt,mapAsync as ge}from"../../../core/async-array.js";async function m(e){const n=await R(e);if(n===null)throw T(`unknown node: ${e}`,{received:e});return n}s(m,"requireMeta");async function H(e){return{subscribesTo:await le(e),subscribers:await Ve(e),children:await Ge(e)}}s(H,"edgesFor");async function b(e){const n=await m(e);return await Y(n,await H(e))}s(b,"detailOf");async function _t(e){let n=(await we(e)).length;try{n+=dn(await z(e),await ce(e)).length}catch(t){if(!on(t))throw t}return n}s(_t,"countFiles");function gt(e){if(typeof e!="object"||e===null)throw w("a node create requires a JSON body");const n=e;if(n.kind!==void 0&&(typeof n.kind!="string"||n.kind.trim()===""))throw w("kind must be a non-empty string when provided");if(n.description!==void 0&&(typeof n.description!="string"||n.description.trim()===""))throw w("description must be a non-empty string when provided");if(n.creator!==void 0&&(typeof n.creator!="string"||n.creator.trim()===""))throw w("creator must be a non-empty node id when provided");if(n.scopes!==void 0&&ye(n.scopes),n.isolated!==void 0&&typeof n.isolated!="boolean")throw new p(400,"invalid_request","isolated must be a boolean",{param:"isolated"});const t=n.root_lifecycle;if(t!==void 0&&t!=="resident"&&t!=="terminal")throw w("root_lifecycle must be 'resident' or 'terminal'");if(n.request_key!==void 0&&(typeof n.request_key!="string"||n.request_key.trim()===""||n.request_key.length>128))throw w("request_key must be a non-empty string of at most 128 characters when provided");return n}s(gt,"parseCreateBody");function bt(e){if(e===void 0)return;const n=Gn(e),t=n===null?null:new Date(Date.now()+n);if(n===null||!Number.isFinite(n)||n<=0||t===null||!Number.isFinite(t.getTime()))throw new p(422,"invalid_deadline","`deadline` must be a positive representable duration");return t.toISOString()}s(bt,"parseDeadline");function vt(e){if(e!==void 0){if(typeof e!="object"||e===null||Array.isArray(e))throw new p(400,"invalid_request","`outcome_delivery` must be an object");if(typeof e.action!="string"||!jn.test(e.action))throw new p(400,"invalid_request","`outcome_delivery.action` must be a declared action name");if(e.payload!==void 0){let n;try{n=JSON.stringify(e.payload)}catch{throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable")}if(n===void 0)throw new p(400,"invalid_request","`outcome_delivery.payload` must be JSON-serializable");if(Buffer.byteLength(n,"utf8")>pe)throw new p(413,"payload_too_large",`serialized payload exceeds ${pe} bytes`)}return e}}s(vt,"parseOutcomeDelivery");function kt(e,n){const t=Mn(e.action,n);if(!("kind"in t))return{actionName:e.action,argv:t.argv,cwd:t.cwd,configOrigin:t.configOrigin,...e.payload===void 0?{}:{payload:e.payload}};throw t.kind==="unknown_action"?new p(422,"unknown_action",`no action named ${e.action} is declared from ${n}`):new p(422,"invalid_action",`${e.action} is declared in ${t.configOrigin} but unusable: ${t.reason}`,{reason:t.reason,configOrigin:t.configOrigin})}s(kt,"resolveOutcomeDelivery");function St(e,n,t){const r={kind:e.kind,cwd:t,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),n!==void 0&&(r.parent=n),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=D(e.pin_cwd??e.cwd??t)),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}s(St,"buildRecipe");function Rt(e,n,t){return!xn()||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:n,profileId:t,model:e.model??null,situationalContext:e.situational_context??null,name:e.name??null,creator:e.creator??null}}s(Rt,"warmRequestFor");import{resolveCreateKind as Nr}from"../../../core/runtime/launch-target.js";function be(e){const n=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Cn(e.model,n,e.modelExact===!0)}s(be,"requestFromLaunch");function It(e,n){if(n===null)return e;if(e.scopes===void 0)return{...e,scopes:[...n]};const t=e.scopes.filter(r=>!O(n,r));if(t.length===0)return e;throw new p(403,"scope_denied",`scopes exceed the bearer token's ceiling: ${t.join(", ")}`,{scopes:t,ceiling:n})}s(It,"withinCeiling");async function ve(e,n,t){const r=(await An(n.kind,n.mode,{lifecycle:n.lifecycle,hasManager:e.parent!==null,model:n.model,modelOverride:!0,cwd:e.cwd,profileId:e.profile_id??null})).launch;await V(be(r),{cwd:e.cwd,profileId:e.profile_id??null},t)}s(ve,"assertNodeModelChangeRegistered");async function ke(e,n){const t=e.principal;if(t.class!=="broker"&&t.class!=="cron")return;const r=lt({app:t.app,resolved:await it(t),launched:t.scopes},n,"read");if("root"in r)return;const i="missing"in r?r.missing:null;throw new p(403,"scope_missing",i?`the child's directory ${n} needs missing scope ${i}`:`no permission of this run names the child's directory ${n}`,void 0,void 0,i?{scope:i}:void 0)}s(ke,"assertCallerReaches");const Q=new Map;async function Ot(e,n={},t={}){const r=It(gt(e.body),e.ceiling);if(e.principal.class==="broker"){const d=e.principal;if(r.prefer_warm===!0&&d.app!=="app:terminal"&&(r.prefer_warm=!1),r.parent!=null){const o=await m(r.parent);if(o.grantee!==d.app)throw new p(403,"other_app_run","cannot create a child under another app's node");if(!await $(d,o.grantee??"app:terminal",r.parent))throw T(`unknown node: ${r.parent}`,{received:r.parent})}if(r.creator!==void 0&&r.creator!==d.node)throw new p(403,"other_app_run","cannot create for another node");if(r.fork_from!==void 0){let o=null;try{o=await ie(await te(r.fork_from))}catch{}if(o?.grantee!==d.app||!await $(d,o.grantee,o.node_id))throw new p(403,"other_app_run","cannot fork another app's conversation")}r.creator=d.node}if(e.principal.class==="person"&&e.principal.sub!==void 0){const d=r.fork_from===void 0?null:await ie(await te(r.fork_from)).catch(()=>null);for(const o of[r.parent,r.creator,d?.node_id])if(o!=null&&await R(o)!==null&&!await nt(e.principal,"edit",o))throw T(`unknown node: ${o}`,{received:o})}if(e.principal.class==="cron"){const d=e.principal;for(const l of["parent","creator","fork_from","node_id"])if(r[l]!=null)throw new p(403,"permission_error",`a cron cannot set ${l} on a node it starts`);r.prefer_warm=!1,r.node_id=await re(),d.isolated&&(r.isolated=!0,r.cwd=await z(r.node_id,d.app));const o=await en({grantee:d.app,sub:d.sub,grant_id:d.grant,scopes:d.scopes,from_exec:d.from_exec},{profile:r.profile,cwd:r.cwd,pin_cwd:r.pin_cwd,kind:r.kind,model:r.model,mode:r.mode});if(!o.allowed)throw nn(o);if(r.scopes!==void 0){const l=r.scopes.find(f=>!O(o.effectiveScopes,f)||!O(d.scopes,f));if(l!==void 0)throw new p(403,"scope_missing",`scope ${l} is not held by this cron`,void 0,void 0,{scope:l})}else d.scopes!==null&&(r.scopes=[...d.scopes])}r.creator!==void 0&&Qn(await m(r.creator),"crtr:act");const i=r.request_key?.trim();if(i===void 0||r.node_id!==void 0&&qe(r.node_id)&&await R(r.node_id)!==null&&(await de(i))?.nodeId!==r.node_id)return M(e,r,n,t);const a=Q.get(i);if(a!==void 0)return a;const u=$t(e,r,i,n,t);Q.set(i,u);try{return await u}finally{Q.delete(i)}}s(Ot,"handleCreate");const Se="create_request_in_progress";async function At(e,n,t){const r=Date.now()+1e4;for(;t!==null;){const i=await R(t);if(i!==null){if(!j(e.principal)&&!await $(e.principal,i.grantee??"app:terminal",t))throw new p(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:await b(t)}}if(Date.now()>=r||(await de(n))?.nodeId!==t)break;await new Promise(a=>setTimeout(a,100))}throw new p(409,Se,"another create with this request_key is in progress; retry it")}s(At,"awaitForeignCreate");async function $t(e,n,t,r,i){const a=await se(t);if(a.nodeId!==null&&await R(a.nodeId)!==null){if(a.state!=="warm_claimed"){const u=await R(a.nodeId);if(!j(e.principal)&&!await $(e.principal,u.grantee??"app:terminal",a.nodeId))throw new p(409,"create_request_conflict","request_key belongs to another caller");return{status:201,body:await b(a.nodeId)}}return M(e,n,r,i,a)}try{return await M(e,n,r,i,a)}catch(u){if(u instanceof p&&u.code===Se)throw u;const d=await se(t);throw(d.nodeId===null||await R(d.nodeId)===null)&&await oe(t,d.nodeId),u}}s($t,"handleKeyedCreateRequest");async function M(e,n,t,r,i=void 0){const a=r.deadlineAt??bt(n.deadline),u=vt(n.outcome_delivery),d=e.principal.class==="cron"?await tn({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:e.principal.kind==="exec"?null:(await he(e.principal.cron))?.created_by??null},n.node_id):null;d!==null&&(n.root=d.root===!0);const o=d?.parent??n.parent??void 0;if(o==null&&n.root!==!0)throw w("a node create requires a parent (or root: true for an independent root)");let l=null;if(n.output_schema!==void 0){try{l=JSON.parse(n.output_schema)}catch{throw w("output_schema must be a JSON schema string")}if(l===null||typeof l!="object"||Array.isArray(l))throw w("output_schema must be a JSON schema object");await Ln(l)}const{profileId:f,kind:h,cwd:c,launch:S}=await Vn(n,{validateKind:Ae});if(n.pin_cwd!==void 0&&n.pin_cwd!==""&&n.worktree===void 0&&n.isolated!==!0&&!C(c)&&!await et(f))throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${c}`,received:c,field:"cwd",next:"Pass an existing directory with --cwd."});await ke(e,c),n.worktree!==void 0&&await ke(e,D(n.pin_cwd??n.cwd??c));const _={...n,kind:h},v=u===void 0?void 0:kt(u,c),Z=("grant"in e.principal?e.principal.grant:null)??(o==null?null:(await R(o))?.grant_id??null);if(await V(be(await Le(S,Z,n.model)),{cwd:c,profileId:f},t.modelRegistry),await ut(Z)!=="app"&&!await ht(f===null?[]:await wt(f)))throw new p(412,"no_provider_credential",_e,{error:"no_provider_credential",message:_e,next:"The person running this runtime logs a provider in with `crtr sys setup`, or stores a provider key on the profile."});let F=null;{const A=i===void 0||i.nodeId===null||i.state==="warm_claimed"?Rt(_,c,f):null,B=l===null&&r.beforeBrokerLaunch===void 0?void 0:async g=>{l!==null&&await Dn(g,"terminal",l),r.beforeBrokerLaunch?.(g)};if(i?.state==="warm_claimed"&&i.nodeId!==null){const g=A===null?null:await Bn(A,i.nodeId,B);if(g===null)throw await oe(i.requestKey,i.nodeId),new p(503,"create_resume_failed",`could not resume warm claim ${i.nodeId}; retry the create`);return await ae(i.requestKey,g),{status:201,body:await b(g)}}if(A!==null){const g=await Fn(A,{...a===void 0?{}:{deadlineAt:a},...v===void 0?{}:{outcomeDelivery:v},...i===void 0?{}:{requestKey:i.requestKey}},B);if(g!==null)return i!==void 0&&await ae(i.requestKey,g),me(A),{status:201,body:await b(g)};F=A}const P=i?.nodeId??n.node_id??(i===void 0?void 0:await re());if(i!==void 0&&i.nodeId===null){const g=await Be(i.requestKey,P);if(g!==P)return await At(e,i.requestKey,g)}const I=St(P===void 0?_:{..._,node_id:P},o,c);d!==null&&(d.rootLifecycle!==void 0&&(I.rootLifecycle=d.rootLifecycle),d.scopes!==void 0&&_.scopes===void 0&&(I.scopes=d.scopes),d.run!==void 0&&(I.run=d.run),d.withinCreate!==void 0&&(I.withinCreate=d.withinCreate)),a!==void 0&&(I.deadlineAt=a),v!==void 0&&(I.outcomeDelivery=v),I.readiness=n.root===!0?"await":"launch";const q=await Me(I,B,()=>{F!==null&&me(F)});return i!==void 0&&await Fe(i.requestKey,q.node.node_id),{status:201,body:await b(q.node.node_id)}}}s(M,"handleCreateRequest");function k(e,n){const t=e.query.getAll(n);if(t.length>1)throw w(`${n} must appear at most once`);return t[0]}s(k,"singleQueryValue");function X(e,n){if(e!==void 0){if(e==="1"||e==="true")return!0;if(e==="0"||e==="false")return!1;throw w(`${n} must be true or false`)}}s(X,"optionalBoolean");function G(e,n,t){if(e!==void 0){if(t.includes(e))return e;throw w(`${n} must be one of: ${t.join(", ")}`)}}s(G,"oneOf");function Nt(e){const n=new Set(["status","lifecycle","kind","mode","profile_id","profile_prefix","parent","top_level","under","under_inclusive","hanging","include"]);for(const[_]of e.query)if(!n.has(_))throw w(`unknown nodes query parameter: ${_}`);const t=G(k(e,"status"),"status",["active","idle","done","dead","canceled"]),r=G(k(e,"lifecycle"),"lifecycle",["terminal","resident"]),i=k(e,"kind"),a=G(k(e,"mode"),"mode",["base","orchestrator"]),u=k(e,"profile_id"),d=k(e,"profile_prefix"),o=k(e,"parent"),l=X(k(e,"top_level"),"top_level"),f=k(e,"under"),h=X(k(e,"under_inclusive"),"under_inclusive"),c=X(k(e,"hanging"),"hanging"),S=G(k(e,"include"),"include",["activity"]);if(o!==void 0&&l===!0)throw w("parent and top_level=true cannot be combined");return{...t!==void 0?{status:t}:{},...r!==void 0?{lifecycle:r}:{},...i!==void 0?{kind:i}:{},...a!==void 0?{mode:a}:{},...u!==void 0?{profile_id:u}:{},...d!==void 0?{profile_prefix:d}:{},...o!==void 0?{parent:o}:{},...l!==void 0?{top_level:l}:{},...f!==void 0?{under:f}:{},...h!==void 0?{under_inclusive:h}:{},...c!==void 0?{hanging:c}:{},...S!==void 0?{include:S}:{}}}s(Nt,"parseListQuery");async function Ct(e){const n=Nt(e);let t=await xe({...n.status!==void 0?{status:n.status}:{},...n.lifecycle!==void 0?{lifecycle:n.lifecycle}:{},...n.kind!==void 0?{kind:n.kind}:{},...n.mode!==void 0?{mode:n.mode}:{},...n.profile_id!==void 0?{profileId:n.profile_id}:{},...n.profile_prefix!==void 0?{profilePrefix:n.profile_prefix}:{},...n.parent!==void 0?{parent:n.parent}:{},...n.top_level===!0?{topLevel:!0}:{},...n.under!==void 0?{under:n.under}:{},...n.under_inclusive===!0?{underInclusive:!0}:{},...n.hanging===!0?{hanging:!0}:{}});const r=await tt(e.principal);r!==null&&(t=t.filter(d=>r.has(d.node_id)));const i=n.include==="activity"?await Ze(t.map(d=>d.node_id)):null,a=t.length>0?Ce():new Set;return{status:200,body:await ge(t,async d=>{const o=await Zn(d,d.profile_id!==null&&a.has(d.profile_id));if(i!==null){const l=await we(d.node_id);o.activity={latest_report:l[0]??null,final_report:d.final_report===null?null:l.find(f=>f.name===d.final_report)??null,pending_human_count:i[d.node_id]??0}}return o})}}s(Ct,"handleList");async function Et(e){const n=e.params.id,t=await rt(e,n,{method:"GET",path:`/v1/nodes/${encodeURIComponent(n)}`,query:ot(e)});if(t.kind==="unknown")throw dt(n,t.unreachable);if(t.kind==="remote"){if(t.status>=400)throw at(t.status,t.body);return{status:t.status,body:st(t.body,t.machine)}}return await m(n),{status:200,body:await b(n)}}s(Et,"handleDetail");async function Tt(e){const n=e.params.id;await m(n);const t=await cn(n);return{status:200,body:{node_id:n,snapshot:{messages:t.snapshot.messages,...t.snapshot.messageIds===void 0?{}:{messageIds:t.snapshot.messageIds},messageVisibility:t.snapshot.messageVisibility,turnVisibility:t.snapshot.turnVisibility,stats:t.snapshot.stats,state:t.snapshot.state,display:t.snapshot.display,...t.snapshot.queued===void 0?{}:{queued:t.snapshot.queued},...t.snapshot.toolGroupSummaries===void 0?{}:{toolGroupSummaries:t.snapshot.toolGroupSummaries},...t.snapshot.turnReplies===void 0?{}:{turnReplies:t.snapshot.turnReplies},...t.snapshot.workingActivity===void 0?{}:{workingActivity:t.snapshot.workingActivity}},commands:t.commands.map(i=>({name:i.name,description:i.description,source:i.source})),captured_at:K()}}}s(Tt,"handleSnapshot");async function Pt(e){const n=e.params.id,t=await fn(n);if(t===null)throw T(`unknown node: ${n}`,{received:n});return{status:200,body:t}}s(Pt,"handleSubject");function Dt(e){for(const[a]of e.query)if(a!=="cursor"&&a!=="limit")throw w(`unknown messages query parameter: ${a}`);const n=e.query.getAll("cursor"),t=e.query.getAll("limit");if(n.length>1)throw w("cursor must appear at most once");if(t.length>1)throw w("limit must appear at most once");if(t.length===0)return n.length===0?{}:{cursor:n[0]};const r=t[0],i=Number(r);if(!Number.isSafeInteger(i)||r==="")throw w("limit must be an integer from 1 through 500");return n.length===0?{limit:i}:{cursor:n[0],limit:i}}s(Dt,"parseMessagesQuery");async function Lt(e){const n=e.params.id,t=await sn(n,Dt(e));return{status:200,body:{node_id:n,messages:t.messages,...t.messageIds===void 0?{}:{message_ids:t.messageIds},message_visibility:t.messageVisibility,next_cursor:t.nextCursor,captured_at:K()}}}s(Lt,"handleMessages");async function jt(e){const n=e.params.id;await m(n);const t=await ln(n);return{status:200,body:{node_id:n,session_file:t.sessionFile,session_jsonl:t.sessionJsonl,system_prompt:t.systemPrompt,captured_at:K()}}}s(jt,"handleSession");async function Mt(e){const n=e.params.id;return await m(n),{status:200,body:{node_id:n,markdown:await un(n)}}}s(Mt,"handleTranscript");async function Gt(e){const n=e.params.id;await m(n);const t=s(async(i,a)=>({node_id:i,label:(await R(i))?.name??i,dir:await ce(i),self:a,files:await _t(i)}),"root"),r=await yt([await t(n,!0),...await ge(await le(n),async i=>await t(i.node_id,!1))],async i=>await Ft(i.node_id,i.dir)||i.files>0);return{status:200,body:{node_id:n,roots:r}}}s(Gt,"handleContext");async function Ft(e,n){try{return rn(await z(e),n)}catch(t){if(an(t))return!1;throw t}}s(Ft,"hasDir");async function Bt(e){const n=await m(e.params.id),t=e.principal.class==="broker"?e.principal.scopes:e.ceiling,r=t===null?void 0:n.scopes==null?[...t]:[...new Set([...n.scopes.filter(a=>O(t,a)),...t.filter(a=>O(n.scopes,a))])],i=await je(n.node_id,r,e.principal.class==="broker"?e.principal.node:void 0);return{status:201,body:await b(i.node.node_id)}}s(Bt,"handleFork");const xt=1e4;async function Kt(e){const n=e.params.id;await m(n);const t=e.body,r=t?.resume??!0,i=t?.reopen??!1;await _n(n,i,e.principal.class==="broker"?e.principal.node:null);const a=!r&&t?.cron_id!==void 0?await he(t.cron_id):null,u=await De(n,{resume:r,capacity:"refuse",...a!==null?{wakeReason:await Yn(a,"schedule_revive")}:{}});u.outcome!=="already-live"&&await Ke(n,{failures:0,notBefore:null});const d=(await R(n))?.status??"active",o=(u.launch??L().get(n)?.handle)?.exited,l=u.outcome!=="frozen"&&await fe(n,o,xt);return{status:200,body:qn(n,u,d,l)}}s(Kt,"handleRevive");async function Vt(e){const n=e.params.id;return{status:200,body:{newNodeId:(await yn(n))?.newNodeId??null}}}s(Vt,"handleRelaunchRoot");async function Wt(e){const n=e.params.id;await m(n);const t=e.body;if(t?.caller_pid!==void 0&&(!Number.isInteger(t.caller_pid)||t.caller_pid<=0))throw w("caller_pid must be a positive integer when provided");const r=Hn(),i=new Promise(u=>{e.res.once("close",()=>u())}),a=await Pe(n,{teardownAfter:i,rootEvent:t?.finish===!0?"finish":"cancel",callerPid:t?.caller_pid,...e.principal.class==="broker"?{closer:e.principal.node}:{},...r===null?{}:{registerDetached:r.registerDetached}});return{status:200,body:Xn(a)}}s(Wt,"handleClose");async function zt(e){if(!j(e.principal))throw new p(403,"permission_error","only the person marks a conversation read");const n=e.params.id;return await m(n),await ze(n),{status:204}}s(zt,"handleMarkRead");async function Jt(e){const n=e.params.id;await m(n);const t=await hn(n);return{status:200,body:{recycled:t.recycled,finalized:t.finalized,new_root:t.newRoot,delivered:t.delivered}}}s(Jt,"handleRecycle");async function Ut(e){const n=e.params.id;return await m(n),await J(n,{lifecycle:"terminal"}),await N(e,n,["lifecycle"]),{status:200,body:await b(n)}}s(Ut,"handleDemote");async function Yt(e,n={}){const t=e.params.id,r=await m(t),i=e.body??{};i.kind!==void 0&&await U(i.kind,r.cwd,r.profile_id??null),i.model!==void 0&&await ve(r,{kind:i.kind??r.kind,mode:"orchestrator",lifecycle:i.resident===!0?"resident":r.lifecycle,model:i.model},n.modelRegistry);const a=await mn(t,{...i.kind!==void 0?{kind:i.kind}:{},...i.resident===!0?{resident:!0}:{},...i.model!==void 0?{model:i.model}:{}});await N(e,t,["mode",...i.kind!==void 0?["kind"]:[],...i.resident===!0?["lifecycle"]:[],...i.model!==void 0?["model"]:[]]);const u=await Y(a.meta,await H(t));return u.roadmap_written=a.roadmapWritten,u.roadmap_ref=a.roadmapRef,u.goal_path=a.goalPath,{status:200,body:u}}s(Yt,"handlePromote");async function Ht(e){const n=e.params.id;return await m(n),{status:200,body:{request:await bn(n)}}}s(Ht,"handleBrokerStructuredRequest");async function Qt(e){const n=e.params.id,t=e.body??{};if(await gn(n,t.expected_execution_id),typeof t.text!="string")throw new p(400,"invalid_request","text must be a string");return await m(n),{status:200,body:{captured:await Sn(n,t.text)}}}s(Qt,"handleBrokerGoal");async function Xt(e,n={}){const t=e.params.id,r=await m(t),i=e.body??{};i.kind!==void 0&&await U(i.kind,r.cwd,r.profile_id??null),i.model!==void 0&&await ve(r,{kind:i.kind??r.kind,mode:i.promote===!0?"orchestrator":r.mode,lifecycle:r.lifecycle,model:i.model},n.modelRegistry);const a=i.note??"Refresh: continue against your roadmap or goal.";await vn(t,a);const u=await wn(t,{...i.promote===!0?{promote:!0}:{},...i.kind!==void 0?{kind:i.kind}:{},...i.model!==void 0?{model:i.model}:{}});return{status:200,body:await Y(u.meta,await H(t))}}s(Xt,"handleYield");async function Zt(e){const n=e.params.id;await m(n);const t=e.body;if(t===void 0||typeof t.controller!="string"||t.controller.trim()==="")throw w("a wait requires a controller node id");const r=await R(t.controller);if(r===null)throw T(`unknown controller: ${t.controller}`,{received:t.controller});if(r.status!=="active"&&r.status!=="idle")throw new p(422,"unprocessable",`controller ${t.controller} is ${r.status}`);return await We(n,t.controller),{status:200,body:await b(n)}}s(Zt,"handleWait");async function qt(e){const n=e.principal,t=await pn(n.class==="broker"?async i=>i.grantee===n.app&&await $(n,i.grantee,i.node_id):n.class==="person"&&!j(n)?async i=>await $(n,i.grantee??"app:terminal",i.node_id):void 0);return{status:200,body:{revived:[...t.revived],failed:[...t.failed],frozen:[...t.frozen]}}}s(qt,"handleReviveAll");const ei=new Set(["interrupt","steer","after-turn","next-turn"]);function ni(e){if(e===null)return null;const n=s(r=>{throw new y({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 n("listen must be an object or null");const t=Object.entries(e);if(t.length===0)return n("listen must name at least one level");for(const[r,i]of t)/^(?:[1-9]|10)$/.test(r)||n(`listen level must be 1..10: ${r}`),(typeof i!="string"||!ei.has(i))&&n(`listen delivery must be interrupt|steer|after-turn|next-turn: ${String(i)}`);return JSON.stringify(Object.fromEntries(t))}s(ni,"listenJson");async function N(e,n,t,r){t.length===0&&r===void 0||await W(async i=>{if(r?.(i),t.length===0)return;const a=await Je(i,n),u=await He(i,e),d=u.class==="person"?u.person:u.class==="app"?u.app:u.node;await Ue(i,d,a),await Ye(i,{event:"configured",object:a,actor:d,attrs:{changed:t.join(",")}})})}s(N,"recordConfigured");function Re(e){const n=L().get(e);if(n===void 0)return!1;try{return process.kill(n.pid,"SIGTERM"),!0}catch{return!1}}s(Re,"restartLiveBroker");function Ie(e,n){try{return ee(e)===ee(n)}catch{return!1}}s(Ie,"sameDirectory");async function ti(e,n={}){const t=e.params.id,r=e.body;let i;if(r===void 0)i={};else if(typeof r=="object"&&r!==null&&!Array.isArray(r))i=r;else throw new y({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(i.profile!==void 0){if(typeof i.profile!="string"||i.profile==="")throw new y({error:"profile_invalid",message:"profile must be a non-empty profile id or name",received:i.profile,field:"profile",next:"Send a profile id or exact name."});if(Object.keys(i).some(h=>h!=="profile"&&h!=="restart"&&i[h]!==void 0))throw new y({error:"profile_not_exclusive",message:"profile can only be combined with restart",field:"profile",next:"Send profile (and optionally restart) alone."});const o=await m(t),l=await zn(e,i.profile);Jn(l.profileId);const f=Un(l.profileId).manifest.grantee??"app:terminal";if(f!==(o.grantee??"app:terminal"))throw new y({error:"profile_grantee_mismatch",message:`profile ${l.profileId} belongs to ${f}, node ${t} to ${o.grantee}`,received:i.profile,field:"profile",next:"Pick a profile owned by the same app as the node."});return(o.profile_id??null)!==l.profileId&&(Kn(o.kind)?(await U(o.kind,o.cwd,l.profileId),await J(t,{profileId:l.profileId})):await E(t,{profile_id:l.profileId}),await N(e,t,["profile"])),i.restart===!0&&Re(t),{status:200,body:await b(t)}}if(Object.prototype.hasOwnProperty.call(i,"cwd")){const o=i.cwd;if(typeof o!="string"||o==="")throw new y({error:"cwd_invalid",message:"cwd must be a non-empty string",received:o,field:"cwd",next:"Send a non-empty absolute cwd string."});if(Object.keys(i).some(c=>c!=="cwd"&&c!=="keep_session"&&c!=="restart"&&i[c]!==void 0))throw new y({error:"cwd_not_exclusive",message:"cwd repair cannot be combined with another config field",received:i,field:"cwd",next:"Send cwd as the only config field."});const l=await m(t),f=C(l.cwd);if(i.keep_session===!0||f&&x(o)&&C(o)&&Ie(l.cwd,o)){if(!x(o))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${o}`,received:o,field:"cwd",next:"Send an absolute path."});const c=D(o);let S=!1;try{S=ne(c).isDirectory()}catch{}if(!S)throw new y({error:"cwd_missing",message:`cwd is not an existing directory: ${c}`,received:o,field:"cwd",next:"Send an existing absolute directory."});if(f&&!Ie(l.cwd,c))throw new y({error:"cwd_not_same_directory",message:`${c} is not the same directory as the recorded ${l.cwd}; --keep-session only relocates an alias`,received:o,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 y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot relocate its cwd`,received:o,field:"cwd",next:"Reconcile the managed worktree first."});const _=l.cwd;return _!==c&&(await W(async v=>{await E(t,{cwd:c}),await v.prepare("UPDATE crons SET cwd = ? WHERE anchor_node = ? AND cwd = ?").run(c,t,_),await Qe(t,_,c)}),await N(e,t,["cwd"])),i.restart===!0&&Re(t),{status:200,body:await b(t)}}if(await L().has(t)){const c=`${t} cannot repair its cwd while its broker is live`;throw new p(409,"cwd_node_live",c,{error:"cwd_node_live",message:c,received:o,field:"cwd",next:"Let the node become dormant, then retry the cwd repair."})}if(l.fork_from!=null)throw new y({error:"cwd_node_forked",message:`${t} is a fork and cannot repair its cwd; recorded cwd: ${l.cwd}`,received:o,field:"cwd",next:`Restore ${l.cwd}, then revive the fork normally.`});if(l.managed_worktree?.state==="open")throw new y({error:"cwd_node_managed_worktree_open",message:`${t} owns an open managed worktree and cannot repair its cwd`,received:o,field:"cwd",next:"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon flow."});if(C(l.cwd))throw new y({error:"cwd_still_present",message:`${t} recorded cwd still exists: ${l.cwd}; cwd repair is not a relocation command`,received:o,field:"cwd",next:"This command only repairs a node whose recorded cwd is gone."});if(!x(o))throw new y({error:"cwd_not_absolute",message:`cwd must be an absolute path: ${o}`,received:o,field:"cwd",next:"Send an absolute path."});const h=D(o);if(!C(h))throw new y({error:"cwd_missing",message:`cwd does not exist: ${h}`,received:o,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."});try{if(!ne(h).isDirectory())throw new y({error:"cwd_not_a_directory",message:`cwd is not a directory: ${h}`,received:o,field:"cwd",next:"Send an existing absolute directory."})}catch(c){throw c instanceof y?c:new y({error:"cwd_missing",message:`cwd does not exist: ${h}`,received:o,field:"cwd",next:"Create the replacement directory or send an existing absolute directory."})}return await W(async()=>{await E(t,{cwd:h}),await Xe(t)}),await N(e,t,["cwd"]),{status:200,body:await b(t)}}let a=await m(t);const u=i.listen===void 0?void 0:ni(i.listen);if(i.scopes!==void 0){const o=ye(i.scopes),l=a.grantee==="app:terminal"?await ft(a):a.grant_id?await ct(a.grant_id):null;if(!o.every(f=>O(a.scopes,f)&&l!==null&&O(l.resolved,f)))throw new y({error:"unknown_scope",message:"scopes may only narrow the node's current effective set",received:o,field:"scopes",next:"Send only scopes the node currently holds."});if(o.includes("crtr:act")&&!O(o,"crtr:llm"))throw new p(400,"invalid_scope","crtr:act requires crtr:llm");a=await E(t,{scopes:o})}if(i.situational_context!==void 0&&await Ee(t,Te(i.situational_context)),i.model!==void 0){const o=(await ue(a.cwd,a.profile_id??null)).modelLadders,l=$n(i.model,o),f=await pt(a.grant_id,i.model,l===void 0),h=f?{family:mt,strength:f.strength}:l,c=f?f.model:Nn(i.model,o);await V({kind:"concrete",spec:c},{cwd:a.cwd,profileId:a.profile_id??null},n.modelRegistry);const S=L();let _=!1;if(await S.isClaimed(t)&&await fe(t,S.get(t)?.handle.exited)&&(_=await Tn(t,c,h).then(()=>!0,v=>{if(v instanceof Pn)return!1;throw v})),!_){if(await S.isClaimed(t)){const v=`${t}'s broker did not accept the model switch; the model was not changed`;throw new p(409,"broker_not_ready",v,{error:"broker_not_ready",message:v,received:i.model,field:"model",next:"Check the node with `crtr node show`, then retry the model change."})}if(!c.includes("/"))throw w(`model must resolve to a provider/id spec: ${i.model}`);await En(t,c,h)}a=await m(t)}if(i.kind!==void 0||i.mode!==void 0||i.lifecycle!==void 0){i.kind!==void 0&&await Ae(i.kind);const o=i.kind??a.kind,l=i.mode??a.mode,f=i.lifecycle??a.lifecycle;let h;l==="orchestrator"&&!await In(t)&&(h=s(async()=>{const c=await kn(t);await Rn(t,c!==null&&c.trim()!==""?{goal:c.trim()}:{})},"beforePersist")),a=await J(t,{...i.kind!==void 0?{kind:o}:{},...i.mode!==void 0?{mode:l}:{},...i.lifecycle!==void 0?{lifecycle:f}:{}},h)}i.name!==void 0&&(a=await E(t,{name:i.name}),a.window&&On(a.window,Wn(a)));const d=["scopes","situational_context","model","kind","mode","lifecycle","name","listen"].filter(o=>i[o]!==void 0);return await N(e,t,d,u===void 0?void 0:async o=>{await o.prepare("UPDATE objects SET listen_json = ? WHERE id = ? AND type = 'node'").run(u,t)}),{status:200,body:await b(t)}}s(ti,"handleConfig");async function Oe(){return(await ue(process.cwd(),Ne()||null)).kinds}s(Oe,"daemonKinds");async function Ae(e){const n=Object.keys(await Oe());if(!n.includes(e))throw w(`unknown kind: ${e}`,{received:e,next:`Valid kinds: ${n.sort().join(", ")}.`})}s(Ae,"assertKindServer");async function ii(){const e=await Oe();return{status:200,body:{kinds:Object.keys(e).sort().map(t=>({kind:t,when_to_use:e[t]?.whenToUse??null,available_to:e[t]?.availableTo??null}))}}}s(ii,"handleListKinds");const Or=[{method:"POST",pattern:"/v1/nodes",scope:"crtr:act",handler:Ot},{method:"GET",pattern:"/v1/nodes",handler:Ct},{method:"GET",pattern:"/v1/kinds",handler:s(()=>ii(),"handler")},{method:"POST",pattern:"/v1/nodes/revive-all",scope:"crtr:act",handler:qt},{method:"GET",pattern:"/v1/nodes/:id",handler:Et},{method:"GET",pattern:"/v1/nodes/:id/snapshot",handler:Tt},{method:"GET",pattern:"/v1/nodes/:id/subject",handler:Pt},{method:"GET",pattern:"/v1/nodes/:id/messages",handler:Lt},{method:"GET",pattern:"/v1/nodes/:id/session",handler:jt},{method:"GET",pattern:"/v1/nodes/:id/transcript",handler:Mt},{method:"GET",pattern:"/v1/nodes/:id/context",handler:Gt},{method:"POST",pattern:"/v1/nodes/:id/fork",scope:"crtr:act",handler:Bt},{method:"POST",pattern:"/v1/nodes/:id/revive",scope:"crtr:act",handler:Kt},{method:"POST",pattern:"/v1/nodes/:id/relaunch-root",scope:"crtr:act",handler:Vt},{method:"POST",pattern:"/v1/nodes/:id/close",handler:Wt},{method:"POST",pattern:"/v1/nodes/:id/read",handler:zt},{method:"POST",pattern:"/v1/nodes/:id/recycle",scope:"crtr:act",handler:Jt},{method:"POST",pattern:"/v1/nodes/:id/demote",scope:"crtr:act",handler:Ut},{method:"POST",pattern:"/v1/nodes/:id/promote",scope:"crtr:act",handler:Yt},{method:"POST",pattern:"/v1/nodes/:id/yield",scope:"crtr:act",handler:Xt},{method:"GET",pattern:"/v1/nodes/:id/broker/structured-request",handler:Ht},{method:"POST",pattern:"/v1/nodes/:id/broker/goal",handler:Qt},{method:"POST",pattern:"/v1/nodes/:id/wait",handler:Zt},{method:"PATCH",pattern:"/v1/nodes/:id/config",handler:ti}];export{ti as handleConfig,Ot as handleCreate,Bt as handleFork,Ct as handleList,Yt as handlePromote,Xt as handleYield,Or as nodeRoutes,Nr as resolveCreateKind};
|