@myagentroam/agent 0.10.11 → 0.10.12
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.
|
@@ -1002,15 +1002,15 @@ export class JsonlSessionStore {
|
|
|
1002
1002
|
}
|
|
1003
1003
|
async #appendRecord(sessionId, input) {
|
|
1004
1004
|
this.#assertOpen();
|
|
1005
|
-
const
|
|
1005
|
+
const before = this.#shared.index.sessions.find((item) => item.id === sessionId) ??
|
|
1006
1006
|
this.#shared.pendingSessions.get(sessionId);
|
|
1007
|
-
if (!
|
|
1007
|
+
if (!before)
|
|
1008
1008
|
throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
|
|
1009
1009
|
const published = !this.#shared.pendingSessions.has(sessionId);
|
|
1010
1010
|
const record = {
|
|
1011
1011
|
schemaVersion: 1,
|
|
1012
1012
|
recordId: randomUUID(),
|
|
1013
|
-
sequence:
|
|
1013
|
+
sequence: before.nextSequence,
|
|
1014
1014
|
timestamp: input.timestamp ?? new Date().toISOString(),
|
|
1015
1015
|
sessionId,
|
|
1016
1016
|
...(input.executionId ? { executionId: input.executionId } : {}),
|
|
@@ -1019,7 +1019,7 @@ export class JsonlSessionStore {
|
|
|
1019
1019
|
payload: input.payload
|
|
1020
1020
|
};
|
|
1021
1021
|
JSON.stringify(record); // Reject malformed payloads before binding resources.
|
|
1022
|
-
await bindToolResultResources(this.sessionDirectory(sessionId), record, (sequence) => this.#readRecordAtSequence(
|
|
1022
|
+
await bindToolResultResources(this.sessionDirectory(sessionId), record, (sequence) => this.#readRecordAtSequence(before, sequence), true);
|
|
1023
1023
|
const serialized = `${JSON.stringify(record)}\n`;
|
|
1024
1024
|
let segment = await this.#currentSegment(sessionId);
|
|
1025
1025
|
let path = this.#segmentPath(sessionId, segment);
|
|
@@ -1049,16 +1049,13 @@ export class JsonlSessionStore {
|
|
|
1049
1049
|
finally {
|
|
1050
1050
|
await handle.close();
|
|
1051
1051
|
}
|
|
1052
|
-
|
|
1053
|
-
await
|
|
1054
|
-
|
|
1055
|
-
|
|
1056
|
-
|
|
1057
|
-
|
|
1058
|
-
|
|
1059
|
-
typeof image.fileName === 'string' &&
|
|
1060
|
-
validInputImageFileName(image.fileName))
|
|
1061
|
-
await rm(join(this.sessionDirectory(sessionId), 'input_images', `.${image.fileName}.pending`), { force: true }).catch(() => undefined);
|
|
1052
|
+
// Index refreshes and commits can replace metadata during file I/O. Publish all
|
|
1053
|
+
// durable-record metadata onto the current entry without another await boundary.
|
|
1054
|
+
const meta = this.#shared.index.sessions.find((item) => item.id === sessionId) ??
|
|
1055
|
+
this.#shared.pendingSessions.get(sessionId);
|
|
1056
|
+
if (!meta)
|
|
1057
|
+
throw new MarAgentError('MAR_AGENT_SESSION_NOT_FOUND', 'Session was not found.');
|
|
1058
|
+
meta.nextSequence = record.sequence + 1;
|
|
1062
1059
|
const segmentMetadata = meta.segments ?? (meta.segments = []);
|
|
1063
1060
|
const known = segmentMetadata.find((item) => item.number === segment);
|
|
1064
1061
|
if (known) {
|
|
@@ -1078,6 +1075,15 @@ export class JsonlSessionStore {
|
|
|
1078
1075
|
this.#shared.index.revision++;
|
|
1079
1076
|
this.#markIndexDirty(sessionId);
|
|
1080
1077
|
}
|
|
1078
|
+
await completeToolResultResources(this.sessionDirectory(sessionId), record);
|
|
1079
|
+
if (record.type === 'turn.user' &&
|
|
1080
|
+
isObject(record.payload) &&
|
|
1081
|
+
Array.isArray(record.payload.images))
|
|
1082
|
+
for (const image of record.payload.images)
|
|
1083
|
+
if (isObject(image) &&
|
|
1084
|
+
typeof image.fileName === 'string' &&
|
|
1085
|
+
validInputImageFileName(image.fileName))
|
|
1086
|
+
await rm(join(this.sessionDirectory(sessionId), 'input_images', `.${image.fileName}.pending`), { force: true }).catch(() => undefined);
|
|
1081
1087
|
return record;
|
|
1082
1088
|
}
|
|
1083
1089
|
async read(sessionId) {
|
|
@@ -1815,7 +1821,6 @@ export class JsonlSessionStore {
|
|
|
1815
1821
|
}
|
|
1816
1822
|
/** Repair the last segment and pending images under the lease, then sync sequence metadata. */
|
|
1817
1823
|
async #reconcileTail(sessionId) {
|
|
1818
|
-
const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
|
|
1819
1824
|
const paths = await this.#segmentPaths(sessionId);
|
|
1820
1825
|
const latestPath = paths.at(-1);
|
|
1821
1826
|
await repairSegmentTail(latestPath);
|
|
@@ -1830,6 +1835,8 @@ export class JsonlSessionStore {
|
|
|
1830
1835
|
throw new MarAgentError('MAR_AGENT_SESSION_CORRUPT', 'Session history is corrupt.');
|
|
1831
1836
|
const bytes = (await stat(latestPath)).size;
|
|
1832
1837
|
const firstSequence = records[0].sequence;
|
|
1838
|
+
// Tail recovery must publish onto metadata that is current after all file I/O.
|
|
1839
|
+
const meta = this.#shared.index.sessions.find((item) => item.id === sessionId);
|
|
1833
1840
|
const known = meta.segments?.find((item) => item.number === segment);
|
|
1834
1841
|
const titleRecord = records.findLast((record) => record.type === 'session.title.updated' &&
|
|
1835
1842
|
typeof record.payload.title === 'string');
|