@north-light/cli 0.3.551 → 0.3.553
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.d.ts +11 -0
- package/dist/api/client.js +3 -3
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/charges.d.ts +122 -0
- package/dist/api/dto/charges.js +0 -0
- package/dist/api/dto/usage.d.ts +3 -3
- package/dist/api/index.d.ts +1 -0
- package/dist/api/index.js +1 -1
- package/dist/api/routes.d.ts +3 -0
- package/dist/api/routes.js +1 -1
- package/dist/builtin-memory/crouter-sdk/release-notes.md +10 -0
- package/dist/clients/attach/viewer.js +50 -50
- package/dist/commands/sys/spend.d.ts +1 -0
- package/dist/commands/sys/spend.js +3 -0
- package/dist/commands/sys.js +1 -1
- package/dist/core/canvas/canvas.js +4 -4
- package/dist/core/canvas/db.js +4 -4
- package/dist/core/canvas/export-sqlite.js +2 -2
- package/dist/core/canvas/import-sqlite.d.ts +2 -0
- package/dist/core/canvas/import-sqlite.js +4 -4
- package/dist/core/canvas/person.js +7 -16
- package/dist/core/canvas/schema-chain.d.ts +34 -0
- package/dist/core/canvas/schema-chain.js +1 -0
- package/dist/core/canvas/schema-pg/.gitkeep +0 -0
- package/dist/core/canvas/schema-pg.sql +61 -0
- package/dist/core/canvas/schema-version.d.ts +29 -3
- package/dist/core/canvas/schema-version.js +1 -1
- package/dist/core/canvas/types.d.ts +4 -0
- package/dist/core/config.js +1 -1
- package/dist/core/grants/mirror.d.ts +2 -1
- package/dist/core/grants/mirror.js +2 -2
- package/dist/core/ledger/backfill.d.ts +12 -0
- package/dist/core/ledger/backfill.js +22 -0
- package/dist/core/ledger/charges.d.ts +18 -0
- package/dist/core/ledger/charges.js +1 -0
- package/dist/core/ledger/check.d.ts +44 -0
- package/dist/core/ledger/check.js +7 -0
- package/dist/core/ledger/index.d.ts +9 -0
- package/dist/core/ledger/index.js +1 -0
- package/dist/core/ledger/limits.d.ts +15 -0
- package/dist/core/ledger/limits.js +3 -0
- package/dist/core/ledger/months.d.ts +6 -0
- package/dist/core/ledger/months.js +1 -0
- package/dist/core/ledger/payer.d.ts +34 -0
- package/dist/core/ledger/payer.js +1 -0
- package/dist/core/ledger/read.d.ts +44 -0
- package/dist/core/ledger/read.js +3 -0
- package/dist/core/ledger/totals.d.ts +19 -0
- package/dist/core/ledger/totals.js +4 -0
- package/dist/core/ledger/types.d.ts +66 -0
- package/dist/core/ledger/types.js +0 -0
- package/dist/core/llm/run.d.ts +17 -5
- package/dist/core/llm/run.js +2 -2
- package/dist/core/providers/call.d.ts +7 -1
- package/dist/core/providers/call.js +1 -1
- package/dist/core/providers/errors.js +1 -1
- package/dist/core/providers/receipts.d.ts +7 -1
- package/dist/core/providers/receipts.js +1 -3
- package/dist/core/runs/operations.d.ts +1 -0
- package/dist/core/runs/operations.js +7 -7
- package/dist/core/runtime/broker/cli-relay.js +1 -1
- package/dist/core/runtime/broker/model-adapter.js +2 -2
- package/dist/core/runtime/broker/turn-cause.d.ts +7 -0
- package/dist/core/runtime/broker/turn-cause.js +1 -0
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/nodes.d.ts +2 -0
- package/dist/core/runtime/nodes.js +1 -1
- package/dist/core/runtime/recycle.js +1 -1
- package/dist/core/runtime/reset.js +1 -1
- package/dist/core/runtime/revive.js +2 -2
- package/dist/core/runtime/spawn.d.ts +2 -0
- package/dist/core/runtime/spawn.js +2 -2
- package/dist/core/runtime/start-check.d.ts +15 -0
- package/dist/core/runtime/start-check.js +1 -0
- package/dist/core/runtime/warm-pool.js +1 -1
- package/dist/core/user-settings.d.ts +4 -0
- package/dist/core/user-settings.js +1 -1
- package/dist/daemon/api/app-listener.js +13 -13
- package/dist/daemon/api/handlers/bash-jobs.js +1 -1
- package/dist/daemon/api/handlers/charges.d.ts +3 -0
- package/dist/daemon/api/handlers/charges.js +1 -0
- package/dist/daemon/api/handlers/llm.d.ts +9 -5
- package/dist/daemon/api/handlers/llm.js +3 -3
- package/dist/daemon/api/handlers/messages.js +2 -2
- package/dist/daemon/api/handlers/providers.d.ts +2 -0
- package/dist/daemon/api/handlers/providers.js +1 -1
- package/dist/daemon/api/handlers/run-routes.js +1 -1
- package/dist/daemon/api/handlers/runs.d.ts +1 -1
- package/dist/daemon/api/handlers/runs.js +1 -1
- package/dist/daemon/api/operations.js +1 -1
- package/dist/daemon/api/router.d.ts +8 -0
- package/dist/daemon/api/router.js +1 -1
- package/dist/daemon/api/server.js +1 -1
- package/dist/daemon/cron/authority.d.ts +1 -1
- package/dist/daemon/cron-run.js +2 -2
- package/dist/daemon/crtrd.js +10 -10
- package/dist/daemon/fleet.js +4 -4
- package/dist/daemon/reconcilers/action-lane.js +1 -1
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.d.ts +2 -0
- package/dist/daemon/reconcilers/node-lifecycle/freeze-lane.js +1 -1
- package/dist/types.d.ts +4 -0
- package/docs/sdk/release-notes.md +10 -0
- package/package.json +3 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +13 -13
- package/scripts/install-runtime.mjs +6 -20
- package/scripts/lib/canvas-schema-gate.mjs +20 -0
- package/dist/core/usage/ledger.d.ts +0 -49
- package/dist/core/usage/ledger.js +0 -10
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var Oe=Object.defineProperty;var u=(e,t)=>Oe(e,"name",{value:t,configurable:!0});import{coveredByAny as be}from"../../shared/env.js";import{createHash as G}from"node:crypto";import{ApiError as De}from"../../api/errors.js";import{CrtrError as Me}from"../errors.js";import{isAbsolute as z,relative as Ie,resolve as Ae,sep as Te,join as Le}from"node:path";import{SessionManager as Ce}from"@earendil-works/pi-coding-agent";import{covers as U}from"@north-light/identity";import{openDb as
|
|
1
|
+
var Oe=Object.defineProperty;var u=(e,t)=>Oe(e,"name",{value:t,configurable:!0});import{coveredByAny as be}from"../../shared/env.js";import{createHash as G}from"node:crypto";import{ApiError as De}from"../../api/errors.js";import{CrtrError as Me}from"../errors.js";import{isAbsolute as z,relative as Ie,resolve as Ae,sep as Te,join as Le}from"node:path";import{SessionManager as Ce}from"@earendil-works/pi-coding-agent";import{covers as U}from"@north-light/identity";import{openDb as B,withCanvasWrite as W}from"../canvas/db.js";import{deleteNodeWithOwned as ke}from"../graph/deletion.js";import{getById as xe}from"../graph/objects.js";import{repairRunConversations as Q}from"../canvas/sessions.js";import{getNode as O,nodeFiles as We,removeNodeFiles as Fe,updateNode as qe}from"../canvas/canvas.js";import{fullName as He}from"../canvas/labels.js";import{renameWindow as Ue}from"../runtime/placement.js";import{liveExecutionForNode as V}from"../canvas/executions.js";import{conversationStore as Z,isConversationNotFound as Be}from"../conversation-store/index.js";import{PARKED_RESIDENT_SQL as Pe}from"../canvas/canvas.js";import{WAKE_MAIL_SQL as $e}from"../canvas/deliveries.js";import{enqueueNodeMail as je}from"../feed/messages.js";import{newestReportBody as Je}from"../feed/reports.js";import{ensureAppProfile as Ye,loadExactProfileManifest as Xe}from"../profiles/manifest.js";import{stopNodeSandboxes as K}from"../spaces/stop.js";import{BrokerUnreachableError as Ge}from"../runtime/broker-request.js";import{interruptLive as ze}from"../runtime/interactive-deliver.js";import{isBrokerLive as ee}from"../runtime/model-swap.js";import{newNodeId as Qe}from"../runtime/nodes.js";import{reviveNode as P}from"../runtime/revive.js";import{spawnChildPrepared as Ve}from"../runtime/spawn.js";import{isPortableModelToken as Ze}from"../runtime/launch.js";import{parseDurationMs as Ke}from"../wake.js";import{expandModelCandidates as et,parseModelSpec as tt}from"../model-routes.js";import{payerOfGrant as $}from"../grants/mirror.js";import{isolatedBrokerLauncherAvailable as nt}from"../runtime/host.js";import{resolveRunKind as st,resolveRunModel as at}from"../runtime/launch-target.js";import{cycleAwareMessages as it}from"../runtime/session-cycles.js";import{originFor as te}from"../runtime/stamp/protocol.js";import{readOutputRequest as rt,readOutputResult as ne}from"../runtime/structured-output.js";import{admitLegacyStructuredOutput as se}from"../../daemon/structured-requests/sidecar.js";import{runSchemaRepromptPending as ot}from"../runtime/stop-guard.js";import{toRunOutcomeDTO as dt}from"../../daemon/api/map.js";import{openAssistantMessageStartSequence as ct}from"../../daemon/runs/observer.js";import{closeNode as ae}from"../runtime/close.js";import{parseScope as ut}from"@north-light/identity";import{appendRunEvent as ie,subscribeRunEvents as mt}from"./events.js";import{runActivity as lt}from"./activity.js";import{cancelOpenQuestions as re,openNoticeIds as pt,openQuestionIds as oe}from"./questions.js";import{appSpace as j}from"../layout.js";import{ensureAppSpace as _t}from"../spaces/space.js";import{assertUploadsUsable as de,resolveStorageUrls as ft}from"../storage/attachments.js";import{storageClient as wt,storageConfig as gt}from"../storage/client.js";import{deleteUploadRow as Et,insertUploadUses as ce,releaseRunUploads as yt}from"../storage/tables.js";import{abortProviderCalls as ue}from"../providers/inflight.js";import{filterAsync as me,mapAsync as k}from"../async-array.js";const le=u((e,t,s)=>ft(t,e,s),"defaultResolver"),ht=3e3;class N extends Error{static{u(this,"RunError")}status;code;param;details;scope;retryable;constructor(t,s,n,d,l,i,r=t===503){super(n),this.status=t,this.code=s,this.param=d,this.details=l,this.scope=i,this.retryable=r}}const S=u((e,t)=>new N(400,"invalid_request",e,t),"invalid"),J=u(()=>new N(404,"not_found","run not found"),"missing"),Y=u(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"usage"),I=u(async()=>await B(),"db");async function F(e,t,s=!1){const n=await O(e);if(!n||n.parent!==null||n.run_id!==e||n.grantee!==t||!s&&n.deleting_at)throw J();return n}u(F,"ownedRun");const pe=["waiting_on_user","idle","settled"];async function C(e){if(e.status==="canceled"||e.status==="dead"||e.status==="done"&&e.intent!=="parked")return"settled";const t=await(await I()).prepare(`SELECT 1 FROM node_rows n WHERE n.run_id = ? AND n.status = 'active' AND
|
|
2
2
|
(n.last_settled_at IS NULL OR EXISTS (
|
|
3
3
|
SELECT 1 FROM run_events e WHERE e.run_id = ? AND e.node_id = n.node_id AND e.type = 'node.turn.started'
|
|
4
4
|
AND e.sequence_number > COALESCE((SELECT MAX(c.sequence_number) FROM run_events c
|
|
5
5
|
WHERE c.run_id = e.run_id AND c.node_id = e.node_id AND c.type = 'node.turn.completed'), 0)
|
|
6
|
-
)) LIMIT 1`).get(e.node_id,e.node_id),
|
|
7
|
-
WHERE n.run_id = ? AND ${
|
|
8
|
-
AND (n.status IN ('active', 'idle') OR ${
|
|
6
|
+
)) LIMIT 1`).get(e.node_id,e.node_id),s=!e.last_settled_at&&e.status!=="done";return t||s||await ot(e)?"running":(await oe(e.node_id)).length?"waiting_on_user":await(await I()).prepare(`SELECT 1 FROM deliveries d JOIN nodes n ON n.node_id = d.destination_id
|
|
7
|
+
WHERE n.run_id = ? AND ${$e("d","'armed', 'pending'")}
|
|
8
|
+
AND (n.status IN ('active', 'idle') OR ${Pe("n")}) LIMIT 1`).get(e.node_id)?"running":"idle"}u(C,"runStatus");async function On(e){const t=await O(e);return t!==null&&await C(t)==="running"}u(On,"runIsRunning");async function x(e){await Q(e.node_id),e=await O(e.node_id)??e;const t=await C(e),s=t==="settled"?[]:await oe(e.node_id),n=await Je(e.node_id)||void 0,d=t==="settled"?dt(e):null,l=d?.kind==="result"?ne(e.node_id,e.grantee):void 0;return{run_id:e.node_id,name:e.name,status:t,...d?{outcome:d}:{},...l===void 0?{}:{result:l},...n!==void 0?{last_report:n}:{},pending_question_ids:s,open_notice_ids:t==="settled"?[]:await pt(e.node_id),...e.last_turn_error_json?{last_turn_error:JSON.parse(e.last_turn_error_json)}:{},usage:JSON.parse(e.usage_json??JSON.stringify(Y())),payer:await $(e.grant_id),scopes:e.scopes,metadata:e.metadata_json?JSON.parse(e.metadata_json):{},created_at:e.created,...t==="settled"&&e.outcome_at?{settled_at:e.outcome_at}:{},latest_sequence:(e.event_cursor??1)-1,last_activity_at:e.last_activity_at,activity:await lt(e.node_id,t)}}u(x,"runObject");const X=864e5,_e=255;function bn(e){if(e!==void 0){if(typeof e!="string"||!e.length||e.length>_e)throw S(`Idempotency-Key must be 1-${_e} characters`);return e}}u(bn,"idempotencyKeyOf");async function q(e,t,s,n){n??=await B();const d=await n.prepare("SELECT body_hash, run_id, response_json, created_at FROM idempotency_keys WHERE grantee = ? AND key = ?").get(e,t);if(!(!d||Date.now()-Date.parse(d.created_at)>=X)){if(d.body_hash!==s)throw new N(409,"idempotency_conflict","key used with a different request");return{run_id:d.run_id,response:JSON.parse(d.response_json)}}}u(q,"findIdempotent");async function fe(e,t,s,n,d,l,i){await e.prepare("DELETE FROM idempotency_keys WHERE grantee = ? AND key = ? AND created_at <= ?").run(t,s,new Date(Date.now()-X).toISOString()),await e.prepare("INSERT INTO idempotency_keys (grantee, key, body_hash, run_id, response_json, created_at) VALUES (?, ?, ?, ?, ?, ?)").run(t,s,n,d,JSON.stringify(l),i)}u(fe,"recordIdempotent");async function Dn(e=Date.now()){return Number((await(await B()).prepare("DELETE FROM idempotency_keys WHERE created_at <= ?").run(new Date(e-X).toISOString())).changes)}u(Dn,"pruneExpiredIdempotencyKeys");async function we(e,t,s,n,d){const l=n.text;let i=0;return{messageId:(await je(t,{kind:"message",label:l.slice(0,120),senderNodeId:"human",senderName:s,bodyJson:d?{body:l}:{body:l,start_turn:!1},urgency:d?"normal":"deferred",wake:d?1:0,withinEnqueue:u(async(c,m)=>{n.uses.length&&(await de(s,n.uses,c),await ce(n.uses.map(({upload_id:h,path:E})=>({upload_id:h,path:E,run_id:t})),c)),i=(await ie(c,t,t,"node.message.accepted",{message_id:m,start_turn:d})).sequence_number},"withinEnqueue")})).messageId,sequence:i}}u(we,"acceptRunMessage");class ge extends Error{static{u(this,"IdempotentReplay")}winner;constructor(t){super("idempotent replay"),this.winner=t}}const Rt=1440*60*1e3;function Ee(e){const t=typeof e=="string"?Ke(e):null;if(t===null||!Number.isSafeInteger(t))throw S(`deadline '${String(e)}' is not a duration; use one or more <int>[smhd] parts such as 10m or 1h30m`,"deadline");if(t<=0)throw S("deadline must be greater than zero","deadline");if(t>Rt)throw S("deadline must be at most 24h","deadline");return t}u(Ee,"parseRunDeadlineMs");async function Mn(e,t,s,n=le){if(t.isolated&&!nt())throw new N(503,"isolated_unavailable","isolated runs require the Linux root launcher","isolated");t.deadline!==void 0&&Ee(t.deadline);const{causedBy:d,...l}=t,i=G("sha256").update(JSON.stringify(l)).digest("hex");if(s){const a=await q(e.grantee,s,i);if(a){const p=await F(a.run_id,e.grantee);return!p.pi_pid&&await C(p)==="running"&&(t.output_schema!==void 0&&!p.outcome_at&&rt(p.node_id).state==="absent"&&ne(p.node_id,p.grantee)===void 0&&await se(p.node_id,"terminal",t.output_schema),await P(p.node_id,{resume:!0,capacity:"freeze"})),a.response}}await _t(e.grantee);const r=t.profile===void 0?Ye(e.grantee):Xe(t.profile),c=r.manifest.grantee??"app:terminal";if(c!==e.grantee){const a=`crtr:memory:rw:${c}:profile:${r.profileId}`;if(!e.resolved.some(p=>U(p,a))||t.scopes!==null&&!t.scopes.some(p=>U(p,a)))throw new N(403,"scope_missing",`missing scope ${a}`,"profile",void 0,a)}if(t.model!==void 0){const a=t.model;if(Ze(a)){if(a.includes("/")&&await $(e.grant)!=="app"){const p=a.lastIndexOf("/"),D=a.slice(0,p),v=a.slice(p+1);if(["ultra","strong","medium","light"].includes(v)&&et({kind:"logical",family:D,strength:v,spec:a},j(e.grantee).files,r.profileId).every(R=>R.family!==D))throw S(`model '${a}' names a model family that is not configured in this daemon`,"model")}}else if(tt(a)===void 0)throw S(`model '${a}' is not a strength (ultra, strong, medium, light), a family/strength, or a provider/model id`,"model")}const m=await Qe(),h=Le(j(e.grantee).nodes,m);if(t.isolated&&t.cwd!==void 0){const a=Ie(h,Ae(t.cwd));if(!z(t.cwd)||a===".."||a.startsWith(`..${Te}`)||z(a))throw S("cwd must be inside the isolated root node folder","cwd")}const E=await n(m,e.grantee,t.prompt),g=E.text;let o;try{o=t.message===void 0?void 0:await n(m,e.grantee,t.message)}catch(a){throw E.cleanup(),a}const _=await $(e.grant);let y;try{const a=at(r,t.model);await Ve({kind:st(r),mode:"base",root:!0,rootLifecycle:"resident",readiness:"launch",cwd:t.isolated?t.cwd??h:j(e.grantee).files,profile:r.profileId,prompt:g,nodeId:m,isolated:t.isolated??!1,...t.causedBy===void 0?{}:{causedBy:t.causedBy},...a===void 0?{}:{model:a},...t.deadline===void 0?{}:{deadlineAt:new Date(Date.now()+Ee(t.deadline)).toISOString()},...t.scopes===null?{}:{scopes:t.scopes},run:{grantee:e.grantee,sub:e.sub,grant_id:e.grant,client_id:e.client_id,metadata_json:JSON.stringify(t.metadata),run_id:m,event_cursor:1,usage_json:JSON.stringify(Y())},withinCreate:u(async(p,D)=>{if(s){const R=await q(e.grantee,s,i,p);if(R)throw new ge(R)}const v=E.uses;if(v.length&&(await de(e.grantee,v,p),await ce(v.map(({upload_id:R,path:A})=>({upload_id:R,path:A,run_id:m})),p)),y={run_id:m,node_id:m,grantee:e.grantee,grant:e.grant,rev:e.rev,scopes:t.scopes,payer:_,status:"running",created_at:D.created,metadata:t.metadata,sequence_number:0},await ie(p,m,m,"run.started",{scopes:t.scopes,payer:_,usage:Y()}),o){const R=await we(p,m,e.grantee,o,!1);y.message={run_id:m,message_id:R.messageId,sequence_number:R.sequence}}s&&await fe(p,e.grantee,s,i,m,y,D.created)},"withinCreate")},t.output_schema===void 0?void 0:async p=>{await se(p,"terminal",t.output_schema)})}catch(a){if(await O(m)||(E.cleanup(),o?.cleanup()),a instanceof ge)return a.winner.response;if(t.model!==void 0&&a instanceof Me&&a.code==="usage")throw S(a.message,"model");if(a instanceof De&&(a.code==="isolated_run"||a.code==="invalid_request")){const p=a.details&&typeof a.details=="object"&&"param"in a.details&&typeof a.details.param=="string"?a.details.param:void 0;throw new N(a.status,a.code,a.message,p)}throw a}if(!y)throw new Error("run creation did not commit");return y}u(Mn,"startRun");async function In(e,t){let s;if(t.after)try{const r=JSON.parse(Buffer.from(t.after,"base64url").toString());if(!r||typeof r!="object"||!("activity"in r)||typeof r.activity!="string"||!("id"in r)||typeof r.id!="string")throw new Error("invalid cursor");s={activity:r.activity,id:r.id}}catch{throw S("invalid list cursor","after")}const n=await(await I()).prepareUncached(`SELECT node_id, COALESCE(last_activity_at, created) AS activity FROM node_rows
|
|
9
9
|
WHERE run_id = node_id AND deleting_at IS NULL ${e===null?"":"AND grantee = ?"}
|
|
10
|
-
ORDER BY activity DESC, node_id DESC`).all(...e===null?[]:[e]),
|
|
10
|
+
ORDER BY activity DESC, node_id DESC`).all(...e===null?[]:[e]),d=await me(await k((await me(n,async({node_id:r})=>!t.visible||await t.visible(r))).filter(({activity:r,node_id:c})=>!s||r<s.activity||r===s.activity&&c<s.id),async r=>({root:await O(r.node_id),activity:r.activity})),async({root:r})=>!t.status||await C(r)===t.status),l=d.slice(0,t.limit),i=l.at(-1);return{runs:await k(l,async({root:r})=>await x(r)),next:d.length>t.limit&&i?Buffer.from(JSON.stringify({activity:i.activity,id:i.root.node_id})).toString("base64url"):null}}u(In,"listRuns");async function An(e,t,s){const n=await F(e,t),d=u(async()=>await x(await F(e,t)),"read");return!s||pe.includes(await C(n))?await d():new Promise((l,i)=>{let r=u(()=>{},"unsubscribe");const c=u(()=>{clearTimeout(o),clearInterval(g),r()},"settle"),m=u(async()=>{c();try{l(await d())}catch(_){i(_)}},"finish"),h=u(async()=>{pe.includes(String((await d()).status))&&await m()},"check"),E=u(()=>{h().catch(_=>{c(),i(_)})},"run"),g=setInterval(E,250),o=setTimeout(()=>{m()},s*1e3);mt(e,E).then(_=>{r=_},_=>{c(),i(_)})})}u(An,"waitRun");async function Tn(e,t,s=le,n=!0,d){const l=e.status==="canceled"||e.outcome_reason==="closed",i=e.grantee??"app:terminal",r=G("sha256").update(JSON.stringify(["run.message",e.node_id,t,n])).digest("hex"),c=u(async g=>{const o=await O(e.node_id),_=await(await I()).prepare("SELECT 1 FROM deliveries WHERE message_id = ? AND state = 'pending' AND canceled_at IS NULL").get(String(g.message_id));return o&&!l&&n&&!o.pi_pid&&_&&await P(e.node_id,{resume:!0,capacity:"freeze"}),g},"replay");if(d){const g=await q(i,d,r);if(g)return c(g.response)}if(l)throw new N(409,"run_settled","canceled run cannot receive a message");const m=await s(e.node_id,i,t),h=n&&e.final_report&&!e.pi_pid?(await import("../runtime/reopen.js")).commitReopenResident:void 0;let E;try{E=await W(async g=>{if(d){const y=await q(i,d,r,g);if(y)return{replayed:y.response}}await h?.(e.node_id);const o=await we(g,e.node_id,i,m,n),_={run_id:e.node_id,message_id:o.messageId,sequence_number:o.sequence};return d&&await fe(g,i,d,r,e.node_id,_,new Date().toISOString()),{result:_}})}catch(g){throw m.cleanup(),g}return"replayed"in E?(m.cleanup(),c(E.replayed)):(n&&!e.pi_pid&&await P(e.node_id,{resume:!0,capacity:"freeze"}),E.result)}u(Tn,"messageRun");async function St(e){const t=u(()=>new N(503,"service_unavailable",`node ${e} broker was unavailable before the interrupt reached it`),"unavailable");for(let s=0;s<2;s++){const n=await O(e);if(!n)throw J();if(!ee(n)){if(n.streaming)throw t();return}const d=(await V(e))?.executionId;try{await ze(e)==="turn"&&ue({nodes:[e]});return}catch(l){if(!(l instanceof Ge))throw l;const i=await O(e);if(!i)throw J();if(!i.streaming)return;if(s===0&&ee(i)&&(await V(e))?.executionId!==d)continue;throw t()}}throw t()}u(St,"interruptNode");async function Ln(e,t="stop"){const s=t==="stop"?(await(await I()).prepare("SELECT node_id FROM nodes WHERE run_id = ?").all(e.node_id)).map(({node_id:n})=>n):[e.node_id];return await Promise.all(s.map(n=>St(n))),await x(await O(e.node_id)??e)}u(Ln,"interruptRun");async function Cn(e,t={}){const s=(await(await I()).prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(i=>i.node_id);ue({run:e.node_id});const n=[];if(await C(e)!=="settled")n.push(...(await ae(e.node_id,{preserveEmpty:!0,stopReason:"run_canceled"})).closed);else for(const i of s){if(i===e.node_id)continue;const r=await O(i);r&&r.status!=="done"&&r.status!=="canceled"&&r.status!=="dead"&&n.push(...(await ae(i,{preserveEmpty:!0,stopReason:"run_canceled"})).closed)}if(await re({run_id:e.node_id},"the run was canceled"),(await Promise.all([...new Set([e.node_id,...n])].map(i=>K(i,"run_canceled")))).some(i=>!i.confirmed))throw new N(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const l=await O(e.node_id);return await x(l??e)}u(Cn,"cancelRun");const ye=200;async function kn(e,t){if(typeof t!="string"||!t.trim())throw S("name is required","name");const s=t.trim();if(s.length>ye)throw S(`name exceeds ${ye} characters`,"name");const n=await qe(e.node_id,{name:s});return n.window&&Ue(n.window,He(n)),await x(n)}u(kn,"renameRun");async function xn(e,t={config:gt,client:wt}){await re({run_id:e.node_id},"the run was deleted");const s=await W(async c=>(await c.prepare("UPDATE nodes SET deleting_at = COALESCE(deleting_at, ?) WHERE node_id = ?").run(new Date().toISOString(),e.node_id),(await c.prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(m=>m.node_id)));if((await Promise.all(s.map(c=>K(c,"run_deleted",{deleting:!0})))).some(c=>!c.confirmed))throw new N(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const d=await k(s,async c=>{const m=await We(c);if(m.app===null)throw new Error(`run node missing during deletion: ${c}`);return m}),l=await(await I()).prepare("SELECT DISTINCT session_id FROM sessions WHERE session_id IS NOT NULL AND node_id IN (SELECT node_id FROM nodes WHERE run_id = ?)").all(e.node_id);for(const{session_id:c}of l)try{await Z().delete(c)}catch(m){if(!Be(m))throw m}const i=await W(async c=>{for(const g of s){const o=await xe(c,g);o!==null&&o.deleted_at===null&&await ke(c,o)}const m=await yt([e.node_id],c);await c.prepare("DELETE FROM run_events WHERE run_id = ?").run(e.node_id),await c.prepare("DELETE FROM idempotency_keys WHERE run_id = ?").run(e.node_id);const h=s.map(()=>"?").join(","),E=await c.prepareUncached(`SELECT message_id FROM messages WHERE sender_node_id IN (${h}) UNION SELECT message_id FROM deliveries WHERE destination_id IN (${h})`).all(...s,...s);await c.prepareUncached(`DELETE FROM deliveries WHERE destination_id IN (${h})`).run(...s);for(const{message_id:g}of E)await c.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(g,g);return m});for(const c of d)await Fe(c);const{notifyRunDeleted:r}=await import("./events.js");return r(e.node_id),{uploads_pending:await Nt(i,t)}}u(xn,"deleteRun");async function Nt(e,t){if(!e.length||!t.config())return e.length;let s;try{s=t.client()}catch{return e.length}const n=new Set,d=e.map(i=>s.deleteUpload(i).then(async()=>{await Et(i),n.add(i)},()=>{}));let l;return await Promise.race([Promise.all(d),new Promise(i=>{l=setTimeout(i,t.budgetMs??ht),l.unref?.()})]),clearTimeout(l),e.length-n.size}u(Nt,"deleteReleasedUploads");async function Wn(e,t,s){await F(e,t),await Q(e);const n=await W(async o=>{const _=await o.prepare("SELECT node_id, parent FROM nodes WHERE run_id = ? ORDER BY CASE WHEN node_id = ? THEN 0 ELSE 1 END, created, node_id").all(e,e),y=new Map;for(const R of _)y.set(R.node_id,(await o.prepare("SELECT session_id FROM sessions WHERE node_id = ? GROUP BY session_id ORDER BY min(created_at)").all(R.node_id)).map(A=>A.session_id));const p=(await o.prepare("SELECT event_cursor FROM nodes WHERE node_id = ?").get(e)).event_cursor-1,D=await o.prepare(`SELECT node_id, sequence_number FROM run_events
|
|
11
11
|
WHERE run_id = ? AND sequence_number <= ? AND type IN ('node.thinking.done', 'node.output_text.done', 'usage')
|
|
12
|
-
ORDER BY sequence_number`).all(e,
|
|
12
|
+
ORDER BY sequence_number`).all(e,p),v=await o.prepare(`SELECT node_id, sequence_number, type, body_json FROM run_events
|
|
13
13
|
WHERE run_id = ? AND sequence_number <= ? AND type IN ('node.thinking.delta', 'node.output_text.delta')
|
|
14
|
-
ORDER BY sequence_number`).all(e,
|
|
14
|
+
ORDER BY sequence_number`).all(e,p);return{nodes:_,sessionIds:y,latestSequence:p,completed:D,deltas:v}}),{nodes:d,sessionIds:l,latestSequence:i,completed:r,deltas:c}=n,m=await k(d,async o=>({node_id:o.node_id,parent_node_id:o.parent,conversations:await k(l.get(o.node_id)??[],async _=>{const{header:y,entries:a}=await Z().read(_);if(s==="entries")return{conversation_id:_,header:y,entries:a};const p=Ce.inMemory(y.cwd,void 0,[y,...a]),D=it(p)??[],v=new Map(a.map((w,b)=>[w.id,b])),R=a.filter(w=>w.type==="custom"&&w.customType==="crtr-system-prompt").map(w=>({id:w.id,message:{role:"custom",customType:"crtr-system-prompt",data:"data"in w?w.data:void 0,timestamp:w.timestamp}})),A=a.filter(w=>w.type==="custom_message"&&w.customType==="app_message").map(w=>({id:w.id,message:{role:"custom",customType:"app_message",content:"content"in w?w.content:"",timestamp:w.timestamp}})),he=o.node_id===e?a.find(w=>{if(w.type!=="message"||w.message.role!=="user")return!1;const b=te(a,w.message.timestamp);return b?.type==="runtime"&&b.kind==="kickoff"})?.id:void 0,Re=[...D.filter(({id:w})=>!A.some(b=>b.id===w)),...R,...A].sort((w,b)=>(v.get(w.id)??Number.MAX_SAFE_INTEGER)-(v.get(b.id)??Number.MAX_SAFE_INTEGER)).map(({id:w,message:b})=>{const f=b,T=f.usage,H=f.role==="user"?te(a,Number(f.timestamp)):null,Se=H?.type==="human"||w===he,L=f.role==="toolResult"?"tool_result":f.role==="bashExecution"?"bash_execution":f.role==="compactionSummary"?"compaction_summary":f.role==="branchSummary"?"branch_summary":f.role==="custom"&&f.customType==="crtr-system-prompt"?"system":f.role==="user"?Se?"user":"custom":f.role,Ne=L==="custom"?f.role==="custom"?f.customType:H?.type==="runtime"?H.kind:"unknown":void 0,ve=L==="system"&&f.customType==="crtr-system-prompt"?[{type:"text",text:f.data?.text??""}]:typeof f.content=="string"?[{type:"text",text:f.content}]:Array.isArray(f.content)?f.content.map(M=>M.type==="toolCall"?{type:"tool_call",tool_call_id:M.id,name:M.name,arguments:M.arguments}:M.type==="image"?{type:"image",mime_type:M.mimeType}:M.type==="thinking"?{type:"thinking",text:M.thinking}:M):[];return{entry_id:w,role:L,...L==="custom"?{custom_type:Ne}:{},time:typeof f.timestamp=="string"?f.timestamp:new Date(Number(f.timestamp??Date.now())).toISOString(),content:ve,...L==="assistant"?{model:f.model,provider:f.provider,stop_reason:f.stopReason,...f.errorMessage?{error_message:f.errorMessage}:{},...T?{usage:{input_tokens:T.input??0,output_tokens:T.output??0,cache_read_tokens:T.cacheRead??0,cache_write_tokens:T.cacheWrite??0,cost_usd:T.cost?.total??0}}:{}}:{},...L==="tool_result"?{tool_call_id:f.toolCallId,tool_name:f.toolName,is_error:f.isError}:{}}})??[];return{conversation_id:_,messages:Re}})})),h=new Map(m.map(o=>[o.node_id,ct(o.node_id)]));for(const o of r){const _=h.get(o.node_id);_!=null&&o.sequence_number>=_&&h.set(o.node_id,null)}const E=new Map;for(const o of c){const _=h.get(o.node_id);if(_==null||o.sequence_number<_)continue;const y=JSON.parse(o.body_json),a=E.get(o.node_id)??{thinking:"",text:""};o.type==="node.thinking.delta"?a.thinking+=y.delta:a.text+=y.delta,E.set(o.node_id,a)}const g=m.map(o=>({...o,in_progress_message:h.get(o.node_id)==null?null:E.get(o.node_id)??{thinking:"",text:""}}));return{run_id:e,latest_sequence:i,nodes:g}}u(Wn,"traceRun");function Fn(e,t,s){if(t===void 0){if(!e.some(n=>U(n,"crtr:llm")))throw new N(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return null}if(!Array.isArray(t)||t.some(n=>typeof n!="string"))throw S("scopes must be a list of scope strings","scopes");for(const n of t){try{ut(n)}catch{throw S(`invalid scope ${n}`,"scopes")}if(/^crtr:files:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))throw S(`own-app files cannot narrow a run: ${n}`,"scopes");if(!(/^crtr:memory:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))&&!be(e,n))throw new N(403,"scope_missing",`missing scope ${n}`,void 0,void 0,n)}if(!t.includes("crtr:llm"))throw new N(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return t}u(Fn,"requestedScopes");export{X as IDEMPOTENCY_WINDOW_MS,Rt as RUN_DEADLINE_MAX_MS,ht as RUN_DELETE_STORAGE_BUDGET_MS,ye as RUN_NAME_MAX,N as RunError,Cn as cancelRun,xn as deleteRun,bn as idempotencyKeyOf,Ln as interruptRun,In as listRuns,Tn as messageRun,F as ownedRun,Ee as parseRunDeadlineMs,Dn as pruneExpiredIdempotencyKeys,kn as renameRun,Fn as requestedScopes,On as runIsRunning,x as runObject,Mn as startRun,Wn as traceRun,An as waitRun};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var R=Object.defineProperty;var p=(n,c)=>R(n,"name",{value:c,configurable:!0});import{createServer as E,request as S}from"node:http";import{chmodSync as w,existsSync as u,rmSync as _,unlinkSync as h}from"node:fs";import{join as m}from"node:path";import{apiSocketPath as B,BROKER_RELEASED_MARKER as C,BROKER_RELAY_GENERATION as k,nodeRunDir as y}from"../../canvas/paths.js";import{writeFileBeneath as v}from"../../spaces/open-beneath.js";import{currentCausedBy as A}from"./turn-cause.js";async function P(n,c){const r=m(y(n),"cli.sock"),o=E((t,e)=>{const a={...t.headers,authorization:`Bearer ${c}`},l=A();l!==void 0&&a["crtr-caused-by"]===void 0&&(a["crtr-caused-by"]=l),delete a.connection;const d=S({socketPath:B(),path:t.url,method:t.method,headers:a},s=>{e.writeHead(s.statusCode??502,s.headers),s.pipe(e)});d.on("error",s=>{e.headersSent||e.writeHead(503,{"content-type":"application/json"}),e.end(JSON.stringify({error:{code:"daemon_unavailable",message:s.message}}))}),t.pipe(d),e.on("close",()=>d.destroy())});u(r)&&h(r),await new Promise((t,e)=>{o.once("error",e),o.listen(r,()=>{o.off("error",e),t()})}),w(r,384);const i=y(n),f=process.env.CRTR_EXECUTION_ID;if(!f)throw new Error("broker relay has no execution id");return v(i,m(i,k),f,{atomic:!0}),_(m(i,C),{force:!0}),{path:r,close(){o.closeAllConnections(),o.close(),u(r)&&h(r)}}}p(P,"serveCliRelay");export{P as serveCliRelay};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var W=Object.defineProperty;var
|
|
2
|
-
`))>=0;){const f=g.slice(0,m).trim();g=g.slice(m+1),f&&$(f)}}if(g+=I.decode(),g.trim()&&$(g.trim()),!T||!O)throw new Error("llm stream ended without usage or served_model");for(const[l,s]of o.content.entries())s.type==="text"&&r.push({type:"text_end",contentIndex:l,content:s.text,partial:o}),s.type==="thinking"&&r.push({type:"thinking_end",contentIndex:l,content:s.thinking,partial:o});if(w==="content_filter")throw new
|
|
1
|
+
var W=Object.defineProperty;var c=(e,t)=>W(e,"name",{value:t,configurable:!0});import{setTimeout as j}from"node:timers/promises";import{createAssistantMessageEventStream as J,getCurrentSystemPrompt as Y,getCurrentTools as z}from"@earendil-works/pi-ai";import{socketFetch as H}from"../../../api/node-transport.js";import{apiSocketPath as X}from"../../canvas/paths.js";import{currentNodeToken as G}from"./node-token.js";import{currentCausedBy as K}from"./turn-cause.js";import{envModelExact as C,envModelIntent as V}from"../../../shared/env.js";import{MODEL_CONTEXT_BODY_MAX_BYTES as b}from"../../llm/body-limits.js";import{modelRequestFromConfig as Q}from"../../model-routes.js";import{parseProviderRateLimit as Z,providerFailureDiagnostic as E}from"../../provider-failure.js";import{UPSTREAM_MODEL_UNAVAILABLE as R}from"../../fault-classifier.js";function ye(e,t){e.checkAuth=async n=>e.getProvider(n)?{type:"api_key"}:void 0,e.getAvailable=async n=>e.getModels(n),e.getAvailableSnapshot=()=>e.getModels(),e.streamSimple=(n,d,r)=>re(n,d,r,t)}c(ye,"configureBrokerModelRuntime");const ee=300,B="crtr:llm-refusal";class k extends Error{static{c(this,"LlmRefusalError")}retryAt;rateLimit;code;status;constructor(t,n,d,r,o){super(t),this.retryAt=n,this.rateLimit=d,this.code=r,this.status=o}}class S extends Error{static{c(this,"UpstreamModelUnavailableError")}}function N(e,t){const n=e===void 0?"the request body":`the request body (${e} bytes)`;return new Error(`request_too_large: ${n} exceeds the ${t}-byte model request limit; compact the conversation to shrink the context`)}c(N,"contextTooLargeError");function A(e){const t=e.details?.rate_limit;if(!t||typeof t!="object")return;const n=Z(t);if(n===void 0)return;const{provider:d,model:r}=t;return typeof d=="string"&&d!==""&&typeof r=="string"&&r!==""?{...n,model:`${d}/${r}`}:n}c(A,"refusalRateLimit");function _e(e){for(const t of e.diagnostics??[]){if(t.type!==B)continue;const n=t.details?.retryAt;if(typeof n=="number"&&Number.isFinite(n)&&n>0)return n}}c(_e,"refusalRetryAt");class D extends Error{static{c(this,"ContentFilteredError")}}function q(e){return typeof e=="string"?e:e.map(t=>t.type==="text"?{type:"text",text:t.text}:{type:"image_url",image_url:{url:`data:${t.mimeType};base64,${t.data}`}})}c(q,"wireContent");function te(e){const t=c(r=>r.role==="assistant"&&(r.stopReason==="error"||r.stopReason==="aborted"),"incomplete"),n=e.some(t)?e.filter(r=>!t(r)):e;let d=n.length;for(;d>0&&n[d-1]?.role==="assistant";)d--;return d===n.length?n:n.slice(0,d)}c(te,"wireHistory");function ne(e,t,n,d){const r=[],o=Y(t.messages),a=z(t.messages);o?r.push({role:"system",content:o}):t.systemPrompt&&r.push({role:"system",content:t.systemPrompt});for(const p of te(t.messages))p.role==="user"?r.push({role:"user",content:q(p.content)}):p.role==="toolResult"?r.push({role:"tool",content:q(p.content),tool_call_id:p.toolCallId}):p.role==="assistant"&&r.push({role:"assistant",content:p.content.filter(u=>u.type==="text").map(u=>u.text).join("")||null,tool_calls:p.content.filter(u=>u.type==="toolCall").map(u=>({id:u.id,type:"function",function:{name:u.name,arguments:JSON.stringify(u.arguments)}}))});const x=`${e.provider}/${e.id}`,_=d??V();return{model:Q(x,_,C())?.kind==="logical"?_:x,model_policy:C()?"exact":"substitute",stream:!0,messages:r,...a.length?{tools:a.map(p=>({type:"function",function:{name:p.name,description:p.description,parameters:p.parameters}}))}:{},...n.reasoning?{reasoning_effort:n.reasoning}:{},...n.temperature!==void 0?{temperature:n.temperature}:{},...n.maxTokens!==void 0?{max_tokens:n.maxTokens}:{}}}c(ne,"requestBody");function L(e,t){if(typeof t!="string")return!1;const n=t.indexOf("/");return n<1||n===t.length-1?!1:(e.provider=t.slice(0,n),e.model=t.slice(n+1),!0)}c(L,"applyServedModel");function F(e){if(e.details?.served_model!==void 0)return e.details.served_model;const t=e.details?.rate_limit;return typeof t?.provider=="string"&&typeof t.model=="string"?`${t.provider}/${t.model}`:void 0}c(F,"refusalRoute");function P(e){if(!e||typeof e!="object"||!("error"in e))throw new Error("llm returned an invalid response");const t=e.error;if(!t||typeof t.message!="string")throw new Error("llm returned an invalid refusal");return t}c(P,"parseRefusal");function oe(){const e=K();return e===void 0?{}:{"crtr-caused-by":e}}c(oe,"causedByHeader");function re(e,t,n={},d){const r=J(),o={role:"assistant",content:[],api:e.api,provider:e.provider,model:e.id,usage:{input:0,output:0,cacheRead:0,cacheWrite:0,totalTokens:0,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:0}},stopReason:"pending",timestamp:Date.now()};return(async()=>{const a=G();if(!a)throw new Error("llm requires a node token");const x=JSON.stringify(ne(e,t,n,d)),_=Buffer.byteLength(x);if(_>b)throw N(_,b);let p=0;for(;;){n.signal?.throwIfAborted();const u=await H(X())("http://localhost/v1/llm",{method:"POST",headers:{authorization:`Bearer ${a}`,"content-type":"application/json",...oe()},body:x,signal:n.signal});if(!u.ok){const l=P(await u.json());if(u.status===413||l.code==="payload_too_large")throw N(_,b);if(L(o,F(l)),l.retryable!==!0)throw new k(l.message,void 0,A(l),l.code,u.status);const s=l.retry_after_s;if(typeof s!="number"||!Number.isFinite(s)||s<=0)throw l.code===R?new S(l.message):new Error(l.message);const m=ee-p;if(s>m){const f=Date.now()+s*1e3;throw new k(`${l.message} (retry after ${s}s, at ${new Date(f).toISOString()})`,f,A(l))}await j(s*1e3,void 0,{signal:n.signal}),p+=s;continue}if(!u.body)throw new Error("llm returned no stream");r.push({type:"start",partial:o});const U=u.body.getReader(),I=new TextDecoder;let g="",w="stop",M,T=!1,O=!1;const $=c(l=>{const s=JSON.parse(l);if(s.error){const i=P(s);throw L(o,F(i)),i.retryable!==!0?new k(i.message,void 0,A(i),i.code):i.code===R?new S(i.message):new Error(i.message)}if(s.served_model){if(O=!0,s.served_model.indexOf("/")<1)throw new Error("llm returned an invalid served_model");L(o,s.served_model)}const m=s.choices?.[0],f=m?.delta;if(f?.reasoning_content){const i=o.content.findIndex(v=>v.type==="thinking"),h=i<0?{type:"thinking",thinking:""}:o.content[i],y=i<0?o.content.push(h)-1:i;if(i<0&&r.push({type:"thinking_start",contentIndex:y,partial:o}),h.type!=="thinking")throw new Error("invalid thinking block");h.thinking+=f.reasoning_content,r.push({type:"thinking_delta",contentIndex:y,delta:f.reasoning_content,partial:o})}if(f?.content){const i=o.content.findIndex(v=>v.type==="text"),h=i<0?{type:"text",text:""}:o.content[i],y=i<0?o.content.push(h)-1:i;if(i<0&&r.push({type:"text_start",contentIndex:y,partial:o}),h.type!=="text")throw new Error("invalid text block");h.text+=f.content,r.push({type:"text_delta",contentIndex:y,delta:f.content,partial:o})}for(const i of f?.tool_calls??[]){const h={type:"toolCall",id:i.id,name:i.function.name,arguments:JSON.parse(i.function.arguments)},y=o.content.push(h)-1;r.push({type:"toolcall_start",contentIndex:y,partial:o}),r.push({type:"toolcall_end",contentIndex:y,toolCall:h,partial:o})}m?.finish_reason&&(w=m.finish_reason),m?.message?.refusal&&(M=m.message.refusal),s.usage&&(T=!0,o.usage={input:s.usage.prompt_tokens,output:s.usage.completion_tokens,cacheRead:s.usage.cache_read_tokens,cacheWrite:s.usage.cache_write_tokens,totalTokens:s.usage.total_tokens,cost:{input:0,output:0,cacheRead:0,cacheWrite:0,total:typeof s.usage.usd_equivalent=="number"&&Number.isFinite(s.usage.usd_equivalent)?s.usage.usd_equivalent:0}})},"apply");for(;;){const{value:l,done:s}=await U.read();if(s)break;g+=I.decode(l,{stream:!0});let m;for(;(m=g.indexOf(`
|
|
2
|
+
`))>=0;){const f=g.slice(0,m).trim();g=g.slice(m+1),f&&$(f)}}if(g+=I.decode(),g.trim()&&$(g.trim()),!T||!O)throw new Error("llm stream ended without usage or served_model");for(const[l,s]of o.content.entries())s.type==="text"&&r.push({type:"text_end",contentIndex:l,content:s.text,partial:o}),s.type==="thinking"&&r.push({type:"thinking_end",contentIndex:l,content:s.thinking,partial:o});if(w==="content_filter")throw new D(M??"Content filtered");if(!["stop","tool_calls","length"].includes(w))throw new Error(`llm returned unknown finish reason: ${w}`);o.stopReason=w==="tool_calls"?"toolUse":w==="length"?"length":"stop",r.push({type:"done",reason:o.stopReason,message:o}),r.end();return}})().catch(a=>{o.stopReason=n.signal?.aborted?"aborted":"error",o.errorMessage=a instanceof Error?a.message:String(a),a instanceof k&&(o.diagnostics=[{type:B,timestamp:Date.now(),...a.retryAt!==void 0?{details:{retryAt:a.retryAt}}:{}},...a.rateLimit!==void 0?[E({status:429,ratelimit:a.rateLimit})]:[],...a.rateLimit===void 0&&a.code==="cap_exhausted"?[E({status:a.status??402,code:a.code})]:[]]),a instanceof S&&(o.diagnostics=[E({status:503,code:R})]),a instanceof D&&o.stopReason==="error"&&(o.rawStopReason="content_filter"),r.push({type:"error",reason:o.stopReason,error:o}),r.end()}),r}c(re,"streamBrokerModel");export{ee as LLM_BROKER_RETRY_WINDOW_S,B as LLM_REFUSAL_DIAGNOSTIC,ye as configureBrokerModelRuntime,_e as refusalRetryAt,ne as requestBody,re as streamBrokerModel,te as wireHistory};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import type { BrokerSession } from './read-ops.js';
|
|
2
|
+
export declare function setTurnCauseSource(source: () => BrokerSession): void;
|
|
3
|
+
type Branch = ReturnType<BrokerSession['sessionManager']['getBranch']>;
|
|
4
|
+
export declare function turnCauseOf(branch: Branch): string | undefined;
|
|
5
|
+
/** `message:<id>` of the turn running now, or undefined. */
|
|
6
|
+
export declare function currentCausedBy(): string | undefined;
|
|
7
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var f=Object.defineProperty;var r=(s,e)=>f(s,"name",{value:e,configurable:!0});let u;function c(s){u=s}r(c,"setTurnCauseSource");function a(s){let e=[],t;for(const n of s)if(n.type==="custom"&&n.customType==="crtr-turn-input"){const i=n.data?.message_ids;Array.isArray(i)&&e.push(...i.filter(o=>typeof o=="string"))}else(n.type==="message"&&n.message.role==="user"||n.type==="custom_message")&&(e.length>0?(t=e[0],e=[]):t=void 0);return t===void 0?void 0:`message:${t}`}r(a,"turnCauseOf");function p(){return u===void 0?void 0:a(u().sessionManager.getBranch())}r(p,"currentCausedBy");export{p as currentCausedBy,c as setTurnCauseSource,a as turnCauseOf};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var Pe=Object.defineProperty;var n=(t,o)=>Pe(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Oe,envModelIntent as Ie,envNodeCwd as De,envNodeId as Ne,envProfileId as Fe,envScopes as Le,isSandboxedNode as $e,scopeAllowed as Be}from"../../shared/env.js";import{createServer as Ue}from"node:net";import{existsSync as ye,readFileSync as Ge,unlinkSync as be}from"node:fs";import{join as Te}from"node:path";import{randomUUID as x}from"node:crypto";import{mark as Ke}from"../timing.js";import{SUBMIT_RESULT_TOOL as je}from"./structured-output.js";import{installSessionManagerStorePatch as We}from"../conversation-store/index.js";import{getAgentDir as Y,ModelRegistry as qe,ModelRuntime as Ve}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Xe,viewSocketPath as He}from"../canvas/paths.js";import{bindBrokerEventSource as Ye}from"../events/source.js";import{emitEvent as T,flushBrokerLog as ze}from"../events/emit.js";import{operationIdContext as Je}from"../events/operation-id.js";import{findMissingPackagePaths as Qe}from"./package-health.js";import{installBrokerConfigSnapshot as Ze}from"../config.js";import{FRONT_DOOR_ENV as en}from"./front-door.js";import{CANVAS_EXTENSIONS as re,piInvocationToSdkConfig as nn}from"./launch.js";import{assertEngineVersion as tn,loadBrokerEngine as rn}from"./broker-sdk.js";import{initCrtrTheme as on}from"./crtr-theme.js";import{resolveBundledPiPackageDir as sn}from"./pi-cli.js";import{captureSessionChatCapabilities as an}from"./command-surface.js";import{InMemoryCredentialStore as dn}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as ln}from"./broker/model-adapter.js";import{mutateBrokerFault as z,recordBrokerTurn as Re}from"./broker/daemon-ops.js";import{modelRequestFromConfig as cn,expandModelCandidates as mn,parseModelSpec as un,unregisteredConcreteModel as fn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as pn}from"./stream-watchdog.js";import{probeOnline as gn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as vn,cycleAwareMessages as hn,endedByAbort as wn}from"./session-cycles.js";import{turnErrorOf as Sn}from"../llm/refusal.js";import{projectTranscript as _n}from"./session-visibility.js";import{currentTurnVisibility as yn}from"./turn-visibility.js";import{isUnknownModel as oe}from"./model-selection.js";import{BrokerClientRegistry as bn}from"./broker/client-registry.js";import{ToolGroupTracker as Tn}from"./broker/tool-groups.js";import{TurnReplyTracker as Rn}from"./broker/turn-replies.js";import{onNodeNamed as kn}from"./broker/node-named.js";import{FaultRetry as En,willDaemonRetry as Mn}from"./broker/fault-retry.js";import{RunTurnEnds as xn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as Cn}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as An,BROKER_RUN_TURN_BUSY as Pn}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as On,settleRunDeferredMail as In}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Dn}from"./broker/run-turn-queue.js";import{EventProjection as Nn}from"./broker/event-projection.js";import{createFrameDispatchContext as Fn,handleFrame as Ln}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as $n,installAdvertisedCommandInvocationContract as Bn}from"./advertised-command-invocation.js";import{RebindDriver as Un}from"./broker/rebind.js";import{beginRuntimeTeardown as Gn}from"./broker/extension-abort.js";import{receiveNodeToken as Kn}from"./broker/node-token.js";import{serveCliRelay as jn}from"./broker/cli-relay.js";import{decodeKickoffOrigin as Wn,KICKOFF_ORIGIN_ENV as qn}from"./stamp/protocol.js";import{announceMessageOrigin as Vn}from"./stamp/channel.js";import{brokerExtensionState as Xn,commitBrokerModel as Hn}from"./broker/daemon-ops.js";import{composerNames as Yn}from"./broker/frame-memory-refs.js";import{FrameOverflowError as zn,normalizeSnapshotTail as Jn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as ur,REVIEW_BOUNDARY_NAVIGATION_CODE as fr}from"./broker/frame-replies.js";function ie(t){return new qe(t.modelRuntime)}n(ie,"registryOf");function B(t,o){if(t==null||oe(t))return null;const s=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${s}`}n(B,"formatModelSpec");function Qn(t,o){const s=B(t,void 0);return s===null?null:`${s}:${o===void 0||o===""?"off":o}`}n(Qn,"formatExactModelSpec");const Zn=12e4;let J=null;import{brokerSignalClient as Q}from"./broker/signal-stream.js";function et(){Q().stop();const t=J;if(J=null,t!==null)try{t.dispose()}catch{}}n(et,"disposeActiveSession");function nt(t,o){const s=Be(o,"crtr:act")?void 0:["bash"],m=t!==void 0&&t.length>0?[...new Set([...t,je])]:t===void 0?void 0:[...t];return{...m!==void 0?{tools:m}:{},...s!==void 0?{excludeTools:s}:{}}}n(nt,"brokerToolOptions");async function lr(t,o=process.hrtime.bigint(),s=new Date().toISOString()){Ye(t);const m=await Kn(),i=await jn(t,m);process.env.CRTR_API_SOCKET=i.path,Je.fresh(()=>{T({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),T({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 l=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Ke(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),T({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:l,model:r}}))},"emitStartupMilestone");process.env[en]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,We(t);const p=await rn();tn(p.VERSION),l=p.VERSION;const S=Xe(t),k=Te(S,"broker-launch.json"),_=JSON.parse(Ge(k,"utf8"));if($e()){if(!_.configSnapshot)throw new Error("broker launch is missing its config snapshot");Ze(_.configSnapshot)}const f=nn(_);f.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await Yn(t);let b,C;const V=n(e=>{b!==void 0?b(e):C??=e},"onSignal");process.on("SIGTERM",()=>V("SIGTERM")),process.on("SIGINT",()=>V("SIGINT"));let{session:U,services:A,resuming:ae,runtime:G}=await it(p,f);d("broker.startup.session_built");const E=(await Xn(t)).node.review_binding?.review_id,R=Oe();J=U;const D=gn;try{process.env.PI_PACKAGE_DIR=sn(),on(A.settingsManager.getTheme(),Y(),!1)}catch(e){T({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of Qe(Y()))T({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const K=He(t),g=new bn(t),X=new Map,O=new Tn(t,e=>g.broadcast(e)),j=new Rn(t,e=>g.broadcast(e));kn(e=>g.broadcast({type:"node_named",...e}));let N=!1,de=!1,H,le,u,W;const Z=new xn;let F,ce=n(()=>{},"notifyTurnAccepted"),me=n(()=>{},"resetFrameState");const ee=Cn();let ue=n(()=>0,"pendingPromptDispatches"),fe;const L=Dn({runNode:R,session:n(()=>u.session(),"session"),isReplacing:n(()=>u.isReplacing(),"isReplacing"),pendingRebind:n(()=>u.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>u.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>ue(),"pendingDispatches"),turnAdmission:ee,prependDeferred:n(e=>On(t,e),"prependDeferred"),onError:n(e=>T({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")}),pe=L.drain;f.firstPrompt!==void 0&&f.firstPrompt!==""&&L.holdForKickoff(),globalThis[An]=L.start,globalThis[Pn]=L.busy,u=new Un({nodeId:t,cfg:f,session:U,services:A,runtime:G,registry:g,toolGroups:O,turnReplies:j,transcriptMessages:n(e=>se(e,E)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>le,"uiContext"),faultRetry:n(()=>W,"faultRetry"),projection:n(()=>F,"projection"),setActiveSession:n(e=>{if(J=e,fe?.(),R){let r="stop",c,v=!1;fe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",c=void 0,v=!1,Z.started()),h.type==="agent_end"){const w=[...h.messages??[]].reverse().find($=>$.role==="assistant");w&&(r=w.stopReason,c=wn(w)?void 0:Sn(w),v=w.role==="assistant"&&Mn(w,e.model?.contextWindow))}h.type==="agent_settled"&&(Z.settled(e.sessionManager,{stop_reason:r,...c?{error:c}:{}},v),In(t,e).catch(w=>{T({level:"error",event:"broker.run_deferred_mail.settle_failed",error:w})}),queueMicrotask(()=>{u.session()===e&&pe()}))})}},"setActiveSession"),disposeAndExit:n((e,r)=>q(e,r),"disposeAndExit"),onSessionRebind:n(()=>{me()},"onSessionRebind"),onReplacementIdle:n(()=>{R&&pe()},"onReplacementIdle"),reWelcomeAll:n(()=>ne(),"reWelcomeAll")});const ge=n(async(e,r=!1)=>{const c=u.session(),v=B(c.model,c.thinkingLevel);if(v===null)return null;const h=await Hn(t,{spec:v,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(f.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,f.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",f.modelExact=!0)),h.modelOverride},"persistModelChoice"),ve=n(async(e=!0,r,c=!1)=>{const v=u.session(),h=B(v.model,v.thinkingLevel),w=e?await ge(r,c):h;g.broadcast({type:"model_changed",model:oe(v.model)?void 0:v.model,spec:w})},"broadcastModelChanged");W=new En({nodeId:t,cfg:f,retryProbe:D,currentSession:n(()=>u.session(),"currentSession"),currentServices:n(()=>u.services(),"currentServices"),installedGeneration:n(()=>u.installedGeneration(),"installedGeneration"),registryOf:ie,formatModelSpec:B,broadcastModelChanged:ve,turnAdmission:ee,reWelcomeAll:n(()=>ne(),"reWelcomeAll"),...R?{turnEnds:Z}:{}});const he=n(()=>{W.rearmIfStranded().catch(e=>{T({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");Q().subscribe("resync",he),Q().subscribe("fault-retry",he),F=new Nn({registry:g,faultRetry:W,installedGeneration:n(()=>u.installedGeneration(),"installedGeneration"),currentSession:n(()=>u.session(),"currentSession"),notifyTurnAccepted:n(()=>ce(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:B});const Ee=n(e=>{const r=u.session(),c=se(r,E),v=Jn(e.snapshotTail),h=c===void 0||v===void 0?c:c.slice(-v),w=h?.map(({message:I})=>I)??r.sessionManager.buildSessionContext().messages,$=O.summaries(),_e=h!==void 0&&v!==void 0?tt(w):void 0,Ae=_e===void 0?$:Object.fromEntries(Object.entries($).filter(([I])=>_e.has(I)));return{messages:w,...h===void 0?{}:{messageIds:h.map(({id:I})=>I)},messageVisibility:h?.map(({visibility:I})=>I)??w.map(()=>"visible"),turnVisibility:yn(),stats:r.getSessionStats(),state:{model:oe(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:{...g.displaySnapshot()},toolGroupSummaries:Ae,turnReplies:j.snapshot(),workingActivity:F.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),we=n(e=>{const r=e.role==="controller"?X.values().next().value:void 0;g.sendFrame(e,{type:"welcome",snapshot:Ee(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:Y()},!0)},"sendWelcome"),Me=n(e=>{const r=[...X.values()];for(let c=1;c<r.length;c++)g.sendFrame(e,r[c].request)},"replayExtraPendingDialogsTo"),ne=n(()=>{try{const e=u.session();j.seed(se(e,E)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){T({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}g.forEachHelloed(we)},"reWelcomeAll"),Se=n(async e=>{if(!N){N=!0,Q().stop(),O.persistPendingSummary(),F.dispose(),et();try{H?.close()}catch{}i.close(),g.dispose();try{ye(K)&&be(K)}catch{}g.clearAttachState(),await ze(),process.exit(e)}},"completeExit"),q=n((e,r=0)=>{if(N)return;const c=e==="shutdown-hook"||e==="shutdown-after-settle";if(c&&O.finishOpenToolGroup(!0),c&&(O.hasSummaryTasks()||j.hasTasks())){if(de)return;de=!0,Promise.allSettled([O.waitForSummaryTasks(),j.waitForTasks()]).finally(()=>Se(r));return}Se(r)},"disposeAndExit");le=st({writable:n(()=>g.writableClients(),"writable"),forward:n((e,r)=>g.sendFrame(e,r),"forward"),pending:X,broadcast:n(e=>g.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>F.knownStreamWait(e),"onKnownStreamWait")}),u.setRebindSession(),await u.enqueueRebind(U,A),d("broker.startup.extensions_bound");const M=Fn({nodeId:t,registry:g,toolGroups:O,projection:F,rebind:u,boundaryReviewId:E,pendingDialogs:X,sendWelcome:we,replayExtraPendingDialogsTo:Me,reWelcomeAll:ne,disposeAndExit:q,persistModelChoice:ge,broadcastModelChanged:ve,registryOf:ie,formatModelSpec:B,formatExactModelSpec:Qn,turnAdmission:ee,memoryInventory:y,runNode:R,onKickoffAdmitted:L.releaseKickoff});ce=M.notifyTurnAccepted,me=M.resetForSession,ue=M.pendingPromptDispatches;const xe=2500;let te=!1;const Ce=n(async e=>{if(N||te)return;if(te=!0,u.isAgentRunActive()||u.session().isStreaming||M.pendingPromptDispatches()>0){const c=Date.now()+xe;for(;M.pendingPromptDispatches()>0&&!u.session().isStreaming&&Date.now()<c;)await new Promise(v=>setTimeout(v,25));if(u.session().isStreaming){const v=c-Date.now();if(v>0){let h;try{Gn(),await Promise.race([u.session().abort().then(()=>!0,()=>!1),new Promise($=>{h=setTimeout(()=>$(!1),v)})])&&await Re(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(M.pendingPromptDispatches()>0||u.isAgentRunActive())&&await Re(t,{event:"interrupted"})}q(e)},"abortAndExit");if(b=n(e=>{Ce(e)},"signalTeardown"),C!==void 0){b(C);return}try{ye(K)&&be(K)}catch{}H=Ue(e=>{const r=g.create(e);e.on("data",v=>{let h;try{h=r.decoder.push(v)}catch(w){w instanceof zn?(g.sendFrame(r,{type:"error",code:"frame_overflow",message:w.message}),g.dropClient(r,`frame overflow: ${w.message}`)):g.dropClient(r,`decoder error: ${String(w)}`);return}for(const w of h)try{Ln(M,r,w)}catch{}});const c=n(()=>{g.removeClient(r)},"drop");e.on("close",c),e.on("error",()=>{})}),H.on("error",e=>{N||(T({level:"error",event:"broker.socket.failed",error:e}),q("socket-error",1))}),H.listen(K,async()=>{Promise.all([z(t,{op:"clear",link:"viewer\u2194broker"}),z(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await W.recoverOnStartup()}catch(r){T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),q("recovery-startup-failed",1);return}if(!(N||te))if(e!=="retry-armed"&&f.firstPrompt!==void 0&&f.firstPrompt!==""){const r=Wn(process.env[qn]);r!==null&&Vn(f.firstPrompt,r);const c=process.env.CRTR_KICKOFF_MESSAGE_IDS;M.kickoff(f.firstPrompt,c?JSON.parse(c):[])}else L.releaseKickoff()}),g.persistAttachState()}n(lr,"runBroker");function tt(t){const o=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const m of s.content)m!==null&&typeof m=="object"&&m.type==="toolCall"&&typeof m.id=="string"&&o.add(m.id);return o}n(tt,"toolCallIds");function se(t,o){const s=t.sessionManager,m=hn(s);return m!==void 0&&$n(m.map(({message:i})=>i)),m===void 0?void 0:_n(m,{boundaryReviewId:o,sessionEntries:s.getEntries?.()})}n(se,"snapshotMessages");function ke(){const t=Ne();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(ke,"currentBrokerNodeId");async function rt(t,o){const s=cn(o.model,Ie(),o.modelExact===!0);if(s===void 0)return;const m=ie(t),i={cwd:De()??o.cwd,profileId:Fe()},a=fn(s,m,i);if(a!==void 0)throw await z(ke(),{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 l=mn(s,i.cwd,i.profileId),d=un(s.spec);for(const p of l){const S=m.find(p.providerId,p.modelId);if(S===void 0)continue;const _=d?.providerId===p.providerId&&d.modelId===p.modelId?d.thinkingLevel??(p.thinkingLevel===void 0?void 0:"off"):p.thinkingLevel;return{model:S,thinkingLevel:_}}if(o.modelExact===!0){const p=l.map(S=>`'${S.providerId}/${S.modelId}' unregistered`).join("; ");throw await z(ke(),{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 (${p})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}T({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:l.map(p=>({provider:p.providerId,model:p.modelId,reason:"unregistered"})).slice(0,16)}})}n(rt,"resolveLaunchModel");function ot(t){let o=!0;return{runtime:new Proxy(t,{get(m,i,a){return o&&i==="getAvailableSnapshot"?()=>[]:o&&i==="getAvailable"?async()=>[]:o&&i==="getModel"?()=>{}:Reflect.get(m,i,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(ot,"modelLessRegistry");async function it(t,o){const s=Y(),m=n(async _=>{const f=await Ve.create({credentials:new dn,modelsPath:Te(_.agentDir,"models.json")});ln(f);const y=await t.createAgentSessionServices({cwd:_.cwd,agentDir:_.agentDir,modelRuntime:f,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(P=>({...P,extensions:P.extensions.filter(E=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(E.path))}),"extensionsOverride")}}),b=y.resourceLoader.getExtensions();if(o.extensionPaths.some(P=>re.includes(P))){const P=new Set(b.extensions.map(R=>R.path)),E=re.filter(R=>!P.has(R));if(E.length>0){const R=b.errors.filter(D=>re.includes(D.path)).map(D=>`${D.path}: ${D.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${E.join(", ")}${R===""?"":` (${R})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const C=await rt(y,o),V=C?.model,U=C?.thinkingLevel,A=C===void 0?ot(y.modelRuntime):void 0,ae=A!==void 0?{...y,modelRuntime:A.runtime}:y,G=await t.createAgentSessionFromServices({services:ae,sessionManager:_.sessionManager,model:V,thinkingLevel:U,...nt(o.tools,Le()),sessionStartEvent:_.sessionStartEvent});return Bn(G.session),an(G.session),A?.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 l=!a&&i!==void 0&&i!=="",d=l&&o.newCycle===!0,p=l&&!d;let S;if(a)S=await t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(p||d){if(S=await t.SessionManager.open(i),d){const _=S.getLeafId();S.resetLeaf(),S.appendCustomEntry(vn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:_})}}else S=await t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const _=n(async y=>{const b=await m({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...b,diagnostics:b.services.diagnostics??[]}},"factory"),f=await t.createAgentSessionRuntime(_,{cwd:o.cwd,agentDir:s,sessionManager:S});return{session:f.session,services:f.services,resuming:p,runtime:f}}const k=await m({cwd:o.cwd,agentDir:s,sessionManager:S});return{session:k.session,services:k.services,resuming:p,runtime:void 0}}n(it,"buildBrokerSession");function st(t){const o=n((i,a,l,d)=>{if(d?.signal?.aborted)return Promise.resolve(i);const p=t.writable();return p.length===0?Promise.resolve(i):new Promise(S=>{let k;const _=n(()=>{k!==void 0&&clearTimeout(k),d?.signal?.removeEventListener("abort",f),t.pending.delete(a.id)},"cleanup"),f=n(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(i)},"onAbort");d?.signal?.addEventListener("abort",f,{once:!0});const y=d?.timeout!==void 0?d.timeout:Zn;k=setTimeout(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(i)},y),typeof k.unref=="function"&&k.unref(),t.pending.set(a.id,{request:a,resolve:n(b=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(l(b))},"resolve")});for(const b of p)t.forward(b,a)})},"dialogPromise"),s=n(()=>{},"noop");return{[pn]: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,l)=>o(void 0,{type:"extension_ui_request",id:x(),method:"select",title:i,options:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"select"),confirm:n((i,a,l)=>o(!1,{type:"extension_ui_request",id:x(),method:"confirm",title:i,message:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,l),"confirm"),input:n((i,a,l)=>o(void 0,{type:"extension_ui_request",id:x(),method:"input",title:i,placeholder:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"input"),editor:n((i,a)=>o(void 0,{type:"extension_ui_request",id:x(),method:"editor",title:i,prefill:a},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0),"editor"),setStatus:n((i,a)=>t.broadcast({type:"extension_ui_request",id:x(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:n((i,a,l)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:x(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:l?.placement})},"setWidget"),setTitle:n(i=>t.broadcast({type:"extension_ui_request",id:x(),method:"setTitle",title:i}),"setTitle"),notify:n((i,a)=>{const l=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:x(),method:"notify",message:i,notifyType:l})},"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(st,"makeBrokerUiContext");export{fr as REVIEW_BOUNDARY_NAVIGATION_CODE,ur as ReviewBoundaryNavigationError,nt as brokerToolOptions,it as buildBrokerSession,et as disposeActiveSession,st as makeBrokerUiContext,lr as runBroker,se as snapshotMessages};
|
|
1
|
+
var Pe=Object.defineProperty;var n=(t,o)=>Pe(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Oe,envModelIntent as Ie,envNodeCwd as De,envNodeId as Ne,envProfileId as Fe,envScopes as Le,isSandboxedNode as $e,scopeAllowed as Be}from"../../shared/env.js";import{createServer as Ue}from"node:net";import{existsSync as ye,readFileSync as Ge,unlinkSync as be}from"node:fs";import{join as Te}from"node:path";import{randomUUID as M}from"node:crypto";import{mark as Ke}from"../timing.js";import{SUBMIT_RESULT_TOOL as je}from"./structured-output.js";import{installSessionManagerStorePatch as We}from"../conversation-store/index.js";import{getAgentDir as Y,ModelRegistry as qe,ModelRuntime as Ve}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Xe,viewSocketPath as He}from"../canvas/paths.js";import{bindBrokerEventSource as Ye}from"../events/source.js";import{emitEvent as T,flushBrokerLog as ze}from"../events/emit.js";import{operationIdContext as Je}from"../events/operation-id.js";import{findMissingPackagePaths as Qe}from"./package-health.js";import{installBrokerConfigSnapshot as Ze}from"../config.js";import{FRONT_DOOR_ENV as en}from"./front-door.js";import{CANVAS_EXTENSIONS as re,piInvocationToSdkConfig as nn}from"./launch.js";import{assertEngineVersion as tn,loadBrokerEngine as rn}from"./broker-sdk.js";import{initCrtrTheme as on}from"./crtr-theme.js";import{resolveBundledPiPackageDir as sn}from"./pi-cli.js";import{captureSessionChatCapabilities as an}from"./command-surface.js";import{InMemoryCredentialStore as dn}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as ln}from"./broker/model-adapter.js";import{mutateBrokerFault as z,recordBrokerTurn as Re}from"./broker/daemon-ops.js";import{modelRequestFromConfig as cn,expandModelCandidates as mn,parseModelSpec as un,unregisteredConcreteModel as fn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as pn}from"./stream-watchdog.js";import{probeOnline as gn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as vn,cycleAwareMessages as hn,endedByAbort as wn}from"./session-cycles.js";import{turnErrorOf as Sn}from"../llm/refusal.js";import{projectTranscript as _n}from"./session-visibility.js";import{currentTurnVisibility as yn}from"./turn-visibility.js";import{isUnknownModel as oe}from"./model-selection.js";import{BrokerClientRegistry as bn}from"./broker/client-registry.js";import{ToolGroupTracker as Tn}from"./broker/tool-groups.js";import{TurnReplyTracker as Rn}from"./broker/turn-replies.js";import{onNodeNamed as kn}from"./broker/node-named.js";import{FaultRetry as En,willDaemonRetry as Cn}from"./broker/fault-retry.js";import{RunTurnEnds as Mn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as xn}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as An,BROKER_RUN_TURN_BUSY as Pn}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as On,settleRunDeferredMail as In}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Dn}from"./broker/run-turn-queue.js";import{EventProjection as Nn}from"./broker/event-projection.js";import{createFrameDispatchContext as Fn,handleFrame as Ln}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as $n,installAdvertisedCommandInvocationContract as Bn}from"./advertised-command-invocation.js";import{RebindDriver as Un}from"./broker/rebind.js";import{beginRuntimeTeardown as Gn}from"./broker/extension-abort.js";import{receiveNodeToken as Kn}from"./broker/node-token.js";import{serveCliRelay as jn}from"./broker/cli-relay.js";import{setTurnCauseSource as Wn}from"./broker/turn-cause.js";import{decodeKickoffOrigin as qn,KICKOFF_ORIGIN_ENV as Vn}from"./stamp/protocol.js";import{announceMessageOrigin as Xn}from"./stamp/channel.js";import{brokerExtensionState as Hn,commitBrokerModel as Yn}from"./broker/daemon-ops.js";import{composerNames as zn}from"./broker/frame-memory-refs.js";import{FrameOverflowError as Jn,normalizeSnapshotTail as Qn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as pr,REVIEW_BOUNDARY_NAVIGATION_CODE as gr}from"./broker/frame-replies.js";function se(t){return new qe(t.modelRuntime)}n(se,"registryOf");function B(t,o){if(t==null||oe(t))return null;const i=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${i}`}n(B,"formatModelSpec");function Zn(t,o){const i=B(t,void 0);return i===null?null:`${i}:${o===void 0||o===""?"off":o}`}n(Zn,"formatExactModelSpec");const et=12e4;let J=null;import{brokerSignalClient as Q}from"./broker/signal-stream.js";function nt(){Q().stop();const t=J;if(J=null,t!==null)try{t.dispose()}catch{}}n(nt,"disposeActiveSession");function tt(t,o){const i=Be(o,"crtr:act")?void 0:["bash"],u=t!==void 0&&t.length>0?[...new Set([...t,je])]:t===void 0?void 0:[...t];return{...u!==void 0?{tools:u}:{},...i!==void 0?{excludeTools:i}:{}}}n(tt,"brokerToolOptions");async function mr(t,o=process.hrtime.bigint(),i=new Date().toISOString()){Ye(t);const u=await Kn(),s=await jn(t,u);process.env.CRTR_API_SOCKET=s.path,Je.fresh(()=>{T({level:"info",event:"broker.startup.cli_entry",ts:i,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),T({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 l=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Ke(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),T({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:l,model:r}}))},"emitStartupMilestone");process.env[en]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,We(t);const p=await rn();tn(p.VERSION),l=p.VERSION;const S=Xe(t),k=Te(S,"broker-launch.json"),_=JSON.parse(Ge(k,"utf8"));if($e()){if(!_.configSnapshot)throw new Error("broker launch is missing its config snapshot");Ze(_.configSnapshot)}const f=nn(_);f.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await zn(t);let b,x;const V=n(e=>{b!==void 0?b(e):x??=e},"onSignal");process.on("SIGTERM",()=>V("SIGTERM")),process.on("SIGINT",()=>V("SIGINT"));let{session:U,services:A,resuming:ae,runtime:G}=await it(p,f);d("broker.startup.session_built");const E=(await Hn(t)).node.review_binding?.review_id,R=Oe();J=U;const D=gn;try{process.env.PI_PACKAGE_DIR=sn(),on(A.settingsManager.getTheme(),Y(),!1)}catch(e){T({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of Qe(Y()))T({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const K=He(t),g=new bn(t),X=new Map,O=new Tn(t,e=>g.broadcast(e)),j=new Rn(t,e=>g.broadcast(e));kn(e=>g.broadcast({type:"node_named",...e}));let N=!1,de=!1,H,le,m,W;const Z=new Mn;let F,ce=n(()=>{},"notifyTurnAccepted"),me=n(()=>{},"resetFrameState");const ee=xn();let ue=n(()=>0,"pendingPromptDispatches"),fe;const L=Dn({runNode:R,session:n(()=>m.session(),"session"),isReplacing:n(()=>m.isReplacing(),"isReplacing"),pendingRebind:n(()=>m.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>m.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>ue(),"pendingDispatches"),turnAdmission:ee,prependDeferred:n(e=>On(t,e),"prependDeferred"),onError:n(e=>T({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")});Wn(()=>m.session());const pe=L.drain;f.firstPrompt!==void 0&&f.firstPrompt!==""&&L.holdForKickoff(),globalThis[An]=L.start,globalThis[Pn]=L.busy,m=new Un({nodeId:t,cfg:f,session:U,services:A,runtime:G,registry:g,toolGroups:O,turnReplies:j,transcriptMessages:n(e=>ie(e,E)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>le,"uiContext"),faultRetry:n(()=>W,"faultRetry"),projection:n(()=>F,"projection"),setActiveSession:n(e=>{if(J=e,fe?.(),R){let r="stop",c,v=!1;fe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",c=void 0,v=!1,Z.started()),h.type==="agent_end"){const w=[...h.messages??[]].reverse().find($=>$.role==="assistant");w&&(r=w.stopReason,c=wn(w)?void 0:Sn(w),v=w.role==="assistant"&&Cn(w,e.model?.contextWindow))}h.type==="agent_settled"&&(Z.settled(e.sessionManager,{stop_reason:r,...c?{error:c}:{}},v),In(t,e).catch(w=>{T({level:"error",event:"broker.run_deferred_mail.settle_failed",error:w})}),queueMicrotask(()=>{m.session()===e&&pe()}))})}},"setActiveSession"),disposeAndExit:n((e,r)=>q(e,r),"disposeAndExit"),onSessionRebind:n(()=>{me()},"onSessionRebind"),onReplacementIdle:n(()=>{R&&pe()},"onReplacementIdle"),reWelcomeAll:n(()=>ne(),"reWelcomeAll")});const ge=n(async(e,r=!1)=>{const c=m.session(),v=B(c.model,c.thinkingLevel);if(v===null)return null;const h=await Yn(t,{spec:v,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(f.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,f.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",f.modelExact=!0)),h.modelOverride},"persistModelChoice"),ve=n(async(e=!0,r,c=!1)=>{const v=m.session(),h=B(v.model,v.thinkingLevel),w=e?await ge(r,c):h;g.broadcast({type:"model_changed",model:oe(v.model)?void 0:v.model,spec:w})},"broadcastModelChanged");W=new En({nodeId:t,cfg:f,retryProbe:D,currentSession:n(()=>m.session(),"currentSession"),currentServices:n(()=>m.services(),"currentServices"),installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:B,broadcastModelChanged:ve,turnAdmission:ee,reWelcomeAll:n(()=>ne(),"reWelcomeAll"),...R?{turnEnds:Z}:{}});const he=n(()=>{W.rearmIfStranded().catch(e=>{T({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");Q().subscribe("resync",he),Q().subscribe("fault-retry",he),F=new Nn({registry:g,faultRetry:W,installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),currentSession:n(()=>m.session(),"currentSession"),notifyTurnAccepted:n(()=>ce(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:B});const Ee=n(e=>{const r=m.session(),c=ie(r,E),v=Qn(e.snapshotTail),h=c===void 0||v===void 0?c:c.slice(-v),w=h?.map(({message:I})=>I)??r.sessionManager.buildSessionContext().messages,$=O.summaries(),_e=h!==void 0&&v!==void 0?rt(w):void 0,Ae=_e===void 0?$:Object.fromEntries(Object.entries($).filter(([I])=>_e.has(I)));return{messages:w,...h===void 0?{}:{messageIds:h.map(({id:I})=>I)},messageVisibility:h?.map(({visibility:I})=>I)??w.map(()=>"visible"),turnVisibility:yn(),stats:r.getSessionStats(),state:{model:oe(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:{...g.displaySnapshot()},toolGroupSummaries:Ae,turnReplies:j.snapshot(),workingActivity:F.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),we=n(e=>{const r=e.role==="controller"?X.values().next().value:void 0;g.sendFrame(e,{type:"welcome",snapshot:Ee(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:Y()},!0)},"sendWelcome"),Ce=n(e=>{const r=[...X.values()];for(let c=1;c<r.length;c++)g.sendFrame(e,r[c].request)},"replayExtraPendingDialogsTo"),ne=n(()=>{try{const e=m.session();j.seed(ie(e,E)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){T({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}g.forEachHelloed(we)},"reWelcomeAll"),Se=n(async e=>{if(!N){N=!0,Q().stop(),O.persistPendingSummary(),F.dispose(),nt();try{H?.close()}catch{}s.close(),g.dispose();try{ye(K)&&be(K)}catch{}g.clearAttachState(),await ze(),process.exit(e)}},"completeExit"),q=n((e,r=0)=>{if(N)return;const c=e==="shutdown-hook"||e==="shutdown-after-settle";if(c&&O.finishOpenToolGroup(!0),c&&(O.hasSummaryTasks()||j.hasTasks())){if(de)return;de=!0,Promise.allSettled([O.waitForSummaryTasks(),j.waitForTasks()]).finally(()=>Se(r));return}Se(r)},"disposeAndExit");le=at({writable:n(()=>g.writableClients(),"writable"),forward:n((e,r)=>g.sendFrame(e,r),"forward"),pending:X,broadcast:n(e=>g.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>F.knownStreamWait(e),"onKnownStreamWait")}),m.setRebindSession(),await m.enqueueRebind(U,A),d("broker.startup.extensions_bound");const C=Fn({nodeId:t,registry:g,toolGroups:O,projection:F,rebind:m,boundaryReviewId:E,pendingDialogs:X,sendWelcome:we,replayExtraPendingDialogsTo:Ce,reWelcomeAll:ne,disposeAndExit:q,persistModelChoice:ge,broadcastModelChanged:ve,registryOf:se,formatModelSpec:B,formatExactModelSpec:Zn,turnAdmission:ee,memoryInventory:y,runNode:R,onKickoffAdmitted:L.releaseKickoff});ce=C.notifyTurnAccepted,me=C.resetForSession,ue=C.pendingPromptDispatches;const Me=2500;let te=!1;const xe=n(async e=>{if(N||te)return;if(te=!0,m.isAgentRunActive()||m.session().isStreaming||C.pendingPromptDispatches()>0){const c=Date.now()+Me;for(;C.pendingPromptDispatches()>0&&!m.session().isStreaming&&Date.now()<c;)await new Promise(v=>setTimeout(v,25));if(m.session().isStreaming){const v=c-Date.now();if(v>0){let h;try{Gn(),await Promise.race([m.session().abort().then(()=>!0,()=>!1),new Promise($=>{h=setTimeout(()=>$(!1),v)})])&&await Re(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(C.pendingPromptDispatches()>0||m.isAgentRunActive())&&await Re(t,{event:"interrupted"})}q(e)},"abortAndExit");if(b=n(e=>{xe(e)},"signalTeardown"),x!==void 0){b(x);return}try{ye(K)&&be(K)}catch{}H=Ue(e=>{const r=g.create(e);e.on("data",v=>{let h;try{h=r.decoder.push(v)}catch(w){w instanceof Jn?(g.sendFrame(r,{type:"error",code:"frame_overflow",message:w.message}),g.dropClient(r,`frame overflow: ${w.message}`)):g.dropClient(r,`decoder error: ${String(w)}`);return}for(const w of h)try{Ln(C,r,w)}catch{}});const c=n(()=>{g.removeClient(r)},"drop");e.on("close",c),e.on("error",()=>{})}),H.on("error",e=>{N||(T({level:"error",event:"broker.socket.failed",error:e}),q("socket-error",1))}),H.listen(K,async()=>{Promise.all([z(t,{op:"clear",link:"viewer\u2194broker"}),z(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await W.recoverOnStartup()}catch(r){T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),q("recovery-startup-failed",1);return}if(!(N||te))if(e!=="retry-armed"&&f.firstPrompt!==void 0&&f.firstPrompt!==""){const r=qn(process.env[Vn]);r!==null&&Xn(f.firstPrompt,r);const c=process.env.CRTR_KICKOFF_MESSAGE_IDS;C.kickoff(f.firstPrompt,c?JSON.parse(c):[])}else L.releaseKickoff()}),g.persistAttachState()}n(mr,"runBroker");function rt(t){const o=new Set;for(const i of t)if(!(i.role!=="assistant"||!Array.isArray(i.content)))for(const u of i.content)u!==null&&typeof u=="object"&&u.type==="toolCall"&&typeof u.id=="string"&&o.add(u.id);return o}n(rt,"toolCallIds");function ie(t,o){const i=t.sessionManager,u=hn(i);return u!==void 0&&$n(u.map(({message:s})=>s)),u===void 0?void 0:_n(u,{boundaryReviewId:o,sessionEntries:i.getEntries?.()})}n(ie,"snapshotMessages");function ke(){const t=Ne();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(ke,"currentBrokerNodeId");async function ot(t,o){const i=cn(o.model,Ie(),o.modelExact===!0);if(i===void 0)return;const u=se(t),s={cwd:De()??o.cwd,profileId:Fe()},a=fn(i,u,s);if(a!==void 0)throw await z(ke(),{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 l=mn(i,s.cwd,s.profileId),d=un(i.spec);for(const p of l){const S=u.find(p.providerId,p.modelId);if(S===void 0)continue;const _=d?.providerId===p.providerId&&d.modelId===p.modelId?d.thinkingLevel??(p.thinkingLevel===void 0?void 0:"off"):p.thinkingLevel;return{model:S,thinkingLevel:_}}if(o.modelExact===!0){const p=l.map(S=>`'${S.providerId}/${S.modelId}' unregistered`).join("; ");throw await z(ke(),{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 (${p})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}T({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:l.map(p=>({provider:p.providerId,model:p.modelId,reason:"unregistered"})).slice(0,16)}})}n(ot,"resolveLaunchModel");function st(t){let o=!0;return{runtime:new Proxy(t,{get(u,s,a){return o&&s==="getAvailableSnapshot"?()=>[]:o&&s==="getAvailable"?async()=>[]:o&&s==="getModel"?()=>{}:Reflect.get(u,s,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(st,"modelLessRegistry");async function it(t,o){const i=Y(),u=n(async _=>{const f=await Ve.create({credentials:new dn,modelsPath:Te(_.agentDir,"models.json")});ln(f);const y=await t.createAgentSessionServices({cwd:_.cwd,agentDir:_.agentDir,modelRuntime:f,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(P=>({...P,extensions:P.extensions.filter(E=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(E.path))}),"extensionsOverride")}}),b=y.resourceLoader.getExtensions();if(o.extensionPaths.some(P=>re.includes(P))){const P=new Set(b.extensions.map(R=>R.path)),E=re.filter(R=>!P.has(R));if(E.length>0){const R=b.errors.filter(D=>re.includes(D.path)).map(D=>`${D.path}: ${D.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${E.join(", ")}${R===""?"":` (${R})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const x=await ot(y,o),V=x?.model,U=x?.thinkingLevel,A=x===void 0?st(y.modelRuntime):void 0,ae=A!==void 0?{...y,modelRuntime:A.runtime}:y,G=await t.createAgentSessionFromServices({services:ae,sessionManager:_.sessionManager,model:V,thinkingLevel:U,...tt(o.tools,Le()),sessionStartEvent:_.sessionStartEvent});return Bn(G.session),an(G.session),A?.reveal(),{...G,services:y}},"buildForManager"),s=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(s===void 0||s==="")&&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 l=!a&&s!==void 0&&s!=="",d=l&&o.newCycle===!0,p=l&&!d;let S;if(a)S=await t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(p||d){if(S=await t.SessionManager.open(s),d){const _=S.getLeafId();S.resetLeaf(),S.appendCustomEntry(vn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:_})}}else S=await t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const _=n(async y=>{const b=await u({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...b,diagnostics:b.services.diagnostics??[]}},"factory"),f=await t.createAgentSessionRuntime(_,{cwd:o.cwd,agentDir:i,sessionManager:S});return{session:f.session,services:f.services,resuming:p,runtime:f}}const k=await u({cwd:o.cwd,agentDir:i,sessionManager:S});return{session:k.session,services:k.services,resuming:p,runtime:void 0}}n(it,"buildBrokerSession");function at(t){const o=n((s,a,l,d)=>{if(d?.signal?.aborted)return Promise.resolve(s);const p=t.writable();return p.length===0?Promise.resolve(s):new Promise(S=>{let k;const _=n(()=>{k!==void 0&&clearTimeout(k),d?.signal?.removeEventListener("abort",f),t.pending.delete(a.id)},"cleanup"),f=n(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(s)},"onAbort");d?.signal?.addEventListener("abort",f,{once:!0});const y=d?.timeout!==void 0?d.timeout:et;k=setTimeout(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(s)},y),typeof k.unref=="function"&&k.unref(),t.pending.set(a.id,{request:a,resolve:n(b=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(l(b))},"resolve")});for(const b of p)t.forward(b,a)})},"dialogPromise"),i=n(()=>{},"noop");return{[pn]:t.onKnownStreamWait??(s=>()=>{}),get theme(){const s=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(s==null)throw new Error("Theme not initialized. Call initTheme() first.");return s},select:n((s,a,l)=>o(void 0,{type:"extension_ui_request",id:M(),method:"select",title:s,options:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"select"),confirm:n((s,a,l)=>o(!1,{type:"extension_ui_request",id:M(),method:"confirm",title:s,message:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,l),"confirm"),input:n((s,a,l)=>o(void 0,{type:"extension_ui_request",id:M(),method:"input",title:s,placeholder:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"input"),editor:n((s,a)=>o(void 0,{type:"extension_ui_request",id:M(),method:"editor",title:s,prefill:a},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0),"editor"),setStatus:n((s,a)=>t.broadcast({type:"extension_ui_request",id:M(),method:"setStatus",statusKey:s,statusText:a}),"setStatus"),setWidget:n((s,a,l)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:M(),method:"setWidget",widgetKey:s,widgetLines:a,widgetPlacement:l?.placement})},"setWidget"),setTitle:n(s=>t.broadcast({type:"extension_ui_request",id:M(),method:"setTitle",title:s}),"setTitle"),notify:n((s,a)=>{const l=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:M(),method:"notify",message:s,notifyType:l})},"notify"),onTerminalInput:n(()=>i,"onTerminalInput"),setWorkingMessage:i,setWorkingVisible:i,setWorkingIndicator:i,setHiddenThinkingLabel:i,setFooter:i,setHeader:i,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:i,setEditorText:i,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:i,setEditorComponent:i,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:i,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:i}}n(at,"makeBrokerUiContext");export{gr as REVIEW_BOUNDARY_NAVIGATION_CODE,pr as ReviewBoundaryNavigationError,tt as brokerToolOptions,it as buildBrokerSession,nt as disposeActiveSession,at as makeBrokerUiContext,mr as runBroker,ie as snapshotMessages};
|
|
@@ -110,6 +110,8 @@ export interface SpawnNodeOpts {
|
|
|
110
110
|
isolated?: boolean;
|
|
111
111
|
/** Run identity set on an app root; managed children inherit it. */
|
|
112
112
|
run?: Pick<NodeMeta, 'grantee' | 'sub' | 'grant_id' | 'client_id' | 'metadata_json' | 'run_id' | 'event_cursor' | 'usage_json'>;
|
|
113
|
+
/** What caused this run, stored on its root node (`run.start`'s `Crtr-Caused-By`). */
|
|
114
|
+
causedBy?: string;
|
|
113
115
|
/** Additional rows committed atomically with the newborn node. */
|
|
114
116
|
withinCreate?: (db: CanvasDb, row: NodeMeta) => Promise<void> | void;
|
|
115
117
|
/** Managed worktree already created for this node, if any. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var J=Object.defineProperty;var l=(e,r)=>J(e,"name",{value:r,configurable:!0});import{envHomeOverride as K,envRuntimeHomeOverride as X,INBOX_BETWEEN_TURNS_ENV as z,SCOPES_FILE_ENV as V,scopeAllowed as I}from"../../shared/env.js";import{isOwnMemoryScope as Y,validateScopes as Q}from"../scopes.js";import{activeGrant as F,terminalGrant as k}from"../grants/mirror.js";import{grantSnapshotMissing as Z}from"../../daemon/readiness.js";import{appendRunEvent as ee}from"../runs/events.js";import{personId as ne}from"../canvas/person.js";import{InputError as S}from"../io.js";import{ApiError as g}from"../../api/errors.js";import{assertGranteeRunsHere as re}from"./unsandboxed.js";import{randomBytes as te}from"node:crypto";import{existsSync as B}from"node:fs";import{resolve as ie,relative as oe,isAbsolute as P,join as ae,sep as le}from"node:path";import{appSpace as se}from"../layout.js";import{scopesFilePath as de}from"../canvas/paths.js";import{createNode as ce,assertRunNotDeleting as ue,conversationOwner as fe,getNode as u,getRow as pe}from"../canvas/index.js";import{ensureAppSpace as me}from"../spaces/space.js";import{LAUNCHER_SOCKET as U}from"../../launcher/spec.js";import{resolveInstallId as _e}from"../canvas/install-id.js";import{isAppRun as we}from"../canvas/app-run.js";import{contextDir as ge}from"../canvas/paths.js";import{conversationIdFromPath as he}from"../conversation-store/index.js";import{usage as H}from"../errors.js";import{assertProfileAvailableForBirth as ve}from"../profiles/deletion-reservation.js";import{loadExactProfileManifest as Re}from"../profiles/manifest.js";import{admitNodeCreate as ye}from"../command-hooks/lifecycle-create.js";import{getById as Ee,nodeObject as C,ownerForGrantee as Ie}from"../graph/objects.js";import{recordActedOn as Ce}from"../graph/edges.js";import{recordWatch as Ne,copyWatchesForFork as ke}from"../graph/watches.js";import{publish as Se}from"../graph/events.js";import{canvasDatabaseUrl as Te}from"../canvas/db.js";import{someAsync as Oe}from"../async-array.js";import{admitIntoManagedCheckout as xe}from"../worktree-mutation-async.js";let T;const L=new Map;function hn(e){T=e}l(hn,"setInstallId");async function De(){if(T!==void 0)return T;const e=await Te(),r=L.get(e);if(r!==void 0)return r;const o=await _e();return L.set(e,o),o}l(De,"installId");function be(){return`${Date.now().toString(36)}-${te(4).toString("hex")}`}l(be,"newJobId");async function Ae(){return`${await De()}-${be()}`}l(Ae,"newNodeId");const O=128,Me=/^[a-z0-9-]+$/;class j extends Error{static{l(this,"NodeIdConflictError")}nodeId;constructor(r){super(`node already exists: ${r}`),this.nodeId=r,this.name="NodeIdConflictError"}}function x(e){if(e.length===0||e.length>O)throw H(`invalid --node-id '${e}': must be 1-${O} characters`,{next:`Pass an id-safe string (lowercase letters, digits, hyphens) of at most ${O} characters.`});if(!Me.test(e))throw H(`invalid --node-id '${e}': must contain only lowercase letters, digits, and hyphens (e.g. 'remote42', 'my-node-1')`,{next:"Use only lowercase letters, digits, and hyphens."})}l(x,"validateNodeIdFormat");async function vn(e){if(x(e),await u(e)!==null)throw new j(e)}l(vn,"preflightNodeId");async function $e(e){if(x(e),await u(e)!==null)throw new j(e);return e}l($e,"validatedExplicitNodeId");async function Rn(e){let r=e;const o=new Set;for(;;){if(o.has(r))return r;o.add(r);const s=await pe(r);if(s===null||s.parent==null)return r;r=s.parent}}l(Rn,"rootOfSpine");function yn(){const e=process.env;return{nodeId:e.CRTR_NODE_ID??null,kind:e.CRTR_KIND??null,mode:e.CRTR_MODE??null}}l(yn,"currentNodeContext");function Fe(e){return we(e)}l(Fe,"inboxBetweenTurns");function En(e){const r={CRTR_NODE_ID:e.node_id,CRTR_KIND:e.kind,CRTR_MODE:e.mode,CRTR_LIFECYCLE:e.lifecycle,CRTR_NODE_CWD:e.cwd,CRTR_CONTEXT_DIR:ge(e.node_id,e.grantee),CRTR_CYCLES:(e.cycles??0).toString(),CRTR_PROFILE_ID:e.profile_id??"",PI_CLAUDE_OAUTH_REINJECT_SCOPE:"never"};e.parent&&(r.CRTR_PARENT_NODE_ID=e.parent),e.run_id&&(r.CRTR_RUN_ID=e.run_id),Fe(e)&&(r[z]="1"),e.scopes!==null&&e.scopes!==void 0&&(r[V]=de(e.node_id)),r.CRTR_GRANTEE=e.grantee??"app:terminal";const o=K();o!==void 0&&o!==""&&(r.CRTR_HOME=o);const s=X();s!==void 0&&s!==""&&(r.CRTR_RUNTIME_HOME=s);const f=process.env.CRTR_SUBTREE;return f!==void 0&&f!==""&&(r.CRTR_SUBTREE=f),{...r,...e.launch?.env??{}}}l(En,"nodeEnv");async function Be(e){const r=he(e),o=r===null?null:await fe(r);return o===null?null:await u(o)}l(Be,"forkSourceNode");async function In(e){const r=e.nodeId!==void 0?(x(e.nodeId),e.nodeId):await Ae(),o=e.parent??null,s=o===null,f=e.spawnedBy??o,m=e.creator??null,D=e.mode??"base",N=e.lifecycle??(s?"resident":"terminal"),h=e.run===void 0?await k():null,n={node_id:r,name:e.name??e.kind,description:e.description,cycles:0,created:new Date().toISOString(),cwd:e.cwd,host_kind:"broker",profile_id:e.profile_id??null,kind:e.kind,mode:D,lifecycle:N,persona_ack:{kind:e.kind,mode:D,lifecycle:N},status:"active",parent:o,spawned_by:f,creator:m,fork_from:e.forkFrom,fork_source_file:e.forkSourceFile,review_binding:e.reviewBinding,model_override:e.modelOverride??null,scopes:e.scopes??null,isolated:e.isolated===!0,grantee:e.run?.grantee??"app:terminal",sub:e.run?.sub??h?.sub??null,grant_id:e.run?.grant_id??h?.id??null,client_id:e.run?.client_id??null,metadata_json:s?e.run?.metadata_json??null:null,run_id:s?r:e.run?.run_id??null,event_cursor:s?e.run?.event_cursor??1:null,usage_json:s?e.run?.usage_json??JSON.stringify({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}):null,passive_default:e.passiveDefault??!1,...e.managedWorktree!==void 0?{managed_worktree:e.managedWorktree}:{},intent:null,deadline_at:e.deadlineAt??null,pi_session_id:null,pi_session_file:null,launch:e.launch},y=e.scopes===void 0?void 0:Q(e.scopes),v=o===null?null:await u(o);if(o!==null&&v===null)throw new Error(`cannot spawn under unknown parent node: ${o}`);if(v?.run_id&&(await u(v.run_id))?.deleting_at)throw new Error("run is deleting");const c=m===null?null:await u(m);if(m!==null&&c===null)throw new Error(`cannot spawn from unknown creator node: ${m}`);if(c?.run_id&&(await u(c.run_id))?.deleting_at)throw new Error("run is deleting");const b=e.forkSourceFile==null?null:await Be(e.forkSourceFile),A=e.replaces==null?null:await u(e.replaces),_=v??b??A??c??(f===null?null:await u(f)),q=[v,c,b,A,f===null?null:await u(f)],M=await Oe(q,async t=>t?.isolated===!0||t?.run_id!=null&&(await u(t.run_id))?.isolated===!0);if(M&&e.isolated===!1)throw new g(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});if(n.isolated=M||e.isolated===!0,_!==null){const t=c??_;if(c&&_.grantee&&c.grantee&&c.grantee!==_.grantee)throw new g(403,"other_app_run","cannot create under another app's node");const i=c&&c!==_?[_,c]:[_],d=[],w=new Set;for(const a of i){a.scopes!==null&&a.scopes!==void 0&&d.push(a.scopes);const p=a.grantee==="app:terminal"?await k():a.grant_id?await F(a.grant_id):null;if(p){const R=[...p.resolved];w.add(R),d.push(R)}else{const R=[];w.add(R),d.push(R)}}const E=l(a=>Y(a,t.grantee??"app:terminal"),"ownMemory"),$=l((a,p)=>E(p)&&w.has(a)||I(a,p),"allowed");if(y!==void 0&&!y.every(a=>d.every(p=>$(p,a))))throw new S({error:"unknown_scope",message:"child scopes must be covered by the creating node, its source and their current grants",received:y,field:"scopes",next:"Request only scopes the creating node currently holds."});if(n.scopes=y??(i.every(a=>a.scopes==null)&&i.every(a=>a.grant_id===t.grant_id&&a.sub===t.sub)?null:i.length===1?_.scopes??null:[...new Set(d.flat().filter(a=>d.every(p=>$(p,a))))]),n.scopes?.includes("crtr:act")&&!I(n.scopes,"crtr:llm"))throw new S({error:"invalid_scope",message:"crtr:act requires crtr:llm",received:n.scopes,field:"scopes",next:"Include crtr:llm or omit crtr:act."});n.grantee=t.grantee,n.sub=t.sub??(n.grantee==="app:terminal"?h?.sub:null)??null,n.grant_id=t.grant_id??(n.grantee==="app:terminal"?h?.id:null)??null,n.client_id=t.client_id,n.run_id=s?r:t.run_id??null}if(re(n.grantee),e.run===void 0&&n.grantee==="app:terminal"&&h===null)throw await Z()?new g(503,"runtime_starting","the first grant snapshot from the directory has not committed"):new g(403,"scope_missing","terminal grant is not active");if(n.isolated){if(process.platform!=="linux"||!B(U))throw new g(400,"isolated_unavailable","isolated nodes require the Linux root launcher");if(e.managedWorktree!==void 0)throw new g(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const t=ae(se(n.grantee??"app:terminal").nodes,r),i=oe(t,ie(n.cwd));if(!P(n.cwd)||i===".."||i.startsWith(`..${le}`)||P(i))throw new g(400,"invalid_request","isolated node cwd must be inside its own folder",{param:"cwd"})}if(n.profile_id){const t=Re(n.profile_id).manifest.grantee??"app:terminal";if(t!==n.grantee){const i=`crtr:memory:rw:${t}:profile:${n.profile_id}`,d=n.grantee==="app:terminal"?await k():n.grant_id?await F(n.grant_id):null;if(!d||d.grantee!==n.grantee||!I(d.resolved,i)||!I(n.scopes,i))throw new S({error:"scope_missing",message:`missing scope ${i}`,received:n.profile_id,field:"profile",next:"Select a profile covered by this run and its current grant."})}}if(ve(n.profile_id??null),!n.grantee)throw new Error("node creation requires an app");const W=await ye({kind:n.kind,mode:n.mode,cwd:n.cwd,profile:n.profile_id??null,root:s,parentId:o,requestingNodeId:m,lifecycle:N,replaces:e.replaces??null},n.grantee),G=l(async(t,i)=>{const d=await C(t,i.node_id),w=m??o??e.actor??f??null,E=w!==null&&(await Ee(t,w))?.type==="node"?await C(t,w):await Ie(t,e.run===void 0?ne():i.grantee);await Ce(t,E,d),o!==null&&e.subscribe!==!1&&await Ne(t,await C(t,o),d,"spawn"),e.forkSourceNode&&await ke(t,await C(t,e.forkSourceNode),d),await Se(t,{event:"created",object:d,actor:E,attrs:{name:i.name,kind:i.kind,creator:m??null}})},"recordBirth");try{e.nodeId!==void 0&&await $e(e.nodeId),await e.beforeCreate?.(),(process.platform!=="linux"||B(U))&&await me(n.grantee??"app:terminal"),await xe(n.cwd,r,()=>ce(n,{outcomeDelivery:e.outcomeDelivery,withinCreate:l(async(t,i)=>{i.run_id&&i.run_id!==i.node_id&&await ue(t,i.run_id),s&&e.run===void 0&&await ee(t,r,r,"run.started",{scopes:i.scopes??null,payer:"user",usage:JSON.parse(i.usage_json)}),await e.withinCreate?.(t,i),await G(t,i)},"withinCreate")}))}finally{W()}return n}l(In,"spawnNode");export{j as NodeIdConflictError,yn as currentNodeContext,Be as forkSourceNode,Fe as inboxBetweenTurns,be as newJobId,Ae as newNodeId,En as nodeEnv,vn as preflightNodeId,Rn as rootOfSpine,hn as setInstallId,In as spawnNode};
|
|
1
|
+
var J=Object.defineProperty;var l=(e,r)=>J(e,"name",{value:r,configurable:!0});import{envHomeOverride as K,envRuntimeHomeOverride as X,INBOX_BETWEEN_TURNS_ENV as z,SCOPES_FILE_ENV as V,scopeAllowed as I}from"../../shared/env.js";import{isOwnMemoryScope as Y,validateScopes as Q}from"../scopes.js";import{activeGrant as F,terminalGrant as k}from"../grants/mirror.js";import{grantSnapshotMissing as Z}from"../../daemon/readiness.js";import{appendRunEvent as ee}from"../runs/events.js";import{personId as ne}from"../canvas/person.js";import{InputError as S}from"../io.js";import{ApiError as g}from"../../api/errors.js";import{assertGranteeRunsHere as re}from"./unsandboxed.js";import{randomBytes as te}from"node:crypto";import{existsSync as B}from"node:fs";import{resolve as ie,relative as oe,isAbsolute as P,join as ae,sep as le}from"node:path";import{appSpace as se}from"../layout.js";import{scopesFilePath as de}from"../canvas/paths.js";import{createNode as ce,assertRunNotDeleting as ue,conversationOwner as fe,getNode as u,getRow as pe}from"../canvas/index.js";import{ensureAppSpace as me}from"../spaces/space.js";import{LAUNCHER_SOCKET as U}from"../../launcher/spec.js";import{resolveInstallId as _e}from"../canvas/install-id.js";import{isAppRun as we}from"../canvas/app-run.js";import{contextDir as ge}from"../canvas/paths.js";import{conversationIdFromPath as he}from"../conversation-store/index.js";import{usage as H}from"../errors.js";import{assertProfileAvailableForBirth as ve}from"../profiles/deletion-reservation.js";import{loadExactProfileManifest as Re}from"../profiles/manifest.js";import{admitNodeCreate as ye}from"../command-hooks/lifecycle-create.js";import{getById as Ee,nodeObject as C,ownerForGrantee as Ie}from"../graph/objects.js";import{recordActedOn as Ce}from"../graph/edges.js";import{recordWatch as Ne,copyWatchesForFork as ke}from"../graph/watches.js";import{publish as Se}from"../graph/events.js";import{canvasDatabaseUrl as Te}from"../canvas/db.js";import{someAsync as Oe}from"../async-array.js";import{admitIntoManagedCheckout as xe}from"../worktree-mutation-async.js";let T;const L=new Map;function hn(e){T=e}l(hn,"setInstallId");async function De(){if(T!==void 0)return T;const e=await Te(),r=L.get(e);if(r!==void 0)return r;const o=await _e();return L.set(e,o),o}l(De,"installId");function be(){return`${Date.now().toString(36)}-${te(4).toString("hex")}`}l(be,"newJobId");async function Ae(){return`${await De()}-${be()}`}l(Ae,"newNodeId");const O=128,Me=/^[a-z0-9-]+$/;class j extends Error{static{l(this,"NodeIdConflictError")}nodeId;constructor(r){super(`node already exists: ${r}`),this.nodeId=r,this.name="NodeIdConflictError"}}function x(e){if(e.length===0||e.length>O)throw H(`invalid --node-id '${e}': must be 1-${O} characters`,{next:`Pass an id-safe string (lowercase letters, digits, hyphens) of at most ${O} characters.`});if(!Me.test(e))throw H(`invalid --node-id '${e}': must contain only lowercase letters, digits, and hyphens (e.g. 'remote42', 'my-node-1')`,{next:"Use only lowercase letters, digits, and hyphens."})}l(x,"validateNodeIdFormat");async function vn(e){if(x(e),await u(e)!==null)throw new j(e)}l(vn,"preflightNodeId");async function $e(e){if(x(e),await u(e)!==null)throw new j(e);return e}l($e,"validatedExplicitNodeId");async function Rn(e){let r=e;const o=new Set;for(;;){if(o.has(r))return r;o.add(r);const s=await pe(r);if(s===null||s.parent==null)return r;r=s.parent}}l(Rn,"rootOfSpine");function yn(){const e=process.env;return{nodeId:e.CRTR_NODE_ID??null,kind:e.CRTR_KIND??null,mode:e.CRTR_MODE??null}}l(yn,"currentNodeContext");function Fe(e){return we(e)}l(Fe,"inboxBetweenTurns");function En(e){const r={CRTR_NODE_ID:e.node_id,CRTR_KIND:e.kind,CRTR_MODE:e.mode,CRTR_LIFECYCLE:e.lifecycle,CRTR_NODE_CWD:e.cwd,CRTR_CONTEXT_DIR:ge(e.node_id,e.grantee),CRTR_CYCLES:(e.cycles??0).toString(),CRTR_PROFILE_ID:e.profile_id??"",PI_CLAUDE_OAUTH_REINJECT_SCOPE:"never"};e.parent&&(r.CRTR_PARENT_NODE_ID=e.parent),e.run_id&&(r.CRTR_RUN_ID=e.run_id),Fe(e)&&(r[z]="1"),e.scopes!==null&&e.scopes!==void 0&&(r[V]=de(e.node_id)),r.CRTR_GRANTEE=e.grantee??"app:terminal";const o=K();o!==void 0&&o!==""&&(r.CRTR_HOME=o);const s=X();s!==void 0&&s!==""&&(r.CRTR_RUNTIME_HOME=s);const f=process.env.CRTR_SUBTREE;return f!==void 0&&f!==""&&(r.CRTR_SUBTREE=f),{...r,...e.launch?.env??{}}}l(En,"nodeEnv");async function Be(e){const r=he(e),o=r===null?null:await fe(r);return o===null?null:await u(o)}l(Be,"forkSourceNode");async function In(e){const r=e.nodeId!==void 0?(x(e.nodeId),e.nodeId):await Ae(),o=e.parent??null,s=o===null,f=e.spawnedBy??o,m=e.creator??null,D=e.mode??"base",N=e.lifecycle??(s?"resident":"terminal"),h=e.run===void 0?await k():null,n={node_id:r,name:e.name??e.kind,description:e.description,cycles:0,created:new Date().toISOString(),cwd:e.cwd,host_kind:"broker",profile_id:e.profile_id??null,kind:e.kind,mode:D,lifecycle:N,persona_ack:{kind:e.kind,mode:D,lifecycle:N},status:"active",parent:o,spawned_by:f,creator:m,fork_from:e.forkFrom,fork_source_file:e.forkSourceFile,review_binding:e.reviewBinding,model_override:e.modelOverride??null,scopes:e.scopes??null,isolated:e.isolated===!0,grantee:e.run?.grantee??"app:terminal",sub:e.run?.sub??h?.sub??null,grant_id:e.run?.grant_id??h?.id??null,client_id:e.run?.client_id??null,metadata_json:s?e.run?.metadata_json??null:null,run_id:s?r:e.run?.run_id??null,event_cursor:s?e.run?.event_cursor??1:null,usage_json:s?e.run?.usage_json??JSON.stringify({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}):null,passive_default:e.passiveDefault??!1,caused_by:e.causedBy??null,...e.managedWorktree!==void 0?{managed_worktree:e.managedWorktree}:{},intent:null,deadline_at:e.deadlineAt??null,pi_session_id:null,pi_session_file:null,launch:e.launch},y=e.scopes===void 0?void 0:Q(e.scopes),v=o===null?null:await u(o);if(o!==null&&v===null)throw new Error(`cannot spawn under unknown parent node: ${o}`);if(v?.run_id&&(await u(v.run_id))?.deleting_at)throw new Error("run is deleting");const c=m===null?null:await u(m);if(m!==null&&c===null)throw new Error(`cannot spawn from unknown creator node: ${m}`);if(c?.run_id&&(await u(c.run_id))?.deleting_at)throw new Error("run is deleting");const b=e.forkSourceFile==null?null:await Be(e.forkSourceFile),A=e.replaces==null?null:await u(e.replaces),_=v??b??A??c??(f===null?null:await u(f)),q=[v,c,b,A,f===null?null:await u(f)],M=await Oe(q,async t=>t?.isolated===!0||t?.run_id!=null&&(await u(t.run_id))?.isolated===!0);if(M&&e.isolated===!1)throw new g(403,"isolated_run","isolation cannot be turned off under an isolated run",{param:"isolated"});if(n.isolated=M||e.isolated===!0,_!==null){const t=c??_;if(c&&_.grantee&&c.grantee&&c.grantee!==_.grantee)throw new g(403,"other_app_run","cannot create under another app's node");const i=c&&c!==_?[_,c]:[_],d=[],w=new Set;for(const a of i){a.scopes!==null&&a.scopes!==void 0&&d.push(a.scopes);const p=a.grantee==="app:terminal"?await k():a.grant_id?await F(a.grant_id):null;if(p){const R=[...p.resolved];w.add(R),d.push(R)}else{const R=[];w.add(R),d.push(R)}}const E=l(a=>Y(a,t.grantee??"app:terminal"),"ownMemory"),$=l((a,p)=>E(p)&&w.has(a)||I(a,p),"allowed");if(y!==void 0&&!y.every(a=>d.every(p=>$(p,a))))throw new S({error:"unknown_scope",message:"child scopes must be covered by the creating node, its source and their current grants",received:y,field:"scopes",next:"Request only scopes the creating node currently holds."});if(n.scopes=y??(i.every(a=>a.scopes==null)&&i.every(a=>a.grant_id===t.grant_id&&a.sub===t.sub)?null:i.length===1?_.scopes??null:[...new Set(d.flat().filter(a=>d.every(p=>$(p,a))))]),n.scopes?.includes("crtr:act")&&!I(n.scopes,"crtr:llm"))throw new S({error:"invalid_scope",message:"crtr:act requires crtr:llm",received:n.scopes,field:"scopes",next:"Include crtr:llm or omit crtr:act."});n.grantee=t.grantee,n.sub=t.sub??(n.grantee==="app:terminal"?h?.sub:null)??null,n.grant_id=t.grant_id??(n.grantee==="app:terminal"?h?.id:null)??null,n.client_id=t.client_id,n.run_id=s?r:t.run_id??null}if(re(n.grantee),e.run===void 0&&n.grantee==="app:terminal"&&h===null)throw await Z()?new g(503,"runtime_starting","the first grant snapshot from the directory has not committed"):new g(403,"scope_missing","terminal grant is not active");if(n.isolated){if(process.platform!=="linux"||!B(U))throw new g(400,"isolated_unavailable","isolated nodes require the Linux root launcher");if(e.managedWorktree!==void 0)throw new g(400,"invalid_request","isolated nodes cannot use a worktree",{param:"worktree"});const t=ae(se(n.grantee??"app:terminal").nodes,r),i=oe(t,ie(n.cwd));if(!P(n.cwd)||i===".."||i.startsWith(`..${le}`)||P(i))throw new g(400,"invalid_request","isolated node cwd must be inside its own folder",{param:"cwd"})}if(n.profile_id){const t=Re(n.profile_id).manifest.grantee??"app:terminal";if(t!==n.grantee){const i=`crtr:memory:rw:${t}:profile:${n.profile_id}`,d=n.grantee==="app:terminal"?await k():n.grant_id?await F(n.grant_id):null;if(!d||d.grantee!==n.grantee||!I(d.resolved,i)||!I(n.scopes,i))throw new S({error:"scope_missing",message:`missing scope ${i}`,received:n.profile_id,field:"profile",next:"Select a profile covered by this run and its current grant."})}}if(ve(n.profile_id??null),!n.grantee)throw new Error("node creation requires an app");const W=await ye({kind:n.kind,mode:n.mode,cwd:n.cwd,profile:n.profile_id??null,root:s,parentId:o,requestingNodeId:m,lifecycle:N,replaces:e.replaces??null},n.grantee),G=l(async(t,i)=>{const d=await C(t,i.node_id),w=m??o??e.actor??f??null,E=w!==null&&(await Ee(t,w))?.type==="node"?await C(t,w):await Ie(t,e.run===void 0?ne():i.grantee);await Ce(t,E,d),o!==null&&e.subscribe!==!1&&await Ne(t,await C(t,o),d,"spawn"),e.forkSourceNode&&await ke(t,await C(t,e.forkSourceNode),d),await Se(t,{event:"created",object:d,actor:E,attrs:{name:i.name,kind:i.kind,creator:m??null}})},"recordBirth");try{e.nodeId!==void 0&&await $e(e.nodeId),await e.beforeCreate?.(),(process.platform!=="linux"||B(U))&&await me(n.grantee??"app:terminal"),await xe(n.cwd,r,()=>ce(n,{outcomeDelivery:e.outcomeDelivery,withinCreate:l(async(t,i)=>{i.run_id&&i.run_id!==i.node_id&&await ue(t,i.run_id),s&&e.run===void 0&&await ee(t,r,r,"run.started",{scopes:i.scopes??null,payer:"user",usage:JSON.parse(i.usage_json)}),await e.withinCreate?.(t,i),await G(t,i)},"withinCreate")}))}finally{W()}return n}l(In,"spawnNode");export{j as NodeIdConflictError,yn as currentNodeContext,Be as forkSourceNode,Fe as inboxBetweenTurns,be as newJobId,Ae as newNodeId,En as nodeEnv,vn as preflightNodeId,Rn as rootOfSpine,hn as setInstallId,In as spawnNode};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var p=Object.defineProperty;var n=(e,t)=>p(e,"name",{value:t,configurable:!0});import{abortExecution as y,beginExecution as _,getNode as s,setPresence as h,setFocusOccupant as v,fullName as R,recordExecutionPid as b,recordLaunch as
|
|
1
|
+
var p=Object.defineProperty;var n=(e,t)=>p(e,"name",{value:t,configurable:!0});import{abortExecution as y,beginExecution as _,getNode as s,setPresence as h,setFocusOccupant as v,fullName as R,recordExecutionPid as b,recordLaunch as k}from"../canvas/index.js";import{pushFinal as E}from"../feed/feed.js";import{newestReportBody as g}from"../feed/reports.js";import{spawnNode as S,rootOfSpine as x}from"./nodes.js";import{buildLaunchSpecAsync as T,buildPiArgv as B}from"./launch.js";import{focusOf as N,respawnPaneSync as O,setPaneOption as P}from"./placement.js";import{waitForBrokerViewSocket as C,viewerSplitEnv as D}from"./placement-tmux.js";import{headlessBrokerHost as u}from"./host.js";import{boundFleet as F}from"./fleet.js";import{transition as z}from"./lifecycle.js";import{ensureDaemon as A}from"../../daemon/manage.js";import{invokeBirthLifecycleHooks as L}from"./spawn.js";import{checkStart as U}from"./start-check.js";async function ne(e,t){const a=await s(e);if(a===null)return{recycled:!1,finalized:!1,newRoot:null,delivered:[]};const o=t??process.env.TMUX_PANE;if(o===void 0||o==="")return{recycled:!1,finalized:!1,newRoot:null,delivered:[]};await U(a);const w=await N(e);try{A()}catch{}const{launch:f}=await T("general","base",{lifecycle:"resident",hasManager:!1,cwd:a.cwd,profileId:a.profile_id}),m=await g(e)||`Closed via recycle \u2014 no final summary was authored by ${a.name}.`;let c=[],d=!1;const r=await S({kind:"general",mode:"base",lifecycle:"resident",cwd:a.cwd,name:"general",parent:null,replaces:e,profile_id:a.profile_id,launch:f,beforeCreate:n(async()=>{try{c=(await E(e,m)).deliveredTo,d=!0}catch{}},"beforeCreate")}),i=await s(r.node_id);await L(i);const l=B(i);if(l.env={...l.env,CRTR_SUBTREE:await x(r.node_id)},!await H(i,l))return{recycled:!1,finalized:d,newRoot:r.node_id,delivered:c};try{u.teardown(e)}catch{}try{await h(e,{pane:null,window:null,tmux_session:null})}catch{}if(w!==null)try{await v(w.focus_id,r.node_id)}catch{}return{recycled:V(i,o),finalized:d,newRoot:r.node_id,delivered:c}}n(ne,"recycleNode");async function H(e,t){const a=await _(e.node_id,{daemonEpoch:F().epoch()});t.env={...t.env,CRTR_EXECUTION_ID:a};let o;try{if(o=await u.launch(e.node_id,t,{cwd:e.cwd,name:R(e),resuming:!1}),o.pid===null)throw new Error("broker host returned no pid");if(await k(e.node_id,new Date().toISOString()),await b(a,e.node_id,o.pid)==="shutdown")throw new Error("broker execution was superseded");if(await C(e.node_id,o.exited))return!0}catch{await y(a,{reason:"launch_failed"})}try{await M(e.node_id)}catch{}try{u.teardown(e.node_id)}catch{}return!1}n(H,"launchRecycledBroker");async function M(e){const t=await s(e);(t?.status==="active"||t?.status==="idle")&&await z(e,"crash")}n(M,"transitionReplacementToDead");function V(e,t){try{P(t,"@crtr_node","")}catch{}return O({pane:t,cwd:e.cwd,env:D(),command:`crtr surface attach to ${e.node_id}`})}n(V,"respawnRecycledViewer");export{ne as recycleNode};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var S=Object.defineProperty;var s=(e,
|
|
1
|
+
var S=Object.defineProperty;var s=(e,a)=>S(e,"name",{value:a,configurable:!0});import{getNode as f,beginExecution as B,recordExecutionPid as N,abortExecution as v,bindSession as b,recordLaunch as g,fullName as x,liveExecutionForNode as F,closeFocusRow as R,view as O}from"../canvas/index.js";import{transition as r}from"./lifecycle.js";import{headlessBrokerHost as y,requestBrokerTeardown as V}from"./host.js";import{boundFleet as C}from"./fleet.js";import{tearDownNode as D,focusOf as P,registerViewerFocus as T,respawnPaneSync as I,windowOfPane as L,renameWindow as q}from"./placement.js";import{viewerSplitEnv as A,waitForBrokerViewSocket as H}from"./placement-tmux.js";import{buildLaunchSpecAsync as M,buildPiArgv as U}from"./launch.js";import{newNodeId as j,spawnNode as W,rootOfSpine as X}from"./nodes.js";import{appSpace as $}from"../layout.js";import{join as z}from"node:path";import{invokeBirthLifecycleHooks as G}from"./spawn.js";import{checkStart as J}from"./start-check.js";async function K(e){const a=[];for(const i of await O(e))try{await r(i,"cancel",{reason:"closed"}),V(i),await D(i),a.push(i)}catch{}return a}s(K,"reapDescendants");async function ue(e,a={}){const i=a.launchBroker??y.launch,l=a.waitForViewSocket??H,p=a.respawnViewer??I,c=a.teardownBroker??y.teardown,n=await f(e);if(n===null||n.parent!=null||n.status==="done")return null;await J(n);const d=await P(e),h=n.isolated?await j():void 0,_=h?z($(n.grantee??"app:terminal").nodes,h):n.cwd,{launch:E}=await M(n.kind,"base",{lifecycle:"resident",hasManager:!1,model:n.model_override??void 0,modelIntent:n.launch?.modelIntent,modelExact:n.launch?.modelExact,cwd:_,profileId:n.profile_id}),t=await W({nodeId:h,kind:n.kind,mode:"base",lifecycle:"resident",cwd:_,name:n.kind,parent:null,replaces:e,profile_id:n.profile_id,launch:E,modelOverride:n.model_override??void 0});await G(t);const u=U(t,{});u.env={...u.env,CRTR_SUBTREE:await X(t.node_id)};const w=await B(t.node_id,{daemonEpoch:C().epoch()});u.env={...u.env,CRTR_EXECUTION_ID:w};let m;try{m=await i(t.node_id,u,{cwd:_,name:x(t),resuming:!1})}catch(o){throw await v(w,{reason:"launch_failed"}),await r(t.node_id,"crash"),o}if(m.pid==null)return await v(w,{reason:"launch_failed"}),await r(t.node_id,"crash"),null;if(await g(t.node_id,new Date().toISOString()),await N(w,t.node_id,m.pid)==="shutdown"){await v(w,{reason:"superseded"});try{c(t.node_id)}catch{}return await r(t.node_id,"crash"),null}let k=!1;try{k=await l(t.node_id,m.exited)}catch{}if(!k){const o=await f(t.node_id);(o?.status==="active"||o?.status==="idle")&&await r(t.node_id,"crash");try{c(t.node_id)}catch{}return null}if(await K(e),await r(e,"finish"),d?.pane!=null){await R(d.focus_id),p({pane:d.pane,cwd:n.cwd,env:A(),command:`crtr surface attach to ${t.node_id}`});const o=L(d.pane);o!==null&&q(o,x(t)),await T(t.node_id,d.pane,d.session,o)}return c(e),{newNodeId:t.node_id}}s(ue,"relaunchRoot");async function Q(e,a,i){const l=await f(e),p={reaped:[],detached:[],reset:!1};if(l===null||l.parent==null)return p;if(a!==void 0){const c=await F(e);c!==null&&await b(e,{executionId:c.executionId,sessionId:a,transcriptPath:i??null})}return p}s(Q,"resetRoot");async function we(e,a,i){return await f(e)===null?{path:"noop"}:(await Q(e,a,i),{path:"reset-child"})}s(we,"handleNewSession");async function fe(e,a){if(a!=="quit")return!1;const i=await f(e);return i===null||i.status!=="active"&&i.status!=="idle"||i.intent!=null?!1:(await r(e,"finish"),!0)}s(fe,"markCleanExitDone");export{we as handleNewSession,fe as markCleanExitDone,K as reapDescendants,ue as relaunchRoot,Q as resetRoot};
|
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
var
|
|
1
|
+
var q=Object.defineProperty;var s=(e,r)=>q(e,"name",{value:r,configurable:!0});import{assertGranteeRunsHere as Q}from"./unsandboxed.js";import{existsSync as B}from"node:fs";import{conversationIdFromPath as h,conversationStore as d,ConversationNotFoundError as D}from"../conversation-store/index.js";import{isAbsolute as Z}from"node:path";import{findNodeBySessionFile as I,getNode as R,updateNode as E,beginExecution as ee,recordExecutionPid as re,abortExecution as S,endLiveExecution as ie,unbindSession as O,recordLaunch as te,setFrozen as ne,clearFrozen as oe,fullName as T}from"../canvas/index.js";import{emitEvent as ae}from"../events/emit.js";import{consumeDeadlineOnWake as se}from"../feed/messages.js";import{isParked as z,transition as x}from"./lifecycle.js";import{publishNotice as le}from"./close.js";import{InputError as $}from"../io.js";import{buildPiArgv as p}from"./launch.js";import{buildReviveKickoff as ce,drainBearings as ue,hasRetainedReports as fe,readGoal as k,readYieldMessage as we,RUNTIME_RESTART_CONTINUATION as de}from"./kickoff.js";import{readRoadmap as H}from"./roadmap.js";import{encodeKickoffOrigin as he,KICKOFF_ORIGIN_ENV as pe}from"./stamp/protocol.js";import{headlessBrokerHost as M}from"./host.js";import{appMemoryFull as ve,appMemoryTooSmall as me,boundFleet as U,brokerCapReached as _e,brokerThresholdsForDaemon as K}from"./fleet.js";import{admitBrokerMemory as ye}from"./memory-admission.js";import{beginBootFaultAttempt as ke,clearFault as ge,hasAdmittedTurn as be}from"../canvas/recovery.js";import{clearNodeLedger as G,forkNodeLedger as Re,noticeChangedWhileDone as Ee}from"./ledger.js";import{forkSourceNode as Se,rootOfSpine as xe}from"./nodes.js";import{checkStart as $e}from"./start-check.js";import{isReviewCompanionBound as Ce}from"../review/companion.js";import{assertProfileActive as Ne}from"../profiles/manifest.js";import{isPidAlive as Ae}from"../canvas/pid.js";import{crtrHome as Fe,jobDir as Pe}from"../canvas/paths.js";import{contextDir as Be,ensureNodeDirs as De,nodeAgentDir as Oe}from"../canvas/node-agent-paths.js";import{discoverLifecycleHookRegistry as Te}from"../command-hooks/discovery.js";import{invokeLifecycleHooks as ze}from"../command-hooks/transport/exec-lifecycle.js";async function He(e,r){const i=e.pi_session_file,t=i?h(i):null;if(t===null)return{};try{const n=await d().header(t);return r?{resumeSessionPath:n.path}:{resumeSessionPath:n.path,newCycle:!0}}catch(n){if(n instanceof D)return{};throw n}}s(He,"resumeArgs");async function L(e){const r=h(e);if(r===null)return!1;try{return await d().header(r),!0}catch(i){if(i instanceof D)return!1;throw i}}s(L,"conversationExists");async function Me(e){const r=h(e);return r===null?!0:(await d().read(r)).entries.some(i=>i.type==="message")}s(Me,"sessionHasConversation");async function Ue(e){const r=h(e);if(r===null)return!0;const i=(await d().header(r)).header.cwd;return typeof i!="string"||B(i)}s(Ue,"sessionCwdExists");async function Ke(e,r,i){const t=r.pi_session_file;if(!t||!await L(t))return{};const n=await I(t);return n!==null&&n.node_id!==e&&Ae(n.pi_pid)?{}:await Ue(t)?await He(r,i):{}}s(Ke,"resumableSessionArgs");async function Ge(e){return await H(e)===null&&await we(e)===null&&!await fe(e)}s(Ge,"isUnstartedBirth");async function kr(e){const r=await k(e);if(r!==null&&r.trim()!=="")return!0;const i=await H(e);return i!==null&&i.trim()!==""}s(kr,"hasFreshGroundState");async function gr(e,r){const i=await j(e,r,!0);if(i.parked)throw new Error(`reviveNode: internal parked decision for activating revive ${e}`);return i.result}s(gr,"reviveNode");async function br(e,r,i){return j(e,{...r,viewerAttach:!0},i)}s(br,"decideAttachRevive");async function j(e,r,i){let t=await R(e);if(t===null)throw new Error(`reviveNode: unknown node ${e}`);if(t=await R(e)??t,t.run_id&&(await R(t.run_id))?.deleting_at)throw new Error("run is deleting");if(t.final_report!==null)throw new Error(`reviveNode: refusing to revive ${e} \u2014 its finalization latch is set (final_report=${t.final_report}). A final landed between the caller's reopen-gate check and this revive; re-run with --reopen if this retask is still wanted.`);Ne(t.profile_id),Q(t.grantee);const n=U();if(!n.has(e)&&!n.isClaimed(e)&&r.wakeReason!=="runtime-restart-abort"&&r.viewerAttach!==!0&&!(!i&&t.lifecycle==="resident"&&z(t))&&await $e(t),n.has(e))return await x(e,t.intent==="refresh"?"refresh-launch":"revive"),{parked:!1,result:{window:null,session:t.tmux_session??null,resumed:!1,outcome:"already-live"}};if(n.isClaimed(e))return{parked:!1,result:{window:null,session:t.tmux_session??null,resumed:!1,outcome:"already-live"}};if(!i&&t.lifecycle==="resident"&&z(t))return{parked:!0};const l=n.reserveSlot(e);let a=null;if(l){try{a=await ye(e)}catch(u){throw n.releaseReservation(e),u}a.verdict!=="admitted"&&n.releaseReservation(e)}if(a?.verdict==="too_small")throw me(a);if(!l||a?.verdict==="denied"){if(r.capacity==="refuse")throw a?.verdict==="denied"?ve(a):_e(K().automaticReviveCap,n.size());return t.frozen_at==null&&(await ne(e,new Date().toISOString()),await ie(e,{reason:"frozen"}),ae({level:"info",event:"broker.frozen",node_id:e,fields:a?.verdict==="denied"?{reason:"app_memory",free_bytes:a.free_bytes,needed_bytes:a.needed_bytes}:{reason:"broker_cap",live_count:n.size(),hard_cap:K().automaticReviveCap}})),{parked:!1,result:{window:null,session:t.tmux_session??null,resumed:!1,outcome:"frozen"}}}try{return{parked:!1,result:await Le(e,t,r)}}finally{n.releaseReservation(e)}}s(j,"decideRevive");async function Le(e,r,i){if(!B(r.cwd)){const v=r.fork_from!=null?`Restore ${r.cwd}, then revive the fork normally with \`crtr node lifecycle revive ${e}\`.`:r.managed_worktree?.state==="open"?"Restore or reconcile the recorded checkout, then use the managed-worktree close or abandon recovery.":`Recreate ${r.cwd}, or repair it with \`crtr node config --cwd <path> --node ${e}\`; durable node work resumes in a fresh conversation. Then retry \`crtr node lifecycle revive ${e}\`.`;throw new $({error:"cwd_missing",message:`${e} cannot be revived \u2014 its recorded cwd no longer exists: ${r.cwd}`,next:v})}r.host_kind!=="broker"&&(await E(e,{host_kind:"broker"}),r.host_kind="broker"),r.review_binding!=null&&!await Ce(e)&&(r.pi_session_id!=null||r.pi_session_file!=null)&&(await O(e),r.pi_session_id=null,r.pi_session_file=null);const n=r.fork_from!=null&&r.pi_session_id==null,l=r.fork_source_file;if(n&&(typeof l!="string"||!Z(l)))throw new $({error:"fork_source_invalid",message:`${e} cannot be revived \u2014 its resolved fork source file is missing or invalid.`,next:`Restore the node's fork source metadata, then retry \`crtr node lifecycle revive ${e}\`.`});const a=n&&typeof l=="string";if(a&&!await L(l))throw new $({error:"fork_from_missing",message:`${e} cannot be revived \u2014 its fork source no longer exists: ${l}`,next:`Restore ${l}, or update the node's fork source, then retry \`crtr node lifecycle revive ${e}\`.`});const u=await ee(e,{daemonEpoch:U().epoch()});try{r.cycles=(r.cycles??0)+1,await E(e,{cycles:r.cycles});const W=r.intent==="refresh"||r.cycle_pending===!0?!1:i.resume,w=a?{}:await Ke(e,r,W),m=w.resumeSessionPath!==void 0,C=m&&w.newCycle===!0,_=m&&!C,N=!m&&(i.wakeReason===void 0||i.wakeReason==="runtime-restart-abort")&&await Ge(e),g=_&&(i.wakeReason===void 0||i.wakeReason==="runtime-restart-abort")&&!await be(e)&&!await Me(w.resumeSessionPath)?(await k(e))?.trim():void 0,A=g!==void 0&&g!=="",J=a||N||A,F=r.cycle_pending===!0||C;await E(e,{cycle_pending:F}),r.cycle_pending=F,!a&&!m&&(r.pi_session_id!=null||r.pi_session_file!=null)&&(await O(e),r.pi_session_id=null,r.pi_session_file=null);let c,f=null;const b=s(()=>({type:"runtime",kind:"kickoff",...r.spawned_by!=null&&r.spawned_by!==""?{spawnedBy:r.spawned_by}:{}}),"birthOrigin");if(a){const o=await k(e),P=h(l);if(P===null)throw new Error(`invalid fork source ${l}`);const Y=(await d().header(await d().fork(P,e))).path;c=p(r,{resumeSessionPath:Y,...o!=null&&o!==""?{prompt:o}:{}}),o!=null&&o!==""&&(f=b()),await Re(e,(await Se(l))?.node_id??null)}else if(A)c=p(r,{...w,prompt:g}),f=b();else if(_)c=p(r,{...w,...i.wakeReason==="runtime-restart-abort"?{prompt:de}:{}}),i.wakeReason==="runtime-restart-abort"&&(f={type:"runtime",kind:"restart-continuation"});else if(N){const o=(await k(e))?.trim();c=p(r,o!==void 0&&o!==""?{prompt:o}:{}),o!==void 0&&o!==""&&(f=b()),await G(e)}else{const o=await ue(r,u);c=p(r,{...w,prompt:await ce(r,o,i.wakeReason==="runtime-restart-abort"?void 0:i.wakeReason)}),r.run_id&&o.unreadMessageIds?.length&&(c.env.CRTR_KICKOFF_MESSAGE_IDS=JSON.stringify(o.unreadMessageIds)),f=i.wakeReason!==void 0&&i.wakeReason!=="runtime-restart-abort"?{type:"runtime",kind:"wake",wake:i.wakeReason}:{type:"runtime",kind:"revive",cycle:r.cycles??0},await G(e)}c.env={...c.env,CRTR_SUBTREE:await xe(e)},f!==null&&(c.env[pe]=he(f)),r.status==="done"&&r.last_settled_at!=null&&await Ee(e,r.last_settled_at),await x(e,r.intent==="refresh"?"refresh-launch":"revive"),await ge(e,{preserveEpisode:!0});const V=await ke(e);i.recovery!==!0&&i.viewerAttach!==!0&&await se(e),await De(e,r.grantee);const X=Te(r.cwd,r.profile_id).plans.get("node:start")??[];await ze(X,{node:{id:e,name:r.name,kind:r.kind,mode:r.mode,lifecycle:r.lifecycle,cwd:r.cwd,nodeDir:await Oe(e),contextDir:await Be(e),jobDir:Pe(e)},runtime:{isBirth:J,canvasHome:Fe(),profile:r.profile_id??null}}),c.env={...c.env,CRTR_EXECUTION_ID:u};let y;try{if(y=await M.launch(e,c,{cwd:r.cwd,name:T(r),resuming:_}),y.pid===null)throw new Error(`broker host returned no pid for ${e}`)}catch(o){try{await x(e,"crash",{reason:"launch_failed",outcome:{detail:{schema:"crtr.node-outcome-detail/v1",message:o instanceof Error?o.message:String(o)}}}),await le(e,"notice.crash",`Child crashed \u2014 ${T(r)} (${e}) failed to relaunch and is now dead: ${o.message}
|
|
2
2
|
|
|
3
|
-
It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,{reason:"child-crashed",child:e})}catch{}throw await S(u,{reason:"launch_failed"}),new Error(`[broker] refusing to revive ${e}: ${o.message}`)}if(await
|
|
3
|
+
It stays dead until you revive it \u2014 \`crtr node lifecycle revive ${e}\`.`,{reason:"child-crashed",child:e})}catch{}throw await S(u,{reason:"launch_failed"}),new Error(`[broker] refusing to revive ${e}: ${o.message}`)}if(await te(e,new Date().toISOString()),await re(u,e,y.pid)==="shutdown")throw await S(u,{reason:"superseded"}),M.teardown(e),new Error(`[broker] refusing to revive ${e}: execution was superseded during launch`);return await oe(e),{window:null,session:r.tmux_session??null,resumed:_,launch:y,faultExplanation:V.explanation,outcome:"launched"}}catch(v){throw await S(u,{reason:"launch_failed"}),v}}s(Le,"launchRevive");export{br as decideAttachRevive,kr as hasFreshGroundState,He as resumeArgs,gr as reviveNode};
|