@north-light/cli 0.3.424 → 0.3.425
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.
|
@@ -1,11 +1,23 @@
|
|
|
1
1
|
import { type TurnReply } from '../../../shared/turn-replies.js';
|
|
2
2
|
import type { BrokerToClient } from '../broker-protocol.js';
|
|
3
|
+
export interface TurnReplyTrackerOptions {
|
|
4
|
+
/** Rewrites a turn's prose; null on failure. Defaults to the light-model call. */
|
|
5
|
+
generate?: (userText: string, prose: readonly string[]) => Promise<string | null>;
|
|
6
|
+
/** Whether the `consolidate_replies` experiment is on. Defaults to user config. */
|
|
7
|
+
enabled?: () => boolean;
|
|
8
|
+
}
|
|
3
9
|
/** Consolidated replies (`consolidate_replies` experiment): tracks the open
|
|
4
10
|
* turn's prose messages and rewrites them into one reply with a no-context light
|
|
5
11
|
* model whenever a second or later prose message ends. A turn runs from one
|
|
6
12
|
* message the person typed to the next; everything the runtime injects stays
|
|
7
13
|
* inside it. Rewrites persist to `turn-replies.json` and broadcast as
|
|
8
|
-
* `turn_reply` frames; the viewer owns presentation.
|
|
14
|
+
* `turn_reply` frames; the viewer owns presentation.
|
|
15
|
+
*
|
|
16
|
+
* The open turn is a projection of the bound session's branch, so anything that
|
|
17
|
+
* moves the leaf in place (a fault-retry rewind, `/tree`) must call `seed()`
|
|
18
|
+
* again: otherwise prose from the abandoned branch stays in every later rewrite,
|
|
19
|
+
* and the viewer — which honours a rewrite only when all its sources are still
|
|
20
|
+
* in the turn — falls back to showing every message verbatim. */
|
|
9
21
|
export declare class TurnReplyTracker {
|
|
10
22
|
private readonly broadcast;
|
|
11
23
|
private readonly path;
|
|
@@ -14,10 +26,16 @@ export declare class TurnReplyTracker {
|
|
|
14
26
|
private turn;
|
|
15
27
|
private inFlight;
|
|
16
28
|
private queued;
|
|
17
|
-
|
|
29
|
+
/** Bumped by every `seed()`. A rewrite requested against an earlier branch
|
|
30
|
+
* may name prose that branch no longer holds, so its result is dropped. */
|
|
31
|
+
private epoch;
|
|
32
|
+
private readonly generate;
|
|
33
|
+
private readonly enabled;
|
|
34
|
+
constructor(nodeId: string, broadcast: (frame: BrokerToClient) => void, options?: TurnReplyTrackerOptions);
|
|
18
35
|
snapshot(): Record<string, TurnReply>;
|
|
19
36
|
/** Rebuild the open turn from the bound session's messages, so a broker
|
|
20
|
-
* restart mid-turn keeps rewriting it
|
|
37
|
+
* restart mid-turn keeps rewriting it and a rewind drops the prose of the
|
|
38
|
+
* branch it left. Earlier turns are frozen. */
|
|
21
39
|
seed(messages: readonly unknown[]): void;
|
|
22
40
|
observe(event: {
|
|
23
41
|
type?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var
|
|
1
|
+
var c=Object.defineProperty;var o=(n,t)=>c(n,"name",{value:t,configurable:!0});import{join as l}from"node:path";import{nodeRunJobDir as m}from"../../canvas/paths.js";import{readConfig as y}from"../../config.js";import{emitEvent as k}from"../../events/emit.js";import{atomicWriteJson as g,readJsonIfExists as b}from"../../fs-utils.js";import{assistantVisibleText as T,isTrueUserMessage as h}from"../../../shared/tool-groups.js";import{generatedContextText as p}from"../../../shared/generated-context.js";import{isSettledAssistant as x,messageKey as a,normalizeTurnReplyRecord as j,START_TURN_KEY as d}from"../../../shared/turn-replies.js";import{headlessTurnReply as w}from"../turn-reply-summary.js";function f(n,t){return n!==void 0&&n.sources.length===t.length&&n.sources.every((s,e)=>s===t[e].key)}o(f,"sameSources");class A{static{o(this,"TurnReplyTracker")}broadcast;path;replies=new Map;tasks=new Set;turn={key:d,userText:"",prose:[]};inFlight;queued;epoch=0;generate;enabled;constructor(t,s,e={}){this.broadcast=s,this.generate=e.generate??w,this.enabled=e.enabled??(()=>y("user").consolidate_replies),this.path=l(m(t),"turn-replies.json");try{for(const[r,i]of Object.entries(j(b(this.path))))this.replies.set(r,i)}catch{}}snapshot(){return Object.fromEntries(this.replies)}seed(t){this.epoch+=1,this.queued=void 0;let s={key:d,userText:"",prose:[]};for(const e of t){if(e===null||typeof e!="object")continue;const r=e;if(h(r)){const u=a(r);u!==void 0&&(s={key:u,userText:p(r),prose:[]});continue}const i=this.proseOf(r);i!==void 0&&s.prose.push(i)}this.turn=s,this.maybeGenerate()}observe(t){if(t.type!=="message_start"&&t.type!=="message_end")return;const s=t.message;if(s===null||typeof s!="object")return;const e=s;if(t.type==="message_start"){if(!h(e))return;const i=a(e);i!==void 0&&i!==this.turn.key&&(this.turn={key:i,userText:p(e),prose:[]});return}const r=this.proseOf(e);r===void 0||this.turn.prose.some(i=>i.key===r.key)||(this.turn.prose.push(r),this.maybeGenerate())}hasTasks(){return this.tasks.size>0}async waitForTasks(){for(;this.tasks.size>0;)await Promise.allSettled([...this.tasks])}proseOf(t){if(t.role!=="assistant"||!x(t))return;const s=T(t).trim(),e=a(t);return s===""||e===void 0?void 0:{key:e,text:s}}maybeGenerate(){const{key:t,userText:s,prose:e}=this.turn;if(e.length<2||!this.enabled()||f(this.replies.get(t),e))return;const r={key:t,userText:s,prose:[...e],epoch:this.epoch};if(this.inFlight!==void 0){this.queued=r;return}this.run(r)}run(t){this.inFlight=t;let s;s=this.generate(t.userText,t.prose.map(e=>e.text)).then(e=>{if(e===null||t.epoch!==this.epoch)return;const r={version:1,sources:t.prose.map(i=>i.key),text:e};this.replies.set(t.key,r);try{g(this.path,Object.fromEntries(this.replies))}catch(i){k({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`failed to persist turn reply: ${i instanceof Error?i.message:String(i)}`}})}this.broadcast({type:"turn_reply",key:t.key,reply:r})}).catch(()=>{}).finally(()=>{this.tasks.delete(s),this.inFlight=void 0;const e=this.queued;this.queued=void 0,e!==void 0&&!f(this.replies.get(e.key),e.prose)&&this.run(e)}),this.tasks.add(s)}}export{A as TurnReplyTracker};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
var Pe=Object.defineProperty;var e=(t,r)=>Pe(t,"name",{value:r,configurable:!0});import{envInboxBetweenTurns as Oe,envModelIntent as Ie,envNodeCwd as De,envNodeId as Ne,envProfileId as Fe,envScopes as Le,isSandboxedNode as Be,scopeAllowed as $e}from"../../shared/env.js";import{createServer as Ue}from"node:net";import{existsSync as Se,readFileSync as Ge,unlinkSync as ye}from"node:fs";import{join as be}from"node:path";import{randomUUID as x}from"node:crypto";import{mark as Ke}from"../timing.js";import{SUBMIT_RESULT_TOOL as je}from"./structured-output.js";import{installSessionManagerStorePatch as We}from"../conversation-store/index.js";import{getAgentDir as Y,ModelRegistry as qe,ModelRuntime as Ve}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Xe,viewSocketPath as He}from"../canvas/paths.js";import{bindBrokerEventSource as Ye}from"../events/source.js";import{emitEvent as E,flushBrokerLog as ze}from"../events/emit.js";import{operationIdContext as Je}from"../events/operation-id.js";import{findMissingPackagePaths as Qe}from"./package-health.js";import{installBrokerConfigSnapshot as Ze}from"../config.js";import{FRONT_DOOR_ENV as en}from"./front-door.js";import{CANVAS_EXTENSIONS as oe,piInvocationToSdkConfig as nn}from"./launch.js";import{assertEngineVersion as tn,loadBrokerEngine as on}from"./broker-sdk.js";import{initCrtrTheme as rn}from"./crtr-theme.js";import{resolveBundledPiPackageDir as sn}from"./pi-cli.js";import{captureSessionChatCapabilities as an}from"./command-surface.js";import{InMemoryCredentialStore as dn}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as ln}from"./broker/model-adapter.js";import{mutateBrokerFault as z,recordBrokerTurn as Te}from"./broker/daemon-ops.js";import{modelRequestFromConfig as cn,expandModelCandidates as mn,parseModelSpec as un,unregisteredConcreteModel as fn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as pn}from"./stream-watchdog.js";import{probeOnline as gn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as vn,cycleAwareMessages as hn,endedByAbort as _n}from"./session-cycles.js";import{turnErrorOf as wn}from"../llm/refusal.js";import{projectTranscript as Sn}from"./session-visibility.js";import{currentTurnVisibility as yn}from"./turn-visibility.js";import{isUnknownModel as re}from"./model-selection.js";import{BrokerClientRegistry as bn}from"./broker/client-registry.js";import{ToolGroupTracker as Tn}from"./broker/tool-groups.js";import{TurnReplyTracker as En}from"./broker/turn-replies.js";import{onNodeNamed as kn}from"./broker/node-named.js";import{FaultRetry as Rn,willDaemonRetry as Mn}from"./broker/fault-retry.js";import{RunTurnEnds as xn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as Cn}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as An,BROKER_RUN_TURN_BUSY as Pn}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as On,settleRunDeferredMail as In}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Dn}from"./broker/run-turn-queue.js";import{EventProjection as Nn}from"./broker/event-projection.js";import{createFrameDispatchContext as Fn,handleFrame as Ln}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as Bn,installAdvertisedCommandInvocationContract as $n}from"./advertised-command-invocation.js";import{RebindDriver as Un}from"./broker/rebind.js";import{beginRuntimeTeardown as Gn}from"./broker/extension-abort.js";import{receiveNodeToken as Kn}from"./broker/node-token.js";import{serveCliRelay as jn}from"./broker/cli-relay.js";import{decodeKickoffOrigin as Wn,KICKOFF_ORIGIN_ENV as qn}from"./stamp/protocol.js";import{announceMessageOrigin as Vn}from"./stamp/channel.js";import{brokerExtensionState as Xn,commitBrokerModel as Hn}from"./broker/daemon-ops.js";import{composerNames as Yn}from"./broker/frame-memory-refs.js";import{FrameOverflowError as zn,normalizeSnapshotTail as Jn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as fo,REVIEW_BOUNDARY_NAVIGATION_CODE as po}from"./broker/frame-replies.js";function se(t){return new qe(t.modelRuntime)}e(se,"registryOf");function $(t,r){if(t==null||re(t))return null;const i=r!==void 0&&r!==""&&r!=="off"?`:${r}`:"";return`${t.provider}/${t.id}${i}`}e($,"formatModelSpec");function Qn(t,r){const i=$(t,void 0);return i===null?null:`${i}:${r===void 0||r===""?"off":r}`}e(Qn,"formatExactModelSpec");const Zn=12e4;let J=null;import{brokerSignalClient as Q}from"./broker/signal-stream.js";function et(){Q().stop();const t=J;if(J=null,t!==null)try{t.dispose()}catch{}}e(et,"disposeActiveSession");function nt(t,r){const i=$e(r,"crtr:act")?void 0:["bash"],m=t!==void 0&&t.length>0?[...new Set([...t,je])]:t===void 0?void 0:[...t];return{...m!==void 0?{tools:m}:{},...i!==void 0?{excludeTools:i}:{}}}e(nt,"brokerToolOptions");async function co(t,r=process.hrtime.bigint(),i=new Date().toISOString()){Ye(t);const m=await Kn(),s=await jn(t,m);process.env.CRTR_API_SOCKET=s.path,Je.fresh(()=>{E({level:"info",event:"broker.startup.cli_entry",ts:i,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),E({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-r)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let l=null;const d=e((n,o=null)=>{a.has(n)||(a.add(n),Ke(n,{duration_ms:Number(process.hrtime.bigint()-r)/1e6}),E({level:"info",event:n,duration_ms:Number(process.hrtime.bigint()-r)/1e6,fields:{runtime_version:process.version,engine_version:l,model:o}}))},"emitStartupMilestone");process.env[en]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,We(t);const f=await on();tn(f.VERSION),l=f.VERSION;const w=Xe(t),k=be(w,"broker-launch.json"),S=JSON.parse(Ge(k,"utf8"));if(Be()){if(!S.configSnapshot)throw new Error("broker launch is missing its config snapshot");Ze(S.configSnapshot)}const u=nn(S);u.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await Yn(t);let b,C;const q=e(n=>{b!==void 0?b(n):C??=n},"onSignal");process.on("SIGTERM",()=>q("SIGTERM")),process.on("SIGINT",()=>q("SIGINT"));let{session:U,services:A,resuming:ie,runtime:G}=await st(f,u);d("broker.startup.session_built");const R=(await Xn(t)).node.review_binding?.review_id,T=Oe();J=U;const D=gn;try{process.env.PI_PACKAGE_DIR=sn(),rn(A.settingsManager.getTheme(),Y(),!1)}catch(n){E({level:"error",event:"broker.theme.initialization_failed",error:n})}try{for(const n of Qe(Y()))E({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:n.source,resolved_path:n.resolved}})}catch{}const K=He(t),p=new bn(t),V=new Map,O=new Tn(t,n=>p.broadcast(n)),X=new En(t,n=>p.broadcast(n));kn(n=>p.broadcast({type:"node_named",...n}));let N=!1,ae=!1,H,de,g,j;const Z=new xn;let F,le=e(()=>{},"notifyTurnAccepted"),ce=e(()=>{},"resetFrameState");const ee=Cn();let me=e(()=>0,"pendingPromptDispatches"),ue;const L=Dn({runNode:T,session:e(()=>g.session(),"session"),isReplacing:e(()=>g.isReplacing(),"isReplacing"),isAgentRunActive:e(()=>g.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:e(()=>me(),"pendingDispatches"),turnAdmission:ee,prependDeferred:e(n=>On(t,n),"prependDeferred"),onError:e(n=>E({level:"error",event:"broker.inbox.idle_prompt_failed",error:n}),"onError")}),fe=L.drain;u.firstPrompt!==void 0&&u.firstPrompt!==""&&L.holdForKickoff(),globalThis[An]=L.start,globalThis[Pn]=L.busy,g=new Un({nodeId:t,cfg:u,session:U,services:A,runtime:G,registry:p,toolGroups:O,turnReplies:X,transcriptMessages:e(n=>Ee(n,R)?.map(({message:o})=>o)??n.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:e(()=>de,"uiContext"),faultRetry:e(()=>j,"faultRetry"),projection:e(()=>F,"projection"),setActiveSession:e(n=>{if(J=n,ue?.(),T){let o="stop",c,v=!1;ue=n.subscribe(h=>{if(h.type==="agent_start"&&(o="stop",c=void 0,v=!1,Z.started()),h.type==="agent_end"){const _=[...h.messages??[]].reverse().find(B=>B.role==="assistant");_&&(o=_.stopReason,c=_n(_)?void 0:wn(_),v=_.role==="assistant"&&Mn(_,n.model?.contextWindow))}h.type==="agent_settled"&&(Z.settled(n.sessionManager,{stop_reason:o,...c?{error:c}:{}},v),In(t,n).catch(_=>{E({level:"error",event:"broker.run_deferred_mail.settle_failed",error:_})}),queueMicrotask(()=>{g.session()===n&&fe()}))})}},"setActiveSession"),disposeAndExit:e((n,o)=>W(n,o),"disposeAndExit"),onSessionRebind:e(()=>{ce()},"onSessionRebind"),onReplacementIdle:e(()=>{T&&fe()},"onReplacementIdle"),reWelcomeAll:e(()=>ne(),"reWelcomeAll")});const pe=e(async(n,o=!1)=>{const c=g.session(),v=$(c.model,c.thinkingLevel);if(v===null)return null;const h=await Hn(t,{spec:v,...n!==void 0?{intent:n}:{},userSelected:o});return o&&(u.model=h.modelOverride,n!==void 0?(process.env.CRTR_MODEL_INTENT=`${n.family}/${n.strength}`,delete process.env.CRTR_MODEL_EXACT,u.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",u.modelExact=!0)),h.modelOverride},"persistModelChoice"),ge=e(async(n=!0,o,c=!1)=>{const v=g.session(),h=$(v.model,v.thinkingLevel),_=n?await pe(o,c):h;p.broadcast({type:"model_changed",model:re(v.model)?void 0:v.model,spec:_})},"broadcastModelChanged");j=new Rn({nodeId:t,cfg:u,retryProbe:D,currentSession:e(()=>g.session(),"currentSession"),currentServices:e(()=>g.services(),"currentServices"),installedGeneration:e(()=>g.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:$,broadcastModelChanged:ge,turnAdmission:ee,reWelcomeAll:e(()=>ne(),"reWelcomeAll"),...T?{turnEnds:Z}:{}});const ve=e(()=>{j.rearmIfStranded().catch(n=>{E({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${n instanceof Error?n.message:String(n)}`}})})},"rearmStrandedRetry");Q().subscribe("resync",ve),Q().subscribe("fault-retry",ve),F=new Nn({registry:p,faultRetry:j,installedGeneration:e(()=>g.installedGeneration(),"installedGeneration"),currentSession:e(()=>g.session(),"currentSession"),notifyTurnAccepted:e(()=>le(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:$});const Re=e(n=>{const o=g.session(),c=Ee(o,R),v=Jn(n.snapshotTail),h=c===void 0||v===void 0?c:c.slice(-v),_=h?.map(({message:I})=>I)??o.sessionManager.buildSessionContext().messages,B=O.summaries(),we=h!==void 0&&v!==void 0?tt(_):void 0,Ae=we===void 0?B:Object.fromEntries(Object.entries(B).filter(([I])=>we.has(I)));return{messages:_,...h===void 0?{}:{messageIds:h.map(({id:I})=>I)},messageVisibility:h?.map(({visibility:I})=>I)??_.map(()=>"visible"),turnVisibility:yn(),stats:o.getSessionStats(),state:{model:re(o.model)?void 0:o.model,thinkingLevel:o.thinkingLevel,isStreaming:o.isStreaming,isCompacting:o.isCompacting,steeringMode:o.steeringMode,followUpMode:o.followUpMode,sessionFile:o.sessionFile,sessionId:o.sessionId,sessionName:o.sessionName,autoCompactionEnabled:o.autoCompactionEnabled,messageCount:o.messages.length,pendingMessageCount:o.pendingMessageCount},display:{...p.displaySnapshot()},toolGroupSummaries:Ae,turnReplies:X.snapshot(),workingActivity:F.currentWorkingActivity(),queued:{steering:[...o.getSteeringMessages()],followUp:[...o.getFollowUpMessages()]}}},"buildSnapshot"),he=e(n=>{const o=n.role==="controller"?V.values().next().value:void 0;p.sendFrame(n,{type:"welcome",snapshot:Re(n),role:n.role,pending_dialog:o!==void 0?o.request:null,agentDir:Y()},!0)},"sendWelcome"),Me=e(n=>{const o=[...V.values()];for(let c=1;c<o.length;c++)p.sendFrame(n,o[c].request)},"replayExtraPendingDialogsTo"),ne=e(()=>{p.forEachHelloed(he)},"reWelcomeAll"),_e=e(async n=>{if(!N){N=!0,Q().stop(),O.persistPendingSummary(),F.dispose(),et();try{H?.close()}catch{}s.close(),p.dispose();try{Se(K)&&ye(K)}catch{}p.clearAttachState(),await ze(),process.exit(n)}},"completeExit"),W=e((n,o=0)=>{if(N)return;const c=n==="shutdown-hook"||n==="shutdown-after-settle";if(c&&O.finishOpenToolGroup(!0),c&&(O.hasSummaryTasks()||X.hasTasks())){if(ae)return;ae=!0,Promise.allSettled([O.waitForSummaryTasks(),X.waitForTasks()]).finally(()=>_e(o));return}_e(o)},"disposeAndExit");de=it({writable:e(()=>p.writableClients(),"writable"),forward:e((n,o)=>p.sendFrame(n,o),"forward"),pending:V,broadcast:e(n=>p.broadcastUi(n),"broadcast"),onKnownStreamWait:e(n=>F.knownStreamWait(n),"onKnownStreamWait")}),g.setRebindSession(),await g.enqueueRebind(U,A),d("broker.startup.extensions_bound");const M=Fn({nodeId:t,registry:p,toolGroups:O,projection:F,rebind:g,boundaryReviewId:R,pendingDialogs:V,sendWelcome:he,replayExtraPendingDialogsTo:Me,reWelcomeAll:ne,disposeAndExit:W,persistModelChoice:pe,broadcastModelChanged:ge,registryOf:se,formatModelSpec:$,formatExactModelSpec:Qn,turnAdmission:ee,memoryInventory:y,runNode:T,onKickoffAdmitted:L.releaseKickoff});le=M.notifyTurnAccepted,ce=M.resetForSession,me=M.pendingPromptDispatches;const xe=2500;let te=!1;const Ce=e(async n=>{if(N||te)return;if(te=!0,g.isAgentRunActive()||g.session().isStreaming||M.pendingPromptDispatches()>0){const c=Date.now()+xe;for(;M.pendingPromptDispatches()>0&&!g.session().isStreaming&&Date.now()<c;)await new Promise(v=>setTimeout(v,25));if(g.session().isStreaming){const v=c-Date.now();if(v>0){let h;try{Gn(),await Promise.race([g.session().abort().then(()=>!0,()=>!1),new Promise(B=>{h=setTimeout(()=>B(!1),v)})])&&await Te(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(M.pendingPromptDispatches()>0||g.isAgentRunActive())&&await Te(t,{event:"interrupted"})}W(n)},"abortAndExit");if(b=e(n=>{Ce(n)},"signalTeardown"),C!==void 0){b(C);return}try{Se(K)&&ye(K)}catch{}H=Ue(n=>{const o=p.create(n);n.on("data",v=>{let h;try{h=o.decoder.push(v)}catch(_){_ instanceof zn?(p.sendFrame(o,{type:"error",code:"frame_overflow",message:_.message}),p.dropClient(o,`frame overflow: ${_.message}`)):p.dropClient(o,`decoder error: ${String(_)}`);return}for(const _ of h)try{Ln(M,o,_)}catch{}});const c=e(()=>{p.removeClient(o)},"drop");n.on("close",c),n.on("error",()=>{})}),H.on("error",n=>{N||(E({level:"error",event:"broker.socket.failed",error:n}),W("socket-error",1))}),H.listen(K,async()=>{Promise.all([z(t,{op:"clear",link:"viewer\u2194broker"}),z(t,{op:"clear",link:"relay\u2194broker"})]).catch(o=>E({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:o,fields:{operation:"broker_socket_bound_fault_clear"}}));let n;try{n=await j.recoverOnStartup()}catch(o){E({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:o,fields:{operation:"recovery_startup"}}),W("recovery-startup-failed",1);return}if(!(N||te))if(n!=="retry-armed"&&u.firstPrompt!==void 0&&u.firstPrompt!==""){const o=Wn(process.env[qn]);o!==null&&Vn(u.firstPrompt,o);const c=process.env.CRTR_KICKOFF_MESSAGE_IDS;M.kickoff(u.firstPrompt,c?JSON.parse(c):[])}else L.releaseKickoff()}),p.persistAttachState()}e(co,"runBroker");function tt(t){const r=new Set;for(const i of t)if(!(i.role!=="assistant"||!Array.isArray(i.content)))for(const m of i.content)m!==null&&typeof m=="object"&&m.type==="toolCall"&&typeof m.id=="string"&&r.add(m.id);return r}e(tt,"toolCallIds");function Ee(t,r){const i=t.sessionManager,m=hn(i);return m!==void 0&&Bn(m.map(({message:s})=>s)),m===void 0?void 0:Sn(m,{boundaryReviewId:r,sessionEntries:i.getEntries?.()})}e(Ee,"snapshotMessages");function ke(){const t=Ne();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}e(ke,"currentBrokerNodeId");async function ot(t,r){const i=cn(r.model,Ie(),r.modelExact===!0);if(i===void 0)return;const m=se(t),s={cwd:De()??r.cwd,profileId:Fe()},a=fn(i,m,s);if(a!==void 0)throw await z(ke(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const l=mn(i,s.cwd,s.profileId),d=un(i.spec);for(const f of l){const w=m.find(f.providerId,f.modelId);if(w===void 0)continue;const S=d?.providerId===f.providerId&&d.modelId===f.modelId?d.thinkingLevel??(f.thinkingLevel===void 0?void 0:"off"):f.thinkingLevel;return{model:w,thinkingLevel:S}}if(r.modelExact===!0){const f=l.map(w=>`'${w.providerId}/${w.modelId}' unregistered`).join("; ");throw await z(ke(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${r.model}' is unavailable \u2014 refusing to substitute (${f})`}}),new Error(`[broker] FATAL: exact-consult model '${r.model}' is unavailable`)}E({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:l.map(f=>({provider:f.providerId,model:f.modelId,reason:"unregistered"})).slice(0,16)}})}e(ot,"resolveLaunchModel");function rt(t){let r=!0;return{runtime:new Proxy(t,{get(m,s,a){return r&&s==="getAvailableSnapshot"?()=>[]:r&&s==="getAvailable"?async()=>[]:r&&s==="getModel"?()=>{}:Reflect.get(m,s,a)}}),reveal:e(()=>{r=!1},"reveal")}}e(rt,"modelLessRegistry");async function st(t,r){const i=Y(),m=e(async S=>{const u=await Ve.create({credentials:new dn,modelsPath:be(S.agentDir,"models.json")});ln(u);const y=await t.createAgentSessionServices({cwd:S.cwd,agentDir:S.agentDir,modelRuntime:u,resourceLoaderOptions:{additionalExtensionPaths:r.extensionPaths,appendSystemPrompt:r.appendSystemPromptPath!==void 0?[r.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:e(P=>({...P,extensions:P.extensions.filter(R=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(R.path))}),"extensionsOverride")}}),b=y.resourceLoader.getExtensions();if(r.extensionPaths.some(P=>oe.includes(P))){const P=new Set(b.extensions.map(T=>T.path)),R=oe.filter(T=>!P.has(T));if(R.length>0){const T=b.errors.filter(D=>oe.includes(D.path)).map(D=>`${D.path}: ${D.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${R.join(", ")}${T===""?"":` (${T})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const C=await ot(y,r),q=C?.model,U=C?.thinkingLevel,A=C===void 0?rt(y.modelRuntime):void 0,ie=A!==void 0?{...y,modelRuntime:A.runtime}:y,G=await t.createAgentSessionFromServices({services:ie,sessionManager:S.sessionManager,model:q,thinkingLevel:U,...nt(r.tools,Le()),sessionStartEvent:S.sessionStartEvent});return $n(G.session),an(G.session),A?.reveal(),{...G,services:y}},"buildForManager"),s=r.resumeSessionPath,a=r.forkFrom!==void 0&&r.forkFrom!=="";if(!a&&(s===void 0||s==="")&&r.resumeSessionId!==void 0&&r.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${r.resumeSessionId}' (pi_session_file was never captured for this node)`);const l=!a&&s!==void 0&&s!=="",d=l&&r.newCycle===!0,f=l&&!d;let w;if(a)w=t.SessionManager.forkFrom(r.forkFrom,r.cwd);else if(f||d){if(w=t.SessionManager.open(s),d){const S=w.getLeafId();w.resetLeaf(),w.appendCustomEntry(vn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:S})}}else w=t.SessionManager.create(r.cwd);if(t.createAgentSessionRuntime!==void 0){const S=e(async y=>{const b=await m({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...b,diagnostics:b.services.diagnostics??[]}},"factory"),u=await t.createAgentSessionRuntime(S,{cwd:r.cwd,agentDir:i,sessionManager:w});return{session:u.session,services:u.services,resuming:f,runtime:u}}const k=await m({cwd:r.cwd,agentDir:i,sessionManager:w});return{session:k.session,services:k.services,resuming:f,runtime:void 0}}e(st,"buildBrokerSession");function it(t){const r=e((s,a,l,d)=>{if(d?.signal?.aborted)return Promise.resolve(s);const f=t.writable();return f.length===0?Promise.resolve(s):new Promise(w=>{let k;const S=e(()=>{k!==void 0&&clearTimeout(k),d?.signal?.removeEventListener("abort",u),t.pending.delete(a.id)},"cleanup"),u=e(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(s)},"onAbort");d?.signal?.addEventListener("abort",u,{once:!0});const y=d?.timeout!==void 0?d.timeout:Zn;k=setTimeout(()=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(s)},y),typeof k.unref=="function"&&k.unref(),t.pending.set(a.id,{request:a,resolve:e(b=>{S(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),w(l(b))},"resolve")});for(const b of f)t.forward(b,a)})},"dialogPromise"),i=e(()=>{},"noop");return{[pn]:t.onKnownStreamWait??(s=>()=>{}),get theme(){const s=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(s==null)throw new Error("Theme not initialized. Call initTheme() first.");return s},select:e((s,a,l)=>r(void 0,{type:"extension_ui_request",id:x(),method:"select",title:s,options:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"select"),confirm:e((s,a,l)=>r(!1,{type:"extension_ui_request",id:x(),method:"confirm",title:s,message:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,l),"confirm"),input:e((s,a,l)=>r(void 0,{type:"extension_ui_request",id:x(),method:"input",title:s,placeholder:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"input"),editor:e((s,a)=>r(void 0,{type:"extension_ui_request",id:x(),method:"editor",title:s,prefill:a},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0),"editor"),setStatus:e((s,a)=>t.broadcast({type:"extension_ui_request",id:x(),method:"setStatus",statusKey:s,statusText:a}),"setStatus"),setWidget:e((s,a,l)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:x(),method:"setWidget",widgetKey:s,widgetLines:a,widgetPlacement:l?.placement})},"setWidget"),setTitle:e(s=>t.broadcast({type:"extension_ui_request",id:x(),method:"setTitle",title:s}),"setTitle"),notify:e((s,a)=>{const l=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:x(),method:"notify",message:s,notifyType:l})},"notify"),onTerminalInput:e(()=>i,"onTerminalInput"),setWorkingMessage:i,setWorkingVisible:i,setWorkingIndicator:i,setHiddenThinkingLabel:i,setFooter:i,setHeader:i,custom:e(()=>Promise.resolve(void 0),"custom"),pasteToEditor:i,setEditorText:i,getEditorText:e(()=>"","getEditorText"),addAutocompleteProvider:i,setEditorComponent:i,getEditorComponent:e(()=>{},"getEditorComponent"),getAllThemes:e(()=>[],"getAllThemes"),getTheme:e(()=>{},"getTheme"),setTheme:i,getToolsExpanded:e(()=>!1,"getToolsExpanded"),setToolsExpanded:i}}e(it,"makeBrokerUiContext");export{po as REVIEW_BOUNDARY_NAVIGATION_CODE,fo as ReviewBoundaryNavigationError,nt as brokerToolOptions,st as buildBrokerSession,et as disposeActiveSession,it as makeBrokerUiContext,co as runBroker,Ee as snapshotMessages};
|
|
1
|
+
var Pe=Object.defineProperty;var n=(t,o)=>Pe(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Oe,envModelIntent as Ie,envNodeCwd as De,envNodeId as Ne,envProfileId as Fe,envScopes as Le,isSandboxedNode as $e,scopeAllowed as Be}from"../../shared/env.js";import{createServer as Ue}from"node:net";import{existsSync as ye,readFileSync as Ge,unlinkSync as be}from"node:fs";import{join as Te}from"node:path";import{randomUUID as x}from"node:crypto";import{mark as Ke}from"../timing.js";import{SUBMIT_RESULT_TOOL as je}from"./structured-output.js";import{installSessionManagerStorePatch as We}from"../conversation-store/index.js";import{getAgentDir as Y,ModelRegistry as qe,ModelRuntime as Ve}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Xe,viewSocketPath as He}from"../canvas/paths.js";import{bindBrokerEventSource as Ye}from"../events/source.js";import{emitEvent as T,flushBrokerLog as ze}from"../events/emit.js";import{operationIdContext as Je}from"../events/operation-id.js";import{findMissingPackagePaths as Qe}from"./package-health.js";import{installBrokerConfigSnapshot as Ze}from"../config.js";import{FRONT_DOOR_ENV as en}from"./front-door.js";import{CANVAS_EXTENSIONS as re,piInvocationToSdkConfig as nn}from"./launch.js";import{assertEngineVersion as tn,loadBrokerEngine as rn}from"./broker-sdk.js";import{initCrtrTheme as on}from"./crtr-theme.js";import{resolveBundledPiPackageDir as sn}from"./pi-cli.js";import{captureSessionChatCapabilities as an}from"./command-surface.js";import{InMemoryCredentialStore as dn}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as ln}from"./broker/model-adapter.js";import{mutateBrokerFault as z,recordBrokerTurn as ke}from"./broker/daemon-ops.js";import{modelRequestFromConfig as cn,expandModelCandidates as mn,parseModelSpec as un,unregisteredConcreteModel as fn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as pn}from"./stream-watchdog.js";import{probeOnline as gn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as vn,cycleAwareMessages as hn,endedByAbort as Sn}from"./session-cycles.js";import{turnErrorOf as _n}from"../llm/refusal.js";import{projectTranscript as wn}from"./session-visibility.js";import{currentTurnVisibility as yn}from"./turn-visibility.js";import{isUnknownModel as oe}from"./model-selection.js";import{BrokerClientRegistry as bn}from"./broker/client-registry.js";import{ToolGroupTracker as Tn}from"./broker/tool-groups.js";import{TurnReplyTracker as kn}from"./broker/turn-replies.js";import{onNodeNamed as En}from"./broker/node-named.js";import{FaultRetry as Rn,willDaemonRetry as Mn}from"./broker/fault-retry.js";import{RunTurnEnds as xn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as Cn}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as An,BROKER_RUN_TURN_BUSY as Pn}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as On,settleRunDeferredMail as In}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Dn}from"./broker/run-turn-queue.js";import{EventProjection as Nn}from"./broker/event-projection.js";import{createFrameDispatchContext as Fn,handleFrame as Ln}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as $n,installAdvertisedCommandInvocationContract as Bn}from"./advertised-command-invocation.js";import{RebindDriver as Un}from"./broker/rebind.js";import{beginRuntimeTeardown as Gn}from"./broker/extension-abort.js";import{receiveNodeToken as Kn}from"./broker/node-token.js";import{serveCliRelay as jn}from"./broker/cli-relay.js";import{decodeKickoffOrigin as Wn,KICKOFF_ORIGIN_ENV as qn}from"./stamp/protocol.js";import{announceMessageOrigin as Vn}from"./stamp/channel.js";import{brokerExtensionState as Xn,commitBrokerModel as Hn}from"./broker/daemon-ops.js";import{composerNames as Yn}from"./broker/frame-memory-refs.js";import{FrameOverflowError as zn,normalizeSnapshotTail as Jn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as ur,REVIEW_BOUNDARY_NAVIGATION_CODE as fr}from"./broker/frame-replies.js";function se(t){return new qe(t.modelRuntime)}n(se,"registryOf");function B(t,o){if(t==null||oe(t))return null;const i=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${i}`}n(B,"formatModelSpec");function Qn(t,o){const i=B(t,void 0);return i===null?null:`${i}:${o===void 0||o===""?"off":o}`}n(Qn,"formatExactModelSpec");const Zn=12e4;let J=null;import{brokerSignalClient as Q}from"./broker/signal-stream.js";function et(){Q().stop();const t=J;if(J=null,t!==null)try{t.dispose()}catch{}}n(et,"disposeActiveSession");function nt(t,o){const i=Be(o,"crtr:act")?void 0:["bash"],m=t!==void 0&&t.length>0?[...new Set([...t,je])]:t===void 0?void 0:[...t];return{...m!==void 0?{tools:m}:{},...i!==void 0?{excludeTools:i}:{}}}n(nt,"brokerToolOptions");async function lr(t,o=process.hrtime.bigint(),i=new Date().toISOString()){Ye(t);const m=await Kn(),s=await jn(t,m);process.env.CRTR_API_SOCKET=s.path,Je.fresh(()=>{T({level:"info",event:"broker.startup.cli_entry",ts:i,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),T({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let l=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Ke(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),T({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:l,model:r}}))},"emitStartupMilestone");process.env[en]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,We(t);const p=await rn();tn(p.VERSION),l=p.VERSION;const _=Xe(t),E=Te(_,"broker-launch.json"),w=JSON.parse(Ge(E,"utf8"));if($e()){if(!w.configSnapshot)throw new Error("broker launch is missing its config snapshot");Ze(w.configSnapshot)}const u=nn(w);u.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await Yn(t);let b,C;const V=n(e=>{b!==void 0?b(e):C??=e},"onSignal");process.on("SIGTERM",()=>V("SIGTERM")),process.on("SIGINT",()=>V("SIGINT"));let{session:U,services:A,resuming:ae,runtime:G}=await st(p,u);d("broker.startup.session_built");const R=(await Xn(t)).node.review_binding?.review_id,k=Oe();J=U;const D=gn;try{process.env.PI_PACKAGE_DIR=sn(),on(A.settingsManager.getTheme(),Y(),!1)}catch(e){T({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of Qe(Y()))T({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const K=He(t),g=new bn(t),X=new Map,O=new Tn(t,e=>g.broadcast(e)),j=new kn(t,e=>g.broadcast(e));En(e=>g.broadcast({type:"node_named",...e}));let N=!1,de=!1,H,le,f,W;const Z=new xn;let F,ce=n(()=>{},"notifyTurnAccepted"),me=n(()=>{},"resetFrameState");const ee=Cn();let ue=n(()=>0,"pendingPromptDispatches"),fe;const L=Dn({runNode:k,session:n(()=>f.session(),"session"),isReplacing:n(()=>f.isReplacing(),"isReplacing"),isAgentRunActive:n(()=>f.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>ue(),"pendingDispatches"),turnAdmission:ee,prependDeferred:n(e=>On(t,e),"prependDeferred"),onError:n(e=>T({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")}),pe=L.drain;u.firstPrompt!==void 0&&u.firstPrompt!==""&&L.holdForKickoff(),globalThis[An]=L.start,globalThis[Pn]=L.busy,f=new Un({nodeId:t,cfg:u,session:U,services:A,runtime:G,registry:g,toolGroups:O,turnReplies:j,transcriptMessages:n(e=>ie(e,R)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>le,"uiContext"),faultRetry:n(()=>W,"faultRetry"),projection:n(()=>F,"projection"),setActiveSession:n(e=>{if(J=e,fe?.(),k){let r="stop",c,v=!1;fe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",c=void 0,v=!1,Z.started()),h.type==="agent_end"){const S=[...h.messages??[]].reverse().find($=>$.role==="assistant");S&&(r=S.stopReason,c=Sn(S)?void 0:_n(S),v=S.role==="assistant"&&Mn(S,e.model?.contextWindow))}h.type==="agent_settled"&&(Z.settled(e.sessionManager,{stop_reason:r,...c?{error:c}:{}},v),In(t,e).catch(S=>{T({level:"error",event:"broker.run_deferred_mail.settle_failed",error:S})}),queueMicrotask(()=>{f.session()===e&&pe()}))})}},"setActiveSession"),disposeAndExit:n((e,r)=>q(e,r),"disposeAndExit"),onSessionRebind:n(()=>{me()},"onSessionRebind"),onReplacementIdle:n(()=>{k&&pe()},"onReplacementIdle"),reWelcomeAll:n(()=>ne(),"reWelcomeAll")});const ge=n(async(e,r=!1)=>{const c=f.session(),v=B(c.model,c.thinkingLevel);if(v===null)return null;const h=await Hn(t,{spec:v,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(u.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,u.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",u.modelExact=!0)),h.modelOverride},"persistModelChoice"),ve=n(async(e=!0,r,c=!1)=>{const v=f.session(),h=B(v.model,v.thinkingLevel),S=e?await ge(r,c):h;g.broadcast({type:"model_changed",model:oe(v.model)?void 0:v.model,spec:S})},"broadcastModelChanged");W=new Rn({nodeId:t,cfg:u,retryProbe:D,currentSession:n(()=>f.session(),"currentSession"),currentServices:n(()=>f.services(),"currentServices"),installedGeneration:n(()=>f.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:B,broadcastModelChanged:ve,turnAdmission:ee,reWelcomeAll:n(()=>ne(),"reWelcomeAll"),...k?{turnEnds:Z}:{}});const he=n(()=>{W.rearmIfStranded().catch(e=>{T({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");Q().subscribe("resync",he),Q().subscribe("fault-retry",he),F=new Nn({registry:g,faultRetry:W,installedGeneration:n(()=>f.installedGeneration(),"installedGeneration"),currentSession:n(()=>f.session(),"currentSession"),notifyTurnAccepted:n(()=>ce(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:B});const Re=n(e=>{const r=f.session(),c=ie(r,R),v=Jn(e.snapshotTail),h=c===void 0||v===void 0?c:c.slice(-v),S=h?.map(({message:I})=>I)??r.sessionManager.buildSessionContext().messages,$=O.summaries(),we=h!==void 0&&v!==void 0?tt(S):void 0,Ae=we===void 0?$:Object.fromEntries(Object.entries($).filter(([I])=>we.has(I)));return{messages:S,...h===void 0?{}:{messageIds:h.map(({id:I})=>I)},messageVisibility:h?.map(({visibility:I})=>I)??S.map(()=>"visible"),turnVisibility:yn(),stats:r.getSessionStats(),state:{model:oe(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{...g.displaySnapshot()},toolGroupSummaries:Ae,turnReplies:j.snapshot(),workingActivity:F.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),Se=n(e=>{const r=e.role==="controller"?X.values().next().value:void 0;g.sendFrame(e,{type:"welcome",snapshot:Re(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:Y()},!0)},"sendWelcome"),Me=n(e=>{const r=[...X.values()];for(let c=1;c<r.length;c++)g.sendFrame(e,r[c].request)},"replayExtraPendingDialogsTo"),ne=n(()=>{try{const e=f.session();j.seed(ie(e,R)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){T({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}g.forEachHelloed(Se)},"reWelcomeAll"),_e=n(async e=>{if(!N){N=!0,Q().stop(),O.persistPendingSummary(),F.dispose(),et();try{H?.close()}catch{}s.close(),g.dispose();try{ye(K)&&be(K)}catch{}g.clearAttachState(),await ze(),process.exit(e)}},"completeExit"),q=n((e,r=0)=>{if(N)return;const c=e==="shutdown-hook"||e==="shutdown-after-settle";if(c&&O.finishOpenToolGroup(!0),c&&(O.hasSummaryTasks()||j.hasTasks())){if(de)return;de=!0,Promise.allSettled([O.waitForSummaryTasks(),j.waitForTasks()]).finally(()=>_e(r));return}_e(r)},"disposeAndExit");le=it({writable:n(()=>g.writableClients(),"writable"),forward:n((e,r)=>g.sendFrame(e,r),"forward"),pending:X,broadcast:n(e=>g.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>F.knownStreamWait(e),"onKnownStreamWait")}),f.setRebindSession(),await f.enqueueRebind(U,A),d("broker.startup.extensions_bound");const M=Fn({nodeId:t,registry:g,toolGroups:O,projection:F,rebind:f,boundaryReviewId:R,pendingDialogs:X,sendWelcome:Se,replayExtraPendingDialogsTo:Me,reWelcomeAll:ne,disposeAndExit:q,persistModelChoice:ge,broadcastModelChanged:ve,registryOf:se,formatModelSpec:B,formatExactModelSpec:Qn,turnAdmission:ee,memoryInventory:y,runNode:k,onKickoffAdmitted:L.releaseKickoff});ce=M.notifyTurnAccepted,me=M.resetForSession,ue=M.pendingPromptDispatches;const xe=2500;let te=!1;const Ce=n(async e=>{if(N||te)return;if(te=!0,f.isAgentRunActive()||f.session().isStreaming||M.pendingPromptDispatches()>0){const c=Date.now()+xe;for(;M.pendingPromptDispatches()>0&&!f.session().isStreaming&&Date.now()<c;)await new Promise(v=>setTimeout(v,25));if(f.session().isStreaming){const v=c-Date.now();if(v>0){let h;try{Gn(),await Promise.race([f.session().abort().then(()=>!0,()=>!1),new Promise($=>{h=setTimeout(()=>$(!1),v)})])&&await ke(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(M.pendingPromptDispatches()>0||f.isAgentRunActive())&&await ke(t,{event:"interrupted"})}q(e)},"abortAndExit");if(b=n(e=>{Ce(e)},"signalTeardown"),C!==void 0){b(C);return}try{ye(K)&&be(K)}catch{}H=Ue(e=>{const r=g.create(e);e.on("data",v=>{let h;try{h=r.decoder.push(v)}catch(S){S instanceof zn?(g.sendFrame(r,{type:"error",code:"frame_overflow",message:S.message}),g.dropClient(r,`frame overflow: ${S.message}`)):g.dropClient(r,`decoder error: ${String(S)}`);return}for(const S of h)try{Ln(M,r,S)}catch{}});const c=n(()=>{g.removeClient(r)},"drop");e.on("close",c),e.on("error",()=>{})}),H.on("error",e=>{N||(T({level:"error",event:"broker.socket.failed",error:e}),q("socket-error",1))}),H.listen(K,async()=>{Promise.all([z(t,{op:"clear",link:"viewer\u2194broker"}),z(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await W.recoverOnStartup()}catch(r){T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),q("recovery-startup-failed",1);return}if(!(N||te))if(e!=="retry-armed"&&u.firstPrompt!==void 0&&u.firstPrompt!==""){const r=Wn(process.env[qn]);r!==null&&Vn(u.firstPrompt,r);const c=process.env.CRTR_KICKOFF_MESSAGE_IDS;M.kickoff(u.firstPrompt,c?JSON.parse(c):[])}else L.releaseKickoff()}),g.persistAttachState()}n(lr,"runBroker");function tt(t){const o=new Set;for(const i of t)if(!(i.role!=="assistant"||!Array.isArray(i.content)))for(const m of i.content)m!==null&&typeof m=="object"&&m.type==="toolCall"&&typeof m.id=="string"&&o.add(m.id);return o}n(tt,"toolCallIds");function ie(t,o){const i=t.sessionManager,m=hn(i);return m!==void 0&&$n(m.map(({message:s})=>s)),m===void 0?void 0:wn(m,{boundaryReviewId:o,sessionEntries:i.getEntries?.()})}n(ie,"snapshotMessages");function Ee(){const t=Ne();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(Ee,"currentBrokerNodeId");async function rt(t,o){const i=cn(o.model,Ie(),o.modelExact===!0);if(i===void 0)return;const m=se(t),s={cwd:De()??o.cwd,profileId:Fe()},a=fn(i,m,s);if(a!==void 0)throw await z(Ee(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const l=mn(i,s.cwd,s.profileId),d=un(i.spec);for(const p of l){const _=m.find(p.providerId,p.modelId);if(_===void 0)continue;const w=d?.providerId===p.providerId&&d.modelId===p.modelId?d.thinkingLevel??(p.thinkingLevel===void 0?void 0:"off"):p.thinkingLevel;return{model:_,thinkingLevel:w}}if(o.modelExact===!0){const p=l.map(_=>`'${_.providerId}/${_.modelId}' unregistered`).join("; ");throw await z(Ee(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${o.model}' is unavailable \u2014 refusing to substitute (${p})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}T({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:l.map(p=>({provider:p.providerId,model:p.modelId,reason:"unregistered"})).slice(0,16)}})}n(rt,"resolveLaunchModel");function ot(t){let o=!0;return{runtime:new Proxy(t,{get(m,s,a){return o&&s==="getAvailableSnapshot"?()=>[]:o&&s==="getAvailable"?async()=>[]:o&&s==="getModel"?()=>{}:Reflect.get(m,s,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(ot,"modelLessRegistry");async function st(t,o){const i=Y(),m=n(async w=>{const u=await Ve.create({credentials:new dn,modelsPath:Te(w.agentDir,"models.json")});ln(u);const y=await t.createAgentSessionServices({cwd:w.cwd,agentDir:w.agentDir,modelRuntime:u,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(P=>({...P,extensions:P.extensions.filter(R=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(R.path))}),"extensionsOverride")}}),b=y.resourceLoader.getExtensions();if(o.extensionPaths.some(P=>re.includes(P))){const P=new Set(b.extensions.map(k=>k.path)),R=re.filter(k=>!P.has(k));if(R.length>0){const k=b.errors.filter(D=>re.includes(D.path)).map(D=>`${D.path}: ${D.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${R.join(", ")}${k===""?"":` (${k})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const C=await rt(y,o),V=C?.model,U=C?.thinkingLevel,A=C===void 0?ot(y.modelRuntime):void 0,ae=A!==void 0?{...y,modelRuntime:A.runtime}:y,G=await t.createAgentSessionFromServices({services:ae,sessionManager:w.sessionManager,model:V,thinkingLevel:U,...nt(o.tools,Le()),sessionStartEvent:w.sessionStartEvent});return Bn(G.session),an(G.session),A?.reveal(),{...G,services:y}},"buildForManager"),s=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(s===void 0||s==="")&&o.resumeSessionId!==void 0&&o.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${o.resumeSessionId}' (pi_session_file was never captured for this node)`);const l=!a&&s!==void 0&&s!=="",d=l&&o.newCycle===!0,p=l&&!d;let _;if(a)_=t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(p||d){if(_=t.SessionManager.open(s),d){const w=_.getLeafId();_.resetLeaf(),_.appendCustomEntry(vn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:w})}}else _=t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const w=n(async y=>{const b=await m({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...b,diagnostics:b.services.diagnostics??[]}},"factory"),u=await t.createAgentSessionRuntime(w,{cwd:o.cwd,agentDir:i,sessionManager:_});return{session:u.session,services:u.services,resuming:p,runtime:u}}const E=await m({cwd:o.cwd,agentDir:i,sessionManager:_});return{session:E.session,services:E.services,resuming:p,runtime:void 0}}n(st,"buildBrokerSession");function it(t){const o=n((s,a,l,d)=>{if(d?.signal?.aborted)return Promise.resolve(s);const p=t.writable();return p.length===0?Promise.resolve(s):new Promise(_=>{let E;const w=n(()=>{E!==void 0&&clearTimeout(E),d?.signal?.removeEventListener("abort",u),t.pending.delete(a.id)},"cleanup"),u=n(()=>{w(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),_(s)},"onAbort");d?.signal?.addEventListener("abort",u,{once:!0});const y=d?.timeout!==void 0?d.timeout:Zn;E=setTimeout(()=>{w(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),_(s)},y),typeof E.unref=="function"&&E.unref(),t.pending.set(a.id,{request:a,resolve:n(b=>{w(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),_(l(b))},"resolve")});for(const b of p)t.forward(b,a)})},"dialogPromise"),i=n(()=>{},"noop");return{[pn]:t.onKnownStreamWait??(s=>()=>{}),get theme(){const s=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(s==null)throw new Error("Theme not initialized. Call initTheme() first.");return s},select:n((s,a,l)=>o(void 0,{type:"extension_ui_request",id:x(),method:"select",title:s,options:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"select"),confirm:n((s,a,l)=>o(!1,{type:"extension_ui_request",id:x(),method:"confirm",title:s,message:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,l),"confirm"),input:n((s,a,l)=>o(void 0,{type:"extension_ui_request",id:x(),method:"input",title:s,placeholder:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"input"),editor:n((s,a)=>o(void 0,{type:"extension_ui_request",id:x(),method:"editor",title:s,prefill:a},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0),"editor"),setStatus:n((s,a)=>t.broadcast({type:"extension_ui_request",id:x(),method:"setStatus",statusKey:s,statusText:a}),"setStatus"),setWidget:n((s,a,l)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:x(),method:"setWidget",widgetKey:s,widgetLines:a,widgetPlacement:l?.placement})},"setWidget"),setTitle:n(s=>t.broadcast({type:"extension_ui_request",id:x(),method:"setTitle",title:s}),"setTitle"),notify:n((s,a)=>{const l=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:x(),method:"notify",message:s,notifyType:l})},"notify"),onTerminalInput:n(()=>i,"onTerminalInput"),setWorkingMessage:i,setWorkingVisible:i,setWorkingIndicator:i,setHiddenThinkingLabel:i,setFooter:i,setHeader:i,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:i,setEditorText:i,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:i,setEditorComponent:i,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:i,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:i}}n(it,"makeBrokerUiContext");export{fr as REVIEW_BOUNDARY_NAVIGATION_CODE,ur as ReviewBoundaryNavigationError,nt as brokerToolOptions,st as buildBrokerSession,et as disposeActiveSession,it as makeBrokerUiContext,lr as runBroker,ie as snapshotMessages};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.425",
|
|
4
4
|
"description": "crtr — agent runtime with memory, plugins, and marketplaces",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -137,7 +137,7 @@
|
|
|
137
137
|
},
|
|
138
138
|
"license": "UNLICENSED",
|
|
139
139
|
"dependencies": {
|
|
140
|
-
"@north-light/identity": "0.3.
|
|
140
|
+
"@north-light/identity": "0.3.425",
|
|
141
141
|
"@earendil-works/pi-agent-core": "1.1.0",
|
|
142
142
|
"@earendil-works/pi-ai": "1.1.0",
|
|
143
143
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
package/runtime.lock.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@north-light/cli",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.425",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "@north-light/cli",
|
|
9
|
-
"version": "0.3.
|
|
9
|
+
"version": "0.3.425",
|
|
10
10
|
"hasInstallScript": true,
|
|
11
11
|
"license": "UNLICENSED",
|
|
12
12
|
"workspaces": [
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"@earendil-works/pi-ai": "1.1.0",
|
|
19
19
|
"@earendil-works/pi-coding-agent": "1.1.0",
|
|
20
20
|
"@earendil-works/pi-tui": "1.1.0",
|
|
21
|
-
"@north-light/identity": "0.3.
|
|
21
|
+
"@north-light/identity": "0.3.425",
|
|
22
22
|
"cron-parser": "^5.6.0",
|
|
23
23
|
"esbuild": "^0.27.7",
|
|
24
24
|
"jose": "^6.2.12",
|
|
@@ -12095,17 +12095,17 @@
|
|
|
12095
12095
|
},
|
|
12096
12096
|
"packages/crouter-api": {
|
|
12097
12097
|
"name": "@north-light/api",
|
|
12098
|
-
"version": "0.3.
|
|
12098
|
+
"version": "0.3.425",
|
|
12099
12099
|
"license": "UNLICENSED"
|
|
12100
12100
|
},
|
|
12101
12101
|
"packages/crouter-env-docker": {
|
|
12102
12102
|
"name": "@north-light/env-docker",
|
|
12103
|
-
"version": "0.3.
|
|
12103
|
+
"version": "0.3.425",
|
|
12104
12104
|
"license": "UNLICENSED"
|
|
12105
12105
|
},
|
|
12106
12106
|
"packages/crouter-identity": {
|
|
12107
12107
|
"name": "@north-light/identity",
|
|
12108
|
-
"version": "0.3.
|
|
12108
|
+
"version": "0.3.425",
|
|
12109
12109
|
"license": "UNLICENSED",
|
|
12110
12110
|
"dependencies": {
|
|
12111
12111
|
"jose": "^6.2.1"
|
|
@@ -12113,20 +12113,20 @@
|
|
|
12113
12113
|
},
|
|
12114
12114
|
"packages/crouter-plugin": {
|
|
12115
12115
|
"name": "@north-light/plugin",
|
|
12116
|
-
"version": "0.3.
|
|
12116
|
+
"version": "0.3.425",
|
|
12117
12117
|
"license": "UNLICENSED",
|
|
12118
12118
|
"dependencies": {
|
|
12119
|
-
"@north-light/api": "0.3.
|
|
12120
|
-
"@north-light/identity": "0.3.
|
|
12119
|
+
"@north-light/api": "0.3.425",
|
|
12120
|
+
"@north-light/identity": "0.3.425"
|
|
12121
12121
|
}
|
|
12122
12122
|
},
|
|
12123
12123
|
"packages/crouter-sdk": {
|
|
12124
12124
|
"name": "@north-light/sdk",
|
|
12125
|
-
"version": "0.3.
|
|
12125
|
+
"version": "0.3.425",
|
|
12126
12126
|
"license": "UNLICENSED",
|
|
12127
12127
|
"dependencies": {
|
|
12128
|
-
"@north-light/api": "0.3.
|
|
12129
|
-
"@north-light/identity": "0.3.
|
|
12128
|
+
"@north-light/api": "0.3.425",
|
|
12129
|
+
"@north-light/identity": "0.3.425",
|
|
12130
12130
|
"jose": "^6.2.1"
|
|
12131
12131
|
},
|
|
12132
12132
|
"bin": {
|