@genesislcap/ai-assistant 15.19.5 → 15.19.6-GENC-1566.2

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.
Files changed (27) hide show
  1. package/dist/ai-assistant.api.json +105 -0
  2. package/dist/ai-assistant.d.ts +39 -0
  3. package/dist/chat-driver.cjs +98 -6
  4. package/dist/chat-driver.cjs.map +2 -2
  5. package/dist/chat-driver.mjs +98 -6
  6. package/dist/chat-driver.mjs.map +2 -2
  7. package/dist/custom-elements.json +52 -0
  8. package/dist/dts/components/ai-driver/ai-driver.d.ts +7 -0
  9. package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
  10. package/dist/dts/components/chat-driver/chat-driver.d.ts +18 -0
  11. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
  12. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +14 -0
  13. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
  14. package/dist/dts/main/main.d.ts.map +1 -1
  15. package/dist/dts/state/persistence/diagnostics.d.ts +30 -0
  16. package/dist/dts/state/persistence/diagnostics.d.ts.map +1 -1
  17. package/dist/dts/state/persistence/session-persister.d.ts +18 -0
  18. package/dist/dts/state/persistence/session-persister.d.ts.map +1 -1
  19. package/dist/dts/utils/condense-history.d.ts +26 -0
  20. package/dist/dts/utils/condense-history.d.ts.map +1 -1
  21. package/dist/esm/components/chat-driver/chat-driver.js +21 -1
  22. package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +16 -0
  23. package/dist/esm/main/main.js +9 -3
  24. package/dist/esm/state/persistence/diagnostics.js +49 -0
  25. package/dist/esm/state/persistence/session-persister.js +36 -16
  26. package/dist/esm/utils/condense-history.js +107 -21
  27. package/package.json +16 -16
@@ -2735,6 +2735,39 @@
2735
2735
  "parameters": [],
2736
2736
  "name": "getExternalDiagnostics"
2737
2737
  },
2738
+ {
2739
+ "kind": "MethodSignature",
2740
+ "canonicalReference": "@genesislcap/ai-assistant!AiDriver#getHistoryForPersistence:member(1)",
2741
+ "docComment": "/**\n * The history a host should PERSIST — {@link AiDriver.getRawHistory} with tool payloads the driver has already condensed out of the model's context replaced by the stubs it sent (GENC-1566). Optional: a driver that does not implement tool-context condensation has nothing to project, and a caller falls back to {@link AiDriver.getRawHistory}.\n */\n",
2742
+ "excerptTokens": [
2743
+ {
2744
+ "kind": "Content",
2745
+ "text": "getHistoryForPersistence?(): "
2746
+ },
2747
+ {
2748
+ "kind": "Reference",
2749
+ "text": "ChatMessage",
2750
+ "canonicalReference": "@genesislcap/foundation-ai!ChatMessage:interface"
2751
+ },
2752
+ {
2753
+ "kind": "Content",
2754
+ "text": "[]"
2755
+ },
2756
+ {
2757
+ "kind": "Content",
2758
+ "text": ";"
2759
+ }
2760
+ ],
2761
+ "isOptional": true,
2762
+ "returnTypeTokenRange": {
2763
+ "startIndex": 1,
2764
+ "endIndex": 3
2765
+ },
2766
+ "releaseTag": "Beta",
2767
+ "overloadIndex": 1,
2768
+ "parameters": [],
2769
+ "name": "getHistoryForPersistence"
2770
+ },
2738
2771
  {
2739
2772
  "kind": "MethodSignature",
2740
2773
  "canonicalReference": "@genesislcap/ai-assistant!AiDriver#getInteractionContext:member(1)",
@@ -4768,6 +4801,42 @@
4768
4801
  "isAbstract": false,
4769
4802
  "name": "getHistory"
4770
4803
  },
4804
+ {
4805
+ "kind": "Method",
4806
+ "canonicalReference": "@genesislcap/ai-assistant!ChatDriver#getHistoryForPersistence:member(1)",
4807
+ "docComment": "/**\n * The transcript as it should be **stored**: every tool payload the model has already stopped seeing replaced by the same stub it was sent (GENC-1566). Live history is untouched — this returns a copy.\n *\n * Condensation deliberately spares stored history, because the live transcript and the debug export both read it. A host writing that transcript to durable storage inherits the other half of that decision: it stores payloads the driver has already retired, on every autosave, for the life of the session. Measured on one small Create session — 58,187 chars, 7.4% of a 790 KB session object, across five payloads worth 14,434 tokens of context, written 86 times.\n *\n * Only already-collapsed payloads are touched, so this can never store a stub for something the model can still see, and it has no side effects (see `condenseForPersistence`, which is internal). A host that wants the unredacted transcript still calls {@link ChatDriver.getRawHistory}, and a diagnostics stream that keeps full payloads is unaffected — which is what makes the elision recoverable.\n */\n",
4808
+ "excerptTokens": [
4809
+ {
4810
+ "kind": "Content",
4811
+ "text": "getHistoryForPersistence(): "
4812
+ },
4813
+ {
4814
+ "kind": "Reference",
4815
+ "text": "ChatMessage",
4816
+ "canonicalReference": "@genesislcap/foundation-ai!ChatMessage:interface"
4817
+ },
4818
+ {
4819
+ "kind": "Content",
4820
+ "text": "[]"
4821
+ },
4822
+ {
4823
+ "kind": "Content",
4824
+ "text": ";"
4825
+ }
4826
+ ],
4827
+ "isStatic": false,
4828
+ "returnTypeTokenRange": {
4829
+ "startIndex": 1,
4830
+ "endIndex": 3
4831
+ },
4832
+ "releaseTag": "Beta",
4833
+ "isProtected": false,
4834
+ "overloadIndex": 1,
4835
+ "parameters": [],
4836
+ "isOptional": false,
4837
+ "isAbstract": false,
4838
+ "name": "getHistoryForPersistence"
4839
+ },
4771
4840
  {
4772
4841
  "kind": "Method",
4773
4842
  "canonicalReference": "@genesislcap/ai-assistant!ChatDriver#getInteractionContext:member(1)",
@@ -15060,6 +15129,42 @@
15060
15129
  "isAbstract": false,
15061
15130
  "name": "getExternalDiagnostics"
15062
15131
  },
15132
+ {
15133
+ "kind": "Method",
15134
+ "canonicalReference": "@genesislcap/ai-assistant!OrchestratingDriver#getHistoryForPersistence:member(1)",
15135
+ "docComment": "/**\n * Delegates to the inner {@link ChatDriver} — condensation policies are registered there, so it is the only object that knows which payloads the model has stopped seeing (GENC-1566).\n *\n * **This forward is the whole feature, for any multi-agent host.** `AiDriver` declares `getHistoryForPersistence` optional, and `SessionPersister` calls it through `?.`, falling back to {@link OrchestratingDriver.getRawHistory}. This class does NOT extend `ChatDriver` — it wraps one — so without an explicit forward the optional call resolves to `undefined` and every host on an orchestrating driver silently keeps persisting the full payloads. Measured exactly that way on a Create run: 10 `context.condensed` events fired, and the session still stored the two largest `read_context` results at 26,907 and 23,060 chars. The method existed, the tests passed, and the feature did nothing.\n */\n",
15136
+ "excerptTokens": [
15137
+ {
15138
+ "kind": "Content",
15139
+ "text": "getHistoryForPersistence(): "
15140
+ },
15141
+ {
15142
+ "kind": "Reference",
15143
+ "text": "ChatMessage",
15144
+ "canonicalReference": "@genesislcap/foundation-ai!ChatMessage:interface"
15145
+ },
15146
+ {
15147
+ "kind": "Content",
15148
+ "text": "[]"
15149
+ },
15150
+ {
15151
+ "kind": "Content",
15152
+ "text": ";"
15153
+ }
15154
+ ],
15155
+ "isStatic": false,
15156
+ "returnTypeTokenRange": {
15157
+ "startIndex": 1,
15158
+ "endIndex": 3
15159
+ },
15160
+ "releaseTag": "Beta",
15161
+ "isProtected": false,
15162
+ "overloadIndex": 1,
15163
+ "parameters": [],
15164
+ "isOptional": false,
15165
+ "isAbstract": false,
15166
+ "name": "getHistoryForPersistence"
15167
+ },
15063
15168
  {
15064
15169
  "kind": "Method",
15065
15170
  "canonicalReference": "@genesislcap/ai-assistant!OrchestratingDriver#getInteractionContext:member(1)",
@@ -630,6 +630,13 @@ export declare interface AiDriver extends EventTarget {
630
630
  * Return the full, unredacted conversation history.
631
631
  */
632
632
  getRawHistory?(): readonly ChatMessage[];
633
+ /**
634
+ * The history a host should PERSIST — {@link AiDriver.getRawHistory} with tool payloads the
635
+ * driver has already condensed out of the model's context replaced by the stubs it sent
636
+ * (GENC-1566). Optional: a driver that does not implement tool-context condensation has nothing
637
+ * to project, and a caller falls back to {@link AiDriver.getRawHistory}.
638
+ */
639
+ getHistoryForPersistence?(): ChatMessage[];
633
640
  /**
634
641
  * The live `AgentConfig` currently active in the driver — the instance whose
635
642
  * `onActivate` ran, so its `serialize`/`getDebugSnapshot` closures hold live
@@ -1824,6 +1831,24 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
1824
1831
  getRawHistory(): readonly ChatMessage[];
1825
1832
  /** Returns the current fold stack names for debugging. */
1826
1833
  getActiveFoldNames(): string[];
1834
+ /**
1835
+ * The transcript as it should be **stored**: every tool payload the model has already stopped
1836
+ * seeing replaced by the same stub it was sent (GENC-1566). Live history is untouched — this
1837
+ * returns a copy.
1838
+ *
1839
+ * Condensation deliberately spares stored history, because the live transcript and the debug
1840
+ * export both read it. A host writing that transcript to durable storage inherits the other
1841
+ * half of that decision: it stores payloads the driver has already retired, on every autosave,
1842
+ * for the life of the session. Measured on one small Create session — 58,187 chars, 7.4% of a
1843
+ * 790 KB session object, across five payloads worth 14,434 tokens of context, written 86 times.
1844
+ *
1845
+ * Only already-collapsed payloads are touched, so this can never store a stub for something the
1846
+ * model can still see, and it has no side effects (see `condenseForPersistence`, which is
1847
+ * internal). A host that wants the unredacted transcript still calls
1848
+ * {@link ChatDriver.getRawHistory}, and a diagnostics stream that keeps full payloads is
1849
+ * unaffected — which is what makes the elision recoverable.
1850
+ */
1851
+ getHistoryForPersistence(): ChatMessage[];
1827
1852
  getSuggestions(history: ChatMessage[], prompt: string, count: number, allAgentInfo?: AllAgentSummary[]): Promise<string[]>;
1828
1853
  /**
1829
1854
  * Whether `compact()` would do anything right now — a summarizable run of older
@@ -4591,6 +4616,20 @@ export declare class OrchestratingDriver extends EventTarget implements AiDriver
4591
4616
  setFlowOwner(name: string | null): void;
4592
4617
  loadHistory(messages: ChatMessage[]): void;
4593
4618
  getRawHistory(): readonly ChatMessage[];
4619
+ /**
4620
+ * Delegates to the inner {@link ChatDriver} — condensation policies are registered there, so it
4621
+ * is the only object that knows which payloads the model has stopped seeing (GENC-1566).
4622
+ *
4623
+ * **This forward is the whole feature, for any multi-agent host.** `AiDriver` declares
4624
+ * `getHistoryForPersistence` optional, and `SessionPersister` calls it through `?.`, falling back
4625
+ * to {@link OrchestratingDriver.getRawHistory}. This class does NOT extend `ChatDriver` — it
4626
+ * wraps one — so without an explicit forward the optional call resolves to `undefined` and every
4627
+ * host on an orchestrating driver silently keeps persisting the full payloads. Measured exactly
4628
+ * that way on a Create run: 10 `context.condensed` events fired, and the session still stored
4629
+ * the two largest `read_context` results at 26,907 and 23,060 chars. The method existed, the
4630
+ * tests passed, and the feature did nothing.
4631
+ */
4632
+ getHistoryForPersistence(): ChatMessage[];
4594
4633
  /** {@inheritDoc AiDriver.compact} */
4595
4634
  compact(): Promise<ChatMessage | null>;
4596
4635
  /** {@inheritDoc AiDriver.canCompact} */
@@ -3757,6 +3757,14 @@ function condenseStub(target, tool, trigger, origLen, restorable, imageCount = 0
3757
3757
  const images = imageCount > 0 ? ` + ${imageCount} image${imageCount === 1 ? "" : "s"}` : "";
3758
3758
  return `[${tool}${key} \u2014 ${what} elided, ~${origLen} chars${images} (${triggerReason(trigger)})${restore}]`;
3759
3759
  }
3760
+ function renderCondensedArgs(policy, tool, fired, origLen) {
3761
+ return {
3762
+ [CONDENSED_ARGS_KEY]: policy === "drop" || policy === "pointer" ? condenseStub("args", tool, fired, origLen, policy === "pointer") : policy.replaceWith
3763
+ };
3764
+ }
3765
+ function renderCondensedResult(policy, tool, fired, textLen, imageCount) {
3766
+ return policy === "drop" || policy === "pointer" ? condenseStub("response", tool, fired, textLen, policy === "pointer", imageCount) : policy.replaceWith;
3767
+ }
3760
3768
  function triggerLabel(trigger) {
3761
3769
  switch (trigger.kind) {
3762
3770
  case "age":
@@ -3831,10 +3839,7 @@ function applyCondensation(history, policies, ctx, onCondensed) {
3831
3839
  const origLen = JSON.stringify(tc.args ?? {}).length;
3832
3840
  if (origLen < CONDENSE_MIN_CHARS) return tc;
3833
3841
  changed = true;
3834
- const result = entry.policy.args;
3835
- const args = {
3836
- [CONDENSED_ARGS_KEY]: result === "drop" || result === "pointer" ? condenseStub("args", tc.name, fired, origLen, result === "pointer") : result.replaceWith
3837
- };
3842
+ const args = renderCondensedArgs(entry.policy.args, tc.name, fired, origLen);
3838
3843
  if (!entry.reportedArgs) {
3839
3844
  entry.reportedArgs = true;
3840
3845
  const stubLen = JSON.stringify(args).length;
@@ -3860,8 +3865,13 @@ function applyCondensation(history, policies, ctx, onCondensed) {
3860
3865
  const fired = entry?.policy.response ? firstFired(msg.toolResult.toolCallId, entry) : void 0;
3861
3866
  if (entry && fired && origLen >= CONDENSE_MIN_CHARS) {
3862
3867
  const tool = nameById.get(msg.toolResult.toolCallId) ?? msg.toolResult.toolCallId;
3863
- const result = entry.policy.response;
3864
- const content = result === "drop" || result === "pointer" ? condenseStub("response", tool, fired, textLen, result === "pointer", images.length) : result.replaceWith;
3868
+ const content = renderCondensedResult(
3869
+ entry.policy.response,
3870
+ tool,
3871
+ fired,
3872
+ textLen,
3873
+ images.length
3874
+ );
3865
3875
  if (!entry.reportedResponse) {
3866
3876
  entry.reportedResponse = true;
3867
3877
  onCondensed({
@@ -3881,6 +3891,52 @@ function applyCondensation(history, policies, ctx, onCondensed) {
3881
3891
  return msg;
3882
3892
  });
3883
3893
  }
3894
+ function condenseForPersistence(history, policies) {
3895
+ if (policies.size === 0) return history;
3896
+ const nameById = /* @__PURE__ */ new Map();
3897
+ for (const msg of history) {
3898
+ for (const tc of msg.toolCalls ?? []) nameById.set(tc.id, tc.name);
3899
+ }
3900
+ let changed = false;
3901
+ const projected = history.map((msg) => {
3902
+ if (msg.toolCalls?.length) {
3903
+ let callsChanged = false;
3904
+ const toolCalls = msg.toolCalls.map((tc) => {
3905
+ const entry = policies.get(tc.id);
3906
+ if (!entry?.reportedArgs || !entry.firedTrigger || !entry.policy.args) return tc;
3907
+ callsChanged = true;
3908
+ const origLen = JSON.stringify(tc.args ?? {}).length;
3909
+ return {
3910
+ ...tc,
3911
+ args: renderCondensedArgs(entry.policy.args, tc.name, entry.firedTrigger, origLen)
3912
+ };
3913
+ });
3914
+ if (callsChanged) {
3915
+ changed = true;
3916
+ return { ...msg, toolCalls };
3917
+ }
3918
+ }
3919
+ if (msg.toolResult) {
3920
+ const entry = policies.get(msg.toolResult.toolCallId);
3921
+ if (entry?.reportedResponse && entry.firedTrigger && entry.policy.response) {
3922
+ changed = true;
3923
+ const tool = nameById.get(msg.toolResult.toolCallId) ?? msg.toolResult.toolCallId;
3924
+ const images = msg.toolResult.attachments ?? [];
3925
+ const content = renderCondensedResult(
3926
+ entry.policy.response,
3927
+ tool,
3928
+ entry.firedTrigger,
3929
+ msg.toolResult.content?.length ?? 0,
3930
+ images.length
3931
+ );
3932
+ const { attachments: _elided, ...restOfResult } = msg.toolResult;
3933
+ return { ...msg, toolResult: { ...restOfResult, content } };
3934
+ }
3935
+ }
3936
+ return msg;
3937
+ });
3938
+ return changed ? projected : history;
3939
+ }
3884
3940
 
3885
3941
  // src/utils/history-transform.ts
3886
3942
  function maskToolPayload(msg) {
@@ -4853,6 +4909,26 @@ var ChatDriver = class _ChatDriver extends EventTarget {
4853
4909
  getActiveFoldNames() {
4854
4910
  return this.foldStack.map((f) => f.foldName);
4855
4911
  }
4912
+ /**
4913
+ * The transcript as it should be **stored**: every tool payload the model has already stopped
4914
+ * seeing replaced by the same stub it was sent (GENC-1566). Live history is untouched — this
4915
+ * returns a copy.
4916
+ *
4917
+ * Condensation deliberately spares stored history, because the live transcript and the debug
4918
+ * export both read it. A host writing that transcript to durable storage inherits the other
4919
+ * half of that decision: it stores payloads the driver has already retired, on every autosave,
4920
+ * for the life of the session. Measured on one small Create session — 58,187 chars, 7.4% of a
4921
+ * 790 KB session object, across five payloads worth 14,434 tokens of context, written 86 times.
4922
+ *
4923
+ * Only already-collapsed payloads are touched, so this can never store a stub for something the
4924
+ * model can still see, and it has no side effects (see `condenseForPersistence`, which is
4925
+ * internal). A host that wants the unredacted transcript still calls
4926
+ * {@link ChatDriver.getRawHistory}, and a diagnostics stream that keeps full payloads is
4927
+ * unaffected — which is what makes the elision recoverable.
4928
+ */
4929
+ getHistoryForPersistence() {
4930
+ return condenseForPersistence([...this.history], this.condensePolicies);
4931
+ }
4856
4932
  async getSuggestions(history, prompt2, count, allAgentInfo) {
4857
4933
  const defaultProvider = this.providerRegistry.default();
4858
4934
  if (!defaultProvider.prompt) {
@@ -6619,6 +6695,22 @@ var OrchestratingDriver = class extends EventTarget {
6619
6695
  getRawHistory() {
6620
6696
  return this.chatDriver.getHistory();
6621
6697
  }
6698
+ /**
6699
+ * Delegates to the inner {@link ChatDriver} — condensation policies are registered there, so it
6700
+ * is the only object that knows which payloads the model has stopped seeing (GENC-1566).
6701
+ *
6702
+ * **This forward is the whole feature, for any multi-agent host.** `AiDriver` declares
6703
+ * `getHistoryForPersistence` optional, and `SessionPersister` calls it through `?.`, falling back
6704
+ * to {@link OrchestratingDriver.getRawHistory}. This class does NOT extend `ChatDriver` — it
6705
+ * wraps one — so without an explicit forward the optional call resolves to `undefined` and every
6706
+ * host on an orchestrating driver silently keeps persisting the full payloads. Measured exactly
6707
+ * that way on a Create run: 10 `context.condensed` events fired, and the session still stored
6708
+ * the two largest `read_context` results at 26,907 and 23,060 chars. The method existed, the
6709
+ * tests passed, and the feature did nothing.
6710
+ */
6711
+ getHistoryForPersistence() {
6712
+ return this.chatDriver.getHistoryForPersistence();
6713
+ }
6622
6714
  /** {@inheritDoc AiDriver.compact} */
6623
6715
  compact() {
6624
6716
  return this.chatDriver.compact();