@claudexor/orchestrator 3.17.2 → 3.19.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/auth-route-classification.d.ts +22 -1
- package/dist/auth-route-classification.d.ts.map +1 -1
- package/dist/auth-route-classification.js +38 -0
- package/dist/auth-route-classification.js.map +1 -1
- package/dist/candidateEvidence.js +1 -1
- package/dist/candidateEvidence.js.map +1 -1
- package/dist/continuity-facts.d.ts +2 -0
- package/dist/continuity-facts.d.ts.map +1 -1
- package/dist/continuity-facts.js +2 -0
- package/dist/continuity-facts.js.map +1 -1
- package/dist/continuity-summary.d.ts +3 -0
- package/dist/continuity-summary.d.ts.map +1 -1
- package/dist/continuity-summary.js +4 -3
- package/dist/continuity-summary.js.map +1 -1
- package/dist/deepScanReducer.js +1 -1
- package/dist/deepScanReducer.js.map +1 -1
- package/dist/modelGovernance.d.ts +5 -31
- package/dist/modelGovernance.d.ts.map +1 -1
- package/dist/modelGovernance.js +49 -4
- package/dist/modelGovernance.js.map +1 -1
- package/dist/orchestrator-credentials.d.ts +19 -2
- package/dist/orchestrator-credentials.d.ts.map +1 -1
- package/dist/orchestrator-credentials.js +34 -2
- package/dist/orchestrator-credentials.js.map +1 -1
- package/dist/orchestrator.d.ts +7 -11
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +77 -96
- package/dist/orchestrator.js.map +1 -1
- package/dist/planRun.d.ts +2 -5
- package/dist/planRun.d.ts.map +1 -1
- package/dist/planRun.js +11 -13
- package/dist/planRun.js.map +1 -1
- package/dist/plannerAttempt.d.ts +15 -4
- package/dist/plannerAttempt.d.ts.map +1 -1
- package/dist/plannerAttempt.js +52 -26
- package/dist/plannerAttempt.js.map +1 -1
- package/dist/processing-dispatch.d.ts +7 -5
- package/dist/processing-dispatch.d.ts.map +1 -1
- package/dist/processing-dispatch.js +65 -31
- package/dist/processing-dispatch.js.map +1 -1
- package/package.json +17 -17
package/dist/orchestrator.js
CHANGED
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import { applyWorkEnvelope, promptWithPointers as renderPromptWithPointers, threadContextPointer, } from "./prompt-framing.js";
|
|
2
2
|
import { requestRefusalFailure } from "./runTerminalResults.js";
|
|
3
3
|
import { delegationBeltFor } from "./delegationBelt.js";
|
|
4
|
-
import { bindProcessingAdmission, processingAdmissionForLease, updateProcessingStreamHold, ProcessingBudgetAdmissionError, } from "./processing-dispatch.js";
|
|
4
|
+
import { bindProcessingAdmission, processingAttemptCostEvidence, processingAdmissionForLease, updateProcessingStreamHold, ProcessingBudgetAdmissionError, } from "./processing-dispatch.js";
|
|
5
5
|
import { cancelledCandidatesResult, emptyCandidateResult, failedCandidatesResult, } from "./candidateTerminals.js";
|
|
6
6
|
import { existsSync } from "node:fs";
|
|
7
7
|
import { effectiveAuthPreference, observeNativeSessionEvent, resumeSessionForProfile, rotateSpecOnTypedLimit, } from "./credential-profiles.js";
|
|
8
|
-
import { OrchestratorCredentials, reviewerProfileResolver, rotatedSpecInLaneHome, } from "./orchestrator-credentials.js";
|
|
8
|
+
import { AdmissionProfileProbes, OrchestratorCredentials, reviewerProfileResolver, rotatedSpecInLaneHome, } from "./orchestrator-credentials.js";
|
|
9
9
|
import { accountPoolRows } from "./account-pool.js";
|
|
10
10
|
import { writeRunTelemetryArtifact } from "./runTelemetryWriter.js";
|
|
11
11
|
import { buildFileBackedSynthesisInput, materializeWinnerOutputs, stageFileBackedContext, writeCandidateAttemptArtifacts, } from "./candidateOutputs.js";
|
|
@@ -18,13 +18,13 @@ import { capabilityIntents } from "@claudexor/gateway";
|
|
|
18
18
|
import { reviewCandidateRuns, resolveEngineReview, unreviewedCandidateEvidence, evaluateUnreviewedConvergence, } from "./candidateReview.js";
|
|
19
19
|
import { join } from "node:path";
|
|
20
20
|
import { finalizePlanRun, runCouncilPlan, writePlanHarnessFailure, } from "./planRun.js";
|
|
21
|
-
import { runPlannerAttempt as executePlannerAttempt, } from "./plannerAttempt.js";
|
|
21
|
+
import { runPlannerAttempt as executePlannerAttempt, plannerAttemptSummary, } from "./plannerAttempt.js";
|
|
22
22
|
import { HarnessRunSpec, MAX_COUNCIL_MEMBERS_DEFAULT, ModeKind as ModeKindSchema, QuotaSnapshot as QuotaSnapshotSchema, isBlocking, makeOutcomeFacts, reviewAllowsApply, workStateVetoes, strictifyOutputSchema, estimateEffectiveAuthRoute, } from "@claudexor/schema";
|
|
23
23
|
import { globalConfigDir, loadConfig } from "@claudexor/config";
|
|
24
24
|
import { prepareRoutedProcessing, processingCostEvidence, prepareReviewerProcessing, } from "./processing-routing.js";
|
|
25
25
|
import { acceptedTryOutput, AccessProfileIncompatibleError, AnswerAssembly, CLAUDEXOR_BROWSER_ARTIFACT_SUBDIR, countsAsAgentProgress, HarnessUnavailableError, summarizeDiffPaths as diffStats, withInactivityWatchdog, } from "@claudexor/core";
|
|
26
26
|
import { assertRouteModelsAllowed, runModelGovernedRoute } from "./modelGovernance.js";
|
|
27
|
-
import { authModeForCredentialRoute, authModeForPreference } from "./auth-route-classification.js";
|
|
27
|
+
import { authModeForCredentialRoute, authModeForPreference, authRouteEvidenceFor, } from "./auth-route-classification.js";
|
|
28
28
|
import { governRouteEffort } from "./effortGovernance.js";
|
|
29
29
|
import { isFullAccess, RequestRequirementsResolver } from "./requestRequirements.js";
|
|
30
30
|
import { activateDelegationParent } from "./delegation-parent-activation.js";
|
|
@@ -69,7 +69,7 @@ import { HarnessGateway } from "@claudexor/gateway";
|
|
|
69
69
|
import { ReadinessLedger, evaluateConvergence, failureSignature, gatesPassed, reviewCandidate, runGates, } from "@claudexor/review";
|
|
70
70
|
import { arbitrate } from "@claudexor/arbitration";
|
|
71
71
|
import { buildSynthesisPlan, decideSynthesis } from "@claudexor/synthesis";
|
|
72
|
-
import {
|
|
72
|
+
import { billingKnowledgeForAuthRoute, attemptUsageCostSettlement, BudgetLedger, isBudgetTerminal, RoutingPreflightError, explainRanking, loadHarnessMetrics, promptFingerprint, rankHarnesses, } from "@claudexor/budget";
|
|
73
73
|
import { readTextSafe, appendLine, assertNoInlineSecretValues, hashJson, newId, noProjectRepoRoot, redactSecrets, safeInvoke, sha256, userConfigDir, } from "@claudexor/util";
|
|
74
74
|
const LABELS = "ABCDEFGHIJ".split("");
|
|
75
75
|
const NO_PROJECT_ROOT = noProjectRepoRoot();
|
|
@@ -489,9 +489,11 @@ export class Orchestrator {
|
|
|
489
489
|
dropped.push(detail);
|
|
490
490
|
droppedLanes.push({ harnessId, stage, detail });
|
|
491
491
|
};
|
|
492
|
-
//
|
|
493
|
-
//
|
|
492
|
+
// Initial lane readiness shares one quota observation. Selection and each
|
|
493
|
+
// physical dispatch still consume the latest exact-profile evidence.
|
|
494
494
|
const vendorQuota = this.credentials.vendorQuotaObservations();
|
|
495
|
+
// Billing later reuses the probe that admitted each row (#260).
|
|
496
|
+
const admissionProbes = new AdmissionProfileProbes();
|
|
495
497
|
const liveUnusable = this.deps.credentialUnusable?.() ?? [];
|
|
496
498
|
for (const id of ids) {
|
|
497
499
|
const adapter = this.deps.registry.get(id);
|
|
@@ -558,6 +560,7 @@ export class Orchestrator {
|
|
|
558
560
|
// the profile's transport, so the default store's state is not the
|
|
559
561
|
// routing truth). Capability/manifest gating above still applies.
|
|
560
562
|
const profileAdapter = this.deps.registry.get(id);
|
|
563
|
+
const profileProbe = admissionProbes.record(profileAdapter?.probeCredentialProfile?.bind(profileAdapter));
|
|
561
564
|
const explicitPin = this.credentials.effectiveProfileId(input, id);
|
|
562
565
|
// Pins and bound/pool rows are checked against their own readiness.
|
|
563
566
|
const rows = await this.credentials.admitRouteRows({
|
|
@@ -567,7 +570,7 @@ export class Orchestrator {
|
|
|
567
570
|
model: input.models?.[id] ?? cfgEntry?.default_model ?? null,
|
|
568
571
|
quota: vendorQuota,
|
|
569
572
|
unusable: liveUnusable,
|
|
570
|
-
probe:
|
|
573
|
+
probe: profileProbe,
|
|
571
574
|
});
|
|
572
575
|
const profileAdmitted = rows.admitted;
|
|
573
576
|
if (profileAdmitted) {
|
|
@@ -661,7 +664,7 @@ export class Orchestrator {
|
|
|
661
664
|
// the default store's sources apply only to profile-less runs.
|
|
662
665
|
authRouteEstimate: this.credentials.profileAuthRoute(input, id) ??
|
|
663
666
|
estimateEffectiveAuthRoute(this.authPreferenceForHarness(input.repoRoot, id, input.authPreference), status.authSources),
|
|
664
|
-
quotaAdmission: { model: null, profile: null, route: null },
|
|
667
|
+
quotaAdmission: { model: null, profile: null, route: null, profileVerification: null },
|
|
665
668
|
supportsSynthesize: manifest.capabilities.synthesize,
|
|
666
669
|
supportsInteractive: manifest.capabilities.interactive,
|
|
667
670
|
liveInput: manifest.capability_profile.live_input,
|
|
@@ -706,7 +709,7 @@ export class Orchestrator {
|
|
|
706
709
|
const model = input.models?.[routed.adapter.id] ?? routed.settings?.defaultModel ?? null;
|
|
707
710
|
let profile;
|
|
708
711
|
try {
|
|
709
|
-
profile = await this.credentials.preflightProfile(input, routed.adapter.id, model, log, routed.authRouteEstimate);
|
|
712
|
+
profile = await this.credentials.preflightProfile(input, routed.adapter.id, model, log, routed.authRouteEstimate, admissionProbes);
|
|
710
713
|
}
|
|
711
714
|
catch (err) {
|
|
712
715
|
// AUTO drops typed lane-local unavailability only when a sibling
|
|
@@ -730,8 +733,16 @@ export class Orchestrator {
|
|
|
730
733
|
: routed.authRouteEstimate === "local_session"
|
|
731
734
|
? "vendor_native"
|
|
732
735
|
: null;
|
|
736
|
+
const profileVerification = profile
|
|
737
|
+
? await this.credentials.selectedProfileBillingVerification(profile, admissionProbes)
|
|
738
|
+
: null;
|
|
733
739
|
return {
|
|
734
|
-
prepared: {
|
|
740
|
+
prepared: {
|
|
741
|
+
...routed,
|
|
742
|
+
quotaAdmission: { model, profile, route, profileVerification },
|
|
743
|
+
paidFallback: this.config(input.repoRoot).global.routing.paid_fallback,
|
|
744
|
+
billingVerificationForProfile: (actual) => this.credentials.selectedProfileBillingVerification(actual),
|
|
745
|
+
},
|
|
735
746
|
refused: null,
|
|
736
747
|
};
|
|
737
748
|
}));
|
|
@@ -862,13 +873,14 @@ export class Orchestrator {
|
|
|
862
873
|
// engine default. Profile A's cooldown never excludes profile B or the
|
|
863
874
|
// default on the same harness and route.
|
|
864
875
|
const credentialSubjectId = r.quotaAdmission.profile?.profile_id ?? null;
|
|
865
|
-
// QA-034: the typed auth-route evidence (
|
|
866
|
-
//
|
|
867
|
-
//
|
|
876
|
+
// QA-034: the typed auth-route evidence (the admitted profile's own
|
|
877
|
+
// verification, else doctor source verification, x the resolved route)
|
|
878
|
+
// is AUTHORITATIVE for billing knowledge in the router — a VERIFIED
|
|
879
|
+
// native route proves subscription_entitlement, so it survives
|
|
868
880
|
// paid_fallback:never and ranks with a real economy tuple instead of
|
|
869
881
|
// reading as unknown/paid. Absent (unknown route) falls back to the
|
|
870
882
|
// metric-derived billingKnowledge below.
|
|
871
|
-
const authRoute =
|
|
883
|
+
const authRoute = authRouteEvidenceFor(authMode, status?.authSources ?? [], r.quotaAdmission.profileVerification);
|
|
872
884
|
const processingCost = processingCostEvidence(r.processing, authRoute ? billingKnowledgeForAuthRoute(authRoute) : "unknown", [`harness:${r.adapter.id}`, `profile:${credentialSubjectId ?? "default"}`]);
|
|
873
885
|
return {
|
|
874
886
|
harnessId: r.adapter.id,
|
|
@@ -968,30 +980,6 @@ export class Orchestrator {
|
|
|
968
980
|
},
|
|
969
981
|
};
|
|
970
982
|
}
|
|
971
|
-
/**
|
|
972
|
-
* Typed auth-route evidence for one candidate (QA-034): the concrete
|
|
973
|
-
* credential route the resolved auth mode maps to, plus the doctor's
|
|
974
|
-
* verification for the source that route runs under. `local_session` →
|
|
975
|
-
* vendor_native + the native/OAuth source verification; `api_key` →
|
|
976
|
-
* managed_api_key + the key source verification. Unknown route → no evidence
|
|
977
|
-
* (the router keeps its conservative metric-derived billing). Verification is
|
|
978
|
-
* the source's typed verdict — never inferred from mere availability.
|
|
979
|
-
*/
|
|
980
|
-
authRouteEvidenceFor(authMode, sources) {
|
|
981
|
-
const usable = (s) => s.availability === "available" && s.verification !== "failed";
|
|
982
|
-
if (authMode === "local_session") {
|
|
983
|
-
const native = sources.find((s) => usable(s) && (s.source === "native_session" || s.source === "oauth_token_env"));
|
|
984
|
-
return { route: "vendor_native", verification: native?.verification ?? "not_run" };
|
|
985
|
-
}
|
|
986
|
-
if (authMode === "api_key") {
|
|
987
|
-
const key = sources.find((s) => usable(s) &&
|
|
988
|
-
(s.source === "api_key_env" ||
|
|
989
|
-
s.source === "api_key_flag" ||
|
|
990
|
-
s.source === "provider_auth_file"));
|
|
991
|
-
return { route: "managed_api_key", verification: key?.verification ?? "not_run" };
|
|
992
|
-
}
|
|
993
|
-
return undefined;
|
|
994
|
-
}
|
|
995
983
|
/**
|
|
996
984
|
* Lazy ContextPack: built ONLY for the read-only report modes
|
|
997
985
|
* (explore/plan/readonly_audit) that consume it. Persisted to
|
|
@@ -1234,6 +1222,8 @@ export class Orchestrator {
|
|
|
1234
1222
|
processing,
|
|
1235
1223
|
processingAdmission,
|
|
1236
1224
|
physicalDispatchStarted,
|
|
1225
|
+
billingVerificationForProfile: (profile) => this.credentials.selectedProfileBillingVerification(profile),
|
|
1226
|
+
paidFallback: this.config(runInput.repoRoot).global.routing.paid_fallback,
|
|
1237
1227
|
});
|
|
1238
1228
|
const result = buildContinuation(req);
|
|
1239
1229
|
// Disclose on every lane and stamp the turn (INV-137: never silent).
|
|
@@ -1319,7 +1309,7 @@ export class Orchestrator {
|
|
|
1319
1309
|
const sessionFields = runInput
|
|
1320
1310
|
? await this.sessionSpecFields(runInput, adapter.id, knobs.model, log, routed.authRouteEstimate, routed.quotaAdmission)
|
|
1321
1311
|
: undefined;
|
|
1322
|
-
const processingAdmission = processingAdmissionForLease(ledger, processingLease.
|
|
1312
|
+
const processingAdmission = processingAdmissionForLease(ledger, processingLease.lease, adapter.id, attemptId, processingLease.onDenied);
|
|
1323
1313
|
const capturedProcessing = {
|
|
1324
1314
|
processing_preference: contract.processing_preference,
|
|
1325
1315
|
processing: knobs.processing?.receipt,
|
|
@@ -1327,7 +1317,7 @@ export class Orchestrator {
|
|
|
1327
1317
|
processing_allow_paid: knobs.processingAllowPaid,
|
|
1328
1318
|
};
|
|
1329
1319
|
const laneContinuity = runInput
|
|
1330
|
-
? await this.resolveContinuity(runInput, adapter.id, sessionFields?.credential_profile?.profile_id ?? runInput.credentialProfileId ?? null, inPlaceEnvelope && !!sessionFields?.resume_session_id, sessionFields, store, paths, envelope.repo_root, log, capturedProcessing, processingAdmission, () => ledger.markPhysicalDispatchStarted(processingLease.
|
|
1320
|
+
? await this.resolveContinuity(runInput, adapter.id, sessionFields?.credential_profile?.profile_id ?? runInput.credentialProfileId ?? null, inPlaceEnvelope && !!sessionFields?.resume_session_id, sessionFields, store, paths, envelope.repo_root, log, capturedProcessing, processingAdmission, () => ledger.markPhysicalDispatchStarted(processingLease.lease.lease_id))
|
|
1331
1321
|
: null;
|
|
1332
1322
|
const artifactRelativeDir = routed.browserRequirement.effective
|
|
1333
1323
|
? (wsm.ensureArtifactDirectory(envelope), wsm.ownedArtifactRelativeDirectory(envelope))
|
|
@@ -1372,16 +1362,12 @@ export class Orchestrator {
|
|
|
1372
1362
|
});
|
|
1373
1363
|
if (runInput)
|
|
1374
1364
|
this.credentials.stampProfileSelection(spec, runInput, adapter.id);
|
|
1375
|
-
bindProcessingAdmission(spec, ledger, processingLease.
|
|
1376
|
-
|
|
1377
|
-
//
|
|
1378
|
-
|
|
1379
|
-
|
|
1380
|
-
|
|
1381
|
-
? "metered"
|
|
1382
|
-
: actual.credential_profile
|
|
1383
|
-
? "subscription_entitlement"
|
|
1384
|
-
: this.routeBillingKnowledge(billingInput, adapter.id);
|
|
1365
|
+
bindProcessingAdmission(spec, ledger, processingLease.lease, adapter.id, attemptId, processingLease.onDenied, processingAdmission);
|
|
1366
|
+
// Profile-less processing keeps its existing route estimate. Named rows
|
|
1367
|
+
// receive their own verification at the shared physical-dispatch gate.
|
|
1368
|
+
spec.extra["routeBillingKnowledge"] = (actual) => actual.credential_profile
|
|
1369
|
+
? "unknown"
|
|
1370
|
+
: this.routeBillingKnowledge(runInput ?? { repoRoot: contract.repo.root }, adapter.id);
|
|
1385
1371
|
if (interaction)
|
|
1386
1372
|
spec.extra["interactionChannel"] = interaction;
|
|
1387
1373
|
const workEnvelope = this.workReportEnvelopeFor(routed, contract, Boolean(interaction));
|
|
@@ -1554,7 +1540,8 @@ export class Orchestrator {
|
|
|
1554
1540
|
// gate and required-actions read a typed category, not a bare boolean.
|
|
1555
1541
|
harnessErrored = true;
|
|
1556
1542
|
errors.push(safeErrorMessage(err));
|
|
1557
|
-
if (err instanceof ProcessingBudgetAdmissionError
|
|
1543
|
+
if (err instanceof ProcessingBudgetAdmissionError ||
|
|
1544
|
+
err instanceof RoutingPreflightError) {
|
|
1558
1545
|
processingRefusal = err;
|
|
1559
1546
|
break;
|
|
1560
1547
|
}
|
|
@@ -1948,7 +1935,7 @@ export class Orchestrator {
|
|
|
1948
1935
|
attemptId,
|
|
1949
1936
|
intent: this.candidateIntent(input),
|
|
1950
1937
|
harnessId: routed.adapter.id,
|
|
1951
|
-
cost:
|
|
1938
|
+
cost: processingAttemptCostEvidence(routed.adapter.id, attemptId, this.reservationEstimateUsd(input, i > 0), this.routeBillingKnowledge(input, routed.adapter.id, routed), routed.processing),
|
|
1952
1939
|
});
|
|
1953
1940
|
log.emit("budget.lease.created", {
|
|
1954
1941
|
granted: lease.granted,
|
|
@@ -1973,7 +1960,7 @@ export class Orchestrator {
|
|
|
1973
1960
|
routed,
|
|
1974
1961
|
attemptId,
|
|
1975
1962
|
label: `Candidate ${LABELS[i] ?? i + 1}`,
|
|
1976
|
-
|
|
1963
|
+
lease: lease.lease,
|
|
1977
1964
|
});
|
|
1978
1965
|
}
|
|
1979
1966
|
const runsBySlot = new Array(slots.length);
|
|
@@ -1984,14 +1971,14 @@ export class Orchestrator {
|
|
|
1984
1971
|
let candidateContinuationCount = 0;
|
|
1985
1972
|
const runSlot = async (slot, slotIdx) => {
|
|
1986
1973
|
if (input.signal?.aborted) {
|
|
1987
|
-
ledger.cancel(slot.
|
|
1974
|
+
ledger.cancel(slot.lease.lease_id);
|
|
1988
1975
|
return;
|
|
1989
1976
|
}
|
|
1990
1977
|
// Leases are granted upfront (before spend exists); a worker still
|
|
1991
1978
|
// re-checks the circuit breaker so queued slots beyond the parallel wave
|
|
1992
1979
|
// do not start after earlier candidates already blew the hard cap.
|
|
1993
1980
|
if (budgetStopped || ledger.tier() === "hard") {
|
|
1994
|
-
ledger.cancel(slot.
|
|
1981
|
+
ledger.cancel(slot.lease.lease_id);
|
|
1995
1982
|
log.emit("budget.lease.created", {
|
|
1996
1983
|
granted: false,
|
|
1997
1984
|
reason: "budget exhausted (hard cap reached)",
|
|
@@ -2055,7 +2042,7 @@ export class Orchestrator {
|
|
|
2055
2042
|
});
|
|
2056
2043
|
harnessHome = this.harnessHomeFor(wsm, envelope, slot.routed, input);
|
|
2057
2044
|
const run = await this.runCandidateInEnvelope(slot.routed, envelope, slot.attemptId, slot.label, contract, input.prompt, store, paths, wsm, ledger, {
|
|
2058
|
-
|
|
2045
|
+
lease: slot.lease,
|
|
2059
2046
|
onDenied: (denial) => {
|
|
2060
2047
|
budgetStopped = true;
|
|
2061
2048
|
budgetDenial ??= denial;
|
|
@@ -2065,14 +2052,14 @@ export class Orchestrator {
|
|
|
2065
2052
|
safeInvoke(input.onHarnessEvent, safeEv);
|
|
2066
2053
|
log.emit("harness.event", harnessEventPayload(adapter.id, slot.attemptId, safeEv));
|
|
2067
2054
|
}, input.signal, downgradeModel ?? undefined, input.effort, this.candidateIntent(input), log, effectiveWeb, this.interactionChannelFor(input, log, runId, taskId, slot.attemptId, adapter.id, slot.routed.supportsInteractive), (streamedUsd) => {
|
|
2068
|
-
ledger.updateHold(slot.
|
|
2055
|
+
ledger.updateHold(slot.lease.lease_id, streamedUsd);
|
|
2069
2056
|
if (ledger.tier() !== "hard")
|
|
2070
2057
|
return false;
|
|
2071
2058
|
budgetStopped = true;
|
|
2072
2059
|
return true;
|
|
2073
2060
|
}, input, requestedSingleCandidate, // W-C4 deltas: single-candidate chat lane only (racing = noise x N)
|
|
2074
2061
|
undefined, undefined, harnessHome);
|
|
2075
|
-
ledger.settle(slot.
|
|
2062
|
+
ledger.settle(slot.lease.lease_id, attemptUsageCostSettlement(run.cost, run.costEstimated, run.attemptId, run.harnessId, run.telemetry.authMode, run.telemetry.usageCost));
|
|
2076
2063
|
log.emit("harness.completed", {
|
|
2077
2064
|
harness_id: adapter.id,
|
|
2078
2065
|
attempt_id: slot.attemptId,
|
|
@@ -2118,7 +2105,7 @@ export class Orchestrator {
|
|
|
2118
2105
|
attemptId: contAttemptId,
|
|
2119
2106
|
intent: this.candidateIntent(input),
|
|
2120
2107
|
harnessId: adapter.id,
|
|
2121
|
-
cost:
|
|
2108
|
+
cost: processingAttemptCostEvidence(adapter.id, contAttemptId, this.estimateUsdFloor(input.repoRoot), this.routeBillingKnowledge(input, adapter.id, slot.routed), slot.routed.processing),
|
|
2122
2109
|
});
|
|
2123
2110
|
if (contLease.granted) {
|
|
2124
2111
|
candidateContinuationCount += 1; // claim the one-shot only once it launches
|
|
@@ -2138,7 +2125,7 @@ export class Orchestrator {
|
|
|
2138
2125
|
const contLeaseId = contLease.lease?.lease_id ?? "";
|
|
2139
2126
|
try {
|
|
2140
2127
|
const contRun = await this.runCandidateInEnvelope(slot.routed, envelope, contAttemptId, slot.label, contract, input.prompt, store, paths, wsm, ledger, {
|
|
2141
|
-
|
|
2128
|
+
lease: contLease.lease,
|
|
2142
2129
|
onDenied: (denial) => {
|
|
2143
2130
|
budgetStopped = true;
|
|
2144
2131
|
budgetDenial ??= denial;
|
|
@@ -2197,7 +2184,7 @@ export class Orchestrator {
|
|
|
2197
2184
|
}
|
|
2198
2185
|
catch (err) {
|
|
2199
2186
|
const failureCost = AC.attemptFailureCost(err, "post-stream-error", 0);
|
|
2200
|
-
ledger.settle(slot.
|
|
2187
|
+
ledger.settle(slot.lease.lease_id, failureCost.settlement);
|
|
2201
2188
|
const message = safeErrorMessage(err);
|
|
2202
2189
|
const declared = declaredFailure(err);
|
|
2203
2190
|
const infraPhase = envelope === undefined ? "workspace" : "harness";
|
|
@@ -2404,7 +2391,7 @@ export class Orchestrator {
|
|
|
2404
2391
|
attemptId: "synth",
|
|
2405
2392
|
intent: "synthesize",
|
|
2406
2393
|
harnessId: synthRouted.adapter.id,
|
|
2407
|
-
cost:
|
|
2394
|
+
cost: processingAttemptCostEvidence(synthRouted.adapter.id, "synth", this.reservationEstimateUsd(input), this.routeBillingKnowledge(input, synthRouted.adapter.id, synthRouted), synthRouted.processing),
|
|
2408
2395
|
});
|
|
2409
2396
|
if (lease.granted) {
|
|
2410
2397
|
let envelope;
|
|
@@ -2431,7 +2418,7 @@ export class Orchestrator {
|
|
|
2431
2418
|
});
|
|
2432
2419
|
const synthHome = this.harnessHomeFor(wsm, envelope, synthRouted, input);
|
|
2433
2420
|
const run = await this.runCandidateInEnvelope(synthRouted, envelope, "synth", "Synthesis", contract, synthesisInput.prompt, store, paths, wsm, ledger, {
|
|
2434
|
-
|
|
2421
|
+
lease: lease.lease,
|
|
2435
2422
|
onDenied: (denial) => {
|
|
2436
2423
|
budgetStopped = true;
|
|
2437
2424
|
budgetDenial ??= denial;
|
|
@@ -3211,7 +3198,7 @@ export class Orchestrator {
|
|
|
3211
3198
|
attemptId,
|
|
3212
3199
|
intent: "repair",
|
|
3213
3200
|
harnessId: adapter.id,
|
|
3214
|
-
cost:
|
|
3201
|
+
cost: processingAttemptCostEvidence(adapter.id, attemptId, this.reservationEstimateUsd(input), this.routeBillingKnowledge(input, adapter.id, routed), routed.processing),
|
|
3215
3202
|
});
|
|
3216
3203
|
if (!lease.granted) {
|
|
3217
3204
|
exhausted = true;
|
|
@@ -3230,7 +3217,7 @@ export class Orchestrator {
|
|
|
3230
3217
|
...(knobs.ignored.length > 0 ? { ignored_settings: knobs.ignored } : {}),
|
|
3231
3218
|
});
|
|
3232
3219
|
run = await this.runCandidateInEnvelope(routed, envelope, attemptId, `Attempt ${attempt}`, contract, prompt, store, paths, wsm, ledger, {
|
|
3233
|
-
|
|
3220
|
+
lease: lease.lease,
|
|
3234
3221
|
onDenied: (denial) => {
|
|
3235
3222
|
exhausted = true;
|
|
3236
3223
|
processingBudgetDenial ??= denial;
|
|
@@ -3796,17 +3783,17 @@ export class Orchestrator {
|
|
|
3796
3783
|
/** Bind private route/session preparation to the planner-attempt owner. */
|
|
3797
3784
|
plannerAttemptDeps() {
|
|
3798
3785
|
return {
|
|
3799
|
-
billingKnowledge: (input, harnessId) => this.routeBillingKnowledge(input, harnessId),
|
|
3786
|
+
billingKnowledge: (input, harnessId, routed) => this.routeBillingKnowledge(input, harnessId, routed),
|
|
3800
3787
|
inactivityTimeoutMs: (repoRoot) => harnessInactivityTimeoutMs(this.config(repoRoot)),
|
|
3801
3788
|
quotaEventSink: this.deps.quotaEventSink,
|
|
3802
|
-
prepare: async (args) => {
|
|
3789
|
+
prepare: async (args, processingAdmission, physicalDispatchStarted) => {
|
|
3803
3790
|
const { input, contract, taskId, runId, log, store, paths, routed, attemptId } = args;
|
|
3804
3791
|
const adapter = routed.adapter;
|
|
3805
3792
|
const knobs = this.routeSpecKnobs(routed, contract, undefined, input.effort);
|
|
3806
3793
|
const effectiveWeb = this.discloseWebUpgrade(log, routed, knobs.webPolicy, attemptId);
|
|
3807
3794
|
const sessionFields = await this.sessionSpecFields(input, adapter.id, knobs.model, log, routed.authRouteEstimate, routed.quotaAdmission);
|
|
3808
3795
|
const laneContinuity = args.laneRun
|
|
3809
|
-
? await this.resolveContinuity(input, adapter.id, sessionFields.credential_profile?.profile_id ?? input.credentialProfileId ?? null, sessionFields.resume_session_id !== null, sessionFields, store, paths, this.execRootOf(input), log)
|
|
3796
|
+
? await this.resolveContinuity(input, adapter.id, sessionFields.credential_profile?.profile_id ?? input.credentialProfileId ?? null, sessionFields.resume_session_id !== null, sessionFields, store, paths, this.execRootOf(input), log, this.harnessSpecKnobs(contract, knobs, args.intent), processingAdmission, physicalDispatchStarted)
|
|
3810
3797
|
: null;
|
|
3811
3798
|
const spec = HarnessRunSpec.parse({
|
|
3812
3799
|
session_id: newId("ses"),
|
|
@@ -3995,13 +3982,7 @@ export class Orchestrator {
|
|
|
3995
3982
|
// terminal names the refused route and does not read "all planners
|
|
3996
3983
|
// failed"; capture the typed denial for the budget classifier.
|
|
3997
3984
|
planBudgetDenial ??= outcome.budgetDenial ?? null;
|
|
3998
|
-
planAttempts.push(
|
|
3999
|
-
attemptId,
|
|
4000
|
-
harnessId: outcome.harnessId,
|
|
4001
|
-
status: outcome.status,
|
|
4002
|
-
outcomeClass: outcome.outcomeClass,
|
|
4003
|
-
error: outcome.error,
|
|
4004
|
-
});
|
|
3985
|
+
planAttempts.push(plannerAttemptSummary(outcome));
|
|
4005
3986
|
break;
|
|
4006
3987
|
}
|
|
4007
3988
|
if (outcome.telemetry)
|
|
@@ -4010,13 +3991,7 @@ export class Orchestrator {
|
|
|
4010
3991
|
harnessId: outcome.harnessId,
|
|
4011
3992
|
telemetry: outcome.telemetry,
|
|
4012
3993
|
});
|
|
4013
|
-
planAttempts.push(
|
|
4014
|
-
attemptId,
|
|
4015
|
-
harnessId: outcome.harnessId,
|
|
4016
|
-
status: outcome.status,
|
|
4017
|
-
outcomeClass: outcome.outcomeClass,
|
|
4018
|
-
error: outcome.error,
|
|
4019
|
-
});
|
|
3994
|
+
planAttempts.push(plannerAttemptSummary(outcome));
|
|
4020
3995
|
if (outcome.status !== "success") {
|
|
4021
3996
|
if (outcome.telemetry?.effortResolution?.resolution === "rejected")
|
|
4022
3997
|
break;
|
|
@@ -4141,7 +4116,13 @@ export class Orchestrator {
|
|
|
4141
4116
|
quotaSnapshotPreflight() {
|
|
4142
4117
|
return [...(this.deps.quotaSnapshots?.() ?? [])].map((snapshot) => QuotaSnapshotSchema.parse(snapshot));
|
|
4143
4118
|
}
|
|
4144
|
-
routeBillingKnowledge(input, harnessId) {
|
|
4119
|
+
routeBillingKnowledge(input, harnessId, routed) {
|
|
4120
|
+
if (routed?.quotaAdmission.profile) {
|
|
4121
|
+
return billingKnowledgeForAuthRoute({
|
|
4122
|
+
route: routed.quotaAdmission.route,
|
|
4123
|
+
verification: routed.quotaAdmission.profileVerification ?? "not_run",
|
|
4124
|
+
});
|
|
4125
|
+
}
|
|
4145
4126
|
// A selected profile's credential_kind decides billing (round-18 #2).
|
|
4146
4127
|
const profileRoute = this.credentials.profileAuthRoute(input, harnessId);
|
|
4147
4128
|
if (profileRoute)
|
|
@@ -4173,9 +4154,7 @@ export class Orchestrator {
|
|
|
4173
4154
|
// The reducer admits under a finite estimate floor (mirror of the n>1
|
|
4174
4155
|
// scout reserve) so a subscription route is not refused for lacking a
|
|
4175
4156
|
// cash quote.
|
|
4176
|
-
|
|
4177
|
-
`harness:${harnessId}`,
|
|
4178
|
-
])),
|
|
4157
|
+
processingAttemptCostEvidence(harnessId, attemptId, this.estimateUsdFloor(input.repoRoot), this.routeBillingKnowledge(input, harnessId, routed), routed?.processing),
|
|
4179
4158
|
buildSpec: async (routed, homeEnv, prompt, attemptId) => {
|
|
4180
4159
|
const knobs = this.routeSpecKnobs(routed, contract, undefined, input.effort);
|
|
4181
4160
|
const effectiveWeb = this.discloseWebUpgrade(log, routed, knobs.webPolicy, attemptId);
|
|
@@ -4349,7 +4328,7 @@ export class Orchestrator {
|
|
|
4349
4328
|
// (mirror of the candidate loop): the first top-level scout reserves
|
|
4350
4329
|
// without a floor; later scouts and every real Delegate child pass the
|
|
4351
4330
|
// repo floor because they overlap an existing family unit.
|
|
4352
|
-
cost:
|
|
4331
|
+
cost: processingAttemptCostEvidence(adapter.id, attemptId, this.reservationEstimateUsd(input, opts.deepScan && idx > 0), this.routeBillingKnowledge(input, adapter.id, routed), routed.processing),
|
|
4353
4332
|
});
|
|
4354
4333
|
if (!lease.granted) {
|
|
4355
4334
|
log.emit("budget.lease.created", {
|
|
@@ -4378,6 +4357,10 @@ export class Orchestrator {
|
|
|
4378
4357
|
}
|
|
4379
4358
|
return { status: "budget_denied", reason: lease.reason ?? "budget lease denied" };
|
|
4380
4359
|
}
|
|
4360
|
+
const processingAdmission = processingAdmissionForLease(ledger, lease.lease, adapter.id, attemptId, (denial) => {
|
|
4361
|
+
budgetStopped = true;
|
|
4362
|
+
budgetDenial ??= denial;
|
|
4363
|
+
});
|
|
4381
4364
|
// As with planners, the granted lease owns profile/continuity/spec
|
|
4382
4365
|
// preparation. Contain a pre-stream rejection as this attempt's failure;
|
|
4383
4366
|
// parallel siblings can then finish before the shared HOME is disposed.
|
|
@@ -4398,7 +4381,7 @@ export class Orchestrator {
|
|
|
4398
4381
|
// scouts are excluded from laneRun); native resume is available only when
|
|
4399
4382
|
// this slot was granted the lane's recorded session.
|
|
4400
4383
|
const laneContinuity = laneRun
|
|
4401
|
-
? await this.resolveContinuity(input, adapter.id, sessionFields.credential_profile?.profile_id ?? input.credentialProfileId ?? null, grantResume, sessionFields, store, paths, this.execRootOf(input), log)
|
|
4384
|
+
? await this.resolveContinuity(input, adapter.id, sessionFields.credential_profile?.profile_id ?? input.credentialProfileId ?? null, grantResume, sessionFields, store, paths, this.execRootOf(input), log, this.harnessSpecKnobs(contract, knobs, opts.intent), processingAdmission, () => ledger.markPhysicalDispatchStarted(lease.lease.lease_id))
|
|
4402
4385
|
: null;
|
|
4403
4386
|
// D-16d: the continuation packet pointer rides after the lane pointer so
|
|
4404
4387
|
// the fresh session is re-grounded in the exhausted attempt's work.
|
|
@@ -4457,7 +4440,7 @@ export class Orchestrator {
|
|
|
4457
4440
|
const message = `read-only attempt setup failed: ${safeErrorMessage(preparation.error)}`;
|
|
4458
4441
|
AC.settleGrantedAttemptLease({
|
|
4459
4442
|
ledger,
|
|
4460
|
-
leaseId: lease.lease
|
|
4443
|
+
leaseId: lease.lease.lease_id,
|
|
4461
4444
|
attemptId,
|
|
4462
4445
|
harnessId: adapter.id,
|
|
4463
4446
|
costUsd: 0,
|
|
@@ -4490,10 +4473,7 @@ export class Orchestrator {
|
|
|
4490
4473
|
const { knobs, spec: preparedSpec, reportAbort, reportInteraction, readonlyWorkMode, attemptEventsPath, telemetry, } = preparation.value;
|
|
4491
4474
|
let { answer } = preparation.value;
|
|
4492
4475
|
let spec = preparedSpec;
|
|
4493
|
-
bindProcessingAdmission(spec, ledger, lease.lease
|
|
4494
|
-
budgetStopped = true;
|
|
4495
|
-
budgetDenial ??= denial;
|
|
4496
|
-
});
|
|
4476
|
+
bindProcessingAdmission(spec, ledger, lease.lease, adapter.id, attemptId, undefined, processingAdmission);
|
|
4497
4477
|
const retryPolicy = transientRetryPolicy(this.config(input.repoRoot));
|
|
4498
4478
|
let activeSessionId = spec.session_id;
|
|
4499
4479
|
const live = liveAttempt(input, routed, paths, contract, attemptId, () => activeSessionId);
|
|
@@ -4595,7 +4575,8 @@ export class Orchestrator {
|
|
|
4595
4575
|
}
|
|
4596
4576
|
catch (err) {
|
|
4597
4577
|
harnessError = safeErrorMessage(err);
|
|
4598
|
-
if (err instanceof ProcessingBudgetAdmissionError
|
|
4578
|
+
if (err instanceof ProcessingBudgetAdmissionError ||
|
|
4579
|
+
err instanceof RoutingPreflightError) {
|
|
4599
4580
|
processingRefusal = err;
|
|
4600
4581
|
break;
|
|
4601
4582
|
}
|
|
@@ -4676,7 +4657,7 @@ export class Orchestrator {
|
|
|
4676
4657
|
input.signal?.removeEventListener("abort", onAbort);
|
|
4677
4658
|
AC.settleGrantedAttemptLease({
|
|
4678
4659
|
ledger,
|
|
4679
|
-
leaseId: lease.lease
|
|
4660
|
+
leaseId: lease.lease.lease_id,
|
|
4680
4661
|
attemptId,
|
|
4681
4662
|
harnessId: adapter.id,
|
|
4682
4663
|
costUsd: cost,
|