@north-light/cli 0.3.574 → 0.3.576
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/builtin-memory/crouter-sdk/release-notes.md +4 -0
- package/dist/clients/attach/viewer.js +73 -73
- package/dist/core/canvas/executions.d.ts +4 -4
- package/dist/core/canvas/executions.js +1 -1
- package/dist/core/command-plugins/bundle.d.ts +6 -3
- package/dist/core/command-plugins/bundle.js +1 -1
- package/dist/core/llm/run.js +2 -2
- package/dist/core/provider-error-recognition.d.ts +3 -0
- package/dist/core/provider-error-recognition.js +1 -1
- package/dist/core/providers/bundles.js +2 -2
- package/dist/core/providers/files.js +1 -1
- package/dist/core/providers/roots.d.ts +4 -0
- package/dist/core/providers/roots.js +1 -1
- package/dist/core/runs/operations.js +1 -1
- package/dist/core/runtime/broker/daemon-ops.js +1 -1
- package/dist/core/runtime/broker-request.js +1 -1
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/host.js +3 -3
- package/dist/core/runtime/runner/blaxel/client.d.ts +2 -0
- package/dist/core/runtime/runner/blaxel/client.js +1 -1
- package/dist/core/runtime/runner/blaxel/runner.js +2 -2
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/view-socket.d.ts +25 -4
- package/dist/core/runtime/view-socket.js +2 -2
- package/dist/core/storage/client.js +2 -2
- package/dist/core/subscription-state.d.ts +4 -0
- package/dist/core/subscription-state.js +1 -1
- package/dist/daemon/api/handlers/crons.js +1 -1
- package/dist/daemon/api/handlers/providers.js +1 -1
- package/dist/daemon/cron/narrowed.d.ts +2 -2
- package/dist/daemon/cron/narrowed.js +2 -2
- package/dist/daemon/cron/settle.js +1 -1
- package/dist/daemon/crtrd.js +11 -11
- package/dist/daemon/reconcilers/broker-supervision.js +4 -4
- package/dist/daemon/reconcilers/live-obligation.d.ts +11 -0
- package/dist/daemon/reconcilers/live-obligation.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/tick.js +1 -1
- package/dist/launcher/run.js +2 -2
- package/dist/launcher/spec.d.ts +3 -1
- package/dist/pi-extensions/canvas-inbox-watcher.js +1 -1
- package/docs/sdk/release-notes.md +4 -0
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -13
- package/scripts/sandbox-start.mjs +8 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
var h=Object.defineProperty;var t=(e,r)=>h(e,"name",{value:r,configurable:!0});import{CrtrClient as R}from"../../../api/client.js";import{currentNodeToken as y}from"./node-token.js";import{localClient as b}from"../../../api/node-transport.js";import{ApiError as l}from"../../../api/errors.js";import{envExecutionId as w}from"../../../shared/env.js";import{brokerSignalClient as N}from"./signal-stream.js";import{cachedBrokerNodeFields as k}from"../../../daemon/broker-signals/bus.js";import{fetchRunAttachments as P}from"./attachments-fetch.js";import{reportRefNodeId as v}from"../../../shared/inbox-entry-body.js";function g(){const e=process.env.CRTR_API_URL;if(!(e===void 0||e==="")){if(!/^https?:\/\//.test(e))throw new Error(`CRTR_API_URL must be an http(s) URL: ${e}`);return e}}t(g,"brokerApiUrl");function o(){const e=g();if(e===void 0)return b({autostart:!1});const r=y();if(r===void 0)throw new Error("broker has no node token for CRTR_API_URL");return new R({baseUrl:e,headers:{authorization:`Bearer ${r}`}})}t(o,"daemonClient");function $(e,r){return o().appendNodeLog(e,{record:r,expected_execution_id:n()})}t($,"appendBrokerLog");function D(e,r){return o().putNodeTelemetry(e,{...r,expected_execution_id:n()})}t(D,"putBrokerTelemetry");function j(e,r){return o().putNodeRecap(e,{briefing:r,expected_execution_id:n()})}t(j,"putBrokerRecap");function z(e,r){return o().readNodePassiveMessage(e,r)}t(z,"readBrokerPassiveMessage");function G(e){return o().nodePushedFinal(e,{action:"clear",expected_execution_id:n()})}t(G,"clearBrokerPushedFinal");function O(e){return o().nodePushedFinal(e,{action:"consume",expected_execution_id:n()})}t(O,"consumeBrokerPushedFinal");function q(e,r){return o().request("POST",`/v1/nodes/${encodeURIComponent(e)}/jobs/start`,{...r,expected_execution_id:n()})}t(q,"startBrokerBashJob");function X(e,r,i){return o().recordBackgroundedJob(e,r,i)}t(X,"recordBackgroundedJob");function H(e,r,i){return o().reportBashJob(e,r,{...i,expected_execution_id:n()})}t(H,"reportBrokerJob");function K(e,r){return o().request("DELETE",`/v1/nodes/${encodeURIComponent(e)}/jobs/${encodeURIComponent(r)}?foreground=1`,{expected_execution_id:n()})}t(K,"stopBrokerBashJob");function n(){const e=w();if(e===void 0||e==="")throw new Error("broker launch is missing CRTR_EXECUTION_ID");return e}t(n,"brokerExecutionId");function Q(e,r){return o().bindBrokerSession(e,{...r,executionId:n()})}t(Q,"bindBrokerSession");function V(e,r){return o().settleBroker(e,{...r,expected_execution_id:n()})}t(V,"settleBroker");function W(e){return o().postBrokerIdle(e,{expected_execution_id:n()})}t(W,"postBrokerIdle");function Y(e,r){return o().completeBrokerPark(e,{...r,expected_execution_id:n()})}t(Y,"completeBrokerPark");function Z(e){return o().recordBrokerParkActivity(e,{expected_execution_id:n()})}t(Z,"recordBrokerParkActivity");function ee(e,r){return o().recordBrokerTelemetry(e,{...r,expected_execution_id:n()})}t(ee,"recordBrokerTelemetry");const m=new Set;async function re(e,r,i){const s=o(),f=n(),a=await s.claimNodeMail(e,{execution_id:f,channel:r});if(a.action==="hold")return a;const x=a.deliveries.filter(u=>!m.has(u.entry.entry_id));if(x.length>0){await P(e);for(const u of x)m.add(u.entry.entry_id)}const p=await Promise.all(a.deliveries.map(async u=>{const c=u.entry.ref;if(c===void 0||v(c)===void 0)return u;try{let d=i.get(c);d===void 0&&(d=s.readNodeInboxReport(e,c,f).then(({content:B})=>B),i.set(c,d));const _=await d;return{...u,entry:{...u.entry,data:{...u.entry.data,report_body:_}}}}catch(d){if(i.delete(c),d instanceof l&&d.status===404)return u;throw d}}));if(p.length>0){const u=new Set(p.map(({entry:c})=>c.ref).filter(c=>c!==void 0));for(const c of i.keys())u.has(c)||i.delete(c)}return{...a,deliveries:p}}t(re,"claimBrokerMail");async function te(e,r){return await(await import("../../conversation-store/index.js")).flushConversation(),o().acknowledgeNodeMail(e,{execution_id:n(),deliveries:r})}t(te,"acknowledgeBrokerMail");function oe(e,r){return o().recordBrokerTurn(e,{...r,expected_execution_id:n()})}t(oe,"recordBrokerTurn");function ne(e,r){return o().mutateBrokerProviderRetry(e,{...r,expected_execution_id:n()})}t(ne,"mutateBrokerProviderRetry");function ie(e,r){return o().mutateBrokerFault(e,{...r,expected_execution_id:n()})}t(ie,"mutateBrokerFault");function ce(e){return o().getBrokerRecovery(e,n())}t(ce,"brokerRecovery");function ue(e,r){return o().recordNodeFault(e,r)}t(ue,"recordNodeFault");function de(e,r={}){return o().clearNodeFault(e,{...r.link===void 0?{}:{link:r.link},...r.preserveEpisode===void 0?{}:{preserve_episode:r.preserveEpisode}}).then(i=>i.cleared)}t(de,"clearNodeFault");function ae(e,r){return o().commitBrokerModel(e,{...r,expected_execution_id:n()})}t(ae,"commitBrokerModel");function C(e){return o().brokerExtensionState(e)}t(C,"brokerExtensionState");async function pe(e){const r=N();return r.state==="connected"&&r.latestNode!==void 0?k(r.latestNode):k((await C(e)).node)}t(pe,"cachedBrokerNode");function se(e,r){return o().nodeDelivery(e,{...r,expected_execution_id:n()})}t(se,"brokerDelivery");function fe(e,r){return o().commitBrokerGeneratedName(e,{...r,expected_execution_id:n()})}t(fe,"commitBrokerGeneratedName");function xe(e,r){return o().commitBrokerPersonaAck(e,{...r,expected_execution_id:n()})}t(xe,"commitBrokerPersonaAck");async function le(e,r){try{await o().pushReport(e,r)}catch(i){if(r.tier==="final"&&i instanceof l&&i.code==="already_finalized")return;throw i}}t(le,"publishBrokerReport");function ke(e){return o().relaunchRoot(e)}t(ke,"relaunchBrokerRoot");export{te as acknowledgeBrokerMail,$ as appendBrokerLog,Q as bindBrokerSession,g as brokerApiUrl,se as brokerDelivery,n as brokerExecutionId,C as brokerExtensionState,ce as brokerRecovery,pe as cachedBrokerNode,re as claimBrokerMail,G as clearBrokerPushedFinal,de as clearNodeFault,fe as commitBrokerGeneratedName,ae as commitBrokerModel,xe as commitBrokerPersonaAck,Y as completeBrokerPark,O as consumeBrokerPushedFinal,o as daemonClient,ie as mutateBrokerFault,ne as mutateBrokerProviderRetry,W as postBrokerIdle,le as publishBrokerReport,j as putBrokerRecap,D as putBrokerTelemetry,z as readBrokerPassiveMessage,X as recordBackgroundedJob,Z as recordBrokerParkActivity,ee as recordBrokerTelemetry,oe as recordBrokerTurn,ue as recordNodeFault,ke as relaunchBrokerRoot,H as reportBrokerJob,V as settleBroker,q as startBrokerBashJob,K as stopBrokerBashJob};
|
|
1
|
+
var h=Object.defineProperty;var t=(e,r)=>h(e,"name",{value:r,configurable:!0});import{CrtrClient as R}from"../../../api/client.js";import{currentNodeToken as y}from"./node-token.js";import{localClient as b}from"../../../api/node-transport.js";import{ApiError as l}from"../../../api/errors.js";import{envExecutionId as w}from"../../../shared/env.js";import{brokerSignalClient as N}from"./signal-stream.js";import{cachedBrokerNodeFields as k}from"../../../daemon/broker-signals/bus.js";import{fetchRunAttachments as P}from"./attachments-fetch.js";import{reportRefNodeId as v}from"../../../shared/inbox-entry-body.js";function g(){const e=process.env.CRTR_API_URL;if(!(e===void 0||e==="")){if(!/^https?:\/\//.test(e))throw new Error(`CRTR_API_URL must be an http(s) URL: ${e}`);return e}}t(g,"brokerApiUrl");function o(){const e=g();if(e===void 0)return b({autostart:!1});const r=y();if(r===void 0)throw new Error("broker has no node token for CRTR_API_URL");return new R({baseUrl:e,headers:{authorization:`Bearer ${r}`}})}t(o,"daemonClient");function $(e,r){return o().appendNodeLog(e,{record:r,expected_execution_id:n()})}t($,"appendBrokerLog");function D(e,r){return o().putNodeTelemetry(e,{...r,expected_execution_id:n()})}t(D,"putBrokerTelemetry");function j(e,r){return o().putNodeRecap(e,{briefing:r,expected_execution_id:n()})}t(j,"putBrokerRecap");function z(e,r){return o().readNodePassiveMessage(e,r)}t(z,"readBrokerPassiveMessage");function G(e){return o().nodePushedFinal(e,{action:"clear",expected_execution_id:n()})}t(G,"clearBrokerPushedFinal");function O(e){return o().nodePushedFinal(e,{action:"consume",expected_execution_id:n()})}t(O,"consumeBrokerPushedFinal");function q(e,r){return o().request("POST",`/v1/nodes/${encodeURIComponent(e)}/jobs/start`,{...r,expected_execution_id:n()})}t(q,"startBrokerBashJob");function X(e,r,i){return o().recordBackgroundedJob(e,r,i)}t(X,"recordBackgroundedJob");function H(e,r,i){return o().reportBashJob(e,r,{...i,expected_execution_id:n()})}t(H,"reportBrokerJob");function K(e,r){return o().request("DELETE",`/v1/nodes/${encodeURIComponent(e)}/jobs/${encodeURIComponent(r)}?foreground=1`,{expected_execution_id:n()})}t(K,"stopBrokerBashJob");function n(){const e=w();if(e===void 0||e==="")throw new Error("broker launch is missing CRTR_EXECUTION_ID");return e}t(n,"brokerExecutionId");function Q(e,r){return o().bindBrokerSession(e,{...r,executionId:n()})}t(Q,"bindBrokerSession");function V(e,r){return o().settleBroker(e,{...r,expected_execution_id:n()})}t(V,"settleBroker");function W(e){return o().postBrokerIdle(e,{expected_execution_id:n()})}t(W,"postBrokerIdle");function Y(e,r){return o().completeBrokerPark(e,{...r,expected_execution_id:n()})}t(Y,"completeBrokerPark");function Z(e){return o().recordBrokerParkActivity(e,{expected_execution_id:n()})}t(Z,"recordBrokerParkActivity");function ee(e,r){return o().recordBrokerTelemetry(e,{...r,expected_execution_id:n()})}t(ee,"recordBrokerTelemetry");const m=new Set;async function re(e,r,i){const s=o(),f=n(),a=await s.claimNodeMail(e,{execution_id:f,channel:r});if(a.action==="hold")return a;const x=a.deliveries.filter(u=>!m.has(u.entry.entry_id));if(x.length>0){await P(e);for(const u of x)m.add(u.entry.entry_id)}const p=await Promise.all(a.deliveries.map(async u=>{const c=u.entry.ref;if(c===void 0||v(c)===void 0)return u;try{let d=i.get(c);d===void 0&&(d=s.readNodeInboxReport(e,c,f).then(({content:B})=>B),i.set(c,d));const _=await d;return{...u,entry:{...u.entry,data:{...u.entry.data,report_body:_}}}}catch(d){if(i.delete(c),d instanceof l&&d.status===404)return u;throw d}}));if(p.length>0){const u=new Set(p.map(({entry:c})=>c.ref).filter(c=>c!==void 0));for(const c of i.keys())u.has(c)||i.delete(c)}return{...a,deliveries:p}}t(re,"claimBrokerMail");async function te(e,r){return await(await import("../../conversation-store/index.js")).flushConversation(),o().acknowledgeNodeMail(e,{execution_id:n(),deliveries:r})}t(te,"acknowledgeBrokerMail");function oe(e,r){return o().recordBrokerTurn(e,{...r,expected_execution_id:n()})}t(oe,"recordBrokerTurn");function ne(e,r){return o().mutateBrokerProviderRetry(e,{...r,expected_execution_id:n()})}t(ne,"mutateBrokerProviderRetry");function ie(e,r){return o().mutateBrokerFault(e,{...r,expected_execution_id:n()})}t(ie,"mutateBrokerFault");function ce(e){return o().getBrokerRecovery(e,n())}t(ce,"brokerRecovery");async function ue(e,r){return o().recordNodeFault(e,r)}t(ue,"recordNodeFault");async function de(e,r={}){return o().clearNodeFault(e,{...r.link===void 0?{}:{link:r.link},...r.preserveEpisode===void 0?{}:{preserve_episode:r.preserveEpisode}}).then(i=>i.cleared)}t(de,"clearNodeFault");function ae(e,r){return o().commitBrokerModel(e,{...r,expected_execution_id:n()})}t(ae,"commitBrokerModel");function C(e){return o().brokerExtensionState(e)}t(C,"brokerExtensionState");async function pe(e){const r=N();return r.state==="connected"&&r.latestNode!==void 0?k(r.latestNode):k((await C(e)).node)}t(pe,"cachedBrokerNode");function se(e,r){return o().nodeDelivery(e,{...r,expected_execution_id:n()})}t(se,"brokerDelivery");function fe(e,r){return o().commitBrokerGeneratedName(e,{...r,expected_execution_id:n()})}t(fe,"commitBrokerGeneratedName");function xe(e,r){return o().commitBrokerPersonaAck(e,{...r,expected_execution_id:n()})}t(xe,"commitBrokerPersonaAck");async function le(e,r){try{await o().pushReport(e,r)}catch(i){if(r.tier==="final"&&i instanceof l&&i.code==="already_finalized")return;throw i}}t(le,"publishBrokerReport");function ke(e){return o().relaunchRoot(e)}t(ke,"relaunchBrokerRoot");export{te as acknowledgeBrokerMail,$ as appendBrokerLog,Q as bindBrokerSession,g as brokerApiUrl,se as brokerDelivery,n as brokerExecutionId,C as brokerExtensionState,ce as brokerRecovery,pe as cachedBrokerNode,re as claimBrokerMail,G as clearBrokerPushedFinal,de as clearNodeFault,fe as commitBrokerGeneratedName,ae as commitBrokerModel,xe as commitBrokerPersonaAck,Y as completeBrokerPark,O as consumeBrokerPushedFinal,o as daemonClient,ie as mutateBrokerFault,ne as mutateBrokerProviderRetry,W as postBrokerIdle,le as publishBrokerReport,j as putBrokerRecap,D as putBrokerTelemetry,z as readBrokerPassiveMessage,X as recordBackgroundedJob,Z as recordBrokerParkActivity,ee as recordBrokerTelemetry,oe as recordBrokerTurn,ue as recordNodeFault,ke as relaunchBrokerRoot,H as reportBrokerJob,V as settleBroker,q as startBrokerBashJob,K as stopBrokerBashJob};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var b=Object.defineProperty;var
|
|
1
|
+
var b=Object.defineProperty;var i=(e,t)=>b(e,"name",{value:t,configurable:!0});import{randomUUID as f}from"node:crypto";import{BrokerClient as h,SocketTransport as m}from"../broker-client/index.js";const u=15e3;class w extends Error{static{i(this,"BrokerUnreachableError")}constructor(t){super(t),this.name="BrokerUnreachableError"}}function I(e){return new Promise(async(t,c)=>{const o=new h(e.nodeId,{transport:new m(e.nodeId,{recordsViewerFaults:!1})}),k=f(),d=f();let a=!1,s=!1;const l=setTimeout(()=>n(()=>c(new Error(`timed out after ${u}ms waiting for the broker to ack ${e.what}`))),u);typeof l.unref=="function"&&l.unref();function n(r){if(!a){a=!0,clearTimeout(l);try{o.close()}catch{}r()}}i(n,"finish"),o.on("error",r=>n(()=>c(s?r:new w(`broker connection refused mid-revive: ${r.message}`)))),o.on("close",()=>n(()=>c(s?new Error(`broker connection closed before it acked ${e.what}`):new w("broker connection closed before it was established (mid-revive)")))),o.on("connect",()=>{s=!0,o.send({type:"hello",role:"controller",client_id:k}),o.send(e.frame(d))}),o.on("frame",r=>{r.type==="ack"&&r.for===e.ackFor&&(e.correlated!==!0||r.id===d)?r.ok?n(()=>t(e.result(r.detail))):n(()=>c(new Error(r.detail??`broker rejected ${e.what}`))):r.type==="error"?n(()=>c(new Error(r.message))):e.observe!==void 0&&e.observe(r)}),o.connect()})}i(I,"oneShotControllerRequest");export{w as BrokerUnreachableError,I as oneShotControllerRequest};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var De=Object.defineProperty;var n=(t,o)=>De(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Ne,envModelIntent as Fe,envNodeCwd as Le,envNodeId as Be,envProfileId as Ue,envScopes as $e,scopeAllowed as Ke}from"../../shared/env.js";import{createServer as We}from"node:net";import{WebSocketServer as Ge,createWebSocketStream as je}from"ws";import{BROKER_VIEW_PORT as qe}from"./view-socket.js";import{existsSync as Re,readFileSync as Ve,unlinkSync as Te}from"node:fs";import{join as Ee}from"node:path";import{randomUUID as M}from"node:crypto";import{mark as Xe}from"../timing.js";import{SUBMIT_RESULT_TOOL as He}from"./structured-output.js";import{flushConversation as ke,installSessionManagerStorePatch as Ye}from"../conversation-store/index.js";import{getAgentDir as J,ModelRegistry as ze,ModelRuntime as Je}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Qe,viewSocketPath as Ze}from"../canvas/paths.js";import{bindBrokerEventSource as en}from"../events/source.js";import{emitEvent as b,flushBrokerLog as nn}from"../events/emit.js";import{operationIdContext as tn}from"../events/operation-id.js";import{findMissingPackagePaths as rn}from"./package-health.js";import{installBrokerConfigSnapshot as on}from"../config.js";import{FRONT_DOOR_ENV as sn}from"./front-door.js";import{CANVAS_EXTENSIONS as oe,piInvocationToSdkConfig as an}from"./launch.js";import{assertEngineVersion as dn,loadBrokerEngine as ln}from"./broker-sdk.js";import{initCrtrTheme as cn}from"./crtr-theme.js";import{resolveBundledPiPackageDir as mn}from"./pi-cli.js";import{captureSessionChatCapabilities as un}from"./command-surface.js";import{InMemoryCredentialStore as fn}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as pn}from"./broker/model-adapter.js";import{brokerApiUrl as gn,mutateBrokerFault as Q,recordBrokerTurn as Ce}from"./broker/daemon-ops.js";import{fetchRunAttachments as vn}from"./broker/attachments-fetch.js";import{modelRequestFromConfig as _n,expandModelCandidates as hn,parseModelSpec as wn,unregisteredConcreteModel as Sn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as bn}from"./stream-watchdog.js";import{probeOnline as yn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as Rn,cycleAwareMessages as Tn,endedByAbort as En}from"./session-cycles.js";import{turnErrorOf as kn}from"../llm/refusal.js";import{projectTranscript as Cn}from"./session-visibility.js";import{currentTurnVisibility as xn}from"./turn-visibility.js";import{isUnknownModel as ie}from"./model-selection.js";import{BrokerClientRegistry as Mn}from"./broker/client-registry.js";import{ToolGroupTracker as An}from"./broker/tool-groups.js";import{TurnReplyTracker as Pn}from"./broker/turn-replies.js";import{onNodeNamed as On}from"./broker/node-named.js";import{FaultRetry as In,willDaemonRetry as Dn}from"./broker/fault-retry.js";import{RunTurnEnds as Nn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as Fn}from"./broker/turn-admission.js";import{BROKER_DISPOSE_AND_EXIT as Ln,BROKER_IDLE_TURN_START as Bn,BROKER_RUN_TURN_BUSY as Un}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as $n,settleRunDeferredMail as Kn}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Wn}from"./broker/run-turn-queue.js";import{EventProjection as Gn}from"./broker/event-projection.js";import{createFrameDispatchContext as jn,handleFrame as qn}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as Vn,installAdvertisedCommandInvocationContract as Xn}from"./advertised-command-invocation.js";import{RebindDriver as Hn}from"./broker/rebind.js";import{beginRuntimeTeardown as Yn}from"./broker/extension-abort.js";import{receiveNodeToken as zn}from"./broker/node-token.js";import{serveCliRelay as Jn}from"./broker/cli-relay.js";import{recordBrokerRelease as Qn}from"./lifecycle.js";import{setTurnCauseSource as Zn}from"./broker/turn-cause.js";import{decodeKickoffOrigin as et,KICKOFF_ORIGIN_ENV as nt}from"./stamp/protocol.js";import{announceMessageOrigin as tt}from"./stamp/channel.js";import{commitBrokerModel as rt}from"./broker/daemon-ops.js";import{bootExtensionState as ot}from"./broker/boot-state.js";import{composerNames as it}from"./broker/frame-memory-refs.js";import{BROKER_READ_CAPS as st,FrameOverflowError as at,normalizeSnapshotTail as dt}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as Mr,REVIEW_BOUNDARY_NAVIGATION_CODE as Ar}from"./broker/frame-replies.js";function se(t){return new ze(t.modelRuntime)}n(se,"registryOf");function $(t,o){if(t==null||ie(t))return null;const s=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${s}`}n($,"formatModelSpec");function lt(t,o){const s=$(t,void 0);return s===null?null:`${s}:${o===void 0||o===""?"off":o}`}n(lt,"formatExactModelSpec");const ct=12e4;let Z=null;import{brokerSignalClient as K}from"./broker/signal-stream.js";function mt(){K().stop();const t=Z;if(Z=null,t!==null)try{t.dispose()}catch{}}n(mt,"disposeActiveSession");function ut(t,o){const s=Ke(o,"crtr:act")?void 0:["bash"],u=t!==void 0&&t.length>0?[...new Set([...t,He])]:t===void 0?void 0:[...t];return{...u!==void 0?{tools:u}:{},...s!==void 0?{excludeTools:s}:{}}}n(ut,"brokerToolOptions");async function kr(t,o=process.hrtime.bigint(),s=new Date().toISOString()){en(t);const u=await zn(),i=await Jn(t,u);process.env.CRTR_API_SOCKET=i.path,tn.fresh(()=>{b({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),b({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let c=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Xe(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),b({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:c,model:r}}))},"emitStartupMilestone");process.env[sn]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,Ye(t);const v=await ln();dn(v.VERSION),c=v.VERSION;const w=Qe(t),E=Ee(w,"broker-launch.json"),S=JSON.parse(Ve(E,"utf8"));if(!S.configSnapshot)throw new Error("broker launch is missing its config snapshot");on(S.configSnapshot);const g=an(S);g.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await it(t);let R,A;const X=n(e=>{R!==void 0?R(e):A??=e},"onSignal");process.on("SIGTERM",()=>X("SIGTERM")),process.on("SIGINT",()=>X("SIGINT")),process.on("SIGUSR1",()=>{const e=process.env.CRTR_EXECUTION_ID;e!==void 0&&e!==""&&K().start(t,e)});let{session:W,services:P,resuming:de,runtime:G}=await vt(v,g);d("broker.startup.session_built");const k=(await ot(t)).node.review_binding?.review_id,T=Ne();Z=W;const F=yn;try{process.env.PI_PACKAGE_DIR=mn(),cn(P.settingsManager.getTheme(),J(),!1)}catch(e){b({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of rn(J()))b({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const j=Ze(t),_=new Mn(t),H=new Map,I=new An(t,e=>_.broadcast(e)),q=new Pn(t,e=>_.broadcast(e));On(e=>_.broadcast({type:"node_named",...e}));let D=!1,le=!1,Y,z,ce,m,V;const ee=new Nn;let L,me=n(()=>{},"notifyTurnAccepted"),ue=n(()=>{},"resetFrameState");const ne=Fn();let fe=n(()=>0,"pendingPromptDispatches"),pe;const B=Wn({runNode:T,session:n(()=>m.session(),"session"),isReplacing:n(()=>m.isReplacing(),"isReplacing"),pendingRebind:n(()=>m.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>m.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>fe(),"pendingDispatches"),turnAdmission:ne,prependDeferred:n(e=>$n(t,e),"prependDeferred"),onError:n(e=>b({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")});Zn(()=>m.session());const ge=B.drain;g.firstPrompt!==void 0&&g.firstPrompt!==""&&B.holdForKickoff(),globalThis[Bn]=B.start,globalThis[Un]=B.busy,m=new Hn({nodeId:t,cfg:g,session:W,services:P,runtime:G,registry:_,toolGroups:I,turnReplies:q,transcriptMessages:n(e=>ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>ce,"uiContext"),faultRetry:n(()=>V,"faultRetry"),projection:n(()=>L,"projection"),setActiveSession:n(e=>{if(Z=e,pe?.(),T||process.env.CRTR_RUN_ID){let r="stop",l,f=!1;pe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",l=void 0,f=!1,ee.started()),h.type==="agent_end"){const p=[...h.messages??[]].reverse().find(U=>U.role==="assistant");p&&(r=p.stopReason,l=En(p)?void 0:kn(p),f=p.role==="assistant"&&Dn(p,e.model?.contextWindow))}h.type==="agent_settled"&&(ee.settled(e.sessionManager,{stop_reason:r,...l?{error:l}:{}},f),T&&(ke().then(()=>Kn(t,e)).catch(p=>{if(String(p?.message).startsWith("conversation_write_failed")){b({level:"error",event:"broker.exited",node_id:t,error:p,fields:{fault:"conversation_write_failed"}}),C("conversation_write_failed",1);return}b({level:"error",event:"broker.run_deferred_mail.settle_failed",error:p})}),queueMicrotask(()=>{m.session()===e&&ge()})))})}},"setActiveSession"),disposeAndExit:n((e,r)=>C(e,r),"disposeAndExit"),onSessionRebind:n(()=>{ue()},"onSessionRebind"),onReplacementIdle:n(()=>{T&&ge()},"onReplacementIdle"),reWelcomeAll:n(()=>te(),"reWelcomeAll")});const ve=n(async(e,r=!1)=>{const l=m.session(),f=$(l.model,l.thinkingLevel);if(f===null)return null;const h=await rt(t,{spec:f,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(g.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,g.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",g.modelExact=!0)),h.modelOverride},"persistModelChoice"),_e=n(async(e=!0,r,l=!1)=>{const f=m.session(),h=$(f.model,f.thinkingLevel),p=e?await ve(r,l):h;_.broadcast({type:"model_changed",model:ie(f.model)?void 0:f.model,spec:p})},"broadcastModelChanged");V=new In({nodeId:t,cfg:g,retryProbe:F,currentSession:n(()=>m.session(),"currentSession"),currentServices:n(()=>m.services(),"currentServices"),installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:$,broadcastModelChanged:_e,turnAdmission:ne,reWelcomeAll:n(()=>te(),"reWelcomeAll"),...T?{turnEnds:ee}:{}});const he=n(()=>{V.rearmIfStranded().catch(e=>{b({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");K().subscribe("resync",he),K().subscribe("fault-retry",he),L=new Gn({registry:_,faultRetry:V,installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),currentSession:n(()=>m.session(),"currentSession"),notifyTurnAccepted:n(()=>me(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:$});const Me=n(e=>{const r=m.session(),l=ae(r,k),f=dt(e.snapshotTail),h=l===void 0||f===void 0?l:l.slice(-f),p=h?.map(({message:N})=>N)??r.sessionManager.buildSessionContext().messages,U=I.summaries(),ye=h!==void 0&&f!==void 0?ft(p):void 0,Ie=ye===void 0?U:Object.fromEntries(Object.entries(U).filter(([N])=>ye.has(N)));return{messages:p,...h===void 0?{}:{messageIds:h.map(({id:N})=>N)},messageVisibility:h?.map(({visibility:N})=>N)??p.map(()=>"visible"),turnVisibility:xn(),stats:r.getSessionStats(),state:{model:ie(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{..._.displaySnapshot()},toolGroupSummaries:Ie,turnReplies:q.snapshot(),workingActivity:L.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),we=n(e=>{const r=e.role==="controller"?H.values().next().value:void 0;_.sendFrame(e,{type:"welcome",snapshot:Me(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:J()},!0)},"sendWelcome"),Ae=n(e=>{const r=[...H.values()];for(let l=1;l<r.length;l++)_.sendFrame(e,r[l].request)},"replayExtraPendingDialogsTo"),te=n(()=>{try{const e=m.session();q.seed(ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){b({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}_.forEachHelloed(we)},"reWelcomeAll"),Se=n(async e=>{if(D)return;D=!0;const r=K().latestNode;r!==void 0&&(r.intent==="idle-release"||r.status==="done")&&Qn(t,process.env.CRTR_EXECUTION_ID??null),K().stop(),e===0&&await ke().catch(l=>{e=1,b({level:"error",event:"broker.exited",node_id:t,error:l,fields:{fault:"conversation_write_failed"}})}),I.persistPendingSummary(),L.dispose(),mt();try{Y?.close(),z?.close()}catch{}i.close(),_.dispose();try{Re(j)&&Te(j)}catch{}_.clearAttachState(),await nn(),process.exit(e)},"completeExit"),C=n((e,r=0)=>{if(D)return;const l=e==="shutdown-hook"||e==="shutdown-after-settle";if(l&&I.finishOpenToolGroup(!0),l&&(I.hasSummaryTasks()||q.hasTasks())){if(le)return;le=!0,Promise.allSettled([I.waitForSummaryTasks(),q.waitForTasks()]).finally(()=>Se(r));return}Se(r)},"disposeAndExit");globalThis[Ln]=C,ce=_t({writable:n(()=>_.writableClients(),"writable"),forward:n((e,r)=>_.sendFrame(e,r),"forward"),pending:H,broadcast:n(e=>_.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>L.knownStreamWait(e),"onKnownStreamWait")}),m.setRebindSession(),await m.enqueueRebind(W,P),d("broker.startup.extensions_bound");const x=jn({nodeId:t,registry:_,toolGroups:I,projection:L,rebind:m,boundaryReviewId:k,pendingDialogs:H,sendWelcome:we,replayExtraPendingDialogsTo:Ae,reWelcomeAll:te,disposeAndExit:C,persistModelChoice:ve,broadcastModelChanged:_e,registryOf:se,formatModelSpec:$,formatExactModelSpec:lt,turnAdmission:ne,memoryInventory:y,runNode:T,onKickoffAdmitted:B.releaseKickoff});me=x.notifyTurnAccepted,ue=x.resetForSession,fe=x.pendingPromptDispatches;const Pe=2500;let re=!1;const Oe=n(async e=>{if(D||re)return;if(re=!0,m.isAgentRunActive()||m.session().isStreaming||x.pendingPromptDispatches()>0){const l=Date.now()+Pe;for(;x.pendingPromptDispatches()>0&&!m.session().isStreaming&&Date.now()<l;)await new Promise(f=>setTimeout(f,25));if(m.session().isStreaming){const f=l-Date.now();if(f>0){let h;try{Yn(),await Promise.race([m.session().abort().then(()=>!0,()=>!1),new Promise(U=>{h=setTimeout(()=>U(!1),f)})])&&await Ce(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(x.pendingPromptDispatches()>0||m.isAgentRunActive())&&await Ce(t,{event:"interrupted"})}C(e)},"abortAndExit");if(R=n(e=>{Oe(e)},"signalTeardown"),A!==void 0){R(A);return}try{Re(j)&&Te(j)}catch{}const be=n(e=>{const r=_.create(e);e.on("data",f=>{let h;try{h=r.decoder.push(f)}catch(p){p instanceof at?(_.sendFrame(r,{type:"error",code:"frame_overflow",message:p.message}),_.dropClient(r,`frame overflow: ${p.message}`)):_.dropClient(r,`decoder error: ${String(p)}`);return}for(const p of h)try{qn(x,r,p)}catch{}});const l=n(()=>{_.removeClient(r)},"drop");e.on("close",l),e.on("error",()=>{})},"serveViewer");Y=We(be),gn()!==void 0&&(z=new Ge({host:"127.0.0.1",port:qe,path:"/view",maxPayload:st.maxLineBytes}),z.on("connection",e=>be(je(e))),z.on("error",e=>{D||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))})),Y.on("error",e=>{D||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))}),Y.listen(j,async()=>{Promise.all([Q(t,{op:"clear",link:"viewer\u2194broker"}),Q(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await V.recoverOnStartup()}catch(r){b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),C("recovery-startup-failed",1);return}if(!(D||re))if(e==="none"&&g.firstPrompt!==void 0&&g.firstPrompt!==""){const r=et(process.env[nt]);r!==null&&tt(g.firstPrompt,r);try{await vn(t)}catch(f){b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:f,fields:{operation:"attachments_fetch"}}),C("attachments-fetch-failed",1);return}const l=process.env.CRTR_KICKOFF_MESSAGE_IDS;x.kickoff(g.firstPrompt,l?JSON.parse(l):[])}else B.releaseKickoff()}),_.persistAttachState()}n(kr,"runBroker");function ft(t){const o=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const u of s.content)u!==null&&typeof u=="object"&&u.type==="toolCall"&&typeof u.id=="string"&&o.add(u.id);return o}n(ft,"toolCallIds");function ae(t,o){const s=t.sessionManager,u=Tn(s);return u!==void 0&&Vn(u.map(({message:i})=>i)),u===void 0?void 0:Cn(u,{boundaryReviewId:o,sessionEntries:s.getEntries?.()})}n(ae,"snapshotMessages");function xe(){const t=Be();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(xe,"currentBrokerNodeId");async function pt(t,o){const s=_n(o.model,Fe(),o.modelExact===!0);if(s===void 0)return;const u=se(t),i={cwd:Le()??o.cwd,profileId:Ue()},a=await Sn(s,u,i);if(a!==void 0)throw await Q(xe(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const c=await hn(s,i.cwd,i.profileId),d=wn(s.spec);for(const v of c){const w=u.find(v.providerId,v.modelId);if(w===void 0)continue;const S=d?.providerId===v.providerId&&d.modelId===v.modelId?d.thinkingLevel??(v.thinkingLevel===void 0?void 0:"off"):v.thinkingLevel;return{model:w,thinkingLevel:S}}if(o.modelExact===!0){const v=c.map(w=>`'${w.providerId}/${w.modelId}' unregistered`).join("; ");throw await Q(xe(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${o.model}' is unavailable \u2014 refusing to substitute (${v})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}b({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:c.map(v=>({provider:v.providerId,model:v.modelId,reason:"unregistered"})).slice(0,16)}})}n(pt,"resolveLaunchModel");function gt(t){let o=!0;return{runtime:new Proxy(t,{get(u,i,a){return o&&i==="getAvailableSnapshot"?()=>[]:o&&i==="getAvailable"?async()=>[]:o&&i==="getModel"?()=>{}:Reflect.get(u,i,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(gt,"modelLessRegistry");async function vt(t,o){const s=J(),u=n(async S=>{const g=await Je.create({credentials:new fn,modelsPath:Ee(S.agentDir,"models.json")});pn(g);const y=await t.createAgentSessionServices({cwd:S.cwd,agentDir:S.agentDir,modelRuntime:g,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(O=>({...O,extensions:O.extensions.filter(k=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(k.path))}),"extensionsOverride")}}),R=y.resourceLoader.getExtensions();if(o.extensionPaths.some(O=>oe.includes(O))){const O=new Set(R.extensions.map(T=>T.path)),k=oe.filter(T=>!O.has(T));if(k.length>0){const T=R.errors.filter(F=>oe.includes(F.path)).map(F=>`${F.path}: ${F.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${k.join(", ")}${T===""?"":` (${T})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const A=await pt(y,o),X=A?.model,W=A?.thinkingLevel,P=A===void 0?gt(y.modelRuntime):void 0,de=P!==void 0?{...y,modelRuntime:P.runtime}:y,G=await t.createAgentSessionFromServices({services:de,sessionManager:S.sessionManager,model:X,thinkingLevel:W,...ut(o.tools,$e()),sessionStartEvent:S.sessionStartEvent});return Xn(G.session),un(G.session),P?.reveal(),{...G,services:y}},"buildForManager"),i=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(i===void 0||i==="")&&o.resumeSessionId!==void 0&&o.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${o.resumeSessionId}' (pi_session_file was never captured for this node)`);const c=!a&&i!==void 0&&i!=="",d=c&&o.newCycle===!0,v=c&&!d;let w;if(a)w=await t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(v||d){if(w=await t.SessionManager.open(i),d){const S=w.getLeafId();w.resetLeaf(),w.appendCustomEntry(Rn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:S})}}else w=await t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const S=n(async y=>{const R=await u({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...R,diagnostics:R.services.diagnostics??[]}},"factory"),g=await t.createAgentSessionRuntime(S,{cwd:o.cwd,agentDir:s,sessionManager:w});return{session:g.session,services:g.services,resuming:v,runtime:g}}const E=await u({cwd:o.cwd,agentDir:s,sessionManager:w});return{session:E.session,services:E.services,resuming:v,runtime:void 0}}n(vt,"buildBrokerSession");function _t(t){const o=n((i,a,c,d)=>{if(d?.signal?.aborted)return Promise.resolve(i);const v=t.writable();return v.length===0?Promise.resolve(i):new Promise(w=>{let E;const S=n(()=>{E!==void 0&&clearTimeout(E),d?.signal?.removeEventListener("abort",g),t.pending.delete(a.id)},"cleanup"),g=n(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},"onAbort");d?.signal?.addEventListener("abort",g,{once:!0});const y=d?.timeout!==void 0?d.timeout:ct;E=setTimeout(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},y),typeof E.unref=="function"&&E.unref(),t.pending.set(a.id,{request:a,resolve:n(R=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(c(R))},"resolve")});for(const R of v)t.forward(R,a)})},"dialogPromise"),s=n(()=>{},"noop");return{[bn]:t.onKnownStreamWait??(i=>()=>{}),get theme(){const i=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(i==null)throw new Error("Theme not initialized. Call initTheme() first.");return i},select:n((i,a,c)=>o(void 0,{type:"extension_ui_request",id:M(),method:"select",title:i,options:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"select"),confirm:n((i,a,c)=>o(!1,{type:"extension_ui_request",id:M(),method:"confirm",title:i,message:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,c),"confirm"),input:n((i,a,c)=>o(void 0,{type:"extension_ui_request",id:M(),method:"input",title:i,placeholder:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"input"),editor:n((i,a)=>o(void 0,{type:"extension_ui_request",id:M(),method:"editor",title:i,prefill:a},c=>"cancelled"in c&&c.cancelled?void 0:"value"in c?c.value:void 0),"editor"),setStatus:n((i,a)=>t.broadcast({type:"extension_ui_request",id:M(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:n((i,a,c)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:M(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:c?.placement})},"setWidget"),setTitle:n(i=>t.broadcast({type:"extension_ui_request",id:M(),method:"setTitle",title:i}),"setTitle"),notify:n((i,a)=>{const c=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:M(),method:"notify",message:i,notifyType:c})},"notify"),onTerminalInput:n(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:s,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}n(_t,"makeBrokerUiContext");export{Ar as REVIEW_BOUNDARY_NAVIGATION_CODE,Mr as ReviewBoundaryNavigationError,ut as brokerToolOptions,vt as buildBrokerSession,mt as disposeActiveSession,_t as makeBrokerUiContext,kr as runBroker,ae as snapshotMessages};
|
|
1
|
+
var De=Object.defineProperty;var n=(t,o)=>De(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Ne,envModelIntent as Fe,envNodeCwd as Le,envNodeId as Be,envProfileId as Ue,envScopes as $e,scopeAllowed as Ke}from"../../shared/env.js";import{createServer as We}from"node:net";import{WebSocketServer as Ge,createWebSocketStream as je}from"ws";import{BROKER_VIEW_PORT as qe}from"./view-socket.js";import{existsSync as Re,readFileSync as Ve,unlinkSync as Te}from"node:fs";import{join as Ee}from"node:path";import{randomUUID as M}from"node:crypto";import{mark as Xe}from"../timing.js";import{SUBMIT_RESULT_TOOL as He}from"./structured-output.js";import{flushConversation as ke,installSessionManagerStorePatch as Ye}from"../conversation-store/index.js";import{getAgentDir as J,ModelRegistry as ze,ModelRuntime as Je}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Qe,viewSocketPath as Ze}from"../canvas/paths.js";import{bindBrokerEventSource as en}from"../events/source.js";import{emitEvent as b,flushBrokerLog as nn}from"../events/emit.js";import{operationIdContext as tn}from"../events/operation-id.js";import{findMissingPackagePaths as rn}from"./package-health.js";import{installBrokerConfigSnapshot as on}from"../config.js";import{FRONT_DOOR_ENV as sn}from"./front-door.js";import{CANVAS_EXTENSIONS as oe,piInvocationToSdkConfig as an}from"./launch.js";import{assertEngineVersion as dn,loadBrokerEngine as ln}from"./broker-sdk.js";import{initCrtrTheme as cn}from"./crtr-theme.js";import{resolveBundledPiPackageDir as mn}from"./pi-cli.js";import{captureSessionChatCapabilities as un}from"./command-surface.js";import{InMemoryCredentialStore as fn}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as pn}from"./broker/model-adapter.js";import{brokerApiUrl as gn,mutateBrokerFault as Q,recordBrokerTurn as Ce}from"./broker/daemon-ops.js";import{fetchRunAttachments as vn}from"./broker/attachments-fetch.js";import{modelRequestFromConfig as _n,expandModelCandidates as hn,parseModelSpec as wn,unregisteredConcreteModel as Sn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as bn}from"./stream-watchdog.js";import{probeOnline as yn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as Rn,cycleAwareMessages as Tn,endedByAbort as En}from"./session-cycles.js";import{turnErrorOf as kn}from"../llm/refusal.js";import{projectTranscript as Cn}from"./session-visibility.js";import{currentTurnVisibility as xn}from"./turn-visibility.js";import{isUnknownModel as ie}from"./model-selection.js";import{BrokerClientRegistry as Mn}from"./broker/client-registry.js";import{ToolGroupTracker as An}from"./broker/tool-groups.js";import{TurnReplyTracker as Pn}from"./broker/turn-replies.js";import{onNodeNamed as On}from"./broker/node-named.js";import{FaultRetry as In,willDaemonRetry as Dn}from"./broker/fault-retry.js";import{RunTurnEnds as Nn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as Fn}from"./broker/turn-admission.js";import{BROKER_DISPOSE_AND_EXIT as Ln,BROKER_IDLE_TURN_START as Bn,BROKER_RUN_TURN_BUSY as Un}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as $n,settleRunDeferredMail as Kn}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Wn}from"./broker/run-turn-queue.js";import{EventProjection as Gn}from"./broker/event-projection.js";import{createFrameDispatchContext as jn,handleFrame as qn}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as Vn,installAdvertisedCommandInvocationContract as Xn}from"./advertised-command-invocation.js";import{RebindDriver as Hn}from"./broker/rebind.js";import{beginRuntimeTeardown as Yn}from"./broker/extension-abort.js";import{receiveNodeToken as zn}from"./broker/node-token.js";import{serveCliRelay as Jn}from"./broker/cli-relay.js";import{recordBrokerRelease as Qn}from"./lifecycle.js";import{setTurnCauseSource as Zn}from"./broker/turn-cause.js";import{decodeKickoffOrigin as et,KICKOFF_ORIGIN_ENV as nt}from"./stamp/protocol.js";import{announceMessageOrigin as tt}from"./stamp/channel.js";import{commitBrokerModel as rt}from"./broker/daemon-ops.js";import{bootExtensionState as ot}from"./broker/boot-state.js";import{composerNames as it}from"./broker/frame-memory-refs.js";import{BROKER_READ_CAPS as st,FrameOverflowError as at,normalizeSnapshotTail as dt}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as Mr,REVIEW_BOUNDARY_NAVIGATION_CODE as Ar}from"./broker/frame-replies.js";function se(t){return new ze(t.modelRuntime)}n(se,"registryOf");function $(t,o){if(t==null||ie(t))return null;const s=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${s}`}n($,"formatModelSpec");function lt(t,o){const s=$(t,void 0);return s===null?null:`${s}:${o===void 0||o===""?"off":o}`}n(lt,"formatExactModelSpec");const ct=12e4;let Z=null;import{brokerSignalClient as K}from"./broker/signal-stream.js";function mt(){K().stop();const t=Z;if(Z=null,t!==null)try{t.dispose()}catch{}}n(mt,"disposeActiveSession");function ut(t,o){const s=Ke(o,"crtr:act")?void 0:["bash"],u=t!==void 0&&t.length>0?[...new Set([...t,He])]:t===void 0?void 0:[...t];return{...u!==void 0?{tools:u}:{},...s!==void 0?{excludeTools:s}:{}}}n(ut,"brokerToolOptions");async function kr(t,o=process.hrtime.bigint(),s=new Date().toISOString()){en(t);const u=await zn(),i=await Jn(t,u);process.env.CRTR_API_SOCKET=i.path,tn.fresh(()=>{b({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),b({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let c=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Xe(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),b({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:c,model:r}}))},"emitStartupMilestone");process.env[sn]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,Ye(t);const v=await ln();dn(v.VERSION),c=v.VERSION;const w=Qe(t),E=Ee(w,"broker-launch.json"),S=JSON.parse(Ve(E,"utf8"));if(!S.configSnapshot)throw new Error("broker launch is missing its config snapshot");on(S.configSnapshot);const g=an(S);g.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await it(t);let R,A;const X=n(e=>{R!==void 0?R(e):A??=e},"onSignal");process.on("SIGTERM",()=>X("SIGTERM")),process.on("SIGINT",()=>X("SIGINT")),process.on("SIGUSR1",()=>{const e=process.env.CRTR_EXECUTION_ID;e!==void 0&&e!==""&&K().start(t,e)});let{session:W,services:P,resuming:de,runtime:G}=await vt(v,g);d("broker.startup.session_built");const k=(await ot(t)).node.review_binding?.review_id,T=Ne();Z=W;const F=yn;try{process.env.PI_PACKAGE_DIR=mn(),cn(P.settingsManager.getTheme(),J(),!1)}catch(e){b({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of rn(J()))b({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const j=Ze(t),_=new Mn(t),H=new Map,I=new An(t,e=>_.broadcast(e)),q=new Pn(t,e=>_.broadcast(e));On(e=>_.broadcast({type:"node_named",...e}));let D=!1,le=!1,Y,z,ce,m,V;const ee=new Nn;let L,me=n(()=>{},"notifyTurnAccepted"),ue=n(()=>{},"resetFrameState");const ne=Fn();let fe=n(()=>0,"pendingPromptDispatches"),pe;const B=Wn({runNode:T,session:n(()=>m.session(),"session"),isReplacing:n(()=>m.isReplacing(),"isReplacing"),pendingRebind:n(()=>m.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>m.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>fe(),"pendingDispatches"),turnAdmission:ne,prependDeferred:n(e=>$n(t,e),"prependDeferred"),onError:n(e=>b({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")});Zn(()=>m.session());const ge=B.drain;g.firstPrompt!==void 0&&g.firstPrompt!==""&&B.holdForKickoff(),globalThis[Bn]=B.start,globalThis[Un]=B.busy,m=new Hn({nodeId:t,cfg:g,session:W,services:P,runtime:G,registry:_,toolGroups:I,turnReplies:q,transcriptMessages:n(e=>ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>ce,"uiContext"),faultRetry:n(()=>V,"faultRetry"),projection:n(()=>L,"projection"),setActiveSession:n(e=>{if(Z=e,pe?.(),T||process.env.CRTR_RUN_ID){let r="stop",l,f=!1;pe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",l=void 0,f=!1,ee.started()),h.type==="agent_end"){const p=[...h.messages??[]].reverse().find(U=>U.role==="assistant");p&&(r=p.stopReason,l=En(p)?void 0:kn(p),f=p.role==="assistant"&&Dn(p,e.model?.contextWindow))}h.type==="agent_settled"&&(ee.settled(e.sessionManager,{stop_reason:r,...l?{error:l}:{}},f),T&&(ke().then(()=>Kn(t,e)).catch(p=>{if(String(p?.message).startsWith("conversation_write_failed")){b({level:"error",event:"broker.exited",node_id:t,error:p,fields:{fault:"conversation_write_failed"}}),C("conversation_write_failed",1);return}b({level:"error",event:"broker.run_deferred_mail.settle_failed",error:p})}),queueMicrotask(()=>{m.session()===e&&ge()})))})}},"setActiveSession"),disposeAndExit:n((e,r)=>C(e,r),"disposeAndExit"),onSessionRebind:n(()=>{ue()},"onSessionRebind"),onReplacementIdle:n(()=>{T&&ge()},"onReplacementIdle"),reWelcomeAll:n(()=>te(),"reWelcomeAll")});const ve=n(async(e,r=!1)=>{const l=m.session(),f=$(l.model,l.thinkingLevel);if(f===null)return null;const h=await rt(t,{spec:f,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(g.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,g.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",g.modelExact=!0)),h.modelOverride},"persistModelChoice"),_e=n(async(e=!0,r,l=!1)=>{const f=m.session(),h=$(f.model,f.thinkingLevel),p=e?await ve(r,l):h;_.broadcast({type:"model_changed",model:ie(f.model)?void 0:f.model,spec:p})},"broadcastModelChanged");V=new In({nodeId:t,cfg:g,retryProbe:F,currentSession:n(()=>m.session(),"currentSession"),currentServices:n(()=>m.services(),"currentServices"),installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:$,broadcastModelChanged:_e,turnAdmission:ne,reWelcomeAll:n(()=>te(),"reWelcomeAll"),...T?{turnEnds:ee}:{}});const he=n(()=>{V.rearmIfStranded().catch(e=>{b({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");K().subscribe("resync",he),K().subscribe("fault-retry",he),L=new Gn({registry:_,faultRetry:V,installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),currentSession:n(()=>m.session(),"currentSession"),notifyTurnAccepted:n(()=>me(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:$});const Me=n(e=>{const r=m.session(),l=ae(r,k),f=dt(e.snapshotTail),h=l===void 0||f===void 0?l:l.slice(-f),p=h?.map(({message:N})=>N)??r.sessionManager.buildSessionContext().messages,U=I.summaries(),ye=h!==void 0&&f!==void 0?ft(p):void 0,Ie=ye===void 0?U:Object.fromEntries(Object.entries(U).filter(([N])=>ye.has(N)));return{messages:p,...h===void 0?{}:{messageIds:h.map(({id:N})=>N)},messageVisibility:h?.map(({visibility:N})=>N)??p.map(()=>"visible"),turnVisibility:xn(),stats:r.getSessionStats(),state:{model:ie(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{..._.displaySnapshot()},toolGroupSummaries:Ie,turnReplies:q.snapshot(),workingActivity:L.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),we=n(e=>{const r=e.role==="controller"?H.values().next().value:void 0;_.sendFrame(e,{type:"welcome",snapshot:Me(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:J()},!0)},"sendWelcome"),Ae=n(e=>{const r=[...H.values()];for(let l=1;l<r.length;l++)_.sendFrame(e,r[l].request)},"replayExtraPendingDialogsTo"),te=n(()=>{try{const e=m.session();q.seed(ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){b({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}_.forEachHelloed(we)},"reWelcomeAll"),Se=n(async e=>{if(D)return;D=!0;const r=K().latestNode;r!==void 0&&(r.intent==="idle-release"||r.status==="done")&&Qn(t,process.env.CRTR_EXECUTION_ID??null),K().stop(),e===0&&await ke().catch(l=>{e=1,b({level:"error",event:"broker.exited",node_id:t,error:l,fields:{fault:"conversation_write_failed"}})}),I.persistPendingSummary(),L.dispose(),mt();try{Y?.close(),z?.close()}catch{}i.close(),_.dispose();try{Re(j)&&Te(j)}catch{}_.clearAttachState(),await nn(),process.exit(e)},"completeExit"),C=n((e,r=0)=>{if(D)return;const l=e==="shutdown-hook"||e==="shutdown-after-settle";if(l&&I.finishOpenToolGroup(!0),l&&(I.hasSummaryTasks()||q.hasTasks())){if(le)return;le=!0,Promise.allSettled([I.waitForSummaryTasks(),q.waitForTasks()]).finally(()=>Se(r));return}Se(r)},"disposeAndExit");globalThis[Ln]=C,ce=_t({writable:n(()=>_.writableClients(),"writable"),forward:n((e,r)=>_.sendFrame(e,r),"forward"),pending:H,broadcast:n(e=>_.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>L.knownStreamWait(e),"onKnownStreamWait")}),m.setRebindSession(),await m.enqueueRebind(W,P),d("broker.startup.extensions_bound");const x=jn({nodeId:t,registry:_,toolGroups:I,projection:L,rebind:m,boundaryReviewId:k,pendingDialogs:H,sendWelcome:we,replayExtraPendingDialogsTo:Ae,reWelcomeAll:te,disposeAndExit:C,persistModelChoice:ve,broadcastModelChanged:_e,registryOf:se,formatModelSpec:$,formatExactModelSpec:lt,turnAdmission:ne,memoryInventory:y,runNode:T,onKickoffAdmitted:B.releaseKickoff});me=x.notifyTurnAccepted,ue=x.resetForSession,fe=x.pendingPromptDispatches;const Pe=2500;let re=!1;const Oe=n(async e=>{if(D||re)return;if(re=!0,m.isAgentRunActive()||m.session().isStreaming||x.pendingPromptDispatches()>0){const l=Date.now()+Pe;for(;x.pendingPromptDispatches()>0&&!m.session().isStreaming&&Date.now()<l;)await new Promise(f=>setTimeout(f,25));if(m.session().isStreaming){const f=l-Date.now();if(f>0){let h;try{Yn(),await Promise.race([m.session().abort().then(()=>!0,()=>!1),new Promise(U=>{h=setTimeout(()=>U(!1),f)})])&&await Ce(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(x.pendingPromptDispatches()>0||m.isAgentRunActive())&&await Ce(t,{event:"interrupted"})}C(e)},"abortAndExit");if(R=n(e=>{Oe(e)},"signalTeardown"),A!==void 0){R(A);return}try{Re(j)&&Te(j)}catch{}const be=n(e=>{const r=_.create(e);e.on("data",f=>{let h;try{h=r.decoder.push(f)}catch(p){p instanceof at?(_.sendFrame(r,{type:"error",code:"frame_overflow",message:p.message}),_.dropClient(r,`frame overflow: ${p.message}`)):_.dropClient(r,`decoder error: ${String(p)}`);return}for(const p of h)try{qn(x,r,p)}catch{}});const l=n(()=>{_.removeClient(r)},"drop");e.on("close",l),e.on("error",()=>{})},"serveViewer");Y=We(be),gn()!==void 0&&(z=new Ge({host:"::",port:qe,path:"/view",maxPayload:st.maxLineBytes}),z.on("connection",e=>be(je(e))),z.on("error",e=>{D||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))})),Y.on("error",e=>{D||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))}),Y.listen(j,async()=>{Promise.all([Q(t,{op:"clear",link:"viewer\u2194broker"}),Q(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await V.recoverOnStartup()}catch(r){b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),C("recovery-startup-failed",1);return}if(!(D||re))if(e==="none"&&g.firstPrompt!==void 0&&g.firstPrompt!==""){const r=et(process.env[nt]);r!==null&&tt(g.firstPrompt,r);try{await vn(t)}catch(f){b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:f,fields:{operation:"attachments_fetch"}}),C("attachments-fetch-failed",1);return}const l=process.env.CRTR_KICKOFF_MESSAGE_IDS;x.kickoff(g.firstPrompt,l?JSON.parse(l):[])}else B.releaseKickoff()}),_.persistAttachState()}n(kr,"runBroker");function ft(t){const o=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const u of s.content)u!==null&&typeof u=="object"&&u.type==="toolCall"&&typeof u.id=="string"&&o.add(u.id);return o}n(ft,"toolCallIds");function ae(t,o){const s=t.sessionManager,u=Tn(s);return u!==void 0&&Vn(u.map(({message:i})=>i)),u===void 0?void 0:Cn(u,{boundaryReviewId:o,sessionEntries:s.getEntries?.()})}n(ae,"snapshotMessages");function xe(){const t=Be();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(xe,"currentBrokerNodeId");async function pt(t,o){const s=_n(o.model,Fe(),o.modelExact===!0);if(s===void 0)return;const u=se(t),i={cwd:Le()??o.cwd,profileId:Ue()},a=await Sn(s,u,i);if(a!==void 0)throw await Q(xe(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const c=await hn(s,i.cwd,i.profileId),d=wn(s.spec);for(const v of c){const w=u.find(v.providerId,v.modelId);if(w===void 0)continue;const S=d?.providerId===v.providerId&&d.modelId===v.modelId?d.thinkingLevel??(v.thinkingLevel===void 0?void 0:"off"):v.thinkingLevel;return{model:w,thinkingLevel:S}}if(o.modelExact===!0){const v=c.map(w=>`'${w.providerId}/${w.modelId}' unregistered`).join("; ");throw await Q(xe(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${o.model}' is unavailable \u2014 refusing to substitute (${v})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}b({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:c.map(v=>({provider:v.providerId,model:v.modelId,reason:"unregistered"})).slice(0,16)}})}n(pt,"resolveLaunchModel");function gt(t){let o=!0;return{runtime:new Proxy(t,{get(u,i,a){return o&&i==="getAvailableSnapshot"?()=>[]:o&&i==="getAvailable"?async()=>[]:o&&i==="getModel"?()=>{}:Reflect.get(u,i,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(gt,"modelLessRegistry");async function vt(t,o){const s=J(),u=n(async S=>{const g=await Je.create({credentials:new fn,modelsPath:Ee(S.agentDir,"models.json")});pn(g);const y=await t.createAgentSessionServices({cwd:S.cwd,agentDir:S.agentDir,modelRuntime:g,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(O=>({...O,extensions:O.extensions.filter(k=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(k.path))}),"extensionsOverride")}}),R=y.resourceLoader.getExtensions();if(o.extensionPaths.some(O=>oe.includes(O))){const O=new Set(R.extensions.map(T=>T.path)),k=oe.filter(T=>!O.has(T));if(k.length>0){const T=R.errors.filter(F=>oe.includes(F.path)).map(F=>`${F.path}: ${F.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${k.join(", ")}${T===""?"":` (${T})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const A=await pt(y,o),X=A?.model,W=A?.thinkingLevel,P=A===void 0?gt(y.modelRuntime):void 0,de=P!==void 0?{...y,modelRuntime:P.runtime}:y,G=await t.createAgentSessionFromServices({services:de,sessionManager:S.sessionManager,model:X,thinkingLevel:W,...ut(o.tools,$e()),sessionStartEvent:S.sessionStartEvent});return Xn(G.session),un(G.session),P?.reveal(),{...G,services:y}},"buildForManager"),i=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(i===void 0||i==="")&&o.resumeSessionId!==void 0&&o.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${o.resumeSessionId}' (pi_session_file was never captured for this node)`);const c=!a&&i!==void 0&&i!=="",d=c&&o.newCycle===!0,v=c&&!d;let w;if(a)w=await t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(v||d){if(w=await t.SessionManager.open(i),d){const S=w.getLeafId();w.resetLeaf(),w.appendCustomEntry(Rn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:S})}}else w=await t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const S=n(async y=>{const R=await u({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...R,diagnostics:R.services.diagnostics??[]}},"factory"),g=await t.createAgentSessionRuntime(S,{cwd:o.cwd,agentDir:s,sessionManager:w});return{session:g.session,services:g.services,resuming:v,runtime:g}}const E=await u({cwd:o.cwd,agentDir:s,sessionManager:w});return{session:E.session,services:E.services,resuming:v,runtime:void 0}}n(vt,"buildBrokerSession");function _t(t){const o=n((i,a,c,d)=>{if(d?.signal?.aborted)return Promise.resolve(i);const v=t.writable();return v.length===0?Promise.resolve(i):new Promise(w=>{let E;const S=n(()=>{E!==void 0&&clearTimeout(E),d?.signal?.removeEventListener("abort",g),t.pending.delete(a.id)},"cleanup"),g=n(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},"onAbort");d?.signal?.addEventListener("abort",g,{once:!0});const y=d?.timeout!==void 0?d.timeout:ct;E=setTimeout(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},y),typeof E.unref=="function"&&E.unref(),t.pending.set(a.id,{request:a,resolve:n(R=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(c(R))},"resolve")});for(const R of v)t.forward(R,a)})},"dialogPromise"),s=n(()=>{},"noop");return{[bn]:t.onKnownStreamWait??(i=>()=>{}),get theme(){const i=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(i==null)throw new Error("Theme not initialized. Call initTheme() first.");return i},select:n((i,a,c)=>o(void 0,{type:"extension_ui_request",id:M(),method:"select",title:i,options:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"select"),confirm:n((i,a,c)=>o(!1,{type:"extension_ui_request",id:M(),method:"confirm",title:i,message:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,c),"confirm"),input:n((i,a,c)=>o(void 0,{type:"extension_ui_request",id:M(),method:"input",title:i,placeholder:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"input"),editor:n((i,a)=>o(void 0,{type:"extension_ui_request",id:M(),method:"editor",title:i,prefill:a},c=>"cancelled"in c&&c.cancelled?void 0:"value"in c?c.value:void 0),"editor"),setStatus:n((i,a)=>t.broadcast({type:"extension_ui_request",id:M(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:n((i,a,c)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:M(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:c?.placement})},"setWidget"),setTitle:n(i=>t.broadcast({type:"extension_ui_request",id:M(),method:"setTitle",title:i}),"setTitle"),notify:n((i,a)=>{const c=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:M(),method:"notify",message:i,notifyType:c})},"notify"),onTerminalInput:n(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:s,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}n(_t,"makeBrokerUiContext");export{Ar as REVIEW_BOUNDARY_NAVIGATION_CODE,Mr as ReviewBoundaryNavigationError,ut as brokerToolOptions,vt as buildBrokerSession,mt as disposeActiveSession,_t as makeBrokerUiContext,kr as runBroker,ae as snapshotMessages};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
2
|
-
`,credentialed:JSON.stringify(o)!==JSON.stringify(n(o))}}a(
|
|
3
|
-
`,{atomic:!0,mode:432}),b(S,ne,432);const oe=p(Y(e),`token-${u}`),
|
|
1
|
+
var xe=Object.defineProperty;var a=(e,t)=>xe(e,"name",{value:t,configurable:!0});import{assertGranteeRunsHere as Te}from"./unsandboxed.js";import{spawn as Oe}from"node:child_process";import{mkdirSync as ue,existsSync as j,unlinkSync as fe,openSync as G,closeSync as C,writeSync as Ne,chmodSync as De,lstatSync as Ce}from"node:fs";import{ensureAppSpace as Le}from"../spaces/space.js";import{sandboxCacheEnv as Ae}from"../spaces/cache-env.js";import{compileLaunch as Be,launchStillGranted as $e}from"../spaces/mounts.js";import{grantsGeneration as de}from"../grants/mirror.js";import{LAUNCHER_SOCKET as q}from"../../launcher/spec.js";import{launcherRequest as F}from"../../launcher/client.js";import{piAgentDir as me}from"./package-health.js";import{existsBeneath as z,readFileBeneath as je,readTextBeneathIfExists as Ge,setModeBeneath as b,withDirBeneath as V,writeFileBeneath as M}from"../spaces/open-beneath.js";import{dirname as X,join as p,resolve as Fe,isAbsolute as Me}from"node:path";import{fileURLToPath as pe}from"node:url";import{connectViewSocket as Ke}from"./view-socket.js";import{appSpace as K}from"../layout.js";import{readConfig as Je,readMergedLaunchConfig as He}from"../config.js";import{loadRotationConfig as Ue}from"../subscription-state.js";import{getNode as g}from"../canvas/index.js";import{withCanvasWrite as We}from"../canvas/db.js";import{requestExecutionStop as qe}from"../canvas/executions.js";import{scopesFilePath as Q,crtrHome as he,nodeRunDir as Y,nodeRunJobDir as ze,jobDir as Ve,viewSocketPath as Xe,nodeAgentDir as Qe,contextDir as Ye,nodeHome as Ze}from"../canvas/paths.js";import{encodeFrame as we}from"./broker-protocol.js";import{buildBrokerEnv as Ie}from"./spawn-env-rows.js";import{hostExecPathFresh as er}from"./branded-host.js";import{isPidAlive as Z,killProcessTreePids as ge,isAnyPidAlive as rr,captureTeardownSnapshot as tr}from"../canvas/pid.js";import{assertMandatoryCanvasExtensions as nr}from"./canvas-extensions.js";import{appMemoryFull as or,appMemoryTooSmall as ir,boundFleet as sr,brokerCapReached as ar,brokerThresholdsForDaemon as cr}from"./fleet.js";import{admitBrokerMemory as lr}from"./memory-admission.js";import{emitEvent as E}from"../events/emit.js";import{bindBrokerEventSource as ur,eventSource as fr}from"../events/source.js";import{envBrokerEngine as dr}from"../../shared/env.js";import{conversationIdFromPath as mr,conversationStore as pr,ConversationNotFoundError as Ee}from"../conversation-store/index.js";import{mintNodeToken as hr}from"../canvas/node-tokens.js";import{personId as wr}from"../canvas/person.js";function J(){const e=X(pe(import.meta.url));return p(e,"broker-cli.js")}a(J,"resolveBrokerEntry");const gr="@earendil-works/pi-coding-agent";function _e(){const e=p(me(),"models.json"),t=Ge(X(e),e);if(t===null)return null;const o=JSON.parse(t),n=a(r=>Array.isArray(r)?r.map(n):r===null||typeof r!="object"?r:Object.fromEntries(Object.entries(r).filter(([s])=>!/^(apiKey|authorization|headers|token|secret)$/i.test(s)).map(([s,c])=>[s,n(c)])),"scrub");return{text:t,clean:`${JSON.stringify(n(o),null,2)}
|
|
2
|
+
`,credentialed:JSON.stringify(o)!==JSON.stringify(n(o))}}a(_e,"scrubbedBrokerModels");function Er(e,t){const o=p(me(),"models.json"),n=p(t,"models.json"),r=_e();if(r!==null){if(o===n&&r.text!==r.clean){if(r.credentialed)throw new Error("terminal models.json contains credentials; move them into daemon secrets");b(e,n,432);return}M(e,n,r.clean,{atomic:!0,mode:432}),b(e,n,432)}}a(Er,"writeBrokerModels");function ke(e){return e.env.CRTR_BROKER_ENGINE??dr()}a(ke,"resolveEngineSpec");function ve(e){return e.includes("/")||e.endsWith(".jsonl")}a(ve,"isPlainLaunchSessionPath");function _r(e,t){return Me(e)?e:Fe(t,e)}a(_r,"resolvePlainLaunchPath");async function kr(e,t,o,n){if(o==="--session"&&!ve(n))throw new Error(`[broker] refusing to launch ${e}: launch recipe passes bare --session id '${n}' \u2014 the broker fatally rejects bare ids; pass the .jsonl path instead.`);if(!ve(n))return;const r=_r(n,t),s=mr(r);try{if(s===null)throw new Ee(r);await pr().header(s)}catch(c){if(!(c instanceof Ee))throw c;const l=o==="--session"?"session file":"fork source";throw new Error(`[broker] refusing to launch ${e}: launch recipe references missing ${l} '${n}' (${r})`)}}a(kr,"preflightLaunchSessionArg");async function vr(e,t,o){const n=_e();return JSON.stringify({...t,configSnapshot:{user:Je("user"),launch:He(o,t.env.CRTR_PROFILE_ID||null),rotation:await Ue()},scopes:(await g(e))?.scopes??null,models:n===null?null:JSON.parse(n.clean)})}a(vr,"brokerLaunchJson");async function yr(e,t,o,n){const r=Y(e);ue(r,{recursive:!0}),process.platform==="linux"&&j(q)&&Ce(r).uid===process.getuid()&&De(r,504);const s=p(r,"broker-launch.json");M(r,s,n??await vr(e,t,o),{atomic:!0}),t.env.CRTR_SCOPES_FILE!==void 0&&M(r,Q(e),JSON.stringify((await g(e))?.scopes??[]),{atomic:!0});const c=je(r,s).toString("utf8"),l=JSON.parse(c);if(!Array.isArray(l.argv))throw new Error(`[broker] refusing to launch ${e}: broker-launch.json is missing the argv array`);const k=ke(t);try{const u=import.meta.resolve(k);if(u.startsWith("file:")&&!j(pe(u)))throw new Error(`resolved to missing file ${u}`)}catch(u){throw new Error(`[broker] refusing to launch ${e}: cannot resolve broker engine '${k}' from ${J()} \u2014 ${u.message}`)}const f=l.argv,N=[];for(let u=0;u<f.length;u++){const P=f[u];if(P==="-e"){const L=f[++u];L!==void 0&&N.push(L);continue}if(P!=="--session"&&P!=="--fork")continue;const T=f[++u];T!==void 0&&await kr(e,o,P,T)}try{nr(N)}catch(u){throw new Error(`[broker] refusing to launch ${e}: ${u.message}`)}}a(yr,"preflightBrokerLaunch");const Sr=2e3,br=2e3,Rr=150;async function H(e,t){const o=Date.now()+t;for(;rr(e);){const n=o-Date.now();if(n<=0)return!1;await new Promise(r=>setTimeout(r,Math.min(Rr,n)))}return!0}a(H,"waitForTreeExit");async function Pr(e,t,o){return e.length===0?{confirmed:!0}:o&&await H(e,Sr)?{confirmed:!0}:(ge(e,"SIGTERM",t),await H(e,br)?{confirmed:!0}:(ge(e,"SIGKILL",t),await H(e,5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`broker process tree for ${e.join(", ")} remained alive after SIGKILL`)}))}a(Pr,"terminateBrokerTree");async function ye(e,t){const o=await g(e),n=o?.pi_pid,r=n!=null?tr(n,o?.pi_pid_identity??null,t.excludePid):null;return r?.reused===!0&&E({level:"warn",event:"broker.teardown.pid_reuse_refused",node_id:e,fields:{recorded_pid:n,expected_identity:o?.pi_pid_identity??null}}),{tree:r?.tree??[],identities:r?.identities??null,nodeId:e,launcherPid:j(q)&&r?.tree.includes(n)?n:null}}a(ye,"prepareBrokerTeardown");async function Se(e){if(e.launcherPid!==null){try{await F({operation:"stop",pid:e.launcherPid})}catch(t){return Z(e.launcherPid)?{confirmed:!1,error:t instanceof Error?t:new Error(String(t))}:{confirmed:!0}}return await H([e.launcherPid],5e3)?{confirmed:!0}:{confirmed:!1,error:new Error(`launcher pid ${e.launcherPid} remained alive`)}}return new Promise(t=>{let o=!1,n=!1;const r=a(k=>{n||(n=!0,t(k))},"settle"),s=a(()=>{try{fe(Xe(e.nodeId))}catch{}},"cleanupSocket"),c=a(k=>{Pr(e.tree,e.identities,k).then(r,f=>r({confirmed:!1,error:f instanceof Error?f:new Error(String(f))}))},"finish"),l=Ke(e.nodeId);l.once("error",()=>{o||(s(),c(!1))}),l.once("connect",()=>{o=!0;try{l.write(we({type:"hello",role:"controller",client_id:`daemon-shutdown-${process.pid}`})),l.write(we({type:"shutdown"}))}catch{}l.end(),s(),c(!0)})})}a(Se,"runPreparedBrokerTeardown");async function ct(e,t={},o){let n;try{await qe(e,{afterTurn:t.startAfter!==void 0,reason:t.reason??"teardown"}),n=await ye(e,t)}catch(r){const s={confirmed:!1,error:r instanceof Error?r:new Error(String(r))};return E({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:s.error}),s}return await new Promise(r=>{const s=a(()=>{Se(n).then(async c=>{if(c.confirmed){if(o!==void 0)try{await o()}catch(l){E({level:"error",event:"broker.teardown.after_failed",node_id:e,error:l})}}else E({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:c.error});r(c)},c=>{const l={confirmed:!1,error:c instanceof Error?c:new Error(String(c))};E({level:"error",event:"broker.teardown.unconfirmed",node_id:e,error:l.error}),r(l)})},"run");t.startAfter===void 0?setImmediate(s):t.startAfter.then(s,s)})}a(ct,"requestBrokerTeardown");function be(){return process.platform==="linux"&&j(q)}a(be,"isolatedBrokerLauncherAvailable");const lt={async launch(e,t,o){if(Te((await g(e))?.grantee),(await g(e))?.isolated===!0&&!be())throw new Error("isolated broker requires the Linux root launcher");await yr(e,t,o.cwd,o.launchJson);const n=sr();if(!await n.reserveSlot(e))throw ar(cr().automaticReviveCap,await n.occupancy());let r=null,s,c=!1;try{const l=Ve(e);ue(l,{recursive:!0}),r=G(p(l,"broker.log"),"a");const k=ke(t),f={...await Ie(t),CRTR_BROKER_ENGINE:k};if(k!==gr){const i=t.env.NODE_OPTIONS??process.env.NODE_OPTIONS;i!==void 0&&(f.NODE_OPTIONS=i);const d=t.env.CRTR_TEST_PG_URL??process.env.CRTR_TEST_PG_URL;d!==void 0&&(f.CRTR_TEST_PG_URL=d)}fr()===void 0&&ur(e);const N=(await g(e))?.run_id;if(N){const i=await g(N);if(!i||i.deleting_at)throw new Error("run is deleting")}const u=t.env.CRTR_EXECUTION_ID;if(!u)throw new Error("broker launch has no execution id");const P=await We(i=>hr(i,u,e,new Date().toISOString())),T=be();if((await g(e))?.isolated===!0&&!T)throw new Error("isolated broker requires the Linux root launcher");if(process.platform==="linux"&&process.env.CRTR_LAUNCHER_SOCKET&&!T)throw new Error("root launcher socket is unavailable; refusing an unsandboxed broker");if(T){const i=await g(e);if(!i)throw new Error(`missing node ${e}`);const d=i.grantee??"app:terminal",x=await lr(e,{useMemo:!1});if(x.verdict==="denied")throw or(x);if(x.verdict==="too_small")throw ir(x);const v=await Le(d);Object.assign(f,Ae(d));const y={uid:process.getuid(),gid:v.gid},w=Y(e);for(const[m,_]of[[K(d).nodes,Qe(e,d)],[K(d).nodes,Ye(e,d)],[w,ze(e)]])V(m,_,()=>{},!0),b(m,_,1528,y);b(w,p(w,"broker-launch.json"),416,y),z(w,Q(e))&&b(w,Q(e),416,y);const re=p(w,"system-prompt.md");z(w,re)&&b(w,re,432,y);for(const m of["output-schema.json","situational-context.md"]){const _=p(w,m);z(w,_)&&b(w,_,432,y)}const te=i.isolated===!0,S=Ze(e,d,te);te&&(V(K(d).nodes,S,()=>{},!0),b(K(d).nodes,S,1528,y),f.HOME=S,f.PI_CODING_AGENT_DIR=p(S,".pi","agent"));const W=p(S,".pi","agent");V(S,W,()=>{},!0),Er(S,W);const ne=p(W,"settings.json"),Re=p(X(J()),"../../builtin-pi-packages/pi-crtr-extensions");M(S,ne,`${JSON.stringify({packages:[Re]})}
|
|
3
|
+
`,{atomic:!0,mode:432}),b(S,ne,432);const oe=p(Y(e),`token-${u}`),B=G(oe,"wx+",384);fe(oe),Ne(B,P);const ie=[G(`/proc/self/fd/${B}`,"r"),G(`/proc/self/fd/${B}`,"r")];C(B);const se={nodeId:e,app:d,sub:i.sub??wr(),grantId:i.grant_id??null,scopes:i.scopes??null,isolated:i.isolated===!0,...i.isolated===!0?{cwd:i.cwd}:{},command:[process.execPath,J(),"--canvas-home",he(),"--epoch",n.epoch(),e],env:Object.fromEntries(Object.entries({...f,...i.isolated===!0?{PWD:i.cwd}:{}}).filter(m=>m[1]!==void 0)),auditMissing:a(m=>E({level:"warn",event:"broker.mount.missing",node_id:e,fields:{source:m}}),"auditMissing")};try{let m;for(const D of ie){const $=await de(),h=await Be(se);h.broker=!0;const R=await F({operation:"launch",spec:h},[D]);if(!("pid"in R))throw new Error("launcher did not return a pid");if(await de()===$||await $e(se,h)){m=R.pid;break}E({level:"info",event:"broker.launch.regranted",node_id:e,fields:{pid:R.pid}}),await F({operation:"stop",pid:R.pid,signal:"SIGKILL"}).catch(()=>{})}if(m===void 0)throw new Error("grant changed during every launch attempt");const _=m,Pe=Date.now(),ae=new Promise(D=>{const $=setInterval(()=>{Z(_)||(clearInterval($),F({operation:"exit.status",pid:_}).then(h=>"oomKilled"in h?{oomKilled:h.oomKilled,code:h.code??null,signal:h.signal??null}:{oomKilled:!1,code:null,signal:null},()=>({oomKilled:!1,code:null,signal:null})).then(({oomKilled:h,code:R,signal:le})=>{E({level:h||R!==0?"warn":"info",event:"broker.exited",node_id:e,fields:{pid:_,code:R,signal:le,uptime_ms:Date.now()-Pe,oom_killed:h}}),D({code:R,signal:le,...h?{oomKilled:!0}:{}})}))},250);$.unref()});C(r),r=null;const ce={pid:_,exited:ae};return n.register(e,ce),c=!0,ae.then(async D=>await n.onChildExit(e,D,u)),ce}finally{for(const m of ie)C(m)}}const L=await er(),O=Oe(L,[J(),"--canvas-home",he(),"--epoch",n.epoch(),e],{cwd:o.cwd,detached:!0,stdio:["ignore",r,r,"pipe"],env:f});s=O;const A=O.stdio[3];if(!A||!("end"in A))throw new Error("broker token pipe did not open");A.on("error",i=>E({event:"broker.token_pipe.failed",level:"error",node_id:e,error:i})),A.end(P),C(r),r=null;const I=Date.now(),ee=new Promise(i=>{let d=!1;const x=a(v=>{d||(d=!0,i(v))},"finish");O.once("exit",(v,y)=>{E({level:v===0?"info":"warn",event:"broker.exited",node_id:e,fields:{code:v,signal:y,uptime_ms:Date.now()-I}}),x({code:v,signal:y})}),O.once("error",v=>{E({level:"error",event:"broker.launch.failed",node_id:e,error:v,fields:{uptime_ms:Date.now()-I}}),x({code:null,signal:null})})});O.unref();const U={pid:O.pid??null,exited:ee};return U.pid!==null&&(n.register(e,U),c=!0,ee.then(async i=>await n.onChildExit(e,i,u))),U}catch(l){if(!c&&s?.pid!=null)try{s.kill("SIGTERM")}catch{}throw l}finally{c||n.releaseReservation(e),r!==null&&C(r)}},async isAlive(e){return Z((typeof e=="string"?await g(e):e)?.pi_pid)},async teardown(e,t={}){try{return Se(await ye(e,t))}catch(o){return Promise.resolve({confirmed:!1,error:o instanceof Error?o:new Error(String(o))})}},async signal(e,t){const o=(await g(e))?.pi_pid;if(o!=null)try{process.kill(o,t)}catch{}}};export{vr as brokerLaunchJson,lt as headlessBrokerHost,be as isolatedBrokerLauncherAvailable,yr as preflightBrokerLaunch,ct as requestBrokerTeardown};
|
|
@@ -13,6 +13,8 @@ export declare class BlaxelApiError extends Error {
|
|
|
13
13
|
readonly code: string | null;
|
|
14
14
|
constructor(status: number, code: string | null, message: string);
|
|
15
15
|
}
|
|
16
|
+
/** Blaxel's sandbox API uses this 404 when the workload URL itself no longer exists. */
|
|
17
|
+
export declare const isWorkloadUnavailable: (error: unknown) => error is BlaxelApiError;
|
|
16
18
|
export interface SandboxSpec {
|
|
17
19
|
name: string;
|
|
18
20
|
image: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var E=Object.defineProperty;var d=(s,o)=>E(s,"name",{value:o,configurable:!0});function h(s=process.env){const o=d(i=>{const f=s[i];if(!f)throw new Error(`${i} is required for the Blaxel runner`);return f},"need");return{apiKey:o("BLAXEL_API_KEY"),workspace:o("BLAXEL_WORKSPACE"),region:o("BLAXEL_REGION")}}d(h,"blaxelConfigFromEnv");class w extends Error{static{d(this,"BlaxelApiError")}status;code;constructor(o,i,f){super(f),this.status=o,this.code=i,this.name="BlaxelApiError"}}const b=d(s=>s instanceof w&&s.status===404&&s.code==="WORKLOAD_UNAVAILABLE","isWorkloadUnavailable");function $(s){const o=s.metadata.url;if(!o)throw new Error(`Blaxel sandbox ${s.metadata.name} has no url`);return{name:s.metadata.name,url:o,state:s.state??null,status:s.status??null}}d($,"toInfo");function A(s){const o=s.fetch??fetch,i=s.controlUrl??"https://api.blaxel.ai/v0",f=d(()=>({authorization:`Bearer ${s.apiKey}`,"x-blaxel-workspace":s.workspace,"content-type":"application/json"}),"headers");async function c(e,t,a,r=[]){const n=await o(e,{method:t,headers:f(),...a===void 0?{}:{body:JSON.stringify(a)}}),l=await n.text();let x=null;if(l!=="")try{x=JSON.parse(l)}catch{x={raw:l}}if(!n.ok&&!r.includes(n.status)){const p=x??{},m=typeof p.message=="string"?p.message:typeof p.error=="string"?p.error:l.slice(0,300);throw new w(n.status,typeof p.code=="string"?p.code:null,`Blaxel ${t} ${e} failed (${n.status}): ${m}`)}return{status:n.status,json:x}}d(c,"call");const u=encodeURIComponent;return{config:s,async createSandbox(e){const t=[...e.ports??[]].map(l=>({name:l.name,target:l.target,protocol:"HTTP"})),a={metadata:{name:e.name},spec:{runtime:{image:e.image,memory:e.memoryMb,...t.length>0?{ports:t}:{}},region:s.region}},{status:r,json:n}=await c(`${i}/sandboxes`,"POST",a,[409]);if(r===409){const l=await this.getSandbox(e.name);if(l===null)throw new Error(`Blaxel sandbox ${e.name} reported as existing but cannot be read`);return{...l,created:!1}}return{...$(n),created:!0}},async getSandbox(e){const{status:t,json:a}=await c(`${i}/sandboxes/${u(e)}`,"GET",void 0,[404]);return t===404?null:$(a)},async deleteSandbox(e){await c(`${i}/sandboxes/${u(e)}`,"DELETE",void 0,[404])},async startProcess(e,t){const{json:a}=await c(`${e.url}/process`,"POST",t);return a},async getProcess(e,t){const{status:a,json:r}=await c(`${e.url}/process/${u(t)}`,"GET",void 0,[404]);if(a===404){const n=r?.code;if(n==="WORKLOAD_UNAVAILABLE")throw new w(404,n,`Blaxel sandbox ${e.name} is unavailable`);return null}return r},async stopProcess(e,t){await c(`${e.url}/process/${u(t)}`,"DELETE",void 0,[404])},async killProcess(e,t){await c(`${e.url}/process/${u(t)}/kill`,"DELETE",void 0,[404])},async exec(e,t,a,r,n){return await this.startProcess(e,{name:t,command:a,waitForCompletion:!0,timeout:r,...n?{env:n}:{}})},async putFile(e,t,a,r="0644"){await c(`${e.url}/filesystem/${t.replace(/^\/+/,"").split("/").map(u).join("/")}`,"PUT",{content:a,permissions:r})},async ensurePreview(e,t,a){const{json:r}=await c(`${i}/sandboxes/${u(e)}/previews`,"POST",{metadata:{name:t},spec:{port:a,public:!1}},[409]),n=r?.spec?.url;if(n)return n;const x=(await c(`${i}/sandboxes/${u(e)}/previews`,"GET")).json.find(p=>p.metadata.name===t);if(!x)throw new Error(`Blaxel preview ${t} of ${e} not found`);return x.spec.url},async createPreviewToken(e,t,a){const{json:r}=await c(`${i}/sandboxes/${u(e)}/previews/${u(t)}/tokens`,"POST",{spec:{expiresAt:a.toISOString()}}),n=r.spec;return{token:n.token,expiresAt:n.expiresAt}}}}d(A,"createBlaxelClient");export{w as BlaxelApiError,h as blaxelConfigFromEnv,A as createBlaxelClient,b as isWorkloadUnavailable};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
1
|
+
var g=Object.defineProperty;var o=(t,a)=>g(t,"name",{value:a,configurable:!0});import{withCanvasWrite as R,openDb as I}from"../../../canvas/db.js";import{mintNodeToken as k}from"../../../canvas/node-tokens.js";import{BlaxelApiError as T,isWorkloadUnavailable as b}from"./client.js";const x=4180,l="view",S="node /opt/crtr/current/scripts/sandbox-start.mjs --wake",C=3,N=/^crtr-sandbox-start: failed (\S+)/m,m=o(t=>`broker-${t}`,"brokerProcessName"),f=o(t=>t.sandboxName??`${t.nodeId}-${t.attempt}`,"sandboxNameFor"),y=o(async t=>await R(a=>k(a,t.executionId,t.nodeId,new Date().toISOString())),"defaultMint");async function P(t){return(await(await I()).prepare("SELECT DISTINCT sandbox_name FROM executions WHERE node_id = ? AND sandbox_name IS NOT NULL").all(t)).map(u=>u.sandbox_name)}o(P,"defaultSandboxNames");function $(t){const a=`${t.logs}
|
|
2
2
|
${t.stderr}
|
|
3
|
-
${t.stdout}`;return{state:"failed",reason:
|
|
3
|
+
${t.stdout}`;return{state:"failed",reason:N.exec(a)?.[1]??"start_failed",code:t.exitCode}}o($,"failureOf");function v(t){const{client:a}=t,u=(t.stopGraceS??10)*1e3,E=new Map;async function d(n){return await a.getSandbox(f(n))}return o(d,"sandboxOf"),{kind:"blaxel",async start(n){const r=await t.launchContext(n),e=f(n),s=await a.createSandbox({name:e,image:r.image,memoryMb:r.memoryMb,ports:[{name:l,target:x}]}),i=m(n.executionId);if((await a.getProcess(s,i))?.status==="running")return{pid:null,exited:null};await a.ensurePreview(e,l,x);const w=await(t.mintToken??y)(n),p={...r.secrets,CRTR_API_URL:r.apiUrl,CRTR_EXECUTION_ID:n.executionId,CRTR_NODE_TOKEN:w,CRTR_RELEASE:n.release,CRTR_RELEASE_URL:r.releaseUrl,CRTR_RELEASE_SHA256:r.releaseSha256};return await a.startProcess(s,{name:i,command:t.bootstrap(),env:p,waitForCompletion:!1}),{pid:null,exited:null}},async wake(n){const r=await d(n);if(r===null)return"no_broker";try{const e=await a.exec(r,`wake-${n.executionId}-${Date.now()}`,`${S} ${n.executionId}`,30);if(e.exitCode===0)return"signalled";if(e.exitCode===C)return"no_broker";throw new Error(`wake of ${n.executionId} failed (exit ${e.exitCode}): ${(e.stderr||e.logs).slice(0,300)}`)}catch(e){if(b(e))return"no_broker";throw e}},async stop(n,r){try{const e=await d(n);if(e===null)return{confirmed:!0};const s=m(n.executionId),i=o(async()=>(await a.getProcess(e,s))?.status==="running","running");if(!await i())return{confirmed:!0};await a.stopProcess(e,s);const c=Date.now()+u;for(;Date.now()<c;){if(!await i())return{confirmed:!0};await new Promise(w=>setTimeout(w,250))}return await a.killProcess(e,s),{confirmed:!await i()}}catch(e){return{confirmed:!1,error:e instanceof Error?e:new Error(String(e))}}},async status(n){try{const r=await d(n);if(r===null)return{state:"gone"};const e=await a.getProcess(r,m(n.executionId));return e===null?{state:"gone"}:e.status==="running"?{state:"running",pid:null}:e.status==="failed"||e.status==="completed"&&e.exitCode!==0?$(e):{state:"gone"}}catch(r){return b(r)?{state:"gone"}:{state:"unknown",error:r instanceof Error?r.message:String(r)}}},async delete(n){for(const r of await(t.sandboxNamesForNode??P)(n))await a.deleteSandbox(r)},async viewerAddress(n){const r=f(n),e=E.get(r);if(e&&e.expiresAt-Date.now()>5*6e4)return _(e.url,e.token);const s=await a.ensurePreview(r,l,x),i=new Date(Date.now()+60*6e4),{token:c}=await a.createPreviewToken(r,l,i);return E.set(r,{url:s,token:c,expiresAt:i.getTime()}),_(s,c)},async sandboxState(n){return(await d(n))?.state??null}}}o(v,"createBlaxelRunner");function _(t,a){return{kind:"wss",url:`${t.replace(/^https:/,"wss:")}/view`,headers:{"x-blaxel-preview-token":a}}}o(_,"viewer");export{x as BROKER_VIEW_PORT,T as BlaxelApiError,C as EXIT_NO_BROKER,N as FAILURE_LINE,S as WAKE_COMMAND,m as brokerProcessName,v as createBlaxelRunner,f as sandboxNameFor};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var we=Object.defineProperty;var d=(e,o)=>we(e,"name",{value:o,configurable:!0});import{accessSync as me,constants as he}from"node:fs";import{isAbsolute as pe,resolve as _e,join as ke}from"node:path";import{appSpace as ve}from"../layout.js";import{ApiError as ee}from"../../api/errors.js";import{spawnNode as ye,forkSourceNode as ge,currentNodeContext as be,rootOfSpine as xe,newNodeId as Ce,preflightNodeId as Ee}from"./nodes.js";import{resolveProfileOperand as Se}from"../profiles/manifest.js";import{selectProfileForCwd as Oe,selectProfileForCwdReadOnly as Re}from"../profiles/select.js";import{buildLaunchSpecAsync as ne,buildPiArgv as $e}from"./launch.js";import{runsOnBlaxel as Fe,sandboxWorktreeRequest as Ie}from"../../daemon/api/environment-of.js";import{createManagedWorktreeAsync as Be,rollbackManagedWorktreeAsync as Ne}from"../worktree-mutation-async.js";import{usage as u,brokerLaunchFailed as B}from"../errors.js";import{writeGoal as Pe}from"./kickoff.js";import{appendSituationalContext as De,formatSituationalProse as Te}from"./situational-context.js";import{ensureRoadmap as Le}from"./roadmap.js";import{buildWakeBearings as Ae}from"./bearings.js";import{encodeKickoffOrigin as Me,KICKOFF_ORIGIN_ENV as We}from"./stamp/protocol.js";import{ExecutionCapReached as je,beginExecution as ze,crtrHome as He,getNode as l,fullName as oe,jobDir as Ke,recordExecutionPid as Ge,abortExecution as M,setFrozen as W}from"../canvas/index.js";import{contextDir as j,nodeAgentDir as z}from"../canvas/node-agent-paths.js";import{copyTreeBeneath as Ue}from"../spaces/open-beneath.js";import{conversationIdFromPath as N,conversationStore as E}from"../conversation-store/index.js";import{appMemoryTooSmall as Ve,boundFleet as Xe,brokerThresholdsForDaemon as re}from"./fleet.js";import{admitBrokerMemory as qe}from"./memory-admission.js";import{emitEvent as H}from"../events/emit.js";import{blaxelEnvironmentOf as Ye}from"./blaxel-environment.js";import{openViewerWindow as Je,focusOf as Qe,windowOfPane as Ze}from"./placement.js";import{waitForBrokerViewSocket as en}from"./placement-tmux.js";import{transition as k}from"./lifecycle.js";import{beginBootFaultAttempt as nn}from"../canvas/recovery.js";import{headlessBrokerHost as K}from"./host.js";import{ensureDaemon as on}from"../../daemon/manage.js";import{readConfig as rn}from"../config.js";import{modelRequestFromConfig as tn,unregisteredConcreteModel as an}from"../model-routes.js";import{openModelRegistry as dn}from"./model-registry.js";import{MODEL_SPEC_NEXT as sn}from"./model-selection.js";import{forkNodeLedger as cn}from"./ledger.js";import{appRungForGrant as ln}from"../llm/app-rungs.js";import{APP_FAMILY as G}from"../model-routes.js";import{discoverLifecycleHookRegistry as fn}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as un}from"../command-hooks/transport/exec-lifecycle.js";import{someAsync as wn}from"../async-array.js";import{checkStart as mn}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 hn(e,o,a){try{return await K.launch(e,o,a)}catch(i){try{await k(e,"crash",{reason:"launch_failed",outcome:v(i)})}catch{}const t=i.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(hn,"launchBrokerOrCrash");async function pn(e,o){try{await k(e,"crash",{reason:"launch_failed",outcome:v(o)})}catch{}try{K.teardown(e)}catch{}}d(pn,"crashAndTearDown");async function _n(e){const o=(await E().list()).map(({conversation_id:t,path:s})=>({id:t,path:s})),a=o.filter(t=>t.id===e),i=a.length>0?a:o.filter(t=>t.id.startsWith(e));if(i.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(i.length>1)throw u(`--fork-from '${e}': ambiguous \u2014 ${i.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 i[0].path}d(_n,"resolveSessionUuid");async function ie(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 i=N(pe(o)?o:_e(process.cwd(),o));if(i===null)throw u(`--fork-from '${o}': invalid conversation path.`,{next:"Pass a conversation file path or id."});return(await E().header(i)).path}const a=await l(o);if(a!==null){const i=a.pi_session_file;if(i==null||i==="")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=N(i);if(t===null)throw u(`node ${o} has no valid conversation id.`,{next:"Pick a node with a captured conversation."});return(await E().header(t)).path}return await _n(o)}d(ie,"resolveForkSource");async function kn(e,o,a,i={}){return e===null?null:e!==void 0&&e!==""?Se(e).profileId:o!==null?(await l(o))?.profile_id??null:i.readOnlySelection===!0?Re(a):Oe(a)}d(kn,"resolveProfileId");function te(e){const o=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return tn(e.model,o,e.modelExact===!0)}d(te,"requestFromLaunch");async function ae(e,o,a){const i=a??(e.modelIntent?`${e.modelIntent.family}/${e.modelIntent.strength}`:e.model),t=await ln(o,i,e.modelExact===!0);if(t===null)return e;const{CRTR_MODEL_INTENT:s,...c}=e.env??{};return{...e,model:t.model,modelIntent:{family:G,strength:t.strength},modelExact:void 0,env:{...c,CRTR_MODEL_INTENT:`${G}/${t.strength}`}}}d(ae,"appPaidLaunch");async function de(e,o,a){if(e===void 0||e.kind==="logical"&&e.family!==G)return;const i=await an(e.kind==="logical"?{kind:"concrete",spec:e.spec}:e,a??await dn(),o);if(i!==void 0)throw u(`model '${i.request.spec}' is not registered in this daemon.`,{received:i.request.spec,next:sn})}d(de,"assertLaunchModelRegistered");function vn(e,o,a){const i=e??o??null;if(!a&&i===null)throw new Error("spawnChild requires a calling node (CRTR_NODE_ID) or an explicit parent");return i}d(vn,"resolveSpawner");async function se(e,o,a){try{on()}catch{}const i=be(),t=e.root===!0,s=vn(e.parent,i.nodeId??null,t),c=e.mode??"base",y=e.rootLifecycle??(t?"resident":"terminal"),ce=t&&y==="resident",O=s===null?null:await l(s),U=e.creator===void 0||e.creator===null?null:await l(e.creator);e.nodeId!==void 0&&await Ee(e.nodeId);const g=e.forkFrom!==void 0?await ie(e.forkFrom):void 0,P=g===void 0?null:await ge(g),D=await wn([O,U,P],async f=>f?.isolated===!0||f?.run_id!=null&&(await l(f.run_id))?.isolated===!0);if(D&&e.isolated===!1)throw new ee(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});const R=D||e.isolated===!0;if(R&&e.worktree===!0)throw new ee(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const S=e.worktree===!0,w=R||S?e.nodeId??await Ce():e.nodeId,$=R?e.run!==void 0&&t&&!D?e.cwd:ke(ve(e.run?.grantee??O?.grantee??"app:terminal").nodes,w):e.cwd,m=await kn(e.profile,s,$),V=e.run?.grant_id??O?.grant_id??null,X=await ae((await ne(e.kind,c,{lifecycle:y,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:$,profileId:m})).launch,V,e.model);await de(te(X),{cwd:$,profileId:m});const T=e.run??U??O??P;await mn({grantee:T?.grantee??"app:terminal",sub:T?.sub,grant_id:T?.grant_id});const q=P?.node_id??null;let b,F=$;const L=S&&await Fe(m)?await Ie(m,e.worktreeCwd??e.cwd,w,e.worktreeBase):void 0;try{S&&L===void 0&&(b=await Be(e.worktreeCwd??e.cwd,w,e.worktreeBase),F=b.path);const f=S?await ae((await ne(e.kind,c,{lifecycle:y,hasManager:!t,model:e.model,modelOverride:e.model!==void 0,cwd:F,profileId:m})).launch,V,e.model):X;L!==void 0&&(f.worktree=L),S&&await de(te(f),{cwd:F,profileId:m});const n=await ye({kind:e.kind,mode:c,lifecycle:y,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:q,spawnedBy:t?s??void 0:void 0,profile_id:m,...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:g,modelOverride:e.model===void 0?void 0:f.model,...b!==void 0?{managedWorktree:b}:{},...w!==void 0?{nodeId:w}:{},...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 cn(n.node_id,q??null)}catch(r){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(r)}),r}if(await Pe(n.node_id,e.prompt),e.situationalContext!==void 0&&await De(n.node_id,Te(e.situationalContext)),o!==void 0)try{o(n.node_id)}catch(r){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(r)}),r}const A=e.prompt!=="",le=`${A&&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 Be}from"../../daemon/api/environment-of.js";import{createManagedWorktreeAsync as De,rollbackManagedWorktreeAsync as Ne}from"../worktree-mutation-async.js";import{usage as w,brokerLaunchFailed as D}from"../errors.js";import{writeGoal as Pe}from"./kickoff.js";import{appendSituationalContext as Le,formatSituationalProse as Me}from"./situational-context.js";import{ensureRoadmap as Te}from"./roadmap.js";import{buildWakeBearings as Ae}from"./bearings.js";import{encodeKickoffOrigin as We,KICKOFF_ORIGIN_ENV as je}from"./stamp/protocol.js";import{ExecutionCapReached as ze,beginExecution as He,crtrHome as Ke,getNode as u,fullName as re,jobDir as Ge,recordExecutionPid as Ue,abortExecution as j,setFrozen as z}from"../canvas/index.js";import{contextDir as H,nodeAgentDir as K}from"../canvas/node-agent-paths.js";import{copyTreeBeneath as Ve}from"../spaces/open-beneath.js";import{conversationIdFromPath as N,conversationStore as S}from"../conversation-store/index.js";import{appMemoryTooSmall as Xe,boundFleet as qe,brokerThresholdsForDaemon as te}from"./fleet.js";import{admitBrokerMemory as Ye}from"./memory-admission.js";import{emitEvent as P}from"../events/emit.js";import{blaxelEnvironmentOf as Je}from"./blaxel-environment.js";import{openViewerWindow as Qe,focusOf as Ze,windowOfPane as en}from"./placement.js";import{awaitBrokerViewSocket as nn}from"./view-socket.js";import{readLogSnapshot as on}from"../events/read.js";import{transition as k}from"./lifecycle.js";import{beginBootFaultAttempt as rn}from"../canvas/recovery.js";import{headlessBrokerHost as G}from"./host.js";import{ensureDaemon as tn}from"../../daemon/manage.js";import{readConfig as an}from"../config.js";import{modelRequestFromConfig as dn,unregisteredConcreteModel as sn}from"../model-routes.js";import{openModelRegistry as ln}from"./model-registry.js";import{MODEL_SPEC_NEXT as cn}from"./model-selection.js";import{forkNodeLedger as un}from"./ledger.js";import{appRungForGrant as fn}from"../llm/app-rungs.js";import{APP_FAMILY as U}from"../model-routes.js";import{discoverLifecycleHookRegistry as wn}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as mn}from"../command-hooks/transport/exec-lifecycle.js";import{someAsync as hn}from"../async-array.js";import{checkStart as pn}from"./start-check.js";function v(e){return{detail:{schema:"crtr.node-outcome-detail/v1",message:e instanceof Error?e.message:String(e)}}}d(v,"launchFailureOutcome");async function _n(e,o,a){try{return await G.launch(e,o,a)}catch(r){try{await k(e,"crash",{reason:"launch_failed",outcome:v(r)})}catch{}const i=r.message;throw D(i.startsWith("[broker]")?i:`[broker] refusing to launch ${e}: ${i}`,"Inspect the cause above, fix the launch recipe or environment, then retry.")}}d(_n,"launchBrokerOrCrash");function kn(e){return on({nodeId:e,component:"broker",pattern:"broker.startup."},!1).items.flatMap(a=>a.kind==="event"&&a.envelope.event.startsWith("broker.startup.")&&a.envelope.event!=="broker.startup.warning"?[a.envelope.event.slice(15)]:[]).at(-1)??null}d(kn,"lastStartupStep");function vn(e,o){const a=kn(e),r=a===null?"it had logged no startup step":`the last startup step it logged was \`${a}\``;if(o.reason==="exited"){const{code:i,signal:s}=o.status;return{text:`exited (code ${i??"null"}, signal ${s??"null"}) before binding its view socket; ${r}`,fields:{reason:"exited",code:i,signal:s,last_startup_step:a}}}return{text:`was still starting after ${Math.round(o.waitedMs/1e3)} s without binding its view socket, so the launcher stopped it; ${r}`,fields:{reason:"timeout",waited_ms:o.waitedMs,last_startup_step:a}}}d(vn,"notReadyDescription");async function gn(e,o){try{await k(e,"crash",{reason:"launch_failed",outcome:v(o)})}catch{}try{G.teardown(e)}catch{}}d(gn,"crashAndTearDown");async function yn(e){const o=(await S().list()).map(({conversation_id:i,path:s})=>({id:i,path:s})),a=o.filter(i=>i.id===e),r=a.length>0?a:o.filter(i=>i.id.startsWith(e));if(r.length===0)throw w(`--fork-from '${e}': no pi session with that id found.`,{next:"Pass a live node id, a real session uuid/prefix, or an absolute .jsonl session path."});if(r.length>1)throw w(`--fork-from '${e}': ambiguous \u2014 ${r.length} sessions match that id prefix; pass the full id or the .jsonl path.`,{next:"Pass the full session uuid or an absolute .jsonl path to disambiguate."});return r[0].path}d(yn,"resolveSessionUuid");async function ie(e){const o=e.trim();if(o==="")throw w("--fork-from requires a node id, session file, or session uuid.",{next:"Pass a live node id, an absolute .jsonl session path, or a session uuid/prefix."});if(o.includes("/")||o.endsWith(".jsonl")){const r=N(_e(o)?o:ke(process.cwd(),o));if(r===null)throw w(`--fork-from '${o}': invalid conversation path.`,{next:"Pass a conversation file path or id."});return(await S().header(r)).path}const a=await u(o);if(a!==null){const r=a.pi_session_file;if(r==null||r==="")throw w(`node ${o} has no pi session yet \u2014 it has not captured a session FILE to fork from (the broker forks a .jsonl path, not a bare id).`,{next:"Pick a node that has captured a session, or drop --fork-from."});const i=N(r);if(i===null)throw w(`node ${o} has no valid conversation id.`,{next:"Pick a node with a captured conversation."});return(await S().header(i)).path}return await yn(o)}d(ie,"resolveForkSource");async function bn(e,o,a,r={}){return e===null?null:e!==void 0&&e!==""?Ee(e).profileId:o!==null?(await u(o))?.profile_id??null:r.readOnlySelection===!0?Oe(a):Re(a)}d(bn,"resolveProfileId");function ae(e){const o=e.modelIntent===void 0?void 0:`${e.modelIntent.family}/${e.modelIntent.strength}`;return dn(e.model,o,e.modelExact===!0)}d(ae,"requestFromLaunch");async function de(e,o,a){const r=a??(e.modelIntent?`${e.modelIntent.family}/${e.modelIntent.strength}`:e.model),i=await fn(o,r,e.modelExact===!0);if(i===null)return e;const{CRTR_MODEL_INTENT:s,...l}=e.env??{};return{...e,model:i.model,modelIntent:{family:U,strength:i.strength},modelExact:void 0,env:{...l,CRTR_MODEL_INTENT:`${U}/${i.strength}`}}}d(de,"appPaidLaunch");async function se(e,o,a){if(e===void 0||e.kind==="logical"&&e.family!==U)return;const r=await sn(e.kind==="logical"?{kind:"concrete",spec:e.spec}:e,a??await ln(),o);if(r!==void 0)throw w(`model '${r.request.spec}' is not registered in this daemon.`,{received:r.request.spec,next:cn})}d(se,"assertLaunchModelRegistered");function xn(e,o,a){const r=e??o??null;if(!a&&r===null)throw new Error("spawnChild requires a calling node (CRTR_NODE_ID) or an explicit parent");return r}d(xn,"resolveSpawner");async function le(e,o,a){try{tn()}catch{}const r=xe(),i=e.root===!0,s=xn(e.parent,r.nodeId??null,i),l=e.mode??"base",g=e.rootLifecycle??(i?"resident":"terminal"),ce=i&&g==="resident",E=s===null?null:await u(s),V=e.creator===void 0||e.creator===null?null:await u(e.creator);e.nodeId!==void 0&&await Ce(e.nodeId);const y=e.forkFrom!==void 0?await ie(e.forkFrom):void 0,L=y===void 0?null:await be(y),M=await hn([E,V,L],async f=>f?.isolated===!0||f?.run_id!=null&&(await u(f.run_id))?.isolated===!0);if(M&&e.isolated===!1)throw new ne(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});const R=M||e.isolated===!0;if(R&&e.worktree===!0)throw new ne(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const C=e.worktree===!0,m=R||C?e.nodeId??await Se():e.nodeId,O=R?e.run!==void 0&&i&&!M?e.cwd:ve(ge(e.run?.grantee??E?.grantee??"app:terminal").nodes,m):e.cwd,h=await bn(e.profile,s,O),X=e.run?.grant_id??E?.grant_id??null,q=await de((await oe(e.kind,l,{lifecycle:g,hasManager:!i,model:e.model,modelOverride:e.model!==void 0,cwd:O,profileId:h})).launch,X,e.model);await se(ae(q),{cwd:O,profileId:h});const T=e.run??V??E??L;await pn({grantee:T?.grantee??"app:terminal",sub:T?.sub,grant_id:T?.grant_id});const Y=L?.node_id??null;let b,F=O;const A=C&&await Ie(h)?await Be(h,e.worktreeCwd??e.cwd,m,e.worktreeBase):void 0;try{C&&A===void 0&&(b=await De(e.worktreeCwd??e.cwd,m,e.worktreeBase),F=b.path);const f=C?await de((await oe(e.kind,l,{lifecycle:g,hasManager:!i,model:e.model,modelOverride:e.model!==void 0,cwd:F,profileId:h})).launch,X,e.model):q;A!==void 0&&(f.worktree=A),C&&await se(ae(f),{cwd:F,profileId:h});const n=await ye({kind:e.kind,mode:l,lifecycle:g,cwd:F,name:e.name??e.kind,description:e.description,parent:i?null:s,creator:e.creator,...e.actor===void 0?{}:{actor:e.actor},forkSourceNode:Y,spawnedBy:i?s??void 0:void 0,profile_id:h,...e.scopes===void 0?{}:{scopes:e.scopes},isolated:R,...e.run===void 0?{}:{run:e.run},...e.causedBy===void 0?{}:{causedBy:e.causedBy},...e.withinCreate===void 0?{}:{withinCreate:e.withinCreate},forkFrom:e.forkFrom,forkSourceFile:y,modelOverride:e.model===void 0?void 0:f.model,...b!==void 0?{managedWorktree:b}:{},...m!==void 0?{nodeId:m}:{},...e.reviewBinding===void 0?{}:{reviewBinding:e.reviewBinding},...e.deadlineAt===void 0?{}:{deadlineAt:e.deadlineAt},...e.outcomeDelivery===void 0?{}:{outcomeDelivery:e.outcomeDelivery},launch:f});if(a?.(n.node_id),e.forkFrom!==void 0)try{await un(n.node_id,Y??null)}catch(t){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(t)}),t}if(await Pe(n.node_id,e.prompt),e.situationalContext!==void 0&&await Le(n.node_id,Me(e.situationalContext)),o!==void 0)try{o(n.node_id)}catch(t){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(t)}),t}const W=e.prompt!=="",ue=`${W&&e.wakeOrigin!==void 0?`${Ae(e.wakeOrigin)}
|
|
2
2
|
|
|
3
|
-
`:""}${e.prompt}`;
|
|
3
|
+
`:""}${e.prompt}`;l==="orchestrator"&&await Te(n.node_id,{goal:e.prompt.trim()}),await $n(n);let J;if(y!==void 0)try{const t=N(y);if(t===null)throw new Error(`invalid fork source ${y}`);const c=await S().fork(t,n.node_id);J=(await S().header(c)).path}catch(t){throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(t)}),t}const x=Fe(n,{prompt:ue,resumeSessionPath:J});if(x.env={...x.env,CRTR_SUBTREE:await $e(n.node_id)},W){const t=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(t)}const p=qe();if(await Je(n.profile_id??null)!==null)return await z(n.node_id,new Date().toISOString()),P({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 t=Xe(_);throw await k(n.node_id,"crash",{reason:"launch_failed",outcome:v(t)}),t}if(!Q||_?.verdict==="denied")return _?.verdict==="denied"&&p.releaseReservation(n.node_id),await z(n.node_id,new Date().toISOString()),P({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(t){if(!(t instanceof ze))throw t;return p.releaseReservation(n.node_id),await z(n.node_id,new Date().toISOString()),P({level:"info",event:"broker.frozen",node_id:n.node_id,fields:{reason:"broker_cap",live_count:t.live,hard_cap:t.cap}}),{node:await u(n.node_id),frozen:!0,window:null,session:null}}x.env={...x.env,CRTR_EXECUTION_ID:$};let I;try{I=await _n(n.node_id,x,{cwd:n.cwd,name:re(n),resuming:!1})}catch(t){throw await j($,{reason:"launch_failed"}),t}finally{p.releaseReservation(n.node_id)}if(I.pid===null){const t=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(t)}),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,I.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 t=await nn(n.node_id,I.exited);if(!t.ready){const c=vn(n.node_id,t);P({level:"error",event:"broker.launch.not_ready",node_id:n.node_id,fields:c.fields});const B=await fe.explanation();throw await gn(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(!i&&s!==null&&an("user").auto_open_child_viewers)try{const t=await Ze(s);if(t!==null&&t.pane!==null&&t.pane!==""){const c=await Qe(n.node_id,t.session??"",{name:re(n),cwd:e.cwd,besidePane:t.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 Ne(b),f}}d(le,"spawnChildPrepared");async function ko(e){return le(e)}d(ko,"spawnChild");async function $n(e){const o=wn(e.cwd,e.profile_id).plans.get("node:start")??[];await mn(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($n,"invokeBirthLifecycleHooks");const Sn=new Set(["initial-prompt.md","yield-message.md","result.json","jobs"]);async function vo(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 i=await ie(e),s=await H(e);try{await S().header(N(i)),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,Sn)})}d(vo,"forkNode");export{de as appPaidLaunch,se as assertLaunchModelRegistered,vo as forkNode,$n as invokeBirthLifecycleHooks,ie as resolveForkSource,bn as resolveProfileId,xn as resolveSpawner,ko as spawnChild,le as spawnChildPrepared};
|
|
@@ -10,15 +10,36 @@ export declare function connectViewSocket(nodeId: string): Socket;
|
|
|
10
10
|
* `timeoutMs`. A view.sock that is a symlink rejects with the refusal, so no
|
|
11
11
|
* wait reads a planted link as a broker that is still starting. */
|
|
12
12
|
export declare function probeViewSocket(nodeId: string, timeoutMs: number): Promise<boolean>;
|
|
13
|
+
/** How a wait for a broker's view.sock ended: it accepted, the launch handle reported the broker's exit (with the
|
|
14
|
+
* status Node observed), or the deadline passed with the broker still running. */
|
|
15
|
+
export type BrokerViewWait = {
|
|
16
|
+
ready: true;
|
|
17
|
+
} | {
|
|
18
|
+
ready: false;
|
|
19
|
+
reason: 'exited';
|
|
20
|
+
status: {
|
|
21
|
+
code: number | null;
|
|
22
|
+
signal: NodeJS.Signals | null;
|
|
23
|
+
};
|
|
24
|
+
} | {
|
|
25
|
+
ready: false;
|
|
26
|
+
reason: 'timeout';
|
|
27
|
+
waitedMs: number;
|
|
28
|
+
};
|
|
13
29
|
/** Wait for a launched broker's view.sock, failing fast when its launch handle
|
|
14
|
-
* exits. `exited`
|
|
15
|
-
* bounded readiness deadline without a handle; `waitMs`
|
|
16
|
-
* for a caller holding an HTTP request open. */
|
|
30
|
+
* exits and saying which way the wait ended. `exited` is optional for callers
|
|
31
|
+
* that only need the bounded readiness deadline without a handle; `waitMs`
|
|
32
|
+
* shortens that deadline for a caller holding an HTTP request open. */
|
|
33
|
+
export declare function awaitBrokerViewSocket(nodeId: string, exited?: Promise<{
|
|
34
|
+
code: number | null;
|
|
35
|
+
signal: NodeJS.Signals | null;
|
|
36
|
+
}>, waitMs?: number): Promise<BrokerViewWait>;
|
|
37
|
+
/** {@link awaitBrokerViewSocket} for callers that only branch on readiness. */
|
|
17
38
|
export declare function waitForBrokerViewSocket(nodeId: string, exited?: Promise<{
|
|
18
39
|
code: number | null;
|
|
19
40
|
signal: NodeJS.Signals | null;
|
|
20
41
|
}>, waitMs?: number): Promise<boolean>;
|
|
21
|
-
/** The port a sandboxed broker serves `/view` on (
|
|
42
|
+
/** The port a sandboxed broker serves `/view` on (bound to `::`; reached only through the private preview and its per-attach token). */
|
|
22
43
|
export declare const BROKER_VIEW_PORT = 4180;
|
|
23
44
|
/** The relay's end of one broker view connection: a view.sock {@link Socket}, or {@link connectWssView}'s link. Bytes in
|
|
24
45
|
* both directions are newline-terminated frames; `close` carries whether an error preceded it. */
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var m=Object.defineProperty;var
|
|
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.slice(0,-1):e;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
|
|
3
|
+
`)?e.slice(0,-1):e;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,3 +1,3 @@
|
|
|
1
|
-
var x=Object.defineProperty;var
|
|
1
|
+
var x=Object.defineProperty;var i=(r,d)=>x(r,"name",{value:d,configurable:!0});import{createReadStream as v,read as S,statSync as $}from"node:fs";import{Readable as _}from"node:stream";import{promisify as T}from"node:util";import{readConfig as E}from"../config.js";import{directoryIssuer as O}from"../directory/issuer.js";import{RunError as b}from"../runs/operations.js";import{mintDirectoryToken as C,runtimeId as R}from"../grants/sync.js";const G=104857600;class m extends Error{static{i(this,"StorageRefused")}status;code;constructor(d,u,l){super(l),this.status=d,this.code=u}}const j=T(S);async function*U(r,d){let u=0;for(;u<d;){const l=Buffer.allocUnsafe(Math.min(1048576,d-u)),{bytesRead:f}=await j(r,l,0,l.length,u);if(f===0)throw new Error("file shrank while it was being copied");u+=f,yield l.subarray(0,f)}}i(U,"fdChunks");const s=i(r=>new b(503,"storage_unavailable",r,void 0,void 0,void 0,!0),"unavailable");function P(){const r=E("user").runtime?.storage;return!r?.service_url||!r.base_url?null:{service_url:r.service_url.replace(/\/$/,""),base_url:r.base_url.replace(/\/$/,"")}}i(P,"storageConfig");let w;function F(){const r=P(),d=O();if(!r||!d)throw new b(503,"storage_unavailable","file storage is not configured on this runtime: it has no `runtime.storage` setting (service_url, base_url) or no joined directory. Only a hosted runtime has file storage (its provisioner sets CRTR_BOOT_STORAGE_URL), and the directory issues storage tokens only to a sandboxed runtime, so a computer joined with `crtr sys join` cannot send or receive files yet. Retrying does not help: run this command from your hosted runtime.",void 0,void 0,void 0,!1);const u=`${d}
|
|
2
2
|
${r.service_url}
|
|
3
|
-
${r.base_url}`;return
|
|
3
|
+
${r.base_url}`;return w?.key!==u&&(w={key:u,client:A(r,()=>C(d,r.service_url),R())}),w.client}i(F,"storageClient");function J(){w=void 0}i(J,"resetStorageClient");function A(r,d,u){let l,f;const k=i(async()=>{if(l&&l.expires_at-6e4>Date.now())return l.access_token;f??=d().finally(()=>{f=void 0});try{l=await f}catch(t){throw s(`storage token could not be minted: ${t instanceof Error?t.message:String(t)}`)}return l.access_token},"bearer"),c=i(async(t,e,n={})=>{const p=[AbortSignal.timeout(n.timeoutMs??1e4),...n.signal?[n.signal]:[]];let o;try{o=await fetch(`${r.service_url}${e}`,{method:t,signal:AbortSignal.any(p),headers:{Authorization:`Bearer ${await k()}`,...n.body===void 0?{}:{"Content-Type":"application/json"}},...n.body===void 0?{}:{body:JSON.stringify(n.body)}})}catch(a){throw a instanceof b?a:s(`storage could not be reached: ${a instanceof Error?a.message:String(a)}`)}if(o.status===401&&(l=void 0),o.status===404||o.status===409){const a=await o.json().catch(()=>({})),g=a.error?.code??a.code??(o.status===404?"not_found":"not_uploaded");throw new m(o.status,g,a.error?.message??a.message??`storage answered ${o.status}`)}if(!o.ok)throw await o.body?.cancel().catch(()=>{}),s(`storage answered ${o.status} to ${t} ${e.split("?")[0]}`);return o},"call"),y=i(async t=>{try{return await t.json()}catch{throw s("storage answered with an invalid body")}},"json"),h=i(t=>encodeURIComponent(t),"id");return{config:r,runtimeId:u,async createUpload(t){const e=await y(await c("POST","/v1/uploads",{body:t}));if(typeof e.upload_id!="string"||typeof e.url!="string"||typeof e.upload_link!="string"||typeof e.expires_at!="string")throw s("storage answered with an invalid upload");return{upload_id:e.upload_id,url:e.url,upload_link:e.upload_link,expires_at:e.expires_at}},async fetchUpload(t,e){const n=await c("GET",`/v1/uploads/${h(t)}/content`,{...e?{signal:e}:{},timeoutMs:11e4});if(!n.body)throw s("storage answered with no body");const p=n.headers.get("content-length");return{body:_.fromWeb(n.body),size:p===null?null:Number(p),media_type:n.headers.get("content-type")}},async signDownload(t){const e=await y(await c("POST",`/v1/uploads/${h(t)}/download-link`));if(typeof e.url!="string"||typeof e.expires_at!="string")throw s("storage answered with an invalid link");return{url:e.url,expires_at:e.expires_at}},async deleteUpload(t){try{await c("DELETE",`/v1/uploads/${h(t)}`)}catch(e){if(!(e instanceof m&&e.status===404))throw e}},async createShare(t){const e=await y(await c("POST","/v1/shares",{body:t}));if(typeof e.share_id!="string"||typeof e.url!="string"||typeof e.upload_link!="string")throw s("storage answered with an invalid share");return{share_id:e.share_id,url:e.url,upload_link:e.upload_link,expires_at:e.expires_at??null}},async putShareBytes(t,e,n,p){if($(e).size!==n)throw new Error("shared file changed size while it was being copied");let o;try{o=await fetch(t,{method:"PUT",signal:AbortSignal.timeout(11e4),headers:{"Content-Type":p,"Content-Length":String(n)},body:_.toWeb(v(e)),duplex:"half"})}catch(a){throw s(`storage could not be reached: ${a instanceof Error?a.message:String(a)}`)}if(await o.body?.cancel().catch(()=>{}),!o.ok)throw s(`storage answered ${o.status} to the share upload`)},async deleteShare(t){try{await c("DELETE",`/v1/shares/${h(t)}`)}catch(e){if(!(e instanceof m&&e.status===404))throw e}},async createResultUpload(t){const e=await y(await c("POST","/v1/uploads",{body:{name:t.name,media_type:t.media_type,max_size:t.max_size}}));if(typeof e.upload_id!="string"||typeof e.url!="string"||typeof e.upload_link!="string"||typeof e.expires_at!="string")throw s("storage answered with an invalid upload");return{upload_id:e.upload_id,url:e.url,upload_link:e.upload_link,expires_at:e.expires_at}},async signUploadLink(t){const e=await y(await c("POST",`/v1/uploads/${h(t)}/upload-link`));if(typeof e.upload_link!="string"||typeof e.expires_at!="string")throw s("storage answered with an invalid upload link");return{upload_link:e.upload_link,expires_at:e.expires_at}},async createOutbound(t){const e=await y(await c("POST","/v1/outbound",{body:t}));if(typeof e.object_id!="string"||typeof e.upload_link!="string"||typeof e.url!="string"||typeof e.expires_at!="string")throw s("storage answered with an invalid outbound object");return{object_id:e.object_id,upload_link:e.upload_link,url:e.url,link_expires_at:e.link_expires_at,expires_at:e.expires_at}},async signOutbound(t){const e=await y(await c("POST",`/v1/outbound/${h(t)}/link`));if(typeof e.url!="string"||typeof e.expires_at!="string")throw s("storage answered with an invalid link");return{url:e.url,link_expires_at:e.link_expires_at,expires_at:e.expires_at}},async putFileBytes(t,e,n,p){const o=_.from(U(e,n));let a;try{a=await fetch(t,{method:"PUT",signal:AbortSignal.timeout(11e4),headers:{"Content-Type":p,"Content-Length":String(n)},body:_.toWeb(o),duplex:"half"})}catch(g){throw s(`storage could not be reached: ${g instanceof Error?g.message:String(g)}`)}finally{o.destroy()}if(await a.body?.cancel().catch(()=>{}),!a.ok)throw s(`storage answered ${a.status} to the upload`)}}}i(A,"createStorageClient");function X(r){return!r||Buffer.byteLength(r,"utf8")>255?"name must be 1-255 bytes":r==="."||r===".."?"name must not be . or ..":/[/\\\u0000-\u001f\u007f]/.test(r)?"name must not contain /, \\, or control characters":null}i(X,"invalidStorageName");export{m as StorageRefused,G as UPLOAD_MAX_BYTES,A as createStorageClient,X as invalidStorageName,J as resetStorageClient,F as storageClient,P as storageConfig};
|
|
@@ -34,6 +34,10 @@ export declare const REFRESH_EXCHANGE_TIMEOUT_MS = 10000;
|
|
|
34
34
|
export declare class RefreshBusyError extends Error {
|
|
35
35
|
constructor(provider: ManagedProviderId, label: string);
|
|
36
36
|
}
|
|
37
|
+
/** The vendor did not answer a refresh exchange within `REFRESH_EXCHANGE_TIMEOUT_MS`. */
|
|
38
|
+
export declare class RefreshTimeoutError extends Error {
|
|
39
|
+
constructor(provider: ManagedProviderId);
|
|
40
|
+
}
|
|
37
41
|
export declare function insertAccount(db: CanvasDb, person: string, provider: ManagedProviderId, row: ProviderRow, entry: StoredCredential): Promise<void>;
|
|
38
42
|
export declare function upsertModelCooldown(db: CanvasDb, person: string, provider: string, accountId: string, family: string, until: number, rateLimitedAt: number): Promise<void>;
|
|
39
43
|
export declare function readSubscriptionPool(provider: ManagedProviderId): Promise<SubscriptionCredential[]>;
|