@north-light/cli 0.3.588 → 0.3.590
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 +4 -1
- package/dist/api/client.js +1 -1
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/docs.d.ts +5 -0
- package/dist/api/dto/settings.d.ts +21 -0
- package/dist/build-root.d.ts +2 -0
- package/dist/build-root.js +1 -1
- package/dist/cli.js +8 -8
- package/dist/clients/attach/viewer.js +505 -505
- package/dist/commands/pkg/app-installs.d.ts +53 -0
- package/dist/commands/pkg/app-installs.js +2 -0
- package/dist/commands/pkg/market-inspect.js +1 -1
- package/dist/commands/pkg/market-manage.js +1 -1
- package/dist/commands/pkg/plugin-inspect.js +1 -1
- package/dist/commands/pkg/plugin-manage.js +13 -13
- package/dist/core/canvas/schema-pg/011-package-revision.sql +12 -0
- package/dist/core/canvas/schema-version.d.ts +1 -1
- package/dist/core/canvas/schema-version.js +1 -1
- package/dist/core/config.d.ts +1 -0
- package/dist/core/config.js +1 -1
- package/dist/core/graph/names.js +8 -8
- package/dist/core/graph/package-docs.d.ts +6 -15
- package/dist/core/graph/package-docs.js +8 -6
- package/dist/core/graph/package-publish.d.ts +35 -5
- package/dist/core/graph/package-publish.js +3 -3
- package/dist/core/graph/package-reconcile.d.ts +20 -1
- package/dist/core/graph/package-reconcile.js +3 -1
- package/dist/core/import/export/dump.js +4 -3
- package/dist/core/import/load/stores.js +2 -2
- package/dist/core/installed-plugins.js +1 -1
- package/dist/core/packages/directory-sync.d.ts +41 -0
- package/dist/core/packages/directory-sync.js +6 -0
- package/dist/core/packages/eligibility.d.ts +16 -0
- package/dist/core/packages/eligibility.js +4 -0
- package/dist/core/packages/launch-kinds.d.ts +6 -0
- package/dist/core/packages/launch-kinds.js +2 -0
- package/dist/core/packages/source-url.d.ts +3 -0
- package/dist/core/packages/source-url.js +1 -0
- package/dist/core/permissions/ceiling.d.ts +9 -2
- package/dist/core/permissions/ceiling.js +11 -12
- package/dist/core/permissions/evaluator.js +2 -2
- package/dist/core/runtime/launch-config-worker.js +1 -1
- package/dist/core/runtime/launch-target.d.ts +6 -2
- package/dist/core/runtime/launch-target.js +1 -1
- package/dist/core/runtime/launch.d.ts +8 -1
- package/dist/core/runtime/launch.js +2 -2
- package/dist/core/runtime/promote.js +1 -1
- package/dist/core/runtime/recycle.js +1 -1
- package/dist/core/runtime/reset.js +1 -1
- package/dist/core/runtime/runner/blaxel/runner.js +3 -3
- package/dist/core/runtime/runner/types.d.ts +7 -1
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/view-socket.d.ts +2 -1
- package/dist/core/runtime/view-socket.js +2 -1
- package/dist/core/runtime/warm-pool.js +1 -1
- package/dist/core/scoped-state/legacy-profiles.js +1 -1
- package/dist/core/scoped-state/migrate-app-installs.d.ts +13 -0
- package/dist/core/scoped-state/migrate-app-installs.js +1 -0
- package/dist/core/scoped-state/person-rows.js +4 -6
- package/dist/core/scoped-state/person-store.d.ts +23 -0
- package/dist/core/scoped-state/person-store.js +1 -1
- package/dist/daemon/api/bridge.js +3 -3
- package/dist/daemon/api/handlers/execution-start.d.ts +2 -0
- package/dist/daemon/api/handlers/execution-start.js +2 -2
- package/dist/daemon/api/handlers/nodes.js +1 -1
- package/dist/daemon/api/handlers/package-docs.d.ts +1 -1
- package/dist/daemon/api/handlers/package-docs.js +1 -1
- package/dist/daemon/api/handlers/settings.d.ts +4 -1
- package/dist/daemon/api/handlers/settings.js +1 -1
- package/dist/daemon/crtrd.js +19 -19
- package/dist/daemon/reconcilers/node-lifecycle/remote-wake.d.ts +2 -1
- package/dist/daemon/reconcilers/node-lifecycle/remote-wake.js +1 -1
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -13
- package/dist/core/graph/package-kinds.d.ts +0 -22
- package/dist/core/graph/package-kinds.js +0 -1
- package/dist/core/scoped-state/materialized-plugins.d.ts +0 -20
- package/dist/core/scoped-state/materialized-plugins.js +0 -1
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var me=Object.defineProperty;var d=(e,o)=>me(e,"name",{value:o,configurable:!0});import{accessSync as he,constants as pe}from"node:fs";import{isAbsolute as _e,resolve as ke,join as ve}from"node:path";import{appSpace as ge}from"../layout.js";import{ApiError as ne}from"../../api/errors.js";import{spawnNode as ye,forkSourceNode as be,currentNodeContext as xe,rootOfSpine as $e,newNodeId as Se,preflightNodeId as Ce}from"./nodes.js";import{resolveProfileOperand as Ee}from"../profiles/manifest.js";import{selectProfileForCwd as Re,selectProfileForCwdReadOnly as Oe}from"../profiles/select.js";import{buildLaunchSpecAsync as oe,buildPiArgv as Fe}from"./launch.js";import{runsOnBlaxel as Ie,sandboxWorktreeRequest as Pe}from"../../daemon/api/environment-of.js";import{createManagedWorktreeAsync as Be,rollbackManagedWorktreeAsync as De}from"../worktree-mutation-async.js";import{usage as w,brokerLaunchFailed as B}from"../errors.js";import{writeGoal as Ne}from"./kickoff.js";import{appendSituationalContext as Le,formatSituationalProse as Me}from"./situational-context.js";import{ensureRoadmap as Te}from"./roadmap.js";import{buildWakeBearings as Ae}from"./bearings.js";import{encodeKickoffOrigin as We,KICKOFF_ORIGIN_ENV as je}from"./stamp/protocol.js";import{ExecutionCapReached as ze,beginExecution as He,crtrHome as Ke,getNode as u,fullName as re,jobDir as Ge,recordExecutionPid as Ue,abortExecution as j,setFrozen as z}from"../canvas/index.js";import{contextDir as H,nodeAgentDir as K}from"../canvas/node-agent-paths.js";import{copyTreeBeneath as Ve}from"../spaces/open-beneath.js";import{conversationIdFromPath as D,conversationStore as S}from"../conversation-store/index.js";import{appMemoryTooSmall as Xe,boundFleet as qe,brokerThresholdsForDaemon as te}from"./fleet.js";import{admitBrokerMemory as Ye}from"./memory-admission.js";import{emitEvent as N}from"../events/emit.js";import{blaxelEnvironmentOf as Je}from"./blaxel-environment.js";import{openViewerWindow as Qe,focusOf as Ze,windowOfPane as en}from"./placement.js";import{awaitBrokerViewSocket as nn}from"./view-socket.js";import{readLogSnapshot as on}from"../events/read.js";import{transition as k}from"./lifecycle.js";import{beginBootFaultAttempt as rn}from"../canvas/recovery.js";import{headlessBrokerHost as G}from"./host.js";import{ensureDaemon as tn}from"../../daemon/manage.js";import{readConfig as an}from"../config.js";import{modelRequestFromConfig as dn,unregisteredConcreteModel as sn,unroutableConcreteModel as ln}from"../model-routes.js";import{openModelRegistry as cn}from"./model-registry.js";import{MODEL_SPEC_NEXT as un}from"./model-selection.js";import{forkNodeLedger as fn}from"./ledger.js";import{appRungForGrant as wn}from"../llm/app-rungs.js";import{APP_FAMILY as U}from"../model-routes.js";import{discoverLifecycleHookRegistry as mn}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as hn}from"../command-hooks/transport/exec-lifecycle.js";import{someAsync as pn}from"../async-array.js";import{checkStart as _n}from"./start-check.js";function v(e){return{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}d(v,"launchFailureOutcome");async function kn(e,o,a){try{return await G.launch(e,o,a)}catch(r){try{await k(e,"crash",{reason:"launch_failed",outcome:v(r)})}catch{}const t=r.message;throw B(t.startsWith("[broker]")?t:`[broker] refusing to launch ${e}: ${t}`,"Inspect the cause above, fix the launch recipe or environment, then retry.")}}d(kn,"launchBrokerOrCrash");function vn(e){return on({nodeId:e,component:"broker",pattern:"broker.startup."},!1).items.flatMap(a=>a.kind==="event"&&a.envelope.event.startsWith("broker.startup.")&&a.envelope.event!=="broker.startup.warning"?[a.envelope.event.slice(15)]:[]).at(-1)??null}d(vn,"lastStartupStep");function gn(e,o){const a=vn(e),r=a===null?"it had logged no startup step":`the last startup step it logged was \`${a}\``;if(o.reason==="exited"){const{code:t,signal:s}=o.status;return{text:`exited (code ${t??"null"}, signal ${s??"null"}) before binding its view socket; ${r}`,fields:{reason:"exited",code:t,signal:s,last_startup_step:a}}}return{text:`was still starting after ${Math.round(o.waitedMs/1e3)} s without binding its view socket, so the launcher stopped it; ${r}`,fields:{reason:"timeout",waited_ms:o.waitedMs,last_startup_step:a}}}d(gn,"notReadyDescription");async function yn(e,o){try{await k(e,"crash",{reason:"launch_failed",outcome:v(o)})}catch{}try{G.teardown(e)}catch{}}d(yn,"crashAndTearDown");async function bn(e){const o=(await S().list()).map(({conversation_id:t,path:s})=>({id:t,path:s})),a=o.filter(t=>t.id===e),r=a.length>0?a:o.filter(t=>t.id.startsWith(e));if(r.length===0)throw w(`--fork-from '${e}': no pi session with that id found.`,{next:"Pass a live node id, a real session uuid/prefix, or an absolute .jsonl session path."});if(r.length>1)throw w(`--fork-from '${e}': ambiguous \u2014 ${r.length} sessions match that id prefix; pass the full id or the .jsonl path.`,{next:"Pass the full session uuid or an absolute .jsonl path to disambiguate."});return r[0].path}d(bn,"resolveSessionUuid");async function ie(e){const o=e.trim();if(o==="")throw w("--fork-from requires a node id, session file, or session uuid.",{next:"Pass a live node id, an absolute .jsonl session path, or a session uuid/prefix."});if(o.includes("/")||o.endsWith(".jsonl")){const r=D(_e(o)?o:ke(process.cwd(),o));if(r===null)throw w(`--fork-from '${o}': invalid conversation path.`,{next:"Pass a conversation file path or id."});return(await S().header(r)).path}const a=await u(o);if(a!==null){const r=a.pi_session_file;if(r==null||r==="")throw w(`node ${o} has no pi session yet \u2014 it has not captured a session FILE to fork from (the broker forks a .jsonl path, not a bare id).`,{next:"Pick a node that has captured a session, or drop --fork-from."});const t=D(r);if(t===null)throw w(`node ${o} has no valid conversation id.`,{next:"Pick a node with a captured conversation."});return(await S().header(t)).path}return await bn(o)}d(ie,"resolveForkSource");async function xn(e,o,a,r={}){return e===null?null:e!==void 0&&e!==""?Ee(e).profileId:o!==null?(await u(o))?.profile_id??null:r.readOnlySelection===!0?Oe(a):Re(a)}d(xn,"resolveProfileId");function ae(e){const o=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return dn(e.model,o,e.modelExact===!0)}d(ae,"requestFromLaunch");async function de(e,o,a){const r=a??(e.modelIntent?`${e.modelIntent.family}/${e.modelIntent.strength}`:e.model),t=await wn(o,r,e.modelExact===!0);if(t===null)return e;const{CRTR_MODEL_INTENT:s,...l}=e.env??{};return{...e,model:t.model,modelIntent:{family:U,strength:t.strength},modelExact:void 0,env:{...l,CRTR_MODEL_INTENT:`${U}/${t.strength}`}}}d(de,"appPaidLaunch");async function se(e,o,a){if(e===void 0||e.kind==="logical"&&e.family!==U)return;const r=await sn(e.kind==="logical"?{kind:"concrete",spec:e.spec}:e,a??await cn(),o);if(r!==void 0)throw w(`model '${r.request.spec}' is not registered in this daemon.`,{received:r.request.spec,next:un});const t=await ln(e,o);if(t!==void 0)throw w(`model '${t.spec}' is registered but no configured model route offers it, so no turn could be served.`,{received:t.spec,next:"Pick a model from your configured routes (`crtr sys config get modelLadders`), or add this one to a ladder or route."})}d(se,"assertLaunchModelRegistered");function $n(e,o,a){const r=e??o??null;if(!a&&r===null)throw new Error("spawnChild requires a calling node (CRTR_NODE_ID) or an explicit parent");return r}d($n,"resolveSpawner");async function le(e,o,a){try{tn()}catch{}const r=xe(),t=e.root===!0,s=$n(e.parent,r.nodeId??null,t),l=e.mode??"base",g=e.rootLifecycle??(t?"resident":"terminal"),ce=t&&g==="resident",E=s===null?null:await u(s),V=e.creator===void 0||e.creator===null?null:await u(e.creator);e.nodeId!==void 0&&await Ce(e.nodeId);const y=e.forkFrom!==void 0?await ie(e.forkFrom):void 0,L=y===void 0?null:await be(y),M=await pn([E,V,L],async f=>f?.isolated===!0||f?.run_id!=null&&(await u(f.run_id))?.isolated===!0);if(M&&e.isolated===!1)throw new ne(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});const R=M||e.isolated===!0;if(R&&e.worktree===!0)throw new ne(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const C=e.worktree===!0,m=R||C?e.nodeId??await Se():e.nodeId,O=R?e.run!==void 0&&t&&!M?e.cwd:ve(ge(e.run?.grantee??E?.grantee??"app:terminal").nodes,m):e.cwd,h=await xn(e.profile,s,O),X=e.run?.grant_id??E?.grant_id??null,q=await de((await oe(e.kind,l,{lifecycle:g,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:O,profileId:h})).launch,X,e.model);await se(ae(q),{cwd:O,profileId:h});const T=e.run??V??E??L;await _n({grantee:T?.grantee??"app:terminal",sub:T?.sub,grant_id:T?.grant_id});const Y=L?.node_id??null;let b,F=O;const A=C&&await Ie(h)?await Pe(h,e.worktreeCwd??e.cwd,m,e.worktreeBase):void 0;try{C&&A===void 0&&(b=await Be(e.worktreeCwd??e.cwd,m,e.worktreeBase),F=b.path);const f=C?await de((await oe(e.kind,l,{lifecycle:g,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:F,profileId:h})).launch,X,e.model):q;A!==void 0&&(f.worktree=A),C&&await se(ae(f),{cwd:F,profileId:h});const n=await ye({kind:e.kind,mode:l,lifecycle:g,cwd:F,name:e.name??e.kind,description:e.description,parent:t?null:s,creator:e.creator,...e.actor===void 0?{}:{actor:e.actor},forkSourceNode:Y,spawnedBy:t?s??void 0:void 0,profile_id:h,...e.scopes===void 0?{}:{scopes:e.scopes},isolated:R,...e.run===void 0?{}:{run:e.run},...e.causedBy===void 0?{}:{causedBy:e.causedBy},...e.withinCreate===void 0?{}:{withinCreate:e.withinCreate},forkFrom:e.forkFrom,forkSourceFile:y,modelOverride:e.model===void 0?void 0:f.model,...b!==void 0?{managedWorktree:b}:{},...m!==void 0?{nodeId:m}:{},...e.reviewBinding===void 0?{}:{reviewBinding:e.reviewBinding},...e.deadlineAt===void 0?{}:{deadlineAt:e.deadlineAt},...e.outcomeDelivery===void 0?{}:{outcomeDelivery:e.outcomeDelivery},launch:f});if(a?.(n.node_id),e.forkFrom!==void 0)try{await fn(n.node_id,Y??null)}catch(i){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),i}if(await Ne(n.node_id,e.prompt),e.situationalContext!==void 0&&await Le(n.node_id,Me(e.situationalContext)),o!==void 0)try{o(n.node_id)}catch(i){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),i}const W=e.prompt!=="",ue=`${W&&e.wakeOrigin!==void 0?`${Ae(e.wakeOrigin)}
|
|
1
|
+
var me=Object.defineProperty;var d=(e,o)=>me(e,"name",{value:o,configurable:!0});import{accessSync as he,constants as pe}from"node:fs";import{isAbsolute as _e,resolve as ke,join as ve}from"node:path";import{appSpace as ge}from"../layout.js";import{ApiError as ne}from"../../api/errors.js";import{spawnNode as ye,forkSourceNode as be,currentNodeContext as xe,rootOfSpine as $e,newNodeId as Se,preflightNodeId as Ce}from"./nodes.js";import{resolveProfileOperand as Ee}from"../profiles/manifest.js";import{selectProfileForCwd as Re,selectProfileForCwdReadOnly as Oe}from"../profiles/select.js";import{buildLaunchSpecAsync as oe,buildPiArgv as Fe}from"./launch.js";import{runsOnBlaxel as Ie,sandboxWorktreeRequest as Pe}from"../../daemon/api/environment-of.js";import{createManagedWorktreeAsync as Be,rollbackManagedWorktreeAsync as De}from"../worktree-mutation-async.js";import{usage as w,brokerLaunchFailed as D}from"../errors.js";import{writeGoal as Ne}from"./kickoff.js";import{appendSituationalContext as Le,formatSituationalProse as Me}from"./situational-context.js";import{ensureRoadmap as Te}from"./roadmap.js";import{buildWakeBearings as Ae}from"./bearings.js";import{encodeKickoffOrigin as We,KICKOFF_ORIGIN_ENV as je}from"./stamp/protocol.js";import{ExecutionCapReached as ze,beginExecution as He,crtrHome as Ke,getNode as u,fullName as re,jobDir as Ge,recordExecutionPid as Ue,abortExecution as j,setFrozen as z}from"../canvas/index.js";import{contextDir as H,nodeAgentDir as K}from"../canvas/node-agent-paths.js";import{copyTreeBeneath as Ve}from"../spaces/open-beneath.js";import{conversationIdFromPath as N,conversationStore as S}from"../conversation-store/index.js";import{appMemoryTooSmall as Xe,boundFleet as qe,brokerThresholdsForDaemon as te}from"./fleet.js";import{admitBrokerMemory as Ye}from"./memory-admission.js";import{emitEvent as L}from"../events/emit.js";import{blaxelEnvironmentOf as Je}from"./blaxel-environment.js";import{openViewerWindow as Qe,focusOf as Ze,windowOfPane as en}from"./placement.js";import{awaitBrokerViewSocket as nn}from"./view-socket.js";import{readLogSnapshot as on}from"../events/read.js";import{transition as k}from"./lifecycle.js";import{beginBootFaultAttempt as rn}from"../canvas/recovery.js";import{headlessBrokerHost as G}from"./host.js";import{ensureDaemon as tn}from"../../daemon/manage.js";import{readConfig as an}from"../config.js";import{modelRequestFromConfig as dn,unregisteredConcreteModel as sn,unroutableConcreteModel as ln}from"../model-routes.js";import{openModelRegistry as cn}from"./model-registry.js";import{MODEL_SPEC_NEXT as un}from"./model-selection.js";import{forkNodeLedger as fn}from"./ledger.js";import{appRungForGrant as wn}from"../llm/app-rungs.js";import{APP_FAMILY as U}from"../model-routes.js";import{discoverLifecycleHookRegistry as mn}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as hn}from"../command-hooks/transport/exec-lifecycle.js";import{someAsync as pn}from"../async-array.js";import{checkStart as _n}from"./start-check.js";function v(e){return{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}d(v,"launchFailureOutcome");async function kn(e,o,a){try{return await G.launch(e,o,a)}catch(r){try{await k(e,"crash",{reason:"launch_failed",outcome:v(r)})}catch{}const t=r.message;throw D(t.startsWith("[broker]")?t:`[broker] refusing to launch ${e}: ${t}`,"Inspect the cause above, fix the launch recipe or environment, then retry.")}}d(kn,"launchBrokerOrCrash");function vn(e){return on({nodeId:e,component:"broker",pattern:"broker.startup."},!1).items.flatMap(a=>a.kind==="event"&&a.envelope.event.startsWith("broker.startup.")&&a.envelope.event!=="broker.startup.warning"?[a.envelope.event.slice(15)]:[]).at(-1)??null}d(vn,"lastStartupStep");function gn(e,o){const a=vn(e),r=a===null?"it had logged no startup step":`the last startup step it logged was \`${a}\``;if(o.reason==="exited"){const{code:t,signal:s}=o.status;return{text:`exited (code ${t??"null"}, signal ${s??"null"}) before binding its view socket; ${r}`,fields:{reason:"exited",code:t,signal:s,last_startup_step:a}}}return{text:`was still starting after ${Math.round(o.waitedMs/1e3)} s without binding its view socket, so the launcher stopped it; ${r}`,fields:{reason:"timeout",waited_ms:o.waitedMs,last_startup_step:a}}}d(gn,"notReadyDescription");async function yn(e,o){try{await k(e,"crash",{reason:"launch_failed",outcome:v(o)})}catch{}try{G.teardown(e)}catch{}}d(yn,"crashAndTearDown");async function bn(e){const o=(await S().list()).map(({conversation_id:t,path:s})=>({id:t,path:s})),a=o.filter(t=>t.id===e),r=a.length>0?a:o.filter(t=>t.id.startsWith(e));if(r.length===0)throw w(`--fork-from '${e}': no pi session with that id found.`,{next:"Pass a live node id, a real session uuid/prefix, or an absolute .jsonl session path."});if(r.length>1)throw w(`--fork-from '${e}': ambiguous \u2014 ${r.length} sessions match that id prefix; pass the full id or the .jsonl path.`,{next:"Pass the full session uuid or an absolute .jsonl path to disambiguate."});return r[0].path}d(bn,"resolveSessionUuid");async function ie(e){const o=e.trim();if(o==="")throw w("--fork-from requires a node id, session file, or session uuid.",{next:"Pass a live node id, an absolute .jsonl session path, or a session uuid/prefix."});if(o.includes("/")||o.endsWith(".jsonl")){const r=N(_e(o)?o:ke(process.cwd(),o));if(r===null)throw w(`--fork-from '${o}': invalid conversation path.`,{next:"Pass a conversation file path or id."});return(await S().header(r)).path}const a=await u(o);if(a!==null){const r=a.pi_session_file;if(r==null||r==="")throw w(`node ${o} has no pi session yet \u2014 it has not captured a session FILE to fork from (the broker forks a .jsonl path, not a bare id).`,{next:"Pick a node that has captured a session, or drop --fork-from."});const t=N(r);if(t===null)throw w(`node ${o} has no valid conversation id.`,{next:"Pick a node with a captured conversation."});return(await S().header(t)).path}return await bn(o)}d(ie,"resolveForkSource");async function xn(e,o,a,r={}){return e===null?null:e!==void 0&&e!==""?Ee(e).profileId:o!==null?(await u(o))?.profile_id??null:r.readOnlySelection===!0?Oe(a):Re(a)}d(xn,"resolveProfileId");function ae(e){const o=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return dn(e.model,o,e.modelExact===!0)}d(ae,"requestFromLaunch");async function de(e,o,a){const r=a??(e.modelIntent?`${e.modelIntent.family}/${e.modelIntent.strength}`:e.model),t=await wn(o,r,e.modelExact===!0);if(t===null)return e;const{CRTR_MODEL_INTENT:s,...l}=e.env??{};return{...e,model:t.model,modelIntent:{family:U,strength:t.strength},modelExact:void 0,env:{...l,CRTR_MODEL_INTENT:`${U}/${t.strength}`}}}d(de,"appPaidLaunch");async function se(e,o,a){if(e===void 0||e.kind==="logical"&&e.family!==U)return;const r=await sn(e.kind==="logical"?{kind:"concrete",spec:e.spec}:e,a??await cn(),o);if(r!==void 0)throw w(`model '${r.request.spec}' is not registered in this daemon.`,{received:r.request.spec,next:un});const t=await ln(e,o);if(t!==void 0)throw w(`model '${t.spec}' is registered but no configured model route offers it, so no turn could be served.`,{received:t.spec,next:"Pick a model from your configured routes (`crtr sys config get modelLadders`), or add this one to a ladder or route."})}d(se,"assertLaunchModelRegistered");function $n(e,o,a){const r=e??o??null;if(!a&&r===null)throw new Error("spawnChild requires a calling node (CRTR_NODE_ID) or an explicit parent");return r}d($n,"resolveSpawner");async function le(e,o,a){try{tn()}catch{}const r=xe(),t=e.root===!0,s=$n(e.parent,r.nodeId??null,t),l=e.mode??"base",g=e.rootLifecycle??(t?"resident":"terminal"),ce=t&&g==="resident",R=s===null?null:await u(s),V=e.creator===void 0||e.creator===null?null:await u(e.creator);e.nodeId!==void 0&&await Ce(e.nodeId);const y=e.forkFrom!==void 0?await ie(e.forkFrom):void 0,M=y===void 0?null:await be(y),T=await pn([R,V,M],async f=>f?.isolated===!0||f?.run_id!=null&&(await u(f.run_id))?.isolated===!0);if(T&&e.isolated===!1)throw new ne(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});const O=T||e.isolated===!0;if(O&&e.worktree===!0)throw new ne(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const C=e.worktree===!0,m=O||C?e.nodeId??await Se():e.nodeId,F=O?e.run!==void 0&&t&&!T?e.cwd:ve(ge(e.run?.grantee??R?.grantee??"app:terminal").nodes,m):e.cwd,h=await xn(e.profile,s,F),X=e.run?.grant_id??R?.grant_id??null,E=e.run??V??R??M,q=await de((await oe(e.kind,l,{lifecycle:g,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:F,profileId:h,app:E?.grantee??"app:terminal"})).launch,X,e.model);await se(ae(q),{cwd:F,profileId:h}),await _n({grantee:E?.grantee??"app:terminal",sub:E?.sub,grant_id:E?.grant_id});const Y=M?.node_id??null;let b,I=F;const A=C&&await Ie(h)?await Pe(h,e.worktreeCwd??e.cwd,m,e.worktreeBase):void 0;try{C&&A===void 0&&(b=await Be(e.worktreeCwd??e.cwd,m,e.worktreeBase),I=b.path);const f=C?await de((await oe(e.kind,l,{lifecycle:g,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:I,profileId:h,app:E?.grantee??"app:terminal"})).launch,X,e.model):q;A!==void 0&&(f.worktree=A),C&&await se(ae(f),{cwd:I,profileId:h});const n=await ye({kind:e.kind,mode:l,lifecycle:g,cwd:I,name:e.name??e.kind,description:e.description,parent:t?null:s,creator:e.creator,...e.actor===void 0?{}:{actor:e.actor},forkSourceNode:Y,spawnedBy:t?s??void 0:void 0,profile_id:h,...e.scopes===void 0?{}:{scopes:e.scopes},isolated:O,...e.run===void 0?{}:{run:e.run},...e.causedBy===void 0?{}:{causedBy:e.causedBy},...e.withinCreate===void 0?{}:{withinCreate:e.withinCreate},forkFrom:e.forkFrom,forkSourceFile:y,modelOverride:e.model===void 0?void 0:f.model,...b!==void 0?{managedWorktree:b}:{},...m!==void 0?{nodeId:m}:{},...e.reviewBinding===void 0?{}:{reviewBinding:e.reviewBinding},...e.deadlineAt===void 0?{}:{deadlineAt:e.deadlineAt},...e.outcomeDelivery===void 0?{}:{outcomeDelivery:e.outcomeDelivery},launch:f});if(a?.(n.node_id),e.forkFrom!==void 0)try{await fn(n.node_id,Y??null)}catch(i){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),i}if(await Ne(n.node_id,e.prompt),e.situationalContext!==void 0&&await Le(n.node_id,Me(e.situationalContext)),o!==void 0)try{o(n.node_id)}catch(i){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),i}const W=e.prompt!=="",ue=`${W&&e.wakeOrigin!==void 0?`${Ae(e.wakeOrigin)}
|
|
2
2
|
|
|
3
|
-
`:""}${e.prompt}`;l==="orchestrator"&&await Te(n.node_id,{goal:e.prompt.trim()}),await Sn(n);let J;if(y!==void 0)try{const i=
|
|
3
|
+
`:""}${e.prompt}`;l==="orchestrator"&&await Te(n.node_id,{goal:e.prompt.trim()}),await Sn(n);let J;if(y!==void 0)try{const i=N(y);if(i===null)throw new Error(`invalid fork source ${y}`);const c=await S().fork(i,n.node_id);J=(await S().header(c)).path}catch(i){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),i}const x=Fe(n,{prompt:ue,resumeSessionPath:J});if(x.env={...x.env,CRTR_SUBTREE:await $e(n.node_id)},W){const i=e.wakeOrigin!==void 0?{type:"runtime",kind:"wake",wake:e.wakeOrigin}:{type:"runtime",kind:"kickoff",...n.spawned_by!=null&&n.spawned_by!==""?{spawnedBy:n.spawned_by}:{}};x.env[je]=We(i)}const p=qe();if(await Je(n.profile_id??null)!==null)return await z(n.node_id,new Date().toISOString()),L({level:"info",event:"broker.frozen",node_id:n.node_id,fields:{reason:"remote_environment"}}),{node:await u(n.node_id),frozen:!0,window:null,session:null};const Q=await p.reserveSlot(n.node_id),_=Q?await Ye(n.node_id):null;if(_?.verdict==="too_small"){p.releaseReservation(n.node_id);const i=Xe(_);throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),i}if(!Q||_?.verdict==="denied")return _?.verdict==="denied"&&p.releaseReservation(n.node_id),await z(n.node_id,new Date().toISOString()),L({level:"info",event:"broker.frozen",node_id:n.node_id,fields:_?.verdict==="denied"?{reason:"app_memory",free_bytes:_.free_bytes,needed_bytes:_.needed_bytes}:{reason:"broker_cap",live_count:await p.occupancy(),hard_cap:te().automaticReviveCap}}),{node:await u(n.node_id),frozen:!0,window:null,session:null};const fe=await rn(n.node_id),{automaticReviveCap:we}=te();let $;try{$=await He(n.node_id,{daemonEpoch:p.epoch(),cap:we})}catch(i){if(!(i instanceof ze))throw i;return p.releaseReservation(n.node_id),await z(n.node_id,new Date().toISOString()),L({level:"info",event:"broker.frozen",node_id:n.node_id,fields:{reason:"broker_cap",live_count:i.live,hard_cap:i.cap}}),{node:await u(n.node_id),frozen:!0,window:null,session:null}}x.env={...x.env,CRTR_EXECUTION_ID:$};let P;try{P=await kn(n.node_id,x,{cwd:n.cwd,name:re(n),resuming:!1})}catch(i){throw await j($,{reason:"launch_failed"}),i}finally{p.releaseReservation(n.node_id)}if(P.pid===null){const i=new Error(`broker host returned no pid for ${n.node_id}`);throw await j($,{reason:"launch_failed"}),await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(i)}),D(`failed to launch the broker engine for ${n.node_id} (${n.name}) \u2014 the node was not started.`,`Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then verify the pi engine can start in this environment.`)}if(await Ue($,n.node_id,P.pid)==="shutdown")throw await j($,{reason:"superseded"}),G.teardown(n.node_id),D(`broker execution was superseded for ${n.node_id}`,"Retry spawning the node.");if(ce&&e.readiness==="await"){const i=await nn(n.node_id,P.exited);if(!i.ready){const c=gn(n.node_id,i);L({level:"error",event:"broker.launch.not_ready",node_id:n.node_id,fields:c.fields});const B=await fe.explanation();throw await yn(n.node_id,new Error(B??c.text)),D(B!==null?`the root broker ${n.node_id} could not start \u2014 ${B}`:`the root broker ${n.node_id} ${c.text} \u2014 it was not started.`,B!==null?"Resolve the cause named above, then retry.":`Inspect canonical event diagnostics with \`crtr sys logs --node ${n.node_id}\`, then retry.`)}}let Z=null,ee=null;if(!t&&s!==null&&an("user").auto_open_child_viewers)try{const i=await Ze(s);if(i!==null&&i.pane!==null&&i.pane!==""){const c=await Qe(n.node_id,i.session??"",{name:re(n),cwd:e.cwd,besidePane:i.pane,waitForBroker:!0,initialWhip:W});c!==null&&c.pane!==null&&c.pane!==""&&(ee=c.session,Z=en(c.pane))}}catch{}return{node:await u(n.node_id),frozen:!1,window:Z,session:ee}}catch(f){throw b!==void 0&&m!==void 0&&await u(m)===null&&await De(b),f}}d(le,"spawnChildPrepared");async function vo(e){return le(e)}d(vo,"spawnChild");async function Sn(e){const o=mn(e.cwd,e.profile_id).plans.get("node:start")??[];await hn(o,{node:{id:e.node_id,name:e.name,kind:e.kind,mode:e.mode,lifecycle:e.lifecycle,cwd:e.cwd,nodeDir:await K(e.node_id),contextDir:await H(e.node_id),jobDir:Ge(e.node_id)},runtime:{isBirth:!0,canvasHome:Ke(),profile:e.profile_id??null}})}d(Sn,"invokeBirthLifecycleHooks");const Cn=new Set(["initial-prompt.md","yield-message.md","result.json","jobs"]);async function go(e,o,a){const r=await u(e);if(r===null)throw w(`unknown node: ${e}`,{received:e,next:"List nodes and pass the id of a node with a captured pi session."});const t=await ie(e),s=await H(e);try{await S().header(N(t)),he(s,pe.R_OK)}catch(l){throw new Error(`cannot fork ${e}: its conversation or context is unreadable \u2014 ${l.message}`)}return le({kind:r.kind,mode:"base",cwd:r.cwd,prompt:"",root:!0,readiness:"await",forkFrom:e,...a===void 0?{}:{actor:a},profile:r.profile_id,model:r.model_override??void 0,...o===void 0?{}:{scopes:o}},async l=>{const g=await H(l);Ve(await K(e),s,await K(l),g,Cn)})}d(go,"forkNode");export{de as appPaidLaunch,se as assertLaunchModelRegistered,go as forkNode,Sn as invokeBirthLifecycleHooks,ie as resolveForkSource,xn as resolveProfileId,$n as resolveSpawner,vo as spawnChild,le as spawnChildPrepared};
|
|
@@ -53,7 +53,8 @@ export interface BrokerViewLink {
|
|
|
53
53
|
on(event: 'close', listener: (hadError: boolean) => void): this;
|
|
54
54
|
}
|
|
55
55
|
/** A broker's `/view` WebSocket as a {@link BrokerViewLink}. Each broker message is one frame, delivered as one
|
|
56
|
-
* newline-terminated chunk; each line written is sent as one text message
|
|
56
|
+
* newline-terminated chunk; each line written is sent as one text message that keeps its newline: the broker reads
|
|
57
|
+
* this WebSocket as a byte stream through its line decoder, which completes a frame only at a newline. The headers (the preview token) are
|
|
57
58
|
* sent on the handshake only and kept nowhere else. */
|
|
58
59
|
export declare function connectWssView(url: string, headers: Record<string, string>): BrokerViewLink;
|
|
59
60
|
/** Resolve true once the broker's `/view` WebSocket accepts a handshake within `waitMs`, retrying while it refuses;
|
|
@@ -1,3 +1,4 @@
|
|
|
1
1
|
var m=Object.defineProperty;var c=(n,e)=>m(n,"name",{value:e,configurable:!0});import{EventEmitter as p}from"node:events";import{createConnection as y,Socket as E}from"node:net";import{WebSocket as u}from"ws";import{CLIENT_READ_CAPS as S}from"./broker-protocol.js";import{nodeRunDir as x,viewSocketPath as k}from"../canvas/paths.js";import{isBeneathRefusal as O,socketBeneath as _}from"../spaces/open-beneath.js";const w=3e4,d=100,K=w;function h(n){return new Promise(e=>{setTimeout(e,n)})}c(h,"sleep");function R(n){let e;try{e=_(x(n),k(n))}catch(t){const r=new E;return process.nextTick(()=>r.destroy(t)),r}const s=y(e.path);return s.once("connect",e.release),s.once("close",e.release),s}c(R,"connectViewSocket");function T(n,e){return new Promise((s,t)=>{let r=!1,i=null;const f=c(o=>{r||(r=!0,i!==null&&i.destroy(),o instanceof Error?t(o):s(o))},"finish");i=R(n),i.once("connect",()=>f(!0)),i.once("error",o=>f(O(o)?o:!1)),i.setTimeout(e,()=>f(!1))})}c(T,"probeViewSocket");async function B(n,e,s=w){const t=Date.now()+s,r=e?.then(i=>({exit:i}));for(;Date.now()<=t;){const i=Math.max(0,t-Date.now()),f=T(n,Math.min(d,i)).then(a=>a?"ready":"retry"),o=r===void 0?await f:await Promise.race([f,r]);if(o==="ready")return{ready:!0};if(typeof o=="object")return{ready:!1,reason:"exited",status:o.exit};if(r!==void 0){const a=await Promise.race([h(d).then(()=>"sleep"),r]);if(typeof a=="object")return{ready:!1,reason:"exited",status:a.exit}}else await h(d)}return{ready:!1,reason:"timeout",waitedMs:s}}c(B,"awaitBrokerViewSocket");async function I(n,e,s=w){return(await B(n,e,s)).ready}c(I,"waitForBrokerViewSocket");const M=4180;function C(n,e){return new g(n,e)}c(C,"connectWssView");class g extends p{static{c(this,"WssViewLink")}ws;failed=!1;ended=!1;terminated=!1;pending=[];constructor(e,s){super(),this.ws=new u(e,{headers:s,maxPayload:S.maxLineBytes}),this.ws.on("open",()=>{for(const t of this.pending.splice(0))this.ws.send(t);this.emit("connect")}),this.ws.on("message",t=>{const r=Array.isArray(t)?Buffer.concat(t):Buffer.isBuffer(t)?t:Buffer.from(new Uint8Array(t));this.emit("data",r.at(-1)===10?r:Buffer.concat([r,Buffer.from(`
|
|
2
2
|
`)]))}),this.ws.on("unexpected-response",(t,r)=>{this.fail(Object.assign(new Error(`broker view refused the upgrade (${r.statusCode??"no status"})`),{code:"ECONNREFUSED"})),this.ws.terminate()}),this.ws.on("error",t=>this.fail(t)),this.ws.on("close",t=>{this.ended||(t===1006&&!this.terminated&&this.fail(Object.assign(new Error("broker view connection dropped (1006)"),{code:"ECONNRESET"})),this.ended=!0,this.emit("close",this.failed))})}get destroyed(){return this.ended||this.ws.readyState===u.CLOSING||this.ws.readyState===u.CLOSED}write(e){const s=e.endsWith(`
|
|
3
|
-
`)?e
|
|
3
|
+
`)?e:`${e}
|
|
4
|
+
`;return this.ws.readyState===u.CONNECTING?(this.pending.push(s),!0):this.ws.readyState!==u.OPEN?!1:(this.ws.send(s),!0)}destroy(){return this.terminated=!0,this.ws.terminate(),this}fail(e){this.failed||(this.failed=!0,this.emit("error",e))}}async function F(n,e,s,t=w){const r=Date.now()+t;let i=!1;for(s?.then(()=>{i=!0});Date.now()<=r&&!i;){if(await new Promise(o=>{const a=C(n,e),l=setTimeout(()=>{a.destroy(),o(!1)},Math.max(1,r-Date.now()));a.on("connect",()=>{clearTimeout(l),a.destroy(),o(!0)}),a.on("error",()=>{}),a.on("close",()=>{clearTimeout(l),o(!1)})}))return!0;if(Date.now()+d>r)break;await h(d)}return!1}c(F,"waitForWssView");export{M as BROKER_VIEW_PORT,K as BROKER_VIEW_SOCKET_WAIT_MS,B as awaitBrokerViewSocket,R as connectViewSocket,C as connectWssView,T as probeViewSocket,I as waitForBrokerViewSocket,F as waitForWssView};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var N=Object.defineProperty;var n=(e,r)=>N(e,"name",{value:r,configurable:!0});import{createHash as R,randomUUID as L}from"node:crypto";import{openDb as b}from"../canvas/db.js";import{claimReconcilerLease as C,releaseReconcilerLease as E,renewReconcilerLease as W}from"../canvas/reconciler-leases.js";import{claimWarmSpare as M,deleteNode as u,getNode as
|
|
1
|
+
var N=Object.defineProperty;var n=(e,r)=>N(e,"name",{value:r,configurable:!0});import{createHash as R,randomUUID as L}from"node:crypto";import{openDb as b}from"../canvas/db.js";import{claimReconcilerLease as C,releaseReconcilerLease as E,renewReconcilerLease as W}from"../canvas/reconciler-leases.js";import{claimWarmSpare as M,deleteNode as u,getNode as p,listNodes as P,listWarmSpares as y,registerWarmSpare as I,unregisterWarmSpare as h,updateNode as A,warmSpareCount as g}from"../canvas/index.js";import{recordedPidLiveness as D}from"../canvas/pid.js";import{nowIso as _}from"../fs-utils.js";import{admitNodeCreate as O}from"../command-hooks/lifecycle-create.js";import{isDrained as T}from"../../daemon/drain.js";import{spawnChildPrepared as H}from"./spawn.js";import{blaxelEnvironmentOf as F}from"./blaxel-environment.js";import{newNodeId as K}from"./nodes.js";import{checkStart as U}from"./start-check.js";import{buildLaunchSpecAsync as j}from"./launch.js";import{setModelLive as B}from"./model-swap.js";import{setSituationalContextLive as G}from"./situational-live.js";import{deliverBearingsLive as J}from"./deliver-live.js";import{closeNode as f}from"./close.js";function v(){return process.env.CRTR_WARM_POOL!=="0"}n(v,"warmPoolEnabled");function z(e,r,a){const t=Object.entries(a.env??{}).sort(([s],[i])=>s<i?-1:s>i?1:0),o=JSON.stringify([e,r,a.tools??[],a.extensions??[],a.systemPrompt??null,t]);return R("sha256").update(o).digest("hex").slice(0,32)}n(z,"warmRecipeKey");async function d(e){const{launch:r}=await j(e.kind,e.mode,{lifecycle:"resident",hasManager:!1,...e.model!==null?{model:e.model}:{},cwd:e.cwd,profileId:e.profileId,app:"app:terminal"});return{key:z(e.cwd,e.profileId,r),launch:r,request:e}}n(d,"resolveRecipe");async function S(e){const r=e.creator===null?null:await p(e.creator);await U({grantee:r?.grantee??"app:terminal",sub:r?.sub,grant_id:r?.grant_id})}n(S,"checkClaimantStart");async function ye(e,r={},a){await S(e);const t=await d(e);if(await g(t.key)===0)return null;const o=_(),s=await O({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 M(t.key,o,r)}finally{s()}return i===null?null:k(i,t,o,a)}n(ye,"claimWarmNode");async function he(e,r,a){return await S(e),k(r,await d(e),_(),a)}n(he,"resumeWarmClaim");async function k(e,r,a,t){const{request:o}=r,i=(await p(e))?.launch?.model;await A(e,{created:a,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{t?.(e)}catch(l){return await m(e,"birth preparation",l)}try{await J(e)}catch(l){return await m(e,"bearings delivery",l)}const c=r.launch.model;if(c!==void 0&&c!==i)try{await B(e,c,r.launch.modelIntent)}catch(l){return await m(e,"model swap",l)}if(o.situationalContext!==null)try{await G(e,o.situationalContext)}catch(l){return await m(e,"situational-context delivery",l)}return e}n(k,"completeWarmClaim");async function m(e,r,a){console.error(`[warm-pool] ${r} failed on claim; closing the spare: ${a.message}`);try{await f(e)}catch{}return null}n(m,"abandonSpare");const Q=3600*1e3;async function ge(){const e=[];let r;try{r=await y()}catch(t){return console.error(`[warm-pool] spare scan failed: ${t.message}`),e}const a=Date.now()-Q;for(const t of r){if(await V(t.node_id))continue;const o=Date.parse(t.created),s=Number.isNaN(o)||o<a,i=D(t.pi_pid,t.pi_pid_identity),c=(t.status==="active"||t.status==="idle")&&i==="alive";if(!(c&&!s)&&!(i==="indeterminate"&&!s))try{if(!await h(t.node_id))continue;if(c)try{await f(t.node_id)}catch{}await u(t.node_id),e.push(t.node_id)}catch(l){console.error(`[warm-pool] reap failed for ${t.node_id}: ${l.message}`)}}return e}n(ge,"reapStaleSpares");async function _e(){for(const e of await y())if(await h(e.node_id)){try{await f(e.node_id)}catch(r){console.error(`[warm-pool] close failed for ${e.node_id}: ${r.message}`)}await u(e.node_id)}}n(_e,"emptyWarmPool");const w=6e4;async function x(e,r){const a=L();if(await C(e,r,a,w)===void 0)return;const t=setInterval(()=>{W(e,r,a,w).catch(()=>{})},w/3);return t.unref(),async()=>{clearInterval(t),await E(e,r,a)}}n(x,"holdMintLease");async function V(e){return await(await b()).prepare("SELECT 1 FROM reconciler_leases WHERE lane = ? AND key = ? AND expires_at > ?").get("warm-pool-mint",e,new Date().toISOString())!==void 0}n(V,"mintLeaseHeld");function ve(e){if(v())try{d({...e,model:null,situationalContext:null}).then($).catch(r=>console.error(`[warm-pool] recipe resolution failed: ${r.message}`))}catch(r){console.error(`[warm-pool] recipe resolution failed: ${r.message}`)}}n(ve,"refillWarmPool");async function $(e){if(await T())return;const{key:r}=e;if(await F(e.request.profileId)!==null)return;const a=await x("warm-pool",r);if(a!==void 0){if(await g(r)>0){await a();return}X(e,await K()).finally(()=>a().catch(()=>{}))}}n($,"mint");async function X({key:e,request:r},a){const t=await x("warm-pool-mint",a);if(t===void 0){console.error(`[warm-pool] mint refused for ${r.kind}: the mint lease of ${a} is held elsewhere`);return}try{await H({nodeId:a,kind:r.kind,mode:r.mode,cwd:r.cwd,prompt:"",root:!0,readiness:"await",profile:r.profileId},async o=>{await I(o,e)})}catch(o){console.error(`[warm-pool] mint failed for ${r.kind}: ${o.message}`)}finally{await t().catch(()=>{})}}n(X,"birthSpare");const Y=2;async function Se(){if(!v())return;let e;try{const r=new Set;e=[];for(const a of(await P({status:["active","idle"]})).reverse()){if(a.parent!==null||a.kind==="human")continue;const t=a.profile_id??null;if(!r.has(t??"")&&(r.add(t??""),e.push({cwd:a.cwd,profileId:t}),e.length>=Y))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($).catch(a=>console.error(`[warm-pool] prewarm failed for ${r.cwd}: ${a.message}`))}catch(a){console.error(`[warm-pool] prewarm failed for ${r.cwd}: ${a.message}`)}}n(Se,"prewarmRecentRecipes");export{X as birthSpare,ye as claimWarmNode,_e as emptyWarmPool,x as holdMintLease,Se as prewarmRecentRecipes,ge as reapStaleSpares,ve as refillWarmPool,he as resumeWarmClaim,v as warmPoolEnabled};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var y=Object.defineProperty;var r=(s,a)=>y(s,"name",{value:a,configurable:!0});import{prepared as o}from"../sqlite-statements.js";import{userStore as c}from"./paths.js";import{openScopedStore as u,scopedStoreExists as i,withScopedWrite as g}from"./db.js";function S(s){const a=c(s);if(!i(a))return null;const t=u(a),m=o(t,"SELECT profile_id, path FROM profile_projects ORDER BY profile_id, position").all(),E=o(t,"SELECT id, name, created_at, last_used_at, paused_at, default_kind, grantee, metadata_json, delivery_limits_json, environment_id FROM profiles ORDER BY rowid").all().map(e=>{const n=JSON.parse(e.metadata_json),f=JSON.parse(e.delivery_limits_json);return{profileId:e.id,manifest:{schema_version:1,name:e.name,projects:m.filter(_=>_.profile_id===e.id).map(_=>({path:_.path})),paused_at:e.paused_at,...e.default_kind===null?{}:{default_kind:e.default_kind},...e.grantee===null?{}:{grantee:e.grantee},...e.environment_id===null?{}:{environment_id:e.environment_id},...Object.keys(f).length===0?{}:{delivery_limits:f},...Object.keys(n).length===0?{}:{metadata:n},created_at:e.created_at,last_used_at:e.last_used_at}}}),k=Object.fromEntries(o(t,"SELECT directory, profile_id FROM profile_defaults").all().map(e=>[e.directory,e.profile_id])),p={};for(const e of o(t,"SELECT owner_key, raw_json FROM scope_settings WHERE owner_key != 'project'").all())p[e.owner_key]=JSON.parse(e.raw_json);const d={},l=r(e=>d[e]??={marketplaces:{},plugins:{},activeCanvas:null},"stateOf");for(const e of o(t,"SELECT owner_key, last_self_check, active_canvas FROM scope_bookkeeping WHERE owner_key != 'project'").all()){const n=l(e.owner_key);e.last_self_check!==null&&(n.last_self_check=e.last_self_check),n.activeCanvas=e.active_canvas}for(const e of o(t,"SELECT owner_key, name, last_updated FROM scope_marketplaces WHERE owner_key != 'project'").all())l(e.owner_key).marketplaces[e.name]=e.last_updated===null?{}:{last_updated:e.last_updated};for(const e of o(t,"SELECT owner_key, name, last_updated, etag, checked_at FROM scope_plugins WHERE owner_key != 'project'").all())l(e.owner_key).plugins[e.name]={...e.last_updated===null?{}:{last_updated:e.last_updated},...e.etag===null?{}:{etag:e.etag},...e.checked_at===null?{}:{checked_at:e.checked_at}};return{profiles:E,defaults:k,settings:p,state:d}}r(S,"readLegacyUserSnapshot");function v(s){const a=c(s);return i(a)?o(u(a),"SELECT profile_id, path, memory FROM legacy_project_caps ORDER BY profile_id, path").all().map(t=>({profileId:t.profile_id,path:t.path,memory:t.memory})):[]}r(v,"listLegacyProjectCaps");function w(s){const a=c(s);i(a)&&g(a,t=>{o(t,"DELETE FROM legacy_project_caps").run()})}r(w,"deleteLegacyProjectCaps");export{w as deleteLegacyProjectCaps,v as listLegacyProjectCaps,S as readLegacyUserSnapshot};
|
|
1
|
+
var y=Object.defineProperty;var r=(s,a)=>y(s,"name",{value:a,configurable:!0});import{prepared as o}from"../sqlite-statements.js";import{userStore as c}from"./paths.js";import{openScopedStore as u,scopedStoreExists as i,withScopedWrite as g}from"./db.js";function S(s){const a=c(s);if(!i(a))return null;const t=u(a),m=o(t,"SELECT profile_id, path FROM profile_projects ORDER BY profile_id, position").all(),E=o(t,"SELECT id, name, created_at, last_used_at, paused_at, default_kind, grantee, metadata_json, delivery_limits_json, environment_id FROM profiles ORDER BY rowid").all().map(e=>{const n=JSON.parse(e.metadata_json),f=JSON.parse(e.delivery_limits_json);return{profileId:e.id,manifest:{schema_version:1,name:e.name,projects:m.filter(_=>_.profile_id===e.id).map(_=>({path:_.path})),paused_at:e.paused_at,...e.default_kind===null?{}:{default_kind:e.default_kind},...e.grantee===null?{}:{grantee:e.grantee},...e.environment_id===null?{}:{environment_id:e.environment_id},...Object.keys(f).length===0?{}:{delivery_limits:f},...Object.keys(n).length===0?{}:{metadata:n},created_at:e.created_at,last_used_at:e.last_used_at}}}),k=Object.fromEntries(o(t,"SELECT directory, profile_id FROM profile_defaults").all().map(e=>[e.directory,e.profile_id])),p={};for(const e of o(t,"SELECT owner_key, raw_json FROM scope_settings WHERE owner_key != 'project'").all())p[e.owner_key]=JSON.parse(e.raw_json);const d={},l=r(e=>d[e]??={marketplaces:{},plugins:{},activeCanvas:null},"stateOf");for(const e of o(t,"SELECT owner_key, last_self_check, active_canvas FROM scope_bookkeeping WHERE owner_key != 'project'").all()){const n=l(e.owner_key);e.last_self_check!==null&&(n.last_self_check=e.last_self_check),n.activeCanvas=e.active_canvas}for(const e of o(t,"SELECT owner_key, name, last_updated FROM scope_marketplaces WHERE owner_key != 'project'").all())l(e.owner_key).marketplaces[e.name]=e.last_updated===null?{}:{last_updated:e.last_updated};for(const e of o(t,"SELECT owner_key, name, last_updated, etag, checked_at FROM scope_plugins WHERE owner_key != 'project'").all())l(e.owner_key).plugins[e.name]={...e.last_updated===null?{}:{last_updated:e.last_updated},...e.etag===null?{}:{etag:e.etag},...e.checked_at===null?{}:{checked_at:e.checked_at}};return{profiles:E,defaults:k,settings:p,state:d,apps:{}}}r(S,"readLegacyUserSnapshot");function v(s){const a=c(s);return i(a)?o(u(a),"SELECT profile_id, path, memory FROM legacy_project_caps ORDER BY profile_id, path").all().map(t=>({profileId:t.profile_id,path:t.path,memory:t.memory})):[]}r(v,"listLegacyProjectCaps");function w(s){const a=c(s);i(a)&&g(a,t=>{o(t,"DELETE FROM legacy_project_caps").run()})}r(w,"deleteLegacyProjectCaps");export{w as deleteLegacyProjectCaps,v as listLegacyProjectCaps,S as readLegacyUserSnapshot};
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { CanvasDb } from '../canvas/db.js';
|
|
2
|
+
export declare const APP_INSTALLS_MIGRATED_KEY = "app_installs_migrated";
|
|
3
|
+
export interface AppInstallMigrationReport {
|
|
4
|
+
moved: number;
|
|
5
|
+
discarded: number;
|
|
6
|
+
people: number;
|
|
7
|
+
alreadyDone: boolean;
|
|
8
|
+
}
|
|
9
|
+
/** Which of two owners' installs wins a name within one app: a profile over the user row; among profiles the most recently used, then the owner key.
|
|
10
|
+
* Negative when `a` wins. The startup migration and the import share it. */
|
|
11
|
+
export declare function compareInstallOwners(a: string, lastUsedA: string, b: string, lastUsedB: string): number;
|
|
12
|
+
/** Move every person's `user` and `profile:<id>` plugin and marketplace rows to `app:*` owner keys. Runs inside the caller's write transaction. */
|
|
13
|
+
export declare function migrateAppInstalls(db: CanvasDb): Promise<AppInstallMigrationReport>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var $=Object.defineProperty;var l=(n,p)=>$(n,"name",{value:p,configurable:!0});import{emitEvent as v}from"../events/emit.js";const N="app_installs_migrated";function M(n,p,_,c){return n==="user"!=(_==="user")?n==="user"?1:-1:p!==c?p<c?1:-1:n<_?-1:n>_?1:0}l(M,"compareInstallOwners");async function F(n){if(await n.prepare("SELECT pg_advisory_xact_lock(hashtext('app_installs_migrated'))").get(),await n.prepare("SELECT value FROM canvas_meta WHERE key = ?").get(N)!==void 0)return{moved:0,discarded:0,people:0,alreadyDone:!0};const p="(owner_key = 'user' OR owner_key LIKE 'profile:%')",_=await n.prepare(`SELECT person, owner_key, name, source_marketplace FROM scope_plugins WHERE ${p}`).all(),c=await n.prepare(`SELECT person, owner_key, name, url FROM scope_marketplaces WHERE ${p}`).all(),A=await n.prepare("SELECT person, id, grantee, last_used_at FROM profiles").all(),k=new Map(A.map(r=>[`${r.person}\0profile:${r.id}`,r])),w=l((r,a)=>a==="user"?"app:terminal":k.get(`${r}\0${a}`)?.grantee??"app:terminal","appOf"),y=l((r,a)=>k.get(`${r}\0${a}`)?.last_used_at??"","lastUsed"),f=l((r,a)=>M(r.owner_key,y(r.person,r.owner_key),a.owner_key,y(a.person,a.owner_key)),"order"),m=new Set;let g=0,T=0;const u=new Map;for(const r of _){const a=`${r.person}\0${w(r.person,r.owner_key)}`;u.set(a,[...u.get(a)??[],r])}for(const r of c){const a=`${r.person}\0${w(r.person,r.owner_key)}`;u.has(a)||u.set(a,[])}const O=l((r,a,o)=>c.find(s=>s.person===r&&s.owner_key===a&&s.name===o)?.url??null,"marketUrl");for(const[r,a]of[...u].sort(([o],[s])=>o<s?-1:1)){const[o,s]=r.split("\0"),R=new Set((await n.prepare("SELECT name FROM scope_plugins WHERE person = ? AND owner_key = ?").all(o,s)).map(e=>e.name)),E=new Map((await n.prepare("SELECT name, url FROM scope_marketplaces WHERE person = ? AND owner_key = ?").all(o,s)).map(e=>[e.name,e.url])),S=l(async(e,t)=>{const d=O(o,e,t);let i=t;for(let D=2;E.has(i)&&E.get(i)!==d;D+=1)i=`${t}-${D}`;return E.has(i)||(await n.prepare("UPDATE scope_marketplaces SET owner_key = ?, name = ? WHERE person = ? AND owner_key = ? AND name = ?").run(s,i,o,e,t),E.set(i,d)),i},"moveMarket");for(const e of[...a].sort(f)){if(R.has(e.name)){T+=1,v({level:"warn",event:"daemon.packages.install_migration",fields:{person:o,app:s,owner:e.owner_key,name:e.name,source:e.source_marketplace===null?null:O(o,e.owner_key,e.source_marketplace)}});continue}R.add(e.name);const t=e.source_marketplace===null?null:await S(e.owner_key,e.source_marketplace);await n.prepare("UPDATE scope_plugins SET owner_key = ?, source_marketplace = ? WHERE person = ? AND owner_key = ? AND name = ?").run(s,t,o,e.owner_key,e.name),g+=1,m.add(o)}const L=c.filter(e=>e.person===o&&w(o,e.owner_key)===s).sort((e,t)=>f({...e,source_marketplace:null},{...t,source_marketplace:null})||(e.name<t.name?-1:e.name>t.name?1:0));for(const e of L)await n.prepare("SELECT 1 AS one FROM scope_marketplaces WHERE person = ? AND owner_key = ? AND name = ?").get(o,e.owner_key,e.name)!==void 0&&(await S(e.owner_key,e.name),m.add(o))}await n.prepare(`DELETE FROM scope_plugins WHERE ${p}`).run(),await n.prepare(`DELETE FROM scope_marketplaces WHERE ${p}`).run();for(const r of m)await n.prepare("INSERT INTO person_settings (person, plugins_revision) VALUES (?, 1) ON CONFLICT (person) DO UPDATE SET plugins_revision = person_settings.plugins_revision + 1").run(r);return await n.prepare("INSERT INTO canvas_meta (key, value) VALUES (?, ?) ON CONFLICT (key) DO NOTHING").run(N,new Date().toISOString()),{moved:g,discarded:T,people:m.size,alreadyDone:!1}}l(F,"migrateAppInstalls");export{N as APP_INSTALLS_MIGRATED_KEY,M as compareInstallOwners,F as migrateAppInstalls};
|
|
@@ -1,6 +1,4 @@
|
|
|
1
|
-
var
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
ON CONFLICT (person, owner_key, name) DO UPDATE SET url = EXCLUDED.url, ref = EXCLUDED.ref, installed_at = EXCLUDED.installed_at`).run(t,n.owner,d,c.url??null,c.ref??null,c.installed_at??null)}else if(n.op==="state.write"){await a.prepare(`INSERT INTO scope_bookkeeping (person, owner_key, last_self_check, active_canvas) VALUES (?, ?, ?, ?)
|
|
6
|
-
ON CONFLICT (person, owner_key) DO UPDATE SET last_self_check = EXCLUDED.last_self_check, active_canvas = EXCLUDED.active_canvas`).run(t,n.owner,n.state.last_self_check??null,n.state.activeCanvas??null);for(const[r,i]of Object.entries(n.state.marketplaces))await a.prepare("UPDATE scope_marketplaces SET last_updated = ? WHERE person = ? AND owner_key = ? AND name = ?").run(i.last_updated??null,t,n.owner,r);for(const[r,i]of Object.entries(n.state.plugins))await a.prepare("UPDATE scope_plugins SET last_updated = ?, etag = ?, checked_at = ? WHERE person = ? AND owner_key = ? AND name = ?").run(i.last_updated??null,i.etag??null,i.checked_at??null,t,n.owner,r)}else if(n.op==="profile.insert"){const r=n.profile.manifest;await a.prepare("INSERT INTO profiles (id, person, name, created_at, last_used_at, paused_at, default_kind, grantee, metadata_json, delivery_limits_json, environment_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(n.profile.profileId,t,r.name,r.created_at,r.last_used_at,r.paused_at,r.default_kind??null,r.grantee??null,JSON.stringify(r.metadata??{}),JSON.stringify(r.delivery_limits??{}),r.environment_id??null),await k(a,n.profile)}else if(n.op==="profile.update"){const r=n.profile.manifest;if((await a.prepare("UPDATE profiles SET name = ?, last_used_at = ?, paused_at = ?, default_kind = ?, grantee = ?, metadata_json = ?, delivery_limits_json = ?, environment_id = ? WHERE id = ? AND person = ?").run(r.name,r.last_used_at,r.paused_at,r.default_kind??null,r.grantee??null,JSON.stringify(r.metadata??{}),JSON.stringify(r.delivery_limits??{}),r.environment_id??null,n.profile.profileId,t)).changes!==1)throw new Error(`no stored profile ${n.profile.profileId}`);await k(a,n.profile)}else if(n.op==="profile.delete"){const r=`profile:${n.profileId}`;for(const i of["scope_settings","scope_bookkeeping","scope_marketplaces","scope_plugins"])await a.prepare(`DELETE FROM ${i} WHERE person = ? AND owner_key = ?`).run(t,r);await a.prepare("DELETE FROM profiles WHERE id = ? AND person = ?").run(n.profileId,t)}else{await a.prepare("DELETE FROM profile_defaults WHERE person = ?").run(t);for(const[r,i]of Object.entries(n.defaults))await a.prepare("INSERT INTO profile_defaults (person, directory, profile_id) VALUES (?, ?, ?)").run(t,r,i)}u&&await a.prepare("INSERT INTO person_settings (person, plugins_revision) VALUES (?, 1) ON CONFLICT (person) DO UPDATE SET plugins_revision = person_settings.plugins_revision + 1").run(t),await a.prepare("SELECT pg_notify('crtr_signal', ?)").get(`settings:${t}`)}_(U,"applyOpsToRows");async function k(a,t){await a.prepare("DELETE FROM profile_projects WHERE profile_id = ?").run(t.profileId);let o=0;for(const u of t.manifest.projects)await a.prepare("INSERT INTO profile_projects (profile_id, path, position) VALUES (?, ?, ?)").run(t.profileId,u.path,o++)}_(k,"replaceProjects");const F=_(async(a,t)=>(await N(o=>U(o,a,t)),await g(a)),"rowsTransport");h(F),C(g);export{U as applyOpsToRows,g as loadPersonSettings,w as readSnapshotFromRows,F as rowsTransport};
|
|
1
|
+
var R=Object.defineProperty;var p=(t,a)=>R(t,"name",{value:a,configurable:!0});import{openDb as v,withCanvasWrite as D}from"../canvas/db.js";import{appRevisionOf as w,revisionOf as L,setPersonSnapshot as h,setSettingsReloader as C,setSettingsTransport as j,SettingsRevisionConflictError as S}from"./person-store.js";const s=p(t=>typeof t=="string"?t:void 0,"s");async function O(t,a){const o=await t.prepare("SELECT * FROM profiles WHERE person = ? AND deleting_since IS NULL ORDER BY created_at, id").all(a),c=await t.prepare("SELECT p.profile_id, p.path FROM profile_projects p JOIN profiles f ON f.id = p.profile_id WHERE f.person = ? ORDER BY p.profile_id, p.position").all(a),n=new Map;for(const e of c)(n.get(e.profile_id)??n.set(e.profile_id,[]).get(e.profile_id)).push({path:e.path});const r=o.map(e=>{const l=JSON.parse(String(e.metadata_json)),_=JSON.parse(String(e.delivery_limits_json));return{profileId:String(e.id),manifest:{schema_version:1,name:String(e.name),projects:n.get(String(e.id))??[],paused_at:s(e.paused_at)??null,...s(e.default_kind)===void 0?{}:{default_kind:s(e.default_kind)},...s(e.grantee)===void 0?{}:{grantee:s(e.grantee)},...s(e.environment_id)===void 0?{}:{environment_id:s(e.environment_id)},...Object.keys(_).length===0?{}:{delivery_limits:_},...Object.keys(l).length===0?{}:{metadata:l},created_at:String(e.created_at),last_used_at:s(e.last_used_at)??null}}}),i=Object.fromEntries((await t.prepare("SELECT directory, profile_id FROM profile_defaults WHERE person = ?").all(a)).map(e=>[e.directory,e.profile_id])),f={};for(const e of await t.prepare("SELECT owner_key, raw_json FROM scope_settings WHERE person = ?").all(a))f[e.owner_key]=JSON.parse(e.raw_json);const E={},u={},d=p(e=>u[e]??={plugins:{},marketplaces:{},revision:""},"appOf"),m=p(e=>E[e]??={marketplaces:{},plugins:{},activeCanvas:null},"stateOf");for(const e of await t.prepare("SELECT owner_key, last_self_check, active_canvas FROM scope_bookkeeping WHERE person = ?").all(a)){const l=m(e.owner_key);e.last_self_check!==null&&(l.last_self_check=e.last_self_check),l.activeCanvas=e.active_canvas}for(const e of await t.prepare("SELECT * FROM scope_marketplaces WHERE person = ? ORDER BY owner_key, name").all(a)){const l=String(e.owner_key),_=String(e.name);if(l.startsWith("app:")){d(l).marketplaces[_]={url:s(e.url),ref:s(e.ref)??"",installed_at:s(e.installed_at)??""};continue}if(m(l).marketplaces[_]=s(e.last_updated)===void 0?{}:{last_updated:s(e.last_updated)},s(e.url)!==void 0){const g=f[l]??={},k=g.marketplaces??={};k[_]={url:s(e.url),ref:s(e.ref)??"",installed_at:s(e.installed_at)??""}}}for(const e of await t.prepare("SELECT * FROM scope_plugins WHERE person = ? ORDER BY owner_key, name").all(a)){const l=String(e.owner_key),_=String(e.name);if(l.startsWith("app:")){d(l).plugins[_]={enabled:Number(e.enabled)===1,...s(e.source_marketplace)===void 0?{}:{source_marketplace:s(e.source_marketplace)},...s(e.version)===void 0?{}:{version:s(e.version)}};continue}m(l).plugins[_]={...s(e.last_updated)===void 0?{}:{last_updated:s(e.last_updated)},...s(e.etag)===void 0?{}:{etag:s(e.etag)},...s(e.checked_at)===void 0?{}:{checked_at:s(e.checked_at)}};const g=f[l]??={},k=g.plugins??={};k[_]={enabled:Number(e.enabled)===1,...s(e.source_marketplace)===void 0?{}:{source_marketplace:s(e.source_marketplace)},...s(e.version)===void 0?{}:{version:s(e.version)}}}for(const e of Object.values(u))e.revision=w(e);return{profiles:r,defaults:i,settings:f,state:E,apps:u}}p(O,"readSnapshotFromRows");async function N(t){const a=await v(),o=await O(a,t);return h(t,o),o}p(N,"loadPersonSettings");async function I(t,a,o){return(await O(t,a)).settings[o]}p(I,"currentRaw");async function A(t,a,o){let c=!1;for(const n of o)if(n.op==="settings.replace"){const r=await I(t,a,n.owner);if(n.ifRevision!==L(r))throw new S;const{plugins:i,marketplaces:f,...E}=n.raw,u=JSON.stringify(E);await t.prepare("INSERT INTO scope_settings (person, owner_key, raw_json) VALUES (?, ?, ?) ON CONFLICT (person, owner_key) DO UPDATE SET raw_json = EXCLUDED.raw_json").run(a,n.owner,u);const d=JSON.stringify([r?.plugins,r?.marketplaces]);d!==JSON.stringify([i,f])&&!(d==="[null,null]"&&i===void 0&&f===void 0)&&(c=!0),await T(t,a,n.owner,i??{},f??{})}else if(n.op==="app-plugins.replace"){await t.prepare("SELECT pg_advisory_xact_lock(hashtext(?))").get(`app-plugins|${a}|${n.app}`);const r=(await O(t,a)).apps[n.app];if(n.ifRevision!==w(r))throw new S;w(n)!==w(r)&&(c=!0),await T(t,a,n.app,n.plugins,n.marketplaces)}else if(n.op==="state.write"){await t.prepare(`INSERT INTO scope_bookkeeping (person, owner_key, last_self_check, active_canvas) VALUES (?, ?, ?, ?)
|
|
2
|
+
ON CONFLICT (person, owner_key) DO UPDATE SET last_self_check = EXCLUDED.last_self_check, active_canvas = EXCLUDED.active_canvas`).run(a,n.owner,n.state.last_self_check??null,n.state.activeCanvas??null);for(const[r,i]of Object.entries(n.state.marketplaces))await t.prepare("UPDATE scope_marketplaces SET last_updated = ? WHERE person = ? AND owner_key = ? AND name = ?").run(i.last_updated??null,a,n.owner,r);for(const[r,i]of Object.entries(n.state.plugins))await t.prepare("UPDATE scope_plugins SET last_updated = ?, etag = ?, checked_at = ? WHERE person = ? AND owner_key = ? AND name = ?").run(i.last_updated??null,i.etag??null,i.checked_at??null,a,n.owner,r)}else if(n.op==="profile.insert"){const r=n.profile.manifest;await t.prepare("INSERT INTO profiles (id, person, name, created_at, last_used_at, paused_at, default_kind, grantee, metadata_json, delivery_limits_json, environment_id) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)").run(n.profile.profileId,a,r.name,r.created_at,r.last_used_at,r.paused_at,r.default_kind??null,r.grantee??null,JSON.stringify(r.metadata??{}),JSON.stringify(r.delivery_limits??{}),r.environment_id??null),await y(t,n.profile)}else if(n.op==="profile.update"){const r=n.profile.manifest;if((await t.prepare("UPDATE profiles SET name = ?, last_used_at = ?, paused_at = ?, default_kind = ?, grantee = ?, metadata_json = ?, delivery_limits_json = ?, environment_id = ? WHERE id = ? AND person = ?").run(r.name,r.last_used_at,r.paused_at,r.default_kind??null,r.grantee??null,JSON.stringify(r.metadata??{}),JSON.stringify(r.delivery_limits??{}),r.environment_id??null,n.profile.profileId,a)).changes!==1)throw new Error(`no stored profile ${n.profile.profileId}`);await y(t,n.profile)}else if(n.op==="profile.delete"){const r=`profile:${n.profileId}`;for(const i of["scope_settings","scope_bookkeeping","scope_marketplaces","scope_plugins"])await t.prepare(`DELETE FROM ${i} WHERE person = ? AND owner_key = ?`).run(a,r);await t.prepare("DELETE FROM profiles WHERE id = ? AND person = ?").run(n.profileId,a)}else{await t.prepare("DELETE FROM profile_defaults WHERE person = ?").run(a);for(const[r,i]of Object.entries(n.defaults))await t.prepare("INSERT INTO profile_defaults (person, directory, profile_id) VALUES (?, ?, ?)").run(a,r,i)}c&&await t.prepare("INSERT INTO person_settings (person, plugins_revision) VALUES (?, 1) ON CONFLICT (person) DO UPDATE SET plugins_revision = person_settings.plugins_revision + 1").run(a),await t.prepare("SELECT pg_notify('crtr_signal', ?)").get(`settings:${a}`)}p(A,"applyOpsToRows");async function T(t,a,o,c,n){await t.prepare("DELETE FROM scope_plugins WHERE person = ? AND owner_key = ? AND NOT (name IN (SELECT jsonb_array_elements_text(?::jsonb)))").run(a,o,JSON.stringify(Object.keys(c)));for(const[r,i]of Object.entries(c))await t.prepare(`INSERT INTO scope_plugins (person, owner_key, name, enabled, source_marketplace, version) VALUES (?, ?, ?, ?, ?, ?)
|
|
3
|
+
ON CONFLICT (person, owner_key, name) DO UPDATE SET enabled = EXCLUDED.enabled, source_marketplace = EXCLUDED.source_marketplace, version = EXCLUDED.version`).run(a,o,r,i.enabled===!1?0:1,i.source_marketplace??null,i.version??null);await t.prepare("DELETE FROM scope_marketplaces WHERE person = ? AND owner_key = ? AND NOT (name IN (SELECT jsonb_array_elements_text(?::jsonb)))").run(a,o,JSON.stringify(Object.keys(n)));for(const[r,i]of Object.entries(n))await t.prepare(`INSERT INTO scope_marketplaces (person, owner_key, name, url, ref, installed_at) VALUES (?, ?, ?, ?, ?, ?)
|
|
4
|
+
ON CONFLICT (person, owner_key, name) DO UPDATE SET url = EXCLUDED.url, ref = EXCLUDED.ref, installed_at = EXCLUDED.installed_at`).run(a,o,r,i.url??null,i.ref??null,i.installed_at??null)}p(T,"writeInstallRows");async function y(t,a){await t.prepare("DELETE FROM profile_projects WHERE profile_id = ?").run(a.profileId);let o=0;for(const c of a.manifest.projects)await t.prepare("INSERT INTO profile_projects (profile_id, path, position) VALUES (?, ?, ?)").run(a.profileId,c.path,o++)}p(y,"replaceProjects");const U=p(async(t,a)=>(await D(o=>A(o,t,a)),await N(t)),"rowsTransport");j(U),C(N);export{A as applyOpsToRows,N as loadPersonSettings,O as readSnapshotFromRows,U as rowsTransport};
|
|
@@ -10,12 +10,33 @@ export interface PersonSnapshot {
|
|
|
10
10
|
defaults: Record<string, string>;
|
|
11
11
|
settings: Record<string, Record<string, unknown>>;
|
|
12
12
|
state: Record<string, ScopeState>;
|
|
13
|
+
/** App installs (`app:<id>` → plugins, marketplaces) with a revision covering only that app's block. Cloud roles write plugins here, never to `settings`. */
|
|
14
|
+
apps: Record<string, AppInstallBlock>;
|
|
15
|
+
}
|
|
16
|
+
export interface AppInstallBlock {
|
|
17
|
+
plugins: Record<string, {
|
|
18
|
+
enabled?: boolean;
|
|
19
|
+
source_marketplace?: string;
|
|
20
|
+
version?: string;
|
|
21
|
+
}>;
|
|
22
|
+
marketplaces: Record<string, {
|
|
23
|
+
url?: string;
|
|
24
|
+
ref?: string;
|
|
25
|
+
installed_at?: string;
|
|
26
|
+
}>;
|
|
27
|
+
revision: string;
|
|
13
28
|
}
|
|
14
29
|
export type SettingsOp = {
|
|
15
30
|
op: 'settings.replace';
|
|
16
31
|
owner: string;
|
|
17
32
|
raw: Record<string, unknown>;
|
|
18
33
|
ifRevision: string;
|
|
34
|
+
} | {
|
|
35
|
+
op: 'app-plugins.replace';
|
|
36
|
+
app: string;
|
|
37
|
+
plugins: AppInstallBlock['plugins'];
|
|
38
|
+
marketplaces: AppInstallBlock['marketplaces'];
|
|
39
|
+
ifRevision: string;
|
|
19
40
|
} | {
|
|
20
41
|
op: 'state.write';
|
|
21
42
|
owner: string;
|
|
@@ -40,6 +61,8 @@ export declare class PersonSettingsNotLoadedError extends Error {
|
|
|
40
61
|
constructor(person: string);
|
|
41
62
|
}
|
|
42
63
|
declare const BLOCKS: readonly ["plugins", "marketplaces"];
|
|
64
|
+
/** The revision of an app's install block; `absent` for an app with no rows. */
|
|
65
|
+
export declare function appRevisionOf(block: Pick<AppInstallBlock, 'plugins' | 'marketplaces'> | undefined): string;
|
|
43
66
|
export declare function revisionOf(raw: Record<string, unknown> | undefined): string;
|
|
44
67
|
export declare function installPersonSnapshot(person: string, snapshot: PersonSnapshot): void;
|
|
45
68
|
export declare function heldPersons(): string[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var h=Object.defineProperty;var n=(e,t)=>h(e,"name",{value:t,configurable:!0});import{createHash as x}from"node:crypto";import{PersonOutsideRequestError as g,PersonUnresolvedError as S,personId as u}from"../canvas/person-state.js";class m extends Error{static{n(this,"SettingsRevisionConflictError")}constructor(){super("settings changed since the supplied revision"),this.name="SettingsRevisionConflictError"}}class w extends Error{static{n(this,"PersonSettingsNotLoadedError")}constructor(t){super(`settings for ${t} are not loaded in this process`),this.name="PersonSettingsNotLoadedError"}}const P=["plugins","marketplaces"],o=new Map;function O(e){return e===void 0?"absent":p({plugins:e.plugins,marketplaces:e.marketplaces})}n(O,"appRevisionOf");function p(e){return e===void 0?"absent":x("sha256").update(JSON.stringify(e)).digest("hex")}n(p,"revisionOf");function R(e,t){o.set(e,t)}n(R,"installPersonSnapshot");function I(){return[...o.keys()]}n(I,"heldPersons");function L(){o.clear()}n(L,"dropPersonSnapshots");const f=n(()=>({profiles:[],defaults:{},settings:{},state:{},apps:{}}),"emptySnapshot");let a;function N(e){a=e}n(N,"installPreludeSnapshot");function r(){let e;try{e=u()}catch(s){if(s instanceof g)return f();if(s instanceof S)return a??f();throw s}const t=o.get(e);if(t!==void 0)return t;if(a!==void 0)return a;throw new w(e)}n(r,"currentSnapshot");function T(){try{return o.has(u())}catch{return!1}}n(T,"personHasSnapshot");let d=n(async()=>{throw new Error("no settings transport installed in this process")},"transport");function _(e){d=e}n(_,"setSettingsTransport");async function k(e){const t=u();for(let s=0;;s++){const c=e(r());if(c.length===0)return r();try{const i=await d(t,c);return o.set(t,i),i}catch(i){if(!(i instanceof m)||s>=2)throw i;await C(t)}}}n(k,"writeSettings");function K(e,t){o.set(e,t),a=void 0}n(K,"setPersonSnapshot");let l;function B(e){l=e}n(B,"setSettingsReloader");async function C(e){o.set(e,await(l??(async()=>{throw new Error("no settings reloader installed in this process")}))(e))}n(C,"reloadViaTransport");function H(e){return e===void 0?"user":`profile:${e}`}n(H,"ownerKeyOf");function $(e){const t=r().settings[e];return{settings:t===void 0?null:structuredClone(t),revision:p(t)}}n($,"readCachedSettings");function q(e){const t=r().state[e];return t===void 0?{marketplaces:{},plugins:{},activeCanvas:null}:structuredClone(t)}n(q,"readCachedState");function D(){return structuredClone(r().profiles)}n(D,"listCachedProfiles");function G(e){const t=r().profiles.find(s=>s.profileId===e);return t===void 0?null:structuredClone(t)}n(G,"getCachedProfile");function J(e){return r().profiles.find(t=>t.profileId===e)?.manifest.paused_at!=null}n(J,"cachedProfilePaused");function M(){return new Set(r().profiles.filter(e=>e.manifest.paused_at!==null).map(e=>e.profileId))}n(M,"cachedPausedProfileIds");function U(){return{...r().defaults}}n(U,"cachedDefaults");export{w as PersonSettingsNotLoadedError,P as SETTINGS_ROW_BLOCKS,m as SettingsRevisionConflictError,O as appRevisionOf,U as cachedDefaults,M as cachedPausedProfileIds,J as cachedProfilePaused,r as currentSnapshot,L as dropPersonSnapshots,G as getCachedProfile,I as heldPersons,R as installPersonSnapshot,N as installPreludeSnapshot,D as listCachedProfiles,H as ownerKeyOf,T as personHasSnapshot,$ as readCachedSettings,q as readCachedState,p as revisionOf,K as setPersonSnapshot,B as setSettingsReloader,_ as setSettingsTransport,k as writeSettings};
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
var j=Object.defineProperty;var
|
|
1
|
+
var j=Object.defineProperty;var a=(r,e)=>j(r,"name",{value:e,configurable:!0});import{WebSocketServer as K}from"ws";import{isSafeNodeId as N,viewSocketPath as Q}from"../../core/canvas/paths.js";import{getNode as T}from"../../core/canvas/index.js";import{requestPersonId as z,runAsPerson as G}from"../../core/canvas/person-state.js";import{BROKER_READ_CAPS as X,CLIENT_READ_CAPS as Y,FrameDecoder as Z,FrameOverflowError as I}from"../../core/runtime/broker-protocol.js";import{emitEvent as A}from"../../core/events/emit.js";import{classify as R}from"../../core/fault-classifier.js";import{clearFault as g,markNodeRead as ee,recordFault as $}from"../../core/canvas/recovery.js";import{decideAttachRevive as re}from"../../core/runtime/revive.js";import{connectViewSocket as te,connectWssView as ne,probeViewSocket as ae,waitForBrokerViewSocket as ie,waitForWssView as P}from"../../core/runtime/view-socket.js";import{liveExecutionForNode as oe,recordExecutionAwake as ce}from"../../core/canvas/executions.js";import{settleSandboxBeforeWake as se}from"../reconcilers/ledger-sandbox.js";import{runnerForExecution as le}from"../../core/runtime/runner/index.js";import{isBeneathRefusal as fe}from"../../core/spaces/open-beneath.js";import{openMachineView as ue,probeMachineView as me,waitForMachineView as de}from"../machine-link/forward.js";import{attachViewer as F,detachViewer as he,holdViewerForRedial as we,presentViewer as pe}from"./viewer-presence.js";const ye=3e4,ve=new K({noServer:!0,maxPayload:X.maxLineBytes}),ke=25e3,ge=6e4;function be(r,e=ke,s=ge){let n=!0,h=!1,u=Date.now();const l=a(()=>{n=!0},"acknowledge"),i=a(()=>{h||(h=!0,clearInterval(o),r.off("pong",l))},"stop");r.on("pong",l);const o=setInterval(()=>{if(Date.now()-u>s){n=!0;return}if(!n){i(),r.terminate();return}n=!1;try{r.ping()}catch{i(),r.terminate()}},e);return o.unref(),{stop:i,noteActivity:a(()=>{u=Date.now()},"noteActivity")}}a(be,"startRemoteAttachHeartbeat");function C(r){const e=Buffer.from(r,"utf8");return e.byteLength<=123?r:e.subarray(0,123).toString("utf8")}a(C,"clampReason");function y(r,e,s,n,h){const u=JSON.stringify({error:{code:n,message:h,origin:"runtime"}}),l=`HTTP/1.1 ${e} ${s}\r
|
|
2
2
|
content-type: application/json; charset=utf-8\r
|
|
3
3
|
content-length: ${Buffer.byteLength(u)}\r
|
|
4
4
|
connection: close\r
|
|
5
5
|
\r
|
|
6
|
-
`+u;try{r.end(l)}catch{try{r.destroy()}catch{}}}
|
|
6
|
+
`+u;try{r.end(l)}catch{try{r.destroy()}catch{}}}a(y,"refuseUpgrade");function _e(r){if(new URL(r.url??"/","http://127.0.0.1").searchParams.get("revive")==="0")return!0;const s=r.headers["x-crtr-attach-revive"];return(Array.isArray(s)?s[0]:s)==="0"}a(_e,"reviveOptedOut");function Ae(r){return new URL(r.url??"/","http://127.0.0.1").searchParams.get("wakeParked")==="1"}a(Ae,"wakeParkedRequested");function O(r){return r===1e3||r===1001||r===1005}a(O,"isCleanViewerClose");function w(r,e,s){s.catch(n=>A({level:"error",event:e,node_id:r,error:n}))}a(w,"detach");async function D(r){const e=await oe(r);return e===null||e.runner==="process"?{kind:"unix",path:Q(r)}:(e.runner==="blaxel"&&e.idleAt!==null&&(await se(e.executionId,Date.now()),await ce(e.executionId)),le(e.runner).viewerAddress(e))}a(D,"brokerViewAddress");function Ee(r,e){return e.kind==="machine"?ue(e.environmentId,r):e.kind==="wss"?ne(e.url,e.headers):te(r)}a(Ee,"connectBrokerView");function Se(r,e,s){return e.kind==="machine"?me(e.environmentId,r,s):e.kind==="wss"?P(e.url,e.headers,void 0,s):ae(r,s)}a(Se,"probeBrokerView");async function xe(r,e,s,n){const h=[];let u=a(t=>{h.push(t)},"relayMessage");if(r.on("message",t=>u(t)),!N(e)){try{r.close(1008,C(`invalid node id: ${e}`))}catch{}return}if(await T(e)===null){try{r.close(1011,C(`no node ${e}`))}catch{}return}await g(e,{link:"viewer\u2194crtrd"});const l=Ee(e,s),i=new Z(Y);let o=!1,v=!1,d,b=!1,V=!1,E="controller",B=Promise.resolve(),_=!1;const S=[];let x=!1;l.on("connect",()=>{b=!0,!o&&_&&w(e,"daemon.bridge.presence_failed",F(e,r)),w(e,"daemon.bridge.connect_failed",g(e,{link:"relay\u2194broker"}))});const p=a((t,f,c=!1)=>{if(!o){if(o=!0,w(e,"daemon.bridge.presence_failed",c?we(e,r):he(e,r)),d?.stop(),!l.destroyed)try{l.destroy()}catch{}try{r.close(t,C(f))}catch{}}},"teardown");d=be(r);const W=a(async t=>{d?.noteActivity();let f;try{f=i.push(t)}catch(c){const m=c instanceof I?`broker sent an oversized frame (${c.message})`:`failed to decode a broker frame for ${e}`;p(1009,m);return}S.push(...f),x||await M()},"onData"),M=a(async()=>{x=!0;try{for(;S.length>0&&!o;){const t=S.splice(0);let f;try{f=await n(E)}catch(m){A({level:"error",event:"daemon.bridge.attach_recheck_failed",node_id:e,error:m}),p(1011,"revoked");return}if(o)return;if(!f){p(1008,"revoked");return}let c=!1;for(const m of t)r.readyState===r.OPEN&&(r.send(JSON.stringify(m)),m?.type==="welcome"&&(c=!0));if(_&&c)try{await pe(e,r)&&await ee(e)}catch(m){A({level:"warn",event:"daemon.bridge.present_failed",node_id:e,error:m})}}}finally{x=!1}},"drainOutbound");l.on("data",t=>w(e,"daemon.bridge.data_failed",W(t)));const U=a(async t=>{const f=R("relay\u2194broker",t);await $(e,{link:"relay\u2194broker",op:"bridge socket",kind:f.kind,retry:{disposition:"manual"},message:t.message});const c=t.code==="ECONNREFUSED"||t.code==="ENOENT"?`no running broker for ${e}`:`view socket error for ${e}: ${t.message}`;p(1011,c,!0)},"onSocketError");l.on("error",t=>w(e,"daemon.bridge.socket_error_failed",U(t)));const H=a(async t=>{o||t||(await g(e,{link:"relay\u2194broker"}),p(1e3,"broker socket closed",!0))},"onSocketClose");l.on("close",t=>w(e,"daemon.bridge.socket_close_failed",H(t)));const L=a(async(t,f)=>{const c=f.toString("utf8");if(o){O(t)&&await g(e,{link:"viewer\u2194crtrd"});return}if(O(t))await g(e,{link:"viewer\u2194crtrd"});else if(!v){v=!0;const m=R("viewer\u2194crtrd",{code:t,reason:c});await $(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:m.kind,retry:{disposition:"auto"},message:c||`remote attach closed (${t})`})}p(t,c||`remote attach closed (${t})`)},"onWsClose");r.on("close",(t,f)=>w(e,"daemon.bridge.ws_close_failed",L(t,f)));const J=a(async()=>{if(!v){v=!0;const t=R("viewer\u2194crtrd",{code:1006,reason:"remote attach websocket error"});await $(e,{link:"viewer\u2194crtrd",op:"remote attach websocket",kind:t.kind,retry:{disposition:"auto"},message:"remote attach websocket error"})}p(1011,"remote attach websocket error")},"onWsError");r.on("error",()=>w(e,"daemon.bridge.ws_error_failed",J())),u=a(t=>{if(o||l.destroyed)return;d?.noteActivity();const c=(Array.isArray(t)?Buffer.concat(t):Buffer.isBuffer(t)?t:Buffer.from(new Uint8Array(t))).toString("utf8");if(!V)try{const k=JSON.parse(c);k?.type==="hello"&&(V=!0,E=k.role==="observer"?"observer":"controller",_=k.attends!==!1,_&&b&&w(e,"daemon.bridge.presence_failed",F(e,r)))}catch{}const m=c.endsWith(`
|
|
7
7
|
`)?c:c+`
|
|
8
|
-
`,q=
|
|
8
|
+
`,q=a(()=>{try{l.write(m)}catch{}},"write");B=B.then(async()=>{o||(await n(E)?q():p(1008,"revoked"))}).catch(k=>{A({level:"error",event:"daemon.bridge.attach_recheck_failed",node_id:e,error:k}),p(1011,"revoked")})},"relayMessage");for(const t of h.splice(0))u(t)}a(xe,"bridgeConnection");async function qe(r,e,s,n,h){const u=z(),l=u===void 0?h:i=>G(u,()=>h(i));e.on("error",()=>{});try{if(!N(n)){y(e,400,"Bad Request","invalid_node_id",`invalid node id: ${n}`);return}if(await T(n)===null){y(e,404,"Not Found","node_not_found",`no node ${n}`);return}let i;if(_e(r)){if(i=await D(n),!await Se(n,i,250)){y(e,409,"Conflict","node_dormant",`node ${n} is dormant and revive was opted out (?revive=0)`);return}}else{let o;try{const d=await re(n,{resume:!0,capacity:"refuse"},Ae(r));if(d.parked){y(e,409,"Conflict","node_dormant",`node ${n} is parked; attach with ?wakeParked=1 to wake it`);return}o=d.result.launch?.exited}catch(d){const b=d instanceof Error?d.message:String(d);y(e,409,"Conflict","attach_revive_failed",`attach revive failed: ${b}`);return}if(i=await D(n),!(i.kind==="machine"?await de(i.environmentId,n,o,ye):i.kind==="wss"?await P(i.url,i.headers,o):await ie(n,o))){y(e,409,"Conflict","broker_not_ready",`broker view socket for ${n} did not become listenable after revive`);return}}if(e.destroyed)return;ve.handleUpgrade(r,e,s,o=>w(n,"daemon.bridge.connection_failed",xe(o,n,i,l)))}catch(i){const o=i instanceof Error?i.message:String(i);if(fe(i)){y(e,400,"Bad Request","invalid_request",o);return}y(e,500,"Internal Server Error","internal",`attach upgrade failed: ${o}`)}}a(qe,"handleAttachUpgrade");export{ke as REMOTE_ATTACH_HEARTBEAT_MS,ge as REMOTE_ATTACH_QUIET_MS,qe as handleAttachUpgrade,O as isCleanViewerClose,y as refuseUpgrade,be as startRemoteAttachHeartbeat};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var f=Object.defineProperty;var
|
|
2
|
-
WHERE person = ? AND enabled = 1 AND owner_key
|
|
1
|
+
var f=Object.defineProperty;var u=(o,e)=>f(o,"name",{value:e,configurable:!0});import{ApiError as a}from"../../../api/errors.js";import{getNode as w}from"../../../core/canvas/canvas.js";import{openDb as l}from"../../../core/canvas/db.js";import{blobStore as h}from"../../../core/blobs/index.js";import{presignGet as E,releaseSignerFromEnv as b}from"../../../core/secrets/blaxel-launch.js";import{grantedProviderIds as g,isProviderBundleRow as k}from"../../../core/grants/mirror.js";import{profileMetadataEnv as x}from"../../../core/runtime/spawn-env.js";import{localEnvironmentSecrets as v}from"../../../core/secrets/environment-owner.js";import{environmentOfNode as y,recipeOf as R}from"../environment-of.js";import{mintInstallationToken as S}from"./git-credential.js";async function O(o,e){const n=await l(),s=new Map((await n.prepare(`SELECT owner_key, name, version, source_marketplace, source_path FROM scope_plugins
|
|
2
|
+
WHERE person = ? AND enabled = 1 AND owner_key = ? ORDER BY name`).all(o,e)).map(i=>[i.name,i])),t=[],r=await g(o);for(const i of s.values()){if(k(i,r))continue;if(i.source_path!==null){t.push({name:i.name,source:{path:i.source_path},version:i.version});continue}if(i.source_marketplace===null)throw new a(500,"plugin_source_missing",`plugin ${i.name} names neither a marketplace nor a path`);const c=await n.prepare("SELECT url, ref FROM scope_marketplaces WHERE person = ? AND owner_key = ? AND name = ?").get(o,i.owner_key,i.source_marketplace);t.push({name:i.name,source:{marketplace:{url:c?.url??null,ref:c?.ref??null}},version:i.version})}return t}u(O,"plugins");const T=900;async function $(o){const e=await l(),n=await e.prepare("SELECT blob_key, unpacked_at FROM import_node_files WHERE node = ?").get(o);if(n===void 0)return null;if(!(await(await h()).list(n.blob_key)).includes(n.blob_key)){if(n.unpacked_at!==null)return null;throw new a(500,"import_files_missing",`the imported archive ${n.blob_key} of ${o} is gone and no sandbox unpacked it`)}const s=/^imports\/([^/]+)\/node-files\//.exec(n.blob_key)?.[1];if(s===void 0)throw new a(500,"import_files_invalid",`import_node_files names ${n.blob_key} for ${o}, which is no imports/<run>/node-files key`);const t=await e.prepare("SELECT source_value, target_value FROM import_id_map WHERE run_id = ? AND kind = 'path' ORDER BY source_value").all(s);return{url:E(b(),n.blob_key,T),path_map:t.map(r=>({from:r.source_value,to:r.target_value}))}}u($,"importFiles");async function N(o){const{principal:e}=o;if(e.class!=="broker")throw new a(403,"broker_only","this route is called with a node token");const n=o.params.execution_id??"",t=await(await l()).prepare("SELECT node_id, state FROM executions WHERE execution_id = ?").get(n);if(t===void 0||t.node_id!==e.node)throw new a(403,"not_your_execution",`execution ${n} is not an execution of this node`);if(t.state!=="launching"&&t.state!=="running")throw new a(403,"execution_ended",`execution ${n} is ${t.state}`);return e.node}u(N,"ownedExecution");async function D(o){const e=await N(o);return await(await l()).prepare("UPDATE import_node_files SET unpacked_at = ? WHERE node = ? AND unpacked_at IS NULL").run(new Date().toISOString(),e),{status:200,body:{}}}u(D,"handleImportUnpacked");async function L(o){const{principal:e}=o;if(e.class!=="broker")throw new a(403,"broker_only","the start bundle is read with a node token");const n=o.params.execution_id??"",s=await l(),t=await s.prepare("SELECT node_id, state, launch_json, runner FROM executions WHERE execution_id = ?").get(n);if(t===void 0||t.node_id!==e.node)throw new a(403,"not_your_execution",`execution ${n} is not an execution of this node`);if(t.state!=="launching"&&t.state!=="running")throw new a(403,"execution_ended",`execution ${n} is ${t.state}`);if(t.launch_json===null)throw new a(409,"launch_missing",`execution ${n} carries no launch recipe`);const r=await w(e.node);if(r===null)throw new a(404,"node_not_found",`no node ${e.node}`);const i=await s.prepare("SELECT plugins_revision FROM person_settings WHERE person = ?").get(e.sub),c=await y(r.profile_id??null),p=await R(c),d=p?.repositories.map(m=>m.github_full_name)??[],_=d.length===0?null:(await S(e.sub,d)).author;return{status:200,body:{launch:JSON.parse(t.launch_json),node:{id:r.node_id,app:e.app,cwd:r.cwd,profile:r.profile_id??null,isolated:r.isolated===!0,environment_id:c},recipe:p,git_identity:_,plugins_revision:i===void 0?0:Number(i.plugins_revision),plugins:await O(e.sub,e.app),import_node_files:await $(r.node_id),...t.runner==="machine"?{machine_env:{...x(r.profile_id??null),...await v(r.profile_id??null,e.app)}}:{}}}}u(L,"handleStart");const Y=[{method:"GET",pattern:"/v1/executions/:execution_id/start",handler:L},{method:"POST",pattern:"/v1/executions/:execution_id/import-unpacked",handler:D}];export{Y as executionStartRoutes,O as plugins};
|