@sema-agent/core 5.56.0 → 5.58.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/CHANGELOG.md +122 -0
- package/dist/agents/cascade.d.ts +1 -1
- package/dist/agents/cumulative-stats.d.ts +1 -1
- package/dist/agents/observer.d.ts +2 -2
- package/dist/agents/peer-admission.d.ts +1 -1
- package/dist/agents/retain-ledger.d.ts +2 -2
- package/dist/agents/roster-store.d.ts +8 -8
- package/dist/agents/send-message-tool.d.ts +13 -2
- package/dist/agents/send-message-tool.js +34 -12
- package/dist/agents/subagent-steps.d.ts +1 -1
- package/dist/agents/subagent.d.ts +13 -13
- package/dist/agents/team.d.ts +15 -6
- package/dist/agents/team.js +1 -0
- package/dist/agents/tool-filter.d.ts +2 -2
- package/dist/agents/verify.d.ts +1 -1
- package/dist/bench/metrics.d.ts +35 -35
- package/dist/brain/anthropic.js +15 -5
- package/dist/brain/circuit-breaker.js +2 -1
- package/dist/brain/degrading.d.ts +1 -1
- package/dist/brain/degrading.js +4 -1
- package/dist/brain/errors.d.ts +3 -3
- package/dist/brain/failover.js +16 -1
- package/dist/brain/open-responses.js +15 -5
- package/dist/brain/openai.js +16 -5
- package/dist/brain/reasoning.d.ts +2 -2
- package/dist/brain/repetition.d.ts +1 -1
- package/dist/brain/request-params.d.ts +30 -27
- package/dist/brain/request-params.js +1 -7
- package/dist/brain/route-adjudicator.d.ts +190 -0
- package/dist/brain/route-adjudicator.js +189 -0
- package/dist/brain/route-conformance.d.ts +55 -0
- package/dist/brain/route-conformance.js +136 -0
- package/dist/brain/routing.js +8 -3
- package/dist/brain/status-sink.d.ts +2 -2
- package/dist/brain/stream-shared.d.ts +1 -1
- package/dist/config/catalog.d.ts +5 -5
- package/dist/core/arg-summary.d.ts +4 -4
- package/dist/core/ask-class.d.ts +2 -2
- package/dist/core/ask-question.d.ts +1 -1
- package/dist/core/auto-compaction.d.ts +15 -15
- package/dist/core/auto-mode.d.ts +5 -5
- package/dist/core/background-agent-store.d.ts +20 -20
- package/dist/core/background-shell.d.ts +4 -4
- package/dist/core/checkpoint-store.d.ts +35 -27
- package/dist/core/context-edit.d.ts +1 -1
- package/dist/core/context-guard.d.ts +1 -1
- package/dist/core/exec-output-tail.d.ts +6 -6
- package/dist/core/file-snapshot-store.d.ts +8 -8
- package/dist/core/git-worktree-env.d.ts +3 -3
- package/dist/core/governance-codes.js +2 -0
- package/dist/core/hooks.d.ts +73 -33
- package/dist/core/hooks.js +87 -25
- package/dist/core/image-downsample.d.ts +1 -1
- package/dist/core/locked-config.d.ts +1 -1
- package/dist/core/lsp.d.ts +1 -1
- package/dist/core/mailbox-store.d.ts +1 -1
- package/dist/core/mcp.d.ts +3 -3
- package/dist/core/mcp.js +4 -4
- package/dist/core/memory-engine/consolidation-driver.d.ts +207 -0
- package/dist/core/memory-engine/consolidation-driver.js +378 -0
- package/dist/core/memory-engine/consolidation.d.ts +46 -2
- package/dist/core/memory-engine/consolidation.js +1 -0
- package/dist/core/memory-engine/data-plane.d.ts +1 -1
- package/dist/core/memory-engine/distiller.d.ts +550 -0
- package/dist/core/memory-engine/distiller.js +598 -0
- package/dist/core/memory-engine/dual-root.d.ts +1 -1
- package/dist/core/memory-engine/engine.d.ts +62 -8
- package/dist/core/memory-engine/engine.js +40 -4
- package/dist/core/memory-engine/file-backend.d.ts +1 -1
- package/dist/core/memory-engine/index.d.ts +4 -2
- package/dist/core/memory-engine/index.js +4 -2
- package/dist/core/memory-engine/origin-clearance.d.ts +1 -1
- package/dist/core/memory-engine/scope-contract.d.ts +4 -4
- package/dist/core/memory-engine/sync-client.d.ts +16 -16
- package/dist/core/memory-engine/sync.d.ts +4 -4
- package/dist/core/memory-recall.d.ts +1 -1
- package/dist/core/memory.d.ts +2 -2
- package/dist/core/permission-rule-consent.d.ts +230 -36
- package/dist/core/permission-rule-consent.js +258 -54
- package/dist/core/permission-rule-model.d.ts +295 -97
- package/dist/core/permission-rule-model.js +132 -41
- package/dist/core/permission-rules.d.ts +9 -9
- package/dist/core/remote-env.d.ts +8 -8
- package/dist/core/roles.d.ts +3 -3
- package/dist/core/roles.js +1 -0
- package/dist/core/runner/assemble-result.d.ts +2 -2
- package/dist/core/runner/compaction-call-options.d.ts +3 -3
- package/dist/core/runner/memory-consolidation-driver.d.ts +49 -0
- package/dist/core/runner/memory-consolidation-driver.js +60 -0
- package/dist/core/runner/memory-consolidation.d.ts +1 -1
- package/dist/core/runner/prepare-config-doors.d.ts +3 -3
- package/dist/core/runner/prepare-task.d.ts +21 -21
- package/dist/core/runner/prepare-task.js +54 -18
- package/dist/core/runner/prepare-workspace-restore.d.ts +2 -2
- package/dist/core/runner/runtask.d.ts +15 -12
- package/dist/core/runner/runtask.js +48 -0
- package/dist/core/runner/session-rule-policy.d.ts +1 -1
- package/dist/core/runner/teardown-bounded.d.ts +1 -1
- package/dist/core/runner/tool-disclosure.d.ts +2 -2
- package/dist/core/runner/turn-attachments.d.ts +11 -11
- package/dist/core/scheduler.d.ts +10 -5
- package/dist/core/secret-env.d.ts +1 -1
- package/dist/core/sensitive-path-policy.d.ts +1 -1
- package/dist/core/session-policy-store.d.ts +2 -2
- package/dist/core/session-reconcile.d.ts +2 -2
- package/dist/core/session-store.d.ts +3 -3
- package/dist/core/session.d.ts +1 -1
- package/dist/core/shutdown-debug.d.ts +2 -2
- package/dist/core/side-query.d.ts +14 -7
- package/dist/core/spec-contract.d.ts +1 -1
- package/dist/core/store-contracts/contract-harness.d.ts +2 -2
- package/dist/core/store-contracts/contract-kit-version.d.ts +2 -2
- package/dist/core/store-contracts/mailbox-store-contract.d.ts +1 -1
- package/dist/core/store-contracts/mailbox-store-contract.js +1 -1
- package/dist/core/task-notification.d.ts +5 -5
- package/dist/core/task-registry-agent.d.ts +12 -12
- package/dist/core/task-registry-monitor.d.ts +1 -1
- package/dist/core/task-registry-shared.d.ts +41 -41
- package/dist/core/task-registry.d.ts +12 -12
- package/dist/core/tool-detach.d.ts +2 -2
- package/dist/core/tool-errors.d.ts +3 -3
- package/dist/core/tool-policy.d.ts +55 -28
- package/dist/core/tool-result-budget.d.ts +1 -1
- package/dist/core/tool-result-store.d.ts +2 -2
- package/dist/core/tools.d.ts +1 -1
- package/dist/core/trace.d.ts +26 -23
- package/dist/core/types.d.ts +155 -70
- package/dist/core/untrusted-egress.d.ts +1 -1
- package/dist/core/untrusted-text.d.ts +7 -7
- package/dist/core/wiring-manifest.d.ts +5 -5
- package/dist/core/workflow-journal-store.d.ts +14 -14
- package/dist/core/workflow-run-store-contract.d.ts +1 -1
- package/dist/core/workflow-run-store-contract.js +1 -1
- package/dist/core/workflow-run-store.d.ts +4 -4
- package/dist/engine/compaction/compaction.d.ts +3 -3
- package/dist/engine/compaction/utils.d.ts +2 -2
- package/dist/engine/execution-env/kill-tree.d.ts +1 -1
- package/dist/engine/execution-env/node-execution-env.d.ts +8 -8
- package/dist/engine/harness/agent-harness.d.ts +6 -6
- package/dist/engine/harness/agent-harness.js +26 -1
- package/dist/engine/harness/messages.d.ts +1 -1
- package/dist/engine/harness/types.d.ts +15 -11
- package/dist/engine/llm/types.d.ts +79 -14
- package/dist/engine/loop/agent-loop.d.ts +3 -3
- package/dist/engine/loop/types.d.ts +4 -4
- package/dist/engine/lsp/node-lsp-manager.d.ts +2 -2
- package/dist/engine/session/import-validate.d.ts +1 -1
- package/dist/engine/session/log-digest.d.ts +1 -1
- package/dist/engine/session/memory-repo.d.ts +2 -2
- package/dist/engine/session/session.d.ts +4 -4
- package/dist/fixtures/index.d.ts +4 -4
- package/dist/index.d.ts +8 -4
- package/dist/index.js +5 -2
- package/dist/internal/llm.d.ts +1 -1
- package/dist/orchestration/goal.d.ts +1 -1
- package/dist/orchestration/run-spec.d.ts +1 -1
- package/dist/orchestration/run-workflow-tool.d.ts +12 -12
- package/dist/orchestration/workflow-governance.d.ts +4 -4
- package/dist/orchestration/workflow-observe.d.ts +1 -1
- package/dist/orchestration/workflow-script-runner.d.ts +1 -1
- package/dist/orchestration/workflow-script-store.d.ts +9 -9
- package/dist/orchestration/workflow-size-guideline.d.ts +1 -1
- package/dist/orchestration/workflow-types.d.ts +5 -5
- package/dist/orchestration/workflow.d.ts +10 -10
- package/dist/prompt-assembly/artifact-store.d.ts +1 -1
- package/dist/prompt-assembly/artifact.d.ts +1 -1
- package/dist/prompt-assembly/assemble.d.ts +1 -1
- package/dist/prompt-assembly/composer.d.ts +2 -2
- package/dist/prompt-assembly/epoch.d.ts +2 -2
- package/dist/prompt-assembly/event-registry.d.ts +1 -1
- package/dist/prompt-assembly/explain.d.ts +3 -3
- package/dist/prompt-assembly/tool-catalog.d.ts +1 -1
- package/dist/prompt-assembly/turn-snapshot.d.ts +4 -4
- package/dist/prompt-assembly/types.d.ts +12 -12
- package/dist/prompts/coordinator.d.ts +1 -1
- package/dist/prompts/default.d.ts +10 -10
- package/dist/prompts/default.js +2 -0
- package/dist/prompts/simple-sections.d.ts +3 -3
- package/dist/prompts/supervisor.d.ts +2 -2
- package/dist/scenarios/full-body.d.ts +3 -3
- package/dist/scenarios/scenario-registry.d.ts +6 -2
- package/dist/scenarios/scenario-registry.js +4 -2
- package/dist/stores/cc/sidecar-transcript.d.ts +3 -3
- package/dist/stores/file/fs-atomic.d.ts +2 -2
- package/dist/stores/file/index.d.ts +1 -1
- package/dist/stores/file/session-store.d.ts +2 -2
- package/dist/stores/file/workflow-journal-store.d.ts +4 -4
- package/dist/tools/fs/bash-readonly-classifier.d.ts +1 -1
- package/dist/tools/fs/encoding.d.ts +4 -4
- package/dist/tools/fs/fs-bash.d.ts +3 -3
- package/dist/tools/fs/fs-pdf.d.ts +1 -1
- package/dist/tools/fs/fs-shared.d.ts +6 -6
- package/dist/tools/fs/index.d.ts +2 -2
- package/dist/tools/fs/index.js +8 -1
- package/dist/tools/fs/notebook.d.ts +1 -1
- package/dist/tools/fs/pdf.d.ts +1 -1
- package/dist/tools/fs/read-deny.d.ts +1 -1
- package/dist/tools/fs/safety.d.ts +9 -9
- package/dist/tools/fs/search.d.ts +2 -2
- package/dist/tools/monitor.d.ts +3 -3
- package/dist/tools/scheduler-tools.js +28 -6
- package/dist/tools/task-list.d.ts +2 -2
- package/dist/tools/web.d.ts +19 -4
- package/dist/tools/web.js +8 -2
- package/dist/tools/worktree.d.ts +5 -5
- package/dist/tools/worktree.js +2 -2
- package/package.json +1 -1
- package/test/export-surface.snapshot.json +74 -3
package/dist/bench/metrics.d.ts
CHANGED
|
@@ -71,7 +71,7 @@ export interface DeliveryDecision {
|
|
|
71
71
|
}
|
|
72
72
|
/**
|
|
73
73
|
* design/95 §3.2 — the lifecycle status of a run, so INFRA noise never poisons the mode signal
|
|
74
|
-
* (
|
|
74
|
+
* (design/89 §3.3 Beatsep red line). The Beatsep task#2b 9% pass-rate was infra
|
|
75
75
|
* death (OOM / K8S passthrough / nested-root), NOT a mode signal — feeding such runs into the
|
|
76
76
|
* numerator turns them into spurious DELIVERED-WRONG / zero datapoints and reproduces the very noise
|
|
77
77
|
* the design claims to have isolated. `buildReport` SCORES only `scored`; `infra-failed` / `excluded`
|
|
@@ -94,7 +94,7 @@ export interface RunRecord {
|
|
|
94
94
|
/** Repeat/seed index within the cell (design/89 §3.4 N-repeat). */
|
|
95
95
|
seed?: number | string;
|
|
96
96
|
/**
|
|
97
|
-
* design/95 §3.2
|
|
97
|
+
* design/95 §3.2 — lifecycle status. Only "scored" runs reach the numerator / cost /
|
|
98
98
|
* Pareto. Absent ⇒ "scored" (back-compat). See {@link RunStatus}.
|
|
99
99
|
*/
|
|
100
100
|
runStatus?: RunStatus;
|
|
@@ -313,7 +313,7 @@ export interface ArmCell {
|
|
|
313
313
|
/** Avoided-loss rate = CORRECTLY-WITHHELD / n. The supervisor's §2.2.1 value, single-listed. */
|
|
314
314
|
correctlyWithheldRate: number;
|
|
315
315
|
/**
|
|
316
|
-
*
|
|
316
|
+
* design/95 M10 — withhold treated as a binary detector of would-be-wrong delivery
|
|
317
317
|
* (positive = withheld; ground truth = would-be-wrong, established by the §2.4 counterfactual). Reported
|
|
318
318
|
* as precision/recall — NOT just the raw correctly-withheld count — so an arm cannot look good by
|
|
319
319
|
* withholding indiscriminately (high count, low precision) or by rarely withholding (high precision,
|
|
@@ -420,10 +420,10 @@ export declare function riskTransferDisclosure(cells: ArmCell[]): {
|
|
|
420
420
|
};
|
|
421
421
|
};
|
|
422
422
|
/**
|
|
423
|
-
*
|
|
423
|
+
* a paired-binary comparison of two arms on the SAME tasks/seeds. The two arms' truly-
|
|
424
424
|
* correct flags are paired row-by-row (paired-seed, design/89 §3.4). For binary paired data the
|
|
425
425
|
* RIGHT tests are McNemar (discordant pairs) and a paired-bootstrap difference interval — NOT two
|
|
426
|
-
* independent proportions with "CI non-overlap" (that ignores the pairing and is under-powered
|
|
426
|
+
* independent proportions with "CI non-overlap" (that ignores the pairing and is under-powered).
|
|
427
427
|
*/
|
|
428
428
|
export interface PairedBinaryComparison {
|
|
429
429
|
/** Arm A (e.g. "sup") vs arm B (e.g. "solo"). pDiff = P(A) − P(B). */
|
|
@@ -440,12 +440,12 @@ export interface PairedBinaryComparison {
|
|
|
440
440
|
* b+c large). */
|
|
441
441
|
mcnemarP: number;
|
|
442
442
|
/** Bootstrap percentile 95% CI for the paired difference (lo, hi) — a percentile CI on the seeded
|
|
443
|
-
* paired-bootstrap distribution, NOT Newcombe's analytic interval
|
|
443
|
+
* paired-bootstrap distribution, NOT Newcombe's analytic interval. Crosses 0 ⇒ not significant. */
|
|
444
444
|
ci95: [number, number];
|
|
445
445
|
/** TRUE iff the difference is statistically significant at α=0.05 (CI excludes 0 AND McNemar p<0.05). */
|
|
446
446
|
significant: boolean;
|
|
447
447
|
/**
|
|
448
|
-
*
|
|
448
|
+
* pre-registered Minimum Detectable Effect at the observed nPairs (the difference this
|
|
449
449
|
* comparison COULD have detected at 80% power). When |pDiff| is below this AND not significant, the
|
|
450
450
|
* verdict is "not powered" — NOT "no difference". This is the field that stops "N≥15 is an assertion".
|
|
451
451
|
*/
|
|
@@ -456,8 +456,8 @@ export interface PairedBinaryComparison {
|
|
|
456
456
|
verdict: "A-better" | "B-better" | "no-detectable-difference" | "not-powered";
|
|
457
457
|
}
|
|
458
458
|
/**
|
|
459
|
-
*
|
|
460
|
-
* `(taskId, seed)` key (
|
|
459
|
+
* compare two arms' delivered truly-correct as PAIRED binary. Pairs runs by the COMPOSITE
|
|
460
|
+
* `(taskId, seed)` key (a bare `seed` collides across tasks — the same repeat index
|
|
461
461
|
* recurs per task — so cross-task input would overwrite pairs and contaminate the McNemar sample);
|
|
462
462
|
* only rows where BOTH arms delivered (not withheld, both scored) form a pair — a
|
|
463
463
|
* withheld run has no delivered binary to pair (it is scored in the withhold/avoided-loss axis, not
|
|
@@ -469,7 +469,7 @@ export declare function pairedBinaryCompare(scoredRuns: RunRecord[], armA: Arm,
|
|
|
469
469
|
bootstrapIters?: number;
|
|
470
470
|
}): PairedBinaryComparison;
|
|
471
471
|
/**
|
|
472
|
-
*
|
|
472
|
+
* the pre-registered C2 exchange rate(s): how many human-review SECONDS we are willing to
|
|
473
473
|
* pay to buy one unit of supervisor value. Without these, "higher P / more withholds ⇒ worth it" is
|
|
474
474
|
* unfalsifiable (the "helpful but too expensive" counter-thesis cannot be observed). Declared BEFORE
|
|
475
475
|
* the run (design/95 §9), not fit after.
|
|
@@ -482,20 +482,20 @@ export interface C2Thresholds {
|
|
|
482
482
|
}
|
|
483
483
|
export interface ParetoVerdict {
|
|
484
484
|
arm: Arm;
|
|
485
|
-
/** Non-dominated on (C1, C2.sec, P) — necessary condition to be considered at all
|
|
485
|
+
/** Non-dominated on (C1, C2.sec, P) — necessary condition to be considered at all. */
|
|
486
486
|
nonDominated: boolean;
|
|
487
487
|
/** The pre-registered exchange-rate check: does the arm's extra C2 buy enough avoided-loss / saved
|
|
488
488
|
* decisions to clear the declared threshold? Undefined when the arm has no extra C2 over baseline. */
|
|
489
489
|
clearsC2Threshold?: boolean;
|
|
490
490
|
/**
|
|
491
|
-
*
|
|
491
|
+
* the label. An arm may ONLY be "worth-it" when it is non-dominated AND clears the C2
|
|
492
492
|
* threshold. A non-dominated but threshold-failing arm is "quality-tradeoff" (higher quality, but the
|
|
493
493
|
* cost is not bought back) — NEVER "worth-it". A dominated arm is "dominated".
|
|
494
494
|
*/
|
|
495
495
|
label: "worth-it" | "quality-tradeoff" | "dominated";
|
|
496
496
|
}
|
|
497
497
|
/**
|
|
498
|
-
*
|
|
498
|
+
* classify each arm against the SUP/TEAM-vs-baseline value question with a pre-registered
|
|
499
499
|
* exchange rate. `baselineArm` is the cost floor to compare extra C2 against (default "solo").
|
|
500
500
|
* `avoidedWrong` / `savedDecisions` per arm come from the cells / campaign report.
|
|
501
501
|
*
|
|
@@ -518,31 +518,31 @@ export declare function paretoValueVerdict(cells: ArmCell[], thresholds: C2Thres
|
|
|
518
518
|
* design/95 §7.1 — V1 (免重复劳动): campaign-level human-decision delta. The ONLY authoritative V1
|
|
519
519
|
* mechanism (design/95 reconcile, MAJOR#2): cross-task reuse of a decided strategy. Semantics:
|
|
520
520
|
* - `soloHumanDecisions` is the V1 BASELINE — the operator's actual up-front decision count when
|
|
521
|
-
* running solo across the campaign (
|
|
521
|
+
* running solo across the campaign (NOT 0, NOT synthetic — measured from real operator
|
|
522
522
|
* prep across runs). `0` is only valid when the campaign genuinely needed no human decision.
|
|
523
523
|
* - `repeatedDecisionsSaved = soloHumanDecisions − supHumanDecisions` (may be negative = SUP cost
|
|
524
524
|
* MORE human decisions; reported honestly, not floored).
|
|
525
525
|
*/
|
|
526
526
|
export interface CampaignV1Saved {
|
|
527
527
|
decisionKind: string;
|
|
528
|
-
/** V1 baseline
|
|
528
|
+
/** V1 baseline: operator's measured up-front decisions when running SOLO. Provenance MUST
|
|
529
529
|
* be recorded in the stamp (real prep, not 0/synthetic). */
|
|
530
530
|
soloHumanDecisions: number;
|
|
531
531
|
/** SUP arm's actual human-review decision count for this decision kind. */
|
|
532
532
|
supHumanDecisions: number;
|
|
533
533
|
/** = soloHumanDecisions − supHumanDecisions. Positive ⇒ SUP saved repeated labour (V1 evidence). */
|
|
534
534
|
repeatedDecisionsSaved: number;
|
|
535
|
-
/** Whether the baseline is a real measurement vs absent (
|
|
535
|
+
/** Whether the baseline is a real measurement vs absent (honesty gate). */
|
|
536
536
|
baselineProvenance: "measured-operator-baseline" | "absent-not-claimable";
|
|
537
537
|
}
|
|
538
538
|
/**
|
|
539
|
-
* design/95 §7.2 — V2 (蓝图清晰度) THREE-arm ablation
|
|
539
|
+
* design/95 §7.2 — V2 (蓝图清晰度) THREE-arm ablation. All three are
|
|
540
540
|
* paired on the SAME seeds (paired===true ⇒ the three pX arrays/values are over the same n seeds).
|
|
541
541
|
* INVARIANT: `n` is the paired-seed count common to all three sub-arms; the three deltas are computed
|
|
542
542
|
* over those n pairs.
|
|
543
543
|
* - pSoloRaw — only the original brief (no blueprint baseline).
|
|
544
544
|
* - pSoloSupGenerated — the SUP-arm-GENERATED blueprint (attributable to supervisor; gen cost charged).
|
|
545
|
-
* - pSoloExperimenterIdeal — the experimenter "ideal" blueprint.
|
|
545
|
+
* - pSoloExperimenterIdeal — the experimenter "ideal" blueprint. this is a CONSTRAINED upper
|
|
546
546
|
* bound on "better-prompt help", NOT "supervisor's mechanistic ceiling", UNLESS the ideal blueprint
|
|
547
547
|
* was generated under the {@link IdealBlueprintConstraints} (run-time, visible-brief-only, no oracle
|
|
548
548
|
* access, same info budget, leak-reviewed). `idealConstraintsSatisfied` records which it is.
|
|
@@ -557,16 +557,16 @@ export interface BlueprintAblationTriple {
|
|
|
557
557
|
pSoloExperimenterIdeal: number;
|
|
558
558
|
/** = pSoloSupGenerated − pSoloRaw (supervisor blueprint's real net value). */
|
|
559
559
|
deltaSupVsRaw: number;
|
|
560
|
-
/** = pSoloExperimenterIdeal − pSoloRaw. LABELLED per `idealConstraintsSatisfied
|
|
560
|
+
/** = pSoloExperimenterIdeal − pSoloRaw. LABELLED per `idealConstraintsSatisfied`. */
|
|
561
561
|
deltaIdealVsRaw: number;
|
|
562
|
-
/**
|
|
562
|
+
/** when false, deltaIdealVsRaw is "manual-prompt upper bound", NOT "supervisor potential". */
|
|
563
563
|
idealConstraintsSatisfied: boolean;
|
|
564
|
-
/**
|
|
564
|
+
/** blueprint generation cost charged to the sup-generated arm (budget-match red line). */
|
|
565
565
|
blueprintGenC1MicroUsd: number;
|
|
566
566
|
blueprintGenC2Count: number;
|
|
567
567
|
blueprintGenC2Sec: number;
|
|
568
568
|
}
|
|
569
|
-
/**
|
|
569
|
+
/** the constraints under which an "ideal" blueprint may be read as a supervisor-mechanism
|
|
570
570
|
* upper bound rather than a generic "better prompt helps" result. Recorded per ablation. */
|
|
571
571
|
export interface IdealBlueprintConstraints {
|
|
572
572
|
generatedBeforeRun: boolean;
|
|
@@ -575,10 +575,10 @@ export interface IdealBlueprintConstraints {
|
|
|
575
575
|
sameInfoBudget: boolean;
|
|
576
576
|
solutionLeakReviewed: boolean;
|
|
577
577
|
}
|
|
578
|
-
/** True iff ALL ideal-blueprint constraints hold
|
|
578
|
+
/** True iff ALL ideal-blueprint constraints hold. */
|
|
579
579
|
export declare function idealConstraintsSatisfied(c: IdealBlueprintConstraints): boolean;
|
|
580
580
|
/**
|
|
581
|
-
* design/95 §7.3 — V3 (无关性隔离) contamination probe (canary, mechanical, zero LLM-judge).
|
|
581
|
+
* design/95 §7.3 — V3 (无关性隔离) contamination probe (canary, mechanical, zero LLM-judge).
|
|
582
582
|
* the isolated-vs-shared P delta CONFOUNDS execution order / context size / worker count / budget; the
|
|
583
583
|
* PRIMARY signal must be per-subgoal oracle failure + explicit wrong-use of a sibling artifact (the
|
|
584
584
|
* canary leak), with the P delta kept as a DIAGNOSTIC only.
|
|
@@ -590,12 +590,12 @@ export interface IsolationContamination {
|
|
|
590
590
|
isolatedSubgoalP: number[];
|
|
591
591
|
/** Per-factor P under shared context. length === factorCount. */
|
|
592
592
|
sharedSubgoalP: number[];
|
|
593
|
-
/** PRIMARY mechanical signal
|
|
593
|
+
/** PRIMARY mechanical signal: cross-factor canary leak rate (explicit token bleed). */
|
|
594
594
|
canaryLeakRate: number;
|
|
595
|
-
/** PRIMARY mechanical signal
|
|
595
|
+
/** PRIMARY mechanical signal: count of factors that failed their oracle AND demonstrably
|
|
596
596
|
* used a sibling factor's artifact (the controlled-ablation harm signal). */
|
|
597
597
|
wrongSiblingArtifactUses: number;
|
|
598
|
-
/** DIAGNOSTIC ONLY (
|
|
598
|
+
/** DIAGNOSTIC ONLY (confound): mean(isolated P) − mean(shared P). Not the primary signal. */
|
|
599
599
|
contaminationRateDiag: number;
|
|
600
600
|
/** Extra C1 the isolation cost (multi-worker / repeated context load). */
|
|
601
601
|
isolationOverheadC1: number;
|
|
@@ -614,7 +614,7 @@ export interface CampaignReport {
|
|
|
614
614
|
implementedAxes: ImplementedAxes;
|
|
615
615
|
}
|
|
616
616
|
/**
|
|
617
|
-
* design/95 §2
|
|
617
|
+
* design/95 §2 — one heterogeneity CELL: a `(suiteVersion, taskId, archetype, valueDimension,
|
|
618
618
|
* arm)` group with its folded {@link ArmCell}. The decision surface is the per-cell vector — NOT the
|
|
619
619
|
* arm mean (the Simpson's-paradox guard). `groupKey` is the stable join key.
|
|
620
620
|
*/
|
|
@@ -648,7 +648,7 @@ export interface ComparisonCell {
|
|
|
648
648
|
pareto: ParetoResult;
|
|
649
649
|
}
|
|
650
650
|
/**
|
|
651
|
-
*
|
|
651
|
+
* council Q1 — capability metadata: which of the four §7/Pareto value axes are actually
|
|
652
652
|
* IMPLEMENTED in this report. Consumers must read this before claiming a V1/V2/V3 result; an unset axis
|
|
653
653
|
* is NOT a null result, it is "not measured here". (The T1 structures above are types + pure helpers;
|
|
654
654
|
* the report-level V1/V2/V3 fields are populated by the harness, not synthesized in `buildReport`.)
|
|
@@ -660,7 +660,7 @@ export interface ImplementedAxes {
|
|
|
660
660
|
v3: boolean;
|
|
661
661
|
}
|
|
662
662
|
export interface ValueJudgmentReport {
|
|
663
|
-
/**
|
|
663
|
+
/** per-arm cells grouped by full heterogeneity key (incl. arm). Single-arm; use for cell
|
|
664
664
|
* inspection / `pairedBinaryCompare` inputs. NOT directly a cross-arm verdict surface (each is one arm). */
|
|
665
665
|
groupedCells: GroupedCell[];
|
|
666
666
|
/**
|
|
@@ -671,7 +671,7 @@ export interface ValueJudgmentReport {
|
|
|
671
671
|
*/
|
|
672
672
|
comparisons: ComparisonCell[];
|
|
673
673
|
/**
|
|
674
|
-
*
|
|
674
|
+
* suite-level rollup: per-arm cells folded over ALL scored runs. A WEIGHTED summary for
|
|
675
675
|
* dashboards ONLY — NOT a decision surface (folding heterogeneous tasks can flip a verdict, Simpson).
|
|
676
676
|
* Consumers MUST decide on `comparisons`; this is convenience aggregation.
|
|
677
677
|
*/
|
|
@@ -687,7 +687,7 @@ export interface ValueJudgmentReport {
|
|
|
687
687
|
/** design/89 §3.4: cells with n<8 are directional-only, not verdict-grade. Flagged, not dropped. */
|
|
688
688
|
directionalOnly: Arm[];
|
|
689
689
|
/**
|
|
690
|
-
*
|
|
690
|
+
* the exclusion ledger: runs dropped from scoring (infra-failed / excluded) with reasons.
|
|
691
691
|
* A regression-grade invariant: these never reach `cells` / `pareto` (no infra noise in the verdict).
|
|
692
692
|
*/
|
|
693
693
|
excluded: Array<{
|
|
@@ -696,16 +696,16 @@ export interface ValueJudgmentReport {
|
|
|
696
696
|
seed?: number | string;
|
|
697
697
|
reason: RunStatus;
|
|
698
698
|
}>;
|
|
699
|
-
/**
|
|
699
|
+
/** which value axes this report actually measured. */
|
|
700
700
|
implementedAxes: ImplementedAxes;
|
|
701
701
|
}
|
|
702
702
|
/**
|
|
703
|
-
* Top-level
|
|
703
|
+
* Top-level: SCORE only `scored` runs (B4 — drop infra-failed/excluded with reasons),
|
|
704
704
|
* group by `(suiteVersion, taskId, archetype, valueDimension, arm)` (B1 — the per-cell decision surface,
|
|
705
705
|
* Simpson's-paradox guard), fold each group, AND provide a suite-level per-arm rollup for dashboards
|
|
706
706
|
* (explicitly NOT a decision surface). Deterministic; no model.
|
|
707
707
|
*
|
|
708
|
-
* `opts.implementedAxes` lets the harness declare which §7 axes it populated
|
|
708
|
+
* `opts.implementedAxes` lets the harness declare which §7 axes it populated; default
|
|
709
709
|
* = only Pareto (the V1/V2/V3 structures are T1 net-new, not synthesized here).
|
|
710
710
|
*/
|
|
711
711
|
export declare function buildReport(runs: RunRecord[], opts?: {
|
package/dist/brain/anthropic.js
CHANGED
|
@@ -5,7 +5,8 @@ import { createRepetitionPoll, parseStreamedToolArgs } from "./stream-shared.js"
|
|
|
5
5
|
import { mintFallbackToolCallId } from "./tool-call-id.js";
|
|
6
6
|
import { emitBrainTelemetry, reportReasoningWireFacts } from "./status-sink.js";
|
|
7
7
|
import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, modelSupportsVision, sendableImages } from "./media-degrade.js";
|
|
8
|
-
import { ANTHROPIC_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, effectiveOutputCap, lockHeader, mergeHeaders,
|
|
8
|
+
import { ANTHROPIC_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, effectiveOutputCap, lockHeader, mergeHeaders, takeHeaderCasefold } from "./request-params.js";
|
|
9
|
+
import { adjudicateModelRoute, applyRouteCredentialHeaders, createBrainRouteJudge, resolveRouteCredential, routeRefusalText } from "./route-adjudicator.js";
|
|
9
10
|
import { MIN_THINKING_TOKENS, budgetCapSkipsThinking, declaredEffortLevels, reasoningBudgetShare, reasoningRequestCarried, resolveEffort } from "./reasoning.js";
|
|
10
11
|
import { runStreamingBrain } from "./stream-engine.js";
|
|
11
12
|
function thinkingBudget(maxTokens, share, fixed, hardCap = false) {
|
|
@@ -234,7 +235,17 @@ export function createAnthropicBrain(config = {}) {
|
|
|
234
235
|
httpLabel: "anthropic",
|
|
235
236
|
stallTimeouts: options?.stallTimeouts,
|
|
236
237
|
buildRequest: (overrides) => {
|
|
237
|
-
const
|
|
238
|
+
const routeCredential = resolveRouteCredential({
|
|
239
|
+
optionsApiKey: options?.apiKey,
|
|
240
|
+
optionsHeaders: options?.headers,
|
|
241
|
+
modelHeaders: model.headers,
|
|
242
|
+
configApiKey: config.apiKey,
|
|
243
|
+
configHeaders: config.headers,
|
|
244
|
+
});
|
|
245
|
+
const routeVerdict = adjudicateModelRoute(model, routeCredential, { baseUrl: config.baseUrl });
|
|
246
|
+
if (!routeVerdict.ok)
|
|
247
|
+
throw new BrainError("invalid_request", routeRefusalText(routeVerdict));
|
|
248
|
+
const apiKey = routeCredential.apiKey;
|
|
238
249
|
const root = (model.baseUrl || config.baseUrl || "https://api.anthropic.com").replace(/\/+$/, "");
|
|
239
250
|
const nonEmptyBlocks = context.systemBlocks?.filter((b) => b.text.length > 0);
|
|
240
251
|
const system = nonEmptyBlocks?.length
|
|
@@ -302,8 +313,7 @@ export function createAnthropicBrain(config = {}) {
|
|
|
302
313
|
betas.push("interleaved-thinking-2025-05-14");
|
|
303
314
|
}
|
|
304
315
|
const headers = mergeHeaders(model.headers, config.headers, options?.headers);
|
|
305
|
-
|
|
306
|
-
stripAuthHeaders(headers);
|
|
316
|
+
applyRouteCredentialHeaders(headers, routeCredential, { model: model.headers, options: options?.headers });
|
|
307
317
|
if (betas.length > 0) {
|
|
308
318
|
const existing = (takeHeaderCasefold(headers, "anthropic-beta") ?? "").split(",").map((b) => b.trim()).filter(Boolean);
|
|
309
319
|
for (const beta of betas) {
|
|
@@ -680,5 +690,5 @@ export function createAnthropicBrain(config = {}) {
|
|
|
680
690
|
},
|
|
681
691
|
});
|
|
682
692
|
};
|
|
683
|
-
return { stream };
|
|
693
|
+
return { stream, adjudicateRoute: createBrainRouteJudge(config) };
|
|
684
694
|
}
|
|
@@ -153,5 +153,6 @@ export function createCircuitBreakerBrain(inner, opts = {}) {
|
|
|
153
153
|
})();
|
|
154
154
|
return out;
|
|
155
155
|
};
|
|
156
|
-
|
|
156
|
+
const adjudicateRoute = (model, perModelAuth) => inner.adjudicateRoute?.(model, perModelAuth);
|
|
157
|
+
return { stream, adjudicateRoute };
|
|
157
158
|
}
|
|
@@ -75,7 +75,7 @@ export declare function readDegradation(msg: {
|
|
|
75
75
|
diagnostics?: AssistantMessageDiagnostic[];
|
|
76
76
|
} | undefined): DegradationInfo | undefined;
|
|
77
77
|
/**
|
|
78
|
-
* design/131
|
|
78
|
+
* design/131 — resilience-standdown pass-through: forward one brain's stream
|
|
79
79
|
* verbatim, but keep the decorator discipline that a REJECTING inner brain (throw instead of an
|
|
80
80
|
* error event) still leaves a terminal on the returned stream — otherwise `result()` never
|
|
81
81
|
* resolves and the harness hangs (the same class as the degradation-brain blocker).
|
package/dist/brain/degrading.js
CHANGED
|
@@ -144,6 +144,8 @@ export function createDegradingBrain(opts) {
|
|
|
144
144
|
break;
|
|
145
145
|
if (hop.model.id === failedModelId)
|
|
146
146
|
continue;
|
|
147
|
+
if (hop.brain.adjudicateRoute?.(hop.model)?.ok === false)
|
|
148
|
+
continue;
|
|
147
149
|
chainPath.push(hop.model.id);
|
|
148
150
|
degradeInfo = {
|
|
149
151
|
from: model.id,
|
|
@@ -182,5 +184,6 @@ export function createDegradingBrain(opts) {
|
|
|
182
184
|
})();
|
|
183
185
|
return out;
|
|
184
186
|
};
|
|
185
|
-
|
|
187
|
+
const adjudicateRoute = (model, perModelAuth) => opts.primary.adjudicateRoute?.(model, perModelAuth);
|
|
188
|
+
return { stream, adjudicateRoute };
|
|
186
189
|
}
|
package/dist/brain/errors.d.ts
CHANGED
|
@@ -12,7 +12,7 @@ export declare const ZERO_USAGE: Usage;
|
|
|
12
12
|
/** The single source of truth for brain error codes — the type, the `[code]` parser, and the prefix
|
|
13
13
|
* stripper all derive from this one list, so adding a code can't silently diverge across call sites.
|
|
14
14
|
*
|
|
15
|
-
* The last three are IN-BAND terminal-output codes
|
|
15
|
+
* The last three are IN-BAND terminal-output codes: stamped on errored assistant MESSAGES
|
|
16
16
|
* (never thrown as BrainError) so `TaskResult.errorCode` covers the error family end-to-end and
|
|
17
17
|
* downstream consumers can bucket without string-matching. Deliberately behavior-neutral everywhere
|
|
18
18
|
* else: the circuit breaker's default countCodes excludes them (model-output problems, not provider
|
|
@@ -27,7 +27,7 @@ export type BrainErrorCode = (typeof BRAIN_ERROR_CODES)[number];
|
|
|
27
27
|
* tool-errors.ts must classify every member — a code added here but missed there folds to "unknown"). */
|
|
28
28
|
export declare const ALL_BRAIN_ERROR_CODES: readonly BrainErrorCode[];
|
|
29
29
|
/** The in-band terminal-output subset (see the list doc above). The circuit breaker collapses these
|
|
30
|
-
* to the legacy `"http"` bucket before counting
|
|
30
|
+
* to the legacy `"http"` bucket before counting: its taxonomy is TRANSPORT-level,
|
|
31
31
|
* and before these codes existed the same failures reached it as the unprefixed→"http" fallback — a
|
|
32
32
|
* custom `countCodes: ["http"]` policy must keep counting them exactly as it always did. */
|
|
33
33
|
export declare const IN_BAND_OUTPUT_CODES: ReadonlySet<BrainErrorCode>;
|
|
@@ -65,7 +65,7 @@ export declare function stripErrorCodePrefix(errorMessage: string): string;
|
|
|
65
65
|
*/
|
|
66
66
|
export type ConnectFailureClass = "deterministic" | "indeterminate";
|
|
67
67
|
export declare function classifyConnectFailure(e: unknown): ConnectFailureClass;
|
|
68
|
-
/** RB-386③
|
|
68
|
+
/** RB-386③ — render a transport-level error WITHOUT folding away its cause chain. undici's
|
|
69
69
|
* `fetch` rejects with `TypeError("fetch failed", { cause })` where the CAUSE carries the actually
|
|
70
70
|
* actionable fact (`connect ECONNREFUSED …` / `getaddrinfo ENOTFOUND …` / `SocketError: other side
|
|
71
71
|
* closed` with a `code`); `String(e)` / `e.message` alone collapsed ALL THREE network-failure shapes
|
package/dist/brain/failover.js
CHANGED
|
@@ -82,5 +82,20 @@ export function createFailoverBrain(brains) {
|
|
|
82
82
|
})();
|
|
83
83
|
return out;
|
|
84
84
|
};
|
|
85
|
-
|
|
85
|
+
const adjudicateRoute = (model, perModelAuth) => {
|
|
86
|
+
let firstRefusal;
|
|
87
|
+
let sawUnjudged = false;
|
|
88
|
+
for (const b of brains) {
|
|
89
|
+
const verdict = b.adjudicateRoute?.(model, perModelAuth);
|
|
90
|
+
if (verdict === undefined) {
|
|
91
|
+
sawUnjudged = true;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (verdict.ok)
|
|
95
|
+
return verdict;
|
|
96
|
+
firstRefusal ??= verdict;
|
|
97
|
+
}
|
|
98
|
+
return sawUnjudged ? undefined : firstRefusal;
|
|
99
|
+
};
|
|
100
|
+
return { stream, adjudicateRoute };
|
|
86
101
|
}
|
|
@@ -5,7 +5,8 @@ import { createRepetitionPoll, parseStreamedToolArgs } from "./stream-shared.js"
|
|
|
5
5
|
import { mintFallbackToolCallId } from "./tool-call-id.js";
|
|
6
6
|
import { emitBrainTelemetry } from "./status-sink.js";
|
|
7
7
|
import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, imagesOmittedNoVisionNote, modelSupportsVision, sendableImages } from "./media-degrade.js";
|
|
8
|
-
import { OUTPUT_CAP_KEYS, RESPONSES_RESERVED, applyExtraBody, effectiveOutputCap, lockHeader, mergeHeaders
|
|
8
|
+
import { OUTPUT_CAP_KEYS, RESPONSES_RESERVED, applyExtraBody, effectiveOutputCap, lockHeader, mergeHeaders } from "./request-params.js";
|
|
9
|
+
import { adjudicateModelRoute, applyRouteCredentialHeaders, createBrainRouteJudge, resolveRouteCredential, routeRefusalText } from "./route-adjudicator.js";
|
|
9
10
|
import { mintEffortWireValue, reasoningRequestCarried } from "./reasoning.js";
|
|
10
11
|
import { runStreamingBrain } from "./stream-engine.js";
|
|
11
12
|
const DEGENERATE_POLL_CHARS = 64;
|
|
@@ -228,7 +229,17 @@ export function createOpenResponsesBrain(config = {}) {
|
|
|
228
229
|
httpLabel: "responses",
|
|
229
230
|
stallTimeouts: options?.stallTimeouts,
|
|
230
231
|
buildRequest: (overrides) => {
|
|
231
|
-
const
|
|
232
|
+
const routeCredential = resolveRouteCredential({
|
|
233
|
+
optionsApiKey: options?.apiKey,
|
|
234
|
+
optionsHeaders: options?.headers,
|
|
235
|
+
modelHeaders: model.headers,
|
|
236
|
+
configApiKey: config.apiKey,
|
|
237
|
+
configHeaders: config.headers,
|
|
238
|
+
});
|
|
239
|
+
const routeVerdict = adjudicateModelRoute(model, routeCredential, { baseUrl: config.baseUrl });
|
|
240
|
+
if (!routeVerdict.ok)
|
|
241
|
+
throw new BrainError("invalid_request", routeRefusalText(routeVerdict));
|
|
242
|
+
const apiKey = routeCredential.apiKey;
|
|
232
243
|
const root = (model.baseUrl || config.baseUrl || "").replace(/\/+$/, "");
|
|
233
244
|
if (!root) {
|
|
234
245
|
throw new Error("createOpenResponsesBrain: no baseUrl configured (set config.baseUrl or model.baseUrl)");
|
|
@@ -265,8 +276,7 @@ export function createOpenResponsesBrain(config = {}) {
|
|
|
265
276
|
if (effort !== undefined)
|
|
266
277
|
body.reasoning = { effort };
|
|
267
278
|
const headers = mergeHeaders(model.headers, config.headers, options?.headers);
|
|
268
|
-
|
|
269
|
-
stripAuthHeaders(headers);
|
|
279
|
+
applyRouteCredentialHeaders(headers, routeCredential, { model: model.headers, options: options?.headers });
|
|
270
280
|
lockHeader(headers, "content-type", "application/json");
|
|
271
281
|
if (apiKey)
|
|
272
282
|
headers["authorization"] = `Bearer ${apiKey}`;
|
|
@@ -738,5 +748,5 @@ export function createOpenResponsesBrain(config = {}) {
|
|
|
738
748
|
},
|
|
739
749
|
});
|
|
740
750
|
};
|
|
741
|
-
return { stream };
|
|
751
|
+
return { stream, adjudicateRoute: createBrainRouteJudge(config) };
|
|
742
752
|
}
|
package/dist/brain/openai.js
CHANGED
|
@@ -5,7 +5,9 @@ import { createRepetitionPoll, parseStreamedToolArgs } from "./stream-shared.js"
|
|
|
5
5
|
import { mintFallbackToolCallId } from "./tool-call-id.js";
|
|
6
6
|
import { emitBrainTelemetry } from "./status-sink.js";
|
|
7
7
|
import { errorResultMediaNote, IMAGE_OMITTED_NO_VISION, imagesOmittedNoVisionNote, modelSupportsVision, sendableImages } from "./media-degrade.js";
|
|
8
|
-
import { OPENAI_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, effectiveOutputCap, lockHeader, mergeHeaders
|
|
8
|
+
import { OPENAI_RESERVED, OUTPUT_CAP_KEYS, applyExtraBody, effectiveOutputCap, lockHeader, mergeHeaders } from "./request-params.js";
|
|
9
|
+
import { BrainError } from "./errors.js";
|
|
10
|
+
import { adjudicateModelRoute, applyRouteCredentialHeaders, createBrainRouteJudge, resolveRouteCredential, routeRefusalText } from "./route-adjudicator.js";
|
|
9
11
|
import { mintEffortWireValue, reasoningRequestCarried } from "./reasoning.js";
|
|
10
12
|
import { runStreamingBrain } from "./stream-engine.js";
|
|
11
13
|
function closeToolCallAccum(acc) {
|
|
@@ -270,7 +272,17 @@ export function createOpenAIBrain(config = {}) {
|
|
|
270
272
|
httpLabel: "gateway",
|
|
271
273
|
stallTimeouts: options?.stallTimeouts,
|
|
272
274
|
buildRequest: (overrides) => {
|
|
273
|
-
const
|
|
275
|
+
const routeCredential = resolveRouteCredential({
|
|
276
|
+
optionsApiKey: options?.apiKey,
|
|
277
|
+
optionsHeaders: options?.headers,
|
|
278
|
+
modelHeaders: model.headers,
|
|
279
|
+
configApiKey: config.apiKey,
|
|
280
|
+
configHeaders: config.headers,
|
|
281
|
+
});
|
|
282
|
+
const routeVerdict = adjudicateModelRoute(model, routeCredential, { baseUrl: config.baseUrl });
|
|
283
|
+
if (!routeVerdict.ok)
|
|
284
|
+
throw new BrainError("invalid_request", routeRefusalText(routeVerdict));
|
|
285
|
+
const apiKey = routeCredential.apiKey;
|
|
274
286
|
const root = (model.baseUrl || config.baseUrl || "").replace(/\/+$/, "");
|
|
275
287
|
if (!root) {
|
|
276
288
|
throw new Error("createOpenAIBrain: no baseUrl configured (set config.baseUrl or model.baseUrl)");
|
|
@@ -304,8 +316,7 @@ export function createOpenAIBrain(config = {}) {
|
|
|
304
316
|
body.stop = options.stop;
|
|
305
317
|
applyThinking(body, model, options?.reasoning);
|
|
306
318
|
const headers = mergeHeaders(model.headers, config.headers, options?.headers);
|
|
307
|
-
|
|
308
|
-
stripAuthHeaders(headers);
|
|
319
|
+
applyRouteCredentialHeaders(headers, routeCredential, { model: model.headers, options: options?.headers });
|
|
309
320
|
lockHeader(headers, "content-type", "application/json");
|
|
310
321
|
if (apiKey)
|
|
311
322
|
headers["authorization"] = `Bearer ${apiKey}`;
|
|
@@ -618,5 +629,5 @@ export function createOpenAIBrain(config = {}) {
|
|
|
618
629
|
},
|
|
619
630
|
});
|
|
620
631
|
};
|
|
621
|
-
return { stream };
|
|
632
|
+
return { stream, adjudicateRoute: createBrainRouteJudge(config) };
|
|
622
633
|
}
|
|
@@ -92,7 +92,7 @@ export interface ReasoningResolution {
|
|
|
92
92
|
* the cap-wins predicate below and the brain's budget-window math read ONE constant. */
|
|
93
93
|
export declare const MIN_THINKING_TOKENS = 1024;
|
|
94
94
|
/**
|
|
95
|
-
* The anthropic BUDGET path's cap-wins arm (#346, single-sourced; design/119 #2 review
|
|
95
|
+
* The anthropic BUDGET path's cap-wins arm (#346, single-sourced; design/119 #2 review):
|
|
96
96
|
* a HARD per-request output cap (an engine-imposed override or the caller's explicit
|
|
97
97
|
* `options.maxTokens` — the two lanes the brain refuses to raise) too small to host a legal thinking
|
|
98
98
|
* budget (≥ {@link MIN_THINKING_TOKENS}) plus answer room means the CAP WINS and thinking is skipped
|
|
@@ -276,7 +276,7 @@ export interface ReasoningProfileFlags {
|
|
|
276
276
|
}
|
|
277
277
|
/**
|
|
278
278
|
* design/96 §D (S4) — map a named {@link ReasoningTier} to its engine {@link ReasoningProfileFlags} (default
|
|
279
|
-
* mapping). G2
|
|
279
|
+
* mapping). G2: the intensity→capability mapping is PROFILE-layer data — core gives this primitive +
|
|
280
280
|
* a sane default; a profile/scenario layer calls it (and may override the table) to set a task's `thinking` +
|
|
281
281
|
* prompt flags. Core never forces it. Returns a fresh COPY (callers may mutate).
|
|
282
282
|
*/
|
|
@@ -36,7 +36,7 @@ export declare const DEGENERATE_MESSAGE = "degenerate repetition detected \u2014
|
|
|
36
36
|
* One detector hit — either the event that CUT a stream (`degenerate`) or a repetition that landed in
|
|
37
37
|
* a detection window but was SPARED by a 2e1c161 structural allowance (code-line shape / divider run).
|
|
38
38
|
* Spared events are the RSI raw material for judging whether the allowance is too wide or too narrow
|
|
39
|
-
* (
|
|
39
|
+
* (2026-07-10: the detector must report counts AND the detected segment, not just a boolean).
|
|
40
40
|
*/
|
|
41
41
|
export interface RepetitionEvent {
|
|
42
42
|
/** Which rule's window the repetition landed in: rule 1 (`char-run`) or rule 2 (`unit-loop`). */
|
|
@@ -22,17 +22,16 @@ export declare function reservedFor(api: string): ReadonlySet<string>;
|
|
|
22
22
|
* deployment with no `extraBody` is unaffected.
|
|
23
23
|
*/
|
|
24
24
|
export declare function applyExtraBody(body: Record<string, unknown>, extraBody: Record<string, unknown> | undefined, reserved: ReadonlySet<string>): Record<string, unknown>;
|
|
25
|
-
/**
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
|
|
35
|
-
export declare function stripAuthHeaders(headers: Record<string, string>): void;
|
|
25
|
+
/** The auth-bearing header names (case-fold), single-sourced for the credential enforcement
|
|
26
|
+
* (`applyRouteCredentialHeaders`, route-adjudicator.ts — the ONE authority over auth spelling: a
|
|
27
|
+
* per-model winner strips every carrier, any case, and re-asserts the winning bag's own),
|
|
28
|
+
* {@link mergeHeaders} (which EXEMPTS them — see there), and the route credential resolver (which
|
|
29
|
+
* reads carrier PRESENCE per bag to classify a headers-borne credential). The former per-call
|
|
30
|
+
* strip helper that lived here (`stripAuthHeaders` — "per-call auth replaces construction-time
|
|
31
|
+
* auth", triggered on `options.apiKey` presence) is retired: the three brains now run the
|
|
32
|
+
* route-credential resolution instead, whose per-model arm strips a strict superset of what the
|
|
33
|
+
* helper did. */
|
|
34
|
+
export declare const AUTH_CARRIER_NAMES: ReadonlySet<string>;
|
|
36
35
|
/**
|
|
37
36
|
* #343 — the shared USER-HEADER merge layer (`model.headers` → construction `config.headers` →
|
|
38
37
|
* per-call `options.headers`, later bag wins), CASE-FOLD deduplicated: HTTP header field names are
|
|
@@ -45,26 +44,29 @@ export declare function stripAuthHeaders(headers: Record<string, string>): void;
|
|
|
45
44
|
* deployment — is byte-identical on the wire).
|
|
46
45
|
*
|
|
47
46
|
* EXEMPT: the auth carriers (`authorization` / `x-api-key`, any case) pass through with the exact
|
|
48
|
-
* legacy spread semantics (same-spelling override only, no case-fold dedup), so that
|
|
49
|
-
*
|
|
50
|
-
* second, subtly different one.
|
|
47
|
+
* legacy spread semantics (same-spelling override only, no case-fold dedup), so that the credential
|
|
48
|
+
* enforcement (`applyRouteCredentialHeaders`, route-adjudicator.ts) stays the ONE authority over
|
|
49
|
+
* auth spelling and this layer never becomes a second, subtly different one.
|
|
51
50
|
*
|
|
52
51
|
* RE-RULED, because the exemption used to be justified by a reason that does not hold: the
|
|
53
52
|
* note claimed it protected "the header-only ANTHROPIC_AUTH_TOKEN shape, which must survive under its
|
|
54
53
|
* own capital-A spelling". Dedup would not endanger that shape — it keeps the WINNER'S spelling, and a
|
|
55
54
|
* lone `Authorization` has nothing to be deduped against, so it survives either way; nor does the
|
|
56
|
-
*
|
|
57
|
-
* spelling present. Measured, not reasoned:
|
|
58
|
-
* BOTH, and the platform `Headers` fold
|
|
55
|
+
* credential-replaces flow depend on the exemption, since the enforcement already deletes every
|
|
56
|
+
* spelling present when a per-model credential wins. Measured, not reasoned:
|
|
57
|
+
* `mergeHeaders({Authorization:A},{authorization:B})` keeps BOTH, and the platform `Headers` fold
|
|
58
|
+
* sends `authorization: A, B`.
|
|
59
59
|
*
|
|
60
|
-
* STATED RESIDUAL (deliberately not fixed here)
|
|
61
|
-
*
|
|
62
|
-
*
|
|
63
|
-
*
|
|
64
|
-
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
60
|
+
* STATED RESIDUAL (deliberately not fixed here), NARROWED by the credential enforcement: where a
|
|
61
|
+
* PER-MODEL credential wins (an options- or entry-bag carrier), every carrier is stripped and only
|
|
62
|
+
* the winning bag's re-asserted, so a cross-layer double spelling now folds to the winner. What
|
|
63
|
+
* remains is the DEPLOYMENT-CONFIG arm — its bytes ride untouched by design — so a config bag that
|
|
64
|
+
* itself spells the SAME auth carrier two ways still ships both, comma-folded. It is held, not
|
|
65
|
+
* denied, on severity: no server accepts a comma-joined credential, so the failure is a LOUD 401
|
|
66
|
+
* attributable to the misconfiguration, whereas the non-auth case this function exists for produced
|
|
67
|
+
* a silently WRONG value (`X-Tenant: a, b` — neither writer's, the later layer's documented
|
|
68
|
+
* override defeated). Tightening it changes which credential reaches the wire, so it belongs in a
|
|
69
|
+
* window that discloses an auth-face behavior change.
|
|
68
70
|
*/
|
|
69
71
|
/**
|
|
70
72
|
* #343 (review r4) — assign a STRUCTURAL locked header under its canonical lowercase name, deleting
|
|
@@ -72,8 +74,9 @@ export declare function stripAuthHeaders(headers: Record<string, string>): void;
|
|
|
72
74
|
* the user-bag merge precisely so they "can NEVER be overridden" (council design/40) — but a valid
|
|
73
75
|
* user bag carrying `Content-Type: text/plain` survived BESIDE the lowercase lock, and the platform
|
|
74
76
|
* `Headers` fold turns the pair into `text/plain, application/json` on the wire: the lock decided
|
|
75
|
-
* nothing. Auth carriers are deliberately NOT routed through here (
|
|
76
|
-
* header-only boot flow are
|
|
77
|
+
* nothing. Auth carriers are deliberately NOT routed through here (credential replacement + the
|
|
78
|
+
* header-only boot flow are the pinned jurisdiction of `applyRouteCredentialHeaders`,
|
|
79
|
+
* route-adjudicator.ts).
|
|
77
80
|
*/
|
|
78
81
|
export declare function lockHeader(headers: Record<string, string>, lowerName: string, value: string): void;
|
|
79
82
|
/**
|
|
@@ -54,13 +54,7 @@ export function applyExtraBody(body, extraBody, reserved) {
|
|
|
54
54
|
}
|
|
55
55
|
return { ...passthrough, ...body };
|
|
56
56
|
}
|
|
57
|
-
const AUTH_CARRIER_NAMES = new Set(["authorization", "x-api-key"]);
|
|
58
|
-
export function stripAuthHeaders(headers) {
|
|
59
|
-
for (const k of Object.keys(headers)) {
|
|
60
|
-
if (AUTH_CARRIER_NAMES.has(k.toLowerCase()))
|
|
61
|
-
delete headers[k];
|
|
62
|
-
}
|
|
63
|
-
}
|
|
57
|
+
export const AUTH_CARRIER_NAMES = new Set(["authorization", "x-api-key"]);
|
|
64
58
|
export function lockHeader(headers, lowerName, value) {
|
|
65
59
|
for (const k of Object.keys(headers)) {
|
|
66
60
|
if (k !== lowerName && k.toLowerCase() === lowerName)
|