@north-light/cli 0.3.550 → 0.3.552
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/client.d.ts +11 -0
- package/dist/api/client.js +3 -3
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/charges.d.ts +122 -0
- package/dist/api/dto/charges.js +0 -0
- package/dist/api/dto/usage.d.ts +3 -3
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -1
- package/dist/api/routes.d.ts +3 -0
- package/dist/api/routes.js +1 -1
- package/dist/builtin-memory/crouter-sdk/release-notes.md +10 -0
- package/dist/clients/attach/viewer.js +50 -50
- package/dist/commands/sys/spend.d.ts +1 -0
- package/dist/commands/sys/spend.js +3 -0
- package/dist/commands/sys.js +1 -1
- package/dist/core/canvas/canvas.js +4 -4
- package/dist/core/canvas/export-sqlite.js +2 -2
- package/dist/core/canvas/import-sqlite.js +1 -1
- package/dist/core/canvas/person.js +7 -16
- package/dist/core/canvas/schema-pg.sql +61 -0
- package/dist/core/canvas/types.d.ts +4 -0
- package/dist/core/config.js +1 -1
- package/dist/core/grants/mirror.d.ts +2 -1
- package/dist/core/grants/mirror.js +2 -2
- package/dist/core/ledger/backfill.d.ts +12 -0
- package/dist/core/ledger/backfill.js +22 -0
- package/dist/core/ledger/charges.d.ts +18 -0
- package/dist/core/ledger/charges.js +1 -0
- package/dist/core/ledger/check.d.ts +44 -0
- package/dist/core/ledger/check.js +7 -0
- package/dist/core/ledger/index.d.ts +9 -0
- package/dist/core/ledger/index.js +1 -0
- package/dist/core/ledger/limits.d.ts +15 -0
- package/dist/core/ledger/limits.js +3 -0
- package/dist/core/ledger/months.d.ts +6 -0
- package/dist/core/ledger/months.js +1 -0
- package/dist/core/ledger/payer.d.ts +34 -0
- package/dist/core/ledger/payer.js +1 -0
- package/dist/core/ledger/read.d.ts +44 -0
- package/dist/core/ledger/read.js +3 -0
- package/dist/core/ledger/totals.d.ts +19 -0
- package/dist/core/ledger/totals.js +4 -0
- package/dist/core/ledger/types.d.ts +66 -0
- package/dist/core/ledger/types.js +0 -0
- package/dist/core/llm/run.d.ts +17 -5
- package/dist/core/llm/run.js +2 -2
- package/dist/core/providers/call.d.ts +7 -1
- package/dist/core/providers/call.js +1 -1
- package/dist/core/providers/errors.js +1 -1
- package/dist/core/providers/receipts.d.ts +7 -1
- package/dist/core/providers/receipts.js +1 -3
- package/dist/core/runs/operations.d.ts +1 -0
- package/dist/core/runs/operations.js +7 -7
- package/dist/core/runtime/broker/cli-relay.js +1 -1
- package/dist/core/runtime/broker/model-adapter.js +2 -2
- package/dist/core/runtime/broker/turn-cause.d.ts +7 -0
- package/dist/core/runtime/broker/turn-cause.js +1 -0
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/nodes.d.ts +2 -0
- package/dist/core/runtime/nodes.js +1 -1
- package/dist/core/runtime/recycle.js +1 -1
- package/dist/core/runtime/reset.js +1 -1
- package/dist/core/runtime/revive.js +2 -2
- package/dist/core/runtime/spawn.d.ts +2 -0
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/start-check.d.ts +15 -0
- package/dist/core/runtime/start-check.js +1 -0
- package/dist/core/runtime/warm-pool.js +1 -1
- package/dist/core/user-settings.d.ts +4 -0
- package/dist/core/user-settings.js +1 -1
- package/dist/daemon/api/app-listener.js +13 -13
- package/dist/daemon/api/handlers/bash-jobs.js +1 -1
- package/dist/daemon/api/handlers/charges.d.ts +3 -0
- package/dist/daemon/api/handlers/charges.js +1 -0
- package/dist/daemon/api/handlers/llm.d.ts +9 -5
- package/dist/daemon/api/handlers/llm.js +3 -3
- package/dist/daemon/api/handlers/messages.js +2 -2
- package/dist/daemon/api/handlers/providers.d.ts +2 -0
- package/dist/daemon/api/handlers/providers.js +1 -1
- package/dist/daemon/api/handlers/run-routes.js +1 -1
- package/dist/daemon/api/handlers/runs.d.ts +1 -1
- package/dist/daemon/api/handlers/runs.js +1 -1
- package/dist/daemon/api/operations.js +1 -1
- package/dist/daemon/api/router.d.ts +8 -0
- package/dist/daemon/api/router.js +1 -1
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/cron/authority.d.ts +1 -1
- package/dist/daemon/cron-run.js +2 -2
- package/dist/daemon/crtrd.js +10 -10
- package/dist/daemon/fleet.js +4 -4
- package/dist/daemon/reconcilers/action-lane.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +2 -0
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
- package/dist/doc-editor/editor.css +1 -1
- package/dist/doc-editor/editor.js +16 -16
- package/dist/types.d.ts +4 -0
- package/docs/sdk/release-notes.md +10 -0
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -13
- package/dist/core/usage/ledger.d.ts +0 -49
- package/dist/core/usage/ledger.js +0 -10
|
@@ -1 +1 @@
|
|
|
1
|
-
var J=Object.defineProperty;var l=(e,r)=>J(e,"name",{value:r,configurable:!0});import{envHomeOverride as K,envRuntimeHomeOverride as X,INBOX_BETWEEN_TURNS_ENV as z,SCOPES_FILE_ENV as V,scopeAllowed as I}from"../../shared/env.js";import{isOwnMemoryScope as Y,validateScopes as Q}from"../scopes.js";import{activeGrant as F,terminalGrant as k}from"../grants/mirror.js";import{grantSnapshotMissing as Z}from"../../daemon/readiness.js";import{appendRunEvent as ee}from"../runs/events.js";import{personId as ne}from"../canvas/person.js";import{InputError as S}from"../io.js";import{ApiError as g}from"../../api/errors.js";import{assertGranteeRunsHere as re}from"./unsandboxed.js";import{randomBytes as te}from"node:crypto";import{existsSync as B}from"node:fs";import{resolve as ie,relative as oe,isAbsolute as P,join as ae,sep as le}from"node:path";import{appSpace as se}from"../layout.js";import{scopesFilePath as de}from"../canvas/paths.js";import{createNode as ce,assertRunNotDeleting as ue,conversationOwner as fe,getNode as u,getRow as pe}from"../canvas/index.js";import{ensureAppSpace as me}from"../spaces/space.js";import{LAUNCHER_SOCKET as U}from"../../launcher/spec.js";import{resolveInstallId as _e}from"../canvas/install-id.js";import{isAppRun as we}from"../canvas/app-run.js";import{contextDir as ge}from"../canvas/paths.js";import{conversationIdFromPath as he}from"../conversation-store/index.js";import{usage as H}from"../errors.js";import{assertProfileAvailableForBirth as ve}from"../profiles/deletion-reservation.js";import{loadExactProfileManifest as Re}from"../profiles/manifest.js";import{admitNodeCreate as ye}from"../command-hooks/lifecycle-create.js";import{getById as Ee,nodeObject as C,ownerForGrantee as Ie}from"../graph/objects.js";import{recordActedOn as Ce}from"../graph/edges.js";import{recordWatch as Ne,copyWatchesForFork as ke}from"../graph/watches.js";import{publish as Se}from"../graph/events.js";import{canvasDatabaseUrl as Te}from"../canvas/db.js";import{someAsync as Oe}from"../async-array.js";import{admitIntoManagedCheckout as xe}from"../worktree-mutation-async.js";let T;const L=new Map;function hn(e){T=e}l(hn,"setInstallId");async function De(){if(T!==void 0)return T;const e=await Te(),r=L.get(e);if(r!==void 0)return r;const o=await _e();return L.set(e,o),o}l(De,"installId");function be(){return`${Date.now().toString(36)}-${te(4).toString("hex")}`}l(be,"newJobId");async function Ae(){return`${await De()}-${be()}`}l(Ae,"newNodeId");const O=128,Me=/^[a-z0-9-]+$/;class j extends Error{static{l(this,"NodeIdConflictError")}nodeId;constructor(r){super(`node already exists: ${r}`),this.nodeId=r,this.name="NodeIdConflictError"}}function x(e){if(e.length===0||e.length>O)throw H(`invalid --node-id '${e}': must be 1-${O} characters`,{next:`Pass an id-safe string (lowercase letters, digits, hyphens) of at most ${O} characters.`});if(!Me.test(e))throw H(`invalid --node-id '${e}': must contain only lowercase letters, digits, and hyphens (e.g. 'remote42', 'my-node-1')`,{next:"Use only lowercase letters, digits, and hyphens."})}l(x,"validateNodeIdFormat");async function vn(e){if(x(e),await u(e)!==null)throw new j(e)}l(vn,"preflightNodeId");async function $e(e){if(x(e),await u(e)!==null)throw new j(e);return e}l($e,"validatedExplicitNodeId");async function Rn(e){let r=e;const o=new Set;for(;;){if(o.has(r))return r;o.add(r);const s=await pe(r);if(s===null||s.parent==null)return r;r=s.parent}}l(Rn,"rootOfSpine");function yn(){const e=process.env;return{nodeId:e.CRTR_NODE_ID??null,kind:e.CRTR_KIND??null,mode:e.CRTR_MODE??null}}l(yn,"currentNodeContext");function Fe(e){return we(e)}l(Fe,"inboxBetweenTurns");function En(e){const r={CRTR_NODE_ID:e.node_id,CRTR_KIND:e.kind,CRTR_MODE:e.mode,CRTR_LIFECYCLE:e.lifecycle,CRTR_NODE_CWD:e.cwd,CRTR_CONTEXT_DIR:ge(e.node_id,e.grantee),CRTR_CYCLES:(e.cycles??0).toString(),CRTR_PROFILE_ID:e.profile_id??"",PI_CLAUDE_OAUTH_REINJECT_SCOPE:"never"};e.parent&&(r.CRTR_PARENT_NODE_ID=e.parent),e.run_id&&(r.CRTR_RUN_ID=e.run_id),Fe(e)&&(r[z]="1"),e.scopes!==null&&e.scopes!==void 0&&(r[V]=de(e.node_id)),r.CRTR_GRANTEE=e.grantee??"app:terminal";const o=K();o!==void 0&&o!==""&&(r.CRTR_HOME=o);const s=X();s!==void 0&&s!==""&&(r.CRTR_RUNTIME_HOME=s);const f=process.env.CRTR_SUBTREE;return f!==void 0&&f!==""&&(r.CRTR_SUBTREE=f),{...r,...e.launch?.env??{}}}l(En,"nodeEnv");async function Be(e){const r=he(e),o=r===null?null:await fe(r);return o===null?null:await u(o)}l(Be,"forkSourceNode");async function In(e){const r=e.nodeId!==void 0?(x(e.nodeId),e.nodeId):await Ae(),o=e.parent??null,s=o===null,f=e.spawnedBy??o,m=e.creator??null,D=e.mode??"base",N=e.lifecycle??(s?"resident":"terminal"),h=e.run===void 0?await k():null,n={node_id:r,name:e.name??e.kind,description:e.description,cycles:0,created:new Date().toISOString(),cwd:e.cwd,host_kind:"broker",profile_id:e.profile_id??null,kind:e.kind,mode:D,lifecycle:N,persona_ack:{kind:e.kind,mode:D,lifecycle:N},status:"active",parent:o,spawned_by:f,creator:m,fork_from:e.forkFrom,fork_source_file:e.forkSourceFile,review_binding:e.reviewBinding,model_override:e.modelOverride??null,scopes:e.scopes??null,isolated:e.isolated===!0,grantee:e.run?.grantee??"app:terminal",sub:e.run?.sub??h?.sub??null,grant_id:e.run?.grant_id??h?.id??null,client_id:e.run?.client_id??null,metadata_json:s?e.run?.metadata_json??null:null,run_id:s?r:e.run?.run_id??null,event_cursor:s?e.run?.event_cursor??1:null,usage_json:s?e.run?.usage_json??JSON.stringify({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}):null,passive_default:e.passiveDefault??!1,...e.managedWorktree!==void 0?{managed_worktree:e.managedWorktree}:{},intent:null,deadline_at:e.deadlineAt??null,pi_session_id:null,pi_session_file:null,launch:e.launch},y=e.scopes===void 0?void 0:Q(e.scopes),v=o===null?null:await u(o);if(o!==null&&v===null)throw new Error(`cannot spawn under unknown parent node: ${o}`);if(v?.run_id&&(await u(v.run_id))?.deleting_at)throw new Error("run is deleting");const c=m===null?null:await u(m);if(m!==null&&c===null)throw new Error(`cannot spawn from unknown creator node: ${m}`);if(c?.run_id&&(await u(c.run_id))?.deleting_at)throw new Error("run is deleting");const b=e.forkSourceFile==null?null:await Be(e.forkSourceFile),A=e.replaces==null?null:await u(e.replaces),_=v??b??A??c??(f===null?null:await u(f)),q=[v,c,b,A,f===null?null:await u(f)],M=await Oe(q,async t=>t?.isolated===!0||t?.run_id!=null&&(await u(t.run_id))?.isolated===!0);if(M&&e.isolated===!1)throw new g(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});if(n.isolated=M||e.isolated===!0,_!==null){const t=c??_;if(c&&_.grantee&&c.grantee&&c.grantee!==_.grantee)throw new g(403,"other_app_run","cannot create under another app's node");const i=c&&c!==_?[_,c]:[_],d=[],w=new Set;for(const a of i){a.scopes!==null&&a.scopes!==void 0&&d.push(a.scopes);const p=a.grantee==="app:terminal"?await k():a.grant_id?await F(a.grant_id):null;if(p){const R=[...p.resolved];w.add(R),d.push(R)}else{const R=[];w.add(R),d.push(R)}}const E=l(a=>Y(a,t.grantee??"app:terminal"),"ownMemory"),$=l((a,p)=>E(p)&&w.has(a)||I(a,p),"allowed");if(y!==void 0&&!y.every(a=>d.every(p=>$(p,a))))throw new S({error:"unknown_scope",message:"child scopes must be covered by the creating node, its source and their current grants",received:y,field:"scopes",next:"Request only scopes the creating node currently holds."});if(n.scopes=y??(i.every(a=>a.scopes==null)&&i.every(a=>a.grant_id===t.grant_id&&a.sub===t.sub)?null:i.length===1?_.scopes??null:[...new Set(d.flat().filter(a=>d.every(p=>$(p,a))))]),n.scopes?.includes("crtr:act")&&!I(n.scopes,"crtr:llm"))throw new S({error:"invalid_scope",message:"crtr:act requires crtr:llm",received:n.scopes,field:"scopes",next:"Include crtr:llm or omit crtr:act."});n.grantee=t.grantee,n.sub=t.sub??(n.grantee==="app:terminal"?h?.sub:null)??null,n.grant_id=t.grant_id??(n.grantee==="app:terminal"?h?.id:null)??null,n.client_id=t.client_id,n.run_id=s?r:t.run_id??null}if(re(n.grantee),e.run===void 0&&n.grantee==="app:terminal"&&h===null)throw await Z()?new g(503,"runtime_starting","the first grant snapshot from the directory has not committed"):new g(403,"scope_missing","terminal grant is not active");if(n.isolated){if(process.platform!=="linux"||!B(U))throw new g(400,"isolated_unavailable","isolated nodes require the Linux root launcher");if(e.managedWorktree!==void 0)throw new g(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const t=ae(se(n.grantee??"app:terminal").nodes,r),i=oe(t,ie(n.cwd));if(!P(n.cwd)||i===".."||i.startsWith(`..${le}`)||P(i))throw new g(400,"invalid_request","isolated node cwd must be inside its own folder",{param:"cwd"})}if(n.profile_id){const t=Re(n.profile_id).manifest.grantee??"app:terminal";if(t!==n.grantee){const i=`crtr:memory:rw:${t}:profile:${n.profile_id}`,d=n.grantee==="app:terminal"?await k():n.grant_id?await F(n.grant_id):null;if(!d||d.grantee!==n.grantee||!I(d.resolved,i)||!I(n.scopes,i))throw new S({error:"scope_missing",message:`missing scope ${i}`,received:n.profile_id,field:"profile",next:"Select a profile covered by this run and its current grant."})}}if(ve(n.profile_id??null),!n.grantee)throw new Error("node creation requires an app");const W=await ye({kind:n.kind,mode:n.mode,cwd:n.cwd,profile:n.profile_id??null,root:s,parentId:o,requestingNodeId:m,lifecycle:N,replaces:e.replaces??null},n.grantee),G=l(async(t,i)=>{const d=await C(t,i.node_id),w=m??o??e.actor??f??null,E=w!==null&&(await Ee(t,w))?.type==="node"?await C(t,w):await Ie(t,e.run===void 0?ne():i.grantee);await Ce(t,E,d),o!==null&&e.subscribe!==!1&&await Ne(t,await C(t,o),d,"spawn"),e.forkSourceNode&&await ke(t,await C(t,e.forkSourceNode),d),await Se(t,{event:"created",object:d,actor:E,attrs:{name:i.name,kind:i.kind,creator:m??null}})},"recordBirth");try{e.nodeId!==void 0&&await $e(e.nodeId),await e.beforeCreate?.(),(process.platform!=="linux"||B(U))&&await me(n.grantee??"app:terminal"),await xe(n.cwd,r,()=>ce(n,{outcomeDelivery:e.outcomeDelivery,withinCreate:l(async(t,i)=>{i.run_id&&i.run_id!==i.node_id&&await ue(t,i.run_id),s&&e.run===void 0&&await ee(t,r,r,"run.started",{scopes:i.scopes??null,payer:"user",usage:JSON.parse(i.usage_json)}),await e.withinCreate?.(t,i),await G(t,i)},"withinCreate")}))}finally{W()}return n}l(In,"spawnNode");export{j as NodeIdConflictError,yn as currentNodeContext,Be as forkSourceNode,Fe as inboxBetweenTurns,be as newJobId,Ae as newNodeId,En as nodeEnv,vn as preflightNodeId,Rn as rootOfSpine,hn as setInstallId,In as spawnNode};
|
|
1
|
+
var J=Object.defineProperty;var l=(e,r)=>J(e,"name",{value:r,configurable:!0});import{envHomeOverride as K,envRuntimeHomeOverride as X,INBOX_BETWEEN_TURNS_ENV as z,SCOPES_FILE_ENV as V,scopeAllowed as I}from"../../shared/env.js";import{isOwnMemoryScope as Y,validateScopes as Q}from"../scopes.js";import{activeGrant as F,terminalGrant as k}from"../grants/mirror.js";import{grantSnapshotMissing as Z}from"../../daemon/readiness.js";import{appendRunEvent as ee}from"../runs/events.js";import{personId as ne}from"../canvas/person.js";import{InputError as S}from"../io.js";import{ApiError as g}from"../../api/errors.js";import{assertGranteeRunsHere as re}from"./unsandboxed.js";import{randomBytes as te}from"node:crypto";import{existsSync as B}from"node:fs";import{resolve as ie,relative as oe,isAbsolute as P,join as ae,sep as le}from"node:path";import{appSpace as se}from"../layout.js";import{scopesFilePath as de}from"../canvas/paths.js";import{createNode as ce,assertRunNotDeleting as ue,conversationOwner as fe,getNode as u,getRow as pe}from"../canvas/index.js";import{ensureAppSpace as me}from"../spaces/space.js";import{LAUNCHER_SOCKET as U}from"../../launcher/spec.js";import{resolveInstallId as _e}from"../canvas/install-id.js";import{isAppRun as we}from"../canvas/app-run.js";import{contextDir as ge}from"../canvas/paths.js";import{conversationIdFromPath as he}from"../conversation-store/index.js";import{usage as H}from"../errors.js";import{assertProfileAvailableForBirth as ve}from"../profiles/deletion-reservation.js";import{loadExactProfileManifest as Re}from"../profiles/manifest.js";import{admitNodeCreate as ye}from"../command-hooks/lifecycle-create.js";import{getById as Ee,nodeObject as C,ownerForGrantee as Ie}from"../graph/objects.js";import{recordActedOn as Ce}from"../graph/edges.js";import{recordWatch as Ne,copyWatchesForFork as ke}from"../graph/watches.js";import{publish as Se}from"../graph/events.js";import{canvasDatabaseUrl as Te}from"../canvas/db.js";import{someAsync as Oe}from"../async-array.js";import{admitIntoManagedCheckout as xe}from"../worktree-mutation-async.js";let T;const L=new Map;function hn(e){T=e}l(hn,"setInstallId");async function De(){if(T!==void 0)return T;const e=await Te(),r=L.get(e);if(r!==void 0)return r;const o=await _e();return L.set(e,o),o}l(De,"installId");function be(){return`${Date.now().toString(36)}-${te(4).toString("hex")}`}l(be,"newJobId");async function Ae(){return`${await De()}-${be()}`}l(Ae,"newNodeId");const O=128,Me=/^[a-z0-9-]+$/;class j extends Error{static{l(this,"NodeIdConflictError")}nodeId;constructor(r){super(`node already exists: ${r}`),this.nodeId=r,this.name="NodeIdConflictError"}}function x(e){if(e.length===0||e.length>O)throw H(`invalid --node-id '${e}': must be 1-${O} characters`,{next:`Pass an id-safe string (lowercase letters, digits, hyphens) of at most ${O} characters.`});if(!Me.test(e))throw H(`invalid --node-id '${e}': must contain only lowercase letters, digits, and hyphens (e.g. 'remote42', 'my-node-1')`,{next:"Use only lowercase letters, digits, and hyphens."})}l(x,"validateNodeIdFormat");async function vn(e){if(x(e),await u(e)!==null)throw new j(e)}l(vn,"preflightNodeId");async function $e(e){if(x(e),await u(e)!==null)throw new j(e);return e}l($e,"validatedExplicitNodeId");async function Rn(e){let r=e;const o=new Set;for(;;){if(o.has(r))return r;o.add(r);const s=await pe(r);if(s===null||s.parent==null)return r;r=s.parent}}l(Rn,"rootOfSpine");function yn(){const e=process.env;return{nodeId:e.CRTR_NODE_ID??null,kind:e.CRTR_KIND??null,mode:e.CRTR_MODE??null}}l(yn,"currentNodeContext");function Fe(e){return we(e)}l(Fe,"inboxBetweenTurns");function En(e){const r={CRTR_NODE_ID:e.node_id,CRTR_KIND:e.kind,CRTR_MODE:e.mode,CRTR_LIFECYCLE:e.lifecycle,CRTR_NODE_CWD:e.cwd,CRTR_CONTEXT_DIR:ge(e.node_id,e.grantee),CRTR_CYCLES:(e.cycles??0).toString(),CRTR_PROFILE_ID:e.profile_id??"",PI_CLAUDE_OAUTH_REINJECT_SCOPE:"never"};e.parent&&(r.CRTR_PARENT_NODE_ID=e.parent),e.run_id&&(r.CRTR_RUN_ID=e.run_id),Fe(e)&&(r[z]="1"),e.scopes!==null&&e.scopes!==void 0&&(r[V]=de(e.node_id)),r.CRTR_GRANTEE=e.grantee??"app:terminal";const o=K();o!==void 0&&o!==""&&(r.CRTR_HOME=o);const s=X();s!==void 0&&s!==""&&(r.CRTR_RUNTIME_HOME=s);const f=process.env.CRTR_SUBTREE;return f!==void 0&&f!==""&&(r.CRTR_SUBTREE=f),{...r,...e.launch?.env??{}}}l(En,"nodeEnv");async function Be(e){const r=he(e),o=r===null?null:await fe(r);return o===null?null:await u(o)}l(Be,"forkSourceNode");async function In(e){const r=e.nodeId!==void 0?(x(e.nodeId),e.nodeId):await Ae(),o=e.parent??null,s=o===null,f=e.spawnedBy??o,m=e.creator??null,D=e.mode??"base",N=e.lifecycle??(s?"resident":"terminal"),h=e.run===void 0?await k():null,n={node_id:r,name:e.name??e.kind,description:e.description,cycles:0,created:new Date().toISOString(),cwd:e.cwd,host_kind:"broker",profile_id:e.profile_id??null,kind:e.kind,mode:D,lifecycle:N,persona_ack:{kind:e.kind,mode:D,lifecycle:N},status:"active",parent:o,spawned_by:f,creator:m,fork_from:e.forkFrom,fork_source_file:e.forkSourceFile,review_binding:e.reviewBinding,model_override:e.modelOverride??null,scopes:e.scopes??null,isolated:e.isolated===!0,grantee:e.run?.grantee??"app:terminal",sub:e.run?.sub??h?.sub??null,grant_id:e.run?.grant_id??h?.id??null,client_id:e.run?.client_id??null,metadata_json:s?e.run?.metadata_json??null:null,run_id:s?r:e.run?.run_id??null,event_cursor:s?e.run?.event_cursor??1:null,usage_json:s?e.run?.usage_json??JSON.stringify({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}):null,passive_default:e.passiveDefault??!1,caused_by:e.causedBy??null,...e.managedWorktree!==void 0?{managed_worktree:e.managedWorktree}:{},intent:null,deadline_at:e.deadlineAt??null,pi_session_id:null,pi_session_file:null,launch:e.launch},y=e.scopes===void 0?void 0:Q(e.scopes),v=o===null?null:await u(o);if(o!==null&&v===null)throw new Error(`cannot spawn under unknown parent node: ${o}`);if(v?.run_id&&(await u(v.run_id))?.deleting_at)throw new Error("run is deleting");const c=m===null?null:await u(m);if(m!==null&&c===null)throw new Error(`cannot spawn from unknown creator node: ${m}`);if(c?.run_id&&(await u(c.run_id))?.deleting_at)throw new Error("run is deleting");const b=e.forkSourceFile==null?null:await Be(e.forkSourceFile),A=e.replaces==null?null:await u(e.replaces),_=v??b??A??c??(f===null?null:await u(f)),q=[v,c,b,A,f===null?null:await u(f)],M=await Oe(q,async t=>t?.isolated===!0||t?.run_id!=null&&(await u(t.run_id))?.isolated===!0);if(M&&e.isolated===!1)throw new g(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});if(n.isolated=M||e.isolated===!0,_!==null){const t=c??_;if(c&&_.grantee&&c.grantee&&c.grantee!==_.grantee)throw new g(403,"other_app_run","cannot create under another app's node");const i=c&&c!==_?[_,c]:[_],d=[],w=new Set;for(const a of i){a.scopes!==null&&a.scopes!==void 0&&d.push(a.scopes);const p=a.grantee==="app:terminal"?await k():a.grant_id?await F(a.grant_id):null;if(p){const R=[...p.resolved];w.add(R),d.push(R)}else{const R=[];w.add(R),d.push(R)}}const E=l(a=>Y(a,t.grantee??"app:terminal"),"ownMemory"),$=l((a,p)=>E(p)&&w.has(a)||I(a,p),"allowed");if(y!==void 0&&!y.every(a=>d.every(p=>$(p,a))))throw new S({error:"unknown_scope",message:"child scopes must be covered by the creating node, its source and their current grants",received:y,field:"scopes",next:"Request only scopes the creating node currently holds."});if(n.scopes=y??(i.every(a=>a.scopes==null)&&i.every(a=>a.grant_id===t.grant_id&&a.sub===t.sub)?null:i.length===1?_.scopes??null:[...new Set(d.flat().filter(a=>d.every(p=>$(p,a))))]),n.scopes?.includes("crtr:act")&&!I(n.scopes,"crtr:llm"))throw new S({error:"invalid_scope",message:"crtr:act requires crtr:llm",received:n.scopes,field:"scopes",next:"Include crtr:llm or omit crtr:act."});n.grantee=t.grantee,n.sub=t.sub??(n.grantee==="app:terminal"?h?.sub:null)??null,n.grant_id=t.grant_id??(n.grantee==="app:terminal"?h?.id:null)??null,n.client_id=t.client_id,n.run_id=s?r:t.run_id??null}if(re(n.grantee),e.run===void 0&&n.grantee==="app:terminal"&&h===null)throw await Z()?new g(503,"runtime_starting","the first grant snapshot from the directory has not committed"):new g(403,"scope_missing","terminal grant is not active");if(n.isolated){if(process.platform!=="linux"||!B(U))throw new g(400,"isolated_unavailable","isolated nodes require the Linux root launcher");if(e.managedWorktree!==void 0)throw new g(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const t=ae(se(n.grantee??"app:terminal").nodes,r),i=oe(t,ie(n.cwd));if(!P(n.cwd)||i===".."||i.startsWith(`..${le}`)||P(i))throw new g(400,"invalid_request","isolated node cwd must be inside its own folder",{param:"cwd"})}if(n.profile_id){const t=Re(n.profile_id).manifest.grantee??"app:terminal";if(t!==n.grantee){const i=`crtr:memory:rw:${t}:profile:${n.profile_id}`,d=n.grantee==="app:terminal"?await k():n.grant_id?await F(n.grant_id):null;if(!d||d.grantee!==n.grantee||!I(d.resolved,i)||!I(n.scopes,i))throw new S({error:"scope_missing",message:`missing scope ${i}`,received:n.profile_id,field:"profile",next:"Select a profile covered by this run and its current grant."})}}if(ve(n.profile_id??null),!n.grantee)throw new Error("node creation requires an app");const W=await ye({kind:n.kind,mode:n.mode,cwd:n.cwd,profile:n.profile_id??null,root:s,parentId:o,requestingNodeId:m,lifecycle:N,replaces:e.replaces??null},n.grantee),G=l(async(t,i)=>{const d=await C(t,i.node_id),w=m??o??e.actor??f??null,E=w!==null&&(await Ee(t,w))?.type==="node"?await C(t,w):await Ie(t,e.run===void 0?ne():i.grantee);await Ce(t,E,d),o!==null&&e.subscribe!==!1&&await Ne(t,await C(t,o),d,"spawn"),e.forkSourceNode&&await ke(t,await C(t,e.forkSourceNode),d),await Se(t,{event:"created",object:d,actor:E,attrs:{name:i.name,kind:i.kind,creator:m??null}})},"recordBirth");try{e.nodeId!==void 0&&await $e(e.nodeId),await e.beforeCreate?.(),(process.platform!=="linux"||B(U))&&await me(n.grantee??"app:terminal"),await xe(n.cwd,r,()=>ce(n,{outcomeDelivery:e.outcomeDelivery,withinCreate:l(async(t,i)=>{i.run_id&&i.run_id!==i.node_id&&await ue(t,i.run_id),s&&e.run===void 0&&await ee(t,r,r,"run.started",{scopes:i.scopes??null,payer:"user",usage:JSON.parse(i.usage_json)}),await e.withinCreate?.(t,i),await G(t,i)},"withinCreate")}))}finally{W()}return n}l(In,"spawnNode");export{j as NodeIdConflictError,yn as currentNodeContext,Be as forkSourceNode,Fe as inboxBetweenTurns,be as newJobId,Ae as newNodeId,En as nodeEnv,vn as preflightNodeId,Rn as rootOfSpine,hn as setInstallId,In as spawnNode};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var p=Object.defineProperty;var n=(e,t)=>p(e,"name",{value:t,configurable:!0});import{abortExecution as y,beginExecution as _,getNode as s,setPresence as h,setFocusOccupant as v,fullName as R,recordExecutionPid as b,recordLaunch as
|
|
1
|
+
var p=Object.defineProperty;var n=(e,t)=>p(e,"name",{value:t,configurable:!0});import{abortExecution as y,beginExecution as _,getNode as s,setPresence as h,setFocusOccupant as v,fullName as R,recordExecutionPid as b,recordLaunch as k}from"../canvas/index.js";import{pushFinal as E}from"../feed/feed.js";import{newestReportBody as g}from"../feed/reports.js";import{spawnNode as S,rootOfSpine as x}from"./nodes.js";import{buildLaunchSpecAsync as T,buildPiArgv as B}from"./launch.js";import{focusOf as N,respawnPaneSync as O,setPaneOption as P}from"./placement.js";import{waitForBrokerViewSocket as C,viewerSplitEnv as D}from"./placement-tmux.js";import{headlessBrokerHost as u}from"./host.js";import{boundFleet as F}from"./fleet.js";import{transition as z}from"./lifecycle.js";import{ensureDaemon as A}from"../../daemon/manage.js";import{invokeBirthLifecycleHooks as L}from"./spawn.js";import{checkStart as U}from"./start-check.js";async function ne(e,t){const a=await s(e);if(a===null)return{recycled:!1,finalized:!1,newRoot:null,delivered:[]};const o=t??process.env.TMUX_PANE;if(o===void 0||o==="")return{recycled:!1,finalized:!1,newRoot:null,delivered:[]};await U(a);const w=await N(e);try{A()}catch{}const{launch:f}=await T("general","base",{lifecycle:"resident",hasManager:!1,cwd:a.cwd,profileId:a.profile_id}),m=await g(e)||`Closed via recycle \u2014 no final summary was authored by ${a.name}.`;let c=[],d=!1;const r=await S({kind:"general",mode:"base",lifecycle:"resident",cwd:a.cwd,name:"general",parent:null,replaces:e,profile_id:a.profile_id,launch:f,beforeCreate:n(async()=>{try{c=(await E(e,m)).deliveredTo,d=!0}catch{}},"beforeCreate")}),i=await s(r.node_id);await L(i);const l=B(i);if(l.env={...l.env,CRTR_SUBTREE:await x(r.node_id)},!await H(i,l))return{recycled:!1,finalized:d,newRoot:r.node_id,delivered:c};try{u.teardown(e)}catch{}try{await h(e,{pane:null,window:null,tmux_session:null})}catch{}if(w!==null)try{await v(w.focus_id,r.node_id)}catch{}return{recycled:V(i,o),finalized:d,newRoot:r.node_id,delivered:c}}n(ne,"recycleNode");async function H(e,t){const a=await _(e.node_id,{daemonEpoch:F().epoch()});t.env={...t.env,CRTR_EXECUTION_ID:a};let o;try{if(o=await u.launch(e.node_id,t,{cwd:e.cwd,name:R(e),resuming:!1}),o.pid===null)throw new Error("broker host returned no pid");if(await k(e.node_id,new Date().toISOString()),await b(a,e.node_id,o.pid)==="shutdown")throw new Error("broker execution was superseded");if(await C(e.node_id,o.exited))return!0}catch{await y(a,{reason:"launch_failed"})}try{await M(e.node_id)}catch{}try{u.teardown(e.node_id)}catch{}return!1}n(H,"launchRecycledBroker");async function M(e){const t=await s(e);(t?.status==="active"||t?.status==="idle")&&await z(e,"crash")}n(M,"transitionReplacementToDead");function V(e,t){try{P(t,"@crtr_node","")}catch{}return O({pane:t,cwd:e.cwd,env:D(),command:`crtr surface attach to ${e.node_id}`})}n(V,"respawnRecycledViewer");export{ne as recycleNode};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var S=Object.defineProperty;var s=(e,
|
|
1
|
+
var S=Object.defineProperty;var s=(e,a)=>S(e,"name",{value:a,configurable:!0});import{getNode as f,beginExecution as B,recordExecutionPid as N,abortExecution as v,bindSession as b,recordLaunch as g,fullName as x,liveExecutionForNode as F,closeFocusRow as R,view as O}from"../canvas/index.js";import{transition as r}from"./lifecycle.js";import{headlessBrokerHost as y,requestBrokerTeardown as V}from"./host.js";import{boundFleet as C}from"./fleet.js";import{tearDownNode as D,focusOf as P,registerViewerFocus as T,respawnPaneSync as I,windowOfPane as L,renameWindow as q}from"./placement.js";import{viewerSplitEnv as A,waitForBrokerViewSocket as H}from"./placement-tmux.js";import{buildLaunchSpecAsync as M,buildPiArgv as U}from"./launch.js";import{newNodeId as j,spawnNode as W,rootOfSpine as X}from"./nodes.js";import{appSpace as $}from"../layout.js";import{join as z}from"node:path";import{invokeBirthLifecycleHooks as G}from"./spawn.js";import{checkStart as J}from"./start-check.js";async function K(e){const a=[];for(const i of await O(e))try{await r(i,"cancel",{reason:"closed"}),V(i),await D(i),a.push(i)}catch{}return a}s(K,"reapDescendants");async function ue(e,a={}){const i=a.launchBroker??y.launch,l=a.waitForViewSocket??H,p=a.respawnViewer??I,c=a.teardownBroker??y.teardown,n=await f(e);if(n===null||n.parent!=null||n.status==="done")return null;await J(n);const d=await P(e),h=n.isolated?await j():void 0,_=h?z($(n.grantee??"app:terminal").nodes,h):n.cwd,{launch:E}=await M(n.kind,"base",{lifecycle:"resident",hasManager:!1,model:n.model_override??void 0,modelIntent:n.launch?.modelIntent,modelExact:n.launch?.modelExact,cwd:_,profileId:n.profile_id}),t=await W({nodeId:h,kind:n.kind,mode:"base",lifecycle:"resident",cwd:_,name:n.kind,parent:null,replaces:e,profile_id:n.profile_id,launch:E,modelOverride:n.model_override??void 0});await G(t);const u=U(t,{});u.env={...u.env,CRTR_SUBTREE:await X(t.node_id)};const w=await B(t.node_id,{daemonEpoch:C().epoch()});u.env={...u.env,CRTR_EXECUTION_ID:w};let m;try{m=await i(t.node_id,u,{cwd:_,name:x(t),resuming:!1})}catch(o){throw await v(w,{reason:"launch_failed"}),await r(t.node_id,"crash"),o}if(m.pid==null)return await v(w,{reason:"launch_failed"}),await r(t.node_id,"crash"),null;if(await g(t.node_id,new Date().toISOString()),await N(w,t.node_id,m.pid)==="shutdown"){await v(w,{reason:"superseded"});try{c(t.node_id)}catch{}return await r(t.node_id,"crash"),null}let k=!1;try{k=await l(t.node_id,m.exited)}catch{}if(!k){const o=await f(t.node_id);(o?.status==="active"||o?.status==="idle")&&await r(t.node_id,"crash");try{c(t.node_id)}catch{}return null}if(await K(e),await r(e,"finish"),d?.pane!=null){await R(d.focus_id),p({pane:d.pane,cwd:n.cwd,env:A(),command:`crtr surface attach to ${t.node_id}`});const o=L(d.pane);o!==null&&q(o,x(t)),await T(t.node_id,d.pane,d.session,o)}return c(e),{newNodeId:t.node_id}}s(ue,"relaunchRoot");async function Q(e,a,i){const l=await f(e),p={reaped:[],detached:[],reset:!1};if(l===null||l.parent==null)return p;if(a!==void 0){const c=await F(e);c!==null&&await b(e,{executionId:c.executionId,sessionId:a,transcriptPath:i??null})}return p}s(Q,"resetRoot");async function we(e,a,i){return await f(e)===null?{path:"noop"}:(await Q(e,a,i),{path:"reset-child"})}s(we,"handleNewSession");async function fe(e,a){if(a!=="quit")return!1;const i=await f(e);return i===null||i.status!=="active"&&i.status!=="idle"||i.intent!=null?!1:(await r(e,"finish"),!0)}s(fe,"markCleanExitDone");export{we as handleNewSession,fe as markCleanExitDone,K as reapDescendants,ue as relaunchRoot,Q as resetRoot};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
1
|
+
var q=Object.defineProperty;var s=(e,r)=>q(e,"name",{value:r,configurable:!0});import{assertGranteeRunsHere as Q}from"./unsandboxed.js";import{existsSync as B}from"node:fs";import{conversationIdFromPath as h,conversationStore as d,ConversationNotFoundError as D}from"../conversation-store/index.js";import{isAbsolute as Z}from"node:path";import{findNodeBySessionFile as I,getNode as R,updateNode as E,beginExecution as ee,recordExecutionPid as re,abortExecution as S,endLiveExecution as ie,unbindSession as O,recordLaunch as te,setFrozen as ne,clearFrozen as oe,fullName as T}from"../canvas/index.js";import{emitEvent as ae}from"../events/emit.js";import{consumeDeadlineOnWake as se}from"../feed/messages.js";import{isParked as z,transition as x}from"./lifecycle.js";import{publishNotice as le}from"./close.js";import{InputError as $}from"../io.js";import{buildPiArgv as p}from"./launch.js";import{buildReviveKickoff as ce,drainBearings as ue,hasRetainedReports as fe,readGoal as k,readYieldMessage as we,RUNTIME_RESTART_CONTINUATION as de}from"./kickoff.js";import{readRoadmap as H}from"./roadmap.js";import{encodeKickoffOrigin as he,KICKOFF_ORIGIN_ENV as pe}from"./stamp/protocol.js";import{headlessBrokerHost as M}from"./host.js";import{appMemoryFull as ve,appMemoryTooSmall as me,boundFleet as U,brokerCapReached as _e,brokerThresholdsForDaemon as K}from"./fleet.js";import{admitBrokerMemory as ye}from"./memory-admission.js";import{beginBootFaultAttempt as ke,clearFault as ge,hasAdmittedTurn as be}from"../canvas/recovery.js";import{clearNodeLedger as G,forkNodeLedger as Re,noticeChangedWhileDone as Ee}from"./ledger.js";import{forkSourceNode as Se,rootOfSpine as xe}from"./nodes.js";import{checkStart as $e}from"./start-check.js";import{isReviewCompanionBound as Ce}from"../review/companion.js";import{assertProfileActive as Ne}from"../profiles/manifest.js";import{isPidAlive as Ae}from"../canvas/pid.js";import{crtrHome as Fe,jobDir as Pe}from"../canvas/paths.js";import{contextDir as Be,ensureNodeDirs as De,nodeAgentDir as Oe}from"../canvas/node-agent-paths.js";import{discoverLifecycleHookRegistry as Te}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as ze}from"../command-hooks/transport/exec-lifecycle.js";async function He(e,r){const i=e.pi_session_file,t=i?h(i):null;if(t===null)return{};try{const n=await d().header(t);return r?{resumeSessionPath:n.path}:{resumeSessionPath:n.path,newCycle:!0}}catch(n){if(n instanceof D)return{};throw n}}s(He,"resumeArgs");async function L(e){const r=h(e);if(r===null)return!1;try{return await d().header(r),!0}catch(i){if(i instanceof D)return!1;throw i}}s(L,"conversationExists");async function Me(e){const r=h(e);return r===null?!0:(await d().read(r)).entries.some(i=>i.type==="message")}s(Me,"sessionHasConversation");async function Ue(e){const r=h(e);if(r===null)return!0;const i=(await d().header(r)).header.cwd;return typeof i!="string"||B(i)}s(Ue,"sessionCwdExists");async function Ke(e,r,i){const t=r.pi_session_file;if(!t||!await L(t))return{};const n=await I(t);return n!==null&&n.node_id!==e&&Ae(n.pi_pid)?{}:await Ue(t)?await He(r,i):{}}s(Ke,"resumableSessionArgs");async function Ge(e){return await H(e)===null&&await we(e)===null&&!await fe(e)}s(Ge,"isUnstartedBirth");async function kr(e){const r=await k(e);if(r!==null&&r.trim()!=="")return!0;const i=await H(e);return i!==null&&i.trim()!==""}s(kr,"hasFreshGroundState");async function gr(e,r){const i=await j(e,r,!0);if(i.parked)throw new Error(`reviveNode: internal parked decision for activating revive ${e}`);return i.result}s(gr,"reviveNode");async function br(e,r,i){return j(e,{...r,viewerAttach:!0},i)}s(br,"decideAttachRevive");async function j(e,r,i){let t=await R(e);if(t===null)throw new Error(`reviveNode: unknown node ${e}`);if(t=await R(e)??t,t.run_id&&(await R(t.run_id))?.deleting_at)throw new Error("run is deleting");if(t.final_report!==null)throw new Error(`reviveNode: refusing to revive ${e} \u2014 its finalization latch is set (final_report=${t.final_report}). A final landed between the caller's reopen-gate check and this revive; re-run with --reopen if this retask is still wanted.`);Ne(t.profile_id),Q(t.grantee);const n=U();if(!n.has(e)&&!n.isClaimed(e)&&r.wakeReason!=="runtime-restart-abort"&&r.viewerAttach!==!0&&!(!i&&t.lifecycle==="resident"&&z(t))&&await $e(t),n.has(e))return await x(e,t.intent==="refresh"?"refresh-launch":"revive"),{parked:!1,result:{window:null,session:t.tmux_session??null,resumed:!1,outcome:"already-live"}};if(n.isClaimed(e))return{parked:!1,result:{window:null,session:t.tmux_session??null,resumed:!1,outcome:"already-live"}};if(!i&&t.lifecycle==="resident"&&z(t))return{parked:!0};const l=n.reserveSlot(e);let a=null;if(l){try{a=await ye(e)}catch(u){throw n.releaseReservation(e),u}a.verdict!=="admitted"&&n.releaseReservation(e)}if(a?.verdict==="too_small")throw me(a);if(!l||a?.verdict==="denied"){if(r.capacity==="refuse")throw a?.verdict==="denied"?ve(a):_e(K().automaticReviveCap,n.size());return t.frozen_at==null&&(await ne(e,new Date().toISOString()),await ie(e,{reason:"frozen"}),ae({level:"info",event:"broker.frozen",node_id:e,fields:a?.verdict==="denied"?{reason:"app_memory",free_bytes:a.free_bytes,needed_bytes:a.needed_bytes}:{reason:"broker_cap",live_count:n.size(),hard_cap:K().automaticReviveCap}})),{parked:!1,result:{window:null,session:t.tmux_session??null,resumed:!1,outcome:"frozen"}}}try{return{parked:!1,result:await Le(e,t,r)}}finally{n.releaseReservation(e)}}s(j,"decideRevive");async function Le(e,r,i){if(!B(r.cwd)){const v=r.fork_from!=null?`Restore ${r.cwd}, then revive the fork normally with \`crtr node lifecycle revive ${e}\`.`:r.managed_worktree?.state==="open"?"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon recovery.":`Recreate ${r.cwd}, or repair it with \`crtr node config --cwd <path> --node ${e}\`; durable node work resumes in a fresh conversation. Then retry \`crtr node lifecycle revive ${e}\`.`;throw new $({error:"cwd_missing",message:`${e} cannot be revived \u2014 its recorded cwd no longer exists: ${r.cwd}`,next:v})}r.host_kind!=="broker"&&(await E(e,{host_kind:"broker"}),r.host_kind="broker"),r.review_binding!=null&&!await Ce(e)&&(r.pi_session_id!=null||r.pi_session_file!=null)&&(await O(e),r.pi_session_id=null,r.pi_session_file=null);const n=r.fork_from!=null&&r.pi_session_id==null,l=r.fork_source_file;if(n&&(typeof l!="string"||!Z(l)))throw new $({error:"fork_source_invalid",message:`${e} cannot be revived \u2014 its resolved fork source file is missing or invalid.`,next:`Restore the node's fork source metadata, then retry \`crtr node lifecycle revive ${e}\`.`});const a=n&&typeof l=="string";if(a&&!await L(l))throw new $({error:"fork_from_missing",message:`${e} cannot be revived \u2014 its fork source no longer exists: ${l}`,next:`Restore ${l}, or update the node's fork source, then retry \`crtr node lifecycle revive ${e}\`.`});const u=await ee(e,{daemonEpoch:U().epoch()});try{r.cycles=(r.cycles??0)+1,await E(e,{cycles:r.cycles});const W=r.intent==="refresh"||r.cycle_pending===!0?!1:i.resume,w=a?{}:await Ke(e,r,W),m=w.resumeSessionPath!==void 0,C=m&&w.newCycle===!0,_=m&&!C,N=!m&&(i.wakeReason===void 0||i.wakeReason==="runtime-restart-abort")&&await Ge(e),g=_&&(i.wakeReason===void 0||i.wakeReason==="runtime-restart-abort")&&!await be(e)&&!await Me(w.resumeSessionPath)?(await k(e))?.trim():void 0,A=g!==void 0&&g!=="",J=a||N||A,F=r.cycle_pending===!0||C;await E(e,{cycle_pending:F}),r.cycle_pending=F,!a&&!m&&(r.pi_session_id!=null||r.pi_session_file!=null)&&(await O(e),r.pi_session_id=null,r.pi_session_file=null);let c,f=null;const b=s(()=>({type:"runtime",kind:"kickoff",...r.spawned_by!=null&&r.spawned_by!==""?{spawnedBy:r.spawned_by}:{}}),"birthOrigin");if(a){const o=await k(e),P=h(l);if(P===null)throw new Error(`invalid fork source ${l}`);const Y=(await d().header(await d().fork(P,e))).path;c=p(r,{resumeSessionPath:Y,...o!=null&&o!==""?{prompt:o}:{}}),o!=null&&o!==""&&(f=b()),await Re(e,(await Se(l))?.node_id??null)}else if(A)c=p(r,{...w,prompt:g}),f=b();else if(_)c=p(r,{...w,...i.wakeReason==="runtime-restart-abort"?{prompt:de}:{}}),i.wakeReason==="runtime-restart-abort"&&(f={type:"runtime",kind:"restart-continuation"});else if(N){const o=(await k(e))?.trim();c=p(r,o!==void 0&&o!==""?{prompt:o}:{}),o!==void 0&&o!==""&&(f=b()),await G(e)}else{const o=await ue(r,u);c=p(r,{...w,prompt:await ce(r,o,i.wakeReason==="runtime-restart-abort"?void 0:i.wakeReason)}),r.run_id&&o.unreadMessageIds?.length&&(c.env.CRTR_KICKOFF_MESSAGE_IDS=JSON.stringify(o.unreadMessageIds)),f=i.wakeReason!==void 0&&i.wakeReason!=="runtime-restart-abort"?{type:"runtime",kind:"wake",wake:i.wakeReason}:{type:"runtime",kind:"revive",cycle:r.cycles??0},await G(e)}c.env={...c.env,CRTR_SUBTREE:await xe(e)},f!==null&&(c.env[pe]=he(f)),r.status==="done"&&r.last_settled_at!=null&&await Ee(e,r.last_settled_at),await x(e,r.intent==="refresh"?"refresh-launch":"revive"),await ge(e,{preserveEpisode:!0});const V=await ke(e);i.recovery!==!0&&i.viewerAttach!==!0&&await se(e),await De(e,r.grantee);const X=Te(r.cwd,r.profile_id).plans.get("node:start")??[];await ze(X,{node:{id:e,name:r.name,kind:r.kind,mode:r.mode,lifecycle:r.lifecycle,cwd:r.cwd,nodeDir:await Oe(e),contextDir:await Be(e),jobDir:Pe(e)},runtime:{isBirth:J,canvasHome:Fe(),profile:r.profile_id??null}}),c.env={...c.env,CRTR_EXECUTION_ID:u};let y;try{if(y=await M.launch(e,c,{cwd:r.cwd,name:T(r),resuming:_}),y.pid===null)throw new Error(`broker host returned no pid for ${e}`)}catch(o){try{await x(e,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:o instanceof Error?o.message:String(o)}}}),await le(e,"notice.crash",`Child crashed \u2014 ${T(r)} (${e}) failed to relaunch and is now dead: ${o.message}
|
|
2
2
|
|
|
3
|
-
It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,{reason:"child-crashed",child:e})}catch{}throw await S(u,{reason:"launch_failed"}),new Error(`[broker] refusing to revive ${e}: ${o.message}`)}if(await
|
|
3
|
+
It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,{reason:"child-crashed",child:e})}catch{}throw await S(u,{reason:"launch_failed"}),new Error(`[broker] refusing to revive ${e}: ${o.message}`)}if(await te(e,new Date().toISOString()),await re(u,e,y.pid)==="shutdown")throw await S(u,{reason:"superseded"}),M.teardown(e),new Error(`[broker] refusing to revive ${e}: execution was superseded during launch`);return await oe(e),{window:null,session:r.tmux_session??null,resumed:_,launch:y,faultExplanation:V.explanation,outcome:"launched"}}catch(v){throw await S(u,{reason:"launch_failed"}),v}}s(Le,"launchRevive");export{br as decideAttachRevive,kr as hasFreshGroundState,He as resumeArgs,gr as reviveNode};
|
|
@@ -57,6 +57,8 @@ export interface SpawnChildOpts {
|
|
|
57
57
|
isolated?: boolean;
|
|
58
58
|
/** App run identity set at birth; children inherit from the spawner. */
|
|
59
59
|
run?: SpawnNodeOpts['run'];
|
|
60
|
+
/** What caused this run, stored on its root node. */
|
|
61
|
+
causedBy?: string;
|
|
60
62
|
/** Commit run rows inside the same transaction as the newborn node. */
|
|
61
63
|
withinCreate?: SpawnNodeOpts['withinCreate'];
|
|
62
64
|
/** Select the profile this node runs under — an exact profile id or a unique
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
1
|
+
var se=Object.defineProperty;var d=(e,o)=>se(e,"name",{value:o,configurable:!0});import{accessSync as ce,constants as le}from"node:fs";import{isAbsolute as fe,resolve as ue,join as me}from"node:path";import{appSpace as we}from"../layout.js";import{ApiError as J}from"../../api/errors.js";import{spawnNode as he,forkSourceNode as pe,currentNodeContext as ke,rootOfSpine as _e,newNodeId as ve,preflightNodeId as ye}from"./nodes.js";import{resolveProfileOperand as ge}from"../profiles/manifest.js";import{selectProfileForCwd as be,selectProfileForCwdReadOnly as xe}from"../profiles/select.js";import{buildLaunchSpecAsync as Q,buildPiArgv as Ce}from"./launch.js";import{createManagedWorktreeAsync as Ee,rollbackManagedWorktreeAsync as $e}from"../worktree-mutation-async.js";import{usage as u,brokerLaunchFailed as N}from"../errors.js";import{writeGoal as Fe}from"./kickoff.js";import{appendSituationalContext as Se,formatSituationalProse as Oe}from"./situational-context.js";import{ensureRoadmap as Re}from"./roadmap.js";import{buildWakeBearings as Ie}from"./bearings.js";import{encodeKickoffOrigin as Ne,KICKOFF_ORIGIN_ENV as Pe}from"./stamp/protocol.js";import{beginExecution as Be,crtrHome as De,getNode as f,fullName as Z,jobDir as Te,recordExecutionPid as Le,abortExecution as A,setFrozen as Ae}from"../canvas/index.js";import{contextDir as M,nodeAgentDir as j}from"../canvas/node-agent-paths.js";import{copyTreeBeneath as Me}from"../spaces/open-beneath.js";import{conversationIdFromPath as P,conversationStore as x}from"../conversation-store/index.js";import{appMemoryTooSmall as je,boundFleet as We,brokerThresholdsForDaemon as He}from"./fleet.js";import{admitBrokerMemory as Ke}from"./memory-admission.js";import{emitEvent as ze}from"../events/emit.js";import{openViewerWindow as Ge,focusOf as Ue,windowOfPane as Ve}from"./placement.js";import{waitForBrokerViewSocket as Xe}from"./placement-tmux.js";import{transition as h}from"./lifecycle.js";import{beginBootFaultAttempt as qe}from"../canvas/recovery.js";import{headlessBrokerHost as W}from"./host.js";import{ensureDaemon as Ye}from"../../daemon/manage.js";import{readConfig as Je}from"../config.js";import{modelRequestFromConfig as Qe,unregisteredConcreteModel as Ze}from"../model-routes.js";import{openModelRegistry as en}from"./model-registry.js";import{MODEL_SPEC_NEXT as nn}from"./model-selection.js";import{forkNodeLedger as on}from"./ledger.js";import{appRungForGrant as rn}from"../llm/app-rungs.js";import{APP_FAMILY as H}from"../model-routes.js";import{discoverLifecycleHookRegistry as tn}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as an}from"../command-hooks/transport/exec-lifecycle.js";import{someAsync as dn}from"../async-array.js";import{checkStart as sn}from"./start-check.js";function p(e){return{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}d(p,"launchFailureOutcome");async function cn(e,o,a){try{return await W.launch(e,o,a)}catch(r){try{await h(e,"crash",{reason:"launch_failed",outcome:p(r)})}catch{}const t=r.message;throw N(t.startsWith("[broker]")?t:`[broker] refusing to launch ${e}: ${t}`,"Inspect the cause above, fix the launch recipe or environment, then retry.")}}d(cn,"launchBrokerOrCrash");async function ln(e,o){try{await h(e,"crash",{reason:"launch_failed",outcome:p(o)})}catch{}try{W.teardown(e)}catch{}}d(ln,"crashAndTearDown");async function fn(e){const o=(await x().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 u(`--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 u(`--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(fn,"resolveSessionUuid");async function ee(e){const o=e.trim();if(o==="")throw u("--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=P(fe(o)?o:ue(process.cwd(),o));if(r===null)throw u(`--fork-from '${o}': invalid conversation path.`,{next:"Pass a conversation file path or id."});return(await x().header(r)).path}const a=await f(o);if(a!==null){const r=a.pi_session_file;if(r==null||r==="")throw u(`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=P(r);if(t===null)throw u(`node ${o} has no valid conversation id.`,{next:"Pick a node with a captured conversation."});return(await x().header(t)).path}return await fn(o)}d(ee,"resolveForkSource");async function un(e,o,a,r={}){return e===null?null:e!==void 0&&e!==""?ge(e).profileId:o!==null?(await f(o))?.profile_id??null:r.readOnlySelection===!0?xe(a):be(a)}d(un,"resolveProfileId");function ne(e){const o=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return Qe(e.model,o,e.modelExact===!0)}d(ne,"requestFromLaunch");async function oe(e,o,a){const r=a??(e.modelIntent?`${e.modelIntent.family}/${e.modelIntent.strength}`:e.model),t=await rn(o,r,e.modelExact===!0);if(t===null)return e;const{CRTR_MODEL_INTENT:s,...c}=e.env??{};return{...e,model:t.model,modelIntent:{family:H,strength:t.strength},modelExact:void 0,env:{...c,CRTR_MODEL_INTENT:`${H}/${t.strength}`}}}d(oe,"appPaidLaunch");async function re(e,o,a){if(e===void 0||e.kind==="logical"&&e.family!==H)return;const r=Ze(e.kind==="logical"?{kind:"concrete",spec:e.spec}:e,a??await en(),o);if(r!==void 0)throw u(`model '${r.request.spec}' is not registered in this daemon.`,{received:r.request.spec,next:nn})}d(re,"assertLaunchModelRegistered");function mn(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(mn,"resolveSpawner");async function ie(e,o,a){try{Ye()}catch{}const r=ke(),t=e.root===!0,s=mn(e.parent,r.nodeId??null,t),c=e.mode??"base",k=e.rootLifecycle??(t?"resident":"terminal"),te=t&&k==="resident",$=s===null?null:await f(s),K=e.creator===void 0||e.creator===null?null:await f(e.creator);e.nodeId!==void 0&&await ye(e.nodeId);const _=e.forkFrom!==void 0?await ee(e.forkFrom):void 0,B=_===void 0?null:await pe(_),D=await dn([$,K,B],async l=>l?.isolated===!0||l?.run_id!=null&&(await f(l.run_id))?.isolated===!0);if(D&&e.isolated===!1)throw new J(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});const F=D||e.isolated===!0;if(F&&e.worktree===!0)throw new J(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const S=e.worktree===!0,v=F||S?e.nodeId??await ve():e.nodeId,O=F?e.run!==void 0&&t&&!D?e.cwd:me(we(e.run?.grantee??$?.grantee??"app:terminal").nodes,v):e.cwd,C=await un(e.profile,s,O),z=e.run?.grant_id??$?.grant_id??null,G=await oe((await Q(e.kind,c,{lifecycle:k,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:O,profileId:C})).launch,z,e.model);await re(ne(G),{cwd:O,profileId:C});const T=e.run??K??$??B;await sn({grantee:T?.grantee??"app:terminal",sub:T?.sub,grant_id:T?.grant_id});const U=B?.node_id??null;let y,R=O;try{S&&(y=await Ee(e.worktreeCwd??e.cwd,v,e.worktreeBase),R=y.path);const l=S?await oe((await Q(e.kind,c,{lifecycle:k,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:R,profileId:C})).launch,z,e.model):G;S&&await re(ne(l),{cwd:R,profileId:C});const n=await he({kind:e.kind,mode:c,lifecycle:k,cwd:R,name:e.name??e.kind,description:e.description,parent:t?null:s,creator:e.creator,...e.actor===void 0?{}:{actor:e.actor},forkSourceNode:U,spawnedBy:t?s??void 0:void 0,profile_id:C,...e.scopes===void 0?{}:{scopes:e.scopes},isolated:F,...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:_,modelOverride:e.model===void 0?void 0:l.model,...y!==void 0?{managedWorktree:y}:{},...v!==void 0?{nodeId:v}:{},...e.reviewBinding===void 0?{}:{reviewBinding:e.reviewBinding},...e.deadlineAt===void 0?{}:{deadlineAt:e.deadlineAt},...e.outcomeDelivery===void 0?{}:{outcomeDelivery:e.outcomeDelivery},launch:l});if(a?.(n.node_id),e.forkFrom!==void 0)try{await on(n.node_id,U??null)}catch(i){throw await h(n.node_id,"crash",{reason:"launch_failed",outcome:p(i)}),i}if(await Fe(n.node_id,e.prompt),e.situationalContext!==void 0&&Se(n.node_id,Oe(e.situationalContext)),o!==void 0)try{o(n.node_id)}catch(i){throw await h(n.node_id,"crash",{reason:"launch_failed",outcome:p(i)}),i}const L=e.prompt!=="",ae=`${L&&e.wakeOrigin!==void 0?`${Ie(e.wakeOrigin)}
|
|
2
2
|
|
|
3
|
-
`:""}${e.prompt}`;c==="orchestrator"&&await Re(n.node_id,{goal:e.prompt.trim()}),await
|
|
3
|
+
`:""}${e.prompt}`;c==="orchestrator"&&await Re(n.node_id,{goal:e.prompt.trim()}),await wn(n);let V;if(_!==void 0)try{const i=P(_);if(i===null)throw new Error(`invalid fork source ${_}`);const w=await x().fork(i,n.node_id);V=(await x().header(w)).path}catch(i){throw await h(n.node_id,"crash",{reason:"launch_failed",outcome:p(i)}),i}const g=Ce(n,{prompt:ae,resumeSessionPath:V});if(g.env={...g.env,CRTR_SUBTREE:await _e(n.node_id)},L){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}:{}};g.env[Pe]=Ne(i)}const b=We(),X=b.reserveSlot(n.node_id),m=X?await Ke(n.node_id):null;if(m?.verdict==="too_small"){b.releaseReservation(n.node_id);const i=je(m);throw await h(n.node_id,"crash",{reason:"launch_failed",outcome:p(i)}),i}if(!X||m?.verdict==="denied")return m?.verdict==="denied"&&b.releaseReservation(n.node_id),await Ae(n.node_id,new Date().toISOString()),ze({level:"info",event:"broker.frozen",node_id:n.node_id,fields:m?.verdict==="denied"?{reason:"app_memory",free_bytes:m.free_bytes,needed_bytes:m.needed_bytes}:{reason:"broker_cap",live_count:b.size(),hard_cap:He().automaticReviveCap}}),{node:await f(n.node_id),frozen:!0,window:null,session:null};const de=await qe(n.node_id),E=await Be(n.node_id,{daemonEpoch:b.epoch()});g.env={...g.env,CRTR_EXECUTION_ID:E};let I;try{I=await cn(n.node_id,g,{cwd:n.cwd,name:Z(n),resuming:!1})}catch(i){throw await A(E,{reason:"launch_failed"}),i}finally{b.releaseReservation(n.node_id)}if(I.pid===null){const i=new Error(`broker host returned no pid for ${n.node_id}`);throw await A(E,{reason:"launch_failed"}),await h(n.node_id,"crash",{reason:"launch_failed",outcome:p(i)}),N(`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 Le(E,n.node_id,I.pid)==="shutdown")throw await A(E,{reason:"superseded"}),W.teardown(n.node_id),N(`broker execution was superseded for ${n.node_id}`,"Retry spawning the node.");if(te&&e.readiness==="await"&&!await Xe(n.node_id,I.exited)){const i=await de.explanation();throw await ln(n.node_id,new Error(i??`broker view socket never bound for ${n.node_id}`)),N(i!==null?`the root broker ${n.node_id} could not start \u2014 ${i}`:`the root broker ${n.node_id} never bound its view socket \u2014 it was not started.`,i!==null?"Resolve the cause named above, then retry.":`The broker engine exited before binding its view socket. Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then retry.`)}let q=null,Y=null;if(!t&&s!==null&&Je("user").auto_open_child_viewers)try{const i=await Ue(s);if(i!==null&&i.pane!==null&&i.pane!==""){const w=await Ge(n.node_id,i.session??"",{name:Z(n),cwd:e.cwd,besidePane:i.pane,waitForBroker:!0,initialWhip:L});w!==null&&w.pane!==null&&w.pane!==""&&(Y=w.session,q=Ve(w.pane))}}catch{}return{node:await f(n.node_id),frozen:!1,window:q,session:Y}}catch(l){throw y!==void 0&&v!==void 0&&await f(v)===null&&await $e(y),l}}d(ie,"spawnChildPrepared");async function io(e){return ie(e)}d(io,"spawnChild");async function wn(e){const o=tn(e.cwd,e.profile_id).plans.get("node:start")??[];await an(o,{node:{id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,cwd:e.cwd,nodeDir:await j(e.node_id),contextDir:await M(e.node_id),jobDir:Te(e.node_id)},runtime:{isBirth:!0,canvasHome:De(),profile:e.profile_id??null}})}d(wn,"invokeBirthLifecycleHooks");const hn=new Set(["initial-prompt.md","yield-message.md","result.json","jobs"]);async function to(e,o,a){const r=await f(e);if(r===null)throw u(`unknown node: ${e}`,{received:e,next:"List nodes and pass the id of a node with a captured pi session."});const t=await ee(e),s=await M(e);try{await x().header(P(t)),ce(s,le.R_OK)}catch(c){throw new Error(`cannot fork ${e}: its conversation or context is unreadable \u2014 ${c.message}`)}return ie({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 c=>{const k=await M(c);Me(await j(e),s,await j(c),k,hn)})}d(to,"forkNode");export{oe as appPaidLaunch,re as assertLaunchModelRegistered,to as forkNode,wn as invokeBirthLifecycleHooks,ee as resolveForkSource,un as resolveProfileId,mn as resolveSpawner,io as spawnChild,ie as spawnChildPrepared};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type Refusal, type StartCandidate } from '../ledger/index.js';
|
|
2
|
+
import { RunError } from '../runs/operations.js';
|
|
3
|
+
export interface StartIdentity {
|
|
4
|
+
grantee?: string;
|
|
5
|
+
sub?: string | null;
|
|
6
|
+
grant_id?: string | null;
|
|
7
|
+
}
|
|
8
|
+
/** The start candidate for an identity, or null when no person is known yet (a terminal node before its first grant snapshot). */
|
|
9
|
+
export declare function startCandidateOf(who: StartIdentity): Promise<StartCandidate | null>;
|
|
10
|
+
/** Throw `402 cap_exhausted` (limit named) when a limit covering every charge of this identity's payer is reached. */
|
|
11
|
+
export declare function checkStart(who: StartIdentity): Promise<void>;
|
|
12
|
+
/** The refusal, without throwing, for callers that settle a refused state instead of failing (cron fire). */
|
|
13
|
+
export declare function startRefusal(who: StartIdentity): Promise<Refusal | null>;
|
|
14
|
+
/** Whether an error is the start check's `402 cap_exhausted` refusal. */
|
|
15
|
+
export declare function isStartRefusal(error: unknown): error is RunError;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var c=Object.defineProperty;var n=(a,t)=>c(a,"name",{value:t,configurable:!0});import{check as s,findRefusal as u,payerOf as o}from"../ledger/index.js";import{RunError as l}from"../runs/operations.js";import{payerOfGrant as p,terminalGrant as f}from"../grants/mirror.js";async function e(a){const t=a.grantee??"app:terminal",r=a.sub??(t==="app:terminal"?(await f())?.sub:void 0)??null;if(r===null)return null;const i=await p(a.grant_id);return{scope:"start",payer:o({call:"start",grantPayer:i,sub:r,grantee:t}).payer,sub:r,grantee:t}}n(e,"startCandidateOf");async function w(a){const t=await e(a);t!==null&&await s(t)}n(w,"checkStart");async function R(a){const t=await e(a);return t===null?null:await u(t)}n(R,"startRefusal");function b(a){return a instanceof l&&a.code==="cap_exhausted"}n(b,"isStartRefusal");export{w as checkStart,b as isStartRefusal,e as startCandidateOf,R as startRefusal};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var _=Object.defineProperty;var n=(e,r)=>_(e,"name",{value:r,configurable:!0});import{createHash as x}from"node:crypto";import{claimWarmSpare as N,deleteNode as $,getNode as p,listNodes as C,listWarmSpares as b,registerWarmSpare as R,unregisterWarmSpare as W,updateNode as P,warmSpareCount as w}from"../canvas/index.js";import{recordedPidLiveness as L}from"../canvas/pid.js";import{nowIso as y}from"../fs-utils.js";import{admitNodeCreate as M}from"../command-hooks/lifecycle-create.js";import{spawnChildPrepared as A}from"./spawn.js";import{checkStart as E}from"./start-check.js";import{buildLaunchSpecAsync as O}from"./launch.js";import{setModelLive as I}from"./model-swap.js";import{setSituationalContextLive as T}from"./situational-live.js";import{deliverBearingsLive as D}from"./deliver-live.js";import{closeNode as h}from"./close.js";function g(){return process.env.CRTR_WARM_POOL!=="0"}n(g,"warmPoolEnabled");function j(e,r,t){const a=Object.entries(t.env??{}).sort(([s],[i])=>s<i?-1:s>i?1:0),o=JSON.stringify([e,r,t.tools??[],t.extensions??[],t.systemPrompt??null,a]);return x("sha256").update(o).digest("hex").slice(0,32)}n(j,"warmRecipeKey");async function d(e){const{launch:r}=await O(e.kind,e.mode,{lifecycle:"resident",hasManager:!1,...e.model!==null?{model:e.model}:{},cwd:e.cwd,profileId:e.profileId});return{key:j(e.cwd,e.profileId,r),launch:r,request:e}}n(d,"resolveRecipe");async function k(e){const r=e.creator===null?null:await p(e.creator);await E({grantee:r?.grantee??"app:terminal",sub:r?.sub,grant_id:r?.grant_id})}n(k,"checkClaimantStart");async function re(e,r={},t){await k(e);const a=await d(e);if(await w(a.key)===0)return null;const o=y(),s=await M({kind:e.kind,mode:e.mode,cwd:e.cwd,profile:e.profileId,root:!0,parentId:null,requestingNodeId:e.creator,lifecycle:"resident",replaces:null},e.creator===null?"app:terminal":await(async()=>{const c=await p(e.creator);if(!c?.grantee)throw new Error("warm node creator has no app");return c.grantee})());let i;try{i=await N(a.key,o,r)}finally{s()}return i===null?null:v(i,a,o,t)}n(re,"claimWarmNode");async function te(e,r,t){return await k(e),v(r,await d(e),y(),t)}n(te,"resumeWarmClaim");async function v(e,r,t,a){const{request:o}=r,i=(await p(e))?.launch?.model;await P(e,{created:t,kind:o.kind,mode:o.mode,name:o.name??o.kind,creator:o.creator,launch:r.launch,persona_ack:{kind:o.kind,mode:o.mode,lifecycle:"resident"},...o.model!==null?{model_override:o.model}:{}});try{a?.(e)}catch(l){return await m(e,"birth preparation",l)}try{await D(e)}catch(l){return await m(e,"bearings delivery",l)}const c=r.launch.model;if(c!==void 0&&c!==i)try{await I(e,c,r.launch.modelIntent)}catch(l){return await m(e,"model swap",l)}if(o.situationalContext!==null)try{await T(e,o.situationalContext)}catch(l){return await m(e,"situational-context delivery",l)}return e}n(v,"completeWarmClaim");async function m(e,r,t){console.error(`[warm-pool] ${r} failed on claim; closing the spare: ${t.message}`);try{await h(e)}catch{}return null}n(m,"abandonSpare");const B=3600*1e3;async function ae(){const e=[];let r;try{r=await b()}catch(a){return console.error(`[warm-pool] spare scan failed: ${a.message}`),e}const t=Date.now()-B;for(const a of r){if(u.has(a.node_id))continue;const o=Date.parse(a.created),s=Number.isNaN(o)||o<t,i=L(a.pi_pid,a.pi_pid_identity),c=(a.status==="active"||a.status==="idle")&&i==="alive";if(!(c&&!s)&&!(i==="indeterminate"&&!s))try{if(!await W(a.node_id))continue;if(c)try{await h(a.node_id)}catch{}await $(a.node_id),e.push(a.node_id)}catch(l){console.error(`[warm-pool] reap failed for ${a.node_id}: ${l.message}`)}}return e}n(ae,"reapStaleSpares");const f=new Set,u=new Set;function oe(e){if(g())try{d({...e,model:null,situationalContext:null}).then(S).catch(r=>console.error(`[warm-pool] recipe resolution failed: ${r.message}`))}catch(r){console.error(`[warm-pool] recipe resolution failed: ${r.message}`)}}n(oe,"refillWarmPool");async function S(e){const{key:r,request:t}=e;f.has(r)||await w(r)>0||(f.add(r),(async()=>{let a=null;try{await A({kind:t.kind,mode:t.mode,cwd:t.cwd,prompt:"",root:!0,readiness:"await",profile:t.profileId},async o=>{a=o,u.add(o),await R(o,r)})}catch(o){console.error(`[warm-pool] mint failed for ${t.kind}: ${o.message}`)}finally{a!==null&&u.delete(a),f.delete(r)}})())}n(S,"mint");const F=2;async function ne(){if(!g())return;let e;try{const r=new Set;e=[];for(const t of(await C({status:["active","idle"]})).reverse()){if(t.parent!==null||t.kind==="human")continue;const a=t.profile_id??null;if(!r.has(a??"")&&(r.add(a??""),e.push({cwd:t.cwd,profileId:a}),e.length>=F))break}}catch(r){console.error(`[warm-pool] prewarm scan failed: ${r.message}`);return}for(const r of e)try{d({kind:"general",mode:"base",cwd:r.cwd,profileId:r.profileId,model:null,situationalContext:null,name:null,creator:null}).then(S).catch(t=>console.error(`[warm-pool] prewarm failed for ${r.cwd}: ${t.message}`))}catch(t){console.error(`[warm-pool] prewarm failed for ${r.cwd}: ${t.message}`)}}n(ne,"prewarmRecentRecipes");export{re as claimWarmNode,ne as prewarmRecentRecipes,ae as reapStaleSpares,oe as refillWarmPool,te as resumeWarmClaim,g as warmPoolEnabled};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var v=Object.defineProperty;var n=(e,t)=>v(e,"name",{value:t,configurable:!0});import{CONDENSED_HISTORY_MODES as u,MOUSE_MODE_DEFAULTS as p,WHIP_MESSAGE_MODES as d}from"../types.js";function i(e,t,o){const s=e.indexOf(t),a=s>=0?s:0;return e[(a+o+e.length)%e.length]}n(i,"cycleChoice");function c(e,t,o){const s=e.indexOf(t);return s>=0?e[(s+o+e.length)%e.length]:o>=0?e.find(a=>a>t)??e[0]:[...e].reverse().find(a=>a<t)??e[e.length-1]}n(c,"cycleNumber");function r(e,t){return e==="true"?!0:e==="false"?!1:`${t} must be true or false`}n(r,"booleanFromString");function f(e,t){if(!/^\d+$/.test(e))return`${t} must be an integer >= 0`;const o=Number(e);return Number.isSafeInteger(o)?o:`${t} must be an integer >= 0`}n(f,"nonNegativeIntegerFromString");function _(e,t){const o=f(e,t);return typeof o=="string"||o<1?`${t} must be an integer >= 1`:o}n(_,"positiveIntegerFromString");const m=[!1,"notify","apply"],w=[0,1,6,12,24,48,72,168],b=[1,2,3,4,5,6,8,10,12],l="openai-codex";function g(e,t){const o=e.providerOptions[t];if(o!==void 0)return o;const s={};return e.providerOptions[t]=s,s}n(g,"providerOptionsFor");const x=[1,2,3,4,5,6],h={schema_version:{surface:"specialized",owner:"internal schema migration"},marketplaces:{surface:"specialized",owner:"Plugins and pkg market commands"},plugins:{surface:"specialized",owner:"Plugins tab and pkg plugin commands"},auto_update:{surface:"settings",settings:{crtr:{key:"auto_update.crtr",label:"crouter updates",description:"Notify about crouter releases, install them automatically, or turn checks off.",valueConstraint:"true|false|notify|apply; true stores notify",applies:"Applies on the next crouter command.",group:"updates",order:70,format:n(e=>e.auto_update.crtr===!1?"off":e.auto_update.crtr,"format"),cycle:n((e,t)=>{e.auto_update.crtr=i(m,e.auto_update.crtr,t)},"cycle"),setFromString:n((e,t)=>{const o=t==="true"?"notify":t;return o!=="notify"&&o!=="apply"&&o!=="false"?"auto_update.crtr must be notify, apply, or false":(e.auto_update.crtr=o==="false"?!1:o,null)},"setFromString")},content:{key:"auto_update.content",label:"Content updates",description:"Notify about plugin and marketplace updates, apply them automatically, or turn checks off.",valueConstraint:"false|notify|apply",applies:"Applies on the next crouter command.",group:"updates",order:80,format:n(e=>e.auto_update.content===!1?"off":e.auto_update.content,"format"),cycle:n((e,t)=>{e.auto_update.content=i(m,e.auto_update.content,t)},"cycle"),setFromString:n((e,t)=>t!=="notify"&&t!=="apply"&&t!=="false"?"auto_update.content must be notify, apply, or false":(e.auto_update.content=t==="false"?!1:t,null),"setFromString")},interval_hours:{key:"auto_update.interval_hours",label:"Update interval",description:"Minimum hours between automatic update checks. Zero checks on every command.",valueConstraint:"integer >= 0",applies:"Applies on the next crouter command.",group:"updates",order:90,format:n(e=>`${e.auto_update.interval_hours}h`,"format"),cycle:n((e,t)=>{e.auto_update.interval_hours=c(w,e.auto_update.interval_hours,t)},"cycle"),setFromString:n((e,t)=>{const o=f(t,"auto_update.interval_hours");return typeof o=="string"?o:(e.auto_update.interval_hours=o,null)},"setFromString")}}},max_panes_per_window:{surface:"settings",setting:{key:"max_panes_per_window",label:"Maximum panes",description:"Maximum human-review panes placed in one tmux window before using another window.",valueConstraint:"integer >= 1",applies:"Applies to the next pane placement.",group:"panes",order:20,format:n(e=>String(e.max_panes_per_window),"format"),cycle:n((e,t)=>{e.max_panes_per_window=c(b,e.max_panes_per_window,t)},"cycle"),setFromString:n((e,t)=>{const o=_(t,"max_panes_per_window");return typeof o=="string"?o:(e.max_panes_per_window=o,null)},"setFromString")}},auto_open_child_viewers:{surface:"settings",setting:{key:"auto_open_child_viewers",label:"Open child panes",description:"Open each managed child beside its watched parent. Off keeps new children running in the background.",valueConstraint:"true|false",applies:"Applies to the next managed child created; independent roots still open their attended viewer.",group:"panes",order:10,format:n(e=>e.auto_open_child_viewers?"on":"off","format"),cycle:n(e=>{e.auto_open_child_viewers=!e.auto_open_child_viewers},"cycle"),setFromString:n((e,t)=>{const o=r(t,"auto_open_child_viewers");return typeof o=="string"?o:(e.auto_open_child_viewers=o,null)},"setFromString")}},brokerThresholds:{surface:"specialized",owner:"Broker limits tab"},lifecycle:{surface:"specialized",owner:"sys config set lifecycle.unattendedParkMs"},completion_bell:{surface:"settings",setting:{key:"completion_bell",label:"Completion bell",description:"Ring a short sound when the node in an attached viewer finishes a turn.",valueConstraint:"true|false",applies:"Applies on the next turn end.",group:"display",order:41,format:n(e=>e.completion_bell?"on":"off","format"),cycle:n(e=>{e.completion_bell=!e.completion_bell},"cycle"),setFromString:n((e,t)=>{const o=r(t,"completion_bell");return typeof o=="string"?o:(e.completion_bell=o,null)},"setFromString")}},working_gerunds:{surface:"specialized",owner:"sys config set working_gerunds"},whip_mode:{surface:"settings",setting:{key:"whip_mode",label:"Whip mode",description:"Play the whip animation when you send a prompt and when a viewer opens for an agent with an initial prompt.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:39,format:n(e=>e.whip_mode?"on":"off","format"),cycle:n(e=>{e.whip_mode=!e.whip_mode},"cycle"),setFromString:n((e,t)=>{const o=r(t,"whip_mode");return typeof o=="string"?o:(e.whip_mode=o,null)},"setFromString")}},page_surface:{surface:"settings",setting:{key:"page_surface",label:"Page human surface",description:"This host reads pages in a browser rather than a terminal. Agents are told the page module runs as written, HTML pages are offered, and document review and live display leave the command tree.",valueConstraint:"true|false",applies:"Applies when human command help is assembled.",group:"display",order:37,format:n(e=>e.page_surface?"on":"off","format"),cycle:n(e=>{e.page_surface=!e.page_surface},"cycle"),setFromString:n((e,t)=>{const o=r(t,"page_surface");return typeof o=="string"?o:(e.page_surface=o,null)},"setFromString")}},whip_messages:{surface:"specialized",owner:"sys config set whip_messages"},whip_message_mode:{surface:"settings",setting:{key:"whip_message_mode",label:"Whip message",description:"What the whip action sends: a random line from whip_messages, or the fixed \u201CGo faster\u201D.",valueConstraint:d.join("|"),applies:"Applies on the next attach.",group:"display",order:40,format:n(e=>e.whip_message_mode==="go-faster"?"go faster":"random","format"),cycle:n((e,t)=>{e.whip_message_mode=i(d,e.whip_message_mode,t)},"cycle"),setFromString:n((e,t)=>d.includes(t)?(e.whip_message_mode=t,null):`whip_message_mode must be one of: ${d.join("|")}`,"setFromString")}},mouse_mode_default:{surface:"settings",setting:{key:"mouse_mode_default",label:"Default mouse mode",description:"Initial mouse wheel scrolling for each attached viewer.",valueConstraint:p.join("|"),applies:"Applies on the next attach.",group:"display",order:38,format:n(e=>e.mouse_mode_default==="tmux"?"follow tmux":e.mouse_mode_default,"format"),cycle:n((e,t)=>{e.mouse_mode_default=i(p,e.mouse_mode_default,t)},"cycle"),setFromString:n((e,t)=>p.includes(t)?(e.mouse_mode_default=t,null):`mouse_mode_default must be one of: ${p.join("|")}`,"setFromString")}},live_cycles:{surface:"settings",setting:{key:"live_cycles",label:"Live cycles",description:"Trailing refresh cycles rendered at full fidelity; older cycles condense to text.",valueConstraint:"integer >= 1",applies:"Applies on the next attach.",group:"display",order:50,format:n(e=>String(e.live_cycles),"format"),cycle:n((e,t)=>{e.live_cycles=c(x,e.live_cycles,t)},"cycle"),setFromString:n((e,t)=>{const o=_(t,"live_cycles");return typeof o=="string"?o:(e.live_cycles=o,null)},"setFromString")}},condensed_history:{surface:"settings",setting:{key:"condensed_history",label:"Condensed history",description:"Messages retained from condensed cycles. Tool calls are never kept.",valueConstraint:u.join("|"),applies:"Applies on the next attach.",group:"display",order:60,format:n(e=>e.condensed_history,"format"),cycle:n((e,t)=>{e.condensed_history=i(u,e.condensed_history,t)},"cycle"),setFromString:n((e,t)=>u.includes(t)?(e.condensed_history=t,null):`condensed_history must be one of: ${u.join("|")}`,"setFromString")}},bash_tool_purpose:{surface:"settings",setting:{key:"bash_tool_purpose",label:"Bash purpose field",description:"Expose the optional purpose label to agents in the bash tool schema. Off removes the field without disabling the bash valve.",valueConstraint:"true|false",applies:"Applies on the next node session.",group:"display",order:25,format:n(e=>e.bash_tool_purpose?"on":"off","format"),cycle:n(e=>{e.bash_tool_purpose=!e.bash_tool_purpose},"cycle"),setFromString:n((e,t)=>{const o=r(t,"bash_tool_purpose");return typeof o=="string"?o:(e.bash_tool_purpose=o,null)},"setFromString")}},fold_finished_tools:{surface:"settings",setting:{key:"fold_finished_tools",label:"Fold finished tools",description:"Fold every settled tool call to its call line. Toggle live with /fold-tools.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:30,format:n(e=>e.fold_finished_tools?"on":"off","format"),cycle:n(e=>{e.fold_finished_tools=!e.fold_finished_tools},"cycle"),setFromString:n((e,t)=>{const o=r(t,"fold_finished_tools");return typeof o=="string"?o:(e.fold_finished_tools=o,null)},"setFromString")}},summarize_tool_calls:{surface:"settings",setting:{key:"summarize_tool_calls",label:"Summarize tool calls",description:"Replace completed folded tool-call groups with a one-line broker summary when available.",valueConstraint:"true|false",applies:"Applies when the next visible message closes a tool-call group.",group:"display",order:35,format:n(e=>e.summarize_tool_calls?"on":"off","format"),cycle:n(e=>{e.summarize_tool_calls=!e.summarize_tool_calls},"cycle"),setFromString:n((e,t)=>{const o=r(t,"summarize_tool_calls");return typeof o=="string"?o:(e.summarize_tool_calls=o,null)},"setFromString")}},document_port:{surface:"settings",setting:{key:"document_port",label:"Document browser port",description:"Fixed localhost port where crtrd serves editable document pages.",valueConstraint:"1-65535",applies:"Applies after daemon handover and on the next attach.",group:"display",order:37.5,format:n(e=>String(e.document_port),"format"),cycle:n((e,t)=>{e.document_port=Math.max(1,Math.min(65535,e.document_port+t))},"cycle"),setFromString:n((e,t)=>{const o=Number(t);return!/^\d+$/.test(t)||!Number.isInteger(o)||o<1||o>65535?"document_port must be an integer from 1 to 65535":(e.document_port=o,null)},"setFromString")}},detailed_tool_recaps:{surface:"settings",setting:{key:"detailed_tool_recaps",label:"Detailed tool recaps",description:"Show each document read and edited file in folded tool recaps. Off shows a compact count line instead.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:36,format:n(e=>e.detailed_tool_recaps?"on":"off","format"),cycle:n(e=>{e.detailed_tool_recaps=!e.detailed_tool_recaps},"cycle"),setFromString:n((e,t)=>{const o=r(t,"detailed_tool_recaps");return typeof o=="string"?o:(e.detailed_tool_recaps=o,null)},"setFromString")}},consolidate_replies:{surface:"settings",setting:{key:"consolidate_replies",label:"Consolidate replies",description:"Experiment: show one rewritten agent reply per message you type, with the working folded behind it (/show-working).",valueConstraint:"true|false",applies:"Applies on the next attach; the broker reads it per turn.",group:"display",order:36.5,format:n(e=>e.consolidate_replies?"on":"off","format"),cycle:n(e=>{e.consolidate_replies=!e.consolidate_replies},"cycle"),setFromString:n((e,t)=>{const o=r(t,"consolidate_replies");return typeof o=="string"?o:(e.consolidate_replies=o,null)},"setFromString")}},keybindings:{surface:"specialized",owner:"Keybindings tab"},tmux_passthrough:{surface:"specialized",owner:"Keybindings tab"},providerOptions:{surface:"settings",settings:{"openai-codex.fastMode":{key:`providerOptions.${l}.fastMode`,label:"Codex fast mode",description:"Serve Codex turns at the ChatGPT priority tier: about 1.5x faster generation for about 2x the credits. Displayed cost does not reflect the premium.",valueConstraint:"true|false",applies:"Applies on each node's next turn.",group:"providers",order:40,format:n(e=>e.providerOptions[l]?.fastMode?"on":"off","format"),cycle:n(e=>{const t=g(e,l);t.fastMode=!t.fastMode},"cycle"),setFromString:n((e,t)=>{const o=r(t,`providerOptions.${l}.fastMode`);return typeof o=="string"?o:(g(e,l).fastMode=o,null)},"setFromString")}}},modelLadders:{surface:"specialized",owner:"Models tab"},modelRoutes:{surface:"specialized",owner:"Models route declarations"},modelRouting:{surface:"specialized",owner:"Models route declarations"},kinds:{surface:"specialized",owner:"Models tab and kind registry"},page_components:{surface:"specialized",owner:"Page component catalog: product-registered page component kinds"},remoteCanvas:{surface:"specialized",owner:"canvas config commands"},api:{surface:"specialized",owner:"sys connect"},paths:{surface:"specialized",owner:"runtime layout"},store:{surface:"specialized",owner:"daemon conversation store"},runtime:{surface:"specialized",owner:"app-facing listener"},spawnEnv:{surface:"specialized",owner:"spawn environment allow-list"},bin:{surface:"specialized",owner:"bare-binary contributions on every node PATH"},humanActions:{surface:"specialized",owner:"scope-configured human completion actions"}},O=Object.keys(h);function S(){const e=[];for(const t of Object.values(h))t.surface==="settings"&&("setting"in t?e.push(t.setting):e.push(...Object.values(t.settings)));return e.sort((t,o)=>t.order-o.order)}n(S,"collectUserSettings");const y=S();function A(e){return y.find(t=>t.key===e)}n(A,"findUserSetting");function z(e){return y.filter(t=>t.group===e)}n(z,"userSettingsInGroup");export{h as CONFIG_SETTINGS_COVERAGE,O as SCOPE_CONFIG_KEYS,y as USER_SETTINGS,A as findUserSetting,z as userSettingsInGroup};
|
|
1
|
+
var v=Object.defineProperty;var n=(e,t)=>v(e,"name",{value:t,configurable:!0});import{CONDENSED_HISTORY_MODES as u,MOUSE_MODE_DEFAULTS as p,WHIP_MESSAGE_MODES as d}from"../types.js";function i(e,t,o){const s=e.indexOf(t),a=s>=0?s:0;return e[(a+o+e.length)%e.length]}n(i,"cycleChoice");function c(e,t,o){const s=e.indexOf(t);return s>=0?e[(s+o+e.length)%e.length]:o>=0?e.find(a=>a>t)??e[0]:[...e].reverse().find(a=>a<t)??e[e.length-1]}n(c,"cycleNumber");function r(e,t){return e==="true"?!0:e==="false"?!1:`${t} must be true or false`}n(r,"booleanFromString");function f(e,t){if(!/^\d+$/.test(e))return`${t} must be an integer >= 0`;const o=Number(e);return Number.isSafeInteger(o)?o:`${t} must be an integer >= 0`}n(f,"nonNegativeIntegerFromString");function _(e,t){const o=f(e,t);return typeof o=="string"||o<1?`${t} must be an integer >= 1`:o}n(_,"positiveIntegerFromString");const m=[!1,"notify","apply"],w=[0,1,6,12,24,48,72,168],b=[1,2,3,4,5,6,8,10,12],l="openai-codex";function g(e,t){const o=e.providerOptions[t];if(o!==void 0)return o;const s={};return e.providerOptions[t]=s,s}n(g,"providerOptionsFor");const x=[1,2,3,4,5,6],h={schema_version:{surface:"specialized",owner:"internal schema migration"},marketplaces:{surface:"specialized",owner:"Plugins and pkg market commands"},plugins:{surface:"specialized",owner:"Plugins tab and pkg plugin commands"},auto_update:{surface:"settings",settings:{crtr:{key:"auto_update.crtr",label:"crouter updates",description:"Notify about crouter releases, install them automatically, or turn checks off.",valueConstraint:"true|false|notify|apply; true stores notify",applies:"Applies on the next crouter command.",group:"updates",order:70,format:n(e=>e.auto_update.crtr===!1?"off":e.auto_update.crtr,"format"),cycle:n((e,t)=>{e.auto_update.crtr=i(m,e.auto_update.crtr,t)},"cycle"),setFromString:n((e,t)=>{const o=t==="true"?"notify":t;return o!=="notify"&&o!=="apply"&&o!=="false"?"auto_update.crtr must be notify, apply, or false":(e.auto_update.crtr=o==="false"?!1:o,null)},"setFromString")},content:{key:"auto_update.content",label:"Content updates",description:"Notify about plugin and marketplace updates, apply them automatically, or turn checks off.",valueConstraint:"false|notify|apply",applies:"Applies on the next crouter command.",group:"updates",order:80,format:n(e=>e.auto_update.content===!1?"off":e.auto_update.content,"format"),cycle:n((e,t)=>{e.auto_update.content=i(m,e.auto_update.content,t)},"cycle"),setFromString:n((e,t)=>t!=="notify"&&t!=="apply"&&t!=="false"?"auto_update.content must be notify, apply, or false":(e.auto_update.content=t==="false"?!1:t,null),"setFromString")},interval_hours:{key:"auto_update.interval_hours",label:"Update interval",description:"Minimum hours between automatic update checks. Zero checks on every command.",valueConstraint:"integer >= 0",applies:"Applies on the next crouter command.",group:"updates",order:90,format:n(e=>`${e.auto_update.interval_hours}h`,"format"),cycle:n((e,t)=>{e.auto_update.interval_hours=c(w,e.auto_update.interval_hours,t)},"cycle"),setFromString:n((e,t)=>{const o=f(t,"auto_update.interval_hours");return typeof o=="string"?o:(e.auto_update.interval_hours=o,null)},"setFromString")}}},max_panes_per_window:{surface:"settings",setting:{key:"max_panes_per_window",label:"Maximum panes",description:"Maximum human-review panes placed in one tmux window before using another window.",valueConstraint:"integer >= 1",applies:"Applies to the next pane placement.",group:"panes",order:20,format:n(e=>String(e.max_panes_per_window),"format"),cycle:n((e,t)=>{e.max_panes_per_window=c(b,e.max_panes_per_window,t)},"cycle"),setFromString:n((e,t)=>{const o=_(t,"max_panes_per_window");return typeof o=="string"?o:(e.max_panes_per_window=o,null)},"setFromString")}},auto_open_child_viewers:{surface:"settings",setting:{key:"auto_open_child_viewers",label:"Open child panes",description:"Open each managed child beside its watched parent. Off keeps new children running in the background.",valueConstraint:"true|false",applies:"Applies to the next managed child created; independent roots still open their attended viewer.",group:"panes",order:10,format:n(e=>e.auto_open_child_viewers?"on":"off","format"),cycle:n(e=>{e.auto_open_child_viewers=!e.auto_open_child_viewers},"cycle"),setFromString:n((e,t)=>{const o=r(t,"auto_open_child_viewers");return typeof o=="string"?o:(e.auto_open_child_viewers=o,null)},"setFromString")}},brokerThresholds:{surface:"specialized",owner:"Broker limits tab"},lifecycle:{surface:"specialized",owner:"sys config set lifecycle.unattendedParkMs"},completion_bell:{surface:"settings",setting:{key:"completion_bell",label:"Completion bell",description:"Ring a short sound when the node in an attached viewer finishes a turn.",valueConstraint:"true|false",applies:"Applies on the next turn end.",group:"display",order:41,format:n(e=>e.completion_bell?"on":"off","format"),cycle:n(e=>{e.completion_bell=!e.completion_bell},"cycle"),setFromString:n((e,t)=>{const o=r(t,"completion_bell");return typeof o=="string"?o:(e.completion_bell=o,null)},"setFromString")}},working_gerunds:{surface:"specialized",owner:"sys config set working_gerunds"},whip_mode:{surface:"settings",setting:{key:"whip_mode",label:"Whip mode",description:"Play the whip animation when you send a prompt and when a viewer opens for an agent with an initial prompt.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:39,format:n(e=>e.whip_mode?"on":"off","format"),cycle:n(e=>{e.whip_mode=!e.whip_mode},"cycle"),setFromString:n((e,t)=>{const o=r(t,"whip_mode");return typeof o=="string"?o:(e.whip_mode=o,null)},"setFromString")}},page_surface:{surface:"settings",setting:{key:"page_surface",label:"Page human surface",description:"This host reads pages in a browser rather than a terminal. Agents are told the page module runs as written, HTML pages are offered, and document review and live display leave the command tree.",valueConstraint:"true|false",applies:"Applies when human command help is assembled.",group:"display",order:37,format:n(e=>e.page_surface?"on":"off","format"),cycle:n(e=>{e.page_surface=!e.page_surface},"cycle"),setFromString:n((e,t)=>{const o=r(t,"page_surface");return typeof o=="string"?o:(e.page_surface=o,null)},"setFromString")}},whip_messages:{surface:"specialized",owner:"sys config set whip_messages"},whip_message_mode:{surface:"settings",setting:{key:"whip_message_mode",label:"Whip message",description:"What the whip action sends: a random line from whip_messages, or the fixed \u201CGo faster\u201D.",valueConstraint:d.join("|"),applies:"Applies on the next attach.",group:"display",order:40,format:n(e=>e.whip_message_mode==="go-faster"?"go faster":"random","format"),cycle:n((e,t)=>{e.whip_message_mode=i(d,e.whip_message_mode,t)},"cycle"),setFromString:n((e,t)=>d.includes(t)?(e.whip_message_mode=t,null):`whip_message_mode must be one of: ${d.join("|")}`,"setFromString")}},mouse_mode_default:{surface:"settings",setting:{key:"mouse_mode_default",label:"Default mouse mode",description:"Initial mouse wheel scrolling for each attached viewer.",valueConstraint:p.join("|"),applies:"Applies on the next attach.",group:"display",order:38,format:n(e=>e.mouse_mode_default==="tmux"?"follow tmux":e.mouse_mode_default,"format"),cycle:n((e,t)=>{e.mouse_mode_default=i(p,e.mouse_mode_default,t)},"cycle"),setFromString:n((e,t)=>p.includes(t)?(e.mouse_mode_default=t,null):`mouse_mode_default must be one of: ${p.join("|")}`,"setFromString")}},live_cycles:{surface:"settings",setting:{key:"live_cycles",label:"Live cycles",description:"Trailing refresh cycles rendered at full fidelity; older cycles condense to text.",valueConstraint:"integer >= 1",applies:"Applies on the next attach.",group:"display",order:50,format:n(e=>String(e.live_cycles),"format"),cycle:n((e,t)=>{e.live_cycles=c(x,e.live_cycles,t)},"cycle"),setFromString:n((e,t)=>{const o=_(t,"live_cycles");return typeof o=="string"?o:(e.live_cycles=o,null)},"setFromString")}},condensed_history:{surface:"settings",setting:{key:"condensed_history",label:"Condensed history",description:"Messages retained from condensed cycles. Tool calls are never kept.",valueConstraint:u.join("|"),applies:"Applies on the next attach.",group:"display",order:60,format:n(e=>e.condensed_history,"format"),cycle:n((e,t)=>{e.condensed_history=i(u,e.condensed_history,t)},"cycle"),setFromString:n((e,t)=>u.includes(t)?(e.condensed_history=t,null):`condensed_history must be one of: ${u.join("|")}`,"setFromString")}},bash_tool_purpose:{surface:"settings",setting:{key:"bash_tool_purpose",label:"Bash purpose field",description:"Expose the optional purpose label to agents in the bash tool schema. Off removes the field without disabling the bash valve.",valueConstraint:"true|false",applies:"Applies on the next node session.",group:"display",order:25,format:n(e=>e.bash_tool_purpose?"on":"off","format"),cycle:n(e=>{e.bash_tool_purpose=!e.bash_tool_purpose},"cycle"),setFromString:n((e,t)=>{const o=r(t,"bash_tool_purpose");return typeof o=="string"?o:(e.bash_tool_purpose=o,null)},"setFromString")}},fold_finished_tools:{surface:"settings",setting:{key:"fold_finished_tools",label:"Fold finished tools",description:"Fold every settled tool call to its call line. Toggle live with /fold-tools.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:30,format:n(e=>e.fold_finished_tools?"on":"off","format"),cycle:n(e=>{e.fold_finished_tools=!e.fold_finished_tools},"cycle"),setFromString:n((e,t)=>{const o=r(t,"fold_finished_tools");return typeof o=="string"?o:(e.fold_finished_tools=o,null)},"setFromString")}},summarize_tool_calls:{surface:"settings",setting:{key:"summarize_tool_calls",label:"Summarize tool calls",description:"Replace completed folded tool-call groups with a one-line broker summary when available.",valueConstraint:"true|false",applies:"Applies when the next visible message closes a tool-call group.",group:"display",order:35,format:n(e=>e.summarize_tool_calls?"on":"off","format"),cycle:n(e=>{e.summarize_tool_calls=!e.summarize_tool_calls},"cycle"),setFromString:n((e,t)=>{const o=r(t,"summarize_tool_calls");return typeof o=="string"?o:(e.summarize_tool_calls=o,null)},"setFromString")}},document_port:{surface:"settings",setting:{key:"document_port",label:"Document browser port",description:"Fixed localhost port where crtrd serves editable document pages.",valueConstraint:"1-65535",applies:"Applies after daemon handover and on the next attach.",group:"display",order:37.5,format:n(e=>String(e.document_port),"format"),cycle:n((e,t)=>{e.document_port=Math.max(1,Math.min(65535,e.document_port+t))},"cycle"),setFromString:n((e,t)=>{const o=Number(t);return!/^\d+$/.test(t)||!Number.isInteger(o)||o<1||o>65535?"document_port must be an integer from 1 to 65535":(e.document_port=o,null)},"setFromString")}},detailed_tool_recaps:{surface:"settings",setting:{key:"detailed_tool_recaps",label:"Detailed tool recaps",description:"Show each document read and edited file in folded tool recaps. Off shows a compact count line instead.",valueConstraint:"true|false",applies:"Applies on the next attach.",group:"display",order:36,format:n(e=>e.detailed_tool_recaps?"on":"off","format"),cycle:n(e=>{e.detailed_tool_recaps=!e.detailed_tool_recaps},"cycle"),setFromString:n((e,t)=>{const o=r(t,"detailed_tool_recaps");return typeof o=="string"?o:(e.detailed_tool_recaps=o,null)},"setFromString")}},consolidate_replies:{surface:"settings",setting:{key:"consolidate_replies",label:"Consolidate replies",description:"Experiment: show one rewritten agent reply per message you type, with the working folded behind it (/show-working).",valueConstraint:"true|false",applies:"Applies on the next attach; the broker reads it per turn.",group:"display",order:36.5,format:n(e=>e.consolidate_replies?"on":"off","format"),cycle:n(e=>{e.consolidate_replies=!e.consolidate_replies},"cycle"),setFromString:n((e,t)=>{const o=r(t,"consolidate_replies");return typeof o=="string"?o:(e.consolidate_replies=o,null)},"setFromString")}},keybindings:{surface:"specialized",owner:"Keybindings tab"},tmux_passthrough:{surface:"specialized",owner:"Keybindings tab"},providerOptions:{surface:"settings",settings:{"openai-codex.fastMode":{key:`providerOptions.${l}.fastMode`,label:"Codex fast mode",description:"Serve Codex turns at the ChatGPT priority tier: about 1.5x faster generation for about 2x the credits. Displayed cost does not reflect the premium.",valueConstraint:"true|false",applies:"Applies on each node's next turn.",group:"providers",order:40,format:n(e=>e.providerOptions[l]?.fastMode?"on":"off","format"),cycle:n(e=>{const t=g(e,l);t.fastMode=!t.fastMode},"cycle"),setFromString:n((e,t)=>{const o=r(t,`providerOptions.${l}.fastMode`);return typeof o=="string"?o:(g(e,l).fastMode=o,null)},"setFromString")}}},modelLadders:{surface:"specialized",owner:"Models tab"},modelRoutes:{surface:"specialized",owner:"Models route declarations"},modelRouting:{surface:"specialized",owner:"Models route declarations"},kinds:{surface:"specialized",owner:"Models tab and kind registry"},page_components:{surface:"specialized",owner:"Page component catalog: product-registered page component kinds"},remoteCanvas:{surface:"specialized",owner:"canvas config commands"},api:{surface:"specialized",owner:"sys connect"},paths:{surface:"specialized",owner:"runtime layout"},ledger:{surface:"specialized",owner:"money ledger (take_pct)"},store:{surface:"specialized",owner:"daemon conversation store"},runtime:{surface:"specialized",owner:"app-facing listener"},spawnEnv:{surface:"specialized",owner:"spawn environment allow-list"},bin:{surface:"specialized",owner:"bare-binary contributions on every node PATH"},humanActions:{surface:"specialized",owner:"scope-configured human completion actions"}},O=Object.keys(h);function S(){const e=[];for(const t of Object.values(h))t.surface==="settings"&&("setting"in t?e.push(t.setting):e.push(...Object.values(t.settings)));return e.sort((t,o)=>t.order-o.order)}n(S,"collectUserSettings");const y=S();function A(e){return y.find(t=>t.key===e)}n(A,"findUserSetting");function z(e){return y.filter(t=>t.group===e)}n(z,"userSettingsInGroup");export{h as CONFIG_SETTINGS_COVERAGE,O as SCOPE_CONFIG_KEYS,y as USER_SETTINGS,A as findUserSetting,z as userSettingsInGroup};
|
|
@@ -1,24 +1,24 @@
|
|
|
1
|
-
var Y=Object.defineProperty;var i=(e,n)=>Y(e,"name",{value:n,configurable:!0});import{randomUUID as Q}from"node:crypto";import{createServer as W}from"node:http";import{Router as V}from"./router.js";import{toErrorBody as
|
|
2
|
-
data: ${JSON.stringify(
|
|
1
|
+
var Y=Object.defineProperty;var i=(e,n)=>Y(e,"name",{value:n,configurable:!0});import{randomUUID as Q}from"node:crypto";import{createServer as W}from"node:http";import{Router as V,causedByOf as q}from"./router.js";import{toErrorBody as K}from"./map.js";import{objectRoutes as Z}from"./handlers/objects.js";import{customObjectRoutes as ee}from"./handlers/custom-objects.js";import{checkRoutes as te}from"./handlers/check.js";import{chargeRoutes as re}from"./handlers/charges.js";import{docRoutes as ne}from"./handlers/docs.js";import{relationRoutes as ae}from"./handlers/relations.js";import{schemaRoutes as oe}from"./handlers/schemas.js";import{OPERATIONS as ie}from"./operations.js";import{runtimeReadiness as se}from"../readiness.js";import{errorCodes as $}from"../../api/error-codes.js";import{MINIMUM_RUNTIME_VERSION_HEADER as ue,RUNTIME_VERSION_HEADER as ce,minimumRuntimeRefusal as de}from"../../api/runtime-version.js";import{CONTRACT_HEADER as le,CONTRACT_LEVEL as X,REQUIRED_CONTRACT_HEADER as me,contractRefusal as fe}from"../../api/contract.js";import{crtrVersion as J}from"../../shared/crtr-version.js";import{newTraceId as pe,parseTraceparent as he}from"../../shared/traceparent.js";import{AppPrincipalResolver as we}from"./principal.js";import{isDaemonRoute as ye,runtimeOwner as _e,servePeer as z}from"../peer/ingress.js";import{applySyncNotice as ve}from"./sync-notice.js";import{ownMachineId as ge}from"../../core/peer/directory.js";import{handleRunOperation as Re,integer as Oe}from"./handlers/runs.js";import{llmCallerOf as be,parseLlmRequest as Ee,runLlm as Ae}from"../../core/llm/run.js";import{parseUsageMonth as Te,usageFor as Se}from"../../core/ledger/index.js";import{capFields as Ne}from"./handlers/llm.js";import{CONTROL_BODY_MAX_BYTES as Ce,MODEL_CONTEXT_BODY_MAX_BYTES as Ie}from"../../core/llm/body-limits.js";import{RunError as m,runIsRunning as Pe}from"../../core/runs/operations.js";import{requireRun as L}from"./router.js";import{deferHead as ke}from"./deferred-head.js";import{readRunEvents as G,registerGrantStream as He,subscribeRunEvents as Me}from"../../core/runs/events.js";import{activeGrant as F,payerOfGrant as De}from"../../core/grants/mirror.js";async function je(e){if(await De(e)==="app")throw new m(401,"grant_revoked","this app-paid grant is no longer active");return null}i(je,"appPaidGone");import{releaseGrantWaiters as xe}from"../../core/grants/watch.js";import{emitEvent as Be}from"../../core/events/emit.js";import{runNotices as Je}from"../run-notices.js";import{handleVendorSignIn as Le,isVendorSignInPath as Ue}from"./vendor-signin.js";import{listAppProfiles as Ve}from"./handlers/app-profiles.js";import{handleTransferDownload as $e,handleTransferOperation as Xe,TRANSFER_OPERATIONS as ze}from"./handlers/transfer.js";import{handleQuestionOperation as Ge,QUESTION_OPERATIONS as Fe}from"./handlers/questions.js";import{removeVendorAccount as Ye,vendorStatus as Qe}from"./handlers/vendor-status.js";import{handleMemoryOperation as We,MEMORY_OPERATIONS as qe}from"./handlers/memory.js";import{abortOnClose as Ke,callerFromApp as Ze,handleProviderOperation as et,PROVIDER_OPERATIONS as tt,providerFailure as rt}from"./handlers/providers.js";function nt(e){return Object.prototype.hasOwnProperty.call($,e)?$[e]:void 0}i(nt,"fixedRow");function at(e){const n=nt(e);return n?n.type:e==="stream_gap"||e==="provider_error"||e==="runtime_version_unsupported"?"invalid_request_error":"server_error"}i(at,"errorType");function ot(e){if(!e||typeof e!="object"||Array.isArray(e)||!("rate_limit"in e))return e;const{rate_limit:n,...o}=e;return o}i(ot,"appDetails");function B(e,n,o){const p=ot(e.details);return{error:{code:e.code,message:e.message,...p===void 0?{}:{details:p},type:at(e.code),...e.param?{param:e.param}:{},origin:"runtime",retryable:e.retryable||e.code==="stream_dropped",request_id:n,...o?{run_id:o}:{},...e.scope?{scope:e.scope}:{},...e.code==="unauthorized"?{user_action:"reconnect"}:{},...Ne(e),...e.code==="all_routes_exhausted"?{retry_after_s:e.details.retry_after_s}:{}}}}i(B,"envelope");function it(e,n,o,p,f){const d=n instanceof m?n:new m(500,"server_failure","runtime request failed");if(n instanceof m||console.error("[app-listener]",`trace_id=${p}`,n),e.headersSent&&!String(e.getHeader("Content-Type")??"").startsWith("text/event-stream")){e.destroy();return}if(e.headersSent){e.end(`event: error
|
|
2
|
+
data: ${JSON.stringify(B(d,o,f))}
|
|
3
3
|
|
|
4
|
-
`);return}e.writeHead(
|
|
4
|
+
`);return}e.writeHead(d.status,{"Content-Type":"application/json; charset=utf-8","Request-Id":o,"X-Content-Type-Options":"nosniff",...d.code==="all_routes_exhausted"?{"Retry-After":String(d.details.retry_after_s)}:{}}),e.end(JSON.stringify(B(d,o,f)))}i(it,"fail");function U(e){return Array.isArray(e)?e[0]:e}i(U,"headerValue");function g(e,n,o){e.writeHead(n,{"Content-Type":"application/json; charset=utf-8"}),e.end(JSON.stringify(o))}i(g,"json");async function C(e,n=Ce){const o=[];let p=0;for await(const f of e){if(p+=f.length,p>n)throw new m(400,"invalid_request","request body too large");o.push(f)}if(p)try{return JSON.parse(Buffer.concat(o).toString("utf8"))}catch{throw new m(400,"invalid_request","invalid JSON body")}}i(C,"bodyOf");function st(e,n){const o=e.headers["last-event-id"]??n.get("after");if(Array.isArray(o))throw new m(400,"invalid_request","invalid cursor","after");return Oe(o??null,"after",0,Number.MAX_SAFE_INTEGER,0)}i(st,"cursor");function ut(e){return`id: ${e.sequence_number}
|
|
5
5
|
event: ${e.type}
|
|
6
6
|
data: ${JSON.stringify(e)}
|
|
7
7
|
|
|
8
|
-
`}i(
|
|
8
|
+
`}i(ut,"frame");const ct=6e4;async function dt(e,n,o,p,f,d,E,I={},M){await L(p,o);let w=await G(o,f);if(f>w.latest_sequence)throw new m(400,"invalid_request","cursor is beyond the run","after");if(f<w.latest_sequence&&(w.earliest_sequence===null||f<w.earliest_sequence-1))throw new m(409,"stream_gap","events have expired",void 0,{earliest_sequence:w.earliest_sequence,latest_sequence:w.latest_sequence});if(n.destroyed||e.destroyed)return n.destroy(),Promise.resolve();n.writeHead(200,{"Content-Type":E==="sse"?"text/event-stream":"application/x-ndjson","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),E==="sse"?n.write(`: connected
|
|
9
9
|
|
|
10
|
-
`):n.flushHeaders();let T=f;const r=await
|
|
11
|
-
data: ${JSON.stringify(
|
|
10
|
+
`):n.flushHeaders();let T=f;const r=await Je().streamOpened(o);let t=!1,y=!1,b=!1,A;const P=new Promise(u=>{A=u}),_=i(()=>{t||(t=!0,r(T).catch(u=>console.error("[app-listener]",...M===void 0?[]:[`trace_id=${M}`],u)),clearInterval(N),clearInterval(O),H(),j(),n.off("close",_),n.off("drain",h),n.end(),A())},"end"),h=i(()=>{b=!1,a()},"onDrain"),R=i(u=>{t||n.write(E==="sse"?`event: error
|
|
11
|
+
data: ${JSON.stringify(B(u,d,o))}
|
|
12
12
|
|
|
13
|
-
`:`${JSON.stringify({type:"error",...
|
|
14
|
-
`),_()},"error"),a=i(async()=>{if(!(t||y)){y=!0;try{if(!await S()){
|
|
15
|
-
`),T=
|
|
13
|
+
`:`${JSON.stringify({type:"error",...B(u,d,o)})}
|
|
14
|
+
`),_()},"error"),a=i(async()=>{if(!(t||y)){y=!0;try{if(!await S()){D();return}if(await L(p,o),w=await G(o,T),w.backlog_count>1e3||w.backlog_bytes>32*1024*1024){R(new m(503,"stream_dropped","stream reader fell behind",void 0,{last_sequence:T}));return}for(const u of w.events){if(b)break;b=!n.write(E==="sse"?ut(u):`${JSON.stringify(u)}
|
|
15
|
+
`),T=u.sequence_number}}catch(u){R(u instanceof m?u:new m(500,"server_failure","stream failed"))}finally{y=!1}}},"flush"),D=i(()=>R(new m(401,"grant_revoked","grant is not active")),"revoked"),S=i(async()=>"class"in p||await F(p.grant)!==null,"grantActive"),H=await Me(o,a),j="class"in p?()=>{}:He(p.grant,D),N=setInterval(()=>{!t&&!b&&E==="sse"&&n.write(`: keepalive
|
|
16
16
|
|
|
17
|
-
`)},15e3),
|
|
17
|
+
`)},15e3),c=I.idleMs??ct,x=I.isRunning??Pe;let s=Date.now(),v=T;const l=i(async()=>{if(t||E!=="sse")return;const u=Date.now();let k=!0;try{k=await x(o)}catch{}if(!t){if(k||T!==v){s=u,v=T;return}u-s<c||b||(n.write(`event: idle
|
|
18
18
|
data: {}
|
|
19
19
|
|
|
20
|
-
`),_())}},"checkIdle"),
|
|
20
|
+
`),_())}},"checkIdle"),O=setInterval(()=>{l().catch(u=>Be({level:"error",event:"api.run_stream.idle_check_failed",error:u}))},I.idleCheckMs??1e3);return O.unref(),n.on("drain",h),n.on("close",_),await a(),P}i(dt,"streamRunEvents");async function er(e,n,o,p={}){const f=e.listener;if(!e.issuer||!e.audience||!f?.address||!Number.isInteger(f.port)||f.port<1||f.port>65535)throw new Error("runtime issuer, audience and listener address/port are required");if(["0.0.0.0","::","[::]"].includes(f.address))throw new Error("runtime listener must bind a specific address");const d=new we(e.issuer,e.audience,o,e.jwksUrl),E=new V,I=new Map;for(const r of ie.filter(t=>t.stage!==void 0)){const t=i(()=>({status:500}),"handler");E.register({method:r.method,pattern:r.path,handler:t}),I.set(t,r)}const M=new V().registerAll(Z).registerAll(ee).registerAll(ne).registerAll(oe).registerAll(ae).registerAll(te).registerAll(re),w=W((r,t)=>{(async()=>{ke(r,t,p.deferHead);const y=Q();t.setHeader("Request-Id",y);const b=he(U(r.headers.traceparent))??pe();t.setHeader(ce,J()),t.setHeader(le,X);let A;try{const P=U(r.headers[ue.toLowerCase()]),_=de(P,J())??fe(U(r.headers[me.toLowerCase()]),X,{legacyMinimum:P,runtimeVersion:J()});if(_!==null)throw _.status===400?new m(400,_.code,_.message,_.param):new m(426,_.code,_.message,void 0,_.details);const h=new URL(r.url??"/","http://runtime.local");if(Ue(h.pathname)){await Le(r,t,h,d);return}const R=E.match(r.method??"GET",h.pathname),a=R?I.get(R.handler):void 0,D=a?.name==="runtime.sync-notice"||a?.name==="runtime.vendor-status"||a?.name==="runtime.vendor-account-remove";let S,H;if(!D&&r.headers.authorization!==void 0)try{S=await d.verifyCall(r.headers.authorization)}catch(s){H=s}const j={issuer:e.issuer,jwks:d.jwks,audience:i(async()=>e.audience,"audience"),owner:_e,self:ge,syncGrants:o,ready:i(async()=>d.isReady()&&await n(),"ready")};if(S?.chain[0]?.sub.startsWith("runtime:")){await z(r,t,j,S);return}if(S===void 0&&a===void 0&&await ye(r.method??"GET",h.pathname)){await z(r,t,j,{status:401,code:"unauthorized",message:H===void 0?"a machine token is required":"invalid machine token"});return}if(a?.name==="ready"){const s=await n(),v=await se({jwksReady:d.isReady(),grantsReady:i(()=>s,"grantsReady")});g(t,v.ready?200:503,v);return}if((r.method!=="GET"||h.pathname!=="/v1/health")&&(!d.isReady()||!await n()))throw new m(503,"runtime_starting","runtime_starting");if(!R||!a)throw new m(404,"not_found","unknown operation");A=R.params.run_id;const N=q(r.headers);if(a.name==="health"){g(t,200,{status:"ok",api_version:"2026-09-23"});return}if(a.name==="runtime.sync-notice"){await ve(await d.verifySyncNotice(r.headers.authorization),o,y),t.writeHead(204),t.end();return}if(a.name==="runtime.vendor-status"){await d.verifyDirectoryRead(r.headers.authorization,"vendor_status"),g(t,200,Qe());return}if(a.name==="runtime.vendor-account-remove"){await d.verifyDirectoryRead(r.headers.authorization,"vendor_account_remove"),g(t,200,await Ye(await C(r)));return}if(S===void 0)throw H??new m(401,"unauthorized","a directory access token is required");const c=await d.resolveVerified(S,a.scope);if(t.setHeader("Request-Id",y),A&&await L(c,A,["run.message","run.interrupt","run.cancel","run.rename","run.delete"].includes(a.name),a.name==="run.delete"),a.stage==="objects"){const s=M.match(a.method,h.pathname);if(!s)throw new m(404,"not_found","unknown operation");const v={...N===void 0?{}:{causedBy:N},method:a.method,path:h.pathname,params:s.params,query:h.searchParams,body:await C(r,s.maxBodyBytes),ceiling:c.resolved,principal:{class:"app",app:c.grantee,scopes:c.resolved,sub:c.sub},req:r,res:t};let l;try{l=await s.handler(v)}catch(O){const{status:u,body:k}=K(O);throw u>=500&&console.error("[app-listener]",`trace_id=${b}`,O),new m(u,k.error.code,k.error.message,void 0,k.error.details)}if(t.headersSent)return;if(l.rawBody!==void 0||l.status===204||l.body===void 0){t.writeHead(l.status,l.headers??{}),t.end(l.rawBody);return}t.writeHead(l.status,{"Content-Type":"application/json; charset=utf-8",...l.headers??{}}),t.end(JSON.stringify(l.body));return}if(a.stream==="bytes"){await $e(r,t,c,h.searchParams);return}if(a.stream){await dt(r,t,A,c,st(r,h.searchParams),y,"sse",p.stream,b);return}if(a.name==="llm"){const s=Ee(await C(r,Ie)),v=new AbortController,l=i(()=>v.abort(),"abort");t.on("close",l);try{const O=await Ae(s,v.signal,s.stream?u=>{t.headersSent||t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),t.write(`data: ${JSON.stringify(u)}
|
|
21
21
|
|
|
22
|
-
`)}:void 0,void 0,{grantee:
|
|
22
|
+
`)}:void 0,void 0,{grantee:c.grantee,sub:c.sub,spend_cap:c.spend_cap,request:y},be(await F(c.grant)??await je(c.grant)),N);s.stream?(t.headersSent||t.writeHead(200,{"Content-Type":"text/event-stream","Cache-Control":"no-cache","X-Accel-Buffering":"no"}),t.end(`data: [DONE]
|
|
23
23
|
|
|
24
|
-
`)):g(t,200,
|
|
24
|
+
`)):g(t,200,O.completion)}finally{t.off("close",l)}return}if(a.name==="usage.get"){g(t,200,await Se(c.grantee,Te(h.searchParams.get("month"))));return}if(a.name==="profile.list"){g(t,200,Ve(c));return}if(Fe.has(a.name)){const s=await Ge(a.name,c,R.params.question_id,a.method==="POST"?await C(r):void 0);g(t,s.status,s.body);return}if(tt.has(a.name)){const{signal:s,release:v}=Ke(t);try{const l=await et(a.name,Ze(c),{params:R.params,body:a.method==="POST"?await C(r):void 0,query:h.searchParams},{requestId:y,traceId:b,signal:s,...N===void 0?{}:{causedBy:N}});g(t,l.status,l.body)}catch(l){const O=rt(l,y,!0);t.writeHead(O.status,{"Content-Type":"application/json; charset=utf-8","X-Content-Type-Options":"nosniff",...O.headers}),t.end(JSON.stringify(O.body))}finally{v()}return}if(qe.has(a.name)){const s=await We(a.name,{class:"app",app:c.grantee,scopes:c.resolved},h.searchParams);g(t,s.status,s.body);return}if(ze.has(a.name)){const s=await Xe(a,c,R.params,h.searchParams,await C(r));g(t,s.status,s.body);return}const x=await Re(a,c,A,h.searchParams,await C(r),r.headers["idempotency-key"],N);g(t,x.status,x.body)}catch(P){it(t,P,y,b,A)}})()});return{ready:new Promise((r,t)=>{w.once("error",t),w.listen(f.port,f.address,()=>{w.off("error",t),r()})}),close:i(async()=>{d.close(),xe(),w.closeAllConnections(),await new Promise((r,t)=>w.close(y=>y?t(y):r()))},"close")}}i(er,"createAppListener");export{ct as RUN_STREAM_IDLE_MS,er as createAppListener,st as cursor,dt as streamRunEvents};
|