@north-light/cli 0.3.577 → 0.3.579
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/contract.d.ts +1 -1
- package/dist/api/contract.js +1 -1
- package/dist/api/dto/run-events.d.ts +10 -4
- package/dist/build-root.js +1 -1
- package/dist/builtin-memory/crouter-sdk/release-notes.md +8 -0
- package/dist/builtin-memory/crouter-sdk/streaming.md +2 -0
- package/dist/builtin-memory/northlight-apps/concepts/runs.md +2 -0
- package/dist/builtin-memory/northlight-apps/guides/stream-a-run.md +1 -1
- package/dist/builtin-memory/northlight-apps/guides/test-your-app.md +1 -1
- package/dist/clients/attach/viewer.js +338 -338
- package/dist/core/command.js +5 -5
- package/dist/core/human/feedback-companion.js +1 -1
- package/dist/core/human/page.d.ts +2 -4
- package/dist/core/human/page.js +6 -6
- package/dist/core/human/request-files.d.ts +14 -0
- package/dist/core/human/request-files.js +1 -0
- package/dist/core/human/requests.d.ts +3 -0
- package/dist/core/human/requests.js +18 -17
- package/dist/core/human/tickets.js +1 -1
- package/dist/core/human/visible-paths.d.ts +7 -0
- package/dist/core/human/visible-paths.js +1 -1
- package/dist/core/llm/refusal.d.ts +2 -1
- package/dist/core/llm/refusal.js +1 -1
- package/dist/core/review/document.d.ts +4 -4
- package/dist/core/review/document.js +2 -2
- package/dist/core/review/project.d.ts +7 -5
- package/dist/core/review/project.js +2 -1
- package/dist/core/review/remap.js +1 -1
- package/dist/core/review/stage.d.ts +2 -0
- package/dist/core/review/stage.js +1 -1
- package/dist/core/review/store.js +1 -1
- package/dist/core/runs/operations.d.ts +1 -1
- package/dist/core/runs/operations.js +5 -5
- package/dist/core/runtime/broker/held-deferred-inbox.d.ts +4 -0
- package/dist/core/runtime/broker/held-deferred-inbox.js +1 -1
- package/dist/core/runtime/broker/rebind.d.ts +3 -0
- package/dist/core/runtime/broker/rebind.js +1 -1
- package/dist/core/runtime/broker/run-steer.d.ts +15 -0
- package/dist/core/runtime/broker/run-steer.js +1 -0
- package/dist/core/runtime/broker/run-turn-queue.d.ts +2 -0
- package/dist/core/runtime/broker/run-turn-queue.js +1 -1
- package/dist/core/runtime/broker.js +1 -1
- package/dist/core/runtime/runner/blaxel/client.d.ts +2 -2
- package/dist/core/runtime/runner/blaxel/client.js +1 -1
- package/dist/core/runtime/runner/blaxel/runner.js +2 -2
- package/dist/daemon/api/bridge.d.ts +1 -1
- package/dist/daemon/api/bridge.js +5 -5
- package/dist/daemon/api/handlers/feedback-comments.js +2 -2
- package/dist/daemon/api/handlers/inbox-page.js +1 -1
- package/dist/daemon/api/handlers/inbox.js +1 -1
- package/dist/daemon/api/handlers/reviews.js +1 -1
- package/dist/daemon/api/handlers/runs.js +1 -1
- package/dist/daemon/profile-delete.js +1 -1
- package/dist/daemon/review/finish.js +1 -1
- package/dist/daemon/review/sweep.js +1 -1
- package/dist/daemon/runs/append-section.js +2 -2
- package/dist/daemon/runs/observer.js +3 -3
- package/dist/pi-extensions/canvas-bash-valve.js +6 -6
- package/dist/pi-extensions/canvas-inbox-watcher.js +2 -2
- package/dist/shared/env.d.ts +5 -0
- package/dist/shared/env.js +2 -2
- package/docs/apps/concepts/runs.md +2 -0
- package/docs/apps/guides/stream-a-run.md +1 -1
- package/docs/apps/guides/test-your-app.md +1 -1
- package/docs/sdk/release-notes.md +8 -0
- package/docs/sdk/streaming.md +2 -0
- package/package.json +2 -2
- package/packages/crouter-identity/package.json +1 -1
- package/runtime.lock.json +162 -665
|
@@ -1 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var l=Object.defineProperty;var s=(e,t)=>l(e,"name",{value:t,configurable:!0});import{atomicWriteJson as u}from"../human/convention.js";import{isCloudRole as c}from"../canvas/person.js";import{writeRequestFile as r}from"../human/request-files.js";function f(e,t,n,o){return{schema:"humanloop.review-response/v1",review_id:e.review_id,file:e.file,submitted:!0,approved:!0,changed:n!==e.baseline_sha256,baseline_sha256:e.baseline_sha256,approved_sha256:n,companion_node_id:e.companion_node_id,comments_total:t.total,comments_unresolved:t.unresolved,comments:t.comments,submittedAt:o,savedAt:o}}s(f,"buildReviewResult");const a=s(e=>JSON.stringify(e,null,2)+`
|
|
2
|
+
`,"json");async function v(e,t){const n=`${e.review_dir}/result.json`;await r(n,a(t));const o=c()?null:e.output_path,i=o??`${e.review_dir}/feedback.json`;return i!==n&&(o===null?await r(i,a(t)):u(i,t)),{destinations:i===n?[n]:[n,i]}}s(v,"projectReviewResult");async function b(e,t){const n=`${e.review_dir}/result.json`;return await r(n,a(t)),{destinations:[n]}}s(b,"projectReviewCancellation");export{f as buildReviewResult,b as projectReviewCancellation,v as projectReviewResult};
|
|
@@ -3,7 +3,7 @@ var q=Object.defineProperty;var r=(e,o)=>q(e,"name",{value:o,configurable:!0});i
|
|
|
3
3
|
(review_id, comment_id, kind, state_change, revision_after, actor_kind, actor_node_id, at, operation_id, payload)
|
|
4
4
|
SELECT review_id, ?, 'reanchored', 1, ?, ?, ?, ?, ?, ?
|
|
5
5
|
FROM review_comments WHERE comment_id = ?
|
|
6
|
-
`).run(o.row.comment_id,o.row.revision+1,o.actor.kind,o.actor.node_id,o.at,o.operation_id,JSON.stringify({previous_anchor:o.previous_anchor,anchor:o.anchor,previous_anchor_state:o.previous_anchor_state,anchor_state:o.anchor_state,previous_doc_hash:o.previous_doc_hash,doc_hash:o.doc_hash,line_text:o.line_text}),o.row.comment_id)}r(L,"appendReanchorEvent");async function U(e){const o=await A(async c=>{const i=await c.prepare("SELECT file, anchor_base_sha256 FROM human_requests WHERE request_id = ? AND kind = 'review' AND state = 'open'").get(e.review_id);if(i===void 0)throw new h("unknown_review","review was not found",{received:e.review_id});const a=O(i.file,"comment");a.sha256!==e.to_doc_hash&&p("to_doc_hash",e.to_doc_hash,a.sha256),i.anchor_base_sha256!==e.from_doc_hash&&p("from_doc_hash",i.anchor_base_sha256,e.from_doc_hash);const d=await c.prepare(`
|
|
6
|
+
`).run(o.row.comment_id,o.row.revision+1,o.actor.kind,o.actor.node_id,o.at,o.operation_id,JSON.stringify({previous_anchor:o.previous_anchor,anchor:o.anchor,previous_anchor_state:o.previous_anchor_state,anchor_state:o.anchor_state,previous_doc_hash:o.previous_doc_hash,doc_hash:o.doc_hash,line_text:o.line_text}),o.row.comment_id)}r(L,"appendReanchorEvent");async function U(e){const o=await A(async c=>{const i=await c.prepare("SELECT file, anchor_base_sha256 FROM human_requests WHERE request_id = ? AND kind = 'review' AND state = 'open'").get(e.review_id);if(i===void 0)throw new h("unknown_review","review was not found",{received:e.review_id});const a=await O(i.file,"comment");a.sha256!==e.to_doc_hash&&p("to_doc_hash",e.to_doc_hash,a.sha256),i.anchor_base_sha256!==e.from_doc_hash&&p("from_doc_hash",i.anchor_base_sha256,e.from_doc_hash);const d=await c.prepare(`
|
|
7
7
|
SELECT comment_id, status, revision, text, anchor_line, anchor_end_line,
|
|
8
8
|
anchor_col_start, anchor_col_end, anchor_quote, anchor_line_text,
|
|
9
9
|
anchor_doc_hash, anchor_state
|
|
@@ -31,6 +31,8 @@ export type StagedReview = {
|
|
|
31
31
|
};
|
|
32
32
|
/** Remove only review-directory state that was never committed to a review row. */
|
|
33
33
|
export declare function discardStaging(reviewId: string, branchFile?: string): Promise<void>;
|
|
34
|
+
/** Delete one review's files: its `requests/<id>/` blobs on a cloud role, else its review directory. */
|
|
35
|
+
export declare function deleteReviewFiles(reviewId: string): Promise<void>;
|
|
34
36
|
/**
|
|
35
37
|
* Capture an existing origin and write its immutable branch without creating a
|
|
36
38
|
* canvas node or review row. The caller alone commits or discards this stage.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var F=Object.defineProperty;var n=(e,i)=>F(e,"name",{value:i,configurable:!0});import{createHash as k}from"node:crypto";import{existsSync as B,realpathSync as x,rmSync as E,statSync as I}from"node:fs";import{isAbsolute as O}from"node:path";import{getNode as q}from"../canvas/index.js";import{conversationIdFromPath as D,conversationStore as $,ConversationNotFoundError as z}from"../conversation-store/index.js";import{ensureReviewDir as j,reviewDir as p}from"../canvas/paths.js";import{checkReviewableBytes as N,checkReviewableFile as P}from"../human/visible-paths.js";import{isCloudRole as w}from"../canvas/person.js";import{blobStore as U}from"../blobs/index.js";import{REQUEST_BLOB_PREFIX as A,isBlobRequestPath as h,readRequestFile as v,writeRequestFile as C}from"../human/request-files.js";import{newNodeId as y}from"../runtime/nodes.js";import{captureOrigin as T}from"./companion.js";import{materializeSessionBranch as H}from"../runtime/session-branch.js";import{getRequestByIdempotencyKey as K}from"../human/requests.js";import{ReviewOperationError as r}from"./types.js";function o(e,i){return new r("review_target_unreviewable","review target cannot be staged",{phase:"create",file:e,reason:i})}n(o,"targetError");function d(e){return w()?`${A}${e}`:p(e)}n(d,"stagedReviewDir");function b(e){return e==="file is not UTF-8 text"?"binary":e==="file is too large to review (2 MB limit)"?"too_large":e==="file is too long to review (5,000 line limit)"?"too_many_lines":"not_a_file"}n(b,"unreviewableReason");async function L(e){const i=N(await v(e));if(!i.ok)throw o(e,b(i.reason));return e}n(L,"validateBlobReviewFile");function g(e){if(!O(e))throw o(e,"not_absolute");if(!B(e))throw o(e,"missing");try{if(!I(e).isFile())throw o(e,"not_a_file")}catch(t){throw t instanceof r?t:o(e,"missing")}const i=P(e);if(!i.ok)throw o(e,b(i.reason));try{return x(e)}catch{throw o(e,"missing")}}n(g,"validateReviewFile");function M(e){return new r("review_branch_unavailable","review branch could not be materialized",{reason:"materialize_failed",origin_node_id:e})}n(M,"branchUnavailable");async function Q(e){try{return await T(e)}catch(i){throw i instanceof r&&i.code==="review_origin_missing"?new r("review_origin_missing","review origin was not found",{origin_node_id:e,reason:"origin_missing"}):i}}n(Q,"captureStagedOrigin");async function X(e,i){try{return await H(i)}catch{throw M(e)}}n(X,"materialize");async function G(e,i){if(i!==void 0){const t=D(i);if(t===null)throw new Error(`invalid staged conversation path: ${i}`);try{await $().delete(t)}catch(c){if(!(c instanceof z))throw c}}try{await J(e)}catch{}}n(G,"discardStaging");async function J(e){if(w()){const i=await U();for(const t of await i.list(`${d(e)}/`))await i.delete(t)}else E(p(e),{recursive:!0,force:!0})}n(J,"deleteReviewFiles");async function _e(e){const i=await K(e.idempotency_key);if(i!==null)return{existing:i};if(e.document===void 0&&w())throw o(e.file??"","cloud_unsupported");if(await q(e.origin_node_id)===null)throw new r("review_origin_missing","review origin was not found",{origin_node_id:e.origin_node_id,reason:"origin_missing"});const t=await y(),c=await y();let u,_=e.document===void 0?g(e.file??""):"";try{const l=d(t);if(h(l)||j(t),e.document!==void 0){const s=`${l}/document.md`;await C(s,e.document.body),_=h(s)?await L(s):g(s)}const a=await Q(e.origin_node_id),R=new Date().toISOString(),m=await v(_),f=k("sha256").update(m).digest("hex");u=await X(e.origin_node_id,a);const S=new Date().toISOString();return{row:{review_id:t,idempotency_key:e.idempotency_key,origin_kind:e.origin_kind,origin_node_id:e.origin_node_id,companion_node_id:c,review_dir:d(t),file:_,origin_session_file:a.sourceFile,origin_session_id:a.sourceSessionId,origin_leaf_id:a.leafId,model_spec:a.modelSpec,branch_file:u,baseline_sha256:f,baseline_bytes:m.length,anchor_base_sha256:f,anchor_base_bytes:m,state:"binding",created:S,captured_at:R,opened_at:null,submit_requested_at:null,output_path:e.output_path??null,document_id:e.document?.id??null,document_name:e.document?.name??null,document_base:e.document?.base??null,subtitle:e.subtitle??null,approved_at:null,approved_sha256:null,changed:null,comments_total:null,comments_unresolved:null,result_json:null,canceled_at:null,cancel_reason:null,cancel_actor:null,delivery_entry_id:null,delivered_at:null,delivery_error:null,projected_at:null,projection_error:null},review_dir:d(t)}}catch(l){throw await G(t,u),l}}n(_e,"stageReview");export{J as deleteReviewFiles,G as discardStaging,_e as stageReview};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var u=Object.defineProperty;var r=(e,t)=>u(e,"name",{value:t,configurable:!0});import{requestFileExists as l}from"../human/request-files.js";import{withCanvasWrite as d,openDb as s}from"../canvas/db.js";import{getRequest as _,getRequestByCompanion as p,getRequestByIdempotencyKey as w,listBindingRequests as m,listRequests as c,listSubmitRequestedRequests as v,listUnprojectedReviews as f,markProjected as y,markProjectionError as h,openRequest as R,readAnchorBase as E,replaceAnchorBaseLocked as j,requestSubmit as k}from"../human/requests.js";import{ReviewOperationError as b}from"./types.js";function g(e){try{const t=JSON.parse(e.specification_json);if(typeof t!="object"||t===null)throw new Error("not an object");return t}catch(t){throw new Error(`corrupt review specification: ${e.request_id}`,{cause:t})}}r(g,"specification");function x(e){return e.state!=="settled"?e.state:e.outcome==="approved"?"approved":"canceled"}r(x,"state");function N(e,t){if(e.kind!=="review")throw new Error(`human request is not a review: ${e.request_id}`);const n=g(e),i=x(e),o=e.settled_at;return{review_id:e.request_id,idempotency_key:e.idempotency_key??"",origin_kind:n.origin_kind??(e.inbox_listed?"ticket":"inline"),origin_node_id:e.requester_node_id??"",companion_node_id:e.companion_node_id??"",review_dir:e.request_dir,file:e.file??"",origin_session_file:n.origin_session_file,origin_session_id:n.origin_session_id,origin_leaf_id:n.origin_leaf_id,model_spec:n.model_spec,branch_file:n.branch_file,baseline_sha256:n.baseline_sha256,baseline_bytes:n.baseline_bytes,anchor_base_sha256:e.anchor_base_sha256??"",state:i,created:e.created_at,captured_at:n.captured_at,opened_at:e.opened_at,submit_requested_at:e.submit_requested_at,output_path:n.output_path??null,document_id:n.document_id??null,document_name:n.document_name??null,document_base:n.document_base??null,subtitle:e.subtitle,approved_at:i==="approved"?o:null,approved_sha256:i==="approved"?(()=>{try{return JSON.parse(e.result_json??"{}").approved_sha256??null}catch{return null}})():null,changed:i==="approved"?(()=>{try{return JSON.parse(e.result_json??"{}").changed??null}catch{return null}})():null,comments_total:i==="approved"?(()=>{try{return JSON.parse(e.result_json??"{}").comments_total??null}catch{return null}})():null,comments_unresolved:i==="approved"?(()=>{try{return JSON.parse(e.result_json??"{}").comments_unresolved??null}catch{return null}})():null,result_json:e.result_json,canceled_at:i==="canceled"?o:null,cancel_reason:i==="canceled"?(()=>{try{return JSON.parse(e.result_json??"{}").reason??null}catch{return null}})():null,cancel_actor:i==="canceled"?(()=>{try{return JSON.parse(e.result_json??"{}").actor??null}catch{return null}})():null,delivery_entry_id:e.settlement_delivery_id,delivered_at:e.settlement_delivery_id===null?null:o,delivery_error:null,projected_at:e.projected_at,projection_error:e.projection_error,source_missing:t}}r(N,"record");async function a(e){return N(e,!await l(e.file??""))}r(a,"recordOf");async function S(e){const t=await _(e);return t?.kind==="review"?t:null}r(S,"requestForReview");async function A(e){const t=await S(e);return t===null?null:await a(t)}r(A,"getReview");async function U(e){const t=await A(e);if(t===null||t.state==="binding")throw new b("unknown_review","review was not found",{received:e});return t}r(U,"requireVisibleReview");async function T(e){const t=await w(e);return t?.kind==="review"?await a(t):null}r(T,"getReviewByIdempotencyKey");async function I(e){const t=await p(e);return t?.kind==="review"?await a(t):null}r(I,"getReviewByCompanion");async function J(e){const t=await c({kind:"review",...e.origin_node_id===void 0?{}:{requester_node_id:e.origin_node_id},...e.file===void 0?{}:{file:e.file}});return(await Promise.all(t.map(a))).filter(n=>n.state!=="binding"&&(e.state===void 0||n.state===e.state))}r(J,"listReviews");async function D(e){const t=new Set(e);return(await c({kind:"review"})).filter(n=>n.requester_node_id!==null&&t.has(n.requester_node_id)).map(n=>n.request_id)}r(D,"reviewIdsByOriginNodes");async function W(e){const t=await D(e);return t.length===0?[]:(await d(async n=>{const i=t.map(()=>"?").join(",");await n.prepareUncached(`DELETE FROM review_comment_events WHERE review_id IN (${i})`).run(...t),await n.prepareUncached(`DELETE FROM review_comments WHERE review_id IN (${i})`).run(...t),await n.prepareUncached(`DELETE FROM human_requests WHERE request_id IN (${i})`).run(...t)}),t)}r(W,"deleteReviewsByOriginNodes");async function H(){return await Promise.all((await m()).map(a))}r(H,"listBindingReviews");async function F(){return await Promise.all((await v()).map(a))}r(F,"listSubmitRequestedReviews");async function $(){return await Promise.all((await f()).map(a))}r($,"listUnprojectedTerminalReviews");async function C(e,t){return await R(e,t)}r(C,"openReviewRow");async function M(e){await(await s()).prepare("UPDATE human_requests SET submit_requested_at = NULL, updated_at = ? WHERE request_id = ? AND kind = 'review' AND state = 'open'").run(new Date().toISOString(),e)}r(M,"clearReviewSubmit");async function K(e,t){return await k(e,t)}r(K,"requestReviewSubmit");async function V(e,t){return(await e.prepare("UPDATE human_requests SET state = 'settled', outcome = 'approved', result_json = ?, settled_at = ?, progress_json = NULL, updated_at = ? WHERE request_id = ? AND kind = 'review' AND state = 'open'").run(t.result_json,t.approved_at,t.approved_at,t.review_id)).changes>0}r(V,"approveReviewLocked");async function z(e,t){return(await(await s()).prepare("UPDATE human_requests SET state = 'settled', outcome = 'canceled', result_json = ?, settled_at = ?, progress_json = NULL, updated_at = ? WHERE request_id = ? AND kind = 'review' AND state = 'open'").run(JSON.stringify({schema:"humanloop.cancel/v1",kind:"canceled",canceledAt:t.at,...t.reason===""?{}:{reason:t.reason},...t.actor===null?{}:{actor:t.actor}}),t.at,t.at,e)).changes>0}r(z,"cancelReviewRow");async function G(e,t){await y(e,t)}r(G,"markProjected");async function Q(e,t){await h(e,t)}r(Q,"markProjectionError");function X(e,t,n){}r(X,"markDelivered");function Y(e,t){}r(Y,"markDeliveryError");async function Z(e){return await E(e)}r(Z,"readAnchorBase");async function ee(e,t,n,i){await j(e,t,n,i)}r(ee,"replaceAnchorBaseLocked");export{V as approveReviewLocked,z as cancelReviewRow,M as clearReviewSubmit,W as deleteReviewsByOriginNodes,A as getReview,I as getReviewByCompanion,T as getReviewByIdempotencyKey,H as listBindingReviews,J as listReviews,F as listSubmitRequestedReviews,$ as listUnprojectedTerminalReviews,X as markDelivered,Y as markDeliveryError,G as markProjected,Q as markProjectionError,C as openReviewRow,Z as readAnchorBase,ee as replaceAnchorBaseLocked,K as requestReviewSubmit,U as requireVisibleReview,D as reviewIdsByOriginNodes};
|
|
@@ -62,7 +62,7 @@ export declare function listRuns(grantee: string | null, options: {
|
|
|
62
62
|
next: string | null;
|
|
63
63
|
}>;
|
|
64
64
|
export declare function waitRun(id: string, grantee: string, seconds: number): Promise<Record<string, unknown>>;
|
|
65
|
-
export declare function messageRun(root: NodeMeta, original: string, resolveAttachments?: AttachmentResolver, startTurn?: boolean, idempotencyKey?: string): Promise<{
|
|
65
|
+
export declare function messageRun(root: NodeMeta, original: string, resolveAttachments?: AttachmentResolver, startTurn?: boolean, idempotencyKey?: string, steer?: boolean): Promise<{
|
|
66
66
|
run_id: string;
|
|
67
67
|
message_id: string;
|
|
68
68
|
sequence_number: number;
|
|
@@ -1,14 +1,14 @@
|
|
|
1
|
-
var Me=Object.defineProperty;var c=(e,t)=>Me(e,"name",{value:t,configurable:!0});import{coveredByAny as Ae}from"../../shared/env.js";import{createHash as Q}from"node:crypto";import{ApiError as Ie}from"../../api/errors.js";import{CrtrError as Te}from"../errors.js";import{isCloudRole as Le}from"../canvas/person.js";import{isAbsolute as V,relative as Ce,resolve as ke,sep as xe,join as We}from"node:path";import{SessionManager as Fe}from"@earendil-works/pi-coding-agent";import{covers as P}from"@north-light/identity";import{openDb as B,withCanvasWrite as F}from"../canvas/db.js";import{deleteNodeWithOwned as qe}from"../graph/deletion.js";import{getById as He}from"../graph/objects.js";import{repairRunConversations as Z}from"../canvas/sessions.js";import{getNode as O,nodeFiles as Ue,removeNodeFiles as $e,updateNode as Pe}from"../canvas/canvas.js";import{fullName as Be}from"../canvas/labels.js";import{renameWindow as je}from"../runtime/placement.js";import{liveExecutionForNode as K}from"../canvas/executions.js";import{conversationStore as ee,isConversationNotFound as Je}from"../conversation-store/index.js";import{PARKED_RESIDENT_SQL as Ye}from"../canvas/canvas.js";import{WAKE_MAIL_SQL as Ge}from"../canvas/deliveries.js";import{readNodeRecap as Xe}from"../canvas/node-recap.js";import{enqueueNodeMail as ze}from"../feed/messages.js";import{newestReportBody as Qe}from"../feed/reports.js";import{ensureAppProfile as te,loadExactProfileManifest as ne}from"../profiles/manifest.js";import{stopNodeSandboxes as se}from"../spaces/stop.js";import{BrokerUnreachableError as Ve}from"../runtime/broker-request.js";import{interruptLive as Ze}from"../runtime/interactive-deliver.js";import{isBrokerLive as ae}from"../runtime/model-swap.js";import{newNodeId as Ke}from"../runtime/nodes.js";import{reviveNode as j}from"../runtime/revive.js";import{spawnChildPrepared as et}from"../runtime/spawn.js";import{isPortableModelToken as tt}from"../runtime/launch.js";import{parseDurationMs as nt}from"../wake.js";import{expandModelCandidates as st,parseModelSpec as at}from"../model-routes.js";import{payerOfGrant as J}from"../grants/mirror.js";import{isolatedBrokerLauncherAvailable as it}from"../runtime/host.js";import{blaxelEnvironmentOf as rt}from"../runtime/blaxel-environment.js";import{resolveRunKind as ot,resolveRunModel as dt}from"../runtime/launch-target.js";import{cycleAwareMessages as ct}from"../runtime/session-cycles.js";import{originFor as ie}from"../runtime/stamp/protocol.js";import{readOutputRequest as ut,readOutputResult as re}from"../runtime/output-result.js";import{admitLegacyStructuredOutput as oe}from"../../daemon/structured-requests/sidecar.js";import{runSchemaRepromptPending as mt}from"../runtime/stop-guard.js";import{toRunOutcomeDTO as lt}from"../../daemon/api/map.js";import{openAssistantMessageStartSequence as
|
|
1
|
+
var Me=Object.defineProperty;var c=(e,t)=>Me(e,"name",{value:t,configurable:!0});import{coveredByAny as Ae}from"../../shared/env.js";import{createHash as Q}from"node:crypto";import{ApiError as Ie}from"../../api/errors.js";import{CrtrError as Te}from"../errors.js";import{isCloudRole as Le}from"../canvas/person.js";import{isAbsolute as V,relative as Ce,resolve as ke,sep as xe,join as We}from"node:path";import{SessionManager as Fe}from"@earendil-works/pi-coding-agent";import{covers as P}from"@north-light/identity";import{openDb as B,withCanvasWrite as F}from"../canvas/db.js";import{deleteNodeWithOwned as qe}from"../graph/deletion.js";import{getById as He}from"../graph/objects.js";import{repairRunConversations as Z}from"../canvas/sessions.js";import{getNode as O,nodeFiles as Ue,removeNodeFiles as $e,updateNode as Pe}from"../canvas/canvas.js";import{fullName as Be}from"../canvas/labels.js";import{renameWindow as je}from"../runtime/placement.js";import{liveExecutionForNode as K}from"../canvas/executions.js";import{conversationStore as ee,isConversationNotFound as Je}from"../conversation-store/index.js";import{PARKED_RESIDENT_SQL as Ye}from"../canvas/canvas.js";import{WAKE_MAIL_SQL as Ge}from"../canvas/deliveries.js";import{readNodeRecap as Xe}from"../canvas/node-recap.js";import{enqueueNodeMail as ze}from"../feed/messages.js";import{newestReportBody as Qe}from"../feed/reports.js";import{ensureAppProfile as te,loadExactProfileManifest as ne}from"../profiles/manifest.js";import{stopNodeSandboxes as se}from"../spaces/stop.js";import{BrokerUnreachableError as Ve}from"../runtime/broker-request.js";import{interruptLive as Ze}from"../runtime/interactive-deliver.js";import{isBrokerLive as ae}from"../runtime/model-swap.js";import{newNodeId as Ke}from"../runtime/nodes.js";import{reviveNode as j}from"../runtime/revive.js";import{spawnChildPrepared as et}from"../runtime/spawn.js";import{isPortableModelToken as tt}from"../runtime/launch.js";import{parseDurationMs as nt}from"../wake.js";import{expandModelCandidates as st,parseModelSpec as at}from"../model-routes.js";import{payerOfGrant as J}from"../grants/mirror.js";import{isolatedBrokerLauncherAvailable as it}from"../runtime/host.js";import{blaxelEnvironmentOf as rt}from"../runtime/blaxel-environment.js";import{resolveRunKind as ot,resolveRunModel as dt}from"../runtime/launch-target.js";import{cycleAwareMessages as ct}from"../runtime/session-cycles.js";import{originFor as ie}from"../runtime/stamp/protocol.js";import{readOutputRequest as ut,readOutputResult as re}from"../runtime/output-result.js";import{admitLegacyStructuredOutput as oe}from"../../daemon/structured-requests/sidecar.js";import{runSchemaRepromptPending as mt}from"../runtime/stop-guard.js";import{toRunOutcomeDTO as lt}from"../../daemon/api/map.js";import{openAssistantMessageStartSequence as ft}from"../../daemon/runs/observer.js";import{closeNode as de}from"../runtime/close.js";import{parseScope as pt}from"@north-light/identity";import{appendRunEvent as ce,lockRunRoot as _t,subscribeRunEvents as wt}from"./events.js";import{runActivity as gt}from"./activity.js";import{cancelOpenQuestions as ue,openNoticeIds as Et,openQuestionIds as me}from"./questions.js";import{appSpace as Y}from"../layout.js";import{ensureAppSpace as yt}from"../spaces/space.js";import{assertUploadsUsable as le,resolveStorageUrls as ht}from"../storage/attachments.js";import{storageClient as Rt,storageConfig as St}from"../storage/client.js";import{deleteUploadRow as Nt,insertUploadUses as fe,releaseRunUploads as vt,runUsesPath as bt}from"../storage/tables.js";import{abortProviderCalls as pe}from"../providers/inflight.js";import{filterAsync as _e,mapAsync as x}from"../async-array.js";const we=c((e,t,s,n)=>ht(t,e,s,n?{taken:n}:{}),"defaultResolver"),Ot=3e3;class R extends Error{static{c(this,"RunError")}status;code;param;details;scope;retryable;constructor(t,s,n,d,f,r,i=t===503){super(n),this.status=t,this.code=s,this.param=d,this.details=f,this.scope=r,this.retryable=i}}const N=c((e,t)=>new R(400,"invalid_request",e,t),"invalid"),G=c(()=>new R(404,"not_found","run not found"),"missing"),X=c(()=>({input_tokens:0,output_tokens:0,cache_read_tokens:0,cache_write_tokens:0,cost_usd:0}),"usage"),A=c(async()=>await B(),"db");async function q(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 G();return n}c(q,"ownedRun");const ge=["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 A()).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
6
|
)) LIMIT 1`).get(e.node_id,e.node_id),s=!e.last_settled_at&&e.status!=="done";return t||s||await mt(e)?"running":(await me(e.node_id)).length?"waiting_on_user":await(await A()).prepare(`SELECT 1 FROM deliveries d JOIN nodes n ON n.node_id = d.destination_id
|
|
7
7
|
WHERE n.run_id = ? AND ${Ge("d","'armed', 'pending', 'handed_off'")}
|
|
8
|
-
AND (n.status IN ('active', 'idle') OR ${Ye("n")}) LIMIT 1`).get(e.node_id)?"running":"idle"}c(C,"runStatus");async function Wn(e){const t=await O(e);return t!==null&&await C(t)==="running"}c(Wn,"runIsRunning");async function W(e){await Z(e.node_id),e=await O(e.node_id)??e;const t=await C(e),s=t==="settled"?[]:await me(e.node_id),n=await Qe(e.node_id)||void 0,
|
|
8
|
+
AND (n.status IN ('active', 'idle') OR ${Ye("n")}) LIMIT 1`).get(e.node_id)?"running":"idle"}c(C,"runStatus");async function Wn(e){const t=await O(e);return t!==null&&await C(t)==="running"}c(Wn,"runIsRunning");async function W(e){await Z(e.node_id),e=await O(e.node_id)??e;const t=await C(e),s=t==="settled"?[]:await me(e.node_id),n=await Qe(e.node_id)||void 0,d=t==="settled"?await lt(e):null,f=d?.kind==="result"?await re(e.node_id):void 0,r=Xe(e.node_id);return{run_id:e.node_id,name:e.name,status:t,...d?{outcome:d}:{},...f===void 0?{}:{result:f},...n!==void 0?{last_report:n}:{},...r?{recap:r}:{},pending_question_ids:s,open_notice_ids:t==="settled"?[]:await Et(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(X())),payer:await J(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 gt(e.node_id,t)}}c(W,"runObject");const z=864e5,Ee=255;function Fn(e){if(e!==void 0){if(typeof e!="string"||!e.length||e.length>Ee)throw N(`Idempotency-Key must be 1-${Ee} characters`);return e}}c(Fn,"idempotencyKeyOf");function Dt(e){if(Le()){if(!e)throw new R(403,"permission_error","a cloud role serves this call only for a token that names a person");return e}}c(Dt,"cloudPersonScope");function k(e,t){const s=Dt(e);return s===void 0?t:`${s}:${t}`}c(k,"personKey");async function H(e,t,s,n){n&&await n.prepare("SELECT pg_advisory_xact_lock(hashtext(?))").get(`idempotency:${e}:${t}`),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)>=z)){if(d.body_hash!==s)throw new R(409,"idempotency_conflict","key used with a different request");return{run_id:d.run_id,response:JSON.parse(d.response_json)}}}c(H,"findIdempotent");async function ye(e,t,s,n,d,f,r){await e.prepare("DELETE FROM idempotency_keys WHERE grantee = ? AND key = ? AND created_at <= ?").run(t,s,new Date(Date.now()-z).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(f),r)}c(ye,"recordIdempotent");async function qn(e=Date.now()){return Number((await(await B()).prepare("DELETE FROM idempotency_keys WHERE created_at <= ?").run(new Date(e-z).toISOString())).changes)}c(qn,"pruneExpiredIdempotencyKeys");async function he(e,t,s,n,d,f=!1){const r=n.text;let i=0;return{messageId:(await ze(t,{kind:"message",label:r.slice(0,120),senderNodeId:"human",senderName:s,bodyJson:d?{body:r,...f?{steer:!0}:{}}:{body:r,start_turn:!1},urgency:d?"normal":"deferred",wake:d?1:0,withinEnqueue:c(async(m,h)=>{n.uses.length&&(await le(s,n.uses,m),await fe(n.uses.map(({upload_id:g,path:E,blob_key:o})=>({upload_id:g,path:E,blob_key:o,run_id:t})),m)),i=(await ce(m,t,t,"node.message.accepted",{message_id:h,start_turn:d})).sequence_number},"withinEnqueue")})).messageId,sequence:i}}c(he,"acceptRunMessage");class Re extends Error{static{c(this,"IdempotentReplay")}winner;constructor(t){super("idempotent replay"),this.winner=t}}const Mt=1440*60*1e3;function Se(e){const t=typeof e=="string"?nt(e):null;if(t===null||!Number.isSafeInteger(t))throw N(`deadline '${String(e)}' is not a duration; use one or more <int>[smhd] parts such as 10m or 1h30m`,"deadline");if(t<=0)throw N("deadline must be greater than zero","deadline");if(t>Mt)throw N("deadline must be at most 24h","deadline");return t}c(Se,"parseRunDeadlineMs");async function Hn(e,t,s,n=we){if(t.isolated&&!it()&&await rt((t.profile===void 0?await te(e.grantee):ne(t.profile)).profileId)===null)throw new R(503,"isolated_unavailable","isolated runs require the Linux root launcher","isolated");t.deadline!==void 0&&Se(t.deadline);const{causedBy:d,...f}=t,r=Q("sha256").update(JSON.stringify(f)).digest("hex");if(s){const a=await H(e.grantee,k(e.sub,s),r);if(a){const l=await q(a.run_id,e.grantee);return!l.pi_pid&&await C(l)==="running"&&(t.output_schema!==void 0&&!l.outcome_at&&await ut(l.node_id)===null&&await re(l.node_id)===void 0&&await oe(l.node_id,"terminal",t.output_schema),await j(l.node_id,{resume:!0,capacity:"freeze"})),a.response}}await yt(e.grantee);const i=t.profile===void 0?await te(e.grantee):ne(t.profile),u=i.manifest.grantee??"app:terminal";if(u!==e.grantee){const a=`crtr:memory:rw:${u}:profile:${i.profileId}`;if(!e.resolved.some(l=>P(l,a))||t.scopes!==null&&!t.scopes.some(l=>P(l,a)))throw new R(403,"scope_missing",`missing scope ${a}`,"profile",void 0,a)}if(t.model!==void 0){const a=t.model;if(tt(a)){if(a.includes("/")&&await J(e.grant)!=="app"){const l=a.lastIndexOf("/"),D=a.slice(0,l),v=a.slice(l+1);if(["ultra","strong","medium","light"].includes(v)&&(await st({kind:"logical",family:D,strength:v,spec:a},Y(e.grantee).files,i.profileId)).every(S=>S.family!==D))throw N(`model '${a}' names a model family that is not configured in this daemon`,"model")}}else if(at(a)===void 0)throw N(`model '${a}' is not a strength (ultra, strong, medium, light), a family/strength, or a provider/model id`,"model")}const m=await Ke(),h=We(Y(e.grantee).nodes,m);if(t.isolated&&t.cwd!==void 0){const a=Ce(h,ke(t.cwd));if(!V(t.cwd)||a===".."||a.startsWith(`..${xe}`)||V(a))throw N("cwd must be inside the isolated root node folder","cwd")}const g=await n(m,e.grantee,t.prompt),E=g.text,o=t.message===void 0?void 0:await n(m,e.grantee,t.message,g.uses.map(a=>a.path)),p=await J(e.grant);let y;try{const a=dt(i,t.model);await et({kind:ot(i),mode:"base",root:!0,rootLifecycle:"resident",readiness:"launch",cwd:t.isolated?t.cwd??h:Y(e.grantee).files,profile:i.profileId,prompt:E,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()+Se(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(X())},withinCreate:c(async(l,D)=>{if(s){const S=await H(e.grantee,k(e.sub,s),r,l);if(S)throw new Re(S)}const v=g.uses;if(v.length&&(await le(e.grantee,v,l),await fe(v.map(({upload_id:S,path:I,blob_key:U})=>({upload_id:S,path:I,blob_key:U,run_id:m})),l)),y={run_id:m,node_id:m,grantee:e.grantee,grant:e.grant,rev:e.rev,scopes:t.scopes,payer:p,status:"running",created_at:D.created,metadata:t.metadata,sequence_number:0},await ce(l,m,m,"run.started",{scopes:t.scopes,payer:p,usage:X()}),o){const S=await he(l,m,e.grantee,o,!1);y.message={run_id:m,message_id:S.messageId,sequence_number:S.sequence}}s&&await ye(l,e.grantee,k(e.sub,s),r,m,y,D.created)},"withinCreate")},t.output_schema===void 0?void 0:async l=>{await oe(l,"terminal",t.output_schema)})}catch(a){if(a instanceof Re)return a.winner.response;if(t.model!==void 0&&a instanceof Te&&a.code==="usage")throw N(a.message,"model");if(a instanceof Ie&&(a.code==="isolated_run"||a.code==="invalid_request")){const l=a.details&&typeof a.details=="object"&&"param"in a.details&&typeof a.details.param=="string"?a.details.param:void 0;throw new R(a.status,a.code,a.message,l)}throw a}if(!y)throw new Error("run creation did not commit");return y}c(Hn,"startRun");async function Un(e,t){let s;if(t.after)try{const i=JSON.parse(Buffer.from(t.after,"base64url").toString());if(!i||typeof i!="object"||!("activity"in i)||typeof i.activity!="string"||!("id"in i)||typeof i.id!="string")throw new Error("invalid cursor");s={activity:i.activity,id:i.id}}catch{throw N("invalid list cursor","after")}const n=await(await A()).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 = ?"}${t.sub===void 0?"":" AND sub = ?"}
|
|
10
|
-
ORDER BY activity DESC, node_id DESC`).all(...e===null?[]:[e],...t.sub===void 0?[]:[t.sub]),
|
|
10
|
+
ORDER BY activity DESC, node_id DESC`).all(...e===null?[]:[e],...t.sub===void 0?[]:[t.sub]),d=await _e(await x((await _e(n,async({node_id:i})=>!t.visible||await t.visible(i))).filter(({activity:i,node_id:u})=>!s||i<s.activity||i===s.activity&&u<s.id),async i=>({root:await O(i.node_id),activity:i.activity})),async({root:i})=>!t.status||await C(i)===t.status),f=d.slice(0,t.limit),r=f.at(-1);return{runs:await x(f,async({root:i})=>await W(i)),next:d.length>t.limit&&r?Buffer.from(JSON.stringify({activity:r.activity,id:r.root.node_id})).toString("base64url"):null}}c(Un,"listRuns");async function $n(e,t,s){const n=await q(e,t),d=c(async()=>await W(await q(e,t)),"read");return!s||ge.includes(await C(n))?await d():new Promise((f,r)=>{let i=c(()=>{},"unsubscribe");const u=c(()=>{clearTimeout(o),clearInterval(E),i()},"settle"),m=c(async()=>{u();try{f(await d())}catch(p){r(p)}},"finish"),h=c(async()=>{ge.includes(String((await d()).status))&&await m()},"check"),g=c(()=>{h().catch(p=>{u(),r(p)})},"run"),E=setInterval(g,250),o=setTimeout(()=>{m()},s*1e3);wt(e,g).then(p=>{i=p},p=>{u(),r(p)})})}c($n,"waitRun");const At=5;async function Pn(e,t,s=we,n=!0,d,f=!0){const r=e.status==="canceled"||e.outcome_reason==="closed",i=e.grantee??"app:terminal",u=Q("sha256").update(JSON.stringify(["run.message",e.node_id,t,n,...n&&!f?["steer:false"]:[]])).digest("hex"),m=c(async g=>{const E=await O(e.node_id),o=await(await A()).prepare("SELECT 1 FROM deliveries WHERE message_id = ? AND state = 'pending' AND canceled_at IS NULL").get(String(g.message_id));return E&&!r&&n&&!E.pi_pid&&o&&await j(e.node_id,{resume:!0,capacity:"freeze"}),g},"replay");if(d){const g=await H(i,k(e.sub,d),u);if(g)return m(g.response)}if(r)throw new R(409,"run_settled","canceled run cannot receive a message");const h=n&&e.final_report&&!e.pi_pid?(await import("../runtime/reopen.js")).commitReopenResident:void 0;for(let g=1;;g++){const E=await s(e.node_id,i,t),o=await F(async p=>{if(d){const l=await H(i,k(e.sub,d),u,p);if(l)return{replayed:l.response}}if(E.uses.length){await _t(p,e.node_id);for(const l of E.uses)if(await bt(e.node_id,l.path,p))return"path_taken"}await h?.(e.node_id);const y=await he(p,e.node_id,i,E,n,n&&f),a={run_id:e.node_id,message_id:y.messageId,sequence_number:y.sequence};return d&&await ye(p,i,k(e.sub,d),u,e.node_id,a,new Date().toISOString()),{result:a}});if(o==="path_taken"){if(g>=At)throw new R(503,"service_unavailable","attachments of concurrent messages kept taking each other's file names; retry");continue}return"replayed"in o?m(o.replayed):(n&&!e.pi_pid&&await j(e.node_id,{resume:!0,capacity:"freeze"}),o.result)}}c(Pn,"messageRun");async function It(e){const t=c(()=>new R(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 G();if(!ae(n)){if(n.streaming)throw t();return}const d=(await K(e))?.executionId;try{await Ze(e)==="turn"&&pe({nodes:[e]});return}catch(f){if(!(f instanceof Ve))throw f;const r=await O(e);if(!r)throw G();if(!r.streaming)return;if(s===0&&ae(r)&&(await K(e))?.executionId!==d)continue;throw t()}}throw t()}c(It,"interruptNode");async function Bn(e,t="stop"){const s=t==="stop"?(await(await A()).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=>It(n))),await W(await O(e.node_id)??e)}c(Bn,"interruptRun");async function jn(e,t={}){const s=(await(await A()).prepare("SELECT node_id FROM nodes WHERE run_id = ? ORDER BY created DESC").all(e.node_id)).map(r=>r.node_id);pe({run:e.node_id});const n=[];if(await C(e)!=="settled")n.push(...(await de(e.node_id,{preserveEmpty:!0,stopReason:"run_canceled"})).closed);else for(const r of s){if(r===e.node_id)continue;const i=await O(r);i&&i.status!=="done"&&i.status!=="canceled"&&i.status!=="dead"&&n.push(...(await de(r,{preserveEmpty:!0,stopReason:"run_canceled"})).closed)}if(await ue({run_id:e.node_id},"the run was canceled"),(await Promise.all([...new Set([e.node_id,...n])].map(r=>se(r,"run_canceled")))).some(r=>!r.confirmed))throw new R(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const f=await O(e.node_id);return await W(f??e)}c(jn,"cancelRun");const Ne=200;async function Jn(e,t){if(typeof t!="string"||!t.trim())throw N("name is required","name");const s=t.trim();if(s.length>Ne)throw N(`name exceeds ${Ne} characters`,"name");const n=await Pe(e.node_id,{name:s});return n.window&&je(n.window,Be(n)),await W(n)}c(Jn,"renameRun");async function Yn(e,t={config:St,client:Rt}){await ue({run_id:e.node_id},"the run was deleted");const s=await F(async u=>(await u.prepare("UPDATE nodes SET deleting_at = COALESCE(deleting_at, ?) WHERE node_id = ?").run(new Date().toISOString(),e.node_id),(await u.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(u=>se(u,"run_deleted",{deleting:!0})))).some(u=>!u.confirmed))throw new R(500,"server_error","run process teardown could not be confirmed",void 0,void 0,void 0,!0);const d=await x(s,async u=>{const m=await Ue(u);if(m.app===null)throw new Error(`run node missing during deletion: ${u}`);return m}),f=await(await A()).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:u}of f)try{await ee().delete(u)}catch(m){if(!Je(m))throw m}const r=await F(async u=>{for(const E of s){const o=await He(u,E);o!==null&&o.deleted_at===null&&await qe(u,o)}const m=await vt([e.node_id],u);await u.prepare("DELETE FROM run_events WHERE run_id = ?").run(e.node_id),await u.prepare("DELETE FROM idempotency_keys WHERE run_id = ?").run(e.node_id);const h=s.map(()=>"?").join(","),g=await u.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 u.prepareUncached(`DELETE FROM deliveries WHERE destination_id IN (${h})`).run(...s);for(const{message_id:E}of g)await u.prepare("DELETE FROM messages WHERE message_id = ? AND NOT EXISTS (SELECT 1 FROM deliveries WHERE message_id = ?)").run(E,E);return m});for(const u of d)await $e(u);const{notifyRunDeleted:i}=await import("./events.js");return i(e.node_id),{uploads_pending:await Tt(r,t)}}c(Yn,"deleteRun");async function Tt(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(r=>s.deleteUpload(r).then(async()=>{await Nt(r),n.add(r)},()=>{}));let f;return await Promise.race([Promise.all(d),new Promise(r=>{f=setTimeout(r,t.budgetMs??Ot),f.unref?.()})]),clearTimeout(f),e.length-n.size}c(Tt,"deleteReleasedUploads");async function Gn(e,t,s){await q(e,t),await Z(e);const n=await F(async o=>{const p=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 S of p)y.set(S.node_id,(await o.prepare("SELECT session_id FROM sessions WHERE node_id = ? GROUP BY session_id ORDER BY min(created_at)").all(S.node_id)).map(I=>I.session_id));const l=(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,l),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,l);return{nodes:p,sessionIds:y,latestSequence:l,completed:D,deltas:v}}),{nodes:d,sessionIds:f,latestSequence:r,completed:i,deltas:u}=n,m=await x(d,async o=>({node_id:o.node_id,parent_node_id:o.parent,conversations:await x(f.get(o.node_id)??[],async p=>{const{header:y,entries:a}=await ee().read(p);if(s==="entries")return{conversation_id:p,header:y,entries:a};const l=Fe.inMemory(y.cwd,void 0,[y,...a]),D=ct(l)??[],v=new Map(a.map((w,b)=>[w.id,b])),S=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}})),I=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}})),U=o.node_id===e?a.find(w=>{if(w.type!=="message"||w.message.role!=="user")return!1;const b=ie(a,w.message.timestamp);return b?.type==="runtime"&&b.kind==="kickoff"})?.id:void 0,ve=[...D.filter(({id:w})=>!I.some(b=>b.id===w)),...S,...I].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 _=b,T=_.usage,$=_.role==="user"?ie(a,Number(_.timestamp)):null,be=$?.type==="human"||w===U,L=_.role==="toolResult"?"tool_result":_.role==="bashExecution"?"bash_execution":_.role==="compactionSummary"?"compaction_summary":_.role==="branchSummary"?"branch_summary":_.role==="custom"&&_.customType==="crtr-system-prompt"?"system":_.role==="user"?be?"user":"custom":_.role,Oe=L==="custom"?_.role==="custom"?_.customType:$?.type==="runtime"?$.kind:"unknown":void 0,De=L==="system"&&_.customType==="crtr-system-prompt"?[{type:"text",text:_.data?.text??""}]:typeof _.content=="string"?[{type:"text",text:_.content}]:Array.isArray(_.content)?_.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:Oe}:{},time:typeof _.timestamp=="string"?_.timestamp:new Date(Number(_.timestamp??Date.now())).toISOString(),content:De,...L==="assistant"?{model:_.model,provider:_.provider,stop_reason:_.stopReason,..._.errorMessage?{error_message:_.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:_.toolCallId,tool_name:_.toolName,is_error:_.isError}:{}}})??[];return{conversation_id:p,messages:ve}})})),h=new Map(await Promise.all(m.map(async o=>[o.node_id,await ft(o.node_id)])));for(const o of i){const p=h.get(o.node_id);p!=null&&o.sequence_number>=p&&h.set(o.node_id,null)}const g=new Map;for(const o of u){const p=h.get(o.node_id);if(p==null||o.sequence_number<p)continue;const y=JSON.parse(o.body_json),a=g.get(o.node_id)??{thinking:"",text:""};o.type==="node.thinking.delta"?a.thinking+=y.delta:a.text+=y.delta,g.set(o.node_id,a)}const E=m.map(o=>({...o,in_progress_message:h.get(o.node_id)==null?null:g.get(o.node_id)??{thinking:"",text:""}}));return{run_id:e,latest_sequence:r,nodes:E}}c(Gn,"traceRun");function Xn(e,t,s){if(t===void 0){if(!e.some(n=>P(n,"crtr:llm")))throw new R(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 N("scopes must be a list of scope strings","scopes");for(const n of t){try{pt(n)}catch{throw N(`invalid scope ${n}`,"scopes")}if(/^crtr:files:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))throw N(`own-app files cannot narrow a run: ${n}`,"scopes");if(!(/^crtr:memory:(?:read|rw):app:/.test(n)&&n.split(":")[4]===s.slice(4))&&!Ae(e,n))throw new R(403,"scope_missing",`missing scope ${n}`,void 0,void 0,n)}if(!t.includes("crtr:llm"))throw new R(403,"scope_missing","missing scope crtr:llm",void 0,void 0,"crtr:llm");return t}c(Xn,"requestedScopes");export{z as IDEMPOTENCY_WINDOW_MS,Mt as RUN_DEADLINE_MAX_MS,Ot as RUN_DELETE_STORAGE_BUDGET_MS,Ne as RUN_NAME_MAX,R as RunError,jn as cancelRun,Dt as cloudPersonScope,Yn as deleteRun,Fn as idempotencyKeyOf,Bn as interruptRun,Un as listRuns,Pn as messageRun,q as ownedRun,Se as parseRunDeadlineMs,qn as pruneExpiredIdempotencyKeys,Jn as renameRun,Xn as requestedScopes,Wn as runIsRunning,W as runObject,Hn as startRun,Gn as traceRun,$n as waitRun};
|
|
@@ -1,6 +1,10 @@
|
|
|
1
|
+
import type { RunSteerBridge } from './run-steer.js';
|
|
1
2
|
export declare const HELD_DEFERRED_INBOX_PROMPT_JOIN: unique symbol;
|
|
2
3
|
export declare const BROKER_IDLE_TURN_START: unique symbol;
|
|
3
4
|
export declare const BROKER_RUN_TURN_BUSY: unique symbol;
|
|
5
|
+
export declare const BROKER_RUN_STEER: unique symbol;
|
|
6
|
+
export type BrokerRunSteer = Pick<RunSteerBridge, 'steerable' | 'accept' | 'takeUnconsumed'>;
|
|
7
|
+
export declare function brokerRunSteer(): BrokerRunSteer | undefined;
|
|
4
8
|
export declare const BROKER_DISPOSE_AND_EXIT: unique symbol;
|
|
5
9
|
/** The broker's one exit path, for an extension whose failure must end the process (a conversation store that stays down). */
|
|
6
10
|
export declare function brokerDisposeAndExit(): ((reason: string, status?: number) => void) | undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var n=Object.defineProperty;var r=(o,t)=>n(o,"name",{value:t,configurable:!0});const e=Symbol.for("@crouton-kit/crtr:held-deferred-inbox-prompt-join"),i=Symbol.for("@crouton-kit/crtr:broker-idle-turn-start"),u=Symbol.for("@crouton-kit/crtr:broker-run-turn-busy"),c=Symbol.for("@crouton-kit/crtr:broker-dispose-and-exit");function
|
|
1
|
+
var n=Object.defineProperty;var r=(o,t)=>n(o,"name",{value:t,configurable:!0});const e=Symbol.for("@crouton-kit/crtr:held-deferred-inbox-prompt-join"),i=Symbol.for("@crouton-kit/crtr:broker-idle-turn-start"),u=Symbol.for("@crouton-kit/crtr:broker-run-turn-busy"),c=Symbol.for("@crouton-kit/crtr:broker-run-steer");function b(){return globalThis[c]}r(b,"brokerRunSteer");const f=Symbol.for("@crouton-kit/crtr:broker-dispose-and-exit");function l(){const o=globalThis[f];return typeof o=="function"?o:void 0}r(l,"brokerDisposeAndExit");function p(){const o=globalThis[u];return typeof o=="function"&&o()}r(p,"brokerRunTurnBusy");function R(){const o=globalThis[e];return typeof o=="function"?o:void 0}r(R,"heldDeferredInboxPromptJoin");function d(){const o=globalThis[i];return typeof o=="function"?o:void 0}r(d,"brokerIdleTurnStart");export{f as BROKER_DISPOSE_AND_EXIT,i as BROKER_IDLE_TURN_START,c as BROKER_RUN_STEER,u as BROKER_RUN_TURN_BUSY,e as HELD_DEFERRED_INBOX_PROMPT_JOIN,l as brokerDisposeAndExit,d as brokerIdleTurnStart,b as brokerRunSteer,p as brokerRunTurnBusy,R as heldDeferredInboxPromptJoin};
|
|
@@ -7,6 +7,7 @@ import type { BrokerSession } from './read-ops.js';
|
|
|
7
7
|
import type { ToolGroupTracker } from './tool-groups.js';
|
|
8
8
|
import type { TurnReplyTracker } from './turn-replies.js';
|
|
9
9
|
import type { OperationId } from '../../events/types.js';
|
|
10
|
+
import type { RunSteerBridge } from './run-steer.js';
|
|
10
11
|
export interface SubscriptionGeneration {
|
|
11
12
|
id: number;
|
|
12
13
|
session: BrokerSession;
|
|
@@ -34,6 +35,8 @@ type RebindDriverDeps = {
|
|
|
34
35
|
registry: BrokerClientRegistry;
|
|
35
36
|
toolGroups: ToolGroupTracker;
|
|
36
37
|
turnReplies: TurnReplyTracker;
|
|
38
|
+
runSteer: RunSteerBridge;
|
|
39
|
+
runNode: boolean;
|
|
37
40
|
/** The bound session's full visible message list (cycle-aware), used to seed
|
|
38
41
|
* the open consolidated-reply turn. */
|
|
39
42
|
transcriptMessages: (session: BrokerSession) => readonly unknown[];
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var k=Object.defineProperty;var l=(
|
|
1
|
+
var k=Object.defineProperty;var l=(a,e)=>k(a,"name",{value:e,configurable:!0});import{mkdirSync as v,writeFileSync as I}from"node:fs";import{join as A}from"node:path";import{nodeRunJobDir as _}from"../../canvas/paths.js";import{emitEvent as u}from"../../events/emit.js";import{operationIdContext as c}from"../../events/operation-id.js";import{installPersonaTransitionGate as w}from"../broker-persona-guidance.js";import{installRetryCardElision as E}from"./retry-card-elision.js";import{abortSessionFromExtension as T}from"./extension-abort.js";import{brokerRecovery as S,mutateBrokerFault as x,mutateBrokerProviderRetry as F,postBrokerIdle as P,settleBroker as V}from"./daemon-ops.js";import{brokerSignalClient as C}from"./signal-stream.js";const f=2,m=3e4,b=Symbol("replacement-deadline-exceeded"),N="(interrupted)",g=Symbol.for("crtr.trailing-thinking-guard");function M(a){for(let e=a.length-1;e>=0;e--){const t=a[e];if(t!==void 0){if(t.type==="text"){if(t.text.trim().length===0)continue;return t}if(t.type==="thinking"){const i=t.thinkingSignature,o=typeof i=="string"&&i.trim().length>0;if(t.redacted!==!0&&t.thinking.trim().length===0&&!o)continue;return t}return t}}}l(M,"lastSerializedBlock");function y(a){return a.map(e=>e.role!=="assistant"||e.stopReason==="error"||e.stopReason==="aborted"||M(e.content)?.type!=="thinking"?e:{...e,content:[...e.content,{type:"text",text:N}]})}l(y,"guardTrailingThinking");function q(a){const e=a.convertToLlm;if(e[g]===!0)return;const t=l(i=>{const o=e(i);return o instanceof Promise?o.then(y):y(o)},"wrapped");t[g]=!0,a.convertToLlm=t}l(q,"installTrailingThinkingGuard");class X{static{l(this,"RebindDriver")}deps;sessionValue;servicesValue;unsubscribe;installed;nextSubscriptionGeneration=0;rebindTail=Promise.resolve();latestRebindRequest=0;replacementTail=Promise.resolve();admittedReplacements=0;rebindsInFlight=0;rebinding;agentRunActiveValue=!1;shutdownRequested=!1;constructor(e){this.deps=e,this.sessionValue=e.session,this.servicesValue=e.services}session(){return this.sessionValue}services(){return this.servicesValue}installedGeneration(){return this.installed}isAgentRunActive(){return this.agentRunActiveValue}isReplacing(){return this.admittedReplacements>0}pendingRebind(){return this.rebinding?.done}requestShutdown(){if(!this.agentRunActiveValue){this.deps.disposeAndExit("shutdown-hook");return}this.shutdownRequested=!0}setRebindSession(){this.deps.runtime?.setRebindSession(e=>this.enqueueRebind(e,this.deps.runtime.services))}enqueueRebind(e,t){const i=++this.latestRebindRequest;if(this.rebindsInFlight++===0){let r;this.rebinding={done:new Promise(d=>{r=d}),resolve:r}}const o=this.rebindTail.then(async()=>{if(i!==this.latestRebindRequest)return;if(this.installed!==void 0){typeof this.sessionValue.sessionFile=="string"&&this.sessionValue.sessionFile!==""&&await F(this.deps.nodeId,{op:"invalidate",session_id:this.sessionValue.sessionManager.getSessionId()});const s=(await S(this.deps.nodeId)).fault;s?.link==="pi\u2192provider"&&s.retry.disposition==="auto"&&s.retry.by==="daemon"&&await x(this.deps.nodeId,{op:"clear",link:"pi\u2192provider",preserve_episode:!0})}this.installed?.executingTools.clear(),this.removeInstalledSubscription(),this.deps.setActiveSession(e),this.deps.projection().reset(),this.deps.faultRetry().reset(),this.agentRunActiveValue=!1,this.deps.onSessionRebind(),this.deps.toolGroups.resetForSession(),this.sessionValue=e,this.servicesValue=t;const r=e.agent;r&&(w(this.deps.nodeId,{agent:r,sessionManager:e.sessionManager}),E(r),r.steeringMode="all",this.deps.runNode&&this.deps.runSteer.bind(r,e),r.followUpMode="all",q(r));const d={id:++this.nextSubscriptionGeneration,session:e,fallback:{blocked:!1},stagedProviderAgentEnd:null,stagedWatchdogAbort:!1,stagedRefreshAbort:!1,stagedOverflowFailure:null,executingTools:new Set};if(this.unsubscribe=this.sessionValue.subscribe(s=>{if(!this.deps.projection().isCurrent(d))return;if(c.current()!==void 0){this.executeSubscriptionCallback(d,s);return}const n=d.fallback;if(s.type==="turn_start"&&n.storedId!==void 0){n.storedId=void 0,n.blocked=!0,c.fresh(()=>{u({level:"warn",event:"broker.turn.fallback_overlap",fields:{generation:d.id,engine_event:s.type}}),this.executeSubscriptionCallback(d,s)});return}if(s.type==="turn_start"&&!n.blocked){c.fresh(R=>{n.storedId=R,this.executeSubscriptionCallback(d,s)});return}const h=n.storedId;if(h!==void 0&&!n.blocked){c.run(h,()=>{this.executeSubscriptionCallback(d,s),s.type==="agent_settled"&&n.storedId===h&&(n.storedId=void 0)});return}this.executeSubscriptionCallback(d,s)}),this.installed=d,await e.bindExtensions({uiContext:this.deps.uiContext(),mode:"rpc",abortHandler:l(()=>T(e,()=>{const s=this.installed;s?.session===e&&(s.stagedRefreshAbort=!0)}),"abortHandler"),shutdownHandler:l(()=>this.requestShutdown(),"shutdownHandler")}),i===this.latestRebindRequest){if(this.deps.cfg.editorName!==void 0&&this.deps.cfg.editorName!=="")try{e.setSessionName(this.deps.cfg.editorName)}catch{}try{this.deps.turnReplies.seed(this.deps.transcriptMessages(e))}catch(s){u({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply seed failed: ${String(s)}`}})}this.deps.projection().rearmIfStreaming(d),this.captureSystemPrompt(e)}}).finally(()=>{--this.rebindsInFlight>0||(this.rebinding?.resolve(),this.rebinding=void 0)});return this.rebindTail=o.catch(()=>{}),o}runReplacement(e,t,i){const o=this.deps.runtime;if(o===void 0){this.deps.registry.sendFrame(e,{type:"error",code:"engine_error",message:"session replacement unsupported at this engine pin"});return}if(this.admittedReplacements>=f){c.fresh(()=>u({level:"warn",event:"broker.session_replacement.rejected",outcome:"skipped",fields:{op:t,reason:"capacity",admitted:f,cap:f}})),this.ackTo(e,t,!1,`session replacement busy (${f} active or queued)`);return}this.admittedReplacements++;const r=this.replacementTail.then(async()=>{try{await c.fresh(async()=>{const d=process.hrtime.bigint();let s;try{const p=new Promise(h=>{s=setTimeout(()=>h(b),m)}),n=await Promise.race([i(o),p]);if(n===b){u({level:"error",event:"broker.session_replacement.timed_out",outcome:"failed",duration_ms:Number(process.hrtime.bigint()-d)/1e6,fields:{op:t,deadline_ms:m,mutation_outcome:"indeterminate"}}),this.ackTo(e,t,!1,"session replacement timed out; broker restarting because session state is indeterminate"),this.deps.disposeAndExit("session-replacement-timeout",1);return}n.cancelled||this.deps.reWelcomeAll(),this.ackTo(e,t,!n.cancelled,n.cancelled?n.detail??"cancelled by extension":void 0)}catch(p){u({level:"error",event:"broker.session_replacement.failed",outcome:"failed",error:p,fields:{op:t,mutation_outcome:"indeterminate"}}),this.ackTo(e,t,!1,"session replacement failed; broker restarting because session state is indeterminate"),this.deps.disposeAndExit("session-replacement-failed",1)}finally{clearTimeout(s)}})}finally{this.admittedReplacements--,this.admittedReplacements===0&&this.deps.onReplacementIdle?.()}});this.replacementTail=r.catch(()=>{})}removeInstalledSubscription(){this.unsubscribe?.(),this.unsubscribe=void 0,this.installed=void 0}captureSystemPrompt(e){try{const t=_(this.deps.nodeId);v(t,{recursive:!0}),I(A(t,"system-prompt.md"),e.systemPrompt,"utf8")}catch{}}executeSubscriptionCallback(e,t){try{t.type==="agent_start"&&(this.agentRunActiveValue=!0),t.type==="agent_end"&&(e.stagedProviderAgentEnd=t,e.stagedOverflowFailure=null),t.type==="compaction_end"&&t.reason==="overflow"&&t.willRetry===!1&&typeof t.errorMessage=="string"&&(e.stagedOverflowFailure={errorMessage:t.errorMessage}),t.type==="agent_settled"&&(this.agentRunActiveValue=!1,this.publishAndScheduleProviderRecovery(e)),this.deps.toolGroups.observeToolGroupEvent(t),this.deps.turnReplies.observe(t),this.deps.projection().relayEvent(t,e)}catch(i){u({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`event relay threw: ${String(i)}`}})}}async publishAndScheduleProviderRecovery(e){try{if(await this.deps.faultRetry().publishSettledProviderFault(e),this.shutdownRequested){this.deps.disposeAndExit("shutdown-after-settle");return}const t=this.deps.faultRetry();await t.schedule()!=="armed"&&!t.fallbackInFlight()&&await t.faultIsFatal()&&await this.idleAfterFatalFault(e)}catch(t){this.deps.faultRetry().abandonTurnEnd(),u({level:"error",event:"broker.daemon.operation.failed",node_id:this.deps.nodeId,error:t,fields:{operation:"provider_fault_settlement"}}),this.shutdownRequested&&this.deps.disposeAndExit("shutdown-after-settle")}}async idleAfterFatalFault(e){const t=l(()=>this.installed===e&&!this.agentRunActiveValue&&!e.session.isStreaming,"stillSettled");!t()||(await V(this.deps.nodeId,{stopReason:"error",pushedFinal:!1,faultSettled:!0})).action!=="stay_resident"||!t()||(await P(this.deps.nodeId),C().stop())}ackTo(e,t,i=!0,o,r){this.deps.registry.sendFrame(e,{type:"ack",for:t,ok:i,...o!==void 0?{detail:o}:{},...r!==void 0?{id:r}:{}})}}export{X as RebindDriver};
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { Agent } from '@earendil-works/pi-agent-core';
|
|
2
|
+
import type { BrokerSession } from './read-ops.js';
|
|
3
|
+
export type RunSteerItem = {
|
|
4
|
+
text: string;
|
|
5
|
+
messageIds: string[];
|
|
6
|
+
cards: readonly string[];
|
|
7
|
+
};
|
|
8
|
+
export type RunSteerBridge = {
|
|
9
|
+
steerable(): boolean;
|
|
10
|
+
accept(items: readonly RunSteerItem[]): 'accepted' | 'not_steerable';
|
|
11
|
+
takeUnconsumed(): RunSteerItem[];
|
|
12
|
+
bind(agent: Agent, session: BrokerSession): void;
|
|
13
|
+
};
|
|
14
|
+
/** This list is separate from pi's viewer-controlled queue until pi's next step. */
|
|
15
|
+
export declare function createRunSteerBridge(steerable: () => boolean): RunSteerBridge;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
var f=Object.defineProperty;var m=(n,t)=>f(n,"name",{value:t,configurable:!0});import{announceMessageOrigin as y}from"../stamp/channel.js";import{SITUATIONAL_CONTEXT_CUSTOM_TYPE as b}from"../../../shared/generated-context.js";function x(n){const t=[];let u;return{steerable:n,accept(a){return n()?(t.push(...a),"accepted"):"not_steerable"},takeUnconsumed(){return t.splice(0)},bind(a,c){const s=a.steeringQueue;if(typeof s?.drain!="function")throw new Error("pi agent has no step-boundary steering drain");u?.();const o=new WeakMap;u=c.subscribe(e=>{if(e.type!=="message_end"||e.message.role!=="user")return;const r=o.get(e.message);r!==void 0&&(o.delete(e.message),c.sessionManager.appendCustomEntry("crtr-turn-input",{message_ids:r.messageIds}),y(r.text,{type:"human"}))});const d=s.drain.bind(s);s.drain=()=>{const e=d(),g=t.splice(0).map(i=>{const p={role:"user",content:[{type:"text",text:i.text}],timestamp:Date.now()};return o.set(p,i),[...i.cards.map(l=>({role:"custom",customType:b,content:l,display:!0,timestamp:Date.now()})),p]});return[...e,...g.flat()]}}}}m(x,"createRunSteerBridge");export{x as createRunSteerBridge};
|
|
@@ -23,6 +23,8 @@ export type RunTurnQueue = {
|
|
|
23
23
|
drain(): void;
|
|
24
24
|
/** Whether a run node must not start an inbox turn now. */
|
|
25
25
|
busy(): boolean;
|
|
26
|
+
/** A live run with no earlier turn queued can accept a step-boundary steer. */
|
|
27
|
+
steerable(): boolean;
|
|
26
28
|
/** The launch prompt will be dispatched; hold inbox turns behind it. */
|
|
27
29
|
holdForKickoff(): void;
|
|
28
30
|
/** The launch prompt ran (or will not run); release held inbox turns. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var A=Object.defineProperty;var e=(n,i)=>A(n,"name",{value:i,configurable:!0});function S(n){const{runNode:i,session:a,turnAdmission:m}=n,s=[];let u=!1,c=!1,r=!1;const p=e(()=>n.isReplacing()||n.isAgentRunActive()||a().isStreaming,"engineBusy"),d=e(()=>r||u||p(),"mustQueue"),g=e(()=>{if(d())return;const t=s.shift();t&&l(t.text,t.messageIds)},"drain"),l=e((t,f=[])=>{const h=n.pendingRebind();if(h!==void 0){h.then(()=>l(t,f));return}if(i&&d()){s.push({text:t,messageIds:f});return}i&&(u=!0),m.admit(async v=>{const o=a();if(i&&o.isStreaming)return s.unshift({text:t,messageIds:f}),v(),Promise.resolve();const R=i?await n.prependDeferred(o):[];return i&&f.length+R.length>0&&o.sessionManager.appendCustomEntry("crtr-turn-input",{message_ids:[...R,...f]}),o.prompt(t,{preflightResult:e(()=>{c=!0,v()},"preflightResult"),...!i&&o.isStreaming?{streamingBehavior:"steer"}:{}})}).catch(n.onError).finally(()=>{i&&(u=!1,c=!1,g())})},"start");return{start:l,drain:g,busy:e(()=>n.pendingRebind()!==void 0||r||u||n.pendingDispatches()>0||n.isAgentRunActive()||a().isStreaming,"busy"),steerable:e(()=>i&&!r&&n.pendingRebind()===void 0&&!n.isReplacing()&&n.pendingDispatches()===0&&n.isAgentRunActive()&&(!u||c)&&s.length===0,"steerable"),holdForKickoff:e(()=>{i&&(r=!0)},"holdForKickoff"),releaseKickoff:e(()=>{r&&(r=!1,g())},"releaseKickoff"),queued:e(()=>s,"queued")}}e(S,"createRunTurnQueue");export{S as createRunTurnQueue};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var Ne=Object.defineProperty;var t=(n,o)=>Ne(n,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Fe,envModelIntent as Le,envNodeCwd as Be,envNodeId as Ue,envProfileId as $e,envScopes as We,scopeAllowed as Ke}from"../../shared/env.js";import{createServer as Ge}from"node:net";import{WebSocketServer as je,createWebSocketStream as qe}from"ws";import{BROKER_VIEW_PORT as Ve}from"./view-socket.js";import{existsSync as Re,readFileSync as Xe,unlinkSync as Te}from"node:fs";import{join as Ee}from"node:path";import{randomUUID as M}from"node:crypto";import{mark as He}from"../timing.js";import{SUBMIT_RESULT_TOOL as Ye}from"./structured-output.js";import{flushConversation as ke,installSessionManagerStorePatch as ze}from"../conversation-store/index.js";import{getAgentDir as J,ModelRegistry as Je,ModelRuntime as Qe}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Ze,viewSocketPath as en}from"../canvas/paths.js";import{bindBrokerEventSource as nn}from"../events/source.js";import{emitEvent as b,flushBrokerLog as tn}from"../events/emit.js";import{operationIdContext as rn}from"../events/operation-id.js";import{findMissingPackagePaths as on}from"./package-health.js";import{installBrokerConfigSnapshot as sn}from"../config.js";import{FRONT_DOOR_ENV as an}from"./front-door.js";import{CANVAS_EXTENSIONS as oe,piInvocationToSdkConfig as dn}from"./launch.js";import{assertEngineVersion as ln,loadBrokerEngine as cn}from"./broker-sdk.js";import{initCrtrTheme as mn}from"./crtr-theme.js";import{resolveBundledPiPackageDir as un}from"./pi-cli.js";import{captureSessionChatCapabilities as fn}from"./command-surface.js";import{InMemoryCredentialStore as pn}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as gn}from"./broker/model-adapter.js";import{brokerApiUrl as vn,mutateBrokerFault as Q,recordBrokerTurn as Ce}from"./broker/daemon-ops.js";import{fetchRunAttachments as _n}from"./broker/attachments-fetch.js";import{modelRequestFromConfig as hn,expandModelCandidates as wn,parseModelSpec as Sn,unregisteredConcreteModel as bn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as yn}from"./stream-watchdog.js";import{probeOnline as Rn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as Tn,cycleAwareMessages as En,endedByAbort as kn}from"./session-cycles.js";import{turnErrorOf as Cn}from"../llm/refusal.js";import{projectTranscript as xn}from"./session-visibility.js";import{currentTurnVisibility as Mn}from"./turn-visibility.js";import{isUnknownModel as ie}from"./model-selection.js";import{BrokerClientRegistry as An}from"./broker/client-registry.js";import{ToolGroupTracker as Pn}from"./broker/tool-groups.js";import{TurnReplyTracker as On}from"./broker/turn-replies.js";import{onNodeNamed as Dn}from"./broker/node-named.js";import{FaultRetry as In,willDaemonRetry as Nn}from"./broker/fault-retry.js";import{RunTurnEnds as Fn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as Ln}from"./broker/turn-admission.js";import{BROKER_DISPOSE_AND_EXIT as Bn,BROKER_IDLE_TURN_START as Un,BROKER_RUN_TURN_BUSY as $n}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as Wn,settleRunDeferredMail as Kn}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Gn}from"./broker/run-turn-queue.js";import{EventProjection as jn}from"./broker/event-projection.js";import{createFrameDispatchContext as qn,handleFrame as Vn}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as Xn,installAdvertisedCommandInvocationContract as Hn}from"./advertised-command-invocation.js";import{RebindDriver as Yn}from"./broker/rebind.js";import{beginRuntimeTeardown as zn}from"./broker/extension-abort.js";import{receiveNodeToken as Jn}from"./broker/node-token.js";import{serveCliRelay as Qn}from"./broker/cli-relay.js";import{recordBrokerRelease as Zn}from"./lifecycle.js";import{setTurnCauseSource as et}from"./broker/turn-cause.js";import{decodeKickoffOrigin as nt,KICKOFF_ORIGIN_ENV as tt}from"./stamp/protocol.js";import{announceMessageOrigin as rt}from"./stamp/channel.js";import{commitBrokerModel as ot,recordConversationWriteFault as xe}from"./broker/daemon-ops.js";import{bootExtensionState as it}from"./broker/boot-state.js";import{composerNames as st}from"./broker/frame-memory-refs.js";import{BROKER_READ_CAPS as at,FrameOverflowError as dt,normalizeSnapshotTail as lt}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as Ar,REVIEW_BOUNDARY_NAVIGATION_CODE as Pr}from"./broker/frame-replies.js";function se(n){return new Je(n.modelRuntime)}t(se,"registryOf");function $(n,o){if(n==null||ie(n))return null;const s=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${n.provider}/${n.id}${s}`}t($,"formatModelSpec");function ct(n,o){const s=$(n,void 0);return s===null?null:`${s}:${o===void 0||o===""?"off":o}`}t(ct,"formatExactModelSpec");const mt=12e4;let Z=null;import{brokerSignalClient as W}from"./broker/signal-stream.js";function ut(){W().stop();const n=Z;if(Z=null,n!==null)try{n.dispose()}catch{}}t(ut,"disposeActiveSession");function ft(n,o){const s=Ke(o,"crtr:act")?void 0:["bash"],f=n!==void 0&&n.length>0?[...new Set([...n,Ye])]:n===void 0?void 0:[...n];return{...f!==void 0?{tools:f}:{},...s!==void 0?{excludeTools:s}:{}}}t(ft,"brokerToolOptions");async function Cr(n,o=process.hrtime.bigint(),s=new Date().toISOString()){nn(n);const f=await Jn(),i=await Qn(n,f);process.env.CRTR_API_SOCKET=i.path,rn.fresh(()=>{b({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),b({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let c=null;const d=t((e,r=null)=>{a.has(e)||(a.add(e),He(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),b({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:c,model:r}}))},"emitStartupMilestone");process.env[an]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,ze(n);const v=await cn();ln(v.VERSION),c=v.VERSION;const w=Ze(n),E=Ee(w,"broker-launch.json"),S=JSON.parse(Xe(E,"utf8"));if(!S.configSnapshot)throw new Error("broker launch is missing its config snapshot");sn(S.configSnapshot);const g=dn(S);g.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await st(n);let R,A;const X=t(e=>{R!==void 0?R(e):A??=e},"onSignal");process.on("SIGTERM",()=>X("SIGTERM")),process.on("SIGINT",()=>X("SIGINT")),process.on("SIGUSR1",()=>{const e=process.env.CRTR_EXECUTION_ID;e!==void 0&&e!==""&&W().start(n,e)});let{session:K,services:P,resuming:de,runtime:G}=await _t(v,g);d("broker.startup.session_built");const k=(await it(n)).node.review_binding?.review_id,T=Fe();Z=K;const F=Rn;try{process.env.PI_PACKAGE_DIR=un(),mn(P.settingsManager.getTheme(),J(),!1)}catch(e){b({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of on(J()))b({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const j=en(n),_=new An(n),H=new Map,D=new Pn(n,e=>_.broadcast(e)),q=new On(n,e=>_.broadcast(e));Dn(e=>_.broadcast({type:"node_named",...e}));let I=!1,le=!1,Y,z,ce,m,V;const ee=new Fn;let L,me=t(()=>{},"notifyTurnAccepted"),ue=t(()=>{},"resetFrameState");const ne=Ln();let fe=t(()=>0,"pendingPromptDispatches"),pe;const B=Gn({runNode:T,session:t(()=>m.session(),"session"),isReplacing:t(()=>m.isReplacing(),"isReplacing"),pendingRebind:t(()=>m.pendingRebind(),"pendingRebind"),isAgentRunActive:t(()=>m.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:t(()=>fe(),"pendingDispatches"),turnAdmission:ne,prependDeferred:t(e=>Wn(n,e),"prependDeferred"),onError:t(e=>b({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")});et(()=>m.session());const ge=B.drain;g.firstPrompt!==void 0&&g.firstPrompt!==""&&B.holdForKickoff(),globalThis[Un]=B.start,globalThis[$n]=B.busy,m=new Yn({nodeId:n,cfg:g,session:K,services:P,runtime:G,registry:_,toolGroups:D,turnReplies:q,transcriptMessages:t(e=>ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:t(()=>ce,"uiContext"),faultRetry:t(()=>V,"faultRetry"),projection:t(()=>L,"projection"),setActiveSession:t(e=>{if(Z=e,pe?.(),T||process.env.CRTR_RUN_ID){let r="stop",l,p=!1;pe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",l=void 0,p=!1,ee.started()),h.type==="agent_end"){const u=[...h.messages??[]].reverse().find(U=>U.role==="assistant");u&&(r=u.stopReason,l=kn(u)?void 0:Cn(u),p=u.role==="assistant"&&Nn(u,e.model?.contextWindow))}h.type==="agent_settled"&&(ee.settled(e.sessionManager,{stop_reason:r,...l?{error:l}:{}},p),T&&(ke().then(()=>Kn(n,e)).catch(async u=>{if(String(u?.message).startsWith("conversation_write_failed")){b({level:"error",event:"broker.exited",node_id:n,error:u,fields:{fault:"conversation_write_failed"}}),await xe(n,u),C("conversation_write_failed",1);return}b({level:"error",event:"broker.run_deferred_mail.settle_failed",error:u})}),queueMicrotask(()=>{m.session()===e&&ge()})))})}},"setActiveSession"),disposeAndExit:t((e,r)=>C(e,r),"disposeAndExit"),onSessionRebind:t(()=>{ue()},"onSessionRebind"),onReplacementIdle:t(()=>{T&&ge()},"onReplacementIdle"),reWelcomeAll:t(()=>te(),"reWelcomeAll")});const ve=t(async(e,r=!1)=>{const l=m.session(),p=$(l.model,l.thinkingLevel);if(p===null)return null;const h=await ot(n,{spec:p,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(g.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,g.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",g.modelExact=!0)),h.modelOverride},"persistModelChoice"),_e=t(async(e=!0,r,l=!1)=>{const p=m.session(),h=$(p.model,p.thinkingLevel),u=e?await ve(r,l):h;_.broadcast({type:"model_changed",model:ie(p.model)?void 0:p.model,spec:u})},"broadcastModelChanged");V=new In({nodeId:n,cfg:g,retryProbe:F,currentSession:t(()=>m.session(),"currentSession"),currentServices:t(()=>m.services(),"currentServices"),installedGeneration:t(()=>m.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:$,broadcastModelChanged:_e,turnAdmission:ne,reWelcomeAll:t(()=>te(),"reWelcomeAll"),...T?{turnEnds:ee}:{}});const he=t(()=>{V.rearmIfStranded().catch(e=>{b({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");W().subscribe("resync",he),W().subscribe("fault-retry",he),L=new jn({registry:_,faultRetry:V,installedGeneration:t(()=>m.installedGeneration(),"installedGeneration"),currentSession:t(()=>m.session(),"currentSession"),notifyTurnAccepted:t(()=>me(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:$});const Ae=t(e=>{const r=m.session(),l=ae(r,k),p=lt(e.snapshotTail),h=l===void 0||p===void 0?l:l.slice(-p),u=h?.map(({message:N})=>N)??r.sessionManager.buildSessionContext().messages,U=D.summaries(),ye=h!==void 0&&p!==void 0?pt(u):void 0,Ie=ye===void 0?U:Object.fromEntries(Object.entries(U).filter(([N])=>ye.has(N)));return{messages:u,...h===void 0?{}:{messageIds:h.map(({id:N})=>N)},messageVisibility:h?.map(({visibility:N})=>N)??u.map(()=>"visible"),turnVisibility:Mn(),stats:r.getSessionStats(),state:{model:ie(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{..._.displaySnapshot()},toolGroupSummaries:Ie,turnReplies:q.snapshot(),workingActivity:L.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),we=t(e=>{const r=e.role==="controller"?H.values().next().value:void 0;_.sendFrame(e,{type:"welcome",snapshot:Ae(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:J()},!0)},"sendWelcome"),Pe=t(e=>{const r=[...H.values()];for(let l=1;l<r.length;l++)_.sendFrame(e,r[l].request)},"replayExtraPendingDialogsTo"),te=t(()=>{try{const e=m.session();q.seed(ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){b({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}_.forEachHelloed(we)},"reWelcomeAll"),Se=t(async e=>{if(I)return;I=!0;const r=W().latestNode;r!==void 0&&(r.intent==="idle-release"||r.status==="done")&&Zn(n,process.env.CRTR_EXECUTION_ID??null),W().stop(),e===0&&await ke().catch(async l=>{e=1,b({level:"error",event:"broker.exited",node_id:n,error:l,fields:{fault:"conversation_write_failed"}}),await xe(n,l)}),D.persistPendingSummary(),L.dispose(),ut();try{Y?.close(),z?.close()}catch{}i.close(),_.dispose();try{Re(j)&&Te(j)}catch{}_.clearAttachState(),await tn(),process.exit(e)},"completeExit"),C=t((e,r=0)=>{if(I)return;const l=e==="shutdown-hook"||e==="shutdown-after-settle";if(l&&D.finishOpenToolGroup(!0),l&&(D.hasSummaryTasks()||q.hasTasks())){if(le)return;le=!0,Promise.allSettled([D.waitForSummaryTasks(),q.waitForTasks()]).finally(()=>Se(r));return}Se(r)},"disposeAndExit");globalThis[Bn]=C,ce=ht({writable:t(()=>_.writableClients(),"writable"),forward:t((e,r)=>_.sendFrame(e,r),"forward"),pending:H,broadcast:t(e=>_.broadcastUi(e),"broadcast"),onKnownStreamWait:t(e=>L.knownStreamWait(e),"onKnownStreamWait")}),m.setRebindSession(),await m.enqueueRebind(K,P),d("broker.startup.extensions_bound");const x=qn({nodeId:n,registry:_,toolGroups:D,projection:L,rebind:m,boundaryReviewId:k,pendingDialogs:H,sendWelcome:we,replayExtraPendingDialogsTo:Pe,reWelcomeAll:te,disposeAndExit:C,persistModelChoice:ve,broadcastModelChanged:_e,registryOf:se,formatModelSpec:$,formatExactModelSpec:ct,turnAdmission:ne,memoryInventory:y,runNode:T,onKickoffAdmitted:B.releaseKickoff});me=x.notifyTurnAccepted,ue=x.resetForSession,fe=x.pendingPromptDispatches;const Oe=2500;let re=!1;const De=t(async e=>{if(I||re)return;if(re=!0,m.isAgentRunActive()||m.session().isStreaming||x.pendingPromptDispatches()>0){const l=Date.now()+Oe;for(;x.pendingPromptDispatches()>0&&!m.session().isStreaming&&Date.now()<l;)await new Promise(p=>setTimeout(p,25));if(m.session().isStreaming){const p=l-Date.now();if(p>0){let h;try{zn(),await Promise.race([m.session().abort().then(()=>!0,()=>!1),new Promise(U=>{h=setTimeout(()=>U(!1),p)})])&&await Ce(n,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(x.pendingPromptDispatches()>0||m.isAgentRunActive())&&await Ce(n,{event:"interrupted"})}C(e)},"abortAndExit");if(R=t(e=>{De(e)},"signalTeardown"),A!==void 0){R(A);return}try{Re(j)&&Te(j)}catch{}const be=t(e=>{const r=_.create(e);e.on("data",p=>{let h;try{h=r.decoder.push(p)}catch(u){u instanceof dt?(_.sendFrame(r,{type:"error",code:"frame_overflow",message:u.message}),_.dropClient(r,`frame overflow: ${u.message}`)):_.dropClient(r,`decoder error: ${String(u)}`);return}for(const u of h)try{Vn(x,r,u)}catch{}});const l=t(()=>{_.removeClient(r)},"drop");e.on("close",l),e.on("error",()=>{})},"serveViewer");Y=Ge(be),vn()!==void 0&&(z=new je({host:"::",port:Ve,path:"/view",maxPayload:at.maxLineBytes}),z.on("connection",e=>be(qe(e))),z.on("error",e=>{I||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))})),Y.on("error",e=>{I||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))}),Y.listen(j,async()=>{Promise.all([Q(n,{op:"clear",link:"viewer\u2194broker"}),Q(n,{op:"clear",link:"relay\u2194broker"})]).catch(r=>b({level:"error",event:"broker.daemon.operation.failed",node_id:n,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await V.recoverOnStartup()}catch(r){b({level:"error",event:"broker.daemon.operation.failed",node_id:n,error:r,fields:{operation:"recovery_startup"}}),C("recovery-startup-failed",1);return}if(!(I||re))if(e==="none"&&g.firstPrompt!==void 0&&g.firstPrompt!==""){const r=nt(process.env[tt]);r!==null&&rt(g.firstPrompt,r);try{await _n(n)}catch(p){b({level:"error",event:"broker.daemon.operation.failed",node_id:n,error:p,fields:{operation:"attachments_fetch"}}),C("attachments-fetch-failed",1);return}const l=process.env.CRTR_KICKOFF_MESSAGE_IDS;x.kickoff(g.firstPrompt,l?JSON.parse(l):[])}else B.releaseKickoff()}),_.persistAttachState()}t(Cr,"runBroker");function pt(n){const o=new Set;for(const s of n)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const f of s.content)f!==null&&typeof f=="object"&&f.type==="toolCall"&&typeof f.id=="string"&&o.add(f.id);return o}t(pt,"toolCallIds");function ae(n,o){const s=n.sessionManager,f=En(s);return f!==void 0&&Xn(f.map(({message:i})=>i)),f===void 0?void 0:xn(f,{boundaryReviewId:o,sessionEntries:s.getEntries?.()})}t(ae,"snapshotMessages");function Me(){const n=Ue();if(n===void 0||n==="")throw new Error("broker launch is missing CRTR_NODE_ID");return n}t(Me,"currentBrokerNodeId");async function gt(n,o){const s=hn(o.model,Le(),o.modelExact===!0);if(s===void 0)return;const f=se(n),i={cwd:Be()??o.cwd,profileId:$e()},a=await bn(s,f,i);if(a!==void 0)throw await Q(Me(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const c=await wn(s,i.cwd,i.profileId),d=Sn(s.spec);for(const v of c){const w=f.find(v.providerId,v.modelId);if(w===void 0)continue;const S=d?.providerId===v.providerId&&d.modelId===v.modelId?d.thinkingLevel??(v.thinkingLevel===void 0?void 0:"off"):v.thinkingLevel;return{model:w,thinkingLevel:S}}if(o.modelExact===!0){const v=c.map(w=>`'${w.providerId}/${w.modelId}' unregistered`).join("; ");throw await Q(Me(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${o.model}' is unavailable \u2014 refusing to substitute (${v})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}b({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:c.map(v=>({provider:v.providerId,model:v.modelId,reason:"unregistered"})).slice(0,16)}})}t(gt,"resolveLaunchModel");function vt(n){let o=!0;return{runtime:new Proxy(n,{get(f,i,a){return o&&i==="getAvailableSnapshot"?()=>[]:o&&i==="getAvailable"?async()=>[]:o&&i==="getModel"?()=>{}:Reflect.get(f,i,a)}}),reveal:t(()=>{o=!1},"reveal")}}t(vt,"modelLessRegistry");async function _t(n,o){const s=J(),f=t(async S=>{const g=await Qe.create({credentials:new pn,modelsPath:Ee(S.agentDir,"models.json")});gn(g);const y=await n.createAgentSessionServices({cwd:S.cwd,agentDir:S.agentDir,modelRuntime:g,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:t(O=>({...O,extensions:O.extensions.filter(k=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(k.path))}),"extensionsOverride")}}),R=y.resourceLoader.getExtensions();if(o.extensionPaths.some(O=>oe.includes(O))){const O=new Set(R.extensions.map(T=>T.path)),k=oe.filter(T=>!O.has(T));if(k.length>0){const T=R.errors.filter(F=>oe.includes(F.path)).map(F=>`${F.path}: ${F.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${k.join(", ")}${T===""?"":` (${T})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const A=await gt(y,o),X=A?.model,K=A?.thinkingLevel,P=A===void 0?vt(y.modelRuntime):void 0,de=P!==void 0?{...y,modelRuntime:P.runtime}:y,G=await n.createAgentSessionFromServices({services:de,sessionManager:S.sessionManager,model:X,thinkingLevel:K,...ft(o.tools,We()),sessionStartEvent:S.sessionStartEvent});return Hn(G.session),fn(G.session),P?.reveal(),{...G,services:y}},"buildForManager"),i=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(i===void 0||i==="")&&o.resumeSessionId!==void 0&&o.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${o.resumeSessionId}' (pi_session_file was never captured for this node)`);const c=!a&&i!==void 0&&i!=="",d=c&&o.newCycle===!0,v=c&&!d;let w;if(a)w=await n.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(v||d){if(w=await n.SessionManager.open(i),d){const S=w.getLeafId();w.resetLeaf(),w.appendCustomEntry(Tn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:S})}}else w=await n.SessionManager.create(o.cwd);if(n.createAgentSessionRuntime!==void 0){const S=t(async y=>{const R=await f({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...R,diagnostics:R.services.diagnostics??[]}},"factory"),g=await n.createAgentSessionRuntime(S,{cwd:o.cwd,agentDir:s,sessionManager:w});return{session:g.session,services:g.services,resuming:v,runtime:g}}const E=await f({cwd:o.cwd,agentDir:s,sessionManager:w});return{session:E.session,services:E.services,resuming:v,runtime:void 0}}t(_t,"buildBrokerSession");function ht(n){const o=t((i,a,c,d)=>{if(d?.signal?.aborted)return Promise.resolve(i);const v=n.writable();return v.length===0?Promise.resolve(i):new Promise(w=>{let E;const S=t(()=>{E!==void 0&&clearTimeout(E),d?.signal?.removeEventListener("abort",g),n.pending.delete(a.id)},"cleanup"),g=t(()=>{S(),n.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},"onAbort");d?.signal?.addEventListener("abort",g,{once:!0});const y=d?.timeout!==void 0?d.timeout:mt;E=setTimeout(()=>{S(),n.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},y),typeof E.unref=="function"&&E.unref(),n.pending.set(a.id,{request:a,resolve:t(R=>{S(),n.broadcast({type:"extension_ui_dismiss",id:a.id}),w(c(R))},"resolve")});for(const R of v)n.forward(R,a)})},"dialogPromise"),s=t(()=>{},"noop");return{[yn]:n.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:t((i,a,c)=>o(void 0,{type:"extension_ui_request",id:M(),method:"select",title:i,options:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"select"),confirm:t((i,a,c)=>o(!1,{type:"extension_ui_request",id:M(),method:"confirm",title:i,message:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,c),"confirm"),input:t((i,a,c)=>o(void 0,{type:"extension_ui_request",id:M(),method:"input",title:i,placeholder:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"input"),editor:t((i,a)=>o(void 0,{type:"extension_ui_request",id:M(),method:"editor",title:i,prefill:a},c=>"cancelled"in c&&c.cancelled?void 0:"value"in c?c.value:void 0),"editor"),setStatus:t((i,a)=>n.broadcast({type:"extension_ui_request",id:M(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:t((i,a,c)=>{typeof a!="function"&&n.broadcast({type:"extension_ui_request",id:M(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:c?.placement})},"setWidget"),setTitle:t(i=>n.broadcast({type:"extension_ui_request",id:M(),method:"setTitle",title:i}),"setTitle"),notify:t((i,a)=>{const c=a==="warn"?"warning":a;n.broadcast({type:"extension_ui_request",id:M(),method:"notify",message:i,notifyType:c})},"notify"),onTerminalInput:t(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:t(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:t(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:t(()=>{},"getEditorComponent"),getAllThemes:t(()=>[],"getAllThemes"),getTheme:t(()=>{},"getTheme"),setTheme:s,getToolsExpanded:t(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}t(ht,"makeBrokerUiContext");export{Pr as REVIEW_BOUNDARY_NAVIGATION_CODE,Ar as ReviewBoundaryNavigationError,ft as brokerToolOptions,_t as buildBrokerSession,ut as disposeActiveSession,ht as makeBrokerUiContext,Cr as runBroker,ae as snapshotMessages};
|
|
1
|
+
var Fe=Object.defineProperty;var n=(t,o)=>Fe(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Le,envModelIntent as Be,envNodeCwd as Ue,envNodeId as $e,envProfileId as Ke,envScopes as We,scopeAllowed as Ge}from"../../shared/env.js";import{createServer as je}from"node:net";import{WebSocketServer as qe,createWebSocketStream as Ve}from"ws";import{BROKER_VIEW_PORT as Xe}from"./view-socket.js";import{existsSync as Te,readFileSync as He,unlinkSync as Ee}from"node:fs";import{join as ke}from"node:path";import{randomUUID as A}from"node:crypto";import{mark as Ye}from"../timing.js";import{SUBMIT_RESULT_TOOL as ze}from"./structured-output.js";import{flushConversation as Ce,installSessionManagerStorePatch as Je}from"../conversation-store/index.js";import{getAgentDir as J,ModelRegistry as Qe,ModelRuntime as Ze}from"@earendil-works/pi-coding-agent";import{nodeRunDir as et,viewSocketPath as tt}from"../canvas/paths.js";import{bindBrokerEventSource as nt}from"../events/source.js";import{emitEvent as b,flushBrokerLog as rt}from"../events/emit.js";import{operationIdContext as ot}from"../events/operation-id.js";import{findMissingPackagePaths as it}from"./package-health.js";import{installBrokerConfigSnapshot as st}from"../config.js";import{FRONT_DOOR_ENV as at}from"./front-door.js";import{CANVAS_EXTENSIONS as oe,piInvocationToSdkConfig as dt}from"./launch.js";import{assertEngineVersion as lt,loadBrokerEngine as ct}from"./broker-sdk.js";import{initCrtrTheme as mt}from"./crtr-theme.js";import{resolveBundledPiPackageDir as ut}from"./pi-cli.js";import{captureSessionChatCapabilities as ft}from"./command-surface.js";import{InMemoryCredentialStore as pt}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as gt,refusalRetryAt as vt}from"./broker/model-adapter.js";import{brokerApiUrl as _t,mutateBrokerFault as Q,recordBrokerTurn as xe}from"./broker/daemon-ops.js";import{fetchRunAttachments as ht}from"./broker/attachments-fetch.js";import{modelRequestFromConfig as wt,expandModelCandidates as St,parseModelSpec as bt,unregisteredConcreteModel as yt}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as Rt}from"./stream-watchdog.js";import{probeOnline as Tt}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as Et,cycleAwareMessages as kt,endedByAbort as Ct}from"./session-cycles.js";import{turnErrorOf as xt}from"../llm/refusal.js";import{projectTranscript as At}from"./session-visibility.js";import{currentTurnVisibility as Mt}from"./turn-visibility.js";import{isUnknownModel as ie}from"./model-selection.js";import{BrokerClientRegistry as Pt}from"./broker/client-registry.js";import{ToolGroupTracker as Ot}from"./broker/tool-groups.js";import{TurnReplyTracker as Dt}from"./broker/turn-replies.js";import{onNodeNamed as It}from"./broker/node-named.js";import{FaultRetry as Nt,willDaemonRetry as Ft}from"./broker/fault-retry.js";import{RunTurnEnds as Lt}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as Bt}from"./broker/turn-admission.js";import{BROKER_DISPOSE_AND_EXIT as Ut,BROKER_IDLE_TURN_START as $t,BROKER_RUN_TURN_BUSY as Kt,BROKER_RUN_STEER as Wt}from"./broker/held-deferred-inbox.js";import{createRunSteerBridge as Gt}from"./broker/run-steer.js";import{prependRunDeferredMail as jt,settleRunDeferredMail as qt}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Vt}from"./broker/run-turn-queue.js";import{EventProjection as Xt}from"./broker/event-projection.js";import{createFrameDispatchContext as Ht,handleFrame as Yt}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as zt,installAdvertisedCommandInvocationContract as Jt}from"./advertised-command-invocation.js";import{RebindDriver as Qt}from"./broker/rebind.js";import{beginRuntimeTeardown as Zt}from"./broker/extension-abort.js";import{receiveNodeToken as en}from"./broker/node-token.js";import{serveCliRelay as tn}from"./broker/cli-relay.js";import{recordBrokerRelease as nn}from"./lifecycle.js";import{setTurnCauseSource as rn}from"./broker/turn-cause.js";import{decodeKickoffOrigin as on,KICKOFF_ORIGIN_ENV as sn}from"./stamp/protocol.js";import{announceMessageOrigin as an}from"./stamp/channel.js";import{commitBrokerModel as dn,recordConversationWriteFault as Ae}from"./broker/daemon-ops.js";import{bootExtensionState as ln}from"./broker/boot-state.js";import{composerNames as cn}from"./broker/frame-memory-refs.js";import{BROKER_READ_CAPS as mn,FrameOverflowError as un,normalizeSnapshotTail as fn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as Nr,REVIEW_BOUNDARY_NAVIGATION_CODE as Fr}from"./broker/frame-replies.js";function se(t){return new Qe(t.modelRuntime)}n(se,"registryOf");function $(t,o){if(t==null||ie(t))return null;const s=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${s}`}n($,"formatModelSpec");function pn(t,o){const s=$(t,void 0);return s===null?null:`${s}:${o===void 0||o===""?"off":o}`}n(pn,"formatExactModelSpec");const gn=12e4;let Z=null;import{brokerSignalClient as K}from"./broker/signal-stream.js";function vn(){K().stop();const t=Z;if(Z=null,t!==null)try{t.dispose()}catch{}}n(vn,"disposeActiveSession");function _n(t,o){const s=Ge(o,"crtr:act")?void 0:["bash"],f=t!==void 0&&t.length>0?[...new Set([...t,ze])]:t===void 0?void 0:[...t];return{...f!==void 0?{tools:f}:{},...s!==void 0?{excludeTools:s}:{}}}n(_n,"brokerToolOptions");async function Or(t,o=process.hrtime.bigint(),s=new Date().toISOString()){nt(t);const f=await en(),i=await tn(t,f);process.env.CRTR_API_SOCKET=i.path,ot.fresh(()=>{b({level:"info",event:"broker.startup.cli_entry",ts:s,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),b({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let c=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Ye(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),b({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:c,model:r}}))},"emitStartupMilestone");process.env[at]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,Je(t);const v=await ct();lt(v.VERSION),c=v.VERSION;const w=et(t),E=ke(w,"broker-launch.json"),S=JSON.parse(He(E,"utf8"));if(!S.configSnapshot)throw new Error("broker launch is missing its config snapshot");st(S.configSnapshot);const g=dt(S);g.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await cn(t);let R,M;const X=n(e=>{R!==void 0?R(e):M??=e},"onSignal");process.on("SIGTERM",()=>X("SIGTERM")),process.on("SIGINT",()=>X("SIGINT")),process.on("SIGUSR1",()=>{const e=process.env.CRTR_EXECUTION_ID;e!==void 0&&e!==""&&K().start(t,e)});let{session:W,services:P,resuming:de,runtime:G}=await bn(v,g);d("broker.startup.session_built");const k=(await ln(t)).node.review_binding?.review_id,T=Le();Z=W;const L=Tt;try{process.env.PI_PACKAGE_DIR=ut(),mt(P.settingsManager.getTheme(),J(),!1)}catch(e){b({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of it(J()))b({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const j=tt(t),_=new Pt(t),H=new Map,D=new Ot(t,e=>_.broadcast(e)),q=new Dt(t,e=>_.broadcast(e));It(e=>_.broadcast({type:"node_named",...e}));let I=!1,le=!1,Y,z,ce,u,V;const ee=new Lt;let B,me=n(()=>{},"notifyTurnAccepted"),ue=n(()=>{},"resetFrameState");const te=Bt();let fe=n(()=>0,"pendingPromptDispatches"),pe;const N=Vt({runNode:T,session:n(()=>u.session(),"session"),isReplacing:n(()=>u.isReplacing(),"isReplacing"),pendingRebind:n(()=>u.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>u.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>fe(),"pendingDispatches"),turnAdmission:te,prependDeferred:n(e=>jt(t,e),"prependDeferred"),onError:n(e=>b({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")}),ge=Gt(N.steerable);globalThis[Wt]=ge,rn(()=>u.session());const ve=N.drain;g.firstPrompt!==void 0&&g.firstPrompt!==""&&N.holdForKickoff(),globalThis[$t]=N.start,globalThis[Kt]=N.busy,u=new Qt({nodeId:t,cfg:g,session:W,services:P,runtime:G,registry:_,toolGroups:D,turnReplies:q,runSteer:ge,runNode:T,transcriptMessages:n(e=>ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>ce,"uiContext"),faultRetry:n(()=>V,"faultRetry"),projection:n(()=>B,"projection"),setActiveSession:n(e=>{if(Z=e,pe?.(),T||process.env.CRTR_RUN_ID){let r="stop",l,p=!1;pe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",l=void 0,p=!1,ee.started()),h.type==="agent_end"){const m=[...h.messages??[]].reverse().find(U=>U.role==="assistant");m&&(r=m.stopReason,l=Ct(m)?void 0:xt(m,vt(m)),p=m.role==="assistant"&&Ft(m,e.model?.contextWindow))}h.type==="agent_settled"&&(ee.settled(e.sessionManager,{stop_reason:r,...l?{error:l}:{}},p),T&&(Ce().then(()=>qt(t,e)).catch(async m=>{if(String(m?.message).startsWith("conversation_write_failed")){b({level:"error",event:"broker.exited",node_id:t,error:m,fields:{fault:"conversation_write_failed"}}),await Ae(t,m),C("conversation_write_failed",1);return}b({level:"error",event:"broker.run_deferred_mail.settle_failed",error:m})}),queueMicrotask(()=>{u.session()===e&&ve()})))})}},"setActiveSession"),disposeAndExit:n((e,r)=>C(e,r),"disposeAndExit"),onSessionRebind:n(()=>{ue()},"onSessionRebind"),onReplacementIdle:n(()=>{T&&ve()},"onReplacementIdle"),reWelcomeAll:n(()=>ne(),"reWelcomeAll")});const _e=n(async(e,r=!1)=>{const l=u.session(),p=$(l.model,l.thinkingLevel);if(p===null)return null;const h=await dn(t,{spec:p,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(g.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,g.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",g.modelExact=!0)),h.modelOverride},"persistModelChoice"),he=n(async(e=!0,r,l=!1)=>{const p=u.session(),h=$(p.model,p.thinkingLevel),m=e?await _e(r,l):h;_.broadcast({type:"model_changed",model:ie(p.model)?void 0:p.model,spec:m})},"broadcastModelChanged");V=new Nt({nodeId:t,cfg:g,retryProbe:L,currentSession:n(()=>u.session(),"currentSession"),currentServices:n(()=>u.services(),"currentServices"),installedGeneration:n(()=>u.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:$,broadcastModelChanged:he,turnAdmission:te,reWelcomeAll:n(()=>ne(),"reWelcomeAll"),...T?{turnEnds:ee}:{}});const we=n(()=>{V.rearmIfStranded().catch(e=>{b({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");K().subscribe("resync",we),K().subscribe("fault-retry",we),B=new Xt({registry:_,faultRetry:V,installedGeneration:n(()=>u.installedGeneration(),"installedGeneration"),currentSession:n(()=>u.session(),"currentSession"),notifyTurnAccepted:n(()=>me(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:$});const Pe=n(e=>{const r=u.session(),l=ae(r,k),p=fn(e.snapshotTail),h=l===void 0||p===void 0?l:l.slice(-p),m=h?.map(({message:F})=>F)??r.sessionManager.buildSessionContext().messages,U=D.summaries(),Re=h!==void 0&&p!==void 0?hn(m):void 0,Ne=Re===void 0?U:Object.fromEntries(Object.entries(U).filter(([F])=>Re.has(F)));return{messages:m,...h===void 0?{}:{messageIds:h.map(({id:F})=>F)},messageVisibility:h?.map(({visibility:F})=>F)??m.map(()=>"visible"),turnVisibility:Mt(),stats:r.getSessionStats(),state:{model:ie(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{..._.displaySnapshot()},toolGroupSummaries:Ne,turnReplies:q.snapshot(),workingActivity:B.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),Se=n(e=>{const r=e.role==="controller"?H.values().next().value:void 0;_.sendFrame(e,{type:"welcome",snapshot:Pe(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:J()},!0)},"sendWelcome"),Oe=n(e=>{const r=[...H.values()];for(let l=1;l<r.length;l++)_.sendFrame(e,r[l].request)},"replayExtraPendingDialogsTo"),ne=n(()=>{try{const e=u.session();q.seed(ae(e,k)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){b({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}_.forEachHelloed(Se)},"reWelcomeAll"),be=n(async e=>{if(I)return;I=!0;const r=K().latestNode;r!==void 0&&(r.intent==="idle-release"||r.status==="done")&&nn(t,process.env.CRTR_EXECUTION_ID??null),K().stop(),e===0&&await Ce().catch(async l=>{e=1,b({level:"error",event:"broker.exited",node_id:t,error:l,fields:{fault:"conversation_write_failed"}}),await Ae(t,l)}),D.persistPendingSummary(),B.dispose(),vn();try{Y?.close(),z?.close()}catch{}i.close(),_.dispose();try{Te(j)&&Ee(j)}catch{}_.clearAttachState(),await rt(),process.exit(e)},"completeExit"),C=n((e,r=0)=>{if(I)return;const l=e==="shutdown-hook"||e==="shutdown-after-settle";if(l&&D.finishOpenToolGroup(!0),l&&(D.hasSummaryTasks()||q.hasTasks())){if(le)return;le=!0,Promise.allSettled([D.waitForSummaryTasks(),q.waitForTasks()]).finally(()=>be(r));return}be(r)},"disposeAndExit");globalThis[Ut]=C,ce=yn({writable:n(()=>_.writableClients(),"writable"),forward:n((e,r)=>_.sendFrame(e,r),"forward"),pending:H,broadcast:n(e=>_.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>B.knownStreamWait(e),"onKnownStreamWait")}),u.setRebindSession(),await u.enqueueRebind(W,P),d("broker.startup.extensions_bound");const x=Ht({nodeId:t,registry:_,toolGroups:D,projection:B,rebind:u,boundaryReviewId:k,pendingDialogs:H,sendWelcome:Se,replayExtraPendingDialogsTo:Oe,reWelcomeAll:ne,disposeAndExit:C,persistModelChoice:_e,broadcastModelChanged:he,registryOf:se,formatModelSpec:$,formatExactModelSpec:pn,turnAdmission:te,memoryInventory:y,runNode:T,onKickoffAdmitted:N.releaseKickoff});me=x.notifyTurnAccepted,ue=x.resetForSession,fe=x.pendingPromptDispatches;const De=2500;let re=!1;const Ie=n(async e=>{if(I||re)return;if(re=!0,u.isAgentRunActive()||u.session().isStreaming||x.pendingPromptDispatches()>0){const l=Date.now()+De;for(;x.pendingPromptDispatches()>0&&!u.session().isStreaming&&Date.now()<l;)await new Promise(p=>setTimeout(p,25));if(u.session().isStreaming){const p=l-Date.now();if(p>0){let h;try{Zt(),await Promise.race([u.session().abort().then(()=>!0,()=>!1),new Promise(U=>{h=setTimeout(()=>U(!1),p)})])&&await xe(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(x.pendingPromptDispatches()>0||u.isAgentRunActive())&&await xe(t,{event:"interrupted"})}C(e)},"abortAndExit");if(R=n(e=>{Ie(e)},"signalTeardown"),M!==void 0){R(M);return}try{Te(j)&&Ee(j)}catch{}const ye=n(e=>{const r=_.create(e);e.on("data",p=>{let h;try{h=r.decoder.push(p)}catch(m){m instanceof un?(_.sendFrame(r,{type:"error",code:"frame_overflow",message:m.message}),_.dropClient(r,`frame overflow: ${m.message}`)):_.dropClient(r,`decoder error: ${String(m)}`);return}for(const m of h)try{Yt(x,r,m)}catch{}});const l=n(()=>{_.removeClient(r)},"drop");e.on("close",l),e.on("error",()=>{})},"serveViewer");Y=je(ye),_t()!==void 0&&(z=new qe({host:"::",port:Xe,path:"/view",maxPayload:mn.maxLineBytes}),z.on("connection",e=>ye(Ve(e))),z.on("error",e=>{I||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))})),Y.on("error",e=>{I||(b({level:"error",event:"broker.socket.failed",error:e}),C("socket-error",1))}),Y.listen(j,async()=>{Promise.all([Q(t,{op:"clear",link:"viewer\u2194broker"}),Q(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await V.recoverOnStartup()}catch(r){b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),C("recovery-startup-failed",1);return}if(!(I||re))if(e==="none"&&g.firstPrompt!==void 0&&g.firstPrompt!==""){const r=on(process.env[sn]);r!==null&&an(g.firstPrompt,r);try{await ht(t)}catch(p){b({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:p,fields:{operation:"attachments_fetch"}}),C("attachments-fetch-failed",1);return}const l=process.env.CRTR_KICKOFF_MESSAGE_IDS;x.kickoff(g.firstPrompt,l?JSON.parse(l):[])}else N.releaseKickoff()}),_.persistAttachState()}n(Or,"runBroker");function hn(t){const o=new Set;for(const s of t)if(!(s.role!=="assistant"||!Array.isArray(s.content)))for(const f of s.content)f!==null&&typeof f=="object"&&f.type==="toolCall"&&typeof f.id=="string"&&o.add(f.id);return o}n(hn,"toolCallIds");function ae(t,o){const s=t.sessionManager,f=kt(s);return f!==void 0&&zt(f.map(({message:i})=>i)),f===void 0?void 0:At(f,{boundaryReviewId:o,sessionEntries:s.getEntries?.()})}n(ae,"snapshotMessages");function Me(){const t=$e();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(Me,"currentBrokerNodeId");async function wn(t,o){const s=wt(o.model,Be(),o.modelExact===!0);if(s===void 0)return;const f=se(t),i={cwd:Ue()??o.cwd,profileId:Ke()},a=await yt(s,f,i);if(a!==void 0)throw await Q(Me(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const c=await St(s,i.cwd,i.profileId),d=bt(s.spec);for(const v of c){const w=f.find(v.providerId,v.modelId);if(w===void 0)continue;const S=d?.providerId===v.providerId&&d.modelId===v.modelId?d.thinkingLevel??(v.thinkingLevel===void 0?void 0:"off"):v.thinkingLevel;return{model:w,thinkingLevel:S}}if(o.modelExact===!0){const v=c.map(w=>`'${w.providerId}/${w.modelId}' unregistered`).join("; ");throw await Q(Me(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${o.model}' is unavailable \u2014 refusing to substitute (${v})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}b({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:c.map(v=>({provider:v.providerId,model:v.modelId,reason:"unregistered"})).slice(0,16)}})}n(wn,"resolveLaunchModel");function Sn(t){let o=!0;return{runtime:new Proxy(t,{get(f,i,a){return o&&i==="getAvailableSnapshot"?()=>[]:o&&i==="getAvailable"?async()=>[]:o&&i==="getModel"?()=>{}:Reflect.get(f,i,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(Sn,"modelLessRegistry");async function bn(t,o){const s=J(),f=n(async S=>{const g=await Ze.create({credentials:new pt,modelsPath:ke(S.agentDir,"models.json")});gt(g);const y=await t.createAgentSessionServices({cwd:S.cwd,agentDir:S.agentDir,modelRuntime:g,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(O=>({...O,extensions:O.extensions.filter(k=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(k.path))}),"extensionsOverride")}}),R=y.resourceLoader.getExtensions();if(o.extensionPaths.some(O=>oe.includes(O))){const O=new Set(R.extensions.map(T=>T.path)),k=oe.filter(T=>!O.has(T));if(k.length>0){const T=R.errors.filter(L=>oe.includes(L.path)).map(L=>`${L.path}: ${L.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${k.join(", ")}${T===""?"":` (${T})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const M=await wn(y,o),X=M?.model,W=M?.thinkingLevel,P=M===void 0?Sn(y.modelRuntime):void 0,de=P!==void 0?{...y,modelRuntime:P.runtime}:y,G=await t.createAgentSessionFromServices({services:de,sessionManager:S.sessionManager,model:X,thinkingLevel:W,..._n(o.tools,We()),sessionStartEvent:S.sessionStartEvent});return Jt(G.session),ft(G.session),P?.reveal(),{...G,services:y}},"buildForManager"),i=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(i===void 0||i==="")&&o.resumeSessionId!==void 0&&o.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${o.resumeSessionId}' (pi_session_file was never captured for this node)`);const c=!a&&i!==void 0&&i!=="",d=c&&o.newCycle===!0,v=c&&!d;let w;if(a)w=await t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(v||d){if(w=await t.SessionManager.open(i),d){const S=w.getLeafId();w.resetLeaf(),w.appendCustomEntry(Et,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:S})}}else w=await t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const S=n(async y=>{const R=await f({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...R,diagnostics:R.services.diagnostics??[]}},"factory"),g=await t.createAgentSessionRuntime(S,{cwd:o.cwd,agentDir:s,sessionManager:w});return{session:g.session,services:g.services,resuming:v,runtime:g}}const E=await f({cwd:o.cwd,agentDir:s,sessionManager:w});return{session:E.session,services:E.services,resuming:v,runtime:void 0}}n(bn,"buildBrokerSession");function yn(t){const o=n((i,a,c,d)=>{if(d?.signal?.aborted)return Promise.resolve(i);const v=t.writable();return v.length===0?Promise.resolve(i):new Promise(w=>{let E;const S=n(()=>{E!==void 0&&clearTimeout(E),d?.signal?.removeEventListener("abort",g),t.pending.delete(a.id)},"cleanup"),g=n(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},"onAbort");d?.signal?.addEventListener("abort",g,{once:!0});const y=d?.timeout!==void 0?d.timeout:gn;E=setTimeout(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(i)},y),typeof E.unref=="function"&&E.unref(),t.pending.set(a.id,{request:a,resolve:n(R=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(c(R))},"resolve")});for(const R of v)t.forward(R,a)})},"dialogPromise"),s=n(()=>{},"noop");return{[Rt]:t.onKnownStreamWait??(i=>()=>{}),get theme(){const i=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(i==null)throw new Error("Theme not initialized. Call initTheme() first.");return i},select:n((i,a,c)=>o(void 0,{type:"extension_ui_request",id:A(),method:"select",title:i,options:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"select"),confirm:n((i,a,c)=>o(!1,{type:"extension_ui_request",id:A(),method:"confirm",title:i,message:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,c),"confirm"),input:n((i,a,c)=>o(void 0,{type:"extension_ui_request",id:A(),method:"input",title:i,placeholder:a,timeout:c?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,c),"input"),editor:n((i,a)=>o(void 0,{type:"extension_ui_request",id:A(),method:"editor",title:i,prefill:a},c=>"cancelled"in c&&c.cancelled?void 0:"value"in c?c.value:void 0),"editor"),setStatus:n((i,a)=>t.broadcast({type:"extension_ui_request",id:A(),method:"setStatus",statusKey:i,statusText:a}),"setStatus"),setWidget:n((i,a,c)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:A(),method:"setWidget",widgetKey:i,widgetLines:a,widgetPlacement:c?.placement})},"setWidget"),setTitle:n(i=>t.broadcast({type:"extension_ui_request",id:A(),method:"setTitle",title:i}),"setTitle"),notify:n((i,a)=>{const c=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:A(),method:"notify",message:i,notifyType:c})},"notify"),onTerminalInput:n(()=>s,"onTerminalInput"),setWorkingMessage:s,setWorkingVisible:s,setWorkingIndicator:s,setHiddenThinkingLabel:s,setFooter:s,setHeader:s,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:s,setEditorText:s,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:s,setEditorComponent:s,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:s,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:s}}n(yn,"makeBrokerUiContext");export{Fr as REVIEW_BOUNDARY_NAVIGATION_CODE,Nr as ReviewBoundaryNavigationError,_n as brokerToolOptions,bn as buildBrokerSession,vn as disposeActiveSession,yn as makeBrokerUiContext,Or as runBroker,ae as snapshotMessages};
|