@caupulican/pi-adaptative 0.96.4 → 0.96.5
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 +12 -0
- package/README.md +8 -0
- package/dist/config.d.ts +2 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +3 -1
- package/dist/config.js.map +1 -1
- package/dist/core/agent-session-contracts.d.ts +1 -1
- package/dist/core/agent-session-contracts.d.ts.map +1 -1
- package/dist/core/agent-session-contracts.js.map +1 -1
- package/dist/core/agent-session.d.ts +2 -0
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +29 -14
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/goals/goal-lifecycle.d.ts.map +1 -1
- package/dist/core/goals/goal-lifecycle.js +5 -1
- package/dist/core/goals/goal-lifecycle.js.map +1 -1
- package/dist/core/goals/goal-session-controller.d.ts.map +1 -1
- package/dist/core/goals/goal-session-controller.js +3 -1
- package/dist/core/goals/goal-session-controller.js.map +1 -1
- package/dist/core/goals/goal-tool-core.d.ts.map +1 -1
- package/dist/core/goals/goal-tool-core.js +32 -7
- package/dist/core/goals/goal-tool-core.js.map +1 -1
- package/dist/core/learning/durable-learning-state.d.ts +76 -0
- package/dist/core/learning/durable-learning-state.d.ts.map +1 -0
- package/dist/core/learning/durable-learning-state.js +493 -0
- package/dist/core/learning/durable-learning-state.js.map +1 -0
- package/dist/core/reflection-controller.d.ts +37 -7
- package/dist/core/reflection-controller.d.ts.map +1 -1
- package/dist/core/reflection-controller.js +278 -49
- package/dist/core/reflection-controller.js.map +1 -1
- package/dist/core/settings-manager.js.map +1 -1
- package/dist/core/tools/goal.d.ts.map +1 -1
- package/dist/core/tools/goal.js +6 -3
- package/dist/core/tools/goal.js.map +1 -1
- package/dist/modes/interactive/components/settings-selector.js +1 -1
- package/dist/modes/interactive/components/settings-selector.js.map +1 -1
- package/docs/durable-learning-state-design.md +217 -0
- package/docs/settings.md +5 -3
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +12 -12
- package/package.json +4 -4
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
3
|
+
import { stateFile } from "../agent-paths.js";
|
|
4
|
+
import { withFileLockSync, writeFileAtomicSync } from "../util/atomic-file.js";
|
|
5
|
+
export const DURABLE_LEARNING_MEMORY_POLICY_VERSION = "1";
|
|
6
|
+
export const DURABLE_LEARNING_STATE_MAX_HISTORY = 32;
|
|
7
|
+
export const DURABLE_LEARNING_STATE_MAX_BYTES = 64 * 1024;
|
|
8
|
+
export const DURABLE_LEARNING_CLAIM_LEASE_MS = 90 * 60_000;
|
|
9
|
+
const STATE_FILE_NAME = "durable-learning-state.json";
|
|
10
|
+
const MAX_VERSION_LENGTH = 128;
|
|
11
|
+
const UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
|
|
12
|
+
const VERSION_RE = /^[A-Za-z0-9][A-Za-z0-9._+-]*$/;
|
|
13
|
+
const TOP_LEVEL_KEYS = [
|
|
14
|
+
"schemaVersion",
|
|
15
|
+
"revision",
|
|
16
|
+
"observedRuntimeVersion",
|
|
17
|
+
"observedMemoryPolicyVersion",
|
|
18
|
+
"current",
|
|
19
|
+
"history",
|
|
20
|
+
];
|
|
21
|
+
const PENDING_KEYS = [
|
|
22
|
+
"transitionId",
|
|
23
|
+
"reason",
|
|
24
|
+
"previousRuntimeVersion",
|
|
25
|
+
"runtimeVersion",
|
|
26
|
+
"previousMemoryPolicyVersion",
|
|
27
|
+
"memoryPolicyVersion",
|
|
28
|
+
"createdAt",
|
|
29
|
+
"updatedAt",
|
|
30
|
+
"claim",
|
|
31
|
+
];
|
|
32
|
+
const RESOLVED_KEYS = [
|
|
33
|
+
"transitionId",
|
|
34
|
+
"reason",
|
|
35
|
+
"previousRuntimeVersion",
|
|
36
|
+
"runtimeVersion",
|
|
37
|
+
"previousMemoryPolicyVersion",
|
|
38
|
+
"memoryPolicyVersion",
|
|
39
|
+
"createdAt",
|
|
40
|
+
"resolvedAt",
|
|
41
|
+
"status",
|
|
42
|
+
];
|
|
43
|
+
const CLAIM_KEYS = ["claimId", "ownerId", "acquiredAt", "expiresAt"];
|
|
44
|
+
function isRecord(value) {
|
|
45
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
46
|
+
}
|
|
47
|
+
function hasUnknownKeys(value, allowed) {
|
|
48
|
+
const allowedKeys = new Set(allowed);
|
|
49
|
+
return Object.keys(value).some((key) => !allowedKeys.has(key));
|
|
50
|
+
}
|
|
51
|
+
function hasExactKeys(value, allowed) {
|
|
52
|
+
return Object.keys(value).length === allowed.length && !hasUnknownKeys(value, allowed);
|
|
53
|
+
}
|
|
54
|
+
function isVersion(value) {
|
|
55
|
+
return (typeof value === "string" &&
|
|
56
|
+
value.length > 0 &&
|
|
57
|
+
value.length <= MAX_VERSION_LENGTH &&
|
|
58
|
+
value.trim() === value &&
|
|
59
|
+
VERSION_RE.test(value));
|
|
60
|
+
}
|
|
61
|
+
function isUuid(value) {
|
|
62
|
+
return typeof value === "string" && UUID_RE.test(value);
|
|
63
|
+
}
|
|
64
|
+
function isTimestamp(value) {
|
|
65
|
+
if (typeof value !== "string" || value.length > 64)
|
|
66
|
+
return false;
|
|
67
|
+
const parsed = new Date(value);
|
|
68
|
+
return Number.isFinite(parsed.getTime()) && parsed.toISOString() === value;
|
|
69
|
+
}
|
|
70
|
+
function isReason(value) {
|
|
71
|
+
return (value === "first-observation" ||
|
|
72
|
+
value === "runtime-change" ||
|
|
73
|
+
value === "memory-policy-change" ||
|
|
74
|
+
value === "runtime-and-policy-change" ||
|
|
75
|
+
value === "recovered-corrupt-state");
|
|
76
|
+
}
|
|
77
|
+
function isNullableVersion(value) {
|
|
78
|
+
return value === null || isVersion(value);
|
|
79
|
+
}
|
|
80
|
+
export function isDurableLearningClaimToken(value) {
|
|
81
|
+
if (!isRecord(value))
|
|
82
|
+
return false;
|
|
83
|
+
return (Object.keys(value).length === 5 &&
|
|
84
|
+
isUuid(value.transitionId) &&
|
|
85
|
+
isUuid(value.claimId) &&
|
|
86
|
+
isUuid(value.ownerId) &&
|
|
87
|
+
isVersion(value.runtimeVersion) &&
|
|
88
|
+
isVersion(value.memoryPolicyVersion));
|
|
89
|
+
}
|
|
90
|
+
export function isDurableLearningReviewMetadata(value) {
|
|
91
|
+
if (!isRecord(value))
|
|
92
|
+
return false;
|
|
93
|
+
return (Object.keys(value).length === 5 &&
|
|
94
|
+
isReason(value.reason) &&
|
|
95
|
+
isNullableVersion(value.previousRuntimeVersion) &&
|
|
96
|
+
isVersion(value.runtimeVersion) &&
|
|
97
|
+
isNullableVersion(value.previousMemoryPolicyVersion) &&
|
|
98
|
+
isVersion(value.memoryPolicyVersion));
|
|
99
|
+
}
|
|
100
|
+
function inspectUnknownKeys(value) {
|
|
101
|
+
if (hasUnknownKeys(value, TOP_LEVEL_KEYS))
|
|
102
|
+
return true;
|
|
103
|
+
const current = value.current;
|
|
104
|
+
if (isRecord(current)) {
|
|
105
|
+
if (hasUnknownKeys(current, PENDING_KEYS))
|
|
106
|
+
return true;
|
|
107
|
+
if (isRecord(current.claim) && hasUnknownKeys(current.claim, CLAIM_KEYS))
|
|
108
|
+
return true;
|
|
109
|
+
}
|
|
110
|
+
if (Array.isArray(value.history)) {
|
|
111
|
+
for (const entry of value.history) {
|
|
112
|
+
if (isRecord(entry) && hasUnknownKeys(entry, RESOLVED_KEYS))
|
|
113
|
+
return true;
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
return false;
|
|
117
|
+
}
|
|
118
|
+
function isClaim(value) {
|
|
119
|
+
if (!isRecord(value) || !hasExactKeys(value, CLAIM_KEYS))
|
|
120
|
+
return false;
|
|
121
|
+
return (isUuid(value.claimId) &&
|
|
122
|
+
isUuid(value.ownerId) &&
|
|
123
|
+
isTimestamp(value.acquiredAt) &&
|
|
124
|
+
isTimestamp(value.expiresAt) &&
|
|
125
|
+
value.expiresAt > value.acquiredAt);
|
|
126
|
+
}
|
|
127
|
+
function hasValidTransitionIdentity(value) {
|
|
128
|
+
return (isUuid(value.transitionId) &&
|
|
129
|
+
isReason(value.reason) &&
|
|
130
|
+
isNullableVersion(value.previousRuntimeVersion) &&
|
|
131
|
+
isVersion(value.runtimeVersion) &&
|
|
132
|
+
isNullableVersion(value.previousMemoryPolicyVersion) &&
|
|
133
|
+
isVersion(value.memoryPolicyVersion) &&
|
|
134
|
+
isTimestamp(value.createdAt));
|
|
135
|
+
}
|
|
136
|
+
function isPendingTransition(value) {
|
|
137
|
+
if (!isRecord(value) || !hasExactKeys(value, PENDING_KEYS))
|
|
138
|
+
return false;
|
|
139
|
+
return (hasValidTransitionIdentity(value) &&
|
|
140
|
+
isTimestamp(value.updatedAt) &&
|
|
141
|
+
(value.claim === null || isClaim(value.claim)));
|
|
142
|
+
}
|
|
143
|
+
function isResolvedTransition(value) {
|
|
144
|
+
if (!isRecord(value) || !hasExactKeys(value, RESOLVED_KEYS))
|
|
145
|
+
return false;
|
|
146
|
+
return (hasValidTransitionIdentity(value) &&
|
|
147
|
+
isTimestamp(value.resolvedAt) &&
|
|
148
|
+
(value.status === "reviewed" || value.status === "superseded"));
|
|
149
|
+
}
|
|
150
|
+
function validateState(value) {
|
|
151
|
+
if (!isRecord(value))
|
|
152
|
+
return { kind: "corrupt" };
|
|
153
|
+
if (value.schemaVersion !== 1)
|
|
154
|
+
return { kind: "unsupported", warningCode: "unsupported-schema" };
|
|
155
|
+
if (inspectUnknownKeys(value))
|
|
156
|
+
return { kind: "unsupported", warningCode: "unknown-keys" };
|
|
157
|
+
if (!hasExactKeys(value, TOP_LEVEL_KEYS))
|
|
158
|
+
return { kind: "corrupt" };
|
|
159
|
+
if (!Number.isSafeInteger(value.revision) || value.revision < 1)
|
|
160
|
+
return { kind: "corrupt" };
|
|
161
|
+
if (!isVersion(value.observedRuntimeVersion) || !isVersion(value.observedMemoryPolicyVersion)) {
|
|
162
|
+
return { kind: "corrupt" };
|
|
163
|
+
}
|
|
164
|
+
if (value.current !== null && !isPendingTransition(value.current))
|
|
165
|
+
return { kind: "corrupt" };
|
|
166
|
+
if (!Array.isArray(value.history) ||
|
|
167
|
+
value.history.length > DURABLE_LEARNING_STATE_MAX_HISTORY ||
|
|
168
|
+
value.history.some((entry) => !isResolvedTransition(entry))) {
|
|
169
|
+
return { kind: "corrupt" };
|
|
170
|
+
}
|
|
171
|
+
const current = value.current;
|
|
172
|
+
if (current &&
|
|
173
|
+
(current.runtimeVersion !== value.observedRuntimeVersion ||
|
|
174
|
+
current.memoryPolicyVersion !== value.observedMemoryPolicyVersion)) {
|
|
175
|
+
return { kind: "corrupt" };
|
|
176
|
+
}
|
|
177
|
+
const ids = [
|
|
178
|
+
current?.transitionId,
|
|
179
|
+
...value.history.map((entry) => entry.transitionId),
|
|
180
|
+
].filter((id) => !!id);
|
|
181
|
+
if (new Set(ids).size !== ids.length)
|
|
182
|
+
return { kind: "corrupt" };
|
|
183
|
+
return { kind: "ok", state: value };
|
|
184
|
+
}
|
|
185
|
+
function exactTokenMatches(current, token) {
|
|
186
|
+
const claim = current?.claim;
|
|
187
|
+
return (!!current &&
|
|
188
|
+
!!claim &&
|
|
189
|
+
current.transitionId === token.transitionId &&
|
|
190
|
+
claim.claimId === token.claimId &&
|
|
191
|
+
claim.ownerId === token.ownerId &&
|
|
192
|
+
current.runtimeVersion === token.runtimeVersion &&
|
|
193
|
+
current.memoryPolicyVersion === token.memoryPolicyVersion);
|
|
194
|
+
}
|
|
195
|
+
function metadataFromTransition(current) {
|
|
196
|
+
return {
|
|
197
|
+
reason: current.reason,
|
|
198
|
+
previousRuntimeVersion: current.previousRuntimeVersion,
|
|
199
|
+
runtimeVersion: current.runtimeVersion,
|
|
200
|
+
previousMemoryPolicyVersion: current.previousMemoryPolicyVersion,
|
|
201
|
+
memoryPolicyVersion: current.memoryPolicyVersion,
|
|
202
|
+
};
|
|
203
|
+
}
|
|
204
|
+
function tokenFromTransition(current) {
|
|
205
|
+
if (!current.claim)
|
|
206
|
+
throw new Error("Durable learning transition has no claim");
|
|
207
|
+
return {
|
|
208
|
+
transitionId: current.transitionId,
|
|
209
|
+
claimId: current.claim.claimId,
|
|
210
|
+
ownerId: current.claim.ownerId,
|
|
211
|
+
runtimeVersion: current.runtimeVersion,
|
|
212
|
+
memoryPolicyVersion: current.memoryPolicyVersion,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
export class DurableLearningState {
|
|
216
|
+
constructor(filePath, options = {}) {
|
|
217
|
+
this.filePath = filePath;
|
|
218
|
+
this.now = options.now ?? (() => new Date());
|
|
219
|
+
this.randomId = options.randomId ?? randomUUID;
|
|
220
|
+
this.leaseMs = options.leaseMs ?? DURABLE_LEARNING_CLAIM_LEASE_MS;
|
|
221
|
+
this.withLock = options.withLock ?? ((path, fn) => withFileLockSync(path, fn));
|
|
222
|
+
this.writeState =
|
|
223
|
+
options.writeState ?? ((path, contents) => writeFileAtomicSync(path, contents, { mode: 0o600 }));
|
|
224
|
+
if (!Number.isSafeInteger(this.leaseMs) || this.leaseMs <= 0) {
|
|
225
|
+
throw new TypeError("Durable learning claim lease must be a positive safe integer");
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
static forAgentDir(agentDir, options = {}) {
|
|
229
|
+
return new DurableLearningState(stateFile(agentDir, STATE_FILE_NAME), options);
|
|
230
|
+
}
|
|
231
|
+
currentDate() {
|
|
232
|
+
const current = this.now();
|
|
233
|
+
if (!(current instanceof Date) || !Number.isFinite(current.getTime())) {
|
|
234
|
+
throw new Error("Durable learning clock returned an invalid date");
|
|
235
|
+
}
|
|
236
|
+
return current;
|
|
237
|
+
}
|
|
238
|
+
nextId() {
|
|
239
|
+
const id = this.randomId();
|
|
240
|
+
if (!isUuid(id))
|
|
241
|
+
throw new Error("Durable learning random ID source returned an invalid UUID");
|
|
242
|
+
return id;
|
|
243
|
+
}
|
|
244
|
+
load() {
|
|
245
|
+
try {
|
|
246
|
+
if (!existsSync(this.filePath))
|
|
247
|
+
return { kind: "missing" };
|
|
248
|
+
if (statSync(this.filePath).size > DURABLE_LEARNING_STATE_MAX_BYTES) {
|
|
249
|
+
return { kind: "unsupported", warningCode: "oversize-state" };
|
|
250
|
+
}
|
|
251
|
+
const contents = readFileSync(this.filePath, "utf-8");
|
|
252
|
+
if (Buffer.byteLength(contents, "utf-8") > DURABLE_LEARNING_STATE_MAX_BYTES) {
|
|
253
|
+
return { kind: "unsupported", warningCode: "oversize-state" };
|
|
254
|
+
}
|
|
255
|
+
try {
|
|
256
|
+
return validateState(JSON.parse(contents));
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
return { kind: "corrupt" };
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
return { kind: "unavailable" };
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
save(state) {
|
|
267
|
+
if (state.history.length > DURABLE_LEARNING_STATE_MAX_HISTORY) {
|
|
268
|
+
state.history = state.history.slice(-DURABLE_LEARNING_STATE_MAX_HISTORY);
|
|
269
|
+
}
|
|
270
|
+
const contents = `${JSON.stringify(state, null, "\t")}\n`;
|
|
271
|
+
if (Buffer.byteLength(contents, "utf-8") > DURABLE_LEARNING_STATE_MAX_BYTES) {
|
|
272
|
+
throw new Error("Durable learning state exceeds its byte bound");
|
|
273
|
+
}
|
|
274
|
+
this.writeState(this.filePath, contents);
|
|
275
|
+
}
|
|
276
|
+
newClaim(ownerId, now) {
|
|
277
|
+
return {
|
|
278
|
+
claimId: this.nextId(),
|
|
279
|
+
ownerId,
|
|
280
|
+
acquiredAt: now.toISOString(),
|
|
281
|
+
expiresAt: new Date(now.getTime() + this.leaseMs).toISOString(),
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
newTransition(versions, reason, previousRuntimeVersion, previousMemoryPolicyVersion, ownerId, now) {
|
|
285
|
+
const at = now.toISOString();
|
|
286
|
+
return {
|
|
287
|
+
transitionId: this.nextId(),
|
|
288
|
+
reason,
|
|
289
|
+
previousRuntimeVersion,
|
|
290
|
+
runtimeVersion: versions.runtimeVersion,
|
|
291
|
+
previousMemoryPolicyVersion,
|
|
292
|
+
memoryPolicyVersion: versions.memoryPolicyVersion,
|
|
293
|
+
createdAt: at,
|
|
294
|
+
updatedAt: at,
|
|
295
|
+
claim: this.newClaim(ownerId, now),
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
resolveCurrent(state, status, now) {
|
|
299
|
+
const current = state.current;
|
|
300
|
+
if (!current)
|
|
301
|
+
return;
|
|
302
|
+
state.history.push({
|
|
303
|
+
transitionId: current.transitionId,
|
|
304
|
+
reason: current.reason,
|
|
305
|
+
previousRuntimeVersion: current.previousRuntimeVersion,
|
|
306
|
+
runtimeVersion: current.runtimeVersion,
|
|
307
|
+
previousMemoryPolicyVersion: current.previousMemoryPolicyVersion,
|
|
308
|
+
memoryPolicyVersion: current.memoryPolicyVersion,
|
|
309
|
+
createdAt: current.createdAt,
|
|
310
|
+
resolvedAt: now.toISOString(),
|
|
311
|
+
status,
|
|
312
|
+
});
|
|
313
|
+
if (state.history.length > DURABLE_LEARNING_STATE_MAX_HISTORY) {
|
|
314
|
+
state.history = state.history.slice(-DURABLE_LEARNING_STATE_MAX_HISTORY);
|
|
315
|
+
}
|
|
316
|
+
state.current = null;
|
|
317
|
+
}
|
|
318
|
+
initialState(versions, ownerId, now, reason) {
|
|
319
|
+
return {
|
|
320
|
+
schemaVersion: 1,
|
|
321
|
+
revision: 1,
|
|
322
|
+
observedRuntimeVersion: versions.runtimeVersion,
|
|
323
|
+
observedMemoryPolicyVersion: versions.memoryPolicyVersion,
|
|
324
|
+
current: this.newTransition(versions, reason, null, null, ownerId, now),
|
|
325
|
+
history: [],
|
|
326
|
+
};
|
|
327
|
+
}
|
|
328
|
+
changedReason(state, versions) {
|
|
329
|
+
const runtimeChanged = state.observedRuntimeVersion !== versions.runtimeVersion;
|
|
330
|
+
const policyChanged = state.observedMemoryPolicyVersion !== versions.memoryPolicyVersion;
|
|
331
|
+
if (runtimeChanged && policyChanged)
|
|
332
|
+
return "runtime-and-policy-change";
|
|
333
|
+
if (runtimeChanged)
|
|
334
|
+
return "runtime-change";
|
|
335
|
+
if (policyChanged)
|
|
336
|
+
return "memory-policy-change";
|
|
337
|
+
return undefined;
|
|
338
|
+
}
|
|
339
|
+
reconcileClaimAndAttach(versions, ownerId, attachCue) {
|
|
340
|
+
if (!isVersion(versions.runtimeVersion) || !isVersion(versions.memoryPolicyVersion)) {
|
|
341
|
+
return { status: "invalid-version" };
|
|
342
|
+
}
|
|
343
|
+
if (!isUuid(ownerId))
|
|
344
|
+
return { status: "invalid-owner" };
|
|
345
|
+
const preflight = this.load();
|
|
346
|
+
if (preflight.kind === "unsupported")
|
|
347
|
+
return { status: "unsupported", warningCode: preflight.warningCode };
|
|
348
|
+
if (preflight.kind === "unavailable")
|
|
349
|
+
return { status: "unavailable", warningCode: "state-unavailable" };
|
|
350
|
+
try {
|
|
351
|
+
return this.withLock(this.filePath, () => {
|
|
352
|
+
const loaded = this.load();
|
|
353
|
+
if (loaded.kind === "unsupported") {
|
|
354
|
+
return { status: "unsupported", warningCode: loaded.warningCode };
|
|
355
|
+
}
|
|
356
|
+
if (loaded.kind === "unavailable") {
|
|
357
|
+
return { status: "unavailable", warningCode: "state-unavailable" };
|
|
358
|
+
}
|
|
359
|
+
const now = this.currentDate();
|
|
360
|
+
let warningCode;
|
|
361
|
+
let state;
|
|
362
|
+
if (loaded.kind === "missing") {
|
|
363
|
+
state = this.initialState(versions, ownerId, now, "first-observation");
|
|
364
|
+
}
|
|
365
|
+
else if (loaded.kind === "corrupt") {
|
|
366
|
+
state = this.initialState(versions, ownerId, now, "recovered-corrupt-state");
|
|
367
|
+
warningCode = "recovered-corrupt-state";
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
state = loaded.state;
|
|
371
|
+
const reason = this.changedReason(state, versions);
|
|
372
|
+
if (reason) {
|
|
373
|
+
const previousRuntimeVersion = state.observedRuntimeVersion;
|
|
374
|
+
const previousMemoryPolicyVersion = state.observedMemoryPolicyVersion;
|
|
375
|
+
this.resolveCurrent(state, "superseded", now);
|
|
376
|
+
state.observedRuntimeVersion = versions.runtimeVersion;
|
|
377
|
+
state.observedMemoryPolicyVersion = versions.memoryPolicyVersion;
|
|
378
|
+
state.current = this.newTransition(versions, reason, previousRuntimeVersion, previousMemoryPolicyVersion, ownerId, now);
|
|
379
|
+
state.revision += 1;
|
|
380
|
+
}
|
|
381
|
+
else if (!state.current) {
|
|
382
|
+
return { status: "unchanged" };
|
|
383
|
+
}
|
|
384
|
+
else {
|
|
385
|
+
const claim = state.current.claim;
|
|
386
|
+
const live = !!claim && new Date(claim.expiresAt).getTime() > now.getTime();
|
|
387
|
+
if (live && claim.ownerId !== ownerId)
|
|
388
|
+
return { status: "busy" };
|
|
389
|
+
if (live) {
|
|
390
|
+
claim.expiresAt = new Date(now.getTime() + this.leaseMs).toISOString();
|
|
391
|
+
state.current.updatedAt = now.toISOString();
|
|
392
|
+
state.revision += 1;
|
|
393
|
+
}
|
|
394
|
+
else {
|
|
395
|
+
state.current.claim = this.newClaim(ownerId, now);
|
|
396
|
+
state.current.updatedAt = now.toISOString();
|
|
397
|
+
state.revision += 1;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
const current = state.current;
|
|
402
|
+
if (!current?.claim)
|
|
403
|
+
throw new Error("Durable learning reconciliation produced no claim");
|
|
404
|
+
this.save(state);
|
|
405
|
+
const token = tokenFromTransition(current);
|
|
406
|
+
let outcome;
|
|
407
|
+
try {
|
|
408
|
+
outcome = attachCue(token, metadataFromTransition(current));
|
|
409
|
+
}
|
|
410
|
+
catch {
|
|
411
|
+
outcome = "failed";
|
|
412
|
+
}
|
|
413
|
+
if (outcome === "disabled" || outcome === "failed") {
|
|
414
|
+
const settlingCurrent = state.current;
|
|
415
|
+
if (settlingCurrent && exactTokenMatches(settlingCurrent, token)) {
|
|
416
|
+
settlingCurrent.claim = null;
|
|
417
|
+
settlingCurrent.updatedAt = this.currentDate().toISOString();
|
|
418
|
+
state.revision += 1;
|
|
419
|
+
this.save(state);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
return warningCode ? { status: outcome, warningCode } : { status: outcome };
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
return { status: "unavailable", warningCode: "state-unavailable" };
|
|
427
|
+
}
|
|
428
|
+
}
|
|
429
|
+
mutateExactClaim(token, mutate) {
|
|
430
|
+
if (!this.validToken(token))
|
|
431
|
+
return false;
|
|
432
|
+
const preflight = this.load();
|
|
433
|
+
if (preflight.kind !== "ok")
|
|
434
|
+
return false;
|
|
435
|
+
try {
|
|
436
|
+
return this.withLock(this.filePath, () => {
|
|
437
|
+
const loaded = this.load();
|
|
438
|
+
if (loaded.kind !== "ok")
|
|
439
|
+
return false;
|
|
440
|
+
const current = loaded.state.current;
|
|
441
|
+
if (!current || !exactTokenMatches(current, token) || !mutate(loaded.state, current))
|
|
442
|
+
return false;
|
|
443
|
+
loaded.state.revision += 1;
|
|
444
|
+
this.save(loaded.state);
|
|
445
|
+
return true;
|
|
446
|
+
});
|
|
447
|
+
}
|
|
448
|
+
catch {
|
|
449
|
+
return false;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
renewClaim(token) {
|
|
453
|
+
return this.mutateExactClaim(token, (_state, current) => {
|
|
454
|
+
const now = this.currentDate();
|
|
455
|
+
if (!current.claim || new Date(current.claim.expiresAt).getTime() <= now.getTime())
|
|
456
|
+
return false;
|
|
457
|
+
current.claim.expiresAt = new Date(now.getTime() + this.leaseMs).toISOString();
|
|
458
|
+
current.updatedAt = now.toISOString();
|
|
459
|
+
return true;
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
releaseClaim(token) {
|
|
463
|
+
return this.mutateExactClaim(token, (_state, current) => {
|
|
464
|
+
current.claim = null;
|
|
465
|
+
current.updatedAt = this.currentDate().toISOString();
|
|
466
|
+
return true;
|
|
467
|
+
});
|
|
468
|
+
}
|
|
469
|
+
completeReview(token) {
|
|
470
|
+
return this.mutateExactClaim(token, (state) => {
|
|
471
|
+
this.resolveCurrent(state, "reviewed", this.currentDate());
|
|
472
|
+
return true;
|
|
473
|
+
});
|
|
474
|
+
}
|
|
475
|
+
readSnapshot() {
|
|
476
|
+
const loaded = this.load();
|
|
477
|
+
if (loaded.kind !== "ok")
|
|
478
|
+
return undefined;
|
|
479
|
+
return {
|
|
480
|
+
schemaVersion: 1,
|
|
481
|
+
revision: loaded.state.revision,
|
|
482
|
+
observedRuntimeVersion: loaded.state.observedRuntimeVersion,
|
|
483
|
+
observedMemoryPolicyVersion: loaded.state.observedMemoryPolicyVersion,
|
|
484
|
+
currentTransitionId: loaded.state.current?.transitionId ?? null,
|
|
485
|
+
currentClaimOwnerId: loaded.state.current?.claim?.ownerId ?? null,
|
|
486
|
+
resolvedTransitions: loaded.state.history.length,
|
|
487
|
+
};
|
|
488
|
+
}
|
|
489
|
+
validToken(token) {
|
|
490
|
+
return isDurableLearningClaimToken(token);
|
|
491
|
+
}
|
|
492
|
+
}
|
|
493
|
+
//# sourceMappingURL=durable-learning-state.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"durable-learning-state.js","sourceRoot":"","sources":["../../../src/core/learning/durable-learning-state.ts"],"names":[],"mappings":"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","sourcesContent":["import { randomUUID } from \"node:crypto\";\nimport { existsSync, readFileSync, statSync } from \"node:fs\";\nimport { stateFile } from \"../agent-paths.ts\";\nimport { withFileLockSync, writeFileAtomicSync } from \"../util/atomic-file.ts\";\n\nexport const DURABLE_LEARNING_MEMORY_POLICY_VERSION = \"1\";\nexport const DURABLE_LEARNING_STATE_MAX_HISTORY = 32;\nexport const DURABLE_LEARNING_STATE_MAX_BYTES = 64 * 1024;\nexport const DURABLE_LEARNING_CLAIM_LEASE_MS = 90 * 60_000;\n\nconst STATE_FILE_NAME = \"durable-learning-state.json\";\nconst MAX_VERSION_LENGTH = 128;\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\nconst VERSION_RE = /^[A-Za-z0-9][A-Za-z0-9._+-]*$/;\n\nexport interface DurableLearningVersions {\n\truntimeVersion: string;\n\tmemoryPolicyVersion: string;\n}\n\nexport type DurableLearningTransitionReason =\n\t| \"first-observation\"\n\t| \"runtime-change\"\n\t| \"memory-policy-change\"\n\t| \"runtime-and-policy-change\"\n\t| \"recovered-corrupt-state\";\n\nexport interface DurableLearningReviewMetadata {\n\treason: DurableLearningTransitionReason;\n\tpreviousRuntimeVersion: string | null;\n\truntimeVersion: string;\n\tpreviousMemoryPolicyVersion: string | null;\n\tmemoryPolicyVersion: string;\n}\n\nexport interface DurableLearningClaimToken {\n\ttransitionId: string;\n\tclaimId: string;\n\townerId: string;\n\truntimeVersion: string;\n\tmemoryPolicyVersion: string;\n}\n\nexport type DurableLearningCueAttachOutcome = \"attached\" | \"coalesced\" | \"replaced-stale\" | \"disabled\" | \"failed\";\n\nexport type DurableLearningStateWarningCode =\n\t| \"recovered-corrupt-state\"\n\t| \"unsupported-schema\"\n\t| \"unknown-keys\"\n\t| \"oversize-state\"\n\t| \"state-unavailable\";\n\nexport type DurableLearningReconcileStatus =\n\t| DurableLearningCueAttachOutcome\n\t| \"busy\"\n\t| \"unchanged\"\n\t| \"unsupported\"\n\t| \"invalid-version\"\n\t| \"invalid-owner\"\n\t| \"unavailable\";\n\nexport interface DurableLearningReconcileResult {\n\tstatus: DurableLearningReconcileStatus;\n\twarningCode?: DurableLearningStateWarningCode;\n}\n\ninterface DurableLearningClaim {\n\tclaimId: string;\n\townerId: string;\n\tacquiredAt: string;\n\texpiresAt: string;\n}\n\ninterface PendingDurableLearningTransition extends DurableLearningReviewMetadata {\n\ttransitionId: string;\n\tcreatedAt: string;\n\tupdatedAt: string;\n\tclaim: DurableLearningClaim | null;\n}\n\ninterface ResolvedDurableLearningTransition extends DurableLearningReviewMetadata {\n\ttransitionId: string;\n\tcreatedAt: string;\n\tresolvedAt: string;\n\tstatus: \"reviewed\" | \"superseded\";\n}\n\ninterface DurableLearningStateFileV1 {\n\tschemaVersion: 1;\n\trevision: number;\n\tobservedRuntimeVersion: string;\n\tobservedMemoryPolicyVersion: string;\n\tcurrent: PendingDurableLearningTransition | null;\n\thistory: ResolvedDurableLearningTransition[];\n}\n\nexport interface DurableLearningStateSnapshot {\n\tschemaVersion: 1;\n\trevision: number;\n\tobservedRuntimeVersion: string;\n\tobservedMemoryPolicyVersion: string;\n\tcurrentTransitionId: string | null;\n\tcurrentClaimOwnerId: string | null;\n\tresolvedTransitions: number;\n}\n\ninterface DurableLearningStateOptions {\n\tnow?: () => Date;\n\trandomId?: () => string;\n\tleaseMs?: number;\n\twithLock?: <T>(filePath: string, fn: () => T) => T;\n\twriteState?: (filePath: string, contents: string) => void;\n}\n\ntype LoadResult =\n\t| { kind: \"missing\" }\n\t| { kind: \"ok\"; state: DurableLearningStateFileV1 }\n\t| { kind: \"corrupt\" }\n\t| { kind: \"unsupported\"; warningCode: DurableLearningStateWarningCode }\n\t| { kind: \"unavailable\" };\n\nconst TOP_LEVEL_KEYS = [\n\t\"schemaVersion\",\n\t\"revision\",\n\t\"observedRuntimeVersion\",\n\t\"observedMemoryPolicyVersion\",\n\t\"current\",\n\t\"history\",\n] as const;\nconst PENDING_KEYS = [\n\t\"transitionId\",\n\t\"reason\",\n\t\"previousRuntimeVersion\",\n\t\"runtimeVersion\",\n\t\"previousMemoryPolicyVersion\",\n\t\"memoryPolicyVersion\",\n\t\"createdAt\",\n\t\"updatedAt\",\n\t\"claim\",\n] as const;\nconst RESOLVED_KEYS = [\n\t\"transitionId\",\n\t\"reason\",\n\t\"previousRuntimeVersion\",\n\t\"runtimeVersion\",\n\t\"previousMemoryPolicyVersion\",\n\t\"memoryPolicyVersion\",\n\t\"createdAt\",\n\t\"resolvedAt\",\n\t\"status\",\n] as const;\nconst CLAIM_KEYS = [\"claimId\", \"ownerId\", \"acquiredAt\", \"expiresAt\"] as const;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n\treturn typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction hasUnknownKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {\n\tconst allowedKeys = new Set(allowed);\n\treturn Object.keys(value).some((key) => !allowedKeys.has(key));\n}\n\nfunction hasExactKeys(value: Record<string, unknown>, allowed: readonly string[]): boolean {\n\treturn Object.keys(value).length === allowed.length && !hasUnknownKeys(value, allowed);\n}\n\nfunction isVersion(value: unknown): value is string {\n\treturn (\n\t\ttypeof value === \"string\" &&\n\t\tvalue.length > 0 &&\n\t\tvalue.length <= MAX_VERSION_LENGTH &&\n\t\tvalue.trim() === value &&\n\t\tVERSION_RE.test(value)\n\t);\n}\n\nfunction isUuid(value: unknown): value is string {\n\treturn typeof value === \"string\" && UUID_RE.test(value);\n}\n\nfunction isTimestamp(value: unknown): value is string {\n\tif (typeof value !== \"string\" || value.length > 64) return false;\n\tconst parsed = new Date(value);\n\treturn Number.isFinite(parsed.getTime()) && parsed.toISOString() === value;\n}\n\nfunction isReason(value: unknown): value is DurableLearningTransitionReason {\n\treturn (\n\t\tvalue === \"first-observation\" ||\n\t\tvalue === \"runtime-change\" ||\n\t\tvalue === \"memory-policy-change\" ||\n\t\tvalue === \"runtime-and-policy-change\" ||\n\t\tvalue === \"recovered-corrupt-state\"\n\t);\n}\n\nfunction isNullableVersion(value: unknown): value is string | null {\n\treturn value === null || isVersion(value);\n}\n\nexport function isDurableLearningClaimToken(value: unknown): value is DurableLearningClaimToken {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\tObject.keys(value).length === 5 &&\n\t\tisUuid(value.transitionId) &&\n\t\tisUuid(value.claimId) &&\n\t\tisUuid(value.ownerId) &&\n\t\tisVersion(value.runtimeVersion) &&\n\t\tisVersion(value.memoryPolicyVersion)\n\t);\n}\n\nexport function isDurableLearningReviewMetadata(value: unknown): value is DurableLearningReviewMetadata {\n\tif (!isRecord(value)) return false;\n\treturn (\n\t\tObject.keys(value).length === 5 &&\n\t\tisReason(value.reason) &&\n\t\tisNullableVersion(value.previousRuntimeVersion) &&\n\t\tisVersion(value.runtimeVersion) &&\n\t\tisNullableVersion(value.previousMemoryPolicyVersion) &&\n\t\tisVersion(value.memoryPolicyVersion)\n\t);\n}\n\nfunction inspectUnknownKeys(value: Record<string, unknown>): boolean {\n\tif (hasUnknownKeys(value, TOP_LEVEL_KEYS)) return true;\n\tconst current = value.current;\n\tif (isRecord(current)) {\n\t\tif (hasUnknownKeys(current, PENDING_KEYS)) return true;\n\t\tif (isRecord(current.claim) && hasUnknownKeys(current.claim, CLAIM_KEYS)) return true;\n\t}\n\tif (Array.isArray(value.history)) {\n\t\tfor (const entry of value.history) {\n\t\t\tif (isRecord(entry) && hasUnknownKeys(entry, RESOLVED_KEYS)) return true;\n\t\t}\n\t}\n\treturn false;\n}\n\nfunction isClaim(value: unknown): value is DurableLearningClaim {\n\tif (!isRecord(value) || !hasExactKeys(value, CLAIM_KEYS)) return false;\n\treturn (\n\t\tisUuid(value.claimId) &&\n\t\tisUuid(value.ownerId) &&\n\t\tisTimestamp(value.acquiredAt) &&\n\t\tisTimestamp(value.expiresAt) &&\n\t\tvalue.expiresAt > value.acquiredAt\n\t);\n}\n\nfunction hasValidTransitionIdentity(value: Record<string, unknown>): boolean {\n\treturn (\n\t\tisUuid(value.transitionId) &&\n\t\tisReason(value.reason) &&\n\t\tisNullableVersion(value.previousRuntimeVersion) &&\n\t\tisVersion(value.runtimeVersion) &&\n\t\tisNullableVersion(value.previousMemoryPolicyVersion) &&\n\t\tisVersion(value.memoryPolicyVersion) &&\n\t\tisTimestamp(value.createdAt)\n\t);\n}\n\nfunction isPendingTransition(value: unknown): value is PendingDurableLearningTransition {\n\tif (!isRecord(value) || !hasExactKeys(value, PENDING_KEYS)) return false;\n\treturn (\n\t\thasValidTransitionIdentity(value) &&\n\t\tisTimestamp(value.updatedAt) &&\n\t\t(value.claim === null || isClaim(value.claim))\n\t);\n}\n\nfunction isResolvedTransition(value: unknown): value is ResolvedDurableLearningTransition {\n\tif (!isRecord(value) || !hasExactKeys(value, RESOLVED_KEYS)) return false;\n\treturn (\n\t\thasValidTransitionIdentity(value) &&\n\t\tisTimestamp(value.resolvedAt) &&\n\t\t(value.status === \"reviewed\" || value.status === \"superseded\")\n\t);\n}\n\nfunction validateState(value: unknown): LoadResult {\n\tif (!isRecord(value)) return { kind: \"corrupt\" };\n\tif (value.schemaVersion !== 1) return { kind: \"unsupported\", warningCode: \"unsupported-schema\" };\n\tif (inspectUnknownKeys(value)) return { kind: \"unsupported\", warningCode: \"unknown-keys\" };\n\tif (!hasExactKeys(value, TOP_LEVEL_KEYS)) return { kind: \"corrupt\" };\n\tif (!Number.isSafeInteger(value.revision) || (value.revision as number) < 1) return { kind: \"corrupt\" };\n\tif (!isVersion(value.observedRuntimeVersion) || !isVersion(value.observedMemoryPolicyVersion)) {\n\t\treturn { kind: \"corrupt\" };\n\t}\n\tif (value.current !== null && !isPendingTransition(value.current)) return { kind: \"corrupt\" };\n\tif (\n\t\t!Array.isArray(value.history) ||\n\t\tvalue.history.length > DURABLE_LEARNING_STATE_MAX_HISTORY ||\n\t\tvalue.history.some((entry) => !isResolvedTransition(entry))\n\t) {\n\t\treturn { kind: \"corrupt\" };\n\t}\n\tconst current = value.current as PendingDurableLearningTransition | null;\n\tif (\n\t\tcurrent &&\n\t\t(current.runtimeVersion !== value.observedRuntimeVersion ||\n\t\t\tcurrent.memoryPolicyVersion !== value.observedMemoryPolicyVersion)\n\t) {\n\t\treturn { kind: \"corrupt\" };\n\t}\n\tconst ids = [\n\t\tcurrent?.transitionId,\n\t\t...(value.history as ResolvedDurableLearningTransition[]).map((entry) => entry.transitionId),\n\t].filter((id): id is string => !!id);\n\tif (new Set(ids).size !== ids.length) return { kind: \"corrupt\" };\n\treturn { kind: \"ok\", state: value as unknown as DurableLearningStateFileV1 };\n}\n\nfunction exactTokenMatches(\n\tcurrent: PendingDurableLearningTransition | null,\n\ttoken: DurableLearningClaimToken,\n): boolean {\n\tconst claim = current?.claim;\n\treturn (\n\t\t!!current &&\n\t\t!!claim &&\n\t\tcurrent.transitionId === token.transitionId &&\n\t\tclaim.claimId === token.claimId &&\n\t\tclaim.ownerId === token.ownerId &&\n\t\tcurrent.runtimeVersion === token.runtimeVersion &&\n\t\tcurrent.memoryPolicyVersion === token.memoryPolicyVersion\n\t);\n}\n\nfunction metadataFromTransition(current: PendingDurableLearningTransition): DurableLearningReviewMetadata {\n\treturn {\n\t\treason: current.reason,\n\t\tpreviousRuntimeVersion: current.previousRuntimeVersion,\n\t\truntimeVersion: current.runtimeVersion,\n\t\tpreviousMemoryPolicyVersion: current.previousMemoryPolicyVersion,\n\t\tmemoryPolicyVersion: current.memoryPolicyVersion,\n\t};\n}\n\nfunction tokenFromTransition(current: PendingDurableLearningTransition): DurableLearningClaimToken {\n\tif (!current.claim) throw new Error(\"Durable learning transition has no claim\");\n\treturn {\n\t\ttransitionId: current.transitionId,\n\t\tclaimId: current.claim.claimId,\n\t\townerId: current.claim.ownerId,\n\t\truntimeVersion: current.runtimeVersion,\n\t\tmemoryPolicyVersion: current.memoryPolicyVersion,\n\t};\n}\n\nexport class DurableLearningState {\n\tprivate readonly filePath: string;\n\tprivate readonly now: () => Date;\n\tprivate readonly randomId: () => string;\n\tprivate readonly leaseMs: number;\n\tprivate readonly withLock: <T>(filePath: string, fn: () => T) => T;\n\tprivate readonly writeState: (filePath: string, contents: string) => void;\n\n\tconstructor(filePath: string, options: DurableLearningStateOptions = {}) {\n\t\tthis.filePath = filePath;\n\t\tthis.now = options.now ?? (() => new Date());\n\t\tthis.randomId = options.randomId ?? randomUUID;\n\t\tthis.leaseMs = options.leaseMs ?? DURABLE_LEARNING_CLAIM_LEASE_MS;\n\t\tthis.withLock = options.withLock ?? ((path, fn) => withFileLockSync(path, fn));\n\t\tthis.writeState =\n\t\t\toptions.writeState ?? ((path, contents) => writeFileAtomicSync(path, contents, { mode: 0o600 }));\n\t\tif (!Number.isSafeInteger(this.leaseMs) || this.leaseMs <= 0) {\n\t\t\tthrow new TypeError(\"Durable learning claim lease must be a positive safe integer\");\n\t\t}\n\t}\n\n\tstatic forAgentDir(agentDir: string, options: DurableLearningStateOptions = {}): DurableLearningState {\n\t\treturn new DurableLearningState(stateFile(agentDir, STATE_FILE_NAME), options);\n\t}\n\n\tprivate currentDate(): Date {\n\t\tconst current = this.now();\n\t\tif (!(current instanceof Date) || !Number.isFinite(current.getTime())) {\n\t\t\tthrow new Error(\"Durable learning clock returned an invalid date\");\n\t\t}\n\t\treturn current;\n\t}\n\n\tprivate nextId(): string {\n\t\tconst id = this.randomId();\n\t\tif (!isUuid(id)) throw new Error(\"Durable learning random ID source returned an invalid UUID\");\n\t\treturn id;\n\t}\n\n\tprivate load(): LoadResult {\n\t\ttry {\n\t\t\tif (!existsSync(this.filePath)) return { kind: \"missing\" };\n\t\t\tif (statSync(this.filePath).size > DURABLE_LEARNING_STATE_MAX_BYTES) {\n\t\t\t\treturn { kind: \"unsupported\", warningCode: \"oversize-state\" };\n\t\t\t}\n\t\t\tconst contents = readFileSync(this.filePath, \"utf-8\");\n\t\t\tif (Buffer.byteLength(contents, \"utf-8\") > DURABLE_LEARNING_STATE_MAX_BYTES) {\n\t\t\t\treturn { kind: \"unsupported\", warningCode: \"oversize-state\" };\n\t\t\t}\n\t\t\ttry {\n\t\t\t\treturn validateState(JSON.parse(contents));\n\t\t\t} catch {\n\t\t\t\treturn { kind: \"corrupt\" };\n\t\t\t}\n\t\t} catch {\n\t\t\treturn { kind: \"unavailable\" };\n\t\t}\n\t}\n\n\tprivate save(state: DurableLearningStateFileV1): void {\n\t\tif (state.history.length > DURABLE_LEARNING_STATE_MAX_HISTORY) {\n\t\t\tstate.history = state.history.slice(-DURABLE_LEARNING_STATE_MAX_HISTORY);\n\t\t}\n\t\tconst contents = `${JSON.stringify(state, null, \"\\t\")}\\n`;\n\t\tif (Buffer.byteLength(contents, \"utf-8\") > DURABLE_LEARNING_STATE_MAX_BYTES) {\n\t\t\tthrow new Error(\"Durable learning state exceeds its byte bound\");\n\t\t}\n\t\tthis.writeState(this.filePath, contents);\n\t}\n\n\tprivate newClaim(ownerId: string, now: Date): DurableLearningClaim {\n\t\treturn {\n\t\t\tclaimId: this.nextId(),\n\t\t\townerId,\n\t\t\tacquiredAt: now.toISOString(),\n\t\t\texpiresAt: new Date(now.getTime() + this.leaseMs).toISOString(),\n\t\t};\n\t}\n\n\tprivate newTransition(\n\t\tversions: DurableLearningVersions,\n\t\treason: DurableLearningTransitionReason,\n\t\tpreviousRuntimeVersion: string | null,\n\t\tpreviousMemoryPolicyVersion: string | null,\n\t\townerId: string,\n\t\tnow: Date,\n\t): PendingDurableLearningTransition {\n\t\tconst at = now.toISOString();\n\t\treturn {\n\t\t\ttransitionId: this.nextId(),\n\t\t\treason,\n\t\t\tpreviousRuntimeVersion,\n\t\t\truntimeVersion: versions.runtimeVersion,\n\t\t\tpreviousMemoryPolicyVersion,\n\t\t\tmemoryPolicyVersion: versions.memoryPolicyVersion,\n\t\t\tcreatedAt: at,\n\t\t\tupdatedAt: at,\n\t\t\tclaim: this.newClaim(ownerId, now),\n\t\t};\n\t}\n\n\tprivate resolveCurrent(\n\t\tstate: DurableLearningStateFileV1,\n\t\tstatus: ResolvedDurableLearningTransition[\"status\"],\n\t\tnow: Date,\n\t): void {\n\t\tconst current = state.current;\n\t\tif (!current) return;\n\t\tstate.history.push({\n\t\t\ttransitionId: current.transitionId,\n\t\t\treason: current.reason,\n\t\t\tpreviousRuntimeVersion: current.previousRuntimeVersion,\n\t\t\truntimeVersion: current.runtimeVersion,\n\t\t\tpreviousMemoryPolicyVersion: current.previousMemoryPolicyVersion,\n\t\t\tmemoryPolicyVersion: current.memoryPolicyVersion,\n\t\t\tcreatedAt: current.createdAt,\n\t\t\tresolvedAt: now.toISOString(),\n\t\t\tstatus,\n\t\t});\n\t\tif (state.history.length > DURABLE_LEARNING_STATE_MAX_HISTORY) {\n\t\t\tstate.history = state.history.slice(-DURABLE_LEARNING_STATE_MAX_HISTORY);\n\t\t}\n\t\tstate.current = null;\n\t}\n\n\tprivate initialState(\n\t\tversions: DurableLearningVersions,\n\t\townerId: string,\n\t\tnow: Date,\n\t\treason: \"first-observation\" | \"recovered-corrupt-state\",\n\t): DurableLearningStateFileV1 {\n\t\treturn {\n\t\t\tschemaVersion: 1,\n\t\t\trevision: 1,\n\t\t\tobservedRuntimeVersion: versions.runtimeVersion,\n\t\t\tobservedMemoryPolicyVersion: versions.memoryPolicyVersion,\n\t\t\tcurrent: this.newTransition(versions, reason, null, null, ownerId, now),\n\t\t\thistory: [],\n\t\t};\n\t}\n\n\tprivate changedReason(\n\t\tstate: DurableLearningStateFileV1,\n\t\tversions: DurableLearningVersions,\n\t): DurableLearningTransitionReason | undefined {\n\t\tconst runtimeChanged = state.observedRuntimeVersion !== versions.runtimeVersion;\n\t\tconst policyChanged = state.observedMemoryPolicyVersion !== versions.memoryPolicyVersion;\n\t\tif (runtimeChanged && policyChanged) return \"runtime-and-policy-change\";\n\t\tif (runtimeChanged) return \"runtime-change\";\n\t\tif (policyChanged) return \"memory-policy-change\";\n\t\treturn undefined;\n\t}\n\n\treconcileClaimAndAttach(\n\t\tversions: DurableLearningVersions,\n\t\townerId: string,\n\t\tattachCue: (\n\t\t\ttoken: DurableLearningClaimToken,\n\t\t\tmetadata: DurableLearningReviewMetadata,\n\t\t) => DurableLearningCueAttachOutcome,\n\t): DurableLearningReconcileResult {\n\t\tif (!isVersion(versions.runtimeVersion) || !isVersion(versions.memoryPolicyVersion)) {\n\t\t\treturn { status: \"invalid-version\" };\n\t\t}\n\t\tif (!isUuid(ownerId)) return { status: \"invalid-owner\" };\n\t\tconst preflight = this.load();\n\t\tif (preflight.kind === \"unsupported\") return { status: \"unsupported\", warningCode: preflight.warningCode };\n\t\tif (preflight.kind === \"unavailable\") return { status: \"unavailable\", warningCode: \"state-unavailable\" };\n\n\t\ttry {\n\t\t\treturn this.withLock(this.filePath, () => {\n\t\t\t\tconst loaded = this.load();\n\t\t\t\tif (loaded.kind === \"unsupported\") {\n\t\t\t\t\treturn { status: \"unsupported\", warningCode: loaded.warningCode };\n\t\t\t\t}\n\t\t\t\tif (loaded.kind === \"unavailable\") {\n\t\t\t\t\treturn { status: \"unavailable\", warningCode: \"state-unavailable\" };\n\t\t\t\t}\n\t\t\t\tconst now = this.currentDate();\n\t\t\t\tlet warningCode: DurableLearningStateWarningCode | undefined;\n\t\t\t\tlet state: DurableLearningStateFileV1;\n\t\t\t\tif (loaded.kind === \"missing\") {\n\t\t\t\t\tstate = this.initialState(versions, ownerId, now, \"first-observation\");\n\t\t\t\t} else if (loaded.kind === \"corrupt\") {\n\t\t\t\t\tstate = this.initialState(versions, ownerId, now, \"recovered-corrupt-state\");\n\t\t\t\t\twarningCode = \"recovered-corrupt-state\";\n\t\t\t\t} else {\n\t\t\t\t\tstate = loaded.state;\n\t\t\t\t\tconst reason = this.changedReason(state, versions);\n\t\t\t\t\tif (reason) {\n\t\t\t\t\t\tconst previousRuntimeVersion = state.observedRuntimeVersion;\n\t\t\t\t\t\tconst previousMemoryPolicyVersion = state.observedMemoryPolicyVersion;\n\t\t\t\t\t\tthis.resolveCurrent(state, \"superseded\", now);\n\t\t\t\t\t\tstate.observedRuntimeVersion = versions.runtimeVersion;\n\t\t\t\t\t\tstate.observedMemoryPolicyVersion = versions.memoryPolicyVersion;\n\t\t\t\t\t\tstate.current = this.newTransition(\n\t\t\t\t\t\t\tversions,\n\t\t\t\t\t\t\treason,\n\t\t\t\t\t\t\tpreviousRuntimeVersion,\n\t\t\t\t\t\t\tpreviousMemoryPolicyVersion,\n\t\t\t\t\t\t\townerId,\n\t\t\t\t\t\t\tnow,\n\t\t\t\t\t\t);\n\t\t\t\t\t\tstate.revision += 1;\n\t\t\t\t\t} else if (!state.current) {\n\t\t\t\t\t\treturn { status: \"unchanged\" };\n\t\t\t\t\t} else {\n\t\t\t\t\t\tconst claim = state.current.claim;\n\t\t\t\t\t\tconst live = !!claim && new Date(claim.expiresAt).getTime() > now.getTime();\n\t\t\t\t\t\tif (live && claim.ownerId !== ownerId) return { status: \"busy\" };\n\t\t\t\t\t\tif (live) {\n\t\t\t\t\t\t\tclaim.expiresAt = new Date(now.getTime() + this.leaseMs).toISOString();\n\t\t\t\t\t\t\tstate.current.updatedAt = now.toISOString();\n\t\t\t\t\t\t\tstate.revision += 1;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tstate.current.claim = this.newClaim(ownerId, now);\n\t\t\t\t\t\t\tstate.current.updatedAt = now.toISOString();\n\t\t\t\t\t\t\tstate.revision += 1;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tconst current = state.current;\n\t\t\t\tif (!current?.claim) throw new Error(\"Durable learning reconciliation produced no claim\");\n\t\t\t\tthis.save(state);\n\t\t\t\tconst token = tokenFromTransition(current);\n\t\t\t\tlet outcome: DurableLearningCueAttachOutcome;\n\t\t\t\ttry {\n\t\t\t\t\toutcome = attachCue(token, metadataFromTransition(current));\n\t\t\t\t} catch {\n\t\t\t\t\toutcome = \"failed\";\n\t\t\t\t}\n\t\t\t\tif (outcome === \"disabled\" || outcome === \"failed\") {\n\t\t\t\t\tconst settlingCurrent = state.current;\n\t\t\t\t\tif (settlingCurrent && exactTokenMatches(settlingCurrent, token)) {\n\t\t\t\t\t\tsettlingCurrent.claim = null;\n\t\t\t\t\t\tsettlingCurrent.updatedAt = this.currentDate().toISOString();\n\t\t\t\t\t\tstate.revision += 1;\n\t\t\t\t\t\tthis.save(state);\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn warningCode ? { status: outcome, warningCode } : { status: outcome };\n\t\t\t});\n\t\t} catch {\n\t\t\treturn { status: \"unavailable\", warningCode: \"state-unavailable\" };\n\t\t}\n\t}\n\n\tprivate mutateExactClaim(\n\t\ttoken: DurableLearningClaimToken,\n\t\tmutate: (state: DurableLearningStateFileV1, current: PendingDurableLearningTransition) => boolean,\n\t): boolean {\n\t\tif (!this.validToken(token)) return false;\n\t\tconst preflight = this.load();\n\t\tif (preflight.kind !== \"ok\") return false;\n\t\ttry {\n\t\t\treturn this.withLock(this.filePath, () => {\n\t\t\t\tconst loaded = this.load();\n\t\t\t\tif (loaded.kind !== \"ok\") return false;\n\t\t\t\tconst current = loaded.state.current;\n\t\t\t\tif (!current || !exactTokenMatches(current, token) || !mutate(loaded.state, current)) return false;\n\t\t\t\tloaded.state.revision += 1;\n\t\t\t\tthis.save(loaded.state);\n\t\t\t\treturn true;\n\t\t\t});\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\trenewClaim(token: DurableLearningClaimToken): boolean {\n\t\treturn this.mutateExactClaim(token, (_state, current) => {\n\t\t\tconst now = this.currentDate();\n\t\t\tif (!current.claim || new Date(current.claim.expiresAt).getTime() <= now.getTime()) return false;\n\t\t\tcurrent.claim.expiresAt = new Date(now.getTime() + this.leaseMs).toISOString();\n\t\t\tcurrent.updatedAt = now.toISOString();\n\t\t\treturn true;\n\t\t});\n\t}\n\n\treleaseClaim(token: DurableLearningClaimToken): boolean {\n\t\treturn this.mutateExactClaim(token, (_state, current) => {\n\t\t\tcurrent.claim = null;\n\t\t\tcurrent.updatedAt = this.currentDate().toISOString();\n\t\t\treturn true;\n\t\t});\n\t}\n\n\tcompleteReview(token: DurableLearningClaimToken): boolean {\n\t\treturn this.mutateExactClaim(token, (state) => {\n\t\t\tthis.resolveCurrent(state, \"reviewed\", this.currentDate());\n\t\t\treturn true;\n\t\t});\n\t}\n\n\treadSnapshot(): DurableLearningStateSnapshot | undefined {\n\t\tconst loaded = this.load();\n\t\tif (loaded.kind !== \"ok\") return undefined;\n\t\treturn {\n\t\t\tschemaVersion: 1,\n\t\t\trevision: loaded.state.revision,\n\t\t\tobservedRuntimeVersion: loaded.state.observedRuntimeVersion,\n\t\t\tobservedMemoryPolicyVersion: loaded.state.observedMemoryPolicyVersion,\n\t\t\tcurrentTransitionId: loaded.state.current?.transitionId ?? null,\n\t\t\tcurrentClaimOwnerId: loaded.state.current?.claim?.ownerId ?? null,\n\t\t\tresolvedTransitions: loaded.state.history.length,\n\t\t};\n\t}\n\n\tprivate validToken(token: DurableLearningClaimToken): boolean {\n\t\treturn isDurableLearningClaimToken(token);\n\t}\n}\n"]}
|