@genesislcap/ai-assistant 15.23.3 → 15.24.0-FUI-2603.10

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 (55) hide show
  1. package/dist/ai-assistant.api.json +421 -52
  2. package/dist/ai-assistant.d.ts +239 -694
  3. package/dist/chat-driver.cjs +138 -120
  4. package/dist/chat-driver.cjs.map +4 -4
  5. package/dist/chat-driver.mjs +138 -120
  6. package/dist/chat-driver.mjs.map +4 -4
  7. package/dist/custom-elements.json +361 -602
  8. package/dist/dts/components/chat-driver/chat-driver.d.ts +22 -11
  9. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
  10. package/dist/dts/components/chat-driver/turn-failures.d.ts +96 -0
  11. package/dist/dts/components/chat-driver/turn-failures.d.ts.map +1 -0
  12. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +16 -0
  13. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
  14. package/dist/dts/components/settings-modal/index.d.ts +1 -0
  15. package/dist/dts/components/settings-modal/index.d.ts.map +1 -1
  16. package/dist/dts/components/settings-modal/settings-modal.d.ts +215 -0
  17. package/dist/dts/components/settings-modal/settings-modal.d.ts.map +1 -0
  18. package/dist/dts/components/settings-modal/settings-modal.template.d.ts.map +1 -1
  19. package/dist/dts/main/attachment-controller.d.ts +66 -0
  20. package/dist/dts/main/attachment-controller.d.ts.map +1 -0
  21. package/dist/dts/main/budget-controller.d.ts +368 -0
  22. package/dist/dts/main/budget-controller.d.ts.map +1 -0
  23. package/dist/dts/main/composer-menu-controller.d.ts +113 -0
  24. package/dist/dts/main/composer-menu-controller.d.ts.map +1 -0
  25. package/dist/dts/main/composer-resize-controller.d.ts +80 -0
  26. package/dist/dts/main/composer-resize-controller.d.ts.map +1 -0
  27. package/dist/dts/main/context-gate-controller.d.ts +197 -0
  28. package/dist/dts/main/context-gate-controller.d.ts.map +1 -0
  29. package/dist/dts/main/cost-ledger-controller.d.ts +228 -0
  30. package/dist/dts/main/cost-ledger-controller.d.ts.map +1 -0
  31. package/dist/dts/main/main.d.ts +201 -722
  32. package/dist/dts/main/main.d.ts.map +1 -1
  33. package/dist/dts/main/main.types.d.ts +25 -0
  34. package/dist/dts/main/main.types.d.ts.map +1 -1
  35. package/dist/dts/main/meta-snapshot.d.ts +50 -0
  36. package/dist/dts/main/meta-snapshot.d.ts.map +1 -0
  37. package/dist/dts/state/persistence/session-persister.d.ts.map +1 -1
  38. package/dist/esm/components/chat-driver/chat-driver.js +92 -142
  39. package/dist/esm/components/chat-driver/turn-failures.js +84 -0
  40. package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +18 -0
  41. package/dist/esm/components/settings-modal/index.js +1 -0
  42. package/dist/esm/components/settings-modal/settings-modal.js +436 -0
  43. package/dist/esm/components/settings-modal/settings-modal.template.js +15 -4
  44. package/dist/esm/main/attachment-controller.js +254 -0
  45. package/dist/esm/main/budget-controller.js +745 -0
  46. package/dist/esm/main/composer-menu-controller.js +234 -0
  47. package/dist/esm/main/composer-resize-controller.js +119 -0
  48. package/dist/esm/main/context-gate-controller.js +289 -0
  49. package/dist/esm/main/cost-ledger-controller.js +498 -0
  50. package/dist/esm/main/main.js +501 -2268
  51. package/dist/esm/main/meta-snapshot.js +108 -0
  52. package/dist/esm/state/persistence/session-persister.js +5 -4
  53. package/docs/migration-GENC-1580.md +209 -0
  54. package/package.json +16 -16
  55. package/docs/.gitattributes +0 -2
@@ -6221,7 +6221,7 @@
6221
6221
  {
6222
6222
  "kind": "PropertySignature",
6223
6223
  "canonicalReference": "@genesislcap/ai-assistant!ChatDriverConfig#budgetExhaustedMessage:member",
6224
- "docComment": "/**\n * Transcript copy appended when the AI-spend budget wall is hit (GENC-1464), used VERBATIM — set it only to own the copy entirely (white-labelling). When unset, the driver composes the bubble per wall: the neutral `DEFAULT_BUDGET_EXHAUSTED_MESSAGE`, upgraded with \"switch to another AI provider\" advice only when the 402's `otherVendorAvailable` positively says another metered vendor still has headroom — the same rule the blocked banner applies, so the two surfaces can no longer contradict each other.\n *\n * The assistant element already lets a host override the blocked **banner** via `setBlocked(true, reason)`; without this the transcript **bubble** stayed on the default, so a white-labelled host got its own copy in the banner and the shipped default directly below it. Passing the same effective copy here keeps the two surfaces saying one thing.\n *\n * Deliberately a driver-config field rather than something read off a chat config: `ChatDriver` has no `chatConfig` and is used standalone (see `chat-driver-node`), so threading one in would be a much larger and less reversible change.\n */\n",
6224
+ "docComment": "/**\n * Transcript copy appended when the AI-spend budget wall is hit (GENC-1464), used VERBATIM — set it only to own the copy entirely (white-labelling). When unset, the driver composes the bubble per wall: the neutral `TURN_FAILURE_EXITS.budgetExhausted.copy`, upgraded with \"switch to another AI provider\" advice only when the 402's `otherVendorAvailable` positively says another metered vendor still has headroom — the same rule the blocked banner applies, so the two surfaces can no longer contradict each other.\n *\n * The assistant element already lets a host override the blocked **banner** via `setBlocked(true, reason)`; without this the transcript **bubble** stayed on the default, so a white-labelled host got its own copy in the banner and the shipped default directly below it. Passing the same effective copy here keeps the two surfaces saying one thing.\n *\n * Deliberately a driver-config field rather than something read off a chat config: `ChatDriver` has no `chatConfig` and is used standalone (see `chat-driver-node`), so threading one in would be a much larger and less reversible change.\n */\n",
6225
6225
  "excerptTokens": [
6226
6226
  {
6227
6227
  "kind": "Content",
@@ -6388,7 +6388,7 @@
6388
6388
  {
6389
6389
  "kind": "PropertySignature",
6390
6390
  "canonicalReference": "@genesislcap/ai-assistant!ChatDriverConfig#providerRefusedMessage:member",
6391
- "docComment": "/**\n * Overrides the transcript sentence shown when the upstream PROVIDER refuses the account (GENC-1506) — see `DEFAULT_PROVIDER_REFUSED_MESSAGE`.\n *\n * Separate from `budgetExhaustedMessage` because the two conditions are separate: ours is a spend cap a host administrator can raise, this is the vendor declining to serve us at all. A host that white-labels one will usually want to white-label both, but conflating them into one field would force identical copy on two situations with different remedies.\n *\n * Rarely needed: unlike the budget default, the shipped sentence names no vendor and no Genesis, so it is already safe for a white-labelled deployment.\n */\n",
6391
+ "docComment": "/**\n * Overrides the transcript sentence shown when the upstream PROVIDER refuses the account (GENC-1506) — see `TURN_FAILURE_EXITS.providerRefused.copy`.\n *\n * Separate from `budgetExhaustedMessage` because the two conditions are separate: ours is a spend cap a host administrator can raise, this is the vendor declining to serve us at all. A host that white-labels one will usually want to white-label both, but conflating them into one field would force identical copy on two situations with different remedies.\n *\n * Rarely needed: unlike the budget default, the shipped sentence names no vendor and no Genesis, so it is already safe for a white-labelled deployment.\n */\n",
6392
6392
  "excerptTokens": [
6393
6393
  {
6394
6394
  "kind": "Content",
@@ -8175,7 +8175,7 @@
8175
8175
  "excerptTokens": [
8176
8176
  {
8177
8177
  "kind": "Content",
8178
- "text": "appSettingsRevision: "
8178
+ "text": "get appSettingsRevision(): "
8179
8179
  },
8180
8180
  {
8181
8181
  "kind": "Content",
@@ -8183,7 +8183,7 @@
8183
8183
  },
8184
8184
  {
8185
8185
  "kind": "Content",
8186
- "text": ";"
8186
+ "text": ";\n\nset appSettingsRevision(value: number);"
8187
8187
  }
8188
8188
  ],
8189
8189
  "isReadonly": false,
@@ -8297,11 +8297,11 @@
8297
8297
  {
8298
8298
  "kind": "Property",
8299
8299
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#attachmentErrors:member",
8300
- "docComment": "",
8300
+ "docComment": "/**\n * Rejection messages for files the last pick refused.\n */\n",
8301
8301
  "excerptTokens": [
8302
8302
  {
8303
8303
  "kind": "Content",
8304
- "text": "attachmentErrors: "
8304
+ "text": "get attachmentErrors(): "
8305
8305
  },
8306
8306
  {
8307
8307
  "kind": "Content",
@@ -8309,7 +8309,7 @@
8309
8309
  },
8310
8310
  {
8311
8311
  "kind": "Content",
8312
- "text": ";"
8312
+ "text": ";\n\nset attachmentErrors(value: string[]);"
8313
8313
  }
8314
8314
  ],
8315
8315
  "isReadonly": false,
@@ -8327,11 +8327,11 @@
8327
8327
  {
8328
8328
  "kind": "Property",
8329
8329
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#attachments:member",
8330
- "docComment": "",
8330
+ "docComment": "/**\n * Attachments pending on the next message.\n */\n",
8331
8331
  "excerptTokens": [
8332
8332
  {
8333
8333
  "kind": "Content",
8334
- "text": "attachments: "
8334
+ "text": "get attachments(): "
8335
8335
  },
8336
8336
  {
8337
8337
  "kind": "Reference",
@@ -8344,7 +8344,16 @@
8344
8344
  },
8345
8345
  {
8346
8346
  "kind": "Content",
8347
- "text": ";"
8347
+ "text": ";\n\nset attachments(value: "
8348
+ },
8349
+ {
8350
+ "kind": "Reference",
8351
+ "text": "ChatAttachment",
8352
+ "canonicalReference": "@genesislcap/foundation-ai!ChatAttachment:type"
8353
+ },
8354
+ {
8355
+ "kind": "Content",
8356
+ "text": "[]);"
8348
8357
  }
8349
8358
  ],
8350
8359
  "isReadonly": false,
@@ -8422,7 +8431,7 @@
8422
8431
  {
8423
8432
  "kind": "Property",
8424
8433
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#blockedVendors:member",
8425
- "docComment": "/**\n * Vendors currently walled by the AI-spend budget, in the order they were walled. Empty for a host that never adopts the per-vendor API.\n *\n * May include a vendor this registry cannot reach — either because the registry moved on after the wall was latched, or because a 402's `otherVendorAvailable: false` walls every vendor the proxy meters (which is what that verdict is a statement about; see {@link FoundationAiAssistant.latchBlockedFrom}). Neither costs anything internally — {@link FoundationAiAssistant.blocked} asks only about the reachable set, and the banner reads the reachability-filtered {@link FoundationAiAssistant.relevantBlockedVendors} — but a host rendering this list itself should filter it against its own registry.\n *\n * Read-only on purpose: a settable array would let a host write a partial list and silently orphan the per-vendor banner copy. {@link FoundationAiAssistant.setVendorBlocked} is the write path.\n *\n * @beta\n */\n",
8434
+ "docComment": "/**\n * Vendors currently walled by the AI-spend budget, in the order they were walled. Empty for a host that never adopts the per-vendor API.\n *\n * May include a vendor this registry cannot reach — either because the registry moved on after the wall was latched, or because a 402's `otherVendorAvailable: false` walls every vendor the proxy meters. Neither costs anything internally — {@link FoundationAiAssistant.blocked} asks only about the reachable set, and the banner reads the reachability-filtered `BudgetController.relevantBlockedVendors` — but a host rendering this list itself should filter it against its own registry.\n *\n * Read-only on purpose: a settable array would let a host write a partial list and silently orphan the per-vendor banner copy. {@link FoundationAiAssistant.setVendorBlocked} is the write path.\n *\n * @beta\n */\n",
8426
8435
  "excerptTokens": [
8427
8436
  {
8428
8437
  "kind": "Content",
@@ -8465,7 +8474,7 @@
8465
8474
  "excerptTokens": [
8466
8475
  {
8467
8476
  "kind": "Content",
8468
- "text": "budgetMeterLastFedAt: "
8477
+ "text": "get budgetMeterLastFedAt(): "
8469
8478
  },
8470
8479
  {
8471
8480
  "kind": "Content",
@@ -8473,7 +8482,7 @@
8473
8482
  },
8474
8483
  {
8475
8484
  "kind": "Content",
8476
- "text": ";"
8485
+ "text": ";\n\nset budgetMeterLastFedAt(value: number | null);"
8477
8486
  }
8478
8487
  ],
8479
8488
  "isReadonly": false,
@@ -8712,7 +8721,7 @@
8712
8721
  {
8713
8722
  "kind": "Property",
8714
8723
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#compactable:member",
8715
- "docComment": "/**\n * Whether the menu's \"Compact\" action would do anything (GENC-1351 §5.7, GENC-1567). Delegates to the driver's plan so the gate uses the exact same history `compact()` acts on, judged against the same budget — one source of truth for both whether a cut is legal and whether it reclaims enough.\n */\n",
8724
+ "docComment": "",
8716
8725
  "excerptTokens": [
8717
8726
  {
8718
8727
  "kind": "Content",
@@ -8739,6 +8748,36 @@
8739
8748
  "isProtected": false,
8740
8749
  "isAbstract": false
8741
8750
  },
8751
+ {
8752
+ "kind": "Property",
8753
+ "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#compactHint:member",
8754
+ "docComment": "",
8755
+ "excerptTokens": [
8756
+ {
8757
+ "kind": "Content",
8758
+ "text": "get compactHint(): "
8759
+ },
8760
+ {
8761
+ "kind": "Content",
8762
+ "text": "string"
8763
+ },
8764
+ {
8765
+ "kind": "Content",
8766
+ "text": ";"
8767
+ }
8768
+ ],
8769
+ "isReadonly": true,
8770
+ "isOptional": false,
8771
+ "releaseTag": "Beta",
8772
+ "name": "compactHint",
8773
+ "propertyTypeTokenRange": {
8774
+ "startIndex": 1,
8775
+ "endIndex": 2
8776
+ },
8777
+ "isStatic": false,
8778
+ "isProtected": false,
8779
+ "isAbstract": false
8780
+ },
8742
8781
  {
8743
8782
  "kind": "Property",
8744
8783
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#compacting:member",
@@ -8772,7 +8811,7 @@
8772
8811
  {
8773
8812
  "kind": "Property",
8774
8813
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#compactionPlan:member",
8775
- "docComment": "/**\n * What compacting right now would reclaim, or `null` when it would not be worth it (GENC-1567). Sized against {@link FoundationAiAssistant.contextBudget}, so the plan aims at this model's window rather than a fixed default.\n *\n * Reads `messages` to stay reactive as the conversation grows: the driver's history is not a tracked observable, so every consumer of this keys its re-evaluation off the Redux mirror.\n */\n",
8814
+ "docComment": "",
8776
8815
  "excerptTokens": [
8777
8816
  {
8778
8817
  "kind": "Content",
@@ -8843,11 +8882,11 @@
8843
8882
  {
8844
8883
  "kind": "Property",
8845
8884
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#composerHeightPx:member",
8846
- "docComment": "/**\n * Explicit composer height (px) once the user has dragged the resize handle; `null` keeps the default auto-grow behaviour. Written into the `--composer-height` custom property via the `composerHeightStyle` getter.\n */\n",
8885
+ "docComment": "/**\n * Explicit composer height once dragged; `null` keeps the default auto-grow.\n */\n",
8847
8886
  "excerptTokens": [
8848
8887
  {
8849
8888
  "kind": "Content",
8850
- "text": "composerHeightPx: "
8889
+ "text": "get composerHeightPx(): "
8851
8890
  },
8852
8891
  {
8853
8892
  "kind": "Content",
@@ -8855,7 +8894,7 @@
8855
8894
  },
8856
8895
  {
8857
8896
  "kind": "Content",
8858
- "text": ";"
8897
+ "text": ";\n\nset composerHeightPx(value: number | null);"
8859
8898
  }
8860
8899
  ],
8861
8900
  "isReadonly": false,
@@ -8873,7 +8912,7 @@
8873
8912
  {
8874
8913
  "kind": "Property",
8875
8914
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#composerHeightStyle:member",
8876
- "docComment": "/**\n * Inline style for the chat input: writes the chosen height into the `--composer-height` custom property (read by `.chat-input` + its control in `main.styles.ts`). Empty until the user drags (or when resizing is disabled), so the default applies.\n */\n",
8915
+ "docComment": "/**\n * Inline style carrying the dragged height into `--composer-height`.\n */\n",
8877
8916
  "excerptTokens": [
8878
8917
  {
8879
8918
  "kind": "Content",
@@ -8930,6 +8969,96 @@
8930
8969
  "isProtected": false,
8931
8970
  "isAbstract": false
8932
8971
  },
8972
+ {
8973
+ "kind": "Property",
8974
+ "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#composerNoticeSrOnly:member",
8975
+ "docComment": "",
8976
+ "excerptTokens": [
8977
+ {
8978
+ "kind": "Content",
8979
+ "text": "get composerNoticeSrOnly(): "
8980
+ },
8981
+ {
8982
+ "kind": "Content",
8983
+ "text": "boolean"
8984
+ },
8985
+ {
8986
+ "kind": "Content",
8987
+ "text": ";"
8988
+ }
8989
+ ],
8990
+ "isReadonly": true,
8991
+ "isOptional": false,
8992
+ "releaseTag": "Beta",
8993
+ "name": "composerNoticeSrOnly",
8994
+ "propertyTypeTokenRange": {
8995
+ "startIndex": 1,
8996
+ "endIndex": 2
8997
+ },
8998
+ "isStatic": false,
8999
+ "isProtected": false,
9000
+ "isAbstract": false
9001
+ },
9002
+ {
9003
+ "kind": "Property",
9004
+ "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#composerNoticeText:member",
9005
+ "docComment": "",
9006
+ "excerptTokens": [
9007
+ {
9008
+ "kind": "Content",
9009
+ "text": "get composerNoticeText(): "
9010
+ },
9011
+ {
9012
+ "kind": "Content",
9013
+ "text": "string"
9014
+ },
9015
+ {
9016
+ "kind": "Content",
9017
+ "text": ";"
9018
+ }
9019
+ ],
9020
+ "isReadonly": true,
9021
+ "isOptional": false,
9022
+ "releaseTag": "Beta",
9023
+ "name": "composerNoticeText",
9024
+ "propertyTypeTokenRange": {
9025
+ "startIndex": 1,
9026
+ "endIndex": 2
9027
+ },
9028
+ "isStatic": false,
9029
+ "isProtected": false,
9030
+ "isAbstract": false
9031
+ },
9032
+ {
9033
+ "kind": "Property",
9034
+ "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#composerNoticeVisible:member",
9035
+ "docComment": "",
9036
+ "excerptTokens": [
9037
+ {
9038
+ "kind": "Content",
9039
+ "text": "get composerNoticeVisible(): "
9040
+ },
9041
+ {
9042
+ "kind": "Content",
9043
+ "text": "boolean"
9044
+ },
9045
+ {
9046
+ "kind": "Content",
9047
+ "text": ";"
9048
+ }
9049
+ ],
9050
+ "isReadonly": true,
9051
+ "isOptional": false,
9052
+ "releaseTag": "Beta",
9053
+ "name": "composerNoticeVisible",
9054
+ "propertyTypeTokenRange": {
9055
+ "startIndex": 1,
9056
+ "endIndex": 2
9057
+ },
9058
+ "isStatic": false,
9059
+ "isProtected": false,
9060
+ "isAbstract": false
9061
+ },
8933
9062
  {
8934
9063
  "kind": "Property",
8935
9064
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#confirmingClear:member",
@@ -9024,7 +9153,7 @@
9024
9153
  {
9025
9154
  "kind": "Property",
9026
9155
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#contextBudget:member",
9027
- "docComment": "/**\n * Context-headroom thresholds for the active model (GENC-1567) — the warning and block lines, plus the tail budget compaction aims at.\n *\n * The per-agent `contextReserve` IS folded in, via the driver (GENC-1582). It used to be described here as a separate, later check made when an agent took ownership of a flow — but there is no such check, and by flow entry the send has already been allowed. Resolving it here, before the send, is what makes it a gate rather than a label.\n *\n * Overhead is read off `messages` (the Redux mirror) rather than the driver's own history, which the compaction plan uses. That is safe rather than sloppy: `estimateSystemOverhead` only looks at messages BEFORE the first usage-bearing one, and the two lists agree completely that early — the drift between mirror and driver history is only ever at the tail.\n */\n",
9156
+ "docComment": "/**\n * The context gate's derived surface (GENC-1567). Every member below delegates to `ContextGateController` — the names are this element's public API and the template's bindings, so they stay put while the derivation moves.\n *\n * The per-agent `contextReserve` IS folded in, via the driver (GENC-1582). It used to be described here as a separate, later check made when an agent took ownership of a flow — but there is no such check, and by flow entry the send has already been allowed. Resolving it before the send is what makes it a gate rather than a label.\n *\n * None carries `@volatile`: the decorators live on the controller's getters, and they reach the binding observer from there — see `docs/code-health.md` §11.4.\n */\n",
9028
9157
  "excerptTokens": [
9029
9158
  {
9030
9159
  "kind": "Content",
@@ -9082,6 +9211,66 @@
9082
9211
  "isProtected": false,
9083
9212
  "isAbstract": false
9084
9213
  },
9214
+ {
9215
+ "kind": "Property",
9216
+ "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#contextGateLabel:member",
9217
+ "docComment": "",
9218
+ "excerptTokens": [
9219
+ {
9220
+ "kind": "Content",
9221
+ "text": "get contextGateLabel(): "
9222
+ },
9223
+ {
9224
+ "kind": "Content",
9225
+ "text": "string"
9226
+ },
9227
+ {
9228
+ "kind": "Content",
9229
+ "text": ";"
9230
+ }
9231
+ ],
9232
+ "isReadonly": true,
9233
+ "isOptional": false,
9234
+ "releaseTag": "Beta",
9235
+ "name": "contextGateLabel",
9236
+ "propertyTypeTokenRange": {
9237
+ "startIndex": 1,
9238
+ "endIndex": 2
9239
+ },
9240
+ "isStatic": false,
9241
+ "isProtected": false,
9242
+ "isAbstract": false
9243
+ },
9244
+ {
9245
+ "kind": "Property",
9246
+ "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#contextGateReason:member",
9247
+ "docComment": "",
9248
+ "excerptTokens": [
9249
+ {
9250
+ "kind": "Content",
9251
+ "text": "get contextGateReason(): "
9252
+ },
9253
+ {
9254
+ "kind": "Content",
9255
+ "text": "string"
9256
+ },
9257
+ {
9258
+ "kind": "Content",
9259
+ "text": ";"
9260
+ }
9261
+ ],
9262
+ "isReadonly": true,
9263
+ "isOptional": false,
9264
+ "releaseTag": "Beta",
9265
+ "name": "contextGateReason",
9266
+ "propertyTypeTokenRange": {
9267
+ "startIndex": 1,
9268
+ "endIndex": 2
9269
+ },
9270
+ "isStatic": false,
9271
+ "isProtected": false,
9272
+ "isAbstract": false
9273
+ },
9085
9274
  {
9086
9275
  "kind": "Property",
9087
9276
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#contextLimit:member",
@@ -9145,11 +9334,11 @@
9145
9334
  {
9146
9335
  "kind": "Property",
9147
9336
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#costSessionHistory:member",
9148
- "docComment": "/**\n * Persisted finalized cost sessions shown on the Usage tab build history list.\n */\n",
9337
+ "docComment": "/**\n * Persisted finalized cost sessions shown on the Usage tab build history list.\n *\n * A get/set pair rather than a read-only projection: the banking tests seed rows to model a page load that found some, and a host provider's rows arrive the same way.\n */\n",
9149
9338
  "excerptTokens": [
9150
9339
  {
9151
9340
  "kind": "Content",
9152
- "text": "costSessionHistory: "
9341
+ "text": "get costSessionHistory(): "
9153
9342
  },
9154
9343
  {
9155
9344
  "kind": "Reference",
@@ -9162,7 +9351,16 @@
9162
9351
  },
9163
9352
  {
9164
9353
  "kind": "Content",
9165
- "text": ";"
9354
+ "text": ";\n\nset costSessionHistory(value: "
9355
+ },
9356
+ {
9357
+ "kind": "Reference",
9358
+ "text": "CostSessionRecord",
9359
+ "canonicalReference": "@genesislcap/ai-assistant!CostSessionRecord:interface"
9360
+ },
9361
+ {
9362
+ "kind": "Content",
9363
+ "text": "[]);"
9166
9364
  }
9167
9365
  ],
9168
9366
  "isReadonly": false,
@@ -9210,7 +9408,7 @@
9210
9408
  {
9211
9409
  "kind": "Property",
9212
9410
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#cumulativeUsage:member",
9213
- "docComment": "/**\n * Lifetime usage across every project in the history scope — cost and all four token buckets. What the Usage tab's lifetime section renders.\n *\n * Rows ONLY — deliberately not rows + live session. Each row holds a project's lifetime usage and the active project's row is kept current on every transcript change, so adding the live total would count this project's spend twice. That double-count is what made the figure grow on every refresh: a page-hide banked a row while the restored session still carried the same spend.\n */\n",
9411
+ "docComment": "/**\n * Lifetime usage across every project in the history scope — rows only, never plus live.\n */\n",
9214
9412
  "excerptTokens": [
9215
9413
  {
9216
9414
  "kind": "Content",
@@ -9533,7 +9731,7 @@
9533
9731
  {
9534
9732
  "kind": "Method",
9535
9733
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#finalizeCostSession:member(1)",
9536
- "docComment": "/**\n * Write this session's usage into persisted build history (`localStorage`) as a single row keyed by the session key, replacing any existing row for that key.\n *\n * **Idempotent** — safe to call per turn, on tab close, and on a title change alike. The name is historical: it does NOT end the session or reset the running totals. Resetting them is what used to double-count spend, since the row was banked while the persisted transcript still carried the same usage, so a reload restored it and the Usage tab counted both.\n *\n * No-op unless `chatConfig.costHistory.enabled` is `true`, when the live session has no usage yet, or when the session has no key to upsert against. Gating on the *live* figures (not the banked total) means a reload that restores nothing rewrites nothing.\n */\n",
9734
+ "docComment": "/**\n * Write this session's usage into persisted build history as a single row keyed by the session key, replacing any existing row for that key.\n *\n * **Idempotent** — safe to call per turn, on tab close, and on a title change alike. The name is historical: it does NOT end the session or reset the running totals. See `CostLedgerController.finalize` for the full contract and the no-op cases.\n */\n",
9537
9735
  "excerptTokens": [
9538
9736
  {
9539
9737
  "kind": "Content",
@@ -10138,7 +10336,7 @@
10138
10336
  {
10139
10337
  "kind": "Property",
10140
10338
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#isComposerResizable:member",
10141
- "docComment": "/**\n * Whether the message input shows a drag handle to resize its height. On by default; hosts opt out via `chatConfig.ui.resizableInput: false`.\n */\n",
10339
+ "docComment": "/**\n * Whether the message input shows a drag handle to resize its height.\n */\n",
10142
10340
  "excerptTokens": [
10143
10341
  {
10144
10342
  "kind": "Content",
@@ -10351,7 +10549,7 @@
10351
10549
  {
10352
10550
  "kind": "Property",
10353
10551
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#liveUsageIsProjectLifetime:member",
10354
- "docComment": "/**\n * Whether the live session figures amount to this project's whole history, which is true exactly when the transcript is restored on load. Drives the Usage tab's live labels (\"Project cost\" vs \"Session cost\") so they state the scope rather than imply one.\n *\n * Note this is NOT what makes the *rows* lifetime — those bank their pre-transcript spend (see `CostSessionRecord.banked`) and are lifetime either way.\n */\n",
10552
+ "docComment": "/**\n * Whether the live session figures amount to this project's whole history.\n */\n",
10355
10553
  "excerptTokens": [
10356
10554
  {
10357
10555
  "kind": "Content",
@@ -10505,7 +10703,7 @@
10505
10703
  {
10506
10704
  "kind": "Method",
10507
10705
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#onComposerResizeEnd:member(1)",
10508
- "docComment": "/**\n * End a resize drag and release the pointer capture.\n */\n",
10706
+ "docComment": "",
10509
10707
  "excerptTokens": [
10510
10708
  {
10511
10709
  "kind": "Content",
@@ -10554,7 +10752,7 @@
10554
10752
  {
10555
10753
  "kind": "Method",
10556
10754
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#onComposerResizeMove:member(1)",
10557
- "docComment": "/**\n * Resize while dragging. Dragging up (clientY decreases) grows the composer; the result is clamped between the natural height (lower) and the available headroom/max (upper). No-op unless a drag is active (the handle holds pointer capture), so plain hover-moves are ignored.\n */\n",
10755
+ "docComment": "",
10558
10756
  "excerptTokens": [
10559
10757
  {
10560
10758
  "kind": "Content",
@@ -10603,7 +10801,7 @@
10603
10801
  {
10604
10802
  "kind": "Method",
10605
10803
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#onComposerResizeStart:member(1)",
10606
- "docComment": "/**\n * Begin a composer resize drag. Captures the pointer so move/up keep firing on the handle even when the cursor leaves its 7px band.\n */\n",
10804
+ "docComment": "",
10607
10805
  "excerptTokens": [
10608
10806
  {
10609
10807
  "kind": "Content",
@@ -11369,7 +11567,7 @@
11369
11567
  {
11370
11568
  "kind": "Property",
11371
11569
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#reachableVendors:member",
11372
- "docComment": "/**\n * The distinct vendors the registry can currently reach, from the provider statuses this element already loads on connect and refreshes on every observable-registry change.\n *\n * This is the element's answer to \"which vendor would the next turn use\" — a question that has **no** correct answer and deliberately gets no API. The provider is resolved per turn AND per agent: `activeProviderInput` may be an async function of the turn's context, an orchestrated turn picks its agent with an LLM `classify()` call, and sub-agents resolve their own providers. Any pre-turn \"peek\" would therefore be a guess that is wrong precisely on the multi-agent hosts per-vendor budgets exist for.\n *\n * Asking instead which vendors are REACHABLE is answerable, synchronous, and free — and it is enough: the composer must stay live while any reachable vendor has headroom, and must lock when none does. It also makes vendor-switch recovery a derivation rather than a mutation: a host that swaps its registry to another vendor fires the observable, the statuses reload, the walled vendor drops out of this set, and `blocked` goes false with every latch left intact.\n *\n * @beta\n */\n",
11570
+ "docComment": "/**\n * The distinct vendors the registry can currently reach, from the provider statuses this element already loads on connect and refreshes on every observable-registry change — this element's answer to \"which vendor would the next turn use\", a question that has no correct answer and deliberately gets no API. See `BudgetController.reachableVendors` for why reachability is the answerable question and what deriving from it buys.\n *\n * @beta\n */\n",
11373
11571
  "excerptTokens": [
11374
11572
  {
11375
11573
  "kind": "Content",
@@ -12432,7 +12630,7 @@
12432
12630
  "excerptTokens": [
12433
12631
  {
12434
12632
  "kind": "Content",
12435
- "text": "settingsAppSlotted: "
12633
+ "text": "get settingsAppSlotted(): "
12436
12634
  },
12437
12635
  {
12438
12636
  "kind": "Reference",
@@ -12445,7 +12643,16 @@
12445
12643
  },
12446
12644
  {
12447
12645
  "kind": "Content",
12448
- "text": ";"
12646
+ "text": ";\n\nset settingsAppSlotted(value: "
12647
+ },
12648
+ {
12649
+ "kind": "Reference",
12650
+ "text": "HTMLElement",
12651
+ "canonicalReference": "!HTMLElement:interface"
12652
+ },
12653
+ {
12654
+ "kind": "Content",
12655
+ "text": "[]);"
12449
12656
  }
12450
12657
  ],
12451
12658
  "isReadonly": false,
@@ -12587,7 +12794,7 @@
12587
12794
  "excerptTokens": [
12588
12795
  {
12589
12796
  "kind": "Content",
12590
- "text": "settingsCostCurrentSlotted: "
12797
+ "text": "get settingsCostCurrentSlotted(): "
12591
12798
  },
12592
12799
  {
12593
12800
  "kind": "Reference",
@@ -12600,7 +12807,16 @@
12600
12807
  },
12601
12808
  {
12602
12809
  "kind": "Content",
12603
- "text": ";"
12810
+ "text": ";\n\nset settingsCostCurrentSlotted(value: "
12811
+ },
12812
+ {
12813
+ "kind": "Reference",
12814
+ "text": "HTMLElement",
12815
+ "canonicalReference": "!HTMLElement:interface"
12816
+ },
12817
+ {
12818
+ "kind": "Content",
12819
+ "text": "[]);"
12604
12820
  }
12605
12821
  ],
12606
12822
  "isReadonly": false,
@@ -12618,7 +12834,7 @@
12618
12834
  {
12619
12835
  "kind": "Property",
12620
12836
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#settingsCostHistoryHeadingVisible:member",
12621
- "docComment": "/**\n * Whether the \"Build history\" heading has anything under it.\n *\n * Broader than {@link FoundationAiAssistant.settingsCostHistorySectionVisible} because the heading also covers the lifetime total, which renders before the first row exists (rows are written as spend accrues, the lifetime section only needs history switched on). Gating the heading on the rows alone left that total sitting under nothing.\n */\n",
12837
+ "docComment": "/**\n * Whether the \"Build history\" heading has anything under it — broader than {@link FoundationAiAssistant.settingsCostHistorySectionVisible}, because the heading also covers the lifetime total, which renders before the first row exists.\n */\n",
12622
12838
  "excerptTokens": [
12623
12839
  {
12624
12840
  "kind": "Content",
@@ -12648,7 +12864,7 @@
12648
12864
  {
12649
12865
  "kind": "Property",
12650
12866
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#settingsCostHistorySectionVisible:member",
12651
- "docComment": "/**\n * Whether the build-history section has anything in it — the built-in row list, or a host's own markup in the `settings-cost-history` slot.\n *\n * Slotted content is checked FIRST, ahead of `enabled`. That flag governs the *built-in* ledger: it gates the row writes, the reload, and the lifetime sum — and it defaults to `false` (`cost?.enabled === true`), while the Usage tab itself shows for `showCost`/`showTokens`, which default true. So a host can legitimately render its own build history into the slot and never opt into our `localStorage` ledger. Short-circuiting on `enabled` above the slot check hid that host's markup outright, since the slot is the only thing in the container.\n */\n",
12867
+ "docComment": "/**\n * Whether the build-history section has anything in it — the built-in row list, or a host's own markup in the `settings-cost-history` slot. See `SettingsModalController.costHistorySectionVisible` for why slotted content is checked ahead of `enabled`.\n */\n",
12652
12868
  "excerptTokens": [
12653
12869
  {
12654
12870
  "kind": "Content",
@@ -12682,7 +12898,7 @@
12682
12898
  "excerptTokens": [
12683
12899
  {
12684
12900
  "kind": "Content",
12685
- "text": "settingsCostHistorySlotted: "
12901
+ "text": "get settingsCostHistorySlotted(): "
12686
12902
  },
12687
12903
  {
12688
12904
  "kind": "Reference",
@@ -12695,7 +12911,16 @@
12695
12911
  },
12696
12912
  {
12697
12913
  "kind": "Content",
12698
- "text": ";"
12914
+ "text": ";\n\nset settingsCostHistorySlotted(value: "
12915
+ },
12916
+ {
12917
+ "kind": "Reference",
12918
+ "text": "HTMLElement",
12919
+ "canonicalReference": "!HTMLElement:interface"
12920
+ },
12921
+ {
12922
+ "kind": "Content",
12923
+ "text": "[]);"
12699
12924
  }
12700
12925
  ],
12701
12926
  "isReadonly": false,
@@ -12713,7 +12938,7 @@
12713
12938
  {
12714
12939
  "kind": "Property",
12715
12940
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#settingsCostLifetimeVisible:member",
12716
- "docComment": "/**\n * Whether the lifetime-usage section has anything to say.\n *\n * Requires build history: with it off there are no rows, so `cumulativeUsage` falls back to the live session and the section would restate the block directly below it under a \"lifetime\" heading it hasn't earned.\n */\n",
12941
+ "docComment": "/**\n * Whether the lifetime-usage section has anything to say. Requires build history AND a resolvable state key — see `SettingsModalController.costLifetimeVisible`.\n */\n",
12717
12942
  "excerptTokens": [
12718
12943
  {
12719
12944
  "kind": "Content",
@@ -12838,7 +13063,7 @@
12838
13063
  "excerptTokens": [
12839
13064
  {
12840
13065
  "kind": "Content",
12841
- "text": "settingsModalTab: "
13066
+ "text": "get settingsModalTab(): "
12842
13067
  },
12843
13068
  {
12844
13069
  "kind": "Reference",
@@ -12847,7 +13072,16 @@
12847
13072
  },
12848
13073
  {
12849
13074
  "kind": "Content",
12850
- "text": ";"
13075
+ "text": ";\n\nset settingsModalTab(value: "
13076
+ },
13077
+ {
13078
+ "kind": "Reference",
13079
+ "text": "SettingsModalTab",
13080
+ "canonicalReference": "@genesislcap/ai-assistant!~SettingsModalTab:type"
13081
+ },
13082
+ {
13083
+ "kind": "Content",
13084
+ "text": ");"
12851
13085
  }
12852
13086
  ],
12853
13087
  "isReadonly": false,
@@ -12865,7 +13099,7 @@
12865
13099
  {
12866
13100
  "kind": "Property",
12867
13101
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#settingsModelSectionVisible:member",
12868
- "docComment": "/**\n * Whether the settings modal AI Model section has slotted app content, context usage or budget figures.\n */\n",
13102
+ "docComment": "/**\n * The settings modal's derived surface. Every member below delegates to `SettingsModalController` — the names are this element's public API and the 943-line template's bindings, so they stay put while the logic moves into the `settings-modal.ts` that folder never had (`docs/code-health.md` §3).\n *\n * None carries `@volatile`: the decorators live on the controller's getters, and they reach the binding observer from there — see `docs/code-health.md` §11.4.\n */\n",
12869
13103
  "excerptTokens": [
12870
13104
  {
12871
13105
  "kind": "Content",
@@ -12895,11 +13129,11 @@
12895
13129
  {
12896
13130
  "kind": "Property",
12897
13131
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#settingsModelSlotted:member",
12898
- "docComment": "/**\n * Light-DOM nodes assigned to settings modal slots (via `slotted()` bindings).\n */\n",
13132
+ "docComment": "/**\n * Light-DOM nodes assigned to settings modal slots. The template's `slotted()` bindings write these by property NAME, so each needs a real setter here even though the controller owns the arrays.\n */\n",
12899
13133
  "excerptTokens": [
12900
13134
  {
12901
13135
  "kind": "Content",
12902
- "text": "settingsModelSlotted: "
13136
+ "text": "get settingsModelSlotted(): "
12903
13137
  },
12904
13138
  {
12905
13139
  "kind": "Reference",
@@ -12912,7 +13146,16 @@
12912
13146
  },
12913
13147
  {
12914
13148
  "kind": "Content",
12915
- "text": ";"
13149
+ "text": ";\n\nset settingsModelSlotted(value: "
13150
+ },
13151
+ {
13152
+ "kind": "Reference",
13153
+ "text": "HTMLElement",
13154
+ "canonicalReference": "!HTMLElement:interface"
13155
+ },
13156
+ {
13157
+ "kind": "Content",
13158
+ "text": "[]);"
12916
13159
  }
12917
13160
  ],
12918
13161
  "isReadonly": false,
@@ -12934,7 +13177,7 @@
12934
13177
  "excerptTokens": [
12935
13178
  {
12936
13179
  "kind": "Content",
12937
- "text": "settingsOpen: "
13180
+ "text": "get settingsOpen(): "
12938
13181
  },
12939
13182
  {
12940
13183
  "kind": "Content",
@@ -12942,7 +13185,7 @@
12942
13185
  },
12943
13186
  {
12944
13187
  "kind": "Content",
12945
- "text": ";"
13188
+ "text": ";\n\nset settingsOpen(value: boolean);"
12946
13189
  }
12947
13190
  ],
12948
13191
  "isReadonly": false,
@@ -13021,7 +13264,7 @@
13021
13264
  {
13022
13265
  "kind": "Method",
13023
13266
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#setVendorBlocked:member(1)",
13024
- "docComment": "/**\n * Wall (or release) one vendor's budget, optionally with banner copy for it. The per-vendor mirror of {@link FoundationAiAssistant.setBlocked}.\n *\n * Walling a vendor does **not** on its own disable the composer: while another reachable vendor has headroom the assistant stays usable and the banner tells the user to switch. Only when every reachable vendor is walled does `blocked` become true.\n *\n * `reason` is composed into the banner sentence for that vendor, **however many vendors are walled** — see {@link FoundationAiAssistant.effectiveBlockedReason}. It is per-vendor copy, not a whole-banner override; {@link FoundationAiAssistant.blockedReason} is the override. Omitting it keeps whatever explanation that vendor already carried, so a driver latch landing after a host one cannot blank it.\n *\n * `'none'` is rejected with a warning rather than accepted: it is the \"no provider configured\" sentinel, not a vendor. Latching it would put the raw sentinel in the banner (\"none's AI usage limit is reached\") and could never be undone by derivation, because `'none'` never appears in {@link FoundationAiAssistant.reachableVendors} — so `blocked` could never become derivable from it either. Use {@link FoundationAiAssistant.setBlocked} for a vendor-agnostic block.\n *\n * @beta\n */\n",
13267
+ "docComment": "/**\n * Wall (or release) one vendor's budget, optionally with banner copy for it. The per-vendor mirror of {@link FoundationAiAssistant.setBlocked}.\n *\n * Walling a vendor does **not** on its own disable the composer: while another reachable vendor has headroom the assistant stays usable and the banner tells the user to switch. Only when every reachable vendor is walled does `blocked` become true.\n *\n * `reason` is composed into the banner sentence for that vendor, **however many vendors are walled** — see `BudgetController.effectiveBlockedReason`. It is per-vendor copy, not a whole-banner override; {@link FoundationAiAssistant.blockedReason} is the override. Omitting it keeps whatever explanation that vendor already carried, so a driver latch landing after a host one cannot blank it.\n *\n * `'none'` is rejected with a warning rather than accepted — it is the \"no provider configured\" sentinel, not a vendor, and a wall on it could never be undone by derivation. Use {@link FoundationAiAssistant.setBlocked} for a vendor-agnostic block.\n *\n * @beta\n */\n",
13025
13268
  "excerptTokens": [
13026
13269
  {
13027
13270
  "kind": "Content",
@@ -13566,7 +13809,7 @@
13566
13809
  {
13567
13810
  "kind": "Property",
13568
13811
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#sortedCostSessionHistory:member",
13569
- "docComment": "/**\n * Build history for display: most recently worked on first.\n *\n * The stored order is insertion order (see `upsertRecord`), which leaves a project returned to sitting wherever it was first seen — so ordering is applied here, on read, where it also covers rows a host provider supplied.\n */\n",
13812
+ "docComment": "/**\n * Build history for display: most recently worked on first.\n */\n",
13570
13813
  "excerptTokens": [
13571
13814
  {
13572
13815
  "kind": "Content",
@@ -13846,7 +14089,7 @@
13846
14089
  {
13847
14090
  "kind": "Method",
13848
14091
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#toggleAgentPicker:member(1)",
13849
- "docComment": "",
14092
+ "docComment": "/**\n * Document-level dismissal for whichever composer menu is open. Bound only while one IS open — a permanently-attached listener on a component that can be mounted twice (bubble + popout panel) is a cost every click on the page pays for a menu that is usually closed.\n *\n * Uses `composedPath()` rather than `event.target`: the click lands on a node inside this element's shadow root, which retargets to the host, so a plain `contains()` check cannot tell \"clicked the menu\" from \"clicked the transcript\". The path crosses the boundary and carries both.\n */\n",
13850
14093
  "excerptTokens": [
13851
14094
  {
13852
14095
  "kind": "Content",
@@ -14094,7 +14337,7 @@
14094
14337
  {
14095
14338
  "kind": "Property",
14096
14339
  "canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#uniqueProviderModels:member",
14097
- "docComment": "/**\n * Distinct models the registry currently resolves to — the live session's model chips.\n *\n * `providerStatuses` carries one entry per registry SLOT, so a vendor configured across several tiers that happen to resolve to the same model reports it once per tier, and the chips rendered it once per tier too. Which tier a model came from is not what these chips are for.\n *\n * Deduped on the label actually displayed, not on `status.model`: a slot whose provider reports no model falls back to the slot's own name, and those are distinct per slot, so keying on the label keeps them from collapsing into one another.\n */\n",
14340
+ "docComment": "/**\n * The cost ledger's derived surface (GENC-1475). Every member below delegates to `CostLedgerController` — the names are this element's public API and the settings modal's bindings, so they stay put while the accounting moves.\n *\n * None carries `@volatile`: the decorators live on the controller's getters, and they reach the binding observer from there — see `docs/code-health.md` §11.4.\n */\n",
14098
14341
  "excerptTokens": [
14099
14342
  {
14100
14343
  "kind": "Content",
@@ -18559,6 +18802,132 @@
18559
18802
  ],
18560
18803
  "extendsTokenRanges": []
18561
18804
  },
18805
+ {
18806
+ "kind": "Interface",
18807
+ "canonicalReference": "@genesislcap/ai-assistant!SettingsContextUsage:interface",
18808
+ "docComment": "/**\n * The settings-modal context-window indicator, pre-formatted — the context sibling of {@link SettingsBudgetRow}, and pre-formatted for the same reason: the template stays a pure binding layer, and a test can pin the exact text.\n *\n * `undefined` when there is nothing measurable to show, which is what keeps the template free of non-null assertions. It used to read `x.contextTokens!.toLocaleString()`, and the assertion was not merely untidy: those bindings sit inside a `when(...)` block and re-evaluate in the SAME notify batch as the guard that unmounts them, so a session Clear with the modal open on the Usage tab threw two `TypeError`s per render. A shape that can be absent cannot have that bug.\n *\n * @beta\n */\n",
18809
+ "excerptTokens": [
18810
+ {
18811
+ "kind": "Content",
18812
+ "text": "export interface SettingsContextUsage "
18813
+ }
18814
+ ],
18815
+ "fileUrlPath": "src/main/main.types.ts",
18816
+ "releaseTag": "Beta",
18817
+ "name": "SettingsContextUsage",
18818
+ "preserveMemberOrder": false,
18819
+ "members": [
18820
+ {
18821
+ "kind": "PropertySignature",
18822
+ "canonicalReference": "@genesislcap/ai-assistant!SettingsContextUsage#barValue:member",
18823
+ "docComment": "/**\n * The bar's value, clamped to `0..100` — only the bar clamps.\n */\n",
18824
+ "excerptTokens": [
18825
+ {
18826
+ "kind": "Content",
18827
+ "text": "barValue: "
18828
+ },
18829
+ {
18830
+ "kind": "Content",
18831
+ "text": "number"
18832
+ },
18833
+ {
18834
+ "kind": "Content",
18835
+ "text": ";"
18836
+ }
18837
+ ],
18838
+ "isReadonly": false,
18839
+ "isOptional": false,
18840
+ "releaseTag": "Beta",
18841
+ "name": "barValue",
18842
+ "propertyTypeTokenRange": {
18843
+ "startIndex": 1,
18844
+ "endIndex": 2
18845
+ }
18846
+ },
18847
+ {
18848
+ "kind": "PropertySignature",
18849
+ "canonicalReference": "@genesislcap/ai-assistant!SettingsContextUsage#limit:member",
18850
+ "docComment": "/**\n * The model's context window, e.g. `200,000`.\n */\n",
18851
+ "excerptTokens": [
18852
+ {
18853
+ "kind": "Content",
18854
+ "text": "limit: "
18855
+ },
18856
+ {
18857
+ "kind": "Content",
18858
+ "text": "string"
18859
+ },
18860
+ {
18861
+ "kind": "Content",
18862
+ "text": ";"
18863
+ }
18864
+ ],
18865
+ "isReadonly": false,
18866
+ "isOptional": false,
18867
+ "releaseTag": "Beta",
18868
+ "name": "limit",
18869
+ "propertyTypeTokenRange": {
18870
+ "startIndex": 1,
18871
+ "endIndex": 2
18872
+ }
18873
+ },
18874
+ {
18875
+ "kind": "PropertySignature",
18876
+ "canonicalReference": "@genesislcap/ai-assistant!SettingsContextUsage#percent:member",
18877
+ "docComment": "/**\n * Whole-number percent consumed. Unclamped, like the budget row's text.\n */\n",
18878
+ "excerptTokens": [
18879
+ {
18880
+ "kind": "Content",
18881
+ "text": "percent: "
18882
+ },
18883
+ {
18884
+ "kind": "Content",
18885
+ "text": "number"
18886
+ },
18887
+ {
18888
+ "kind": "Content",
18889
+ "text": ";"
18890
+ }
18891
+ ],
18892
+ "isReadonly": false,
18893
+ "isOptional": false,
18894
+ "releaseTag": "Beta",
18895
+ "name": "percent",
18896
+ "propertyTypeTokenRange": {
18897
+ "startIndex": 1,
18898
+ "endIndex": 2
18899
+ }
18900
+ },
18901
+ {
18902
+ "kind": "PropertySignature",
18903
+ "canonicalReference": "@genesislcap/ai-assistant!SettingsContextUsage#used:member",
18904
+ "docComment": "/**\n * Prompt tokens on the last call, e.g. `12,480`.\n */\n",
18905
+ "excerptTokens": [
18906
+ {
18907
+ "kind": "Content",
18908
+ "text": "used: "
18909
+ },
18910
+ {
18911
+ "kind": "Content",
18912
+ "text": "string"
18913
+ },
18914
+ {
18915
+ "kind": "Content",
18916
+ "text": ";"
18917
+ }
18918
+ ],
18919
+ "isReadonly": false,
18920
+ "isOptional": false,
18921
+ "releaseTag": "Beta",
18922
+ "name": "used",
18923
+ "propertyTypeTokenRange": {
18924
+ "startIndex": 1,
18925
+ "endIndex": 2
18926
+ }
18927
+ }
18928
+ ],
18929
+ "extendsTokenRanges": []
18930
+ },
18562
18931
  {
18563
18932
  "kind": "Variable",
18564
18933
  "canonicalReference": "@genesislcap/ai-assistant!sparkleIconSvg:var",