@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 meta = this.#shared.index.sessions.find((item) => item.id === sessionId) ??
1005
+ const before = this.#shared.index.sessions.find((item) => item.id === sessionId) ??
1006
1006
  this.#shared.pendingSessions.get(sessionId);
1007
- if (!meta)
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: meta.nextSequence,
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(meta, sequence), true);
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
- meta.nextSequence++;
1053
- await completeToolResultResources(this.sessionDirectory(sessionId), record);
1054
- if (record.type === 'turn.user' &&
1055
- isObject(record.payload) &&
1056
- Array.isArray(record.payload.images))
1057
- for (const image of record.payload.images)
1058
- if (isObject(image) &&
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');
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@myagentroam/agent",
3
- "version": "0.10.11",
3
+ "version": "0.10.12",
4
4
  "description": "Embeddable MAR coding agent SDK and CLI.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",