@@ -24,6 +24,7 @@ const REGISTRY_VERSION = 2 as const;
|
24 | 24 | const MAX_SUBAGENT_REGISTRY_READ_CACHE_ENTRIES = 32; |
25 | 25 | |
26 | 26 | type PersistedSubagentRunRecord = SubagentRunRecord; |
| 27 | +type ReadonlySubagentRunRecord = Readonly<SubagentRunRecord>; |
27 | 28 | |
28 | 29 | type RegistryCacheEntry = { |
29 | 30 | signature: string; |
@@ -43,7 +44,9 @@ function cloneSubagentRunRecord(entry: SubagentRunRecord): SubagentRunRecord {
|
43 | 44 | return structuredClone(entry); |
44 | 45 | } |
45 | 46 | |
46 | | -function cloneSubagentRunMap(runs: Map<string, SubagentRunRecord>): Map<string, SubagentRunRecord> { |
| 47 | +function cloneSubagentRunMap( |
| 48 | +runs: ReadonlyMap<string, SubagentRunRecord>, |
| 49 | +): Map<string, SubagentRunRecord> { |
47 | 50 | return new Map([...runs].map(([runId, entry]) => [runId, cloneSubagentRunRecord(entry)])); |
48 | 51 | } |
49 | 52 | |
@@ -78,7 +81,18 @@ export function resolveSubagentRegistryPath(): string {
|
78 | 81 | return path.join(resolveSubagentStateDir(process.env), "subagents", "runs.json"); |
79 | 82 | } |
80 | 83 | |
81 | | -export function loadSubagentRegistryFromDisk(): Map<string, SubagentRunRecord> { |
| 84 | +export function loadSubagentRegistryFromDisk(): Map<string, SubagentRunRecord>; |
| 85 | +export function loadSubagentRegistryFromDisk(options: { |
| 86 | +clone: false; |
| 87 | +}): ReadonlyMap<string, ReadonlySubagentRunRecord>; |
| 88 | +export function loadSubagentRegistryFromDisk(options?: { |
| 89 | +clone?: boolean; |
| 90 | +}): Map<string, SubagentRunRecord> | ReadonlyMap<string, ReadonlySubagentRunRecord> { |
| 91 | +const snapshot = loadSubagentRegistrySnapshotForRead(); |
| 92 | +return options?.clone === false ? snapshot : cloneSubagentRunMap(snapshot); |
| 93 | +} |
| 94 | + |
| 95 | +function loadSubagentRegistrySnapshotForRead(): ReadonlyMap<string, ReadonlySubagentRunRecord> { |
82 | 96 | const pathname = resolveSubagentRegistryPath(); |
83 | 97 | const signature = statRegistryFileSignature(pathname); |
84 | 98 | if (signature === null) { |
@@ -89,7 +103,9 @@ export function loadSubagentRegistryFromDisk(): Map<string, SubagentRunRecord> {
|
89 | 103 | if (cached?.signature === signature) { |
90 | 104 | registryReadCache.delete(pathname); |
91 | 105 | registryReadCache.set(pathname, cached); |
92 | | -return cloneSubagentRunMap(cached.runs); |
| 106 | +// No-clone reads share cached records; only read snapshot callers may use |
| 107 | +// this path. Mutation/restore callers must keep the default cloned load. |
| 108 | +return cached.runs; |
93 | 109 | } |
94 | 110 | const raw = loadJsonFile(pathname); |
95 | 111 | if (!raw || typeof raw !== "object") { |
|