@north-light/cli 0.3.557 → 0.3.558

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.
@@ -104,8 +104,11 @@ export declare class FaultRetry {
104
104
  * in production (session-file identity and the new-cycle guard already rule
105
105
  * it out below), so it is treated the same as "no progress" rather than
106
106
  * blocking the ladder. Returns 'retry-armed' when the timer now owns the
107
- * first turn, 'none' when the caller's default kickoff should proceed. */
108
- recoverOnStartup(): Promise<'retry-armed' | 'none'>;
107
+ * first turn, 'fatal' when the episode had already used its whole retry
108
+ * budget and was settled as a fatal fault (no turn runs; the caller's
109
+ * default kickoff must not), 'none' when the caller's default kickoff should
110
+ * proceed. */
111
+ recoverOnStartup(): Promise<'retry-armed' | 'fatal' | 'none'>;
109
112
  /** True iff the branch segment strictly after `anchorEntryId` (root→leaf,
110
113
  * anchor exclusive) contains an assistant message with non-empty content or
111
114
  * a tool result — the two shapes a runtime card and a `content: []`
@@ -113,7 +116,11 @@ export declare class FaultRetry {
113
116
  * branch cannot be distinguished from "no progress" here; callers treat it
114
117
  * as no progress rather than as a positive finding. */
115
118
  private hasProgressPastAnchor;
116
- schedule(): Promise<void>;
119
+ /** Arms the retry timer when one is owed. Reports what now owns the episode:
120
+ * 'armed' (a timer is armed), 'exhausted' (the episode had no retries left
121
+ * and was settled as a fatal fault), or 'none' (nothing is armed). */
122
+ schedule(): Promise<'armed' | 'exhausted' | 'none'>;
123
+ private settleExhausted;
117
124
  /** A run node's retry would land past its turn's retry window: complete the
118
125
  * turn with its error now and end the episode, so no recovery turn answers a
119
126
  * turn the app already saw complete. The app's next message is a fresh turn
@@ -1 +1 @@
1
- var ue=Object.defineProperty;var m=(i,e)=>ue(i,"name",{value:e,configurable:!0});import{envModelIntent as j,envNodeCwd as Y,envProfileId as q}from"../../../shared/env.js";import{isContextOverflow as V}from"@earendil-works/pi-ai";import{classify as C}from"../../fault-classifier.js";import{isDaemonTransportApiError as X}from"../../../api/errors.js";import{isModelNotFoundError as fe,isProviderUnconfiguredError as pe}from"../fault.js";import{brokerRecovery as he,mutateBrokerFault as J,mutateBrokerProviderRetry as k}from"./daemon-ops.js";import{extractCoolingDeadline as me}from"../managed-provider-cooling.js";import{extractProviderFailureDetails as ge}from"../../provider-failure.js";import{expandModelCandidates as z,modelRequestFromConfig as H,probeRouteAvailability as ye}from"../../model-routes.js";import{operationIdContext as K}from"../../events/operation-id.js";import{emitEvent as F}from"../../events/emit.js";import{CONNECTION_FAULT_RECOVERY_BODY as ve,PROVIDER_FAULT_RECOVERY_BODY as we,RUN_CONNECTION_FAULT_RETRY_BODY as Fe,formatCard as Q,formatModelFallbackRecovery as be}from"../../../shared/generated-context.js";import{markFatalOnExhaust as O,nextFaultRetry as P,policyFor as Z}from"../fault-recovery.js";import{parseModelSpec as ee}from"../model-selection.js";import{endedByAbort as te}from"../session-cycles.js";import{resolveProviderCandidates as ke}from"../../subscription-state.js";import{announceMessageOrigin as ne}from"../stamp/channel.js";import{LLM_REFUSAL_DIAGNOSTIC as _e,refusalRetryAt as Ie}from"./model-adapter.js";import{isSafetyRefusal as re}from"../../llm/refusal.js";const Ee=2147483647,ie=3e4;function Re(i,e,t){const n=Date.parse(i);return!Number.isFinite(n)||t+e-n>ie}m(Re,"runTurnRetryExpired");class _ extends Error{static{m(this,"StaleOutcome")}}const Se=1e3,Ae=3e4;function Me(i,e){return i!=="connection"?we:e?Fe:ve}m(Me,"retryCardBody");function I(i){return{link:i.link,op:i.op,kind:i.kind,retry:i.retry,message:i.message,since:i.since,operation_id:i.operation_id,...i.anchor_entry_id===void 0?{}:{anchorEntryId:i.anchor_entry_id},...i.provider_error===void 0?{}:{providerError:i.provider_error}}}m(I,"policyFault");function se(i){return i instanceof Error?i.message:String(i)}m(se,"errorText");function oe(i){return X(i)||C("pi\u2192provider",i).disposition==="auto"}m(oe,"isTransientRejection");function A(i){return{link:i.link,op:i.op,kind:i.kind,retry:i.retry,message:i.message,...i.operation_id===void 0?{}:{operation_id:i.operation_id},...i.since===void 0?{}:{since:i.since},...i.anchorEntryId===void 0?{}:{anchor_entry_id:i.anchorEntryId},...i.providerError===void 0?{}:{provider_error:i.providerError}}}m(A,"faultInput");function ae(i,e){const t=m(n=>`${n.providerId}/${n.modelId}`===e.modelSpec,"onLiveModel");return(i.find(n=>t(n)&&n.thinkingLevel===e.thinkingLevel)??i.find(t))?.rank}m(ae,"liveRouteRank");function de(i){const e=C("pi\u2192provider",i),t=i.diagnostics?.some(n=>n.type===_e)??!1;return{classified:e,disposition:t?"fatal":e.disposition}}m(de,"settledProviderFault");function Qe(i,e){if(i.stopReason!=="error"||te(i)||re(i)||V(i,e))return!1;const{classified:t,disposition:n}=de(i);return n==="auto"&&(t.kind==="connection"||t.kind==="rate-limit"||t.kind==="overloaded")}m(Qe,"willDaemonRetry");const xe=/does not support assistant message prefill|conversation must end with a user message/i;function Te(i,e){return e&&xe.test(i)}m(Te,"isPrefillRejectionDuringEpisode");class Ze{static{m(this,"FaultRetry")}deps;timer=null;failedRetryRoutes=new Set;notFoundModels=new Set;providerFallbackInFlight=null;notFoundFallbackInFlight=null;stagedCapacityFailure=null;agentStarts=0;constructor(e){this.deps=e}clearTimer(){this.timer!==null&&(clearTimeout(this.timer),this.timer=null)}reset(){this.clearTimer(),this.deps.turnEnds?.abandon(),this.providerFallbackInFlight=null,this.notFoundFallbackInFlight=null,this.stagedCapacityFailure=null}abandonTurnEnd(){this.deps.turnEnds?.abandon()}state(){return he(this.deps.nodeId)}async recordFault(e){return(await J(this.deps.nodeId,{op:"record",input:e})).fault}async clearFault(e,t=!1){await J(this.deps.nodeId,{op:"clear",...e===void 0?{}:{link:e},...t?{preserve_episode:!0}:{}})}sessionId(e){const t=e.sessionManager.getSessionId?.();return typeof t=="string"&&t!==""?t:null}async clearEpisode(e){const t=this.sessionId(e);t!==null&&await k(this.deps.nodeId,{op:"clear",session_id:t})}onEvent(e){e.type==="agent_start"&&this.agentStarts++,this.maybeSwitchProviderForRetry(e),this.maybeFallbackOnUnusableModel(e)}isActiveAutoFault(e){return e===null||e.retry.disposition!=="auto"||e.retry.by!=="daemon"?!1:e.kind==="connection"||e.kind==="rate-limit"||e.kind==="overloaded"}async publishSettledProviderFault(e){const t={agentEnd:e.stagedProviderAgentEnd,watchdogAbort:e.stagedWatchdogAbort,refreshAbort:e.stagedRefreshAbort,overflowFailure:e.stagedOverflowFailure,capacityFailure:this.stagedCapacityFailure?.generation===e?this.stagedCapacityFailure:null};this.stagedCapacityFailure=null,e.stagedProviderAgentEnd=null,e.stagedWatchdogAbort=!1,e.stagedRefreshAbort=!1,e.stagedOverflowFailure=null;const n=this.agentStarts,r=m(()=>{if(this.deps.installedGeneration()!==e||this.agentStarts!==n)throw new _},"assertCurrent");try{await this.retryWhileDaemonUnreachable("settled turn fault write",()=>this.recordStagedOutcome(e,t,r),r)}catch(s){if(!(s instanceof _))throw s}}async retryWhileDaemonUnreachable(e,t,n){let r=Se;for(;;){try{await t();return}catch(s){if(!X(s))throw s;F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`${e} waiting for the daemon: ${s.message}`}})}await new Promise(s=>setTimeout(s,r)),r=Math.min(r*2,Ae),n()}}async recordStagedOutcome(e,t,n){const{agentEnd:r,watchdogAbort:s,refreshAbort:a,overflowFailure:l,capacityFailure:c}=t,o=e.session,f=m(async b=>{n(),await this.clearEpisode(b)},"clearEpisode"),g=m(async b=>{n(),await this.recordFault(b)},"recordFault"),p=m(async(b,ce)=>{n(),await this.recordPendingProviderFault(b,ce)},"recordPendingProviderFault"),y=await this.state(),u=y.fault,h=y.episode,E=this.sessionId(o),w=this.isActiveAutoFault(u)&&u.link==="pi\u2192provider"?u:h?.state==="admitted"&&h.session_id===E&&this.isActiveAutoFault(h.fault)?h.fault:null,v=w===null?null:{since:w.since,anchorEntryId:w.anchor_entry_id,attempt:w.retry.attempt},d=[...Array.isArray(r?.messages)?r.messages:[]].reverse().find(b=>typeof b=="object"&&b!==null&&b.role==="assistant");if(c!==null||l!==null){await f(o),await g({link:"pi\u2192provider",op:"context overflow recovery",kind:"context-overflow",retry:{disposition:"fatal"},message:c?.errorMessage??l.errorMessage,anchor_entry_id:o.sessionManager.getLeafId?.()??void 0});return}if(s&&d?.stopReason==="aborted"){await p(o,{link:"pi\u2192provider",op:"generation turn",kind:"connection",retry:{disposition:"auto",by:"daemon",...v?.attempt!==void 0?{attempt:v.attempt}:{}},message:typeof d.errorMessage=="string"?d.errorMessage:"engine error (no errorMessage recorded)",...v!==null?{since:v.since}:{},anchor_entry_id:this.retryAnchor(o,v?.anchorEntryId)});return}if(d?.stopReason!=="error"){d!==void 0&&await f(o);return}if(a){await f(o);return}if(re(d)){await f(o);return}const M=typeof d.errorMessage=="string"?d.errorMessage:"engine error (no errorMessage recorded)";if(te({stopReason:"error",errorMessage:M})){await f(o);return}const R=V(d,o.model?.contextWindow),x=de(d),D=v!==null&&x.disposition!=="auto"&&Te(M,!0),le=D?{kind:"connection",disposition:"auto"}:x.classified,S=D?"auto":x.disposition,L=me(d),N=Ie(d),G=ge(d),U=typeof d.provider=="string"&&d.provider!==""?d.provider:o.model?.provider,W=typeof d.model=="string"&&d.model!==""?d.model:o.model?.id,B=G===void 0||U===void 0||W===void 0?void 0:{provider:U,model:W,...G};R&&await f(o);const T={link:"pi\u2192provider",op:"generation turn",kind:R?"context-overflow":le.kind,retry:R?{disposition:"fatal"}:S==="auto"?{disposition:"auto",by:"daemon",...L!==void 0?{nextAt:new Date(L).toISOString()}:{},...v?.attempt!==void 0?{attempt:v.attempt}:{}}:{disposition:S,...N!==void 0?{nextAt:new Date(N).toISOString()}:{}},message:M,...!R&&S==="auto"&&v!==null?{since:v.since}:{},anchor_entry_id:!R&&S==="auto"?this.retryAnchor(o,v?.anchorEntryId):o.sessionManager.getLeafId?.()??void 0,...B===void 0?{}:{provider_error:B}};T.retry.disposition==="auto"?await p(o,T):(await f(o),await g(T))}retryAnchor(e,t){const n=e.sessionManager.getLeafId?.()??void 0;return t!==void 0&&!this.hasProgressPastAnchor(e,t)?t:n}async recoverOnStartup(){const e=this.deps.installedGeneration();if(e===void 0)return"none";const t=(await this.state()).episode,n=this.sessionId(e.session);if(this.deps.cfg.newCycle===!0)return t!==null&&n!==null&&t.session_id===n&&await k(this.deps.nodeId,{op:"invalidate",session_id:n}),"none";if(t===null||n===null||t.session_id!==n)return"none";if(t.state==="admitted")if(t.fault.anchor_entry_id!==void 0&&!this.hasProgressPastAnchor(e.session,t.fault.anchor_entry_id)){if(!(await k(this.deps.nodeId,{op:"reopen",session_id:n})).applied)return"none"}else return await this.clearEpisode(e.session),"none";else if(t.state!=="pending")return"none";return await this.recordFault(A(I(t.fault))),await this.schedule(),"retry-armed"}hasProgressPastAnchor(e,t){const n=e.sessionManager.getBranch(),r=n.findIndex(a=>a.id===t);return(r===-1?n:n.slice(r+1)).some(a=>{if(a.type!=="message")return!1;const{message:l}=a;return l.role==="toolResult"?!0:l.role==="assistant"&&Array.isArray(l.content)&&l.content.length>0})}async schedule(){const e=this.deps.installedGeneration(),t=this.deps.currentSession();if(t.isStreaming||this.timer!==null)return;if(e===void 0){this.abandonTurnEnd();return}const n=await this.state(),r=n.fault;if(!this.isActiveAutoFault(r)||this.sessionId(t)!==null&&!this.pendingEpisodeMatches(t,r,n)){this.clearTimer(),this.abandonTurnEnd();return}const s=Date.now(),a=this.faultRetryDelayMs(r,s);if(a!==null&&this.deps.turnEnds?.holding()===!0&&Re(r.since,a,s)){await this.endRunTurnOnFault(t,r,a);return}a!==null?this.clearAndArmFaultRetry(a,e):this.abandonTurnEnd()}async endRunTurnOnFault(e,t,n){this.clearTimer(),this.abandonTurnEnd(),F({level:"info",event:"broker.runtime.diagnostic",fields:{message:`run turn completed on provider fault: ${t.kind} retry in ${n}ms is past the ${ie}ms turn window (since ${t.since}, attempt ${t.retry.attempt??0})`}}),await this.clearEpisode(e),await this.clearFault("pi\u2192provider")}async rearmIfStranded(){if(this.timer!==null||this.deps.installedGeneration()===void 0)return;const e=this.deps.currentSession();if(e.isStreaming)return;const t=await this.state();!this.isActiveAutoFault(t.fault)||!this.pendingEpisodeMatches(e,t.fault,t)||await this.schedule()}maybeSwitchProviderForRetry(e){if(e.type!=="auto_retry_start")return;const t=C("pi\u2192provider",e.errorMessage??"").kind;if(t!=="rate-limit"&&t!=="connection"||this.providerFallbackInFlight!==null||this.deps.cfg.modelExact===!0)return;const n=this.deps.installedGeneration();if(n===void 0)return;const r=this.deps.currentSession(),s=this.deps.currentServices(),a=this.deps.formatModelSpec(r.model,r.thinkingLevel);if(a===null)return;const l=H(this.deps.cfg.model,j(),!1);if(l===void 0)return;const c=z(l,Y()??this.deps.cfg.cwd,q()),o=ee(a),f=ae(c,o),g=f===void 0?{route:void 0,capacityExhausted:!1}:this.nextEligibleFallbackRoute(c.slice(f+1),this.deps.registryOf(s),r.getContextUsage()?.tokens,u=>!this.failedRetryRoutes.has(u.routeId));if(g.route===void 0){g.capacityExhausted&&(this.stageCapacityFailure(n,r),queueMicrotask(()=>{this.deps.installedGeneration()===n&&this.deps.currentSession()===r&&r.abortRetry()}));return}const p=g.route,y=(async()=>{const u=this.deps.registryOf(s).find(p.providerId,p.modelId);if(!u||(await r.setModel(u),this.deps.installedGeneration()!==n||this.deps.currentSession()!==r))return;const h=`${p.providerId}/${p.modelId}`===o.modelSpec?o.thinkingLevel:p.thinkingLevel;r.setThinkingLevel(h??"off"),this.failedRetryRoutes.add(p.routeId),await this.deps.broadcastModelChanged(!1)})().catch(u=>{F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`provider route fallback failed: ${u instanceof Error?u.message:String(u)}`}})}).finally(()=>{this.deps.installedGeneration()===n&&(this.providerFallbackInFlight=null)});this.providerFallbackInFlight=y}maybeFallbackOnUnusableModel(e){if(e.type!=="message_end"||e.message.role!=="assistant"||e.message.stopReason!=="error")return;const t=pe(e.message.errorMessage??"");if(!t&&!fe(e.message.errorMessage??"")||this.deps.cfg.modelExact===!0||this.notFoundFallbackInFlight!==null)return;const n=this.deps.installedGeneration();if(n===void 0)return;const r=this.deps.currentSession(),s=this.deps.currentServices(),a=this.deps.formatModelSpec(r.model,r.thinkingLevel);if(a===null)return;const l=ee(a);this.notFoundModels.add(l.modelSpec);const c=H(this.deps.cfg.model,j(),!1),o=c?z(c,Y()??this.deps.cfg.cwd,q()):[],f=ae(o,l),g=f===void 0?{route:void 0,capacityExhausted:!1}:this.nextEligibleFallbackRoute(o.slice(f+1),this.deps.registryOf(s),r.getContextUsage()?.tokens,h=>!this.notFoundModels.has(`${h.providerId}/${h.modelId}`));if(g.route===void 0){g.capacityExhausted&&this.stageCapacityFailure(n,r);return}const p=g.route,y=`${p.providerId}/${p.modelId}${p.thinkingLevel?`:${p.thinkingLevel}`:""}`,u=(async()=>{const h=this.deps.registryOf(s).find(p.providerId,p.modelId);if(h===void 0){F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback skipped: ${y} is not registered`}});return}if(await r.setModel(h),this.deps.installedGeneration()!==n||this.deps.currentSession()!==r)return;r.setThinkingLevel(p.thinkingLevel??"off"),await this.deps.broadcastModelChanged();const E=this.deps.formatModelSpec(r.model,r.thinkingLevel)??y;if(F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback: ${a} unavailable \u2192 ${E}; re-driving turn`}}),await r.agent.waitForIdle(),this.deps.installedGeneration()!==n||this.deps.currentSession()!==r)return;t&&await this.clearFault("pi\u2192provider");const w=Q("recovery",{},be(a,E,t?"credential":"not-found"));ne(w,{type:"runtime",kind:"recovery"}),await this.deps.turnAdmission.admit(v=>K.fresh(()=>r.prompt(w,{preflightResult:v})))})().catch(h=>{F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback failed: ${h instanceof Error?h.message:String(h)}`}})}).finally(()=>{this.deps.installedGeneration()===n&&(this.notFoundFallbackInFlight=null)});this.notFoundFallbackInFlight=u}nextEligibleFallbackRoute(e,t,n,r){let s=0,a=0;for(const l of e){if(!r(l)||ke([{...l,...ye(l,t),automaticFallback:!0}]).candidates.length===0)continue;const c=t.find(l.providerId,l.modelId);if(c!==void 0){if(s++,this.targetCannotFitContext(c.contextWindow,n)){a++;continue}return{route:l,capacityExhausted:!1}}}return{route:void 0,capacityExhausted:s>0&&s===a}}targetCannotFitContext(e,t){return Number.isFinite(e)&&Number.isFinite(t)&&e<t}stageCapacityFailure(e,t){const n=t.getContextUsage()?.tokens;this.stagedCapacityFailure={generation:e,errorMessage:Number.isFinite(n)?`All available fallback models have context windows smaller than the current conversation (${n} tokens).`:"All available fallback models have context windows smaller than the current conversation."}}async recordPendingProviderFault(e,t){const n=this.sessionId(e);if(n===null){await this.recordFault(t);return}await k(this.deps.nodeId,{op:"record-pending",session_id:n,input:t})}pendingEpisodeMatches(e,t,n){const r=this.sessionId(e),s=n.episode;return r!==null&&s!==null&&s.state==="pending"&&s.session_id===r&&s.fault.fault_id===t.fault_id}faultRetryDelayMs(e,t){if(e.retry.nextAt!==void 0){const n=Date.parse(e.retry.nextAt)-t;return Number.isFinite(n)?Math.max(0,n):null}return P(I(e),t)?.delayMs??null}clearAndArmFaultRetry(e,t){if(this.deps.installedGeneration()!==t)return;this.clearTimer();const n=Math.min(Math.max(0,e),Ee),r=Math.max(0,e-n);this.timer=setTimeout(()=>{if(this.timer=null,this.deps.installedGeneration()===t){if(r>0){this.clearAndArmFaultRetry(r,t);return}this.runFaultRetry().catch(s=>{this.abandonTurnEnd(),F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry fire failed: ${s instanceof Error?s.message:String(s)}`}})})}},n),typeof this.timer.unref=="function"&&this.timer.unref()}async runFaultRetry(){await this.attemptFaultRetry()===void 0&&this.abandonTurnEnd()}async attemptFaultRetry(){const e=this.deps.installedGeneration();if(e===void 0)return;const t=e.session;if(t.isStreaming)return;const n=(await this.state()).fault;if(!this.isActiveAutoFault(n))return;let r=n;if(n.kind==="connection"&&this.deps.turnEnds===void 0){const y=await this.deps.retryProbe();if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming)return;const u=(await this.state()).fault;if(!this.isActiveAutoFault(u)||u.since!==n.since)return;if(!y)return this.clearAndArmFaultRetry(Z(u.kind).baseDelayMs,e),"rearmed";r=u}const s=this.deps.turnEnds!==void 0,a=r.retry.attempt??0,l=Z(r.kind);if(a>=l.max){await this.recordFault(A(O(I(r)))),await this.clearEpisode(t);return}const c=P(I(r),Date.now());if(c===null){await this.recordFault(A(O(I(r)))),await this.clearEpisode(t);return}if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t)return;let o,f;const g=await this.deps.turnAdmission.admit(async y=>{const u=(await this.state()).fault;if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming||!this.isActiveAutoFault(u)||u.since!==r.since){y();return}const h=this.sessionId(t);if(h===null){y();return}if(!(await k(this.deps.nodeId,{op:"admit",session_id:h,fault_id:u.fault_id,retry:c.fault.retry})).applied){y();return}const w=r.anchor_entry_id;if(w!==void 0&&(t.sessionManager.getLeafId?.()??null)!==w&&!this.hasProgressPastAnchor(t,w))try{const d=await t.navigateTree(w);if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t){y();return}d.cancelled||this.deps.reWelcomeAll()}catch(d){F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`fault retry rewind skipped: ${d instanceof Error?d.message:String(d)}`}})}const v=Q("recovery",s?{attempt:c.attempt}:{attempt:c.attempt,max:c.max},Me(r.kind,s));ne(v,{type:"runtime",kind:"recovery"}),this.deps.turnEnds?.beginRecovery();const $=this.agentStarts;try{await K.fresh(()=>t.prompt(v,{preflightResult:y}))}catch(d){o={error:d,faultId:u.fault_id,startsBefore:$},oe(d)||(f={code:"model_error",message:`recovery prompt rejected: ${se(d)}`});return}finally{this.deps.turnEnds?.recoveryReturned(f)}return"prompted"});if(o===void 0)return g;const p=await this.settleRejectedRecoveryPrompt(e,t,o);if(p==="stale")throw o.error;return p==="rearmed"?"rearmed":void 0}async settleRejectedRecoveryPrompt(e,t,n){const r=this.sessionId(t);if(r===null)return"stale";const s=m(()=>{if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming||this.agentStarts!==n.startsBefore)throw new _},"assertCurrent"),a=se(n.error),l=oe(n.error);try{let c;return await this.retryWhileDaemonUnreachable("rejected recovery prompt settlement",async()=>{s();const{episode:o}=await this.state();if(s(),o===null||o.state!=="admitted"||o.session_id!==r||o.fault.fault_id!==n.faultId)throw new _;const f=I(o.fault),g=l&&this.deps.turnEnds===void 0?P(f,Date.now()):null,p=g===null?O(l?f:{...f,kind:"other",message:`recovery prompt rejected: ${a}`}):{...f,retry:{...f.retry,nextAt:g.nextAt}};if(s(),!(await k(this.deps.nodeId,{op:"settle-rejected",session_id:r,fault_id:n.faultId,reopen:g!==null,input:A(p)})).applied)throw new _;c=g?.nextAt},s),c===void 0?(F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`recovery prompt rejected, ending the retry episode: ${a}`}}),"ended"):(F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`recovery prompt rejected before any turn started, retrying at ${c}: ${a}`}}),await this.schedule(),"rearmed")}catch(c){if(!(c instanceof _))throw c;return"stale"}}}export{Ze as FaultRetry,ie as RUN_TURN_RETRY_WINDOW_MS,Te as isPrefillRejectionDuringEpisode,Me as retryCardBody,Re as runTurnRetryExpired,de as settledProviderFault,Qe as willDaemonRetry};
1
+ var ue=Object.defineProperty;var m=(i,e)=>ue(i,"name",{value:e,configurable:!0});import{envModelIntent as B,envNodeCwd as j,envProfileId as Y}from"../../../shared/env.js";import{isContextOverflow as q}from"@earendil-works/pi-ai";import{classify as T}from"../../fault-classifier.js";import{isDaemonTransportApiError as V}from"../../../api/errors.js";import{isModelNotFoundError as fe,isProviderUnconfiguredError as pe}from"../fault.js";import{brokerRecovery as he,mutateBrokerFault as X,mutateBrokerProviderRetry as k}from"./daemon-ops.js";import{extractCoolingDeadline as me}from"../managed-provider-cooling.js";import{extractProviderFailureDetails as ge}from"../../provider-failure.js";import{expandModelCandidates as J,modelRequestFromConfig as z,probeRouteAvailability as ye}from"../../model-routes.js";import{operationIdContext as H}from"../../events/operation-id.js";import{emitEvent as F}from"../../events/emit.js";import{CONNECTION_FAULT_RECOVERY_BODY as ve,PROVIDER_FAULT_RECOVERY_BODY as we,RUN_CONNECTION_FAULT_RETRY_BODY as Fe,formatCard as K,formatModelFallbackRecovery as be}from"../../../shared/generated-context.js";import{markFatalOnExhaust as Q,nextFaultRetry as C,policyFor as Z}from"../fault-recovery.js";import{parseModelSpec as ee}from"../model-selection.js";import{endedByAbort as te}from"../session-cycles.js";import{resolveProviderCandidates as ke}from"../../subscription-state.js";import{announceMessageOrigin as ne}from"../stamp/channel.js";import{LLM_REFUSAL_DIAGNOSTIC as _e,refusalRetryAt as Ie}from"./model-adapter.js";import{isSafetyRefusal as re}from"../../llm/refusal.js";const Ee=2147483647,ie=3e4;function Re(i,e,t){const n=Date.parse(i);return!Number.isFinite(n)||t+e-n>ie}m(Re,"runTurnRetryExpired");class _ extends Error{static{m(this,"StaleOutcome")}}const Se=1e3,Ae=3e4;function Me(i,e){return i!=="connection"?we:e?Fe:ve}m(Me,"retryCardBody");function R(i){return{link:i.link,op:i.op,kind:i.kind,retry:i.retry,message:i.message,since:i.since,operation_id:i.operation_id,...i.anchor_entry_id===void 0?{}:{anchorEntryId:i.anchor_entry_id},...i.provider_error===void 0?{}:{providerError:i.provider_error}}}m(R,"policyFault");function se(i){return i instanceof Error?i.message:String(i)}m(se,"errorText");function oe(i){return V(i)||T("pi\u2192provider",i).disposition==="auto"}m(oe,"isTransientRejection");function O(i){return{link:i.link,op:i.op,kind:i.kind,retry:i.retry,message:i.message,...i.operation_id===void 0?{}:{operation_id:i.operation_id},...i.since===void 0?{}:{since:i.since},...i.anchorEntryId===void 0?{}:{anchor_entry_id:i.anchorEntryId},...i.providerError===void 0?{}:{provider_error:i.providerError}}}m(O,"faultInput");function ae(i,e){const t=m(n=>`${n.providerId}/${n.modelId}`===e.modelSpec,"onLiveModel");return(i.find(n=>t(n)&&n.thinkingLevel===e.thinkingLevel)??i.find(t))?.rank}m(ae,"liveRouteRank");function de(i){const e=T("pi\u2192provider",i),t=i.diagnostics?.some(n=>n.type===_e)??!1;return{classified:e,disposition:t?"fatal":e.disposition}}m(de,"settledProviderFault");function Qe(i,e){if(i.stopReason!=="error"||te(i)||re(i)||q(i,e))return!1;const{classified:t,disposition:n}=de(i);return n==="auto"&&(t.kind==="connection"||t.kind==="rate-limit"||t.kind==="overloaded")}m(Qe,"willDaemonRetry");const xe=/does not support assistant message prefill|conversation must end with a user message/i;function Te(i,e){return e&&xe.test(i)}m(Te,"isPrefillRejectionDuringEpisode");class Ze{static{m(this,"FaultRetry")}deps;timer=null;failedRetryRoutes=new Set;notFoundModels=new Set;providerFallbackInFlight=null;notFoundFallbackInFlight=null;stagedCapacityFailure=null;agentStarts=0;constructor(e){this.deps=e}clearTimer(){this.timer!==null&&(clearTimeout(this.timer),this.timer=null)}reset(){this.clearTimer(),this.deps.turnEnds?.abandon(),this.providerFallbackInFlight=null,this.notFoundFallbackInFlight=null,this.stagedCapacityFailure=null}abandonTurnEnd(){this.deps.turnEnds?.abandon()}state(){return he(this.deps.nodeId)}async recordFault(e){return(await X(this.deps.nodeId,{op:"record",input:e})).fault}async clearFault(e,t=!1){await X(this.deps.nodeId,{op:"clear",...e===void 0?{}:{link:e},...t?{preserve_episode:!0}:{}})}sessionId(e){const t=e.sessionManager.getSessionId?.();return typeof t=="string"&&t!==""?t:null}async clearEpisode(e){const t=this.sessionId(e);t!==null&&await k(this.deps.nodeId,{op:"clear",session_id:t})}onEvent(e){e.type==="agent_start"&&this.agentStarts++,this.maybeSwitchProviderForRetry(e),this.maybeFallbackOnUnusableModel(e)}isActiveAutoFault(e){return e===null||e.retry.disposition!=="auto"||e.retry.by!=="daemon"?!1:e.kind==="connection"||e.kind==="rate-limit"||e.kind==="overloaded"}async publishSettledProviderFault(e){const t={agentEnd:e.stagedProviderAgentEnd,watchdogAbort:e.stagedWatchdogAbort,refreshAbort:e.stagedRefreshAbort,overflowFailure:e.stagedOverflowFailure,capacityFailure:this.stagedCapacityFailure?.generation===e?this.stagedCapacityFailure:null};this.stagedCapacityFailure=null,e.stagedProviderAgentEnd=null,e.stagedWatchdogAbort=!1,e.stagedRefreshAbort=!1,e.stagedOverflowFailure=null;const n=this.agentStarts,r=m(()=>{if(this.deps.installedGeneration()!==e||this.agentStarts!==n)throw new _},"assertCurrent");try{await this.retryWhileDaemonUnreachable("settled turn fault write",()=>this.recordStagedOutcome(e,t,r),r)}catch(s){if(!(s instanceof _))throw s}}async retryWhileDaemonUnreachable(e,t,n){let r=Se;for(;;){try{await t();return}catch(s){if(!V(s))throw s;F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`${e} waiting for the daemon: ${s.message}`}})}await new Promise(s=>setTimeout(s,r)),r=Math.min(r*2,Ae),n()}}async recordStagedOutcome(e,t,n){const{agentEnd:r,watchdogAbort:s,refreshAbort:a,overflowFailure:l,capacityFailure:c}=t,o=e.session,f=m(async b=>{n(),await this.clearEpisode(b)},"clearEpisode"),g=m(async b=>{n(),await this.recordFault(b)},"recordFault"),p=m(async(b,ce)=>{n(),await this.recordPendingProviderFault(b,ce)},"recordPendingProviderFault"),y=await this.state(),u=y.fault,h=y.episode,I=this.sessionId(o),w=this.isActiveAutoFault(u)&&u.link==="pi\u2192provider"?u:h?.state==="admitted"&&h.session_id===I&&this.isActiveAutoFault(h.fault)?h.fault:null,v=w===null?null:{since:w.since,anchorEntryId:w.anchor_entry_id,attempt:w.retry.attempt},d=[...Array.isArray(r?.messages)?r.messages:[]].reverse().find(b=>typeof b=="object"&&b!==null&&b.role==="assistant");if(c!==null||l!==null){await f(o),await g({link:"pi\u2192provider",op:"context overflow recovery",kind:"context-overflow",retry:{disposition:"fatal"},message:c?.errorMessage??l.errorMessage,anchor_entry_id:o.sessionManager.getLeafId?.()??void 0});return}if(s&&d?.stopReason==="aborted"){await p(o,{link:"pi\u2192provider",op:"generation turn",kind:"connection",retry:{disposition:"auto",by:"daemon",...v?.attempt!==void 0?{attempt:v.attempt}:{}},message:typeof d.errorMessage=="string"?d.errorMessage:"engine error (no errorMessage recorded)",...v!==null?{since:v.since}:{},anchor_entry_id:this.retryAnchor(o,v?.anchorEntryId)});return}if(d?.stopReason!=="error"){d!==void 0&&await f(o);return}if(a){await f(o);return}if(re(d)){await f(o);return}const A=typeof d.errorMessage=="string"?d.errorMessage:"engine error (no errorMessage recorded)";if(te({stopReason:"error",errorMessage:A})){await f(o);return}const E=q(d,o.model?.contextWindow),M=de(d),$=v!==null&&M.disposition!=="auto"&&Te(A,!0),le=$?{kind:"connection",disposition:"auto"}:M.classified,S=$?"auto":M.disposition,D=me(d),L=Ie(d),N=ge(d),G=typeof d.provider=="string"&&d.provider!==""?d.provider:o.model?.provider,U=typeof d.model=="string"&&d.model!==""?d.model:o.model?.id,W=N===void 0||G===void 0||U===void 0?void 0:{provider:G,model:U,...N};E&&await f(o);const x={link:"pi\u2192provider",op:"generation turn",kind:E?"context-overflow":le.kind,retry:E?{disposition:"fatal"}:S==="auto"?{disposition:"auto",by:"daemon",...D!==void 0?{nextAt:new Date(D).toISOString()}:{},...v?.attempt!==void 0?{attempt:v.attempt}:{}}:{disposition:S,...L!==void 0?{nextAt:new Date(L).toISOString()}:{}},message:A,...!E&&S==="auto"&&v!==null?{since:v.since}:{},anchor_entry_id:!E&&S==="auto"?this.retryAnchor(o,v?.anchorEntryId):o.sessionManager.getLeafId?.()??void 0,...W===void 0?{}:{provider_error:W}};x.retry.disposition==="auto"?await p(o,x):(await f(o),await g(x))}retryAnchor(e,t){const n=e.sessionManager.getLeafId?.()??void 0;return t!==void 0&&!this.hasProgressPastAnchor(e,t)?t:n}async recoverOnStartup(){const e=this.deps.installedGeneration();if(e===void 0)return"none";const t=(await this.state()).episode,n=this.sessionId(e.session);if(this.deps.cfg.newCycle===!0)return t!==null&&n!==null&&t.session_id===n&&await k(this.deps.nodeId,{op:"invalidate",session_id:n}),"none";if(t===null||n===null||t.session_id!==n)return"none";if(t.state==="admitted")if(t.fault.anchor_entry_id!==void 0&&!this.hasProgressPastAnchor(e.session,t.fault.anchor_entry_id)){if(!(await k(this.deps.nodeId,{op:"reopen",session_id:n})).applied)return"none"}else return await this.clearEpisode(e.session),"none";else if(t.state!=="pending")return"none";await this.recordFault(O(R(t.fault)));const r=await this.schedule();return r==="armed"?"retry-armed":r==="exhausted"?"fatal":"none"}hasProgressPastAnchor(e,t){const n=e.sessionManager.getBranch(),r=n.findIndex(a=>a.id===t);return(r===-1?n:n.slice(r+1)).some(a=>{if(a.type!=="message")return!1;const{message:l}=a;return l.role==="toolResult"?!0:l.role==="assistant"&&Array.isArray(l.content)&&l.content.length>0})}async schedule(){const e=this.deps.installedGeneration(),t=this.deps.currentSession();if(t.isStreaming||this.timer!==null)return this.timer!==null?"armed":"none";if(e===void 0)return this.abandonTurnEnd(),"none";const n=await this.state(),r=n.fault;if(!this.isActiveAutoFault(r)||this.sessionId(t)!==null&&!this.pendingEpisodeMatches(t,r,n))return this.clearTimer(),this.abandonTurnEnd(),"none";const s=Date.now(),a=this.faultRetryDelayMs(r,s);return a!==null&&this.deps.turnEnds?.holding()===!0&&Re(r.since,a,s)?(await this.endRunTurnOnFault(t,r,a),"none"):a!==null?(this.clearAndArmFaultRetry(a,e),this.timer!==null?"armed":"none"):(this.abandonTurnEnd(),r.retry.nextAt!==void 0||this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming?"none":(await this.settleExhausted(t,r),"exhausted"))}async settleExhausted(e,t){await this.recordFault(O(Q(R(t)))),await this.clearEpisode(e)}async endRunTurnOnFault(e,t,n){this.clearTimer(),this.abandonTurnEnd(),F({level:"info",event:"broker.runtime.diagnostic",fields:{message:`run turn completed on provider fault: ${t.kind} retry in ${n}ms is past the ${ie}ms turn window (since ${t.since}, attempt ${t.retry.attempt??0})`}}),await this.clearEpisode(e),await this.clearFault("pi\u2192provider")}async rearmIfStranded(){if(this.timer!==null||this.deps.installedGeneration()===void 0)return;const e=this.deps.currentSession();if(e.isStreaming)return;const t=await this.state();!this.isActiveAutoFault(t.fault)||!this.pendingEpisodeMatches(e,t.fault,t)||await this.schedule()}maybeSwitchProviderForRetry(e){if(e.type!=="auto_retry_start")return;const t=T("pi\u2192provider",e.errorMessage??"").kind;if(t!=="rate-limit"&&t!=="connection"||this.providerFallbackInFlight!==null||this.deps.cfg.modelExact===!0)return;const n=this.deps.installedGeneration();if(n===void 0)return;const r=this.deps.currentSession(),s=this.deps.currentServices(),a=this.deps.formatModelSpec(r.model,r.thinkingLevel);if(a===null)return;const l=z(this.deps.cfg.model,B(),!1);if(l===void 0)return;const c=J(l,j()??this.deps.cfg.cwd,Y()),o=ee(a),f=ae(c,o),g=f===void 0?{route:void 0,capacityExhausted:!1}:this.nextEligibleFallbackRoute(c.slice(f+1),this.deps.registryOf(s),r.getContextUsage()?.tokens,u=>!this.failedRetryRoutes.has(u.routeId));if(g.route===void 0){g.capacityExhausted&&(this.stageCapacityFailure(n,r),queueMicrotask(()=>{this.deps.installedGeneration()===n&&this.deps.currentSession()===r&&r.abortRetry()}));return}const p=g.route,y=(async()=>{const u=this.deps.registryOf(s).find(p.providerId,p.modelId);if(!u||(await r.setModel(u),this.deps.installedGeneration()!==n||this.deps.currentSession()!==r))return;const h=`${p.providerId}/${p.modelId}`===o.modelSpec?o.thinkingLevel:p.thinkingLevel;r.setThinkingLevel(h??"off"),this.failedRetryRoutes.add(p.routeId),await this.deps.broadcastModelChanged(!1)})().catch(u=>{F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`provider route fallback failed: ${u instanceof Error?u.message:String(u)}`}})}).finally(()=>{this.deps.installedGeneration()===n&&(this.providerFallbackInFlight=null)});this.providerFallbackInFlight=y}maybeFallbackOnUnusableModel(e){if(e.type!=="message_end"||e.message.role!=="assistant"||e.message.stopReason!=="error")return;const t=pe(e.message.errorMessage??"");if(!t&&!fe(e.message.errorMessage??"")||this.deps.cfg.modelExact===!0||this.notFoundFallbackInFlight!==null)return;const n=this.deps.installedGeneration();if(n===void 0)return;const r=this.deps.currentSession(),s=this.deps.currentServices(),a=this.deps.formatModelSpec(r.model,r.thinkingLevel);if(a===null)return;const l=ee(a);this.notFoundModels.add(l.modelSpec);const c=z(this.deps.cfg.model,B(),!1),o=c?J(c,j()??this.deps.cfg.cwd,Y()):[],f=ae(o,l),g=f===void 0?{route:void 0,capacityExhausted:!1}:this.nextEligibleFallbackRoute(o.slice(f+1),this.deps.registryOf(s),r.getContextUsage()?.tokens,h=>!this.notFoundModels.has(`${h.providerId}/${h.modelId}`));if(g.route===void 0){g.capacityExhausted&&this.stageCapacityFailure(n,r);return}const p=g.route,y=`${p.providerId}/${p.modelId}${p.thinkingLevel?`:${p.thinkingLevel}`:""}`,u=(async()=>{const h=this.deps.registryOf(s).find(p.providerId,p.modelId);if(h===void 0){F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback skipped: ${y} is not registered`}});return}if(await r.setModel(h),this.deps.installedGeneration()!==n||this.deps.currentSession()!==r)return;r.setThinkingLevel(p.thinkingLevel??"off"),await this.deps.broadcastModelChanged();const I=this.deps.formatModelSpec(r.model,r.thinkingLevel)??y;if(F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback: ${a} unavailable \u2192 ${I}; re-driving turn`}}),await r.agent.waitForIdle(),this.deps.installedGeneration()!==n||this.deps.currentSession()!==r)return;t&&await this.clearFault("pi\u2192provider");const w=K("recovery",{},be(a,I,t?"credential":"not-found"));ne(w,{type:"runtime",kind:"recovery"}),await this.deps.turnAdmission.admit(v=>H.fresh(()=>r.prompt(w,{preflightResult:v})))})().catch(h=>{F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`${t?"unconfigured-provider":"not_found"} fallback failed: ${h instanceof Error?h.message:String(h)}`}})}).finally(()=>{this.deps.installedGeneration()===n&&(this.notFoundFallbackInFlight=null)});this.notFoundFallbackInFlight=u}nextEligibleFallbackRoute(e,t,n,r){let s=0,a=0;for(const l of e){if(!r(l)||ke([{...l,...ye(l,t),automaticFallback:!0}]).candidates.length===0)continue;const c=t.find(l.providerId,l.modelId);if(c!==void 0){if(s++,this.targetCannotFitContext(c.contextWindow,n)){a++;continue}return{route:l,capacityExhausted:!1}}}return{route:void 0,capacityExhausted:s>0&&s===a}}targetCannotFitContext(e,t){return Number.isFinite(e)&&Number.isFinite(t)&&e<t}stageCapacityFailure(e,t){const n=t.getContextUsage()?.tokens;this.stagedCapacityFailure={generation:e,errorMessage:Number.isFinite(n)?`All available fallback models have context windows smaller than the current conversation (${n} tokens).`:"All available fallback models have context windows smaller than the current conversation."}}async recordPendingProviderFault(e,t){const n=this.sessionId(e);if(n===null){await this.recordFault(t);return}await k(this.deps.nodeId,{op:"record-pending",session_id:n,input:t})}pendingEpisodeMatches(e,t,n){const r=this.sessionId(e),s=n.episode;return r!==null&&s!==null&&s.state==="pending"&&s.session_id===r&&s.fault.fault_id===t.fault_id}faultRetryDelayMs(e,t){if(e.retry.nextAt!==void 0){const n=Date.parse(e.retry.nextAt)-t;return Number.isFinite(n)?Math.max(0,n):null}return C(R(e),t)?.delayMs??null}clearAndArmFaultRetry(e,t){if(this.deps.installedGeneration()!==t)return;this.clearTimer();const n=Math.min(Math.max(0,e),Ee),r=Math.max(0,e-n);this.timer=setTimeout(()=>{if(this.timer=null,this.deps.installedGeneration()===t){if(r>0){this.clearAndArmFaultRetry(r,t);return}this.runFaultRetry().catch(s=>{this.abandonTurnEnd(),F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry fire failed: ${s instanceof Error?s.message:String(s)}`}})})}},n),typeof this.timer.unref=="function"&&this.timer.unref()}async runFaultRetry(){await this.attemptFaultRetry()===void 0&&this.abandonTurnEnd()}async attemptFaultRetry(){const e=this.deps.installedGeneration();if(e===void 0)return;const t=e.session;if(t.isStreaming)return;const n=(await this.state()).fault;if(!this.isActiveAutoFault(n))return;let r=n;if(n.kind==="connection"&&this.deps.turnEnds===void 0){const y=await this.deps.retryProbe();if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming)return;const u=(await this.state()).fault;if(!this.isActiveAutoFault(u)||u.since!==n.since)return;if(!y)return this.clearAndArmFaultRetry(Z(u.kind).baseDelayMs,e),"rearmed";r=u}const s=this.deps.turnEnds!==void 0,a=r.retry.attempt??0,l=Z(r.kind),c=a>=l.max?null:C(R(r),Date.now());if(c===null){await this.settleExhausted(t,r);return}if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t)return;let o,f;const g=await this.deps.turnAdmission.admit(async y=>{const u=(await this.state()).fault;if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming||!this.isActiveAutoFault(u)||u.since!==r.since){y();return}const h=this.sessionId(t);if(h===null){y();return}if(!(await k(this.deps.nodeId,{op:"admit",session_id:h,fault_id:u.fault_id,retry:c.fault.retry})).applied){y();return}const w=r.anchor_entry_id;if(w!==void 0&&(t.sessionManager.getLeafId?.()??null)!==w&&!this.hasProgressPastAnchor(t,w))try{const d=await t.navigateTree(w);if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t){y();return}d.cancelled||this.deps.reWelcomeAll()}catch(d){F({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`fault retry rewind skipped: ${d instanceof Error?d.message:String(d)}`}})}const v=K("recovery",s?{attempt:c.attempt}:{attempt:c.attempt,max:c.max},Me(r.kind,s));ne(v,{type:"runtime",kind:"recovery"}),this.deps.turnEnds?.beginRecovery();const P=this.agentStarts;try{await H.fresh(()=>t.prompt(v,{preflightResult:y}))}catch(d){o={error:d,faultId:u.fault_id,startsBefore:P},oe(d)||(f={code:"model_error",message:`recovery prompt rejected: ${se(d)}`});return}finally{this.deps.turnEnds?.recoveryReturned(f)}return"prompted"});if(o===void 0)return g;const p=await this.settleRejectedRecoveryPrompt(e,t,o);if(p==="stale")throw o.error;return p==="rearmed"?"rearmed":void 0}async settleRejectedRecoveryPrompt(e,t,n){const r=this.sessionId(t);if(r===null)return"stale";const s=m(()=>{if(this.deps.installedGeneration()!==e||this.deps.currentSession()!==t||t.isStreaming||this.agentStarts!==n.startsBefore)throw new _},"assertCurrent"),a=se(n.error),l=oe(n.error);try{let c;return await this.retryWhileDaemonUnreachable("rejected recovery prompt settlement",async()=>{s();const{episode:o}=await this.state();if(s(),o===null||o.state!=="admitted"||o.session_id!==r||o.fault.fault_id!==n.faultId)throw new _;const f=R(o.fault),g=l&&this.deps.turnEnds===void 0?C(f,Date.now()):null,p=g===null?Q(l?f:{...f,kind:"other",message:`recovery prompt rejected: ${a}`}):{...f,retry:{...f.retry,nextAt:g.nextAt}};if(s(),!(await k(this.deps.nodeId,{op:"settle-rejected",session_id:r,fault_id:n.faultId,reopen:g!==null,input:O(p)})).applied)throw new _;c=g?.nextAt},s),c===void 0?(F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`recovery prompt rejected, ending the retry episode: ${a}`}}),"ended"):(F({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`recovery prompt rejected before any turn started, retrying at ${c}: ${a}`}}),await this.schedule(),"rearmed")}catch(c){if(!(c instanceof _))throw c;return"stale"}}}export{Ze as FaultRetry,ie as RUN_TURN_RETRY_WINDOW_MS,Te as isPrefillRejectionDuringEpisode,Me as retryCardBody,Re as runTurnRetryExpired,de as settledProviderFault,Qe as willDaemonRetry};
@@ -1 +1 @@
1
- var Pe=Object.defineProperty;var n=(t,o)=>Pe(t,"name",{value:o,configurable:!0});import{envInboxBetweenTurns as Oe,envModelIntent as Ie,envNodeCwd as De,envNodeId as Ne,envProfileId as Fe,envScopes as Le,isSandboxedNode as $e,scopeAllowed as Be}from"../../shared/env.js";import{createServer as Ue}from"node:net";import{existsSync as ye,readFileSync as Ge,unlinkSync as be}from"node:fs";import{join as Te}from"node:path";import{randomUUID as M}from"node:crypto";import{mark as Ke}from"../timing.js";import{SUBMIT_RESULT_TOOL as je}from"./structured-output.js";import{installSessionManagerStorePatch as We}from"../conversation-store/index.js";import{getAgentDir as Y,ModelRegistry as qe,ModelRuntime as Ve}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Xe,viewSocketPath as He}from"../canvas/paths.js";import{bindBrokerEventSource as Ye}from"../events/source.js";import{emitEvent as T,flushBrokerLog as ze}from"../events/emit.js";import{operationIdContext as Je}from"../events/operation-id.js";import{findMissingPackagePaths as Qe}from"./package-health.js";import{installBrokerConfigSnapshot as Ze}from"../config.js";import{FRONT_DOOR_ENV as en}from"./front-door.js";import{CANVAS_EXTENSIONS as re,piInvocationToSdkConfig as nn}from"./launch.js";import{assertEngineVersion as tn,loadBrokerEngine as rn}from"./broker-sdk.js";import{initCrtrTheme as on}from"./crtr-theme.js";import{resolveBundledPiPackageDir as sn}from"./pi-cli.js";import{captureSessionChatCapabilities as an}from"./command-surface.js";import{InMemoryCredentialStore as dn}from"@earendil-works/pi-ai";import{configureBrokerModelRuntime as ln}from"./broker/model-adapter.js";import{mutateBrokerFault as z,recordBrokerTurn as Re}from"./broker/daemon-ops.js";import{modelRequestFromConfig as cn,expandModelCandidates as mn,parseModelSpec as un,unregisteredConcreteModel as fn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as pn}from"./stream-watchdog.js";import{probeOnline as gn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as vn,cycleAwareMessages as hn,endedByAbort as wn}from"./session-cycles.js";import{turnErrorOf as Sn}from"../llm/refusal.js";import{projectTranscript as _n}from"./session-visibility.js";import{currentTurnVisibility as yn}from"./turn-visibility.js";import{isUnknownModel as oe}from"./model-selection.js";import{BrokerClientRegistry as bn}from"./broker/client-registry.js";import{ToolGroupTracker as Tn}from"./broker/tool-groups.js";import{TurnReplyTracker as Rn}from"./broker/turn-replies.js";import{onNodeNamed as kn}from"./broker/node-named.js";import{FaultRetry as En,willDaemonRetry as Cn}from"./broker/fault-retry.js";import{RunTurnEnds as Mn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as xn}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as An,BROKER_RUN_TURN_BUSY as Pn}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as On,settleRunDeferredMail as In}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Dn}from"./broker/run-turn-queue.js";import{EventProjection as Nn}from"./broker/event-projection.js";import{createFrameDispatchContext as Fn,handleFrame as Ln}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as $n,installAdvertisedCommandInvocationContract as Bn}from"./advertised-command-invocation.js";import{RebindDriver as Un}from"./broker/rebind.js";import{beginRuntimeTeardown as Gn}from"./broker/extension-abort.js";import{receiveNodeToken as Kn}from"./broker/node-token.js";import{serveCliRelay as jn}from"./broker/cli-relay.js";import{setTurnCauseSource as Wn}from"./broker/turn-cause.js";import{decodeKickoffOrigin as qn,KICKOFF_ORIGIN_ENV as Vn}from"./stamp/protocol.js";import{announceMessageOrigin as Xn}from"./stamp/channel.js";import{brokerExtensionState as Hn,commitBrokerModel as Yn}from"./broker/daemon-ops.js";import{composerNames as zn}from"./broker/frame-memory-refs.js";import{FrameOverflowError as Jn,normalizeSnapshotTail as Qn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as pr,REVIEW_BOUNDARY_NAVIGATION_CODE as gr}from"./broker/frame-replies.js";function se(t){return new qe(t.modelRuntime)}n(se,"registryOf");function B(t,o){if(t==null||oe(t))return null;const i=o!==void 0&&o!==""&&o!=="off"?`:${o}`:"";return`${t.provider}/${t.id}${i}`}n(B,"formatModelSpec");function Zn(t,o){const i=B(t,void 0);return i===null?null:`${i}:${o===void 0||o===""?"off":o}`}n(Zn,"formatExactModelSpec");const et=12e4;let J=null;import{brokerSignalClient as Q}from"./broker/signal-stream.js";function nt(){Q().stop();const t=J;if(J=null,t!==null)try{t.dispose()}catch{}}n(nt,"disposeActiveSession");function tt(t,o){const i=Be(o,"crtr:act")?void 0:["bash"],u=t!==void 0&&t.length>0?[...new Set([...t,je])]:t===void 0?void 0:[...t];return{...u!==void 0?{tools:u}:{},...i!==void 0?{excludeTools:i}:{}}}n(tt,"brokerToolOptions");async function mr(t,o=process.hrtime.bigint(),i=new Date().toISOString()){Ye(t);const u=await Kn(),s=await jn(t,u);process.env.CRTR_API_SOCKET=s.path,Je.fresh(()=>{T({level:"info",event:"broker.startup.cli_entry",ts:i,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),T({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let l=null;const d=n((e,r=null)=>{a.has(e)||(a.add(e),Ke(e,{duration_ms:Number(process.hrtime.bigint()-o)/1e6}),T({level:"info",event:e,duration_ms:Number(process.hrtime.bigint()-o)/1e6,fields:{runtime_version:process.version,engine_version:l,model:r}}))},"emitStartupMilestone");process.env[en]="1",process.env.CRTR_BROKER_PID=String(process.pid),delete process.env.TMUX_PANE,delete process.env.TMUX,We(t);const p=await rn();tn(p.VERSION),l=p.VERSION;const S=Xe(t),k=Te(S,"broker-launch.json"),_=JSON.parse(Ge(k,"utf8"));if($e()){if(!_.configSnapshot)throw new Error("broker launch is missing its config snapshot");Ze(_.configSnapshot)}const f=nn(_);f.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const y=await zn(t);let b,x;const V=n(e=>{b!==void 0?b(e):x??=e},"onSignal");process.on("SIGTERM",()=>V("SIGTERM")),process.on("SIGINT",()=>V("SIGINT"));let{session:U,services:A,resuming:ae,runtime:G}=await it(p,f);d("broker.startup.session_built");const E=(await Hn(t)).node.review_binding?.review_id,R=Oe();J=U;const D=gn;try{process.env.PI_PACKAGE_DIR=sn(),on(A.settingsManager.getTheme(),Y(),!1)}catch(e){T({level:"error",event:"broker.theme.initialization_failed",error:e})}try{for(const e of Qe(Y()))T({level:"warn",event:"broker.startup.warning",fields:{stage:"package_health",source:e.source,resolved_path:e.resolved}})}catch{}const K=He(t),g=new bn(t),X=new Map,O=new Tn(t,e=>g.broadcast(e)),j=new Rn(t,e=>g.broadcast(e));kn(e=>g.broadcast({type:"node_named",...e}));let N=!1,de=!1,H,le,m,W;const Z=new Mn;let F,ce=n(()=>{},"notifyTurnAccepted"),me=n(()=>{},"resetFrameState");const ee=xn();let ue=n(()=>0,"pendingPromptDispatches"),fe;const L=Dn({runNode:R,session:n(()=>m.session(),"session"),isReplacing:n(()=>m.isReplacing(),"isReplacing"),pendingRebind:n(()=>m.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>m.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>ue(),"pendingDispatches"),turnAdmission:ee,prependDeferred:n(e=>On(t,e),"prependDeferred"),onError:n(e=>T({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")});Wn(()=>m.session());const pe=L.drain;f.firstPrompt!==void 0&&f.firstPrompt!==""&&L.holdForKickoff(),globalThis[An]=L.start,globalThis[Pn]=L.busy,m=new Un({nodeId:t,cfg:f,session:U,services:A,runtime:G,registry:g,toolGroups:O,turnReplies:j,transcriptMessages:n(e=>ie(e,E)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>le,"uiContext"),faultRetry:n(()=>W,"faultRetry"),projection:n(()=>F,"projection"),setActiveSession:n(e=>{if(J=e,fe?.(),R){let r="stop",c,v=!1;fe=e.subscribe(h=>{if(h.type==="agent_start"&&(r="stop",c=void 0,v=!1,Z.started()),h.type==="agent_end"){const w=[...h.messages??[]].reverse().find($=>$.role==="assistant");w&&(r=w.stopReason,c=wn(w)?void 0:Sn(w),v=w.role==="assistant"&&Cn(w,e.model?.contextWindow))}h.type==="agent_settled"&&(Z.settled(e.sessionManager,{stop_reason:r,...c?{error:c}:{}},v),In(t,e).catch(w=>{T({level:"error",event:"broker.run_deferred_mail.settle_failed",error:w})}),queueMicrotask(()=>{m.session()===e&&pe()}))})}},"setActiveSession"),disposeAndExit:n((e,r)=>q(e,r),"disposeAndExit"),onSessionRebind:n(()=>{me()},"onSessionRebind"),onReplacementIdle:n(()=>{R&&pe()},"onReplacementIdle"),reWelcomeAll:n(()=>ne(),"reWelcomeAll")});const ge=n(async(e,r=!1)=>{const c=m.session(),v=B(c.model,c.thinkingLevel);if(v===null)return null;const h=await Yn(t,{spec:v,...e!==void 0?{intent:e}:{},userSelected:r});return r&&(f.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,f.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",f.modelExact=!0)),h.modelOverride},"persistModelChoice"),ve=n(async(e=!0,r,c=!1)=>{const v=m.session(),h=B(v.model,v.thinkingLevel),w=e?await ge(r,c):h;g.broadcast({type:"model_changed",model:oe(v.model)?void 0:v.model,spec:w})},"broadcastModelChanged");W=new En({nodeId:t,cfg:f,retryProbe:D,currentSession:n(()=>m.session(),"currentSession"),currentServices:n(()=>m.services(),"currentServices"),installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:B,broadcastModelChanged:ve,turnAdmission:ee,reWelcomeAll:n(()=>ne(),"reWelcomeAll"),...R?{turnEnds:Z}:{}});const he=n(()=>{W.rearmIfStranded().catch(e=>{T({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");Q().subscribe("resync",he),Q().subscribe("fault-retry",he),F=new Nn({registry:g,faultRetry:W,installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),currentSession:n(()=>m.session(),"currentSession"),notifyTurnAccepted:n(()=>ce(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:B});const Ee=n(e=>{const r=m.session(),c=ie(r,E),v=Qn(e.snapshotTail),h=c===void 0||v===void 0?c:c.slice(-v),w=h?.map(({message:I})=>I)??r.sessionManager.buildSessionContext().messages,$=O.summaries(),_e=h!==void 0&&v!==void 0?rt(w):void 0,Ae=_e===void 0?$:Object.fromEntries(Object.entries($).filter(([I])=>_e.has(I)));return{messages:w,...h===void 0?{}:{messageIds:h.map(({id:I})=>I)},messageVisibility:h?.map(({visibility:I})=>I)??w.map(()=>"visible"),turnVisibility:yn(),stats:r.getSessionStats(),state:{model:oe(r.model)?void 0:r.model,thinkingLevel:r.thinkingLevel,isStreaming:r.isStreaming,isCompacting:r.isCompacting,steeringMode:r.steeringMode,followUpMode:r.followUpMode,sessionFile:r.sessionFile,sessionId:r.sessionId,sessionName:r.sessionName,autoCompactionEnabled:r.autoCompactionEnabled,messageCount:r.messages.length,pendingMessageCount:r.pendingMessageCount},display:{...g.displaySnapshot()},toolGroupSummaries:Ae,turnReplies:j.snapshot(),workingActivity:F.currentWorkingActivity(),queued:{steering:[...r.getSteeringMessages()],followUp:[...r.getFollowUpMessages()]}}},"buildSnapshot"),we=n(e=>{const r=e.role==="controller"?X.values().next().value:void 0;g.sendFrame(e,{type:"welcome",snapshot:Ee(e),role:e.role,pending_dialog:r!==void 0?r.request:null,agentDir:Y()},!0)},"sendWelcome"),Ce=n(e=>{const r=[...X.values()];for(let c=1;c<r.length;c++)g.sendFrame(e,r[c].request)},"replayExtraPendingDialogsTo"),ne=n(()=>{try{const e=m.session();j.seed(ie(e,E)?.map(({message:r})=>r)??e.sessionManager.buildSessionContext().messages)}catch(e){T({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}g.forEachHelloed(we)},"reWelcomeAll"),Se=n(async e=>{if(!N){N=!0,Q().stop(),O.persistPendingSummary(),F.dispose(),nt();try{H?.close()}catch{}s.close(),g.dispose();try{ye(K)&&be(K)}catch{}g.clearAttachState(),await ze(),process.exit(e)}},"completeExit"),q=n((e,r=0)=>{if(N)return;const c=e==="shutdown-hook"||e==="shutdown-after-settle";if(c&&O.finishOpenToolGroup(!0),c&&(O.hasSummaryTasks()||j.hasTasks())){if(de)return;de=!0,Promise.allSettled([O.waitForSummaryTasks(),j.waitForTasks()]).finally(()=>Se(r));return}Se(r)},"disposeAndExit");le=at({writable:n(()=>g.writableClients(),"writable"),forward:n((e,r)=>g.sendFrame(e,r),"forward"),pending:X,broadcast:n(e=>g.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>F.knownStreamWait(e),"onKnownStreamWait")}),m.setRebindSession(),await m.enqueueRebind(U,A),d("broker.startup.extensions_bound");const C=Fn({nodeId:t,registry:g,toolGroups:O,projection:F,rebind:m,boundaryReviewId:E,pendingDialogs:X,sendWelcome:we,replayExtraPendingDialogsTo:Ce,reWelcomeAll:ne,disposeAndExit:q,persistModelChoice:ge,broadcastModelChanged:ve,registryOf:se,formatModelSpec:B,formatExactModelSpec:Zn,turnAdmission:ee,memoryInventory:y,runNode:R,onKickoffAdmitted:L.releaseKickoff});ce=C.notifyTurnAccepted,me=C.resetForSession,ue=C.pendingPromptDispatches;const Me=2500;let te=!1;const xe=n(async e=>{if(N||te)return;if(te=!0,m.isAgentRunActive()||m.session().isStreaming||C.pendingPromptDispatches()>0){const c=Date.now()+Me;for(;C.pendingPromptDispatches()>0&&!m.session().isStreaming&&Date.now()<c;)await new Promise(v=>setTimeout(v,25));if(m.session().isStreaming){const v=c-Date.now();if(v>0){let h;try{Gn(),await Promise.race([m.session().abort().then(()=>!0,()=>!1),new Promise($=>{h=setTimeout(()=>$(!1),v)})])&&await Re(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(C.pendingPromptDispatches()>0||m.isAgentRunActive())&&await Re(t,{event:"interrupted"})}q(e)},"abortAndExit");if(b=n(e=>{xe(e)},"signalTeardown"),x!==void 0){b(x);return}try{ye(K)&&be(K)}catch{}H=Ue(e=>{const r=g.create(e);e.on("data",v=>{let h;try{h=r.decoder.push(v)}catch(w){w instanceof Jn?(g.sendFrame(r,{type:"error",code:"frame_overflow",message:w.message}),g.dropClient(r,`frame overflow: ${w.message}`)):g.dropClient(r,`decoder error: ${String(w)}`);return}for(const w of h)try{Ln(C,r,w)}catch{}});const c=n(()=>{g.removeClient(r)},"drop");e.on("close",c),e.on("error",()=>{})}),H.on("error",e=>{N||(T({level:"error",event:"broker.socket.failed",error:e}),q("socket-error",1))}),H.listen(K,async()=>{Promise.all([z(t,{op:"clear",link:"viewer\u2194broker"}),z(t,{op:"clear",link:"relay\u2194broker"})]).catch(r=>T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await W.recoverOnStartup()}catch(r){T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:r,fields:{operation:"recovery_startup"}}),q("recovery-startup-failed",1);return}if(!(N||te))if(e!=="retry-armed"&&f.firstPrompt!==void 0&&f.firstPrompt!==""){const r=qn(process.env[Vn]);r!==null&&Xn(f.firstPrompt,r);const c=process.env.CRTR_KICKOFF_MESSAGE_IDS;C.kickoff(f.firstPrompt,c?JSON.parse(c):[])}else L.releaseKickoff()}),g.persistAttachState()}n(mr,"runBroker");function rt(t){const o=new Set;for(const i of t)if(!(i.role!=="assistant"||!Array.isArray(i.content)))for(const u of i.content)u!==null&&typeof u=="object"&&u.type==="toolCall"&&typeof u.id=="string"&&o.add(u.id);return o}n(rt,"toolCallIds");function ie(t,o){const i=t.sessionManager,u=hn(i);return u!==void 0&&$n(u.map(({message:s})=>s)),u===void 0?void 0:_n(u,{boundaryReviewId:o,sessionEntries:i.getEntries?.()})}n(ie,"snapshotMessages");function ke(){const t=Ne();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(ke,"currentBrokerNodeId");async function ot(t,o){const i=cn(o.model,Ie(),o.modelExact===!0);if(i===void 0)return;const u=se(t),s={cwd:De()??o.cwd,profileId:Fe()},a=fn(i,u,s);if(a!==void 0)throw await z(ke(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const l=mn(i,s.cwd,s.profileId),d=un(i.spec);for(const p of l){const S=u.find(p.providerId,p.modelId);if(S===void 0)continue;const _=d?.providerId===p.providerId&&d.modelId===p.modelId?d.thinkingLevel??(p.thinkingLevel===void 0?void 0:"off"):p.thinkingLevel;return{model:S,thinkingLevel:_}}if(o.modelExact===!0){const p=l.map(S=>`'${S.providerId}/${S.modelId}' unregistered`).join("; ");throw await z(ke(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${o.model}' is unavailable \u2014 refusing to substitute (${p})`}}),new Error(`[broker] FATAL: exact-consult model '${o.model}' is unavailable`)}T({level:"warn",event:"broker.model.none_viable",fields:{rejected_candidates:l.map(p=>({provider:p.providerId,model:p.modelId,reason:"unregistered"})).slice(0,16)}})}n(ot,"resolveLaunchModel");function st(t){let o=!0;return{runtime:new Proxy(t,{get(u,s,a){return o&&s==="getAvailableSnapshot"?()=>[]:o&&s==="getAvailable"?async()=>[]:o&&s==="getModel"?()=>{}:Reflect.get(u,s,a)}}),reveal:n(()=>{o=!1},"reveal")}}n(st,"modelLessRegistry");async function it(t,o){const i=Y(),u=n(async _=>{const f=await Ve.create({credentials:new dn,modelsPath:Te(_.agentDir,"models.json")});ln(f);const y=await t.createAgentSessionServices({cwd:_.cwd,agentDir:_.agentDir,modelRuntime:f,resourceLoaderOptions:{additionalExtensionPaths:o.extensionPaths,appendSystemPrompt:o.appendSystemPromptPath!==void 0?[o.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(P=>({...P,extensions:P.extensions.filter(E=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(E.path))}),"extensionsOverride")}}),b=y.resourceLoader.getExtensions();if(o.extensionPaths.some(P=>re.includes(P))){const P=new Set(b.extensions.map(R=>R.path)),E=re.filter(R=>!P.has(R));if(E.length>0){const R=b.errors.filter(D=>re.includes(D.path)).map(D=>`${D.path}: ${D.error}`).join("; ");throw new Error(`[broker] FATAL: mandatory canvas extensions failed to load: ${E.join(", ")}${R===""?"":` (${R})`}`)}}y.settingsManager.getRetryEnabled=()=>!1;const x=await ot(y,o),V=x?.model,U=x?.thinkingLevel,A=x===void 0?st(y.modelRuntime):void 0,ae=A!==void 0?{...y,modelRuntime:A.runtime}:y,G=await t.createAgentSessionFromServices({services:ae,sessionManager:_.sessionManager,model:V,thinkingLevel:U,...tt(o.tools,Le()),sessionStartEvent:_.sessionStartEvent});return Bn(G.session),an(G.session),A?.reveal(),{...G,services:y}},"buildForManager"),s=o.resumeSessionPath,a=o.forkFrom!==void 0&&o.forkFrom!=="";if(!a&&(s===void 0||s==="")&&o.resumeSessionId!==void 0&&o.resumeSessionId!=="")throw new Error(`[broker] resume requires a session .jsonl PATH; got only a bare id '${o.resumeSessionId}' (pi_session_file was never captured for this node)`);const l=!a&&s!==void 0&&s!=="",d=l&&o.newCycle===!0,p=l&&!d;let S;if(a)S=await t.SessionManager.forkFrom(o.forkFrom,o.cwd);else if(p||d){if(S=await t.SessionManager.open(s),d){const _=S.getLeafId();S.resetLeaf(),S.appendCustomEntry(vn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:_})}}else S=await t.SessionManager.create(o.cwd);if(t.createAgentSessionRuntime!==void 0){const _=n(async y=>{const b=await u({cwd:y.cwd,agentDir:y.agentDir,sessionManager:y.sessionManager,sessionStartEvent:y.sessionStartEvent});return{...b,diagnostics:b.services.diagnostics??[]}},"factory"),f=await t.createAgentSessionRuntime(_,{cwd:o.cwd,agentDir:i,sessionManager:S});return{session:f.session,services:f.services,resuming:p,runtime:f}}const k=await u({cwd:o.cwd,agentDir:i,sessionManager:S});return{session:k.session,services:k.services,resuming:p,runtime:void 0}}n(it,"buildBrokerSession");function at(t){const o=n((s,a,l,d)=>{if(d?.signal?.aborted)return Promise.resolve(s);const p=t.writable();return p.length===0?Promise.resolve(s):new Promise(S=>{let k;const _=n(()=>{k!==void 0&&clearTimeout(k),d?.signal?.removeEventListener("abort",f),t.pending.delete(a.id)},"cleanup"),f=n(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(s)},"onAbort");d?.signal?.addEventListener("abort",f,{once:!0});const y=d?.timeout!==void 0?d.timeout:et;k=setTimeout(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(s)},y),typeof k.unref=="function"&&k.unref(),t.pending.set(a.id,{request:a,resolve:n(b=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(l(b))},"resolve")});for(const b of p)t.forward(b,a)})},"dialogPromise"),i=n(()=>{},"noop");return{[pn]:t.onKnownStreamWait??(s=>()=>{}),get theme(){const s=globalThis[Symbol.for("@earendil-works/pi-coding-agent:theme")];if(s==null)throw new Error("Theme not initialized. Call initTheme() first.");return s},select:n((s,a,l)=>o(void 0,{type:"extension_ui_request",id:M(),method:"select",title:s,options:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"select"),confirm:n((s,a,l)=>o(!1,{type:"extension_ui_request",id:M(),method:"confirm",title:s,message:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,l),"confirm"),input:n((s,a,l)=>o(void 0,{type:"extension_ui_request",id:M(),method:"input",title:s,placeholder:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"input"),editor:n((s,a)=>o(void 0,{type:"extension_ui_request",id:M(),method:"editor",title:s,prefill:a},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0),"editor"),setStatus:n((s,a)=>t.broadcast({type:"extension_ui_request",id:M(),method:"setStatus",statusKey:s,statusText:a}),"setStatus"),setWidget:n((s,a,l)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:M(),method:"setWidget",widgetKey:s,widgetLines:a,widgetPlacement:l?.placement})},"setWidget"),setTitle:n(s=>t.broadcast({type:"extension_ui_request",id:M(),method:"setTitle",title:s}),"setTitle"),notify:n((s,a)=>{const l=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:M(),method:"notify",message:s,notifyType:l})},"notify"),onTerminalInput:n(()=>i,"onTerminalInput"),setWorkingMessage:i,setWorkingVisible:i,setWorkingIndicator:i,setHiddenThinkingLabel:i,setFooter:i,setHeader:i,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:i,setEditorText:i,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:i,setEditorComponent:i,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:i,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:i}}n(at,"makeBrokerUiContext");export{gr as REVIEW_BOUNDARY_NAVIGATION_CODE,pr as ReviewBoundaryNavigationError,tt as brokerToolOptions,it as buildBrokerSession,nt as disposeActiveSession,at as makeBrokerUiContext,mr as runBroker,ie as snapshotMessages};
1
+ var Pe=Object.defineProperty;var n=(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 $e,scopeAllowed as Be}from"../../shared/env.js";import{createServer as Ue}from"node:net";import{existsSync as be,readFileSync as Ge,unlinkSync as ye}from"node:fs";import{join as Te}from"node:path";import{randomUUID as M}from"node:crypto";import{mark as Ke}from"../timing.js";import{SUBMIT_RESULT_TOOL as je}from"./structured-output.js";import{installSessionManagerStorePatch as We}from"../conversation-store/index.js";import{getAgentDir as Y,ModelRegistry as qe,ModelRuntime as Ve}from"@earendil-works/pi-coding-agent";import{nodeRunDir as Xe,viewSocketPath as He}from"../canvas/paths.js";import{bindBrokerEventSource as Ye}from"../events/source.js";import{emitEvent as T,flushBrokerLog as ze}from"../events/emit.js";import{operationIdContext as Je}from"../events/operation-id.js";import{findMissingPackagePaths as Qe}from"./package-health.js";import{installBrokerConfigSnapshot as Ze}from"../config.js";import{FRONT_DOOR_ENV as en}from"./front-door.js";import{CANVAS_EXTENSIONS as 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 Re}from"./broker/daemon-ops.js";import{modelRequestFromConfig as cn,expandModelCandidates as mn,parseModelSpec as un,unregisteredConcreteModel as fn}from"../model-routes.js";import{KNOWN_STREAM_WAIT_UI as pn}from"./stream-watchdog.js";import{probeOnline as gn}from"./connectivity.js";import{CRTR_CYCLE_CUSTOM_TYPE as vn,cycleAwareMessages as hn,endedByAbort as wn}from"./session-cycles.js";import{turnErrorOf as Sn}from"../llm/refusal.js";import{projectTranscript as _n}from"./session-visibility.js";import{currentTurnVisibility as bn}from"./turn-visibility.js";import{isUnknownModel as re}from"./model-selection.js";import{BrokerClientRegistry as yn}from"./broker/client-registry.js";import{ToolGroupTracker as Tn}from"./broker/tool-groups.js";import{TurnReplyTracker as Rn}from"./broker/turn-replies.js";import{onNodeNamed as kn}from"./broker/node-named.js";import{FaultRetry as En,willDaemonRetry as Cn}from"./broker/fault-retry.js";import{RunTurnEnds as Mn}from"./broker/run-turn-end.js";import{createTurnAdmissionGate as xn}from"./broker/turn-admission.js";import{BROKER_IDLE_TURN_START as An,BROKER_RUN_TURN_BUSY as Pn}from"./broker/held-deferred-inbox.js";import{prependRunDeferredMail as On,settleRunDeferredMail as In}from"./broker/run-deferred-mail.js";import{createRunTurnQueue as Dn}from"./broker/run-turn-queue.js";import{EventProjection as Nn}from"./broker/event-projection.js";import{createFrameDispatchContext as Fn,handleFrame as Ln}from"./broker/frame-dispatch.js";import{hydratePersistedAdvertisedCommandMessages as $n,installAdvertisedCommandInvocationContract as Bn}from"./advertised-command-invocation.js";import{RebindDriver as Un}from"./broker/rebind.js";import{beginRuntimeTeardown as Gn}from"./broker/extension-abort.js";import{receiveNodeToken as Kn}from"./broker/node-token.js";import{serveCliRelay as jn}from"./broker/cli-relay.js";import{setTurnCauseSource as Wn}from"./broker/turn-cause.js";import{decodeKickoffOrigin as qn,KICKOFF_ORIGIN_ENV as Vn}from"./stamp/protocol.js";import{announceMessageOrigin as Xn}from"./stamp/channel.js";import{brokerExtensionState as Hn,commitBrokerModel as Yn}from"./broker/daemon-ops.js";import{composerNames as zn}from"./broker/frame-memory-refs.js";import{FrameOverflowError as Jn,normalizeSnapshotTail as Qn}from"./broker-protocol.js";import{ReviewBoundaryNavigationError as go,REVIEW_BOUNDARY_NAVIGATION_CODE as vo}from"./broker/frame-replies.js";function se(t){return new qe(t.modelRuntime)}n(se,"registryOf");function B(t,r){if(t==null||re(t))return null;const i=r!==void 0&&r!==""&&r!=="off"?`:${r}`:"";return`${t.provider}/${t.id}${i}`}n(B,"formatModelSpec");function Zn(t,r){const i=B(t,void 0);return i===null?null:`${i}:${r===void 0||r===""?"off":r}`}n(Zn,"formatExactModelSpec");const et=12e4;let J=null;import{brokerSignalClient as Q}from"./broker/signal-stream.js";function nt(){Q().stop();const t=J;if(J=null,t!==null)try{t.dispose()}catch{}}n(nt,"disposeActiveSession");function tt(t,r){const i=Be(r,"crtr:act")?void 0:["bash"],u=t!==void 0&&t.length>0?[...new Set([...t,je])]:t===void 0?void 0:[...t];return{...u!==void 0?{tools:u}:{},...i!==void 0?{excludeTools:i}:{}}}n(tt,"brokerToolOptions");async function uo(t,r=process.hrtime.bigint(),i=new Date().toISOString()){Ye(t);const u=await Kn(),s=await jn(t,u);process.env.CRTR_API_SOCKET=s.path,Je.fresh(()=>{T({level:"info",event:"broker.startup.cli_entry",ts:i,duration_ms:0,fields:{runtime_version:process.version,engine_version:null,model:null}}),T({level:"info",event:"broker.startup.module_loaded",duration_ms:Number(process.hrtime.bigint()-r)/1e6,fields:{runtime_version:process.version,engine_version:null,model:null}})});const a=new Set;let l=null;const d=n((e,o=null)=>{a.has(e)||(a.add(e),Ke(e,{duration_ms:Number(process.hrtime.bigint()-r)/1e6}),T({level:"info",event:e,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 p=await on();tn(p.VERSION),l=p.VERSION;const S=Xe(t),k=Te(S,"broker-launch.json"),_=JSON.parse(Ge(k,"utf8"));if($e()){if(!_.configSnapshot)throw new Error("broker launch is missing its config snapshot");Ze(_.configSnapshot)}const f=nn(_);f.modelExact===!0?process.env.CRTR_MODEL_EXACT="1":delete process.env.CRTR_MODEL_EXACT;const b=await zn(t);let y,x;const V=n(e=>{y!==void 0?y(e):x??=e},"onSignal");process.on("SIGTERM",()=>V("SIGTERM")),process.on("SIGINT",()=>V("SIGINT"));let{session:U,services:A,resuming:ae,runtime:G}=await it(p,f);d("broker.startup.session_built");const E=(await Hn(t)).node.review_binding?.review_id,R=Oe();J=U;const D=gn;try{process.env.PI_PACKAGE_DIR=sn(),rn(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 yn(t),X=new Map,O=new Tn(t,e=>g.broadcast(e)),j=new Rn(t,e=>g.broadcast(e));kn(e=>g.broadcast({type:"node_named",...e}));let N=!1,de=!1,H,le,m,W;const Z=new Mn;let F,ce=n(()=>{},"notifyTurnAccepted"),me=n(()=>{},"resetFrameState");const ee=xn();let ue=n(()=>0,"pendingPromptDispatches"),fe;const L=Dn({runNode:R,session:n(()=>m.session(),"session"),isReplacing:n(()=>m.isReplacing(),"isReplacing"),pendingRebind:n(()=>m.pendingRebind(),"pendingRebind"),isAgentRunActive:n(()=>m.isAgentRunActive(),"isAgentRunActive"),pendingDispatches:n(()=>ue(),"pendingDispatches"),turnAdmission:ee,prependDeferred:n(e=>On(t,e),"prependDeferred"),onError:n(e=>T({level:"error",event:"broker.inbox.idle_prompt_failed",error:e}),"onError")});Wn(()=>m.session());const pe=L.drain;f.firstPrompt!==void 0&&f.firstPrompt!==""&&L.holdForKickoff(),globalThis[An]=L.start,globalThis[Pn]=L.busy,m=new Un({nodeId:t,cfg:f,session:U,services:A,runtime:G,registry:g,toolGroups:O,turnReplies:j,transcriptMessages:n(e=>ie(e,E)?.map(({message:o})=>o)??e.sessionManager.buildSessionContext().messages,"transcriptMessages"),uiContext:n(()=>le,"uiContext"),faultRetry:n(()=>W,"faultRetry"),projection:n(()=>F,"projection"),setActiveSession:n(e=>{if(J=e,fe?.(),R){let o="stop",c,v=!1;fe=e.subscribe(h=>{if(h.type==="agent_start"&&(o="stop",c=void 0,v=!1,Z.started()),h.type==="agent_end"){const w=[...h.messages??[]].reverse().find($=>$.role==="assistant");w&&(o=w.stopReason,c=wn(w)?void 0:Sn(w),v=w.role==="assistant"&&Cn(w,e.model?.contextWindow))}h.type==="agent_settled"&&(Z.settled(e.sessionManager,{stop_reason:o,...c?{error:c}:{}},v),In(t,e).catch(w=>{T({level:"error",event:"broker.run_deferred_mail.settle_failed",error:w})}),queueMicrotask(()=>{m.session()===e&&pe()}))})}},"setActiveSession"),disposeAndExit:n((e,o)=>q(e,o),"disposeAndExit"),onSessionRebind:n(()=>{me()},"onSessionRebind"),onReplacementIdle:n(()=>{R&&pe()},"onReplacementIdle"),reWelcomeAll:n(()=>ne(),"reWelcomeAll")});const ge=n(async(e,o=!1)=>{const c=m.session(),v=B(c.model,c.thinkingLevel);if(v===null)return null;const h=await Yn(t,{spec:v,...e!==void 0?{intent:e}:{},userSelected:o});return o&&(f.model=h.modelOverride,e!==void 0?(process.env.CRTR_MODEL_INTENT=`${e.family}/${e.strength}`,delete process.env.CRTR_MODEL_EXACT,f.modelExact=void 0):(delete process.env.CRTR_MODEL_INTENT,process.env.CRTR_MODEL_EXACT="1",f.modelExact=!0)),h.modelOverride},"persistModelChoice"),ve=n(async(e=!0,o,c=!1)=>{const v=m.session(),h=B(v.model,v.thinkingLevel),w=e?await ge(o,c):h;g.broadcast({type:"model_changed",model:re(v.model)?void 0:v.model,spec:w})},"broadcastModelChanged");W=new En({nodeId:t,cfg:f,retryProbe:D,currentSession:n(()=>m.session(),"currentSession"),currentServices:n(()=>m.services(),"currentServices"),installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),registryOf:se,formatModelSpec:B,broadcastModelChanged:ve,turnAdmission:ee,reWelcomeAll:n(()=>ne(),"reWelcomeAll"),...R?{turnEnds:Z}:{}});const he=n(()=>{W.rearmIfStranded().catch(e=>{T({level:"warn",event:"broker.runtime.diagnostic",fields:{message:`fault retry re-arm failed: ${e instanceof Error?e.message:String(e)}`}})})},"rearmStrandedRetry");Q().subscribe("resync",he),Q().subscribe("fault-retry",he),F=new Nn({registry:g,faultRetry:W,installedGeneration:n(()=>m.installedGeneration(),"installedGeneration"),currentSession:n(()=>m.session(),"currentSession"),notifyTurnAccepted:n(()=>ce(),"notifyTurnAccepted"),emitStartupMilestone:d,formatModelSpec:B});const Ee=n(e=>{const o=m.session(),c=ie(o,E),v=Qn(e.snapshotTail),h=c===void 0||v===void 0?c:c.slice(-v),w=h?.map(({message:I})=>I)??o.sessionManager.buildSessionContext().messages,$=O.summaries(),_e=h!==void 0&&v!==void 0?ot(w):void 0,Ae=_e===void 0?$:Object.fromEntries(Object.entries($).filter(([I])=>_e.has(I)));return{messages:w,...h===void 0?{}:{messageIds:h.map(({id:I})=>I)},messageVisibility:h?.map(({visibility:I})=>I)??w.map(()=>"visible"),turnVisibility:bn(),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:{...g.displaySnapshot()},toolGroupSummaries:Ae,turnReplies:j.snapshot(),workingActivity:F.currentWorkingActivity(),queued:{steering:[...o.getSteeringMessages()],followUp:[...o.getFollowUpMessages()]}}},"buildSnapshot"),we=n(e=>{const o=e.role==="controller"?X.values().next().value:void 0;g.sendFrame(e,{type:"welcome",snapshot:Ee(e),role:e.role,pending_dialog:o!==void 0?o.request:null,agentDir:Y()},!0)},"sendWelcome"),Ce=n(e=>{const o=[...X.values()];for(let c=1;c<o.length;c++)g.sendFrame(e,o[c].request)},"replayExtraPendingDialogsTo"),ne=n(()=>{try{const e=m.session();j.seed(ie(e,E)?.map(({message:o})=>o)??e.sessionManager.buildSessionContext().messages)}catch(e){T({level:"debug",event:"broker.runtime.diagnostic",fields:{message:`turn reply reseed failed: ${String(e)}`}})}g.forEachHelloed(we)},"reWelcomeAll"),Se=n(async e=>{if(!N){N=!0,Q().stop(),O.persistPendingSummary(),F.dispose(),nt();try{H?.close()}catch{}s.close(),g.dispose();try{be(K)&&ye(K)}catch{}g.clearAttachState(),await ze(),process.exit(e)}},"completeExit"),q=n((e,o=0)=>{if(N)return;const c=e==="shutdown-hook"||e==="shutdown-after-settle";if(c&&O.finishOpenToolGroup(!0),c&&(O.hasSummaryTasks()||j.hasTasks())){if(de)return;de=!0,Promise.allSettled([O.waitForSummaryTasks(),j.waitForTasks()]).finally(()=>Se(o));return}Se(o)},"disposeAndExit");le=at({writable:n(()=>g.writableClients(),"writable"),forward:n((e,o)=>g.sendFrame(e,o),"forward"),pending:X,broadcast:n(e=>g.broadcastUi(e),"broadcast"),onKnownStreamWait:n(e=>F.knownStreamWait(e),"onKnownStreamWait")}),m.setRebindSession(),await m.enqueueRebind(U,A),d("broker.startup.extensions_bound");const C=Fn({nodeId:t,registry:g,toolGroups:O,projection:F,rebind:m,boundaryReviewId:E,pendingDialogs:X,sendWelcome:we,replayExtraPendingDialogsTo:Ce,reWelcomeAll:ne,disposeAndExit:q,persistModelChoice:ge,broadcastModelChanged:ve,registryOf:se,formatModelSpec:B,formatExactModelSpec:Zn,turnAdmission:ee,memoryInventory:b,runNode:R,onKickoffAdmitted:L.releaseKickoff});ce=C.notifyTurnAccepted,me=C.resetForSession,ue=C.pendingPromptDispatches;const Me=2500;let te=!1;const xe=n(async e=>{if(N||te)return;if(te=!0,m.isAgentRunActive()||m.session().isStreaming||C.pendingPromptDispatches()>0){const c=Date.now()+Me;for(;C.pendingPromptDispatches()>0&&!m.session().isStreaming&&Date.now()<c;)await new Promise(v=>setTimeout(v,25));if(m.session().isStreaming){const v=c-Date.now();if(v>0){let h;try{Gn(),await Promise.race([m.session().abort().then(()=>!0,()=>!1),new Promise($=>{h=setTimeout(()=>$(!1),v)})])&&await Re(t,{event:"closed",end_reason:"teardown-aborted"})}finally{h!==void 0&&clearTimeout(h)}}}else(C.pendingPromptDispatches()>0||m.isAgentRunActive())&&await Re(t,{event:"interrupted"})}q(e)},"abortAndExit");if(y=n(e=>{xe(e)},"signalTeardown"),x!==void 0){y(x);return}try{be(K)&&ye(K)}catch{}H=Ue(e=>{const o=g.create(e);e.on("data",v=>{let h;try{h=o.decoder.push(v)}catch(w){w instanceof Jn?(g.sendFrame(o,{type:"error",code:"frame_overflow",message:w.message}),g.dropClient(o,`frame overflow: ${w.message}`)):g.dropClient(o,`decoder error: ${String(w)}`);return}for(const w of h)try{Ln(C,o,w)}catch{}});const c=n(()=>{g.removeClient(o)},"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(o=>T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:o,fields:{operation:"broker_socket_bound_fault_clear"}}));let e;try{e=await W.recoverOnStartup()}catch(o){T({level:"error",event:"broker.daemon.operation.failed",node_id:t,error:o,fields:{operation:"recovery_startup"}}),q("recovery-startup-failed",1);return}if(!(N||te))if(e==="none"&&f.firstPrompt!==void 0&&f.firstPrompt!==""){const o=qn(process.env[Vn]);o!==null&&Xn(f.firstPrompt,o);const c=process.env.CRTR_KICKOFF_MESSAGE_IDS;C.kickoff(f.firstPrompt,c?JSON.parse(c):[])}else L.releaseKickoff()}),g.persistAttachState()}n(uo,"runBroker");function ot(t){const r=new Set;for(const i of t)if(!(i.role!=="assistant"||!Array.isArray(i.content)))for(const u of i.content)u!==null&&typeof u=="object"&&u.type==="toolCall"&&typeof u.id=="string"&&r.add(u.id);return r}n(ot,"toolCallIds");function ie(t,r){const i=t.sessionManager,u=hn(i);return u!==void 0&&$n(u.map(({message:s})=>s)),u===void 0?void 0:_n(u,{boundaryReviewId:r,sessionEntries:i.getEntries?.()})}n(ie,"snapshotMessages");function ke(){const t=Ne();if(t===void 0||t==="")throw new Error("broker launch is missing CRTR_NODE_ID");return t}n(ke,"currentBrokerNodeId");async function rt(t,r){const i=cn(r.model,Ie(),r.modelExact===!0);if(i===void 0)return;const u=se(t),s={cwd:De()??r.cwd,profileId:Fe()},a=fn(i,u,s);if(a!==void 0)throw await z(ke(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`model '${a.request.spec}' is not registered in the serving model registry`}}),new Error(`[broker] FATAL: model '${a.request.spec}' is not registered in the serving model registry`);const l=mn(i,s.cwd,s.profileId),d=un(i.spec);for(const p of l){const S=u.find(p.providerId,p.modelId);if(S===void 0)continue;const _=d?.providerId===p.providerId&&d.modelId===p.modelId?d.thinkingLevel??(p.thinkingLevel===void 0?void 0:"off"):p.thinkingLevel;return{model:S,thinkingLevel:_}}if(r.modelExact===!0){const p=l.map(S=>`'${S.providerId}/${S.modelId}' unregistered`).join("; ");throw await z(ke(),{op:"record",input:{link:"crtr\u2192pi",op:"model resolution at launch",kind:"model-not-found",retry:{disposition:"fatal"},message:`exact-consult model '${r.model}' is unavailable \u2014 refusing to substitute (${p})`}}),new Error(`[broker] FATAL: exact-consult model '${r.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 st(t){let r=!0;return{runtime:new Proxy(t,{get(u,s,a){return r&&s==="getAvailableSnapshot"?()=>[]:r&&s==="getAvailable"?async()=>[]:r&&s==="getModel"?()=>{}:Reflect.get(u,s,a)}}),reveal:n(()=>{r=!1},"reveal")}}n(st,"modelLessRegistry");async function it(t,r){const i=Y(),u=n(async _=>{const f=await Ve.create({credentials:new dn,modelsPath:Te(_.agentDir,"models.json")});ln(f);const b=await t.createAgentSessionServices({cwd:_.cwd,agentDir:_.agentDir,modelRuntime:f,resourceLoaderOptions:{additionalExtensionPaths:r.extensionPaths,appendSystemPrompt:r.appendSystemPromptPath!==void 0?[r.appendSystemPromptPath]:void 0,noContextFiles:!0,extensionsOverride:n(P=>({...P,extensions:P.extensions.filter(E=>!/[/\\]provider-rotation\.(?:ts|js)$/.test(E.path))}),"extensionsOverride")}}),y=b.resourceLoader.getExtensions();if(r.extensionPaths.some(P=>oe.includes(P))){const P=new Set(y.extensions.map(R=>R.path)),E=oe.filter(R=>!P.has(R));if(E.length>0){const R=y.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: ${E.join(", ")}${R===""?"":` (${R})`}`)}}b.settingsManager.getRetryEnabled=()=>!1;const x=await rt(b,r),V=x?.model,U=x?.thinkingLevel,A=x===void 0?st(b.modelRuntime):void 0,ae=A!==void 0?{...b,modelRuntime:A.runtime}:b,G=await t.createAgentSessionFromServices({services:ae,sessionManager:_.sessionManager,model:V,thinkingLevel:U,...tt(r.tools,Le()),sessionStartEvent:_.sessionStartEvent});return Bn(G.session),an(G.session),A?.reveal(),{...G,services:b}},"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,p=l&&!d;let S;if(a)S=await t.SessionManager.forkFrom(r.forkFrom,r.cwd);else if(p||d){if(S=await t.SessionManager.open(s),d){const _=S.getLeafId();S.resetLeaf(),S.appendCustomEntry(vn,{cycle:Number(process.env.CRTR_CYCLES),fromLeaf:_})}}else S=await t.SessionManager.create(r.cwd);if(t.createAgentSessionRuntime!==void 0){const _=n(async b=>{const y=await u({cwd:b.cwd,agentDir:b.agentDir,sessionManager:b.sessionManager,sessionStartEvent:b.sessionStartEvent});return{...y,diagnostics:y.services.diagnostics??[]}},"factory"),f=await t.createAgentSessionRuntime(_,{cwd:r.cwd,agentDir:i,sessionManager:S});return{session:f.session,services:f.services,resuming:p,runtime:f}}const k=await u({cwd:r.cwd,agentDir:i,sessionManager:S});return{session:k.session,services:k.services,resuming:p,runtime:void 0}}n(it,"buildBrokerSession");function at(t){const r=n((s,a,l,d)=>{if(d?.signal?.aborted)return Promise.resolve(s);const p=t.writable();return p.length===0?Promise.resolve(s):new Promise(S=>{let k;const _=n(()=>{k!==void 0&&clearTimeout(k),d?.signal?.removeEventListener("abort",f),t.pending.delete(a.id)},"cleanup"),f=n(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(s)},"onAbort");d?.signal?.addEventListener("abort",f,{once:!0});const b=d?.timeout!==void 0?d.timeout:et;k=setTimeout(()=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(s)},b),typeof k.unref=="function"&&k.unref(),t.pending.set(a.id,{request:a,resolve:n(y=>{_(),t.broadcast({type:"extension_ui_dismiss",id:a.id}),S(l(y))},"resolve")});for(const y of p)t.forward(y,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)=>r(void 0,{type:"extension_ui_request",id:M(),method:"select",title:s,options:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"select"),confirm:n((s,a,l)=>r(!1,{type:"extension_ui_request",id:M(),method:"confirm",title:s,message:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?!1:"confirmed"in d?d.confirmed:!1,l),"confirm"),input:n((s,a,l)=>r(void 0,{type:"extension_ui_request",id:M(),method:"input",title:s,placeholder:a,timeout:l?.timeout},d=>"cancelled"in d&&d.cancelled?void 0:"value"in d?d.value:void 0,l),"input"),editor:n((s,a)=>r(void 0,{type:"extension_ui_request",id:M(),method:"editor",title:s,prefill:a},l=>"cancelled"in l&&l.cancelled?void 0:"value"in l?l.value:void 0),"editor"),setStatus:n((s,a)=>t.broadcast({type:"extension_ui_request",id:M(),method:"setStatus",statusKey:s,statusText:a}),"setStatus"),setWidget:n((s,a,l)=>{typeof a!="function"&&t.broadcast({type:"extension_ui_request",id:M(),method:"setWidget",widgetKey:s,widgetLines:a,widgetPlacement:l?.placement})},"setWidget"),setTitle:n(s=>t.broadcast({type:"extension_ui_request",id:M(),method:"setTitle",title:s}),"setTitle"),notify:n((s,a)=>{const l=a==="warn"?"warning":a;t.broadcast({type:"extension_ui_request",id:M(),method:"notify",message:s,notifyType:l})},"notify"),onTerminalInput:n(()=>i,"onTerminalInput"),setWorkingMessage:i,setWorkingVisible:i,setWorkingIndicator:i,setHiddenThinkingLabel:i,setFooter:i,setHeader:i,custom:n(()=>Promise.resolve(void 0),"custom"),pasteToEditor:i,setEditorText:i,getEditorText:n(()=>"","getEditorText"),addAutocompleteProvider:i,setEditorComponent:i,getEditorComponent:n(()=>{},"getEditorComponent"),getAllThemes:n(()=>[],"getAllThemes"),getTheme:n(()=>{},"getTheme"),setTheme:i,getToolsExpanded:n(()=>!1,"getToolsExpanded"),setToolsExpanded:i}}n(at,"makeBrokerUiContext");export{vo as REVIEW_BOUNDARY_NAVIGATION_CODE,go as ReviewBoundaryNavigationError,tt as brokerToolOptions,it as buildBrokerSession,nt as disposeActiveSession,at as makeBrokerUiContext,uo as runBroker,ie as snapshotMessages};
@@ -22,9 +22,9 @@ type ReshapeOptions = {
22
22
  profileId?: string | null;
23
23
  };
24
24
  /** Synchronous reshape for CLI callers outside the daemon. */
25
- export declare function reshapeNode(nodeId: string, opts?: ReshapeOptions, beforePersist?: () => void): Promise<NodeMeta>;
25
+ export declare function reshapeNode(nodeId: string, opts?: ReshapeOptions, beforePersist?: () => void | Promise<void>): Promise<NodeMeta>;
26
26
  /** Daemon-safe reshape: network-backed config resolution happens off its event loop. */
27
- export declare function reshapeNodeAsync(nodeId: string, opts?: ReshapeOptions, beforePersist?: () => void): Promise<NodeMeta>;
27
+ export declare function reshapeNodeAsync(nodeId: string, opts?: ReshapeOptions, beforePersist?: () => void | Promise<void>): Promise<NodeMeta>;
28
28
  /** Promote a node to an orchestrator (mode→orchestrator), optionally
29
29
  * specializing its kind (e.g. a `general` worker becoming a
30
30
  * `developer.orchestrator`) and optionally also making it resident. Idempotent:
@@ -1 +1 @@
1
- var g=Object.defineProperty;var r=(n,e)=>g(n,"name",{value:e,configurable:!0});import{getNode as o,updateNode as x}from"../canvas/index.js";import{transition as E}from"./lifecycle.js";import{ensureDaemon as R}from"../../daemon/manage.js";import{buildLaunchSpec as $,buildLaunchSpecAsync as A}from"./launch.js";import{ensureRoadmap as m,hasRoadmap as c,roadmapRef as u}from"./roadmap.js";import{readGoal as f,goalPath as w}from"./kickoff.js";async function k(n,e){const i=await o(n);if(i===null)throw new Error(`unknown node: ${n}`);const a=e.kind??i.kind,l=e.mode??i.mode,d=e.lifecycle??i.lifecycle,t=e.profileId===void 0?i.profile_id??null:e.profileId;return{node:i,kind:a,mode:l,lifecycle:d,profileId:t,launchOpts:{lifecycle:d,hasManager:i.parent!==null,model:e.model??i.model_override??void 0,modelOverride:e.model!==void 0,modelIntent:e.model===void 0?i.launch?.modelIntent:void 0,modelExact:e.model===void 0?i.launch?.modelExact:void 0,cwd:i.cwd,profileId:t}}}r(k,"reshapeInputs");async function s(n,e,i,a,l){l?.();const d=i.node.name===i.node.kind&&i.kind!==i.node.kind;return await x(n,{kind:i.kind,mode:i.mode,lifecycle:i.lifecycle,profile_id:i.profileId,launch:a,...d?{name:i.kind}:{},...e.model!==void 0?{model_override:a?.model??e.model}:{}})}r(s,"persistReshape");async function h(n,e={},i){const a=await k(n,e);return await s(n,e,a,$(a.kind,a.mode,a.launchOpts).launch,i)}r(h,"reshapeNode");async function y(n,e={},i){const a=await k(n,e),{launch:l}=await A(a.kind,a.mode,a.launchOpts);return await s(n,e,a,l,i)}r(y,"reshapeNodeAsync");async function N(n,e={}){const i=await o(n);if(i===null)throw new Error(`unknown node: ${n}`);let a=!1;return{meta:await h(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{},mode:"orchestrator",lifecycle:e.resident===!0?"resident":i.lifecycle},async()=>{if(!await c(n)){const d=await f(n);a=await m(n,d!==null&&d.trim()!==""?{goal:d.trim()}:{})}}),roadmapWritten:a,roadmapRef:u(n),goalPath:await w(n)}}r(N,"promote");async function O(n,e={}){const i=await o(n);if(i===null)throw new Error(`unknown node: ${n}`);let a=!1;return{meta:await y(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{},mode:"orchestrator",lifecycle:e.resident===!0?"resident":i.lifecycle},async()=>{if(!await c(n)){const d=await f(n);a=await m(n,d!==null&&d.trim()!==""?{goal:d.trim()}:{})}}),roadmapWritten:a,roadmapRef:u(n),goalPath:await w(n)}}r(O,"promoteAsync");async function Y(n,e={},i={}){if(await o(n)===null)throw new Error(`unknown node: ${n}`);return e.promote===!0?await O(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{}}):(e.kind!==void 0||e.model!==void 0)&&await y(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{}}),{...await _(n,{},i),promoted:e.promote===!0}}r(Y,"requestYieldAsync");async function _(n,e={},i={}){const a=i.ensure??R;if(await o(n)===null)throw new Error(`unknown node: ${n}`);const d=e.kind!==void 0||e.model!==void 0;let t=!1;return e.promote===!0?(await N(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{}}),t=!0):d&&await h(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{}}),a(),await E(n,"yield"),{meta:await o(n),promoted:t,willRefresh:!0}}r(_,"requestYield");export{N as promote,O as promoteAsync,_ as requestYield,Y as requestYieldAsync,h as reshapeNode,y as reshapeNodeAsync};
1
+ var g=Object.defineProperty;var r=(n,e)=>g(n,"name",{value:e,configurable:!0});import{getNode as o,updateNode as x}from"../canvas/index.js";import{transition as E}from"./lifecycle.js";import{ensureDaemon as R}from"../../daemon/manage.js";import{buildLaunchSpec as $,buildLaunchSpecAsync as A}from"./launch.js";import{ensureRoadmap as m,hasRoadmap as c,roadmapRef as u}from"./roadmap.js";import{readGoal as f,goalPath as w}from"./kickoff.js";async function k(n,e){const i=await o(n);if(i===null)throw new Error(`unknown node: ${n}`);const a=e.kind??i.kind,l=e.mode??i.mode,d=e.lifecycle??i.lifecycle,t=e.profileId===void 0?i.profile_id??null:e.profileId;return{node:i,kind:a,mode:l,lifecycle:d,profileId:t,launchOpts:{lifecycle:d,hasManager:i.parent!==null,model:e.model??i.model_override??void 0,modelOverride:e.model!==void 0,modelIntent:e.model===void 0?i.launch?.modelIntent:void 0,modelExact:e.model===void 0?i.launch?.modelExact:void 0,cwd:i.cwd,profileId:t}}}r(k,"reshapeInputs");async function s(n,e,i,a,l){await l?.();const d=i.node.name===i.node.kind&&i.kind!==i.node.kind;return await x(n,{kind:i.kind,mode:i.mode,lifecycle:i.lifecycle,profile_id:i.profileId,launch:a,...d?{name:i.kind}:{},...e.model!==void 0?{model_override:a?.model??e.model}:{}})}r(s,"persistReshape");async function h(n,e={},i){const a=await k(n,e);return await s(n,e,a,$(a.kind,a.mode,a.launchOpts).launch,i)}r(h,"reshapeNode");async function y(n,e={},i){const a=await k(n,e),{launch:l}=await A(a.kind,a.mode,a.launchOpts);return await s(n,e,a,l,i)}r(y,"reshapeNodeAsync");async function N(n,e={}){const i=await o(n);if(i===null)throw new Error(`unknown node: ${n}`);let a=!1;return{meta:await h(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{},mode:"orchestrator",lifecycle:e.resident===!0?"resident":i.lifecycle},async()=>{if(!await c(n)){const d=await f(n);a=await m(n,d!==null&&d.trim()!==""?{goal:d.trim()}:{})}}),roadmapWritten:a,roadmapRef:u(n),goalPath:await w(n)}}r(N,"promote");async function O(n,e={}){const i=await o(n);if(i===null)throw new Error(`unknown node: ${n}`);let a=!1;return{meta:await y(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{},mode:"orchestrator",lifecycle:e.resident===!0?"resident":i.lifecycle},async()=>{if(!await c(n)){const d=await f(n);a=await m(n,d!==null&&d.trim()!==""?{goal:d.trim()}:{})}}),roadmapWritten:a,roadmapRef:u(n),goalPath:await w(n)}}r(O,"promoteAsync");async function Y(n,e={},i={}){if(await o(n)===null)throw new Error(`unknown node: ${n}`);return e.promote===!0?await O(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{}}):(e.kind!==void 0||e.model!==void 0)&&await y(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{}}),{...await _(n,{},i),promoted:e.promote===!0}}r(Y,"requestYieldAsync");async function _(n,e={},i={}){const a=i.ensure??R;if(await o(n)===null)throw new Error(`unknown node: ${n}`);const d=e.kind!==void 0||e.model!==void 0;let t=!1;return e.promote===!0?(await N(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{}}),t=!0):d&&await h(n,{...e.kind!==void 0?{kind:e.kind}:{},...e.model!==void 0?{model:e.model}:{}}),a(),await E(n,"yield"),{meta:await o(n),promoted:t,willRefresh:!0}}r(_,"requestYield");export{N as promote,O as promoteAsync,_ as requestYield,Y as requestYieldAsync,h as reshapeNode,y as reshapeNodeAsync};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.557",
3
+ "version": "0.3.558",
4
4
  "description": "crtr — agent runtime with memory, plugins, and marketplaces",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -141,7 +141,7 @@
141
141
  },
142
142
  "license": "UNLICENSED",
143
143
  "dependencies": {
144
- "@north-light/identity": "0.3.557",
144
+ "@north-light/identity": "0.3.558",
145
145
  "@earendil-works/pi-agent-core": "1.1.0",
146
146
  "@earendil-works/pi-ai": "1.1.0",
147
147
  "@earendil-works/pi-coding-agent": "1.1.0",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@north-light/identity",
3
- "version": "0.3.557",
3
+ "version": "0.3.558",
4
4
  "description": "Northlight access-token verification and scope rules",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
package/runtime.lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@north-light/cli",
3
- "version": "0.3.557",
3
+ "version": "0.3.558",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "@north-light/cli",
9
- "version": "0.3.557",
9
+ "version": "0.3.558",
10
10
  "hasInstallScript": true,
11
11
  "license": "UNLICENSED",
12
12
  "workspaces": [
@@ -24,7 +24,7 @@
24
24
  "@milkdown/preset-gfm": "^7.22.3",
25
25
  "@milkdown/prose": "^7.22.3",
26
26
  "@milkdown/utils": "^7.22.3",
27
- "@north-light/identity": "0.3.557",
27
+ "@north-light/identity": "0.3.558",
28
28
  "cron-parser": "^5.6.0",
29
29
  "esbuild": "^0.27.7",
30
30
  "jose": "^6.2.12",
@@ -12455,17 +12455,17 @@
12455
12455
  },
12456
12456
  "packages/crouter-api": {
12457
12457
  "name": "@north-light/api",
12458
- "version": "0.3.557",
12458
+ "version": "0.3.558",
12459
12459
  "license": "UNLICENSED"
12460
12460
  },
12461
12461
  "packages/crouter-env-docker": {
12462
12462
  "name": "@north-light/env-docker",
12463
- "version": "0.3.557",
12463
+ "version": "0.3.558",
12464
12464
  "license": "UNLICENSED"
12465
12465
  },
12466
12466
  "packages/crouter-identity": {
12467
12467
  "name": "@north-light/identity",
12468
- "version": "0.3.557",
12468
+ "version": "0.3.558",
12469
12469
  "license": "UNLICENSED",
12470
12470
  "dependencies": {
12471
12471
  "jose": "^6.2.1"
@@ -12473,21 +12473,21 @@
12473
12473
  },
12474
12474
  "packages/crouter-plugin": {
12475
12475
  "name": "@north-light/plugin",
12476
- "version": "0.3.557",
12476
+ "version": "0.3.558",
12477
12477
  "license": "UNLICENSED",
12478
12478
  "dependencies": {
12479
- "@north-light/api": "0.3.557",
12480
- "@north-light/identity": "0.3.557"
12479
+ "@north-light/api": "0.3.558",
12480
+ "@north-light/identity": "0.3.558"
12481
12481
  }
12482
12482
  },
12483
12483
  "packages/crouter-sdk": {
12484
12484
  "name": "@north-light/sdk",
12485
- "version": "0.3.557",
12485
+ "version": "0.3.558",
12486
12486
  "license": "UNLICENSED",
12487
12487
  "dependencies": {
12488
- "@north-light/api": "0.3.557",
12489
- "@north-light/identity": "0.3.557",
12490
- "@north-light/plugin": "0.3.557",
12488
+ "@north-light/api": "0.3.558",
12489
+ "@north-light/identity": "0.3.558",
12490
+ "@north-light/plugin": "0.3.558",
12491
12491
  "jose": "^6.2.1"
12492
12492
  },
12493
12493
  "bin": {