@genesislcap/ai-assistant 15.15.2 → 15.16.0
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.
- package/dist/ai-assistant.api.json +271 -2
- package/dist/ai-assistant.d.ts +90 -1
- package/dist/chat-driver.cjs +72 -0
- package/dist/chat-driver.cjs.map +2 -2
- package/dist/chat-driver.mjs +72 -0
- package/dist/chat-driver.mjs.map +2 -2
- package/dist/custom-elements.json +221 -97
- package/dist/dts/components/ai-driver/ai-driver.d.ts +11 -0
- package/dist/dts/components/ai-driver/ai-driver.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts +31 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts +10 -0
- package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts.map +1 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts +2 -0
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.cost.test.d.ts.map +1 -0
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts +3 -0
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
- package/dist/dts/index.d.ts +1 -1
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/main/file-attachments.test.d.ts +2 -0
- package/dist/dts/main/file-attachments.test.d.ts.map +1 -0
- package/dist/dts/main/interaction-cost.test.d.ts +2 -0
- package/dist/dts/main/interaction-cost.test.d.ts.map +1 -0
- package/dist/dts/main/main.d.ts +27 -0
- package/dist/dts/main/main.d.ts.map +1 -1
- package/dist/dts/main/main.template.d.ts.map +1 -1
- package/dist/dts/react.d.ts +2 -1
- package/dist/dts/state/debug-event-log.d.ts +1 -1
- package/dist/dts/state/debug-event-log.d.ts.map +1 -1
- package/dist/dts/types/ai-chat-widget.d.ts +8 -0
- package/dist/dts/types/ai-chat-widget.d.ts.map +1 -1
- package/dist/esm/components/chat-driver/chat-driver.js +75 -1
- package/dist/esm/components/chat-driver/chat-driver.test.js +90 -0
- package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.js +22 -0
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.cost.test.js +76 -0
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +14 -0
- package/dist/esm/main/file-attachments.test.js +164 -0
- package/dist/esm/main/interaction-cost.test.js +107 -0
- package/dist/esm/main/main.js +193 -21
- package/dist/esm/main/main.template.js +1 -0
- package/dist/esm/state/debug-event-log.js +6 -0
- package/dist/react.cjs +6 -1
- package/dist/react.mjs +6 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/src/components/ai-driver/ai-driver.ts +11 -0
- package/src/components/chat-driver/chat-driver.test.ts +109 -0
- package/src/components/chat-driver/chat-driver.ts +78 -1
- package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +29 -0
- package/src/components/orchestrating-driver/orchestrating-driver.cost.test.ts +107 -0
- package/src/components/orchestrating-driver/orchestrating-driver.ts +17 -0
- package/src/index.ts +4 -1
- package/src/main/file-attachments.test.ts +215 -0
- package/src/main/interaction-cost.test.ts +140 -0
- package/src/main/main.template.ts +1 -0
- package/src/main/main.ts +204 -22
- package/src/state/debug-event-log.ts +8 -0
- package/src/types/ai-chat-widget.ts +8 -0
|
@@ -2270,7 +2270,7 @@
|
|
|
2270
2270
|
{
|
|
2271
2271
|
"kind": "Interface",
|
|
2272
2272
|
"canonicalReference": "@genesislcap/ai-assistant!AiChatWidget:interface",
|
|
2273
|
-
"docComment": "/**\n * Interface that AI inline interaction components implement. The `AiChatInteractionWrapper` sets `interactionId` and `interaction` on the rendered element on every (re)mount, and replaces `interaction` (pending → resolved) when the interaction completes.\n *\n * @remarks\n *\n *
|
|
2273
|
+
"docComment": "/**\n * Interface that AI inline interaction components implement. The `AiChatInteractionWrapper` sets `interactionId` and `interaction` on the rendered element on every (re)mount, and replaces `interaction` (pending → resolved) when the interaction completes.\n *\n * @remarks\n *\n * A widget talks back by dispatching two events, both caught by the wrapper: `interaction-completed` resolves the interaction (once — a second is ignored), and `interaction-cost` reports a positive USD delta for paid work done AFTER resolving, which repeated calls sum. The second exists for widgets that resolve early so the assistant stops waiting, then keep working for the user; without it that spend is billed but missing from the total the user sees.\n *\n * @beta\n */\n",
|
|
2274
2274
|
"excerptTokens": [
|
|
2275
2275
|
{
|
|
2276
2276
|
"kind": "Content",
|
|
@@ -3205,6 +3205,67 @@
|
|
|
3205
3205
|
],
|
|
3206
3206
|
"name": "primeRestoredAgentState"
|
|
3207
3207
|
},
|
|
3208
|
+
{
|
|
3209
|
+
"kind": "MethodSignature",
|
|
3210
|
+
"canonicalReference": "@genesislcap/ai-assistant!AiDriver#recordExternalCost:member(1)",
|
|
3211
|
+
"docComment": "/**\n * Record external spend against an interaction that has ALREADY resolved.\n *\n * For widgets that resolve early — so the assistant stops waiting — and then keep doing paid work on the user's behalf. Reports a positive DELTA; repeated calls sum. Returns false when the spend was NOT recorded — the value was not a positive finite amount, or the message is no longer in history.\n *\n * @beta\n */\n",
|
|
3212
|
+
"excerptTokens": [
|
|
3213
|
+
{
|
|
3214
|
+
"kind": "Content",
|
|
3215
|
+
"text": "recordExternalCost?(interactionId: "
|
|
3216
|
+
},
|
|
3217
|
+
{
|
|
3218
|
+
"kind": "Content",
|
|
3219
|
+
"text": "string"
|
|
3220
|
+
},
|
|
3221
|
+
{
|
|
3222
|
+
"kind": "Content",
|
|
3223
|
+
"text": ", costUsd: "
|
|
3224
|
+
},
|
|
3225
|
+
{
|
|
3226
|
+
"kind": "Content",
|
|
3227
|
+
"text": "number"
|
|
3228
|
+
},
|
|
3229
|
+
{
|
|
3230
|
+
"kind": "Content",
|
|
3231
|
+
"text": "): "
|
|
3232
|
+
},
|
|
3233
|
+
{
|
|
3234
|
+
"kind": "Content",
|
|
3235
|
+
"text": "boolean"
|
|
3236
|
+
},
|
|
3237
|
+
{
|
|
3238
|
+
"kind": "Content",
|
|
3239
|
+
"text": ";"
|
|
3240
|
+
}
|
|
3241
|
+
],
|
|
3242
|
+
"isOptional": true,
|
|
3243
|
+
"returnTypeTokenRange": {
|
|
3244
|
+
"startIndex": 5,
|
|
3245
|
+
"endIndex": 6
|
|
3246
|
+
},
|
|
3247
|
+
"releaseTag": "Beta",
|
|
3248
|
+
"overloadIndex": 1,
|
|
3249
|
+
"parameters": [
|
|
3250
|
+
{
|
|
3251
|
+
"parameterName": "interactionId",
|
|
3252
|
+
"parameterTypeTokenRange": {
|
|
3253
|
+
"startIndex": 1,
|
|
3254
|
+
"endIndex": 2
|
|
3255
|
+
},
|
|
3256
|
+
"isOptional": false
|
|
3257
|
+
},
|
|
3258
|
+
{
|
|
3259
|
+
"parameterName": "costUsd",
|
|
3260
|
+
"parameterTypeTokenRange": {
|
|
3261
|
+
"startIndex": 3,
|
|
3262
|
+
"endIndex": 4
|
|
3263
|
+
},
|
|
3264
|
+
"isOptional": false
|
|
3265
|
+
}
|
|
3266
|
+
],
|
|
3267
|
+
"name": "recordExternalCost"
|
|
3268
|
+
},
|
|
3208
3269
|
{
|
|
3209
3270
|
"kind": "MethodSignature",
|
|
3210
3271
|
"canonicalReference": "@genesislcap/ai-assistant!AiDriver#resolveInteraction:member(1)",
|
|
@@ -4294,7 +4355,7 @@
|
|
|
4294
4355
|
{
|
|
4295
4356
|
"kind": "Class",
|
|
4296
4357
|
"canonicalReference": "@genesislcap/ai-assistant!ChatDriver:class",
|
|
4297
|
-
"docComment": "/**\n * Plain TS class that drives a multi-turn chat conversation, including the tool-call loop. Owned by `FoundationAiAssistant` — created in `connectedCallback`, torn down in `disconnectedCallback`.\n *\n * Dispatches `'history-updated'` events on itself so the owning element can observe changes.\n *\n * @fires\n *\n * history-updated - Fired whenever the in-memory chat history changes (append, tool loop, interaction resolution) with the full history snapshot. detail: `ReadonlyArray<ChatMessage>`\n *\n * @beta\n */\n",
|
|
4358
|
+
"docComment": "/**\n * Plain TS class that drives a multi-turn chat conversation, including the tool-call loop. Owned by `FoundationAiAssistant` — created in `connectedCallback`, torn down in `disconnectedCallback`.\n *\n * Dispatches `'history-updated'` events on itself so the owning element can observe changes.\n *\n * @fires\n *\n * history-updated - Fired whenever the in-memory chat history changes (append, tool loop, interaction resolution, post-resolve external cost) with the full history snapshot. detail: `ReadonlyArray<ChatMessage>`\n *\n * @beta\n */\n",
|
|
4298
4359
|
"excerptTokens": [
|
|
4299
4360
|
{
|
|
4300
4361
|
"kind": "Content",
|
|
@@ -5265,6 +5326,70 @@
|
|
|
5265
5326
|
"isAbstract": false,
|
|
5266
5327
|
"name": "markAsSubAgent"
|
|
5267
5328
|
},
|
|
5329
|
+
{
|
|
5330
|
+
"kind": "Method",
|
|
5331
|
+
"canonicalReference": "@genesislcap/ai-assistant!ChatDriver#recordExternalCost:member(1)",
|
|
5332
|
+
"docComment": "/**\n * Add external (non-LLM) spend to an interaction's message AFTER it has resolved.\n *\n * **Why this exists separately from `resolveInteraction`.** A widget's spend reaches the session total only through `InteractionResult.costUsd`, which is read exactly once — `resolveInteraction` does its whole job inside `if (interaction)` and then deletes the entry from `pendingInteractions`. That is correct for the resolution itself, but it assumes a widget stops costing money when it resolves, and several deliberately do not: a widget that resolves EARLY so the assistant stops waiting (options shown, a preview rendered) may stay interactive for minutes afterwards and do more paid work on the user's behalf. Re-emitting `interaction-completed` does not help — with the interaction gone from the map the call is a silent no-op — so that spend had nowhere to go and was simply missing from the figure shown to the user.\n *\n * Additive by design: the caller reports a DELTA, not a running total, so repeated calls sum. It touches only `externalCostUsd`; the recorded `interaction.resolved` payload is left exactly as the resolution wrote it, because this is not a second resolution and must not read like one.\n *\n * Deliberately does NOT require the interaction to be pending, does not resurrect it, and has no loading/turn side effects — this is bookkeeping about a turn that already happened.\n *\n * @param interactionId - the interaction whose message owns the spend.\n *\n * @param costUsd - a positive delta in USD. Non-finite, zero and negative values are ignored.\n *\n * @returns `true` when the spend was recorded; `false` when it was not — either the value was not a positive finite amount, or the message is no longer in history (trimmed or condensed away). A real outcome a caller may want to log rather than a failure to throw on; every `false` also records an `interaction.external-cost-dropped` meta event here, so money can never disappear without a trace.\n *\n * @beta\n */\n",
|
|
5333
|
+
"excerptTokens": [
|
|
5334
|
+
{
|
|
5335
|
+
"kind": "Content",
|
|
5336
|
+
"text": "recordExternalCost(interactionId: "
|
|
5337
|
+
},
|
|
5338
|
+
{
|
|
5339
|
+
"kind": "Content",
|
|
5340
|
+
"text": "string"
|
|
5341
|
+
},
|
|
5342
|
+
{
|
|
5343
|
+
"kind": "Content",
|
|
5344
|
+
"text": ", costUsd: "
|
|
5345
|
+
},
|
|
5346
|
+
{
|
|
5347
|
+
"kind": "Content",
|
|
5348
|
+
"text": "number"
|
|
5349
|
+
},
|
|
5350
|
+
{
|
|
5351
|
+
"kind": "Content",
|
|
5352
|
+
"text": "): "
|
|
5353
|
+
},
|
|
5354
|
+
{
|
|
5355
|
+
"kind": "Content",
|
|
5356
|
+
"text": "boolean"
|
|
5357
|
+
},
|
|
5358
|
+
{
|
|
5359
|
+
"kind": "Content",
|
|
5360
|
+
"text": ";"
|
|
5361
|
+
}
|
|
5362
|
+
],
|
|
5363
|
+
"isStatic": false,
|
|
5364
|
+
"returnTypeTokenRange": {
|
|
5365
|
+
"startIndex": 5,
|
|
5366
|
+
"endIndex": 6
|
|
5367
|
+
},
|
|
5368
|
+
"releaseTag": "Beta",
|
|
5369
|
+
"isProtected": false,
|
|
5370
|
+
"overloadIndex": 1,
|
|
5371
|
+
"parameters": [
|
|
5372
|
+
{
|
|
5373
|
+
"parameterName": "interactionId",
|
|
5374
|
+
"parameterTypeTokenRange": {
|
|
5375
|
+
"startIndex": 1,
|
|
5376
|
+
"endIndex": 2
|
|
5377
|
+
},
|
|
5378
|
+
"isOptional": false
|
|
5379
|
+
},
|
|
5380
|
+
{
|
|
5381
|
+
"parameterName": "costUsd",
|
|
5382
|
+
"parameterTypeTokenRange": {
|
|
5383
|
+
"startIndex": 3,
|
|
5384
|
+
"endIndex": 4
|
|
5385
|
+
},
|
|
5386
|
+
"isOptional": false
|
|
5387
|
+
}
|
|
5388
|
+
],
|
|
5389
|
+
"isOptional": false,
|
|
5390
|
+
"isAbstract": false,
|
|
5391
|
+
"name": "recordExternalCost"
|
|
5392
|
+
},
|
|
5268
5393
|
{
|
|
5269
5394
|
"kind": "Method",
|
|
5270
5395
|
"canonicalReference": "@genesislcap/ai-assistant!ChatDriver#reportBudgetExhausted:member(1)",
|
|
@@ -9077,6 +9202,55 @@
|
|
|
9077
9202
|
"isAbstract": false,
|
|
9078
9203
|
"name": "handleInteractionCompleted"
|
|
9079
9204
|
},
|
|
9205
|
+
{
|
|
9206
|
+
"kind": "Method",
|
|
9207
|
+
"canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#handleInteractionCost:member(1)",
|
|
9208
|
+
"docComment": "/**\n * A widget reporting spend it incurred AFTER resolving.\n *\n * Note what this deliberately does NOT do: no `startLoadingTimer()`. This is bookkeeping about a turn that already finished, so it must be invisible — showing a spinner would tell the user the assistant is working when nothing is pending.\n */\n",
|
|
9209
|
+
"excerptTokens": [
|
|
9210
|
+
{
|
|
9211
|
+
"kind": "Content",
|
|
9212
|
+
"text": "handleInteractionCost(e: "
|
|
9213
|
+
},
|
|
9214
|
+
{
|
|
9215
|
+
"kind": "Reference",
|
|
9216
|
+
"text": "Event",
|
|
9217
|
+
"canonicalReference": "!Event:interface"
|
|
9218
|
+
},
|
|
9219
|
+
{
|
|
9220
|
+
"kind": "Content",
|
|
9221
|
+
"text": "): "
|
|
9222
|
+
},
|
|
9223
|
+
{
|
|
9224
|
+
"kind": "Content",
|
|
9225
|
+
"text": "void"
|
|
9226
|
+
},
|
|
9227
|
+
{
|
|
9228
|
+
"kind": "Content",
|
|
9229
|
+
"text": ";"
|
|
9230
|
+
}
|
|
9231
|
+
],
|
|
9232
|
+
"isStatic": false,
|
|
9233
|
+
"returnTypeTokenRange": {
|
|
9234
|
+
"startIndex": 3,
|
|
9235
|
+
"endIndex": 4
|
|
9236
|
+
},
|
|
9237
|
+
"releaseTag": "Beta",
|
|
9238
|
+
"isProtected": false,
|
|
9239
|
+
"overloadIndex": 1,
|
|
9240
|
+
"parameters": [
|
|
9241
|
+
{
|
|
9242
|
+
"parameterName": "e",
|
|
9243
|
+
"parameterTypeTokenRange": {
|
|
9244
|
+
"startIndex": 1,
|
|
9245
|
+
"endIndex": 2
|
|
9246
|
+
},
|
|
9247
|
+
"isOptional": false
|
|
9248
|
+
}
|
|
9249
|
+
],
|
|
9250
|
+
"isOptional": false,
|
|
9251
|
+
"isAbstract": false,
|
|
9252
|
+
"name": "handleInteractionCost"
|
|
9253
|
+
},
|
|
9080
9254
|
{
|
|
9081
9255
|
"kind": "Method",
|
|
9082
9256
|
"canonicalReference": "@genesislcap/ai-assistant!FoundationAiAssistant#handlePopout:member(1)",
|
|
@@ -14280,6 +14454,37 @@
|
|
|
14280
14454
|
],
|
|
14281
14455
|
"extendsTokenRanges": []
|
|
14282
14456
|
},
|
|
14457
|
+
{
|
|
14458
|
+
"kind": "TypeAlias",
|
|
14459
|
+
"canonicalReference": "@genesislcap/ai-assistant!InteractionCostEventDetail:type",
|
|
14460
|
+
"docComment": "/**\n * Detail payload for the `interaction-cost` event — a POSITIVE DELTA in USD, not a running total.\n *\n * @public\n */\n",
|
|
14461
|
+
"excerptTokens": [
|
|
14462
|
+
{
|
|
14463
|
+
"kind": "Content",
|
|
14464
|
+
"text": "export type InteractionCostEventDetail = "
|
|
14465
|
+
},
|
|
14466
|
+
{
|
|
14467
|
+
"kind": "Reference",
|
|
14468
|
+
"text": "ChatInteractionEventsMap",
|
|
14469
|
+
"canonicalReference": "@genesislcap/ai-assistant!~ChatInteractionEventsMap:type"
|
|
14470
|
+
},
|
|
14471
|
+
{
|
|
14472
|
+
"kind": "Content",
|
|
14473
|
+
"text": "['interaction-cost']"
|
|
14474
|
+
},
|
|
14475
|
+
{
|
|
14476
|
+
"kind": "Content",
|
|
14477
|
+
"text": ";"
|
|
14478
|
+
}
|
|
14479
|
+
],
|
|
14480
|
+
"fileUrlPath": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts",
|
|
14481
|
+
"releaseTag": "Public",
|
|
14482
|
+
"name": "InteractionCostEventDetail",
|
|
14483
|
+
"typeTokenRange": {
|
|
14484
|
+
"startIndex": 1,
|
|
14485
|
+
"endIndex": 3
|
|
14486
|
+
}
|
|
14487
|
+
},
|
|
14283
14488
|
{
|
|
14284
14489
|
"kind": "Function",
|
|
14285
14490
|
"canonicalReference": "@genesislcap/ai-assistant!isAiAssistantDocked:function(1)",
|
|
@@ -15256,6 +15461,70 @@
|
|
|
15256
15461
|
"isAbstract": false,
|
|
15257
15462
|
"name": "primeRestoredAgentState"
|
|
15258
15463
|
},
|
|
15464
|
+
{
|
|
15465
|
+
"kind": "Method",
|
|
15466
|
+
"canonicalReference": "@genesislcap/ai-assistant!OrchestratingDriver#recordExternalCost:member(1)",
|
|
15467
|
+
"docComment": "/**\n * Delegated for the same reason as `resolveInteraction`: the history that owns the interaction — and therefore the cost — lives on the wrapped driver, not here.\n */\n",
|
|
15468
|
+
"excerptTokens": [
|
|
15469
|
+
{
|
|
15470
|
+
"kind": "Content",
|
|
15471
|
+
"text": "recordExternalCost(interactionId: "
|
|
15472
|
+
},
|
|
15473
|
+
{
|
|
15474
|
+
"kind": "Content",
|
|
15475
|
+
"text": "string"
|
|
15476
|
+
},
|
|
15477
|
+
{
|
|
15478
|
+
"kind": "Content",
|
|
15479
|
+
"text": ", costUsd: "
|
|
15480
|
+
},
|
|
15481
|
+
{
|
|
15482
|
+
"kind": "Content",
|
|
15483
|
+
"text": "number"
|
|
15484
|
+
},
|
|
15485
|
+
{
|
|
15486
|
+
"kind": "Content",
|
|
15487
|
+
"text": "): "
|
|
15488
|
+
},
|
|
15489
|
+
{
|
|
15490
|
+
"kind": "Content",
|
|
15491
|
+
"text": "boolean"
|
|
15492
|
+
},
|
|
15493
|
+
{
|
|
15494
|
+
"kind": "Content",
|
|
15495
|
+
"text": ";"
|
|
15496
|
+
}
|
|
15497
|
+
],
|
|
15498
|
+
"isStatic": false,
|
|
15499
|
+
"returnTypeTokenRange": {
|
|
15500
|
+
"startIndex": 5,
|
|
15501
|
+
"endIndex": 6
|
|
15502
|
+
},
|
|
15503
|
+
"releaseTag": "Beta",
|
|
15504
|
+
"isProtected": false,
|
|
15505
|
+
"overloadIndex": 1,
|
|
15506
|
+
"parameters": [
|
|
15507
|
+
{
|
|
15508
|
+
"parameterName": "interactionId",
|
|
15509
|
+
"parameterTypeTokenRange": {
|
|
15510
|
+
"startIndex": 1,
|
|
15511
|
+
"endIndex": 2
|
|
15512
|
+
},
|
|
15513
|
+
"isOptional": false
|
|
15514
|
+
},
|
|
15515
|
+
{
|
|
15516
|
+
"parameterName": "costUsd",
|
|
15517
|
+
"parameterTypeTokenRange": {
|
|
15518
|
+
"startIndex": 3,
|
|
15519
|
+
"endIndex": 4
|
|
15520
|
+
},
|
|
15521
|
+
"isOptional": false
|
|
15522
|
+
}
|
|
15523
|
+
],
|
|
15524
|
+
"isOptional": false,
|
|
15525
|
+
"isAbstract": false,
|
|
15526
|
+
"name": "recordExternalCost"
|
|
15527
|
+
},
|
|
15259
15528
|
{
|
|
15260
15529
|
"kind": "Method",
|
|
15261
15530
|
"canonicalReference": "@genesislcap/ai-assistant!OrchestratingDriver#resolveInteraction:member(1)",
|
package/dist/ai-assistant.d.ts
CHANGED
|
@@ -532,6 +532,14 @@ export declare class AiChatMarkdown extends GenesisElement {
|
|
|
532
532
|
* change on this `@beta` interface — widgets read `this.interaction` (narrowing on
|
|
533
533
|
* `status`) instead of the removed flat fields.
|
|
534
534
|
*
|
|
535
|
+
* @remarks
|
|
536
|
+
* A widget talks back by dispatching two events, both caught by the wrapper:
|
|
537
|
+
* `interaction-completed` resolves the interaction (once — a second is ignored), and
|
|
538
|
+
* `interaction-cost` reports a positive USD delta for paid work done AFTER resolving,
|
|
539
|
+
* which repeated calls sum. The second exists for widgets that resolve early so the
|
|
540
|
+
* assistant stops waiting, then keep working for the user; without it that spend is
|
|
541
|
+
* billed but missing from the total the user sees.
|
|
542
|
+
*
|
|
535
543
|
* @beta
|
|
536
544
|
*/
|
|
537
545
|
export declare interface AiChatWidget<TData = unknown, TResult = unknown> {
|
|
@@ -597,6 +605,17 @@ export declare interface AiDriver extends EventTarget {
|
|
|
597
605
|
* Resolve a pending blocking interaction with the given result.
|
|
598
606
|
*/
|
|
599
607
|
resolveInteraction(interactionId: string, result: unknown): void;
|
|
608
|
+
/**
|
|
609
|
+
* Record external spend against an interaction that has ALREADY resolved.
|
|
610
|
+
*
|
|
611
|
+
* For widgets that resolve early — so the assistant stops waiting — and then keep doing paid work
|
|
612
|
+
* on the user's behalf. Reports a positive DELTA; repeated calls sum. Returns false when the
|
|
613
|
+
* spend was NOT recorded — the value was not a positive finite amount, or the message is no
|
|
614
|
+
* longer in history.
|
|
615
|
+
*
|
|
616
|
+
* @beta
|
|
617
|
+
*/
|
|
618
|
+
recordExternalCost?(interactionId: string, costUsd: number): boolean;
|
|
600
619
|
/**
|
|
601
620
|
* The live {@link InteractionContext} for a pending interaction (GENC-1390), or
|
|
602
621
|
* `undefined` if the interaction is resolved/evicted or the driver owns no
|
|
@@ -1196,7 +1215,7 @@ export declare type CachePolicyInput = CachePolicy | ((ctx: SystemPromptContext)
|
|
|
1196
1215
|
*
|
|
1197
1216
|
* Dispatches `'history-updated'` events on itself so the owning element can observe changes.
|
|
1198
1217
|
*
|
|
1199
|
-
* @fires history-updated - Fired whenever the in-memory chat history changes (append, tool loop, interaction resolution) with the full history snapshot. detail: `ReadonlyArray<ChatMessage>`
|
|
1218
|
+
* @fires history-updated - Fired whenever the in-memory chat history changes (append, tool loop, interaction resolution, post-resolve external cost) with the full history snapshot. detail: `ReadonlyArray<ChatMessage>`
|
|
1200
1219
|
*
|
|
1201
1220
|
* @beta
|
|
1202
1221
|
*/
|
|
@@ -1858,6 +1877,36 @@ export declare class ChatDriver extends EventTarget implements AiDriver {
|
|
|
1858
1877
|
* bubble and/or shows the "Assistant" label.
|
|
1859
1878
|
*/
|
|
1860
1879
|
requestInteraction<T>(componentName: string, data: any, options?: InteractionRequestOptions): Promise<T>;
|
|
1880
|
+
/**
|
|
1881
|
+
* Add external (non-LLM) spend to an interaction's message AFTER it has resolved.
|
|
1882
|
+
*
|
|
1883
|
+
* **Why this exists separately from `resolveInteraction`.** A widget's spend reaches the session
|
|
1884
|
+
* total only through `InteractionResult.costUsd`, which is read exactly once — `resolveInteraction`
|
|
1885
|
+
* does its whole job inside `if (interaction)` and then deletes the entry from
|
|
1886
|
+
* `pendingInteractions`. That is correct for the resolution itself, but it assumes a widget stops
|
|
1887
|
+
* costing money when it resolves, and several deliberately do not: a widget that resolves EARLY so
|
|
1888
|
+
* the assistant stops waiting (options shown, a preview rendered) may stay interactive for minutes
|
|
1889
|
+
* afterwards and do more paid work on the user's behalf. Re-emitting `interaction-completed` does
|
|
1890
|
+
* not help — with the interaction gone from the map the call is a silent no-op — so that spend had
|
|
1891
|
+
* nowhere to go and was simply missing from the figure shown to the user.
|
|
1892
|
+
*
|
|
1893
|
+
* Additive by design: the caller reports a DELTA, not a running total, so repeated calls sum. It
|
|
1894
|
+
* touches only `externalCostUsd`; the recorded `interaction.resolved` payload is left exactly as
|
|
1895
|
+
* the resolution wrote it, because this is not a second resolution and must not read like one.
|
|
1896
|
+
*
|
|
1897
|
+
* Deliberately does NOT require the interaction to be pending, does not resurrect it, and has no
|
|
1898
|
+
* loading/turn side effects — this is bookkeeping about a turn that already happened.
|
|
1899
|
+
*
|
|
1900
|
+
* @param interactionId the interaction whose message owns the spend.
|
|
1901
|
+
* @param costUsd a positive delta in USD. Non-finite, zero and negative values are ignored.
|
|
1902
|
+
* @returns `true` when the spend was recorded; `false` when it was not — either the value was
|
|
1903
|
+
* not a positive finite amount, or the message is no longer in history (trimmed or condensed
|
|
1904
|
+
* away). A real outcome a caller may want to log rather than a failure to throw on; every
|
|
1905
|
+
* `false` also records an `interaction.external-cost-dropped` meta event here, so money can
|
|
1906
|
+
* never disappear without a trace.
|
|
1907
|
+
* @beta
|
|
1908
|
+
*/
|
|
1909
|
+
recordExternalCost(interactionId: string, costUsd: number): boolean;
|
|
1861
1910
|
/**
|
|
1862
1911
|
* Resolve a pending interaction. The wrapper component calls this on completion.
|
|
1863
1912
|
* Marks the interaction message as resolved so it renders read-only on re-render.
|
|
@@ -2057,6 +2106,10 @@ declare type ChatInteractionEventsMap = {
|
|
|
2057
2106
|
'interaction-completed': InteractionResult<unknown> & {
|
|
2058
2107
|
interactionId: string;
|
|
2059
2108
|
};
|
|
2109
|
+
'interaction-cost': {
|
|
2110
|
+
interactionId: string;
|
|
2111
|
+
costUsd: number;
|
|
2112
|
+
};
|
|
2060
2113
|
};
|
|
2061
2114
|
|
|
2062
2115
|
export { ChatThinkingPolicy }
|
|
@@ -3637,6 +3690,22 @@ export declare class FoundationAiAssistant extends GenesisElement {
|
|
|
3637
3690
|
persistenceChanged(oldValue: SessionPersistenceConfig | undefined, newValue: SessionPersistenceConfig | undefined): void;
|
|
3638
3691
|
showingSplashChanged(): void;
|
|
3639
3692
|
private syncShowingSplash;
|
|
3693
|
+
/**
|
|
3694
|
+
* Recompute the session's cost and token buckets from a transcript.
|
|
3695
|
+
*
|
|
3696
|
+
* Takes the list rather than reading `this.messages`, because it has two callers with
|
|
3697
|
+
* different sources: the `messages` setter passes the rendered list, and post-resolve external
|
|
3698
|
+
* cost passes the DRIVER's history — spend recorded there must reach the total WITHOUT
|
|
3699
|
+
* reassigning `messages`, which would re-render the live interaction row. See
|
|
3700
|
+
* `onExternalCostRecorded`.
|
|
3701
|
+
*
|
|
3702
|
+
* Recomputing (rather than incrementing on append) keeps the totals correct under any mutation
|
|
3703
|
+
* of the message list — clear-chat, re-render, restore. `sumUsage` recurses into
|
|
3704
|
+
* `toolCall.subAgentTrace`, so work a sub-agent did (possibly on another provider at other
|
|
3705
|
+
* rates) counts, and it reads the usage a compaction banked onto its summary, so shrinking
|
|
3706
|
+
* history no longer shrinks the totals.
|
|
3707
|
+
*/
|
|
3708
|
+
private syncUsageTotals;
|
|
3640
3709
|
/**
|
|
3641
3710
|
* Runs side effects that were previously in `messagesChanged()`.
|
|
3642
3711
|
* Called from the `messages` setter after dispatching to the store.
|
|
@@ -4043,6 +4112,9 @@ export declare class FoundationAiAssistant extends GenesisElement {
|
|
|
4043
4112
|
removeAttachmentError(message: string): void;
|
|
4044
4113
|
private isAcceptedFile;
|
|
4045
4114
|
private readFileAsText;
|
|
4115
|
+
/** The base64 payload of a file, without any `data:` prefix — the raw form
|
|
4116
|
+
* `ChatImageAttachment.data` specifies (transports add their own framing). */
|
|
4117
|
+
private readFileAsBase64;
|
|
4046
4118
|
private processFiles;
|
|
4047
4119
|
private loadSelectedFiles;
|
|
4048
4120
|
handleSendClick(): void;
|
|
@@ -4089,6 +4161,14 @@ export declare class FoundationAiAssistant extends GenesisElement {
|
|
|
4089
4161
|
private send;
|
|
4090
4162
|
onChatHeaderMouseDown(e: MouseEvent): void;
|
|
4091
4163
|
handleInteractionCompleted(e: Event): void;
|
|
4164
|
+
/**
|
|
4165
|
+
* A widget reporting spend it incurred AFTER resolving.
|
|
4166
|
+
*
|
|
4167
|
+
* Note what this deliberately does NOT do: no `startLoadingTimer()`. This is bookkeeping about a
|
|
4168
|
+
* turn that already finished, so it must be invisible — showing a spinner would tell the user the
|
|
4169
|
+
* assistant is working when nothing is pending.
|
|
4170
|
+
*/
|
|
4171
|
+
handleInteractionCost(e: Event): void;
|
|
4092
4172
|
/**
|
|
4093
4173
|
* The live {@link InteractionContext} for a pending interaction (GENC-1390).
|
|
4094
4174
|
* `AiChatInteractionWrapper` pierces this across the shadow boundary to build the
|
|
@@ -4305,6 +4385,12 @@ export declare interface InteractionContext<TState extends object = Record<strin
|
|
|
4305
4385
|
onDispose(fn: () => void): void;
|
|
4306
4386
|
}
|
|
4307
4387
|
|
|
4388
|
+
/**
|
|
4389
|
+
* Detail payload for the `interaction-cost` event — a POSITIVE DELTA in USD, not a running total.
|
|
4390
|
+
* @public
|
|
4391
|
+
*/
|
|
4392
|
+
export declare type InteractionCostEventDetail = ChatInteractionEventsMap['interaction-cost'];
|
|
4393
|
+
|
|
4308
4394
|
/** True when the assistant is active in the layout panel (docked) rather than the bubble. */
|
|
4309
4395
|
export declare function isAiAssistantDocked(): boolean;
|
|
4310
4396
|
|
|
@@ -4422,6 +4508,9 @@ export declare class OrchestratingDriver extends EventTarget implements AiDriver
|
|
|
4422
4508
|
budgetExhaustedMessage?: string;
|
|
4423
4509
|
});
|
|
4424
4510
|
resolveInteraction(interactionId: string, result: unknown): void;
|
|
4511
|
+
/** Delegated for the same reason as `resolveInteraction`: the history that owns the
|
|
4512
|
+
* interaction — and therefore the cost — lives on the wrapped driver, not here. */
|
|
4513
|
+
recordExternalCost(interactionId: string, costUsd: number): boolean;
|
|
4425
4514
|
getInteractionContext(interactionId: string): InteractionContext | undefined;
|
|
4426
4515
|
isBusy(): boolean;
|
|
4427
4516
|
/** Currently active provider name from the underlying ChatDriver. */
|
package/dist/chat-driver.cjs
CHANGED
|
@@ -3585,6 +3585,12 @@ var META_EVENT_IMPORTANCE = {
|
|
|
3585
3585
|
"provider.selected": "normal",
|
|
3586
3586
|
"interaction.requested": "normal",
|
|
3587
3587
|
"interaction.resolved": "normal",
|
|
3588
|
+
// Bookkeeping about an already-finished turn; interesting when reconciling a session total.
|
|
3589
|
+
"interaction.external-cost": "normal",
|
|
3590
|
+
// Spend that was billed but could NOT be recorded (the message was trimmed/condensed away, or
|
|
3591
|
+
// the value was not real spend). 'high': it is the one way the session total goes quietly
|
|
3592
|
+
// wrong, so it must stand out when reconciling.
|
|
3593
|
+
"interaction.external-cost-dropped": "high",
|
|
3588
3594
|
"external-diagnostics.folded": "normal",
|
|
3589
3595
|
"session.cleared": "normal",
|
|
3590
3596
|
"session.switched": "low",
|
|
@@ -5070,6 +5076,62 @@ Output format (strict):
|
|
|
5070
5076
|
});
|
|
5071
5077
|
});
|
|
5072
5078
|
}
|
|
5079
|
+
/**
|
|
5080
|
+
* Add external (non-LLM) spend to an interaction's message AFTER it has resolved.
|
|
5081
|
+
*
|
|
5082
|
+
* **Why this exists separately from `resolveInteraction`.** A widget's spend reaches the session
|
|
5083
|
+
* total only through `InteractionResult.costUsd`, which is read exactly once — `resolveInteraction`
|
|
5084
|
+
* does its whole job inside `if (interaction)` and then deletes the entry from
|
|
5085
|
+
* `pendingInteractions`. That is correct for the resolution itself, but it assumes a widget stops
|
|
5086
|
+
* costing money when it resolves, and several deliberately do not: a widget that resolves EARLY so
|
|
5087
|
+
* the assistant stops waiting (options shown, a preview rendered) may stay interactive for minutes
|
|
5088
|
+
* afterwards and do more paid work on the user's behalf. Re-emitting `interaction-completed` does
|
|
5089
|
+
* not help — with the interaction gone from the map the call is a silent no-op — so that spend had
|
|
5090
|
+
* nowhere to go and was simply missing from the figure shown to the user.
|
|
5091
|
+
*
|
|
5092
|
+
* Additive by design: the caller reports a DELTA, not a running total, so repeated calls sum. It
|
|
5093
|
+
* touches only `externalCostUsd`; the recorded `interaction.resolved` payload is left exactly as
|
|
5094
|
+
* the resolution wrote it, because this is not a second resolution and must not read like one.
|
|
5095
|
+
*
|
|
5096
|
+
* Deliberately does NOT require the interaction to be pending, does not resurrect it, and has no
|
|
5097
|
+
* loading/turn side effects — this is bookkeeping about a turn that already happened.
|
|
5098
|
+
*
|
|
5099
|
+
* @param interactionId the interaction whose message owns the spend.
|
|
5100
|
+
* @param costUsd a positive delta in USD. Non-finite, zero and negative values are ignored.
|
|
5101
|
+
* @returns `true` when the spend was recorded; `false` when it was not — either the value was
|
|
5102
|
+
* not a positive finite amount, or the message is no longer in history (trimmed or condensed
|
|
5103
|
+
* away). A real outcome a caller may want to log rather than a failure to throw on; every
|
|
5104
|
+
* `false` also records an `interaction.external-cost-dropped` meta event here, so money can
|
|
5105
|
+
* never disappear without a trace.
|
|
5106
|
+
* @beta
|
|
5107
|
+
*/
|
|
5108
|
+
recordExternalCost(interactionId, costUsd) {
|
|
5109
|
+
const drop = (reason) => {
|
|
5110
|
+
recordMetaEvent(this.sessionKey, "interaction.external-cost-dropped", {
|
|
5111
|
+
interactionId,
|
|
5112
|
+
costUsd,
|
|
5113
|
+
reason
|
|
5114
|
+
});
|
|
5115
|
+
return false;
|
|
5116
|
+
};
|
|
5117
|
+
if (!interactionId) return drop("no interactionId");
|
|
5118
|
+
if (typeof costUsd !== "number" || !Number.isFinite(costUsd) || costUsd <= 0) {
|
|
5119
|
+
return drop("not a positive finite amount");
|
|
5120
|
+
}
|
|
5121
|
+
const idx = this.history.findIndex((m) => m.interaction?.interactionId === interactionId);
|
|
5122
|
+
if (idx === -1) return drop("interaction message no longer in history");
|
|
5123
|
+
this.history[idx] = {
|
|
5124
|
+
...this.history[idx],
|
|
5125
|
+
externalCostUsd: (this.history[idx].externalCostUsd ?? 0) + costUsd
|
|
5126
|
+
};
|
|
5127
|
+
recordMetaEvent(this.sessionKey, "interaction.external-cost", { interactionId, costUsd });
|
|
5128
|
+
this.dispatchEvent(
|
|
5129
|
+
new CustomEvent("external-cost-recorded", {
|
|
5130
|
+
detail: { interactionId, costUsd }
|
|
5131
|
+
})
|
|
5132
|
+
);
|
|
5133
|
+
return true;
|
|
5134
|
+
}
|
|
5073
5135
|
/**
|
|
5074
5136
|
* Resolve a pending interaction. The wrapper component calls this on completion.
|
|
5075
5137
|
* Marks the interaction message as resolved so it renders read-only on re-render.
|
|
@@ -6509,10 +6571,20 @@ var OrchestratingDriver = class extends EventTarget {
|
|
|
6509
6571
|
new CustomEvent("provider-changed", { detail: e.detail })
|
|
6510
6572
|
);
|
|
6511
6573
|
});
|
|
6574
|
+
this.chatDriver.addEventListener("external-cost-recorded", (e) => {
|
|
6575
|
+
this.dispatchEvent(
|
|
6576
|
+
new CustomEvent("external-cost-recorded", { detail: e.detail })
|
|
6577
|
+
);
|
|
6578
|
+
});
|
|
6512
6579
|
}
|
|
6513
6580
|
resolveInteraction(interactionId, result) {
|
|
6514
6581
|
this.chatDriver.resolveInteraction(interactionId, result);
|
|
6515
6582
|
}
|
|
6583
|
+
/** Delegated for the same reason as `resolveInteraction`: the history that owns the
|
|
6584
|
+
* interaction — and therefore the cost — lives on the wrapped driver, not here. */
|
|
6585
|
+
recordExternalCost(interactionId, costUsd) {
|
|
6586
|
+
return this.chatDriver.recordExternalCost(interactionId, costUsd);
|
|
6587
|
+
}
|
|
6516
6588
|
getInteractionContext(interactionId) {
|
|
6517
6589
|
return this.chatDriver.getInteractionContext(interactionId);
|
|
6518
6590
|
}
|