@claudexor/orchestrator 3.20.1 → 3.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/attemptFinalize.d.ts +14 -101
- package/dist/attemptFinalize.d.ts.map +1 -1
- package/dist/attemptFinalize.js +7 -328
- package/dist/attemptFinalize.js.map +1 -1
- package/dist/candidateEvidence.d.ts +15 -6
- package/dist/candidateEvidence.d.ts.map +1 -1
- package/dist/candidateEvidence.js +1 -1
- package/dist/candidateEvidence.js.map +1 -1
- package/dist/candidateOutputs.d.ts +7 -3
- package/dist/candidateOutputs.d.ts.map +1 -1
- package/dist/candidateOutputs.js +4 -1
- package/dist/candidateOutputs.js.map +1 -1
- package/dist/candidateReview.d.ts.map +1 -1
- package/dist/candidateReview.js +3 -1
- package/dist/candidateReview.js.map +1 -1
- package/dist/candidateTerminals.d.ts +4 -0
- package/dist/candidateTerminals.d.ts.map +1 -1
- package/dist/candidateTerminals.js +18 -7
- package/dist/candidateTerminals.js.map +1 -1
- package/dist/candidateWorkProduct.d.ts.map +1 -1
- package/dist/candidateWorkProduct.js +6 -6
- package/dist/candidateWorkProduct.js.map +1 -1
- package/dist/carrier-planner.d.ts +94 -0
- package/dist/carrier-planner.d.ts.map +1 -0
- package/dist/carrier-planner.js +111 -0
- package/dist/carrier-planner.js.map +1 -0
- package/dist/continuation-custody.d.ts +57 -0
- package/dist/continuation-custody.d.ts.map +1 -0
- package/dist/continuation-custody.js +151 -0
- package/dist/continuation-custody.js.map +1 -0
- package/dist/continuation-evidence-io.d.ts +18 -0
- package/dist/continuation-evidence-io.d.ts.map +1 -0
- package/dist/continuation-evidence-io.js +167 -0
- package/dist/continuation-evidence-io.js.map +1 -0
- package/dist/continuation-evidence.d.ts +81 -0
- package/dist/continuation-evidence.d.ts.map +1 -0
- package/dist/continuation-evidence.js +122 -0
- package/dist/continuation-evidence.js.map +1 -0
- package/dist/continuation-input.d.ts +10 -0
- package/dist/continuation-input.d.ts.map +1 -0
- package/dist/continuation-input.js +69 -0
- package/dist/continuation-input.js.map +1 -0
- package/dist/continue-from.d.ts +41 -0
- package/dist/continue-from.d.ts.map +1 -0
- package/dist/continue-from.js +292 -0
- package/dist/continue-from.js.map +1 -0
- package/dist/continuity-notice.d.ts +42 -0
- package/dist/continuity-notice.d.ts.map +1 -0
- package/dist/continuity-notice.js +42 -0
- package/dist/continuity-notice.js.map +1 -0
- package/dist/continuity-terminal.d.ts +19 -0
- package/dist/continuity-terminal.d.ts.map +1 -0
- package/dist/continuity-terminal.js +34 -0
- package/dist/continuity-terminal.js.map +1 -0
- package/dist/credential-cooldown.d.ts.map +1 -1
- package/dist/credential-cooldown.js +8 -3
- package/dist/credential-cooldown.js.map +1 -1
- package/dist/credential-differential.d.ts +1 -0
- package/dist/credential-differential.d.ts.map +1 -1
- package/dist/credential-differential.js +32 -4
- package/dist/credential-differential.js.map +1 -1
- package/dist/deepScanReducer.d.ts +4 -1
- package/dist/deepScanReducer.d.ts.map +1 -1
- package/dist/deepScanReducer.js +10 -5
- package/dist/deepScanReducer.js.map +1 -1
- package/dist/delegatedHome.d.ts +30 -1
- package/dist/delegatedHome.d.ts.map +1 -1
- package/dist/delegatedHome.js +37 -2
- package/dist/delegatedHome.js.map +1 -1
- package/dist/delegationFailure.d.ts +4 -3
- package/dist/delegationFailure.d.ts.map +1 -1
- package/dist/delegationFailure.js +25 -24
- package/dist/delegationFailure.js.map +1 -1
- package/dist/directoryCandidate.d.ts +2 -3
- package/dist/directoryCandidate.d.ts.map +1 -1
- package/dist/directoryCandidate.js +3 -2
- package/dist/directoryCandidate.js.map +1 -1
- package/dist/inrun-continuity-carrier.d.ts +76 -0
- package/dist/inrun-continuity-carrier.d.ts.map +1 -0
- package/dist/inrun-continuity-carrier.js +218 -0
- package/dist/inrun-continuity-carrier.js.map +1 -0
- package/dist/inrun-continuity-thread.d.ts +8 -0
- package/dist/inrun-continuity-thread.d.ts.map +1 -0
- package/dist/inrun-continuity-thread.js +23 -0
- package/dist/inrun-continuity-thread.js.map +1 -0
- package/dist/inrun-continuity-types.d.ts +105 -0
- package/dist/inrun-continuity-types.d.ts.map +1 -0
- package/dist/inrun-continuity-types.js +2 -0
- package/dist/inrun-continuity-types.js.map +1 -0
- package/dist/inrun-continuity.d.ts +79 -0
- package/dist/inrun-continuity.d.ts.map +1 -0
- package/dist/inrun-continuity.js +465 -0
- package/dist/inrun-continuity.js.map +1 -0
- package/dist/inrun-continuity.test-support.d.ts +374 -0
- package/dist/inrun-continuity.test-support.d.ts.map +1 -0
- package/dist/inrun-continuity.test-support.js +198 -0
- package/dist/inrun-continuity.test-support.js.map +1 -0
- package/dist/inrun-retained-output.d.ts +9 -0
- package/dist/inrun-retained-output.d.ts.map +1 -0
- package/dist/inrun-retained-output.js +16 -0
- package/dist/inrun-retained-output.js.map +1 -0
- package/dist/interaction.d.ts +1 -1
- package/dist/interaction.d.ts.map +1 -1
- package/dist/interaction.js +6 -1
- package/dist/interaction.js.map +1 -1
- package/dist/modelGovernance.d.ts +4 -0
- package/dist/modelGovernance.d.ts.map +1 -1
- package/dist/modelGovernance.js +27 -1
- package/dist/modelGovernance.js.map +1 -1
- package/dist/orchestrator-credentials.d.ts +1 -1
- package/dist/orchestrator-credentials.d.ts.map +1 -1
- package/dist/orchestrator-credentials.js +4 -3
- package/dist/orchestrator-credentials.js.map +1 -1
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +261 -235
- package/dist/orchestrator.js.map +1 -1
- package/dist/persistedPatch.d.ts +55 -0
- package/dist/persistedPatch.d.ts.map +1 -0
- package/dist/persistedPatch.js +132 -0
- package/dist/persistedPatch.js.map +1 -0
- package/dist/planFinalize.d.ts +37 -0
- package/dist/planFinalize.d.ts.map +1 -0
- package/dist/planFinalize.js +94 -0
- package/dist/planFinalize.js.map +1 -0
- package/dist/planRun.d.ts +2 -28
- package/dist/planRun.d.ts.map +1 -1
- package/dist/planRun.js +5 -88
- package/dist/planRun.js.map +1 -1
- package/dist/plannerAttempt.d.ts +4 -1
- package/dist/plannerAttempt.d.ts.map +1 -1
- package/dist/plannerAttempt.js +9 -4
- package/dist/plannerAttempt.js.map +1 -1
- package/dist/prompt-framing.d.ts +1 -1
- package/dist/prompt-framing.d.ts.map +1 -1
- package/dist/prompt-framing.js.map +1 -1
- package/dist/reviewerEffort.d.ts +41 -0
- package/dist/reviewerEffort.d.ts.map +1 -0
- package/dist/reviewerEffort.js +37 -0
- package/dist/reviewerEffort.js.map +1 -0
- package/dist/reviewerPanel.d.ts +5 -5
- package/dist/reviewerPanel.d.ts.map +1 -1
- package/dist/reviewerPanel.js +22 -50
- package/dist/reviewerPanel.js.map +1 -1
- package/dist/run-input-resolution.d.ts.map +1 -1
- package/dist/run-input-resolution.js +10 -0
- package/dist/run-input-resolution.js.map +1 -1
- package/dist/runAdmission.js +1 -1
- package/dist/runAdmission.js.map +1 -1
- package/dist/runEventLog.d.ts.map +1 -1
- package/dist/runEventLog.js +5 -0
- package/dist/runEventLog.js.map +1 -1
- package/dist/runFactsBuilder.d.ts.map +1 -1
- package/dist/runFactsBuilder.js +11 -2
- package/dist/runFactsBuilder.js.map +1 -1
- package/dist/runSupport.d.ts +2 -1
- package/dist/runSupport.d.ts.map +1 -1
- package/dist/runSupport.js +2 -1
- package/dist/runSupport.js.map +1 -1
- package/dist/runTelemetryWriter.d.ts.map +1 -1
- package/dist/runTelemetryWriter.js +7 -2
- package/dist/runTelemetryWriter.js.map +1 -1
- package/dist/runTerminalResults.d.ts +6 -2
- package/dist/runTerminalResults.d.ts.map +1 -1
- package/dist/runTerminalResults.js +8 -1
- package/dist/runTerminalResults.js.map +1 -1
- package/dist/runTerminals.d.ts.map +1 -1
- package/dist/runTerminals.js +6 -5
- package/dist/runTerminals.js.map +1 -1
- package/dist/secretDiff.d.ts +67 -27
- package/dist/secretDiff.d.ts.map +1 -1
- package/dist/secretDiff.js +143 -113
- package/dist/secretDiff.js.map +1 -1
- package/dist/session-capsule.d.ts +29 -0
- package/dist/session-capsule.d.ts.map +1 -0
- package/dist/session-capsule.js +86 -0
- package/dist/session-capsule.js.map +1 -0
- package/dist/workReportEnvelope.d.ts +123 -0
- package/dist/workReportEnvelope.d.ts.map +1 -0
- package/dist/workReportEnvelope.js +362 -0
- package/dist/workReportEnvelope.js.map +1 -0
- package/package.json +17 -17
- package/dist/effortGovernance.d.ts +0 -13
- package/dist/effortGovernance.d.ts.map +0 -1
- package/dist/effortGovernance.js +0 -7
- package/dist/effortGovernance.js.map +0 -1
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/** Inputs shared by the in-run controller and its I/O helpers. */
|
|
2
|
+
import type { AnswerAssembly, HarnessAdapter } from "@claudexor/core";
|
|
3
|
+
import type { CredentialProfile, HarnessRunSpec, QuotaSnapshot, RunEventType, RunResumable } from "@claudexor/schema";
|
|
4
|
+
import type { AttemptOutputMarkers } from "./attemptOutputMarkers.js";
|
|
5
|
+
import type { AttemptTelemetry, TransientFailureObservation } from "./attemptTelemetry.js";
|
|
6
|
+
import type { ModelGovernedRoute } from "./modelGovernance.js";
|
|
7
|
+
import type { ProfilePolicy, rotateSpecOnTypedLimit } from "./credential-profile-rotation.js";
|
|
8
|
+
import type { PreProgressRefusalSubject } from "./pre-progress-refusal.js";
|
|
9
|
+
import type { TransientRetryPolicy } from "./runSupport.js";
|
|
10
|
+
import type { ContinuedTry } from "./inrun-continuity-carrier.js";
|
|
11
|
+
import type { PredecessorEvidenceSource } from "./continuation-evidence.js";
|
|
12
|
+
type ContinuityEmit = (type: RunEventType, payload: Record<string, unknown>) => void;
|
|
13
|
+
export interface InRunContinuityDeps {
|
|
14
|
+
adapter: HarnessAdapter;
|
|
15
|
+
runId: string;
|
|
16
|
+
attemptId: string;
|
|
17
|
+
/** The run dir (`paths.root`) — the evidence index reads `events.jsonl` there. */
|
|
18
|
+
runDir: string;
|
|
19
|
+
attemptDir: string;
|
|
20
|
+
/** Execution root the child runs in. */
|
|
21
|
+
cwd: string;
|
|
22
|
+
workspace: RunResumable["workspace"];
|
|
23
|
+
/** The caller's original prompt (the work order), for the evidence index. */
|
|
24
|
+
workOrder: string;
|
|
25
|
+
/** The first try's full prompt (engine constraints included) — the packet carrier resends it. */
|
|
26
|
+
firstPrompt: string;
|
|
27
|
+
registry: readonly CredentialProfile[];
|
|
28
|
+
policy: ProfilePolicy;
|
|
29
|
+
snapshots: readonly QuotaSnapshot[];
|
|
30
|
+
retryPolicy: TransientRetryPolicy;
|
|
31
|
+
pinned: boolean;
|
|
32
|
+
defaultRouteWasVendorNative: boolean;
|
|
33
|
+
requestedProfileId: string | null;
|
|
34
|
+
/** False when the lane has no RunInput: rotation never fired there, and still does not. */
|
|
35
|
+
rotationEnabled: boolean;
|
|
36
|
+
laneEnvFor: (profileId: string | null) => Record<string, string> | null;
|
|
37
|
+
probeReadyProfiles: (spec: HarnessRunSpec, tried: Set<string>) => Promise<ReadonlySet<string>>;
|
|
38
|
+
rotationObservations: (spec: HarnessRunSpec, transients: readonly TransientFailureObservation[], refusal: PreProgressRefusalSubject | null) => Pick<Parameters<typeof rotateSpecOnTypedLimit>[0], "probeCurrentSubject" | "liveUnusable" | "notePreProgressRefusal">;
|
|
39
|
+
emit: ContinuityEmit;
|
|
40
|
+
/** The model-governed route: an attested model is pinned only if it lists the id. */
|
|
41
|
+
route?: ModelGovernedRoute;
|
|
42
|
+
newSessionId: () => string;
|
|
43
|
+
/** First try of a continueFrom successor: predecessor progress and receipt. */
|
|
44
|
+
seed?: {
|
|
45
|
+
acted: boolean;
|
|
46
|
+
completed?: boolean;
|
|
47
|
+
continued: ContinuedTry;
|
|
48
|
+
evidenceSources?: readonly PredecessorEvidenceSource[];
|
|
49
|
+
} | null;
|
|
50
|
+
/** Thread facts for the moved-session disclosure (INV-137); null outside a thread. */
|
|
51
|
+
thread: {
|
|
52
|
+
threadId: string;
|
|
53
|
+
turnId: string | null;
|
|
54
|
+
onSessionObserved?: (harnessId: string, nativeSessionId: string, observedModel?: string | null, profileId?: string | null) => void;
|
|
55
|
+
onContinuityResolved?: (turnId: string, disclosure: {
|
|
56
|
+
kind: "native_resume" | "packet" | "fresh";
|
|
57
|
+
packetTurns: number;
|
|
58
|
+
summarized: boolean;
|
|
59
|
+
laneSwitchedFrom: {
|
|
60
|
+
harness: string;
|
|
61
|
+
profileId: string | null;
|
|
62
|
+
} | null;
|
|
63
|
+
}) => void;
|
|
64
|
+
} | null;
|
|
65
|
+
}
|
|
66
|
+
/** What the loop knows when a try has settled. */
|
|
67
|
+
export interface TryFacts {
|
|
68
|
+
runSpec: HarnessRunSpec;
|
|
69
|
+
nativeTry: number;
|
|
70
|
+
harnessErrored: boolean;
|
|
71
|
+
aborted: boolean;
|
|
72
|
+
budgetStopped?: boolean;
|
|
73
|
+
requestRefused: boolean;
|
|
74
|
+
newTransients: readonly TransientFailureObservation[];
|
|
75
|
+
sawTypedLimit: boolean;
|
|
76
|
+
sawRetryable: boolean;
|
|
77
|
+
answer: AnswerAssembly;
|
|
78
|
+
/** Today's transient-gate fact (raw: workspace unchanged and no answer text). */
|
|
79
|
+
rawDeliverableEmpty: boolean;
|
|
80
|
+
/** Candidate lane: the workspace diff is non-empty (the read-only lane omits it). */
|
|
81
|
+
workspaceDiffNonEmpty?: boolean;
|
|
82
|
+
/** The current workspace diff when the lane has one (evidence index file list). */
|
|
83
|
+
currentDiff?: string;
|
|
84
|
+
markers: AttemptOutputMarkers;
|
|
85
|
+
lastLimit: {
|
|
86
|
+
retryDelayMs: number | null;
|
|
87
|
+
resetsAt: string | null;
|
|
88
|
+
} | null;
|
|
89
|
+
refusal: PreProgressRefusalSubject | null;
|
|
90
|
+
telemetry: AttemptTelemetry;
|
|
91
|
+
}
|
|
92
|
+
export type AfterTryVerdict = {
|
|
93
|
+
kind: "continue";
|
|
94
|
+
spec: HarnessRunSpec;
|
|
95
|
+
delayMs: number;
|
|
96
|
+
}
|
|
97
|
+
/** A typed terminal (pinned limit, pool spent): the loop records the error and stops. */
|
|
98
|
+
| {
|
|
99
|
+
kind: "terminal";
|
|
100
|
+
error: Error;
|
|
101
|
+
} | {
|
|
102
|
+
kind: "break";
|
|
103
|
+
};
|
|
104
|
+
export {};
|
|
105
|
+
//# sourceMappingURL=inrun-continuity-types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inrun-continuity-types.d.ts","sourceRoot":"","sources":["../src/inrun-continuity-types.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inrun-continuity-types.js","sourceRoot":"","sources":["../src/inrun-continuity-types.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { type HarnessEvent, type HarnessRunSpec, type ResumableCause, type RunResumable, type WorkState } from "@claudexor/schema";
|
|
2
|
+
import type { AttemptOutputMarkers } from "./attemptOutputMarkers.js";
|
|
3
|
+
import type { AfterTryVerdict, InRunContinuityDeps, TryFacts } from "./inrun-continuity-types.js";
|
|
4
|
+
import type { ContinuityTerminalFacts } from "./continuity-terminal.js";
|
|
5
|
+
export declare class InRunContinuity {
|
|
6
|
+
private readonly deps;
|
|
7
|
+
private capsule;
|
|
8
|
+
private acted;
|
|
9
|
+
private nativeRejected;
|
|
10
|
+
private readonly triedProfiles;
|
|
11
|
+
private sameAccountTries;
|
|
12
|
+
private lastCause;
|
|
13
|
+
private limit;
|
|
14
|
+
private terminalCode;
|
|
15
|
+
private tryIndex;
|
|
16
|
+
private tryAbort;
|
|
17
|
+
private tryStarted;
|
|
18
|
+
private expectedSessionId;
|
|
19
|
+
private tryModel;
|
|
20
|
+
private tryRequestedModel;
|
|
21
|
+
private tryIdentity;
|
|
22
|
+
private tryFirstInputTokens;
|
|
23
|
+
private continued;
|
|
24
|
+
private pending;
|
|
25
|
+
private packetSession;
|
|
26
|
+
private threadSwitch;
|
|
27
|
+
private readonly retainedOutput;
|
|
28
|
+
/** Carrier of the try that just settled (null = the first try or a fresh replay). */
|
|
29
|
+
private settledCarrier;
|
|
30
|
+
private unstartedInputs;
|
|
31
|
+
constructor(deps: InRunContinuityDeps);
|
|
32
|
+
/** The loop calls this before each try spawns; `abort` is THIS try's controller. */
|
|
33
|
+
beginTry(runSpec: HarnessRunSpec, nativeTry: number, abort: AbortController): void;
|
|
34
|
+
/**
|
|
35
|
+
* Observe one stream event. Returns the typed error that STOPS the try now
|
|
36
|
+
* (the resumed session is not the one requested — a mismatch caught before
|
|
37
|
+
* effects when no agent progress was seen yet; the child is aborted), else
|
|
38
|
+
* null.
|
|
39
|
+
*/
|
|
40
|
+
observe(ev: HarnessEvent, runSpec: HarnessRunSpec, markers: AttemptOutputMarkers): string | null;
|
|
41
|
+
/** Both loops consult this only after the controller accepts the handshake. */
|
|
42
|
+
get mayPublishSession(): boolean;
|
|
43
|
+
/** Decide what the attempt does after a settled try. */
|
|
44
|
+
afterTry(facts: TryFacts): Promise<AfterTryVerdict>;
|
|
45
|
+
/** Receipts, capsule relocation and the terminal `resumable` block once the attempt ends. */
|
|
46
|
+
finish(input: {
|
|
47
|
+
runSpec: HarnessRunSpec;
|
|
48
|
+
errored: boolean;
|
|
49
|
+
nonSuccess?: boolean;
|
|
50
|
+
aborted: boolean;
|
|
51
|
+
cancelReason: string | null;
|
|
52
|
+
workState: WorkState | null | undefined;
|
|
53
|
+
}): Promise<RunResumable | null>;
|
|
54
|
+
/** Keep a snapshot for gates/review/arbitration that can fail after this try completed. */
|
|
55
|
+
terminalFacts(resumable: RunResumable | null): ContinuityTerminalFacts;
|
|
56
|
+
resumable(cause: ResumableCause): RunResumable;
|
|
57
|
+
private poolTerminal;
|
|
58
|
+
private breakWith;
|
|
59
|
+
/** Today's rules for an attempt that did not act: typed-limit / structural
|
|
60
|
+
* rotation onto a fresh session, then the same-profile transient gate. */
|
|
61
|
+
private legacy;
|
|
62
|
+
/** A typed vendor limit ended a try that acted: hop with the session (2A) or a packet (1B). */
|
|
63
|
+
private afterLimit;
|
|
64
|
+
/** The process died after progress: the same account resumes its session
|
|
65
|
+
* (bounded), or re-briefs once a typed fact rejected that session. With no
|
|
66
|
+
* session recorded at all (the harness never reported one) the same account
|
|
67
|
+
* continues on a new session re-briefed by the evidence index (owner 1B),
|
|
68
|
+
* under the same bound. */
|
|
69
|
+
private afterTransport;
|
|
70
|
+
private rotate;
|
|
71
|
+
private hopped;
|
|
72
|
+
private inLaneHome;
|
|
73
|
+
/** Plan and prepare the carrier for the next try, then compose its spec. */
|
|
74
|
+
private prepareContinuedTry;
|
|
75
|
+
private relocate;
|
|
76
|
+
/** The receipt of a continued try, emitted when the try settles (per-try model attestation). */
|
|
77
|
+
private emitReceipt;
|
|
78
|
+
}
|
|
79
|
+
//# sourceMappingURL=inrun-continuity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inrun-continuity.d.ts","sourceRoot":"","sources":["../src/inrun-continuity.ts"],"names":[],"mappings":"AA6BA,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,cAAc,EACnB,KAAK,cAAc,EAEnB,KAAK,YAAY,EAEjB,KAAK,SAAS,EACf,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,2BAA2B,CAAC;AAqBtE,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,6BAA6B,CAAC;AAElG,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,0BAA0B,CAAC;AAMxE,qBAAa,eAAe;IA2Bd,OAAO,CAAC,QAAQ,CAAC,IAAI;IA1BjC,OAAO,CAAC,OAAO,CAAwB;IACvC,OAAO,CAAC,KAAK,CAAS;IACtB,OAAO,CAAC,cAAc,CAAS;IAC/B,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAqB;IACnD,OAAO,CAAC,gBAAgB,CAAK;IAC7B,OAAO,CAAC,SAAS,CAA+B;IAChD,OAAO,CAAC,KAAK,CAAmC;IAChD,OAAO,CAAC,YAAY,CAAuB;IAE3C,OAAO,CAAC,QAAQ,CAAK;IACrB,OAAO,CAAC,QAAQ,CAAgC;IAChD,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,iBAAiB,CAAuB;IAChD,OAAO,CAAC,WAAW,CAA6C;IAChE,OAAO,CAAC,mBAAmB,CAAuB;IAClD,OAAO,CAAC,SAAS,CAA6B;IAC9C,OAAO,CAAC,OAAO,CAA6B;IAC5C,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAA8D;IAClF,OAAO,CAAC,QAAQ,CAAC,cAAc,CAA+B;IAC9D,qFAAqF;IACrF,OAAO,CAAC,cAAc,CAAgD;IACtE,OAAO,CAAC,eAAe,CAAwB;IAE/C,YAA6B,IAAI,EAAE,mBAAmB,EAIrD;IAED,oFAAoF;IACpF,QAAQ,CAAC,OAAO,EAAE,cAAc,EAAE,SAAS,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,GAAG,IAAI,CAqBjF;IAED;;;;;OAKG;IACH,OAAO,CAAC,EAAE,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,OAAO,EAAE,oBAAoB,GAAG,MAAM,GAAG,IAAI,CAgE/F;IAED,+EAA+E;IAC/E,IAAI,iBAAiB,IAAI,OAAO,CAE/B;IAED,wDAAwD;IAClD,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,OAAO,CAAC,eAAe,CAAC,CAyCxD;IAED,6FAA6F;IACvF,MAAM,CAAC,KAAK,EAAE;QAClB,OAAO,EAAE,cAAc,CAAC;QACxB,OAAO,EAAE,OAAO,CAAC;QACjB,UAAU,CAAC,EAAE,OAAO,CAAC;QACrB,OAAO,EAAE,OAAO,CAAC;QACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;QAC5B,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,SAAS,CAAC;KACzC,GAAG,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA0B/B;IAED,2FAA2F;IAC3F,aAAa,CAAC,SAAS,EAAE,YAAY,GAAG,IAAI,GAAG,uBAAuB,CAGrE;IAED,SAAS,CAAC,KAAK,EAAE,cAAc,GAAG,YAAY,CAW7C;IAED,OAAO,CAAC,YAAY;IAYpB,OAAO,CAAC,SAAS;IAKjB;8EAC0E;YAC5D,MAAM;IAiCpB,+FAA+F;YACjF,UAAU;IAuCxB;;;;+BAI2B;YACb,cAAc;YAyCd,MAAM;IA2CpB,OAAO,CAAC,MAAM;IAKd,OAAO,CAAC,UAAU;IASlB,4EAA4E;YAC9D,mBAAmB;YA8BnB,QAAQ;IAItB,gGAAgG;IAChG,OAAO,CAAC,WAAW;CAoBpB"}
|
|
@@ -0,0 +1,465 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* In-run continuation (the owner's "auto-rotation inside the work"): ONE
|
|
3
|
+
* per-attempt controller both the candidate loop and the read-only twin call,
|
|
4
|
+
* so the two lanes never re-derive the ladder (A8).
|
|
5
|
+
*
|
|
6
|
+
* Per try it OBSERVES the stream (the native session id → the capsule, the
|
|
7
|
+
* per-try attested model, the typed limit that ended the try, the identity of
|
|
8
|
+
* a resumed session, the adapter's typed rejection of carried state) and AFTER
|
|
9
|
+
* the try decides what the attempt does next:
|
|
10
|
+
*
|
|
11
|
+
* - the attempt did NOT act → today's rules, byte for byte (typed-limit /
|
|
12
|
+
* structural rotation onto a fresh session, same-profile transient retry);
|
|
13
|
+
* - it acted and a typed vendor limit ended the try → hop to the next
|
|
14
|
+
* eligible account with the session moved (`native_moved`) or, when the
|
|
15
|
+
* session cannot be moved, re-briefed by the evidence index (`packet`,
|
|
16
|
+
* owner 1B) — never a fresh replay of the original prompt;
|
|
17
|
+
* - it acted and the process died (transport) → the same account resumes
|
|
18
|
+
* its own session (`native`), or `packet` once a typed fact rejected the
|
|
19
|
+
* native carrier, bounded by `transient_retry.max_retries` per account;
|
|
20
|
+
* - pinned / `fail` / `ask` / pool spent → a typed terminal that still
|
|
21
|
+
* carries the `resumable` facts (cause, reset, carriers).
|
|
22
|
+
*
|
|
23
|
+
* "Acted" is sticky for the whole attempt (any accepted answer text, any agent
|
|
24
|
+
* progress marker, any file change or workspace diff in ANY try): a silent
|
|
25
|
+
* resumed try never re-opens the `fresh` rung. Hops are bounded by
|
|
26
|
+
* `triedProfiles`; same-account continuations by `max_retries` (A2).
|
|
27
|
+
*/
|
|
28
|
+
import { CONTINUITY_IDENTITY_MISMATCH_CODE, acceptedTryOutput } from "@claudexor/core";
|
|
29
|
+
import { readContinuationSources } from "@claudexor/workspace";
|
|
30
|
+
import { HarnessRunSpec as HarnessRunSpecSchema, } from "@claudexor/schema";
|
|
31
|
+
import { composeContinuedTry, continuityReceipt, relocateCapsule, resumableBlock, uncertainInputFor, } from "./inrun-continuity-carrier.js";
|
|
32
|
+
import { effectiveLimitAction, limitSubjectRoute, rotateSpecOnTypedLimit, } from "./credential-profile-rotation.js";
|
|
33
|
+
import { emitTransientRetryPlan } from "./laneStreamEvents.js";
|
|
34
|
+
import { rotatedSpecInLaneHome } from "./orchestrator-credentials.js";
|
|
35
|
+
import { transientRetryDelayMs } from "./runSupport.js";
|
|
36
|
+
import { readSessionCapsule, writeSessionCapsule } from "./session-capsule.js";
|
|
37
|
+
import { discloseContinuedTry } from "./inrun-continuity-thread.js";
|
|
38
|
+
import { RetainedAttemptOutput } from "./inrun-retained-output.js";
|
|
39
|
+
import { unconfirmedContinuationInputs } from "./continuation-input.js";
|
|
40
|
+
const TYPED_REFUSALS = new Set(["auth_failed", "capability_refused", "config_error"]);
|
|
41
|
+
export class InRunContinuity {
|
|
42
|
+
deps;
|
|
43
|
+
capsule;
|
|
44
|
+
acted = false;
|
|
45
|
+
nativeRejected = false;
|
|
46
|
+
triedProfiles = new Set();
|
|
47
|
+
sameAccountTries = 0;
|
|
48
|
+
lastCause = null;
|
|
49
|
+
limit = null;
|
|
50
|
+
terminalCode = null;
|
|
51
|
+
// Per-try state.
|
|
52
|
+
tryIndex = 0;
|
|
53
|
+
tryAbort = null;
|
|
54
|
+
tryStarted = false;
|
|
55
|
+
expectedSessionId = null;
|
|
56
|
+
tryModel = null;
|
|
57
|
+
tryRequestedModel = null;
|
|
58
|
+
tryIdentity = "not_applicable";
|
|
59
|
+
tryFirstInputTokens = null;
|
|
60
|
+
continued = null;
|
|
61
|
+
pending = null;
|
|
62
|
+
packetSession = false;
|
|
63
|
+
threadSwitch = null;
|
|
64
|
+
retainedOutput = new RetainedAttemptOutput();
|
|
65
|
+
/** Carrier of the try that just settled (null = the first try or a fresh replay). */
|
|
66
|
+
settledCarrier = null;
|
|
67
|
+
unstartedInputs = [];
|
|
68
|
+
constructor(deps) {
|
|
69
|
+
this.deps = deps;
|
|
70
|
+
this.capsule = readSessionCapsule(deps.attemptDir);
|
|
71
|
+
this.acted = deps.seed?.acted === true;
|
|
72
|
+
this.pending = deps.seed?.continued ?? null;
|
|
73
|
+
}
|
|
74
|
+
/** The loop calls this before each try spawns; `abort` is THIS try's controller. */
|
|
75
|
+
beginTry(runSpec, nativeTry, abort) {
|
|
76
|
+
this.limit = null;
|
|
77
|
+
this.terminalCode = null;
|
|
78
|
+
this.tryIndex = nativeTry;
|
|
79
|
+
this.tryAbort = abort;
|
|
80
|
+
this.tryStarted = false;
|
|
81
|
+
this.continued = this.pending;
|
|
82
|
+
this.pending = null;
|
|
83
|
+
if (this.continued) {
|
|
84
|
+
if (this.continued.fromProfileId !== this.continued.toProfileId)
|
|
85
|
+
this.threadSwitch ??= {
|
|
86
|
+
harness: this.deps.adapter.id,
|
|
87
|
+
profileId: this.continued.fromProfileId,
|
|
88
|
+
};
|
|
89
|
+
discloseContinuedTry(this.deps, this.continued, this.threadSwitch);
|
|
90
|
+
}
|
|
91
|
+
this.expectedSessionId = runSpec.resume_session_id ?? null;
|
|
92
|
+
this.tryModel = null;
|
|
93
|
+
this.tryRequestedModel = runSpec.model_hint ?? null;
|
|
94
|
+
this.tryIdentity = "not_applicable";
|
|
95
|
+
this.tryFirstInputTokens = null;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Observe one stream event. Returns the typed error that STOPS the try now
|
|
99
|
+
* (the resumed session is not the one requested — a mismatch caught before
|
|
100
|
+
* effects when no agent progress was seen yet; the child is aborted), else
|
|
101
|
+
* null.
|
|
102
|
+
*/
|
|
103
|
+
observe(ev, runSpec, markers) {
|
|
104
|
+
if (ev.observed_model && this.tryModel === null)
|
|
105
|
+
this.tryModel = ev.observed_model;
|
|
106
|
+
if (ev.rate_limit) {
|
|
107
|
+
this.limit = {
|
|
108
|
+
resetsAt: ev.rate_limit.resets_at ?? null,
|
|
109
|
+
retryDelayMs: ev.rate_limit.retry_delay_ms ?? null,
|
|
110
|
+
constraintId: ev.rate_limit.constraint_id ?? null,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
if (ev.type === "usage" && this.expectedSessionId && this.tryFirstInputTokens === null) {
|
|
114
|
+
const input = ev.usage?.input_token_usage?.total_tokens ?? ev.usage?.input_tokens ?? null;
|
|
115
|
+
if (input !== null)
|
|
116
|
+
this.tryFirstInputTokens = input;
|
|
117
|
+
}
|
|
118
|
+
if (ev.type === "error" &&
|
|
119
|
+
this.expectedSessionId &&
|
|
120
|
+
ev.payload?.["code"] === CONTINUITY_IDENTITY_MISMATCH_CODE) {
|
|
121
|
+
// The adapter compared the recovered handle at its earliest handshake,
|
|
122
|
+
// before any action (codex thread/resume precedes turn/start).
|
|
123
|
+
this.tryIdentity = "mismatch_before_effects";
|
|
124
|
+
this.nativeRejected = true;
|
|
125
|
+
this.tryAbort?.abort();
|
|
126
|
+
return ev.error ?? "recovered native session differs from the requested session";
|
|
127
|
+
}
|
|
128
|
+
if (this.expectedSessionId && this.deps.adapter.continuity?.rejectsCarriedState?.(ev)) {
|
|
129
|
+
this.nativeRejected = true;
|
|
130
|
+
}
|
|
131
|
+
if (ev.type !== "started")
|
|
132
|
+
return null;
|
|
133
|
+
this.tryStarted = true;
|
|
134
|
+
const nid = ev.payload?.["native_session_id"];
|
|
135
|
+
if (typeof nid !== "string" || nid.length === 0)
|
|
136
|
+
return null;
|
|
137
|
+
// Only an adapter with the `continuity` capability promises that a resume
|
|
138
|
+
// keeps the session id; on any other harness a new id after a resume is the
|
|
139
|
+
// vendor's own answer and is recorded as the session, as before.
|
|
140
|
+
if (this.expectedSessionId && nid !== this.expectedSessionId && this.deps.adapter.continuity) {
|
|
141
|
+
this.tryIdentity = markers.sawAgentProgress
|
|
142
|
+
? "mismatch_after_possible_effects"
|
|
143
|
+
: "mismatch_before_effects";
|
|
144
|
+
this.nativeRejected = true;
|
|
145
|
+
this.tryAbort?.abort();
|
|
146
|
+
void this.deps.adapter.cancel?.(runSpec.session_id)?.catch(() => { });
|
|
147
|
+
return `resumed native session ${nid} is not the requested ${this.expectedSessionId}; the try was stopped${markers.sawAgentProgress ? " (effects may have occurred)" : " before any effect"}`;
|
|
148
|
+
}
|
|
149
|
+
if (this.expectedSessionId && nid === this.expectedSessionId)
|
|
150
|
+
this.tryIdentity = "matched_before_effects";
|
|
151
|
+
// Packet-born history lacks earlier thread turns, even on later native resumes.
|
|
152
|
+
this.packetSession =
|
|
153
|
+
this.continued?.carrier === "packet" ||
|
|
154
|
+
(this.packetSession && this.capsule?.nativeSessionId === nid);
|
|
155
|
+
// A new native session (or the resumed one) is the attempt's capsule now.
|
|
156
|
+
this.nativeRejected = false;
|
|
157
|
+
this.capsule = {
|
|
158
|
+
harness: this.deps.adapter.id,
|
|
159
|
+
nativeSessionId: nid,
|
|
160
|
+
holderProfileId: ev.credential_profile_id ?? runSpec.credential_profile?.profile_id ?? null,
|
|
161
|
+
file: this.capsule?.nativeSessionId === nid ? this.capsule.file : null,
|
|
162
|
+
mtimeMs: this.capsule?.nativeSessionId === nid ? this.capsule.mtimeMs : null,
|
|
163
|
+
sidecars: this.capsule?.nativeSessionId === nid ? this.capsule.sidecars : [],
|
|
164
|
+
cwd: runSpec.cwd,
|
|
165
|
+
requestedModel: runSpec.model_hint ?? null,
|
|
166
|
+
};
|
|
167
|
+
writeSessionCapsule(this.deps.attemptDir, this.capsule);
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
/** Both loops consult this only after the controller accepts the handshake. */
|
|
171
|
+
get mayPublishSession() {
|
|
172
|
+
return this.tryStarted && !this.tryIdentity.startsWith("mismatch") && !this.packetSession;
|
|
173
|
+
}
|
|
174
|
+
/** Decide what the attempt does after a settled try. */
|
|
175
|
+
async afterTry(facts) {
|
|
176
|
+
this.retainedOutput.add(facts.answer, facts.harnessErrored, this.tryIdentity);
|
|
177
|
+
const accepted = acceptedTryOutput(facts.answer, facts.harnessErrored);
|
|
178
|
+
this.acted ||=
|
|
179
|
+
accepted.length > 0 ||
|
|
180
|
+
facts.markers.sawAgentProgress ||
|
|
181
|
+
facts.markers.fileChanges > 0 ||
|
|
182
|
+
facts.workspaceDiffNonEmpty === true;
|
|
183
|
+
await this.relocate(facts.runSpec);
|
|
184
|
+
this.settledCarrier = this.continued?.carrier ?? null;
|
|
185
|
+
this.emitReceipt(facts.runSpec);
|
|
186
|
+
if (this.tryStarted)
|
|
187
|
+
this.unstartedInputs = [];
|
|
188
|
+
else if (this.tryIndex === 0) {
|
|
189
|
+
const { runDir, runId, workOrder } = this.deps;
|
|
190
|
+
const sources = readContinuationSources(runDir);
|
|
191
|
+
// A successor's workOrder is the whole joined chain. Keep the individual
|
|
192
|
+
// undelivered callers newest first, including this run's own correction.
|
|
193
|
+
// Further unstarted tries keep these references until a try starts.
|
|
194
|
+
this.unstartedInputs = sources.length
|
|
195
|
+
? unconfirmedContinuationInputs([{ runDir, runId, state: "running" }, ...sources])
|
|
196
|
+
: [{ text: workOrder, runDir }];
|
|
197
|
+
}
|
|
198
|
+
if (facts.budgetStopped)
|
|
199
|
+
return this.breakWith("other");
|
|
200
|
+
if (!facts.harnessErrored || facts.aborted)
|
|
201
|
+
return { kind: "break" };
|
|
202
|
+
if (facts.requestRefused)
|
|
203
|
+
return this.breakWith("other");
|
|
204
|
+
if (facts.telemetry.contextExhausted)
|
|
205
|
+
return this.breakWith("context_exhausted");
|
|
206
|
+
if (!this.acted)
|
|
207
|
+
return this.legacy(facts);
|
|
208
|
+
const typedRefusal = facts.newTransients.some((t) => TYPED_REFUSALS.has(t.category));
|
|
209
|
+
if (typedRefusal)
|
|
210
|
+
return this.breakWith("other");
|
|
211
|
+
// A11: a bare backoff frame (a delay, no reset, no constraint) is transport —
|
|
212
|
+
// the same session is simply resumed — when a session exists to resume;
|
|
213
|
+
// without one the typed limit still hops (nothing to resume on this account).
|
|
214
|
+
const backoffOnly = this.limit !== null &&
|
|
215
|
+
!this.limit.resetsAt &&
|
|
216
|
+
!this.limit.constraintId &&
|
|
217
|
+
this.limit.retryDelayMs !== null;
|
|
218
|
+
if (facts.sawTypedLimit && (!backoffOnly || this.capsule === null)) {
|
|
219
|
+
return this.afterLimit(facts);
|
|
220
|
+
}
|
|
221
|
+
return this.afterTransport(facts);
|
|
222
|
+
}
|
|
223
|
+
/** Receipts, capsule relocation and the terminal `resumable` block once the attempt ends. */
|
|
224
|
+
async finish(input) {
|
|
225
|
+
// A continued try whose attempt ended on a loop exit that skipped
|
|
226
|
+
// `afterTry` (a request or processing refusal) still owes its receipt.
|
|
227
|
+
this.emitReceipt(input.runSpec);
|
|
228
|
+
await this.relocate(input.runSpec);
|
|
229
|
+
const vetoed = input.workState?.state === "needs_input" || input.workState?.state === "incomplete";
|
|
230
|
+
if (!input.errored &&
|
|
231
|
+
!input.aborted &&
|
|
232
|
+
!vetoed &&
|
|
233
|
+
(!input.nonSuccess || (!this.acted && !this.capsule)))
|
|
234
|
+
return null;
|
|
235
|
+
const cause = vetoed
|
|
236
|
+
? input.workState?.state === "needs_input"
|
|
237
|
+
? "input_required"
|
|
238
|
+
: "other"
|
|
239
|
+
: input.aborted
|
|
240
|
+
? input.cancelReason === "wall_clock_exceeded"
|
|
241
|
+
? "wall_clock"
|
|
242
|
+
: "cancelled"
|
|
243
|
+
: input.errored
|
|
244
|
+
? (this.lastCause ?? "other")
|
|
245
|
+
: "other";
|
|
246
|
+
return this.resumable(cause);
|
|
247
|
+
}
|
|
248
|
+
/** Keep a snapshot for gates/review/arbitration that can fail after this try completed. */
|
|
249
|
+
terminalFacts(resumable) {
|
|
250
|
+
if (resumable)
|
|
251
|
+
return { resumable };
|
|
252
|
+
return this.acted || this.capsule ? { resumableOnFailure: this.resumable("other") } : {};
|
|
253
|
+
}
|
|
254
|
+
resumable(cause) {
|
|
255
|
+
return resumableBlock({
|
|
256
|
+
deps: this.deps,
|
|
257
|
+
cause,
|
|
258
|
+
capsule: this.capsule,
|
|
259
|
+
nativeRejected: this.nativeRejected,
|
|
260
|
+
acted: this.acted,
|
|
261
|
+
limit: this.limit,
|
|
262
|
+
terminalCode: this.terminalCode,
|
|
263
|
+
workspace: this.deps.workspace,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
poolTerminal(error) {
|
|
267
|
+
this.lastCause = "pool_exhausted";
|
|
268
|
+
this.terminalCode = codeOf(error);
|
|
269
|
+
const resetsAt = error.resetsAt;
|
|
270
|
+
this.limit = {
|
|
271
|
+
resetsAt: typeof resetsAt === "string" ? resetsAt : null,
|
|
272
|
+
constraintId: this.limit?.constraintId ?? null,
|
|
273
|
+
retryDelayMs: this.limit?.retryDelayMs ?? null,
|
|
274
|
+
};
|
|
275
|
+
return { kind: "terminal", error };
|
|
276
|
+
}
|
|
277
|
+
breakWith(cause) {
|
|
278
|
+
this.lastCause = cause;
|
|
279
|
+
return { kind: "break" };
|
|
280
|
+
}
|
|
281
|
+
/** Today's rules for an attempt that did not act: typed-limit / structural
|
|
282
|
+
* rotation onto a fresh session, then the same-profile transient gate. */
|
|
283
|
+
async legacy(facts) {
|
|
284
|
+
const rotated = await this.rotate(facts, false);
|
|
285
|
+
if (rotated && "poolExhausted" in rotated) {
|
|
286
|
+
return this.poolTerminal(rotated.poolExhausted);
|
|
287
|
+
}
|
|
288
|
+
if (rotated) {
|
|
289
|
+
this.hopped(rotated);
|
|
290
|
+
return { kind: "continue", spec: this.inLaneHome(facts.runSpec, rotated), delayMs: 0 };
|
|
291
|
+
}
|
|
292
|
+
this.lastCause = facts.sawTypedLimit ? "vendor_limit" : "transport";
|
|
293
|
+
if (!facts.sawRetryable ||
|
|
294
|
+
!facts.rawDeliverableEmpty ||
|
|
295
|
+
facts.nativeTry >= this.deps.retryPolicy.maxRetries)
|
|
296
|
+
return { kind: "break" };
|
|
297
|
+
const delayMs = emitTransientRetryPlan((t, p) => this.deps.emit(t, p), this.deps.adapter.id, this.deps.attemptId, facts.telemetry, facts.nativeTry, this.deps.retryPolicy);
|
|
298
|
+
const spec = HarnessRunSpecSchema.parse({
|
|
299
|
+
...facts.runSpec,
|
|
300
|
+
session_id: this.deps.newSessionId(),
|
|
301
|
+
resume_session_id: facts.runSpec.resume_session_id ?? null,
|
|
302
|
+
extra: { ...facts.runSpec.extra },
|
|
303
|
+
});
|
|
304
|
+
return { kind: "continue", spec, delayMs };
|
|
305
|
+
}
|
|
306
|
+
/** A typed vendor limit ended a try that acted: hop with the session (2A) or a packet (1B). */
|
|
307
|
+
async afterLimit(facts) {
|
|
308
|
+
const route = limitSubjectRoute(facts.runSpec.credential_profile ?? null, this.deps.defaultRouteWasVendorNative ? "local_session" : null);
|
|
309
|
+
if (this.deps.pinned) {
|
|
310
|
+
this.lastCause = "pinned_limit";
|
|
311
|
+
this.terminalCode = "subscription_window_exhausted";
|
|
312
|
+
return {
|
|
313
|
+
kind: "terminal",
|
|
314
|
+
error: Object.assign(new Error(`credential profile "${facts.runSpec.credential_profile?.profile_id ?? "default"}" (${this.deps.adapter.id}) hit a typed vendor limit after progress and a pinned account never rotates${this.limit?.resetsAt ? `; resets ${this.limit.resetsAt}` : ""}`), {
|
|
315
|
+
code: "subscription_window_exhausted",
|
|
316
|
+
category: "harness_unavailable",
|
|
317
|
+
resetsAt: this.limit?.resetsAt ?? null,
|
|
318
|
+
}),
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
if (effectiveLimitAction(this.deps.policy, route) !== "rotate")
|
|
322
|
+
return this.breakWith("vendor_limit");
|
|
323
|
+
const rotated = await this.rotate(facts, true);
|
|
324
|
+
if (rotated && "poolExhausted" in rotated) {
|
|
325
|
+
return this.poolTerminal(rotated.poolExhausted);
|
|
326
|
+
}
|
|
327
|
+
if (!rotated)
|
|
328
|
+
return this.breakWith("vendor_limit");
|
|
329
|
+
this.hopped(rotated);
|
|
330
|
+
this.lastCause = "vendor_limit";
|
|
331
|
+
return this.prepareContinuedTry(facts, this.inLaneHome(facts.runSpec, rotated), "vendor_limit", 0);
|
|
332
|
+
}
|
|
333
|
+
/** The process died after progress: the same account resumes its session
|
|
334
|
+
* (bounded), or re-briefs once a typed fact rejected that session. With no
|
|
335
|
+
* session recorded at all (the harness never reported one) the same account
|
|
336
|
+
* continues on a new session re-briefed by the evidence index (owner 1B),
|
|
337
|
+
* under the same bound. */
|
|
338
|
+
async afterTransport(facts) {
|
|
339
|
+
this.lastCause = "transport";
|
|
340
|
+
// A packet try that died before doing anything replayed no effect: the
|
|
341
|
+
// structural branch hops it to the next account with the same packet
|
|
342
|
+
// (today's pre-progress failover, now on the packet carrier).
|
|
343
|
+
const packetDiedUnused = this.capsule === null &&
|
|
344
|
+
this.settledCarrier === "packet" &&
|
|
345
|
+
!facts.sawRetryable &&
|
|
346
|
+
!facts.markers.sawAgentProgress &&
|
|
347
|
+
facts.markers.fileChanges === 0;
|
|
348
|
+
if (packetDiedUnused) {
|
|
349
|
+
const rotated = await this.rotate(facts, true);
|
|
350
|
+
if (rotated && "poolExhausted" in rotated) {
|
|
351
|
+
return this.poolTerminal(rotated.poolExhausted);
|
|
352
|
+
}
|
|
353
|
+
if (!rotated)
|
|
354
|
+
return { kind: "break" };
|
|
355
|
+
this.hopped(rotated);
|
|
356
|
+
return this.prepareContinuedTry(facts, this.inLaneHome(facts.runSpec, rotated), "transport", 0);
|
|
357
|
+
}
|
|
358
|
+
if (this.sameAccountTries >= this.deps.retryPolicy.maxRetries)
|
|
359
|
+
return { kind: "break" };
|
|
360
|
+
const retryIndex = this.sameAccountTries;
|
|
361
|
+
this.sameAccountTries += 1;
|
|
362
|
+
const spec = HarnessRunSpecSchema.parse({
|
|
363
|
+
...facts.runSpec,
|
|
364
|
+
session_id: this.deps.newSessionId(),
|
|
365
|
+
extra: { ...facts.runSpec.extra },
|
|
366
|
+
});
|
|
367
|
+
const delayMs = transientRetryDelayMs(facts.newTransients.at(-1)?.retryDelayMs ?? this.limit?.retryDelayMs ?? null, this.deps.retryPolicy, retryIndex);
|
|
368
|
+
return this.prepareContinuedTry(facts, spec, "transport", delayMs);
|
|
369
|
+
}
|
|
370
|
+
async rotate(facts, forceEligible) {
|
|
371
|
+
if (!this.deps.rotationEnabled)
|
|
372
|
+
return null;
|
|
373
|
+
const { runSpec } = facts;
|
|
374
|
+
const accepted = acceptedTryOutput(facts.answer, facts.harnessErrored);
|
|
375
|
+
return rotateSpecOnTypedLimit({
|
|
376
|
+
spec: runSpec,
|
|
377
|
+
harnessId: this.deps.adapter.id,
|
|
378
|
+
attemptId: this.deps.attemptId,
|
|
379
|
+
policy: this.deps.policy,
|
|
380
|
+
registry: this.deps.registry,
|
|
381
|
+
snapshots: this.deps.snapshots,
|
|
382
|
+
probeReadyProfiles: () => this.deps.probeReadyProfiles(runSpec, this.triedProfiles),
|
|
383
|
+
...this.deps.rotationObservations(runSpec, facts.newTransients, facts.refusal),
|
|
384
|
+
triedProfiles: this.triedProfiles,
|
|
385
|
+
// After progress the predicate's no-deliverable/no-mutation fence scopes
|
|
386
|
+
// only the `fresh` carrier: the planner picks the carrier, rotation only
|
|
387
|
+
// picks the next account.
|
|
388
|
+
markers: forceEligible
|
|
389
|
+
? {
|
|
390
|
+
sawAgentProgress: false,
|
|
391
|
+
fileChanges: 0,
|
|
392
|
+
sawSessionStart: facts.markers.sawSessionStart,
|
|
393
|
+
}
|
|
394
|
+
: facts.markers,
|
|
395
|
+
requestRefused: facts.requestRefused,
|
|
396
|
+
sawTypedLimit: facts.sawTypedLimit,
|
|
397
|
+
sawRetryable: facts.sawRetryable,
|
|
398
|
+
attemptErrored: facts.harnessErrored,
|
|
399
|
+
deliverableEmpty: forceEligible
|
|
400
|
+
? true
|
|
401
|
+
: facts.workspaceDiffNonEmpty !== true && accepted.length === 0,
|
|
402
|
+
workspaceDiffNonEmpty: forceEligible ? false : facts.workspaceDiffNonEmpty,
|
|
403
|
+
lastLimit: facts.lastLimit,
|
|
404
|
+
emit: this.deps.emit,
|
|
405
|
+
newSessionId: this.deps.newSessionId,
|
|
406
|
+
defaultRouteWasVendorNative: this.deps.defaultRouteWasVendorNative,
|
|
407
|
+
pinned: this.deps.pinned,
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
hopped(rotated) {
|
|
411
|
+
if (rotated.credential_profile)
|
|
412
|
+
this.triedProfiles.add(rotated.credential_profile.profile_id);
|
|
413
|
+
this.sameAccountTries = 0;
|
|
414
|
+
}
|
|
415
|
+
inLaneHome(previous, rotated) {
|
|
416
|
+
return rotatedSpecInLaneHome(previous, rotated, this.deps.laneEnvFor, this.deps.requestedProfileId);
|
|
417
|
+
}
|
|
418
|
+
/** Plan and prepare the carrier for the next try, then compose its spec. */
|
|
419
|
+
async prepareContinuedTry(facts, base, cause, delayMs) {
|
|
420
|
+
const composed = await composeContinuedTry({
|
|
421
|
+
deps: this.deps,
|
|
422
|
+
capsule: this.capsule,
|
|
423
|
+
acted: this.acted,
|
|
424
|
+
nativeRejected: this.nativeRejected,
|
|
425
|
+
tryIndex: this.tryIndex,
|
|
426
|
+
uncertainInput: uncertainInputFor(this.deps.runDir, this.unstartedInputs, this.deps.attemptId),
|
|
427
|
+
retainedOutput: this.retainedOutput.text(),
|
|
428
|
+
}, facts, base, cause, delayMs);
|
|
429
|
+
this.pending = composed.continued;
|
|
430
|
+
if (composed.capsule)
|
|
431
|
+
this.capsule = composed.capsule;
|
|
432
|
+
return composed.verdict;
|
|
433
|
+
}
|
|
434
|
+
async relocate(runSpec) {
|
|
435
|
+
if (this.capsule)
|
|
436
|
+
this.capsule = await relocateCapsule(this.deps, this.capsule, runSpec);
|
|
437
|
+
}
|
|
438
|
+
/** The receipt of a continued try, emitted when the try settles (per-try model attestation). */
|
|
439
|
+
emitReceipt(runSpec) {
|
|
440
|
+
const continued = this.continued;
|
|
441
|
+
if (!continued)
|
|
442
|
+
return;
|
|
443
|
+
this.continued = null;
|
|
444
|
+
this.deps.emit("run.continuity", {
|
|
445
|
+
harness_id: this.deps.adapter.id,
|
|
446
|
+
attempt_id: this.deps.attemptId,
|
|
447
|
+
session_id: runSpec.session_id,
|
|
448
|
+
receipt: continuityReceipt({
|
|
449
|
+
deps: this.deps,
|
|
450
|
+
continued,
|
|
451
|
+
tryIndex: this.tryIndex,
|
|
452
|
+
requestedModel: this.tryRequestedModel,
|
|
453
|
+
observedModel: this.tryModel,
|
|
454
|
+
nativeRejected: this.nativeRejected,
|
|
455
|
+
identity: this.tryIdentity,
|
|
456
|
+
reingestedTokens: this.tryFirstInputTokens,
|
|
457
|
+
}),
|
|
458
|
+
});
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
function codeOf(error) {
|
|
462
|
+
const code = error.code;
|
|
463
|
+
return typeof code === "string" ? code : null;
|
|
464
|
+
}
|
|
465
|
+
//# sourceMappingURL=inrun-continuity.js.map
|