@gajae-code/coding-agent 0.12.21 → 0.13.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 +67 -2
- package/dist/types/cli/args.d.ts +5 -2
- package/dist/types/cli/root-flags.d.ts +246 -0
- package/dist/types/cli.d.ts +11 -19
- package/dist/types/commands/daemon.d.ts +0 -30
- package/dist/types/commands/launch.d.ts +11 -19
- package/dist/types/commands/quick-lane.d.ts +32 -0
- package/dist/types/commands/sdk.d.ts +21 -15
- package/dist/types/config/file-lock-gc.d.ts +2 -0
- package/dist/types/config/model-equivalence.d.ts +20 -0
- package/dist/types/config/model-profile-activation.d.ts +62 -17
- package/dist/types/config/model-profiles.d.ts +10 -0
- package/dist/types/config/model-registry.d.ts +68 -1
- package/dist/types/config/model-resolver.d.ts +15 -4
- package/dist/types/config/models-config-schema.d.ts +7 -2
- package/dist/types/config/provider-selection-policy.d.ts +62 -0
- package/dist/types/config/settings-schema.d.ts +36 -78
- package/dist/types/config/settings.d.ts +2 -0
- package/dist/types/edit/renderer.d.ts +5 -2
- package/dist/types/edit/streaming.d.ts +13 -0
- package/dist/types/extensibility/custom-tools/types.d.ts +2 -0
- package/dist/types/extensibility/extensions/compact-handler.d.ts +2 -1
- package/dist/types/extensibility/extensions/types.d.ts +3 -0
- package/dist/types/gjc-runtime/gc-runtime.d.ts +19 -5
- package/dist/types/internal-urls/local-protocol.d.ts +1 -0
- package/dist/types/modes/components/model-selector.d.ts +0 -2
- package/dist/types/modes/components/provider-order-context.d.ts +45 -0
- package/dist/types/modes/components/provider-order-editor.d.ts +24 -0
- package/dist/types/modes/components/settings-defs.d.ts +5 -1
- package/dist/types/modes/components/settings-selector.d.ts +2 -0
- package/dist/types/quick-lane/classify.d.ts +40 -0
- package/dist/types/runtime/stt-settings-setup.d.ts +18 -0
- package/dist/types/sdk/broker/broker.d.ts +56 -2
- package/dist/types/sdk/broker/operation-receipt-ledger.d.ts +25 -0
- package/dist/types/sdk/broker/session-index.d.ts +83 -2
- package/dist/types/sdk/broker/state-version.d.ts +1 -1
- package/dist/types/sdk/bus/notification-service.d.ts +6 -0
- package/dist/types/sdk/bus/prompt-reconciliation.d.ts +8 -1
- package/dist/types/sdk/bus/telegram-daemon-contract.d.ts +4 -1
- package/dist/types/sdk/bus/telegram-daemon.d.ts +26 -0
- package/dist/types/sdk/cli/rows.d.ts +98 -0
- package/dist/types/sdk/cli/session-cli.d.ts +35 -3
- package/dist/types/sdk/elevation/allowlist.d.ts +20 -0
- package/dist/types/sdk/elevation/audit.d.ts +93 -0
- package/dist/types/sdk/elevation/capability.d.ts +3 -0
- package/dist/types/sdk/elevation/digest.d.ts +72 -0
- package/dist/types/sdk/elevation/dispatch-receipt.d.ts +85 -0
- package/dist/types/sdk/elevation/grant-ledger.d.ts +163 -0
- package/dist/types/sdk/elevation/owner.d.ts +48 -0
- package/dist/types/sdk/guides/cache.d.ts +98 -0
- package/dist/types/sdk/guides/catalog.d.ts +156 -0
- package/dist/types/sdk/guides/cli.d.ts +39 -0
- package/dist/types/sdk/guides/manifest.d.ts +66 -0
- package/dist/types/sdk/guides/verify.d.ts +66 -0
- package/dist/types/sdk/host/control/dispatch.d.ts +8 -0
- package/dist/types/sdk/host/control/index.d.ts +1 -1
- package/dist/types/sdk/host/control/operations.d.ts +3 -2
- package/dist/types/sdk/host/query/cursor.d.ts +10 -0
- package/dist/types/sdk/host/query/handlers.d.ts +21 -0
- package/dist/types/sdk/host/session-runtime.d.ts +9 -0
- package/dist/types/sdk/mcp/server.d.ts +2 -2
- package/dist/types/sdk/prompt-status.d.ts +11 -0
- package/dist/types/sdk/session.d.ts +4 -0
- package/dist/types/sdk/transport/index.d.ts +1 -0
- package/dist/types/sdk/transport/relay.d.ts +1 -0
- package/dist/types/sdk/transport/serve-cli.d.ts +20 -1
- package/dist/types/session/agent-session.d.ts +32 -18
- package/dist/types/session/blob-store.d.ts +13 -7
- package/dist/types/session/fallback-chain-controller.d.ts +15 -0
- package/dist/types/session/internal/managed-session-storage.d.ts +25 -1
- package/dist/types/session/internal/session-memory-sidecar.d.ts +5 -5
- package/dist/types/session/session-manager.d.ts +139 -10
- package/dist/types/session/session-storage.d.ts +48 -0
- package/dist/types/setup/provider-onboarding.d.ts +7 -1
- package/dist/types/slash-commands/builtin-registry.d.ts +14 -0
- package/dist/types/stt/setup.d.ts +2 -0
- package/dist/types/task/executor.d.ts +10 -2
- package/dist/types/tools/browser/runtime-diagnostics.d.ts +65 -0
- package/dist/types/tools/browser/tab-protocol.d.ts +4 -0
- package/dist/types/tools/browser/tab-supervisor.d.ts +2 -0
- package/dist/types/tools/browser/tab-worker.d.ts +2 -0
- package/dist/types/tools/browser.d.ts +2 -0
- package/dist/types/tools/image-gen.d.ts +14 -18
- package/dist/types/tools/index.d.ts +2 -0
- package/dist/types/tools/resource-gc.d.ts +2 -0
- package/dist/types/utils/pasted-image-path.d.ts +6 -0
- package/package.json +9 -9
- package/scripts/generate-sdk-operation-inventory.ts +8 -0
- package/scripts/run-test-manifest.ts +61 -21
- package/scripts/verify-gjc-sdk-canonicalization.ts +9 -4
- package/src/cli/args.ts +62 -9
- package/src/cli/completion-cli.ts +1 -0
- package/src/cli/fast-help.ts +1 -0
- package/src/cli/root-flags.ts +100 -0
- package/src/cli/setup-cli.ts +6 -2
- package/src/cli.ts +42 -65
- package/src/commands/acp.ts +1 -1
- package/src/commands/daemon.ts +2 -31
- package/src/commands/gc.ts +1 -1
- package/src/commands/launch.ts +8 -129
- package/src/commands/quick-lane.ts +51 -0
- package/src/commands/sdk.ts +200 -26
- package/src/commands/setup.ts +4 -2
- package/src/config/file-lock-gc.ts +4 -1
- package/src/config/model-equivalence.ts +76 -7
- package/src/config/model-profile-activation.ts +1115 -265
- package/src/config/model-profiles.ts +134 -2
- package/src/config/model-registry.ts +352 -50
- package/src/config/model-resolver.ts +289 -38
- package/src/config/models-config-schema.ts +11 -4
- package/src/config/provider-selection-policy.ts +146 -0
- package/src/config/settings-schema.ts +50 -77
- package/src/config/settings.ts +40 -0
- package/src/coordinator-mcp/server.ts +32 -2
- package/src/edit/renderer.ts +175 -223
- package/src/edit/streaming.ts +108 -1
- package/src/export/html/index.ts +57 -7
- package/src/extensibility/custom-tools/types.ts +2 -0
- package/src/extensibility/extensions/compact-handler.ts +3 -2
- package/src/extensibility/extensions/runner.ts +6 -0
- package/src/extensibility/extensions/types.ts +3 -0
- package/src/gjc-runtime/gc-runtime.ts +379 -20
- package/src/gjc-runtime/launch-worktree.ts +5 -1
- package/src/gjc-runtime/team-runtime.ts +59 -2
- package/src/gjc-runtime/tmux-owner-isolation.ts +19 -0
- package/src/gjc-runtime/ultragoal-receipt-freshness.ts +16 -1
- package/src/internal-urls/docs-index.generated.ts +17 -13
- package/src/internal-urls/local-protocol.ts +1 -0
- package/src/main.ts +40 -3
- package/src/memories/index.ts +4 -2
- package/src/modes/acp/acp-agent.ts +235 -91
- package/src/modes/components/model-selector.ts +206 -42
- package/src/modes/components/provider-order-context.ts +197 -0
- package/src/modes/components/provider-order-editor.ts +441 -0
- package/src/modes/components/settings-defs.ts +21 -1
- package/src/modes/components/settings-selector.ts +45 -2
- package/src/modes/components/tool-execution.ts +47 -15
- package/src/modes/controllers/command-controller.ts +6 -3
- package/src/modes/controllers/extension-ui-controller.ts +2 -0
- package/src/modes/controllers/input-controller.ts +73 -2
- package/src/modes/controllers/selector-controller.ts +260 -153
- package/src/modes/prompt-suggestion-controller.ts +1 -1
- package/src/modes/runtime-init.ts +1 -0
- package/src/modes/utils/ui-helpers.ts +18 -0
- package/src/prompts/tools/browser.md +1 -0
- package/src/quick-lane/classify.ts +257 -0
- package/src/rlm/index.ts +1 -1
- package/src/runtime/stt-settings-setup.ts +57 -0
- package/src/sdk/acp/adapter.ts +2 -1
- package/src/sdk/broker/broker.ts +780 -12
- package/src/sdk/broker/lifecycle.ts +70 -29
- package/src/sdk/broker/operation-receipt-ledger.ts +144 -0
- package/src/sdk/broker/session-index.ts +463 -48
- package/src/sdk/broker/state-version.ts +13 -9
- package/src/sdk/broker/transport.ts +14 -1
- package/src/sdk/bus/index.ts +34 -13
- package/src/sdk/bus/kind-aware-reconciliation.ts +21 -2
- package/src/sdk/bus/notification-service.ts +47 -1
- package/src/sdk/bus/prompt-reconciliation.ts +22 -3
- package/src/sdk/bus/telegram-daemon-contract.ts +4 -1
- package/src/sdk/bus/telegram-daemon.ts +54 -3
- package/src/sdk/cli/rows.ts +247 -0
- package/src/sdk/cli/session-cli.ts +930 -79
- package/src/sdk/elevation/allowlist.ts +54 -0
- package/src/sdk/elevation/audit.ts +208 -0
- package/src/sdk/elevation/capability.ts +41 -0
- package/src/sdk/elevation/digest.ts +129 -0
- package/src/sdk/elevation/dispatch-receipt.ts +184 -0
- package/src/sdk/elevation/grant-ledger.ts +1142 -0
- package/src/sdk/elevation/owner.ts +109 -0
- package/src/sdk/guides/cache.ts +363 -0
- package/src/sdk/guides/catalog.ts +554 -0
- package/src/sdk/guides/cli.ts +235 -0
- package/src/sdk/guides/manifest.ts +152 -0
- package/src/sdk/guides/verify.ts +178 -0
- package/src/sdk/host/control/dispatch.ts +49 -1
- package/src/sdk/host/control/index.ts +1 -0
- package/src/sdk/host/control/operations.ts +8 -1
- package/src/sdk/host/query/cursor.ts +47 -3
- package/src/sdk/host/query/handlers.ts +155 -2
- package/src/sdk/host/sdk-surface-parity.test.ts +1 -0
- package/src/sdk/host/session-runtime.test.ts +391 -1
- package/src/sdk/host/session-runtime.ts +308 -73
- package/src/sdk/host/surface-policy.ts +3 -0
- package/src/sdk/host/websocket-transport.ts +7 -1
- package/src/sdk/mcp/server.ts +88 -15
- package/src/sdk/prompt-status.ts +8 -0
- package/src/sdk/protocol/operation-inventory.generated.json +62 -0
- package/src/sdk/protocol/operation-registry.ts +3 -2
- package/src/sdk/session.ts +87 -39
- package/src/sdk/transport/index.ts +1 -0
- package/src/sdk/transport/relay.ts +3 -0
- package/src/sdk/transport/serve-cli.ts +111 -24
- package/src/secrets/obfuscator.ts +92 -12
- package/src/session/agent-session.ts +322 -93
- package/src/session/blob-store.ts +60 -8
- package/src/session/fallback-chain-controller.ts +35 -0
- package/src/session/internal/managed-session-scope.ts +25 -3
- package/src/session/internal/managed-session-storage.ts +574 -73
- package/src/session/internal/session-memory-sidecar.ts +19 -29
- package/src/session/session-manager.ts +2166 -743
- package/src/session/session-storage.ts +715 -48
- package/src/setup/provider-onboarding.ts +19 -3
- package/src/setup/provider-presets.json +3 -1
- package/src/slash-commands/builtin-registry.ts +85 -3
- package/src/stt/downloader.ts +2 -3
- package/src/stt/setup.ts +29 -4
- package/src/task/executor.ts +22 -18
- package/src/task/index.ts +24 -1
- package/src/tools/archive-reader.ts +11 -2
- package/src/tools/browser/runtime-diagnostics.ts +249 -0
- package/src/tools/browser/tab-protocol.ts +4 -0
- package/src/tools/browser/tab-supervisor.ts +5 -0
- package/src/tools/browser/tab-worker.ts +36 -1
- package/src/tools/browser.ts +7 -0
- package/src/tools/image-gen.ts +110 -166
- package/src/tools/index.ts +2 -0
- package/src/tools/read.ts +1 -1
- package/src/tools/resource-gc.ts +6 -1
- package/src/tools/tool-catalog.generated.ts +5 -1
- package/src/utils/pasted-image-path.ts +93 -0
- package/src/web/search/index.ts +3 -3
|
@@ -387,7 +387,7 @@ function removeResidentCacheTreeNoFollow(pathname: string): void {
|
|
|
387
387
|
fs.unlinkSync(pathname);
|
|
388
388
|
}
|
|
389
389
|
|
|
390
|
-
function disposeVerifiedResidentCacheInstanceDir(instanceDir: string): void {
|
|
390
|
+
export function disposeVerifiedResidentCacheInstanceDir(instanceDir: string): void {
|
|
391
391
|
const instanceKey = path.resolve(instanceDir);
|
|
392
392
|
const uid = residentCacheOwnerUid(instanceDir);
|
|
393
393
|
const quarantineDir = path.join(
|
|
@@ -444,7 +444,7 @@ function removePartialResidentCacheInstanceDir(instanceDir: string): void {
|
|
|
444
444
|
}
|
|
445
445
|
|
|
446
446
|
function isResidentCacheInstanceDirName(name: string): boolean {
|
|
447
|
-
return /^i-[A-Za-z0-9_-]
|
|
447
|
+
return /^(?:i-[A-Za-z0-9_-]+|s-[a-f0-9]{32})$/.test(name);
|
|
448
448
|
}
|
|
449
449
|
|
|
450
450
|
function residentCacheSweepLimit(value: number | undefined, ceiling: number): number {
|
|
@@ -591,7 +591,7 @@ function scheduleResidentCacheRootSweep(root: string): void {
|
|
|
591
591
|
* directories; callers must use {@link EphemeralBlobStore.adoptVerifiedDir}
|
|
592
592
|
* rather than the destructive EphemeralBlobStore constructor.
|
|
593
593
|
*/
|
|
594
|
-
|
|
594
|
+
function openVerifiedCacheInstanceDir(root: string, instanceName?: string): string {
|
|
595
595
|
const uid = residentCacheOwnerUid(root);
|
|
596
596
|
let rootDescriptor: number | null = null;
|
|
597
597
|
let instanceDir: string | null = null;
|
|
@@ -601,14 +601,32 @@ export function openVerifiedResidentCacheInstanceDir(root: string): string {
|
|
|
601
601
|
} catch (error) {
|
|
602
602
|
throw residentCacheTrustError("root_create_failed", root, error);
|
|
603
603
|
}
|
|
604
|
-
|
|
605
604
|
rootDescriptor = openVerifiedResidentCacheDirectory(root, uid);
|
|
606
605
|
try {
|
|
607
|
-
instanceDir = fs.mkdtempSync(path.join(root, "i-"));
|
|
606
|
+
if (instanceName === undefined) instanceDir = fs.mkdtempSync(path.join(root, "i-"));
|
|
607
|
+
else {
|
|
608
|
+
if (!/^s-[a-f0-9]{32}$/.test(instanceName))
|
|
609
|
+
throw new ResidentCacheTrustError("instance_name_invalid", instanceName);
|
|
610
|
+
const candidate = path.join(root, instanceName);
|
|
611
|
+
try {
|
|
612
|
+
fs.mkdirSync(candidate, { mode: BLOB_DIR_MODE });
|
|
613
|
+
} catch (error) {
|
|
614
|
+
if (errorCode(error) !== "EEXIST") throw error;
|
|
615
|
+
const staleInstance = readResidentCacheOwnerSnapshot(candidate, uid);
|
|
616
|
+
if (
|
|
617
|
+
staleInstance === null ||
|
|
618
|
+
!residentCacheOwnerIsStale(staleInstance.owner, new Map<number, number | null>()) ||
|
|
619
|
+
!reapResidentCacheInstanceDir(root, rootDescriptor, candidate, staleInstance, uid)
|
|
620
|
+
) {
|
|
621
|
+
throw error;
|
|
622
|
+
}
|
|
623
|
+
fs.mkdirSync(candidate, { mode: BLOB_DIR_MODE });
|
|
624
|
+
}
|
|
625
|
+
instanceDir = candidate;
|
|
626
|
+
}
|
|
608
627
|
} catch (error) {
|
|
609
628
|
throw residentCacheTrustError("instance_create_failed", root, error);
|
|
610
629
|
}
|
|
611
|
-
|
|
612
630
|
// Keep the root descriptor open while creating the nonce directory, then
|
|
613
631
|
// re-check the path against that descriptor before trusting the child.
|
|
614
632
|
assertResidentCacheDirectoryPathMatchesDescriptor(root, rootDescriptor, uid);
|
|
@@ -637,6 +655,15 @@ export function openVerifiedResidentCacheInstanceDir(root: string): string {
|
|
|
637
655
|
}
|
|
638
656
|
}
|
|
639
657
|
|
|
658
|
+
export function openVerifiedResidentCacheInstanceDir(root: string): string {
|
|
659
|
+
return openVerifiedCacheInstanceDir(root);
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/** Open the deterministic per-session managed-sidecar instance in its separate cache root. */
|
|
663
|
+
export function openVerifiedSidecarCacheInstanceDir(root: string, sessionHash: string): string {
|
|
664
|
+
return openVerifiedCacheInstanceDir(root, `s-${sessionHash}`);
|
|
665
|
+
}
|
|
666
|
+
|
|
640
667
|
function sha256Hex(data: Buffer): string {
|
|
641
668
|
return new Bun.SHA256().update(data).digest("hex");
|
|
642
669
|
}
|
|
@@ -1539,6 +1566,8 @@ export interface CanonicalBlobEntry {
|
|
|
1539
1566
|
readonly path: string;
|
|
1540
1567
|
readonly bytes: number;
|
|
1541
1568
|
readonly mtimeMs: number;
|
|
1569
|
+
readonly dev: number;
|
|
1570
|
+
readonly ino: number;
|
|
1542
1571
|
}
|
|
1543
1572
|
|
|
1544
1573
|
const CANONICAL_BLOB_NAME = /^[0-9a-f]{64}$/;
|
|
@@ -1577,7 +1606,14 @@ export async function listCanonicalBlobs(dir: string): Promise<CanonicalBlobEntr
|
|
|
1577
1606
|
continue;
|
|
1578
1607
|
}
|
|
1579
1608
|
if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1) continue;
|
|
1580
|
-
entries.push({
|
|
1609
|
+
entries.push({
|
|
1610
|
+
hash: name,
|
|
1611
|
+
path: blobPath,
|
|
1612
|
+
bytes: stat.size,
|
|
1613
|
+
mtimeMs: stat.mtimeMs,
|
|
1614
|
+
dev: stat.dev,
|
|
1615
|
+
ino: stat.ino,
|
|
1616
|
+
});
|
|
1581
1617
|
}
|
|
1582
1618
|
return entries;
|
|
1583
1619
|
}
|
|
@@ -1587,11 +1623,17 @@ export async function listCanonicalBlobs(dir: string): Promise<CanonicalBlobEntr
|
|
|
1587
1623
|
* at scan time must still describe the file at unlink time (same inode, size and
|
|
1588
1624
|
* mtime, still a single-link regular file), otherwise the blob is left in place.
|
|
1589
1625
|
*
|
|
1626
|
+
* `beforeUnlink` runs after this function has verified the blob and immediately
|
|
1627
|
+
* before it calls unlink. Callers use it to bind external liveness evidence to
|
|
1628
|
+
* the verified blob identity, so a live reference that appears while the blob is
|
|
1629
|
+
* being revalidated prevents the destructive syscall.
|
|
1630
|
+
*
|
|
1590
1631
|
* `failed` distinguishes an actual IO failure (which a caller should surface as
|
|
1591
1632
|
* a failed reclaim) from a revalidation refusal (which is an ordinary KEEP).
|
|
1592
1633
|
*/
|
|
1593
1634
|
export async function removeCanonicalBlob(
|
|
1594
1635
|
entry: CanonicalBlobEntry,
|
|
1636
|
+
options: { beforeUnlink?: () => Promise<boolean> } = {},
|
|
1595
1637
|
): Promise<{ removed: true } | { removed: false; reason: string; failed?: true }> {
|
|
1596
1638
|
let stat: fs.Stats;
|
|
1597
1639
|
try {
|
|
@@ -1603,7 +1645,17 @@ export async function removeCanonicalBlob(
|
|
|
1603
1645
|
if (!stat.isFile() || stat.isSymbolicLink() || stat.nlink !== 1) {
|
|
1604
1646
|
return { removed: false, reason: "blob_not_plain_file" };
|
|
1605
1647
|
}
|
|
1606
|
-
if (
|
|
1648
|
+
if (
|
|
1649
|
+
stat.dev !== entry.dev ||
|
|
1650
|
+
stat.ino !== entry.ino ||
|
|
1651
|
+
stat.size !== entry.bytes ||
|
|
1652
|
+
stat.mtimeMs !== entry.mtimeMs
|
|
1653
|
+
) {
|
|
1654
|
+
return { removed: false, reason: "blob_changed" };
|
|
1655
|
+
}
|
|
1656
|
+
if (options.beforeUnlink && !(await options.beforeUnlink())) {
|
|
1657
|
+
return { removed: false, reason: "blob_reference_evidence_changed" };
|
|
1658
|
+
}
|
|
1607
1659
|
try {
|
|
1608
1660
|
await fsp.unlink(entry.path);
|
|
1609
1661
|
return { removed: true };
|
|
@@ -17,6 +17,17 @@ export interface FallbackFailure {
|
|
|
17
17
|
|
|
18
18
|
export type FallbackFailureResult = "retry" | "advance" | "exhausted";
|
|
19
19
|
|
|
20
|
+
export interface FallbackChainRuntimeState {
|
|
21
|
+
activeIndex: number;
|
|
22
|
+
attemptsUsed: number;
|
|
23
|
+
totalAttemptsUsed: number;
|
|
24
|
+
attemptStarted: boolean;
|
|
25
|
+
restoredEntryIndices: number[];
|
|
26
|
+
tried: FallbackFailure[];
|
|
27
|
+
skips: Array<{ selector: string; reason: string }>;
|
|
28
|
+
exhaustedForTurn: boolean;
|
|
29
|
+
}
|
|
30
|
+
|
|
20
31
|
/**
|
|
21
32
|
* In-memory policy state for one fallback-chain scope. A controller is deliberately
|
|
22
33
|
* not serializable: configured chain intent is durable, current position is not.
|
|
@@ -43,6 +54,30 @@ export class FallbackChainController {
|
|
|
43
54
|
if (this.chain.entries.length === 0) this.exhaustedForTurn = true;
|
|
44
55
|
}
|
|
45
56
|
|
|
57
|
+
snapshotRuntimeState(): FallbackChainRuntimeState {
|
|
58
|
+
return {
|
|
59
|
+
activeIndex: this.activeIndex,
|
|
60
|
+
attemptsUsed: this.attemptsUsed,
|
|
61
|
+
totalAttemptsUsed: this.#totalAttemptsUsed,
|
|
62
|
+
attemptStarted: this.#attemptStarted,
|
|
63
|
+
restoredEntryIndices: [...this.#restoredEntryIndices],
|
|
64
|
+
tried: this.tried.map(failure => ({ ...failure })),
|
|
65
|
+
skips: this.skips.map(skip => ({ ...skip })),
|
|
66
|
+
exhaustedForTurn: this.exhaustedForTurn,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
restoreRuntimeState(state: FallbackChainRuntimeState): void {
|
|
71
|
+
this.activeIndex = state.activeIndex;
|
|
72
|
+
this.attemptsUsed = state.attemptsUsed;
|
|
73
|
+
this.#totalAttemptsUsed = state.totalAttemptsUsed;
|
|
74
|
+
this.#attemptStarted = state.attemptStarted;
|
|
75
|
+
this.#restoredEntryIndices = new Set(state.restoredEntryIndices);
|
|
76
|
+
this.tried = state.tried.map(failure => ({ ...failure }));
|
|
77
|
+
this.skips = state.skips.map(skip => ({ ...skip }));
|
|
78
|
+
this.exhaustedForTurn = state.exhaustedForTurn;
|
|
79
|
+
}
|
|
80
|
+
|
|
46
81
|
get totalAttemptsUsed(): number {
|
|
47
82
|
return this.#totalAttemptsUsed;
|
|
48
83
|
}
|
|
@@ -51,6 +51,7 @@ import {
|
|
|
51
51
|
prepareManagedDirectoryRoot,
|
|
52
52
|
publishManagedFileNoReplace,
|
|
53
53
|
publishManagedTombstone,
|
|
54
|
+
reapScrubbedProtocolRemnantsSync,
|
|
54
55
|
retainManagedDirectoryAuthority,
|
|
55
56
|
validateManagedArtifactTree,
|
|
56
57
|
validateNativeSecurityResult,
|
|
@@ -193,8 +194,27 @@ export type ManagedScopeResolution =
|
|
|
193
194
|
cause?: { readonly classification: string; readonly diagnostic?: string };
|
|
194
195
|
};
|
|
195
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Classify a failure for the operator-visible `cause`.
|
|
199
|
+
*
|
|
200
|
+
* Must agree with {@link managedScopeErrorCode}: the reported `code` and the
|
|
201
|
+
* `cause.classification` printed in the startup error are produced by separate
|
|
202
|
+
* helpers, so a message recognized by one and not the other still surfaces to
|
|
203
|
+
* the operator as `binding_invalid`.
|
|
204
|
+
*/
|
|
196
205
|
function managedScopeFailureCause(error: unknown): { readonly classification: string } {
|
|
197
|
-
|
|
206
|
+
const security = managedSecurityFailureClassification(error);
|
|
207
|
+
if (security) return { classification: security };
|
|
208
|
+
return { classification: managedScopeErrorCode(error instanceof Error ? error.message : "") };
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* A scope whose directory outgrew a scan budget. The binding is untouched and
|
|
213
|
+
* canonical; only the surrounding entry count is over budget, so this must not
|
|
214
|
+
* be reported as binding corruption.
|
|
215
|
+
*/
|
|
216
|
+
function isManagedScopeCapacityMessage(message: string): boolean {
|
|
217
|
+
return message === "artifact_capacity_exceeded" || message === "managed_replace_cleanup_receipt_limit_exceeded";
|
|
198
218
|
}
|
|
199
219
|
|
|
200
220
|
const managedScopeFailureCodes = new Set<ManagedScopeErrorCode>([
|
|
@@ -214,7 +234,7 @@ const managedScopeFailureCodes = new Set<ManagedScopeErrorCode>([
|
|
|
214
234
|
* corrupt binding, which sends operators to delete a healthy binding file.
|
|
215
235
|
*/
|
|
216
236
|
function managedScopeErrorCode(message: string): ManagedScopeErrorCode {
|
|
217
|
-
if (message === "content_too_large") return "capacity_exceeded";
|
|
237
|
+
if (message === "content_too_large" || isManagedScopeCapacityMessage(message)) return "capacity_exceeded";
|
|
218
238
|
return managedScopeFailureCodes.has(message as ManagedScopeErrorCode)
|
|
219
239
|
? (message as ManagedScopeErrorCode)
|
|
220
240
|
: "binding_invalid";
|
|
@@ -224,7 +244,7 @@ function managedScopeFailureMessage(error: unknown, fallback: string): string {
|
|
|
224
244
|
const classification = managedSecurityFailureClassification(error);
|
|
225
245
|
if (classification) return classification;
|
|
226
246
|
if (!(error instanceof Error)) return fallback;
|
|
227
|
-
if (error.message === "content_too_large") return error.message;
|
|
247
|
+
if (error.message === "content_too_large" || isManagedScopeCapacityMessage(error.message)) return error.message;
|
|
228
248
|
return managedScopeFailureCodes.has(error.message as ManagedScopeErrorCode) ? error.message : fallback;
|
|
229
249
|
}
|
|
230
250
|
|
|
@@ -1133,6 +1153,7 @@ export function prepareManagedSessionScopeForWriteSync(
|
|
|
1133
1153
|
ensureManagedDirectory(path.join(internal, MANAGED_RECEIPTS_DIRECTORY), root, policy);
|
|
1134
1154
|
stage = "tombstones_directory";
|
|
1135
1155
|
ensureManagedDirectory(path.join(internal, MANAGED_TOMBSTONES_DIRECTORY), root, policy);
|
|
1156
|
+
reapScrubbedProtocolRemnantsSync(scope.directoryPath);
|
|
1136
1157
|
return { kind: "resolved", scope };
|
|
1137
1158
|
} catch (error) {
|
|
1138
1159
|
const publication = error instanceof ManagedPublishError ? error : undefined;
|
|
@@ -3713,6 +3734,7 @@ export async function prepareManagedSessionScopeForWrite(
|
|
|
3713
3734
|
ensureManagedDirectory(path.join(internal, MANAGED_RECEIPTS_DIRECTORY), root, policy);
|
|
3714
3735
|
ensureManagedDirectory(path.join(internal, MANAGED_TOMBSTONES_DIRECTORY), root, policy);
|
|
3715
3736
|
await reconcileManagedTombstones(scope, expectedCandidate);
|
|
3737
|
+
reapScrubbedProtocolRemnantsSync(scope.directoryPath);
|
|
3716
3738
|
return { kind: "resolved", scope };
|
|
3717
3739
|
} catch (error) {
|
|
3718
3740
|
const publication = error instanceof ManagedPublishError ? error : undefined;
|