@genesislcap/ai-assistant 15.33.0 → 15.33.1

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.
@@ -63,8 +63,10 @@ export interface DiagnosticEntry {
63
63
  * across page loads. Two lanes with different offset bases plus the input length make an
64
64
  * accidental collision between two real configs vanishingly unlikely — and the consequence of one
65
65
  * would be a single *skipped* re-append of a block whose reader keeps only the newest copy anyway
66
- * (`withFreshMetaSnapshot` discards every stored snapshot on the download path), so this is not a
67
- * correctness-critical hash and must not be treated as one.
66
+ * (`withFreshMetaSnapshot` discards every stored snapshot on the download path), so for snapshots
67
+ * this is not a correctness-critical hash. `diagnosticsMessageKey` also uses it as the identity of
68
+ * a message with no timestamp, where a collision would skip a different message: keep both lanes
69
+ * and the length.
68
70
  *
69
71
  * Old streams need no migration: the delta's cursor is module state seeded empty on every page
70
72
  * load, so a stored full-JSON signature is never compared against a digest. The first flush after
@@ -104,7 +106,7 @@ export interface DebugLog {
104
106
  * Stable identity for a message diagnostic entry — `timestamp::role::subAgentOf::category`.
105
107
  * Used by the forward-capture delta (skip already-emitted messages) and by the
106
108
  * restore watermark (skip messages already present in a prior load's stream).
107
- * `null` when the entry has no timestamp treat as always-new. Shared so the
109
+ * A message with no timestamp is keyed differently (below). Shared so the
108
110
  * element's diagnostics capture and the `SessionPersister`'s restore watermark
109
111
  * compute identity identically (GENC-1351 §5.8/§5.10).
110
112
  *
@@ -116,9 +118,18 @@ export interface DebugLog {
116
118
  * (GENC-1461). `category` is stable across a message's in-place annotation (only `toolCalls` change,
117
119
  * which is deliberately excluded), so a genuine re-append of the same message still dedups.
118
120
  *
121
+ * A message with no timestamp keys on a digest of the whole entry (GENC-1627). Barring a digest
122
+ * collision, only a byte-identical copy shares that key, and `assembleDebugLog` collapses those
123
+ * anyway, so skipping one loses nothing the assembled log shows. A message that changes gets a new
124
+ * key and is written again. Without a key, such a message was written on every flush and the
125
+ * restore watermark did not cover it. These are messages that never went through
126
+ * `appendToHistory`'s stamp: history a host saved without timestamps (e.g. the note and usage stubs
127
+ * Genesis Create saves in place of a sub-agent trace, whose own messages are already in the stream)
128
+ * and external diagnostics that carry none.
129
+ *
119
130
  * @internal
120
131
  */
121
- export declare function diagnosticsMessageKey(entry: DiagnosticEntry): string | null;
132
+ export declare function diagnosticsMessageKey(entry: DiagnosticEntry): string;
122
133
  /**
123
134
  * Reassemble diagnostic entries into the `{ readme, sessionUsage, timeline, meta }`
124
135
  * debug-log shape (GENC-1351 §5.8). `timeline` = the `message`/`turn`/`event` entries sorted
@@ -1 +1 @@
1
- {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../../src/state/persistence/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,eAAe,CAAC;IACrD,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4BG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAajD;AAED,mFAAmF;AACnF,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,GAAG,IAAI,CAI3E;AA+BD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,CA+ChG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,eAAe,EAAE,EAClC,KAAK,EAAE,eAAe,GACrB,eAAe,EAAE,CAEnB"}
1
+ {"version":3,"file":"diagnostics.d.ts","sourceRoot":"","sources":["../../../../src/state/persistence/diagnostics.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,4BAA4B,CAAC;AAEjE;;;;;;;;;GASG;AACH,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,GAAG,MAAM,GAAG,OAAO,GAAG,eAAe,CAAC;IACrD,kFAAkF;IAClF,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,wEAAwE;IACxE,IAAI,CAAC,EAAE,OAAO,CAAC;IACf;;;;;;;;OAQG;IACH,KAAK,CAAC,EAAE,cAAc,CAAC;IACvB;;;;;OAKG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAWD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAajD;AAED,mFAAmF;AACnF,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;IAC1B;;;;;;;;;;;;;;;;;;;OAmBG;IACH,YAAY,CAAC,EAAE,cAAc,CAAC;IAC9B,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,eAAe,GAAG,MAAM,CAcpE;AAgDD;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,eAAe,EAAE,EAAE,MAAM,EAAE,SAAS,MAAM,EAAE,GAAG,QAAQ,CA+ChG;AAED;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,SAAS,eAAe,EAAE,EAClC,KAAK,EAAE,eAAe,GACrB,eAAe,EAAE,CAEnB"}
@@ -248,8 +248,8 @@ export declare class SessionPersister {
248
248
  scheduleDiagnostics(): void;
249
249
  /**
250
250
  * Append the diagnostic entries created since the last flush to the provider's
251
- * forward-only stream. Best-effort — a failed write is logged and never touches
252
- * the chat. (The cursors advance on collect, so a dropped batch isn't retried;
251
+ * forward-only stream. Best-effort — a failed collect or write is logged and never
252
+ * touches the chat. (The cursors advance on collect, so a dropped batch isn't retried;
253
253
  * acceptable for a forensic stream that isn't the source of truth.) Also called
254
254
  * directly by the download path to land the current delta before reassembly.
255
255
  */
@@ -1 +1 @@
1
- {"version":3,"file":"session-persister.d.ts","sourceRoot":"","sources":["../../../../src/state/persistence/session-persister.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"session-persister.d.ts","sourceRoot":"","sources":["../../../../src/state/persistence/session-persister.ts"],"names":[],"mappings":"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"}
@@ -33,8 +33,10 @@ const DIGEST_RADIX = 36;
33
33
  * across page loads. Two lanes with different offset bases plus the input length make an
34
34
  * accidental collision between two real configs vanishingly unlikely — and the consequence of one
35
35
  * would be a single *skipped* re-append of a block whose reader keeps only the newest copy anyway
36
- * (`withFreshMetaSnapshot` discards every stored snapshot on the download path), so this is not a
37
- * correctness-critical hash and must not be treated as one.
36
+ * (`withFreshMetaSnapshot` discards every stored snapshot on the download path), so for snapshots
37
+ * this is not a correctness-critical hash. `diagnosticsMessageKey` also uses it as the identity of
38
+ * a message with no timestamp, where a collision would skip a different message: keep both lanes
39
+ * and the length.
38
40
  *
39
41
  * Old streams need no migration: the delta's cursor is module state seeded empty on every page
40
42
  * load, so a stored full-JSON signature is never compared against a digest. The first flush after
@@ -60,7 +62,7 @@ export function configDigest(json) {
60
62
  * Stable identity for a message diagnostic entry — `timestamp::role::subAgentOf::category`.
61
63
  * Used by the forward-capture delta (skip already-emitted messages) and by the
62
64
  * restore watermark (skip messages already present in a prior load's stream).
63
- * `null` when the entry has no timestamp treat as always-new. Shared so the
65
+ * A message with no timestamp is keyed differently (below). Shared so the
64
66
  * element's diagnostics capture and the `SessionPersister`'s restore watermark
65
67
  * compute identity identically (GENC-1351 §5.8/§5.10).
66
68
  *
@@ -72,13 +74,54 @@ export function configDigest(json) {
72
74
  * (GENC-1461). `category` is stable across a message's in-place annotation (only `toolCalls` change,
73
75
  * which is deliberately excluded), so a genuine re-append of the same message still dedups.
74
76
  *
77
+ * A message with no timestamp keys on a digest of the whole entry (GENC-1627). Barring a digest
78
+ * collision, only a byte-identical copy shares that key, and `assembleDebugLog` collapses those
79
+ * anyway, so skipping one loses nothing the assembled log shows. A message that changes gets a new
80
+ * key and is written again. Without a key, such a message was written on every flush and the
81
+ * restore watermark did not cover it. These are messages that never went through
82
+ * `appendToHistory`'s stamp: history a host saved without timestamps (e.g. the note and usage stubs
83
+ * Genesis Create saves in place of a sub-agent trace, whose own messages are already in the stream)
84
+ * and external diagnostics that carry none.
85
+ *
75
86
  * @internal
76
87
  */
77
88
  export function diagnosticsMessageKey(entry) {
78
89
  var _a, _b, _c;
79
- return typeof entry.timestamp === 'string'
80
- ? `${entry.timestamp}::${(_a = entry.role) !== null && _a !== void 0 ? _a : ''}::${(_b = entry.subAgentOf) !== null && _b !== void 0 ? _b : ''}::${(_c = entry.category) !== null && _c !== void 0 ? _c : ''}`
81
- : null;
90
+ if (typeof entry.timestamp === 'string') {
91
+ return `${entry.timestamp}::${(_a = entry.role) !== null && _a !== void 0 ? _a : ''}::${(_b = entry.subAgentOf) !== null && _b !== void 0 ? _b : ''}::${(_c = entry.category) !== null && _c !== void 0 ? _c : ''}`;
92
+ }
93
+ try {
94
+ return `noTs::${configDigest(JSON.stringify(entry))}`;
95
+ }
96
+ catch (_d) {
97
+ try {
98
+ return `noTs::${configDigest(stringifyLeniently(entry))}`;
99
+ }
100
+ catch (_e) {
101
+ // A getter or `toJSON` that throws, which no replacer gets past: share one key, don't throw.
102
+ return 'noTs::unserializable';
103
+ }
104
+ }
105
+ }
106
+ /**
107
+ * `JSON.stringify` that writes a cycle as `'[Circular]'` and a BigInt as its digits, the way
108
+ * Genesis Create's store sanitises a payload, so such entries still get keys of their own.
109
+ */
110
+ function stringifyLeniently(value) {
111
+ // The chain of parents, not every object seen: the same object twice as siblings is not a cycle.
112
+ const ancestors = [];
113
+ return JSON.stringify(value, function (_key, val) {
114
+ while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this)
115
+ ancestors.pop();
116
+ if (typeof val === 'bigint')
117
+ return val.toString();
118
+ if (val === null || typeof val !== 'object')
119
+ return val;
120
+ if (ancestors.includes(val))
121
+ return '[Circular]';
122
+ ancestors.push(val);
123
+ return val;
124
+ });
82
125
  }
83
126
  /**
84
127
  * Identity of a `turn` entry — `turnIndex::timestamp::agentName`.
@@ -530,9 +530,7 @@ export class SessionPersister {
530
530
  // per-session cursors so this load's forward capture never re-appends them
531
531
  // (only genuinely new activity streams). Shared, so the element view that
532
532
  // never runs restore honours the same watermark.
533
- getDiagnosticsCursors(key).restoredMsgKeys = new Set(flattenSubAgentMessages(trimmed)
534
- .map((e) => diagnosticsMessageKey(e))
535
- .filter((k) => k !== null));
533
+ getDiagnosticsCursors(key).restoredMsgKeys = new Set(flattenSubAgentMessages(trimmed).map((e) => diagnosticsMessageKey(e)));
536
534
  // Prime each stateful agent's persisted machine/state image FIRST — before
537
535
  // seeding Redux or driver history — so the image is waiting on the driver no
538
536
  // matter when the agent re-activates. The flow-owner lock self-heals on
@@ -761,8 +759,8 @@ export class SessionPersister {
761
759
  }
762
760
  /**
763
761
  * Append the diagnostic entries created since the last flush to the provider's
764
- * forward-only stream. Best-effort — a failed write is logged and never touches
765
- * the chat. (The cursors advance on collect, so a dropped batch isn't retried;
762
+ * forward-only stream. Best-effort — a failed collect or write is logged and never
763
+ * touches the chat. (The cursors advance on collect, so a dropped batch isn't retried;
766
764
  * acceptable for a forensic stream that isn't the source of truth.) Also called
767
765
  * directly by the download path to land the current delta before reassembly.
768
766
  */
@@ -771,14 +769,14 @@ export class SessionPersister {
771
769
  const { provider } = this.deps.getPersistence();
772
770
  if (!(provider === null || provider === void 0 ? void 0 : provider.appendDiagnostics))
773
771
  return;
774
- const delta = this.collectDiagnosticsDelta();
775
- if (!delta.length)
776
- return;
777
772
  try {
773
+ const delta = this.collectDiagnosticsDelta();
774
+ if (!delta.length)
775
+ return;
778
776
  yield provider.appendDiagnostics(this.stateKey, delta);
779
777
  }
780
778
  catch (e) {
781
- logger.error('Diagnostics append failed:', e);
779
+ logger.error('Diagnostics flush failed:', e);
782
780
  }
783
781
  });
784
782
  }
@@ -808,11 +806,9 @@ export class SessionPersister {
808
806
  for (const entry of this.deps.getDiagnosticEntries()) {
809
807
  if (entry.kind === 'message') {
810
808
  const key = diagnosticsMessageKey(entry);
811
- if (key !== null) {
812
- if (cursors.restoredMsgKeys.has(key) || cursors.emittedMsgKeys.has(key))
813
- continue;
814
- cursors.emittedMsgKeys.add(key);
815
- }
809
+ if (cursors.restoredMsgKeys.has(key) || cursors.emittedMsgKeys.has(key))
810
+ continue;
811
+ cursors.emittedMsgKeys.add(key);
816
812
  delta.push(entry);
817
813
  }
818
814
  else if (entry.kind === 'turn') {
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@genesislcap/ai-assistant",
3
3
  "description": "Genesis AI Assistant micro-frontend",
4
- "version": "15.33.0",
4
+ "version": "15.33.1",
5
5
  "license": "SEE LICENSE IN license.txt",
6
6
  "main": "dist/esm/index.js",
7
7
  "types": "dist/ai-assistant.d.ts",
@@ -74,26 +74,26 @@
74
74
  }
75
75
  },
76
76
  "devDependencies": {
77
- "@genesislcap/foundation-testing": "15.33.0",
78
- "@genesislcap/genx": "15.33.0",
79
- "@genesislcap/rollup-builder": "15.33.0",
80
- "@genesislcap/ts-builder": "15.33.0",
81
- "@genesislcap/uvu-playwright-builder": "15.33.0",
82
- "@genesislcap/vite-builder": "15.33.0",
83
- "@genesislcap/webpack-builder": "15.33.0",
77
+ "@genesislcap/foundation-testing": "15.33.1",
78
+ "@genesislcap/genx": "15.33.1",
79
+ "@genesislcap/rollup-builder": "15.33.1",
80
+ "@genesislcap/ts-builder": "15.33.1",
81
+ "@genesislcap/uvu-playwright-builder": "15.33.1",
82
+ "@genesislcap/vite-builder": "15.33.1",
83
+ "@genesislcap/webpack-builder": "15.33.1",
84
84
  "@types/dompurify": "^3.0.5",
85
85
  "@types/marked": "^5.0.2",
86
86
  "esbuild": "0.25.12"
87
87
  },
88
88
  "dependencies": {
89
- "@genesislcap/foundation-ai": "15.33.0",
90
- "@genesislcap/foundation-logger": "15.33.0",
91
- "@genesislcap/foundation-notifications": "15.33.0",
92
- "@genesislcap/foundation-redux": "15.33.0",
93
- "@genesislcap/foundation-ui": "15.33.0",
94
- "@genesislcap/foundation-utils": "15.33.0",
95
- "@genesislcap/rapid-design-system": "15.33.0",
96
- "@genesislcap/web-core": "15.33.0",
89
+ "@genesislcap/foundation-ai": "15.33.1",
90
+ "@genesislcap/foundation-logger": "15.33.1",
91
+ "@genesislcap/foundation-notifications": "15.33.1",
92
+ "@genesislcap/foundation-redux": "15.33.1",
93
+ "@genesislcap/foundation-ui": "15.33.1",
94
+ "@genesislcap/foundation-utils": "15.33.1",
95
+ "@genesislcap/rapid-design-system": "15.33.1",
96
+ "@genesislcap/web-core": "15.33.1",
97
97
  "dompurify": "^3.3.1",
98
98
  "marked": "^17.0.3"
99
99
  },