@genesislcap/ai-assistant 15.12.0 → 15.13.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 +245 -3
- package/dist/ai-assistant.d.ts +127 -7
- package/dist/chat-driver.cjs +79 -13
- package/dist/chat-driver.cjs.map +2 -2
- package/dist/chat-driver.mjs +76 -12
- package/dist/chat-driver.mjs.map +2 -2
- package/dist/custom-elements.json +452 -359
- package/dist/dts/chat-driver-node.d.ts +2 -2
- package/dist/dts/chat-driver-node.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts +45 -1
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts +2 -0
- package/dist/dts/components/chat-driver/chat-driver.turn-usage.test.d.ts.map +1 -0
- package/dist/dts/main/main.d.ts +20 -1
- package/dist/dts/main/main.d.ts.map +1 -1
- package/dist/dts/state/debug-event-log.d.ts.map +1 -1
- package/dist/dts/state/persistence/diagnostics.d.ts +65 -8
- package/dist/dts/state/persistence/diagnostics.d.ts.map +1 -1
- package/dist/dts/state/persistence/index.d.ts +1 -1
- package/dist/dts/state/persistence/index.d.ts.map +1 -1
- package/dist/dts/state/persistence/session-persister.d.ts +4 -3
- package/dist/dts/state/persistence/session-persister.d.ts.map +1 -1
- package/dist/dts/utils/sum-usage.d.ts +20 -0
- package/dist/dts/utils/sum-usage.d.ts.map +1 -1
- package/dist/esm/chat-driver-node.js +12 -2
- package/dist/esm/components/chat-driver/chat-driver.js +60 -5
- package/dist/esm/components/chat-driver/chat-driver.turn-usage.test.js +268 -0
- package/dist/esm/main/main.js +53 -28
- package/dist/esm/state/debug-event-log.js +7 -2
- package/dist/esm/state/persistence/diagnostics.js +79 -16
- package/dist/esm/state/persistence/diagnostics.test.js +174 -1
- package/dist/esm/state/persistence/index.js +1 -1
- package/dist/esm/state/persistence/session-persister.js +13 -5
- package/dist/esm/state/persistence/session-persister.test.js +31 -0
- package/dist/esm/utils/sum-usage.js +43 -0
- package/dist/esm/utils/sum-usage.test.js +45 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +17 -17
- package/src/chat-driver-node.ts +12 -2
- package/src/components/chat-driver/chat-driver.ts +107 -6
- package/src/components/chat-driver/chat-driver.turn-usage.test.ts +362 -0
- package/src/main/main.ts +52 -23
- package/src/state/debug-event-log.ts +7 -2
- package/src/state/persistence/diagnostics.test.ts +208 -1
- package/src/state/persistence/diagnostics.ts +117 -15
- package/src/state/persistence/index.ts +1 -1
- package/src/state/persistence/session-persister.test.ts +37 -0
- package/src/state/persistence/session-persister.ts +13 -5
- package/src/utils/sum-usage.test.ts +52 -1
- package/src/utils/sum-usage.ts +45 -0
|
@@ -367,6 +367,14 @@
|
|
|
367
367
|
"module": "./utils/sum-usage"
|
|
368
368
|
}
|
|
369
369
|
},
|
|
370
|
+
{
|
|
371
|
+
"kind": "js",
|
|
372
|
+
"name": "messageUsage",
|
|
373
|
+
"declaration": {
|
|
374
|
+
"name": "messageUsage",
|
|
375
|
+
"module": "./utils/sum-usage"
|
|
376
|
+
}
|
|
377
|
+
},
|
|
370
378
|
{
|
|
371
379
|
"kind": "js",
|
|
372
380
|
"name": "sumUsage",
|
|
@@ -447,6 +455,14 @@
|
|
|
447
455
|
"module": "./state/persistence/diagnostics"
|
|
448
456
|
}
|
|
449
457
|
},
|
|
458
|
+
{
|
|
459
|
+
"kind": "js",
|
|
460
|
+
"name": "withFreshMetaSnapshot",
|
|
461
|
+
"declaration": {
|
|
462
|
+
"name": "withFreshMetaSnapshot",
|
|
463
|
+
"module": "./state/persistence/diagnostics"
|
|
464
|
+
}
|
|
465
|
+
},
|
|
450
466
|
{
|
|
451
467
|
"kind": "js",
|
|
452
468
|
"name": "DebugLog",
|
|
@@ -4075,7 +4091,7 @@
|
|
|
4075
4091
|
"text": "DebugLog"
|
|
4076
4092
|
}
|
|
4077
4093
|
},
|
|
4078
|
-
"description": "The live current-page debug log (`{ readme, timeline, meta }`). @public"
|
|
4094
|
+
"description": "The live current-page debug log (`{ readme, sessionUsage, timeline, meta }`). @public"
|
|
4079
4095
|
},
|
|
4080
4096
|
{
|
|
4081
4097
|
"kind": "method",
|
|
@@ -4088,6 +4104,17 @@
|
|
|
4088
4104
|
},
|
|
4089
4105
|
"description": "Build the current page's diagnostic entries (GENC-1351 §5.8) — the debug-log\ntimeline entries (`message`/`turn`/`event`) plus one `meta-snapshot` carrying\nthe export-time `meta` block. `getDebugLog()` reassembles these into the live\nlog; the persister's forward-capture path (`SessionPersister.flushDiagnostics`,\nfed these via the `getDiagnosticEntries` dep) diffs them against what's already\nbeen appended to the persisted stream."
|
|
4090
4106
|
},
|
|
4107
|
+
{
|
|
4108
|
+
"kind": "method",
|
|
4109
|
+
"name": "buildMetaSnapshot",
|
|
4110
|
+
"privacy": "private",
|
|
4111
|
+
"return": {
|
|
4112
|
+
"type": {
|
|
4113
|
+
"text": "DiagnosticEntry"
|
|
4114
|
+
}
|
|
4115
|
+
},
|
|
4116
|
+
"description": "The single `meta-snapshot` entry for right now — the export-time `meta` block\n(agent summary, active prompt/state, context + cost) plus the `dedupSignature`\nthe forward-capture delta keys on.\n\nSeparate from `buildDiagnosticEntries` because the download path needs a\nFRESH one on its own: the persisted stream only re-appends this block when the\nnear-static config changes, so the newest stored snapshot's volatile half — the\n`context` figures especially — is typically frozen at the session's first flush."
|
|
4117
|
+
},
|
|
4091
4118
|
{
|
|
4092
4119
|
"kind": "method",
|
|
4093
4120
|
"name": "downloadDebugLog",
|
|
@@ -4106,7 +4133,7 @@
|
|
|
4106
4133
|
"text": "Promise<DebugLog>"
|
|
4107
4134
|
}
|
|
4108
4135
|
},
|
|
4109
|
-
"description": "The log to download (GENC-1351 §5.8). When the provider persists diagnostics,\nstitch the **whole lifetime** stream (every page load) rather than just the\ncurrent page's in-memory view: flush the current delta first so it's included,\nthen reassemble everything `loadDiagnostics` returns. Independent of \"remember\nchat\" — diagnostics are a forensic stream keyed on provider capability, not on\nwhether the *chat* is remembered (like preferences). Falls back to the live\ncurrent-page log when diagnostics isn't available or the fetch fails."
|
|
4136
|
+
"description": "The log to download (GENC-1351 §5.8). When the provider persists diagnostics,\nstitch the **whole lifetime** stream (every page load) rather than just the\ncurrent page's in-memory view: flush the current delta first so it's included,\nthen reassemble everything `loadDiagnostics` returns. Independent of \"remember\nchat\" — diagnostics are a forensic stream keyed on provider capability, not on\nwhether the *chat* is remembered (like preferences). Falls back to the live\ncurrent-page log when diagnostics isn't available or the fetch fails.\n\nThe stored `meta-snapshot`s are replaced by a fresh one (`withFreshMetaSnapshot`)\nbefore reassembly. The persisted stream only re-appends that block when the\nnear-static config signature changes (see `collectDiagnosticsDelta`), so on a session\nwhose config never changes the newest STORED snapshot is the first one — its\n`context` half (session cost/usage, context tokens, live agent state) frozen seconds\ninto the session, which is how a lifetime log came out reporting near-zero spend\nagainst a transcript full of priced messages."
|
|
4110
4137
|
},
|
|
4111
4138
|
{
|
|
4112
4139
|
"kind": "method",
|
|
@@ -4649,48 +4676,6 @@
|
|
|
4649
4676
|
}
|
|
4650
4677
|
]
|
|
4651
4678
|
},
|
|
4652
|
-
{
|
|
4653
|
-
"kind": "javascript-module",
|
|
4654
|
-
"path": "src/provider/ai-provider-switcher.ts",
|
|
4655
|
-
"declarations": [
|
|
4656
|
-
{
|
|
4657
|
-
"kind": "variable",
|
|
4658
|
-
"name": "AIProviderSwitcher",
|
|
4659
|
-
"description": "The DI token for the (AIProviderSwitcher:interface). Resolves a noop until the app\nregisters one."
|
|
4660
|
-
}
|
|
4661
|
-
],
|
|
4662
|
-
"exports": [
|
|
4663
|
-
{
|
|
4664
|
-
"kind": "js",
|
|
4665
|
-
"name": "AIProviderSwitcher",
|
|
4666
|
-
"declaration": {
|
|
4667
|
-
"name": "AIProviderSwitcher",
|
|
4668
|
-
"module": "src/provider/ai-provider-switcher.ts"
|
|
4669
|
-
}
|
|
4670
|
-
}
|
|
4671
|
-
]
|
|
4672
|
-
},
|
|
4673
|
-
{
|
|
4674
|
-
"kind": "javascript-module",
|
|
4675
|
-
"path": "src/provider/assistant-app-settings.ts",
|
|
4676
|
-
"declarations": [
|
|
4677
|
-
{
|
|
4678
|
-
"kind": "variable",
|
|
4679
|
-
"name": "AssistantAppSettingsProvider",
|
|
4680
|
-
"description": "The DI token for the (AssistantAppSettingsProvider:interface). Resolves a noop\nuntil the host registers one."
|
|
4681
|
-
}
|
|
4682
|
-
],
|
|
4683
|
-
"exports": [
|
|
4684
|
-
{
|
|
4685
|
-
"kind": "js",
|
|
4686
|
-
"name": "AssistantAppSettingsProvider",
|
|
4687
|
-
"declaration": {
|
|
4688
|
-
"name": "AssistantAppSettingsProvider",
|
|
4689
|
-
"module": "src/provider/assistant-app-settings.ts"
|
|
4690
|
-
}
|
|
4691
|
-
}
|
|
4692
|
-
]
|
|
4693
|
-
},
|
|
4694
4679
|
{
|
|
4695
4680
|
"kind": "javascript-module",
|
|
4696
4681
|
"path": "src/state/ai-assistant-slice.ts",
|
|
@@ -4916,7 +4901,7 @@
|
|
|
4916
4901
|
"type": {
|
|
4917
4902
|
"text": "readonly string[]"
|
|
4918
4903
|
},
|
|
4919
|
-
"default": "[\n 'This is an exported debug log for the Genesis AI assistant. Read it top-to-bottom.',\n '`timeline` is the entire session as one array, already sorted chronologically by `timestamp` (ISO 8601). Every entry has a `kind`.',\n 'Timestamps are millisecond-resolution; entries that share the same millisecond are ordered by a fixed kind rank (event, then turn, then message), which is a heuristic and may not reflect exact causal order within that millisecond — e.g. a user message and the turn it triggered, or a final assistant message and its turn.end event, can appear in either order depending on whether they landed in the same millisecond. Read the logical structure of a turn rather than over-interpreting the micro-ordering of co-timestamped entries of different kinds.',\n \"kind:'message' — the conversation. `role` is user/assistant/tool/system-event/synthetic-user; `agentName` says which agent produced it; `toolCalls`/`toolResult`/`interaction` carry tool and widget activity; `inputTokens`/`outputTokens`/`cost` are per-message LLM usage, where `inputTokens` is the WHOLE prompt for that request and `cacheReadTokens`/`cacheWriteTokens` BREAK IT DOWN rather than add to it — uncached input is `inputTokens` minus those two, and adding the cache fields to `inputTokens` counts the prompt twice. The cache fields are absent on providers that report no cache split (Gemini reports reads only, since implicit caching bills no write) and on messages persisted before they existed, so read them as 0 when missing. Each bucket bills at a different rate — cache reads a fraction of uncached input, cache writes a premium, output highest — so a large token count at a small cost means the prompt was mostly cache hits. `externalCostUsd` is any non-LLM cost a widget reported for its own external service calls (folded into the session cost total alongside `cost`). On model-produced assistant messages, `model` is the concrete model id that generated it (e.g. 'gemini-2.5-flash-lite') and `providerName` is the registry slot it resolved under (e.g. a tier name like 'high'/'low', or the default); together they attribute the message — and any tool calls it carries — to an exact model even across a mid-session vendor/tier switch, where one slot name can map to different models before and after the switch. Both are undefined on any entry that is NOT an LLM response: non-assistant roles (user/tool/system-event) and 'synthetic-user' echoes; assistant interaction/widget entries (empty content carrying an `interaction` — a rendered widget, not a model turn); driver-authored assistant fallbacks (the timeout, repeated-malformed-call, and empty-response apology messages); and messages restored from a session persisted before these fields existed. One partial case: on a genuine model turn whose provider exposes no `getStatus` (or reports no model), `providerName` is still set but `model` alone is undefined. A 'synthetic-user' message is a display-only echo of an interaction outcome (e.g. the answer a widget reported): it renders on the user's side of the chat and `agentName` is the agent that created it, but it is never sent to the LLM — so it has no matching 'turn' and the model learns the outcome only from the corresponding tool result.\",\n \"Sub-agent messages appear inline. When a tool delegates to a sub-agent (via `requestSubAgent`), the sub-agent's whole conversation — its own assistant/tool messages, each with their own `content`/`thinking`/`toolCalls`/`toolResult` and per-message `model`/`providerName`/`inputTokens`/`outputTokens`/`cacheReadTokens`/`cacheWriteTokens`/`cost` — is hoisted into the timeline as ordinary kind:'message' entries, interleaved by timestamp right after the tool call that spawned them (so you read the delegation top-to-bottom). A hoisted entry is marked: `subAgentDepth` is its delegation depth (1 for a sub-agent, 2 for a sub-agent's sub-agent, …), `subAgentOf` is the id of the parent tool call that spawned it (correlates it back even when two sub-agents run in one parent turn), `subAgentName` is the sub-agent's own name, and `agentName` is rewritten to a `\\\"<parent> › <sub-agent>\\\"` breadcrumb (composing when nested, e.g. `\\\"UI Builder › Planner › Grounding\\\"`). The sub-agent's per-LLM-call snapshots also surface as kind:'turn' entries with an N-M `turnIndex`, and subagent.started/completed (or subagent.failed) events bracket the run. Per-message `cost` on hoisted entries is already part of the session total (it is summed from the un-flattened history), so summing the top-level timeline does NOT double-count.\",\n \"kind:'turn' — one LLM call. `turnIndex` is a string: a top-level turn is the bare counter ('0', '1', …); a sub-agent's turns are numbered under the parent turn that activated them ('3-1', '3-2', …, and a nested sub-agent contributes '3-2-1', …), and `agentName` names the agent that ran the turn. `systemPrompt` and `toolNames` are what the model saw. A systemPrompt of '<repeated — identical to turn N>' was byte-identical to turn N and de-duplicated; the full prompt is shown whenever it changes (often because a stateful agent advanced), so prompt evolution is visible.\",\n \"kind:'turn'.`agentSnapshot` — the active agent's own view of its internal state, captured at that turn. An agent opts into this by exposing a `getDebugSnapshot()` that returns JSON-serializable per-state info; stateful/flow agents wire it automatically, so you can watch a flow advance turn-by-turn (e.g. current step, cursor, collected fields, pending changes). Absent for agents that don't expose one.\",\n \"kind:'event' — a meta/lifecycle event. `type` names it (see below); `detail` carries structured data. `detail.placement` is the emitting UI instance: 'bubble' (collapsed), 'panel' (popped-out), or 'standalone'.\",\n \"Each 'event' also has an `importance`: 'high' (failures/limits — turn.error, tool.failed, subagent.failed, file.read-failed, suggestions.failed, context.threshold-crossed), 'normal' (session flow — connects, turns, retries, handoffs, agent/provider changes, interactions, sub-agent start/complete), or 'low' (skippable UI/bookkeeping noise — panel.toggled, attachment.added, driver.wired/unwired, context.updated, context.condensed). To skim, ignore importance:'low'; to triage a failure, filter to importance:'high' then read the nearby messages and turns. A 'high' turn.error is often preceded by one or more 'normal' turn.retry events for the same reason — read them together to see how many attempts were made before bailing. 'message' and 'turn' entries carry no importance — they are the substance, always read them.\",\n 'Event types: assistant.connected/disconnected (mount + placement + whether the session was created or restored), assistant.popout/popin (window placement), driver.created/wired/unwired (which driver is live and why it stops/starts responding across a popout), state.changed (idle↔loading), turn.start/turn.end (turn boundary; turn.end carries durationMs), turn.retry (a recoverable in-turn retry — detail.reason plus attempt/maxAttempts; for malformed calls also finishMessage; for empty responses also the provider finishReason + thoughtsTokens + parts breakdown), turn.error (a turn failed or hit a guardrail — detail.reason is one of exception/malformed-function-call/empty-response/unknown-tool-limit/max-iterations/response-truncated/refusal/budget-exhausted, plus reason-specific diagnostics: attempts (for empty-response also finishReason + thoughtsTokens + a parts breakdown, distinguishing a thinking-only STOP from a truly empty turn), finishMessage, for response-truncated the model + maxTokens + outputTokens + tools, unknownTools (split into staleTools — real earlier this activation but retired by the current state or hidden behind an open exclusive fold — and hallucinatedTools — never advertised) + availableTools, iterations + limit, for budget-exhausted the budgetUsd + spentUsd figures reported by the proxy plus the resolved vendor, or name + message for exceptions), tool.failed (a tool threw), tool.unresolved (the model called a tool that could not be dispatched — detail.kind is folded/fold-hidden/stale/unknown, plus tool + agent and, for the counted kinds, the consecutive streak; the recurring lead-up to an unknown-tool-limit turn.error), subagent.started/completed/failed (the lifecycle of a `requestSubAgent` delegation — detail.agent names the sub-agent; these bracket the sub-agent turns that appear as kind:turn entries with an N-M `turnIndex`; subagent.failed also carries detail.reason, one of max_iterations/malformed_tool_call/empty_response/unknown_tool_limit/timeout/response_truncated/refusal/budget_exhausted; budget_exhausted is terminal for the PARENT turn too — the parent stops rather than calling the model again into the same wall), agent.handoff (routing; from=null is the initial activation), agent.pinned/unpinned (forced routing), provider.selected (model/provider for the upcoming turns), interaction.requested/resolved (blocking user widgets — explain quiet gaps; note that when a sub-agent opens a widget, detail.agent — and the agentName on the interaction message — is the HOST agent that owns the widget, NOT the sub-agent that asked, because widgets render and resolve on the host driver), context.updated/threshold-crossed (token + cost), context.condensed (a stale tool payload was collapsed out of the model-bound history by a `condenseWhen` declaration on the tool — detail.tool + toolCallId, target args|response, trigger (superseded:<key> or age:<n>), stubLen, and an estimated tokensSaved; stored history and this log keep the FULL payload, so the model-visible slice at any point is the full history minus the condensations recorded up to then), panel.toggled, attachment.added, file.read-failed, suggestions.failed.',\n 'Sub-agent meta events: a sub-agent\\'s own turn.retry/turn.error/tool.failed/tool.unresolved events are merged into this same timeline, tagged with `detail.subAgent` — a `\"<parent> › <sub-agent>\"` breadcrumb that composes when nested (e.g. `\"UI Builder › Planner › Grounding\"`) — and interleaved by their original timestamps within the subagent.started→completed/failed bracket. These are the per-attempt/per-failure signals that do NOT appear among the sub-agent\\'s (hoisted) messages: a malformed/empty attempt that gets retried produces no message, and the stale-vs-hallucinated split and streak counts live only on the event. A sub-agent\\'s high-volume, message-derivable events (turn.start/turn.end, provider.selected, context.updated) are intentionally NOT merged — read its hoisted messages for model/tokens/cost and turn-by-turn activity, and the bracketing subagent.* events for the run\\'s span.',\n \"`meta` holds context captured at export time: agentSummary (full agent configs), context (active model, token usage, session cost), activeDebugSnapshot (the active agent's `getDebugSnapshot()` taken fresh at export — reflects state NOW, which may have advanced beyond the last turn's agentSnapshot), debug (optional host-supplied debug state), host, and the export timestamp.\",\n 'To debug a failure: find the last turn.error or tool.failed, then read upward for the user message, the turn(s), and the agent/provider/state events that led into it.',\n]",
|
|
4904
|
+
"default": "[\n 'This is an exported debug log for the Genesis AI assistant. Read it top-to-bottom.',\n \"`sessionUsage` is what this session spent: `costUsd` (USD, provider-reported per request and summed, cache discounts already applied) plus the four TOKEN BUCKETS — `uncachedInputTokens`, `cacheReadTokens`, `cacheWriteTokens`, `outputTokens`. Those four are disjoint and safe to add up for a total-tokens figure; the per-message fields further down are NOT (see kind:'message'). Each bucket bills at a different rate — cache reads a fraction of uncached input, cache writes a premium, output highest — so a big token count against a small cost means the prompt was mostly cache hits, not a missing charge. It covers sub-agent turns and spend a compaction banked, so for the CONVERSATION it is the authoritative total: prefer it over re-summing the timeline, which can be short by whatever the ring buffers evicted. The same figures appear under `meta.context`. It is as current as the snapshot it came from: the assistant's own download stamps a fresh one, but a log stitched by another tool can carry an older one — compare `meta.timestamp` with the last timeline entry, and if it is well behind, read these totals as historical and fall back to summing the timeline. One scope caveat: it is derived from the transcript, so it excludes billed calls that produced no message (a blank or refused attempt that was retried — see kind:'turn'.`usage`). Summing the turns can therefore come out HIGHER than this, and the difference is exactly that discarded spend, not a double-count.\",\n \"What 'session' means for those figures: the CURRENT conversation under this session key (a host-supplied per-project id, or the element id + header title when the host supplies none) — which is not necessarily everything in `timeline`. It is re-derived from the live transcript, so it spans page loads only when the chat is being remembered, and a Clear resets it to zero. `timeline` is append-only regardless: it keeps every page load and the pre-Clear conversation, with the session.cleared event as the boundary. So on a long-lived log, read these totals as the latest conversation's and the earlier sections as history — not as a total of the whole file.\",\n '`timeline` is the entire session as one array, already sorted chronologically by `timestamp` (ISO 8601). Every entry has a `kind`.',\n 'Timestamps are millisecond-resolution; entries that share the same millisecond are ordered by a fixed kind rank (event, then turn, then message), which is a heuristic and may not reflect exact causal order within that millisecond — e.g. a user message and the turn it triggered, or a final assistant message and its turn.end event, can appear in either order depending on whether they landed in the same millisecond. Read the logical structure of a turn rather than over-interpreting the micro-ordering of co-timestamped entries of different kinds.',\n \"kind:'message' — the conversation. `role` is user/assistant/tool/system-event/synthetic-user; `agentName` says which agent produced it; `toolCalls`/`toolResult`/`interaction` carry tool and widget activity; `inputTokens`/`outputTokens`/`cost` are per-message LLM usage, where `inputTokens` is the WHOLE prompt for that request and `cacheReadTokens`/`cacheWriteTokens` BREAK IT DOWN rather than add to it — uncached input is `inputTokens` minus those two, and adding the cache fields to `inputTokens` counts the prompt twice. The cache fields are absent on providers that report no cache split (Gemini reports reads only, since implicit caching bills no write) and on messages persisted before they existed, so read them as 0 when missing. Each bucket bills at a different rate — cache reads a fraction of uncached input, cache writes a premium, output highest — so a large token count at a small cost means the prompt was mostly cache hits. `externalCostUsd` is any non-LLM cost a widget reported for its own external service calls (folded into the session cost total alongside `cost`). On model-produced assistant messages, `model` is the concrete model id that generated it (e.g. 'gemini-2.5-flash-lite') and `providerName` is the registry slot it resolved under (e.g. a tier name like 'high'/'low', or the default); together they attribute the message — and any tool calls it carries — to an exact model even across a mid-session vendor/tier switch, where one slot name can map to different models before and after the switch. Both are undefined on any entry that is NOT an LLM response: non-assistant roles (user/tool/system-event) and 'synthetic-user' echoes; assistant interaction/widget entries (empty content carrying an `interaction` — a rendered widget, not a model turn); driver-authored assistant fallbacks (the timeout, repeated-malformed-call, and empty-response apology messages); and messages restored from a session persisted before these fields existed. One partial case: on a genuine model turn whose provider exposes no `getStatus` (or reports no model), `providerName` is still set but `model` alone is undefined. A 'synthetic-user' message is a display-only echo of an interaction outcome (e.g. the answer a widget reported): it renders on the user's side of the chat and `agentName` is the agent that created it, but it is never sent to the LLM — so it has no matching 'turn' and the model learns the outcome only from the corresponding tool result.\",\n \"Sub-agent messages appear inline. When a tool delegates to a sub-agent (via `requestSubAgent`), the sub-agent's whole conversation — its own assistant/tool messages, each with their own `content`/`thinking`/`toolCalls`/`toolResult` and per-message `model`/`providerName`/`inputTokens`/`outputTokens`/`cacheReadTokens`/`cacheWriteTokens`/`cost` — is hoisted into the timeline as ordinary kind:'message' entries, interleaved by timestamp right after the tool call that spawned them (so you read the delegation top-to-bottom). A hoisted entry is marked: `subAgentDepth` is its delegation depth (1 for a sub-agent, 2 for a sub-agent's sub-agent, …), `subAgentOf` is the id of the parent tool call that spawned it (correlates it back even when two sub-agents run in one parent turn), `subAgentName` is the sub-agent's own name, and `agentName` is rewritten to a `\\\"<parent> › <sub-agent>\\\"` breadcrumb (composing when nested, e.g. `\\\"UI Builder › Planner › Grounding\\\"`). The sub-agent's per-LLM-call snapshots also surface as kind:'turn' entries with an N-M `turnIndex`, and subagent.started/completed (or subagent.failed) events bracket the run. Per-message `cost` on hoisted entries is already part of the session total (it is summed from the un-flattened history), so summing the top-level timeline does NOT double-count.\",\n \"kind:'turn' — one LLM call. `turnIndex` is a string: a top-level turn is the bare counter ('0', '1', …); a sub-agent's turns are numbered under the parent turn that activated them ('3-1', '3-2', …, and a nested sub-agent contributes '3-2-1', …), and `agentName` names the agent that ran the turn. `systemPrompt` and `toolNames` are what the model saw. A systemPrompt of '<repeated — identical to turn N>' was byte-identical to turn N and de-duplicated; the full prompt is shown whenever it changes (often because a stateful agent advanced), so prompt evolution is visible.\",\n \"kind:'turn'.`model`/`providerName`/`provider` — which model ran that call: the concrete model id, the registry slot it resolved under (a tier name like 'high'/'low', or the default), and the vendor. Recorded per CALL, so an agent whose `provider` selector varies by state — a flow that plans on a high tier and executes on a low one — has every step attributed, including calls that produced no message. `model` is the SERVING model where the provider reports one, so a turn answered by a server-side fallback names the model that answered rather than the one requested; it always matches the `model` on the message that call produced. Absent when the provider exposes no `getStatus` and the transport stamped nothing.\",\n \"kind:'turn'.`usage` — what that ONE call cost, in the same four-bucket + `costUsd` shape as `sessionUsage`. Absent while a call is in flight and on providers that report no usage. This is the SAME money as the message the call produced, not extra money: never add turn usage to message usage, and read a turn plus its message as one charge. Its distinct value is the calls that produced NO message — a blank or refused response is billed and then discarded before the retry, so the turn entry is the only record of that spend, and a turn with `usage` but no message after it is exactly that. `costUsd: 0` alongside a nonzero token count means the provider reported no price, not that the call was free.\",\n \"kind:'turn'.`agentSnapshot` — the active agent's own view of its internal state, captured at that turn. An agent opts into this by exposing a `getDebugSnapshot()` that returns JSON-serializable per-state info; stateful/flow agents wire it automatically, so you can watch a flow advance turn-by-turn (e.g. current step, cursor, collected fields, pending changes). Absent for agents that don't expose one.\",\n \"kind:'event' — a meta/lifecycle event. `type` names it (see below); `detail` carries structured data. `detail.placement` is the emitting UI instance: 'bubble' (collapsed), 'panel' (popped-out), or 'standalone'.\",\n \"Each 'event' also has an `importance`: 'high' (failures/limits — turn.error, tool.failed, subagent.failed, file.read-failed, suggestions.failed, context.threshold-crossed), 'normal' (session flow — connects, turns, retries, handoffs, agent/provider changes, interactions, sub-agent start/complete), or 'low' (skippable UI/bookkeeping noise — panel.toggled, attachment.added, driver.wired/unwired, context.updated, context.condensed). To skim, ignore importance:'low'; to triage a failure, filter to importance:'high' then read the nearby messages and turns. A 'high' turn.error is often preceded by one or more 'normal' turn.retry events for the same reason — read them together to see how many attempts were made before bailing. 'message' and 'turn' entries carry no importance — they are the substance, always read them.\",\n 'Event types: assistant.connected/disconnected (mount + placement + whether the session was created or restored), assistant.popout/popin (window placement), driver.created/wired/unwired (which driver is live and why it stops/starts responding across a popout), state.changed (idle↔loading), turn.start/turn.end (turn boundary; turn.end carries durationMs), turn.retry (a recoverable in-turn retry — detail.reason plus attempt/maxAttempts; for malformed calls also finishMessage; for empty responses also the provider finishReason + thoughtsTokens + parts breakdown), turn.error (a turn failed or hit a guardrail — detail.reason is one of exception/malformed-function-call/empty-response/unknown-tool-limit/max-iterations/response-truncated/refusal/budget-exhausted, plus reason-specific diagnostics: attempts (for empty-response also finishReason + thoughtsTokens + a parts breakdown, distinguishing a thinking-only STOP from a truly empty turn), finishMessage, for response-truncated the model + maxTokens + outputTokens + tools, unknownTools (split into staleTools — real earlier this activation but retired by the current state or hidden behind an open exclusive fold — and hallucinatedTools — never advertised) + availableTools, iterations + limit, for budget-exhausted the budgetUsd + spentUsd figures reported by the proxy plus the resolved vendor, or name + message for exceptions), tool.failed (a tool threw), tool.unresolved (the model called a tool that could not be dispatched — detail.kind is folded/fold-hidden/stale/unknown, plus tool + agent and, for the counted kinds, the consecutive streak; the recurring lead-up to an unknown-tool-limit turn.error), subagent.started/completed/failed (the lifecycle of a `requestSubAgent` delegation — detail.agent names the sub-agent; these bracket the sub-agent turns that appear as kind:turn entries with an N-M `turnIndex`; subagent.failed also carries detail.reason, one of max_iterations/malformed_tool_call/empty_response/unknown_tool_limit/timeout/response_truncated/refusal/budget_exhausted; budget_exhausted is terminal for the PARENT turn too — the parent stops rather than calling the model again into the same wall), agent.handoff (routing; from=null is the initial activation), agent.pinned/unpinned (forced routing), provider.selected (the resolved provider for the upcoming turns — detail.provider is the registry SLOT/tier name, detail.model the concrete model behind it and detail.vendor its vendor; emitted only when the slot CHANGES, so read the per-turn `model` for the model of any given call rather than assuming the nearest event still applies), interaction.requested/resolved (blocking user widgets — explain quiet gaps; note that when a sub-agent opens a widget, detail.agent — and the agentName on the interaction message — is the HOST agent that owns the widget, NOT the sub-agent that asked, because widgets render and resolve on the host driver), context.updated/threshold-crossed (token + cost), context.condensed (a stale tool payload was collapsed out of the model-bound history by a `condenseWhen` declaration on the tool — detail.tool + toolCallId, target args|response, trigger (superseded:<key> or age:<n>), stubLen, and an estimated tokensSaved; stored history and this log keep the FULL payload, so the model-visible slice at any point is the full history minus the condensations recorded up to then), panel.toggled, attachment.added, file.read-failed, suggestions.failed.',\n 'Sub-agent meta events: a sub-agent\\'s own turn.retry/turn.error/tool.failed/tool.unresolved events are merged into this same timeline, tagged with `detail.subAgent` — a `\"<parent> › <sub-agent>\"` breadcrumb that composes when nested (e.g. `\"UI Builder › Planner › Grounding\"`) — and interleaved by their original timestamps within the subagent.started→completed/failed bracket. These are the per-attempt/per-failure signals that do NOT appear among the sub-agent\\'s (hoisted) messages: a malformed/empty attempt that gets retried produces no message, and the stale-vs-hallucinated split and streak counts live only on the event. A sub-agent\\'s high-volume, message-derivable events (turn.start/turn.end, provider.selected, context.updated) are intentionally NOT merged — read its hoisted messages for model/tokens/cost and turn-by-turn activity, and the bracketing subagent.* events for the run\\'s span.',\n \"`meta` holds context captured at export time: agentSummary (full agent configs), context (active model, contextTokens/contextLimit/contextUsagePercent for the last call, and the session totals — sessionCostUsd, sessionTokensConsumed, and the four-bucket sessionUsage lifted to the top of this log), activeDebugSnapshot (the active agent's `getDebugSnapshot()` taken fresh at export — reflects state NOW, which may have advanced beyond the last turn's agentSnapshot), debug (optional host-supplied debug state), host, and the export timestamp.\",\n 'Note the two different scopes in `meta.context`: `contextTokens` is the prompt size of the LAST call (against `contextLimit`, the model context window), while `sessionUsage`/`sessionTokensConsumed` are cumulative BILLED throughput. Every turn resends the conversation, so the cumulative figure counts each turn’s prompt again in the next turn’s and is expected to dwarf the context size — that is not double-counting.',\n 'To debug a failure: find the last turn.error or tool.failed, then read upward for the user message, the turn(s), and the agent/provider/state events that led into it.',\n]",
|
|
4920
4905
|
"description": "Human/agent-facing guide emitted as the first key of the exported debug log,\nso whoever opens the JSON (often an AI agent) knows how to read it without\nreverse-engineering the shape. Kept here next to the event catalogue it\ndescribes — but proximity alone demonstrably did NOT keep the two in sync\n(`refusal` was missing from both reason lists for a whole release), so\n`debug-event-log.test.ts` now asserts that every `TurnFailureReason` and every\n`SubAgentFailureReason` is named here, and fails the build when one is added\nwithout a matching sentence. Enumerations below read as exhaustive and WILL be\ntrusted by an agent reading the JSON — keep them so."
|
|
4921
4906
|
}
|
|
4922
4907
|
],
|
|
@@ -5429,6 +5414,48 @@
|
|
|
5429
5414
|
"declarations": [],
|
|
5430
5415
|
"exports": []
|
|
5431
5416
|
},
|
|
5417
|
+
{
|
|
5418
|
+
"kind": "javascript-module",
|
|
5419
|
+
"path": "src/provider/ai-provider-switcher.ts",
|
|
5420
|
+
"declarations": [
|
|
5421
|
+
{
|
|
5422
|
+
"kind": "variable",
|
|
5423
|
+
"name": "AIProviderSwitcher",
|
|
5424
|
+
"description": "The DI token for the (AIProviderSwitcher:interface). Resolves a noop until the app\nregisters one."
|
|
5425
|
+
}
|
|
5426
|
+
],
|
|
5427
|
+
"exports": [
|
|
5428
|
+
{
|
|
5429
|
+
"kind": "js",
|
|
5430
|
+
"name": "AIProviderSwitcher",
|
|
5431
|
+
"declaration": {
|
|
5432
|
+
"name": "AIProviderSwitcher",
|
|
5433
|
+
"module": "src/provider/ai-provider-switcher.ts"
|
|
5434
|
+
}
|
|
5435
|
+
}
|
|
5436
|
+
]
|
|
5437
|
+
},
|
|
5438
|
+
{
|
|
5439
|
+
"kind": "javascript-module",
|
|
5440
|
+
"path": "src/provider/assistant-app-settings.ts",
|
|
5441
|
+
"declarations": [
|
|
5442
|
+
{
|
|
5443
|
+
"kind": "variable",
|
|
5444
|
+
"name": "AssistantAppSettingsProvider",
|
|
5445
|
+
"description": "The DI token for the (AssistantAppSettingsProvider:interface). Resolves a noop\nuntil the host registers one."
|
|
5446
|
+
}
|
|
5447
|
+
],
|
|
5448
|
+
"exports": [
|
|
5449
|
+
{
|
|
5450
|
+
"kind": "js",
|
|
5451
|
+
"name": "AssistantAppSettingsProvider",
|
|
5452
|
+
"declaration": {
|
|
5453
|
+
"name": "AssistantAppSettingsProvider",
|
|
5454
|
+
"module": "src/provider/assistant-app-settings.ts"
|
|
5455
|
+
}
|
|
5456
|
+
}
|
|
5457
|
+
]
|
|
5458
|
+
},
|
|
5432
5459
|
{
|
|
5433
5460
|
"kind": "javascript-module",
|
|
5434
5461
|
"path": "src/types/ai-chat-widget.ts",
|
|
@@ -6557,6 +6584,24 @@
|
|
|
6557
6584
|
],
|
|
6558
6585
|
"description": "`a + b`, per bucket, as a new object.\n\nUsed to lay a row's banked (pre-transcript) spend over what the live transcript\nproves. Pure rather than in-place because both operands are live state a caller\nmust not mutate."
|
|
6559
6586
|
},
|
|
6587
|
+
{
|
|
6588
|
+
"kind": "function",
|
|
6589
|
+
"name": "messageUsage",
|
|
6590
|
+
"return": {
|
|
6591
|
+
"type": {
|
|
6592
|
+
"text": "AggregateUsage | undefined"
|
|
6593
|
+
}
|
|
6594
|
+
},
|
|
6595
|
+
"parameters": [
|
|
6596
|
+
{
|
|
6597
|
+
"name": "m",
|
|
6598
|
+
"type": {
|
|
6599
|
+
"text": "ChatMessage"
|
|
6600
|
+
}
|
|
6601
|
+
}
|
|
6602
|
+
],
|
|
6603
|
+
"description": "The four buckets plus USD for ONE message — the per-message fields projected into\nthe disjoint, addable shape, or `undefined` when the message reports no usage at\nall (a user turn, a display-only reasoning/narration split, a provider that\nreports none).\n\nShallow by design: it does NOT recurse into `toolCalls[].subAgentTrace` and does\nNOT count `compaction.rolledUpUsage`, so it answers \"what did this one request\ncost\" rather than \"what did this message and everything under it cost\". Use\nsumUsage for the latter — passing a whole transcript through this one\nmessage at a time would silently drop both.\n\n`costUsd` folds in `externalCostUsd` (non-LLM spend a widget reported), matching\n`sumUsage`. It is `0` when the provider priced nothing, which is NOT a claim that\nthe call was free — see AggregateUsage; `UsageRow.costUsd` is the\nshape that keeps unpriced distinguishable, and is the right tool for a ledger."
|
|
6604
|
+
},
|
|
6560
6605
|
{
|
|
6561
6606
|
"kind": "function",
|
|
6562
6607
|
"name": "sumUsage",
|
|
@@ -6601,6 +6646,14 @@
|
|
|
6601
6646
|
"module": "src/utils/sum-usage.ts"
|
|
6602
6647
|
}
|
|
6603
6648
|
},
|
|
6649
|
+
{
|
|
6650
|
+
"kind": "js",
|
|
6651
|
+
"name": "messageUsage",
|
|
6652
|
+
"declaration": {
|
|
6653
|
+
"name": "messageUsage",
|
|
6654
|
+
"module": "src/utils/sum-usage.ts"
|
|
6655
|
+
}
|
|
6656
|
+
},
|
|
6604
6657
|
{
|
|
6605
6658
|
"kind": "js",
|
|
6606
6659
|
"name": "sumUsage",
|
|
@@ -8639,7 +8692,7 @@
|
|
|
8639
8692
|
"privacy": "private",
|
|
8640
8693
|
"return": {
|
|
8641
8694
|
"type": {
|
|
8642
|
-
"text": "
|
|
8695
|
+
"text": "TurnSnapshot"
|
|
8643
8696
|
}
|
|
8644
8697
|
},
|
|
8645
8698
|
"parameters": [
|
|
@@ -8668,7 +8721,7 @@
|
|
|
8668
8721
|
}
|
|
8669
8722
|
}
|
|
8670
8723
|
],
|
|
8671
|
-
"description": "Push one snapshot to the ring buffer. Called inside `runToolLoop` just\nbefore each LLM call — that's the latest point where the prompt, tool\nsurface, and agent state line up with what the model is about to see."
|
|
8724
|
+
"description": "Push one snapshot to the ring buffer. Called inside `runToolLoop` just\nbefore each LLM call — that's the latest point where the prompt, tool\nsurface, and agent state line up with what the model is about to see.\n\nReturns the pushed object so the caller can back-fill what only the response\nknows (`usage`). Mutating it after the fact is safe whether or not the ring\nbuffer has since evicted it — an evicted snapshot is simply no longer exported."
|
|
8672
8725
|
},
|
|
8673
8726
|
{
|
|
8674
8727
|
"kind": "method",
|
|
@@ -10178,333 +10231,114 @@
|
|
|
10178
10231
|
},
|
|
10179
10232
|
{
|
|
10180
10233
|
"kind": "javascript-module",
|
|
10181
|
-
"path": "src/components/
|
|
10234
|
+
"path": "src/components/settings-modal/index.ts",
|
|
10182
10235
|
"declarations": [],
|
|
10183
10236
|
"exports": [
|
|
10184
10237
|
{
|
|
10185
10238
|
"kind": "js",
|
|
10186
|
-
"name": "
|
|
10239
|
+
"name": "SettingsModalTemplate",
|
|
10187
10240
|
"declaration": {
|
|
10188
|
-
"name": "
|
|
10189
|
-
"
|
|
10241
|
+
"name": "SettingsModalTemplate",
|
|
10242
|
+
"module": "./settings-modal.template"
|
|
10243
|
+
}
|
|
10244
|
+
},
|
|
10245
|
+
{
|
|
10246
|
+
"kind": "js",
|
|
10247
|
+
"name": "type",
|
|
10248
|
+
"declaration": {
|
|
10249
|
+
"name": "type",
|
|
10250
|
+
"module": "./settings-modal.template"
|
|
10251
|
+
}
|
|
10252
|
+
},
|
|
10253
|
+
{
|
|
10254
|
+
"kind": "js",
|
|
10255
|
+
"name": "SettingsModalTab",
|
|
10256
|
+
"declaration": {
|
|
10257
|
+
"name": "SettingsModalTab",
|
|
10258
|
+
"module": "./settings-modal.template"
|
|
10259
|
+
}
|
|
10260
|
+
},
|
|
10261
|
+
{
|
|
10262
|
+
"kind": "js",
|
|
10263
|
+
"name": "settingsModalStyles",
|
|
10264
|
+
"declaration": {
|
|
10265
|
+
"name": "settingsModalStyles",
|
|
10266
|
+
"module": "./settings-modal.styles"
|
|
10190
10267
|
}
|
|
10191
10268
|
}
|
|
10192
10269
|
]
|
|
10193
10270
|
},
|
|
10194
10271
|
{
|
|
10195
10272
|
"kind": "javascript-module",
|
|
10196
|
-
"path": "src/components/
|
|
10273
|
+
"path": "src/components/settings-modal/settings-modal.styles.ts",
|
|
10197
10274
|
"declarations": [
|
|
10198
10275
|
{
|
|
10199
|
-
"kind": "
|
|
10200
|
-
"
|
|
10201
|
-
"name": "FoundationAiPopoutManager",
|
|
10202
|
-
"
|
|
10203
|
-
|
|
10204
|
-
|
|
10205
|
-
|
|
10206
|
-
|
|
10207
|
-
|
|
10208
|
-
|
|
10209
|
-
|
|
10210
|
-
|
|
10211
|
-
|
|
10212
|
-
|
|
10213
|
-
|
|
10214
|
-
|
|
10215
|
-
|
|
10216
|
-
|
|
10217
|
-
|
|
10218
|
-
|
|
10219
|
-
|
|
10220
|
-
|
|
10221
|
-
|
|
10276
|
+
"kind": "variable",
|
|
10277
|
+
"name": "settingsModalStyles",
|
|
10278
|
+
"default": "css`\n /*\n * Section headings come from the shared fragment the package also exports, so a host titling\n * its own slotted section applies the same rule rather than a copy of it.\n */\n ${assistantSettingsSectionTitleStyles}\n\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n }\n\n .settings-modal {\n --ai-tier-badge-bg-mix: 14%;\n --ai-tier-badge-text-lighten: 18%;\n }\n\n .settings-modal::part(dialog) {\n max-width: 620px;\n width: calc(100vw - 48px);\n max-height: calc(100vh - 48px);\n padding: 0;\n }\n\n .settings-modal::part(content) {\n display: flex;\n flex-direction: column;\n min-height: 0;\n padding: 0;\n width: 100%;\n }\n\n .settings-modal::part(top) {\n padding: calc(var(--design-unit) * 4px) calc(var(--design-unit) * 5px);\n border-bottom: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-modal::part(bottom) {\n padding: calc(var(--design-unit) * 4px) calc(var(--design-unit) * 5px);\n border-top: 1px solid var(--neutral-stroke-rest);\n border-bottom-left-radius: var(--card-border-radius, calc(var(--control-corner-radius) * 1px));\n border-bottom-right-radius: var(--card-border-radius, calc(var(--control-corner-radius) * 1px));\n background-color: var(--neutral-layer-2);\n }\n\n .settings-modal-header {\n display: flex;\n align-items: center;\n min-width: 0;\n }\n\n .settings-modal-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: calc(var(--design-unit) * 2px);\n color: var(--neutral-foreground-rest);\n }\n\n .settings-modal-content {\n display: flex;\n flex-direction: column;\n min-height: 0;\n flex: 1 1 auto;\n }\n\n .settings-modal-tabs::part(tablist) {\n border-bottom: 0;\n padding: 0 calc(var(--design-unit) * 5px);\n column-gap: calc(var(--design-unit) * 5px);\n }\n\n .settings-modal-tabs::part(activeIndicator) {\n height: 2px;\n }\n\n .settings-modal-tab {\n padding: 0;\n font-weight: 600;\n gap: 6px;\n }\n\n .settings-modal-tab[aria-selected='true'] {\n color: var(--neutral-foreground-rest);\n }\n\n .settings-modal-tabs::part(tabpanel) {\n border-top: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-modal-tab-panel {\n display: flex;\n flex-direction: column;\n min-height: 0;\n flex: 1 1 auto;\n padding: 0;\n border-radius: 0;\n }\n\n .settings-modal-tab-panel[hidden] {\n display: none !important;\n }\n\n .settings-modal-body {\n overflow-y: auto;\n padding: 0 calc(var(--design-unit) * 5px) calc(var(--design-unit) * 2px);\n max-height: min(60vh, 520px);\n }\n\n .settings-modal-section {\n padding: calc(var(--design-unit) * 5px) 0;\n border-bottom: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-modal-section:last-child {\n border-bottom: none;\n }\n\n /*\n * Only the spacing. Everything else about this heading comes from the exported fragment\n * above, which the assistant and its hosts share; margin is deliberately not in there,\n * since the gap below a heading depends on the layout around it.\n */\n .ai-settings-section-title {\n margin: 0 0 calc(var(--design-unit) * 3px);\n }\n\n .settings-modal-section-note {\n margin: calc(var(--design-unit) * -2px) 0 calc(var(--design-unit) * 3px);\n font-size: 12px;\n line-height: 1.5;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-modal-section-body {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 4px);\n }\n\n .settings-toggle-row {\n display: flex;\n align-items: flex-start;\n gap: calc(var(--design-unit) * 3px);\n padding: 0 0 calc(var(--design-unit) * 4px) 0;\n border-bottom: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-toggle-row:last-child {\n border-bottom: none;\n padding-bottom: calc(var(--design-unit) * 1px);\n }\n\n .settings-toggle-row.is-stacked {\n flex-direction: column;\n gap: calc(var(--design-unit) * 2px);\n }\n\n /*\n * For rows whose control is a button rather than a switch. The base row top-aligns, which suits\n * a switch (it lands level with the title), but a button is tall enough that top-aligning leaves\n * it above the title-plus-description block it acts on.\n */\n .settings-toggle-row.is-centered {\n align-items: center;\n }\n\n .settings-animation-list {\n display: flex;\n flex-direction: column;\n width: 100%;\n border: 1px solid var(--neutral-stroke-rest);\n border-radius: calc(var(--control-corner-radius) * 1.2px);\n padding: calc(var(--design-unit) * 2px);\n gap: calc(var(--design-unit) * 2px);\n }\n\n .settings-animation-list .settings-toggle-row {\n border: 0;\n }\n\n .settings-animation-category {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 4px);\n }\n\n .settings-animation-category-label {\n font-weight: 600;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-toggle-row + .settings-animation-category-label {\n border-top: 1px solid var(--neutral-stroke-rest);\n padding-top: calc(var(--design-unit) * 2px);\n }\n\n .settings-animation-option {\n padding: 0;\n margin: 0;\n }\n\n .settings-animation-option:last-child {\n border-bottom: none;\n padding-bottom: calc(var(--design-unit) * 2px);\n }\n\n .settings-toggle-text {\n flex: 1;\n min-width: 0;\n }\n\n .settings-toggle-title {\n font-size: 14px;\n font-weight: 500;\n color: var(--neutral-foreground-rest);\n }\n\n .settings-toggle-desc {\n font-size: 12px;\n color: var(--neutral-foreground-hint);\n line-height: 1.5;\n max-width: 92%;\n }\n\n .settings-toggle-control {\n flex: 0 0 auto;\n min-width: 0;\n }\n\n .settings-toggle-control-wide {\n width: 100%;\n max-width: 280px;\n }\n\n .settings-toggle-row.is-stacked .settings-toggle-desc {\n max-width: none;\n }\n\n .settings-toggle-row.is-stacked .settings-toggle-control-wide {\n width: 100%;\n max-width: none;\n }\n\n /*\n * Sub-heading over the provider toggle group. Unlike the section headings it sits INSIDE\n * .settings-modal-section-body, so the parent's 4-unit flex gap already separates it from the\n * first toggle — and flex does not collapse margins, so the shared rule's 3-unit margin-bottom\n * would add to that gap rather than replace it, leaving the label adrift from the rows it\n * names. Zero the margin and pull back 2 of the 4 gap units, expressed in the same token so it\n * tracks if that gap changes.\n */\n .settings-app-toggles-title {\n margin: 0 0 calc(var(--design-unit) * -2px);\n }\n\n .settings-app-toggle-block {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 1px);\n }\n\n .settings-toggle-hint {\n font-size: 12px;\n color: var(--neutral-foreground-hint);\n line-height: 1.4;\n padding-left: calc(var(--design-unit) * 1px);\n font-style: italic;\n }\n\n /*\n * The budget meter (GENC-1464) is the context indicator's money sibling and\n * shares its row anatomy 1:1, so the budget classes JOIN these rules rather\n * than restating them — one place to restyle the header/label/figures shape,\n * and the two indicators cannot drift apart. Design-system tokens only, and\n * unfallbacked: every token here ships a DS default, so a var(--x, y)\n * fallback would be dead code that hides a broken token name (#2411/#2436\n * review rule, pinned by settings-modal.styles.test.ts).\n */\n .settings-context-header,\n .settings-budget-header {\n display: flex;\n justify-content: space-between;\n gap: calc(var(--design-unit) * 2px);\n margin-bottom: calc(var(--design-unit) * 2px);\n font-size: 12px;\n }\n\n .settings-context-label,\n .settings-budget-label {\n color: var(--neutral-foreground-hint);\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n }\n\n .settings-context-tokens,\n .settings-budget-figures {\n color: var(--neutral-foreground-rest);\n }\n\n /* Freshness footer (GENC-1464): refresh button + label under the vendor\n rows, left-aligned — a footnote to the figures above it. The button's\n inline padding is pinned and cancelled by the container margin so the\n ICON GLYPH (not the button box) sits flush with the budget labels'\n left edge, whatever the density tokens say. */\n .settings-budget-toolbar {\n display: flex;\n justify-content: flex-start;\n align-items: center;\n gap: 4px;\n margin-inline-start: -4px;\n }\n\n .settings-budget-refresh::part(control) {\n padding-inline: 4px;\n }\n\n .settings-budget-updated {\n color: var(--neutral-foreground-hint);\n font-size: 11px;\n }\n\n /*\n * ONE rhythm for every meter row. The outer wrapper holds the context\n * indicator and the budget meter; the inner one holds the budget meter's\n * vendor rows — and both gap by the same 2 units (half the section body's 4)\n * so that visually identical meter rows are evenly spaced whatever mix of\n * them is on screen. Without the wrapper the context row inherits the body's\n * 4-unit gap while the vendor rows keep 2, and three identical-looking rows\n * read as an uneven 4/2/2. The wrapper renders only when at least one meter\n * does — see settingsUsageMetersTemplate for why an always-on one would cost\n * a stray gap.\n */\n .settings-usage-meters,\n .settings-budget-usage {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 2px);\n }\n\n .settings-current-build,\n .settings-lifetime-usage {\n background: var(--neutral-layer-2);\n border: 1px solid var(--neutral-stroke-rest);\n border-radius: calc(var(--control-corner-radius) * 1.5px);\n padding: calc(var(--design-unit) * 4px);\n margin: calc(var(--design-unit) * 3px) 0;\n }\n\n /*\n * Deliberately quieter than the live block: no pulsing badge and no accent, so the eye lands\n * on what is being built now — which is why that block leads the tab and this one follows,\n * under the history heading whose rows it totals.\n */\n .settings-lifetime-usage-top {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: calc(var(--design-unit) * 2px);\n margin-bottom: calc(var(--design-unit) * 3px);\n }\n\n .settings-lifetime-label {\n font-size: 10px;\n line-height: 1;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-current-build-top {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: calc(var(--design-unit) * 2px);\n margin-bottom: calc(var(--design-unit) * 3px);\n }\n\n /*\n * Optically centring these 10px caps against the 14px project name beside them. Flex offers\n * only two alignments and neither lands it, because a box centre and a text baseline are\n * different lines:\n * - align-items: center sits the badge baseline about 1.2px high\n * - align-items: baseline matches baselines, but the caps then read as bottom-aligned\n * against the name's ascenders, so the badge looks low\n * The eye wants the midpoint, so: centre the boxes, then translate down by the ~1px of\n * overshoot. This is a nudge, but it corrects a fixed relationship between two font sizes\n * rather than some neighbouring element's layout, so unlike a margin tuned to a sibling it\n * cannot rot when that sibling changes. In em, so it tracks the badge text.\n *\n * display: block, not inline-flex: a flex container has no text baseline of its own and\n * synthesizes one from its first child, which here is the dot, an empty span. As a block box\n * the badge takes the baseline of its first line, i.e. the text.\n */\n .settings-live-badge {\n display: block;\n font-size: 10px;\n line-height: 1;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--accent-fill-rest);\n white-space: nowrap;\n transform: translateY(0.1em);\n }\n\n .settings-live-dot {\n display: inline-block;\n width: 7px;\n height: 7px;\n\n /* Replaces the flex gap the badge no longer has. */\n margin-right: calc(var(--design-unit) * 1px);\n\n /* Centres the dot on the text beside it without disturbing that text's baseline. */\n vertical-align: middle;\n border-radius: 50%;\n background: var(--accent-fill-rest);\n animation: settings-live-pulse 1.6s ease-out infinite;\n }\n\n @keyframes settings-live-pulse {\n 0% {\n box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-fill-rest) 55%, transparent);\n }\n\n 70% {\n box-shadow: 0 0 0 7px transparent;\n }\n\n 100% {\n box-shadow: 0 0 0 0 transparent;\n }\n }\n\n .settings-current-build-name {\n font-size: 14px;\n line-height: 1;\n font-weight: 600;\n }\n\n /*\n * Cost and the token buckets side by side: one number in its own box, the four buckets\n * sharing the box next to it. Stretch, so the two are the same height however tall the 22px\n * cost value makes the left one.\n */\n .settings-usage-row {\n display: flex;\n flex-wrap: wrap;\n align-items: stretch;\n gap: calc(var(--design-unit) * 3px);\n margin-bottom: calc(var(--design-unit) * 3px);\n }\n\n .settings-usage-row-tokens {\n display: flex;\n flex: 1 1 auto;\n min-width: 0;\n }\n\n .settings-build-stat {\n min-width: 0;\n background: var(--neutral-layer-1);\n border: 1px solid var(--neutral-stroke-rest);\n border-radius: calc(var(--control-corner-radius) * 1px);\n padding: calc(var(--design-unit) * 3px);\n }\n\n .settings-build-stat-label {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-build-stat-value {\n font-size: 22px;\n font-weight: 700;\n margin-top: calc(var(--design-unit) * 1px);\n color: var(--neutral-foreground-rest);\n }\n\n .settings-build-stat-value .prefix,\n .settings-build-stat-value .suffix {\n color: var(--accent-fill-rest);\n }\n\n /*\n * Per-bucket token split, beneath the headline cost. Small paired label/value cells\n * rather than four more stat cards: they are the detail behind the cost above, so they\n * have to read as subordinate to it rather than compete with it. The four buckets ARE\n * the token figure now — there is no merged total anywhere for them to break down.\n */\n .settings-token-breakdown {\n display: flex;\n flex-direction: column;\n\n /*\n * Tight against the buckets below. One design unit rather than two, because each bucket\n * separates its own label from its value by only 2px — at two units the title sat four\n * times further from the bucket labels than they sit from their own numbers, which read\n * as a gap between unrelated blocks instead of a heading over its content.\n */\n gap: calc(var(--design-unit) * 1px);\n margin-bottom: calc(var(--design-unit) * 3px);\n padding: calc(var(--design-unit) * 2px) calc(var(--design-unit) * 3px);\n background: var(--neutral-layer-1);\n border: 1px solid var(--neutral-stroke-rest);\n border-radius: calc(var(--control-corner-radius) * 1px);\n }\n\n /*\n * Titles the box, because nothing else in it named the unit. Same styling and position as\n * the cost box's label, so two boxes sitting side by side are titled the same way; the\n * hierarchy against the bucket labels comes from position, not a second type size.\n */\n .settings-token-breakdown-label {\n font-size: 10px;\n line-height: 1;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-token-buckets {\n display: flex;\n flex-wrap: wrap;\n gap: calc(var(--design-unit) * 4px);\n }\n\n .settings-token-bucket {\n display: flex;\n\n /*\n * min-content (not 0) so a bucket cannot be shrunk narrower than its own unbreakable label.\n * With the label set to nowrap, a zero minimum would overflow it into the next column instead\n * of wrapping — so the container's flex-wrap takes over and moves a bucket to a second row,\n * which is the degradation we want when the modal is dragged narrow.\n */\n min-width: min-content;\n flex-direction: column;\n gap: 2px;\n }\n\n .settings-token-bucket-label {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--neutral-foreground-hint);\n\n /*\n * One line, always. The rate marker is a separate inline box after collapsible whitespace, so\n * a wrappable label gives it a break opportunity of its own — in a narrow column it orphaned\n * onto line 2, which also pushed that bucket's value a line below the other three and broke\n * the row of figures. nowrap removes every break opportunity in the label, the space before\n * the marker included, so no glue character is needed.\n */\n white-space: nowrap;\n }\n\n .settings-token-bucket-value {\n font-size: 13px;\n font-weight: 600;\n color: var(--neutral-foreground-rest);\n }\n\n /*\n * The price-direction marker on a cache bucket's label — down for reads (a fraction of the\n * uncached input rate), up for writes (a premium over it). Three tiers, so a bucket with no\n * marker is the reference rate rather than an unlabelled fourth case.\n *\n * Carried by the label rather than the value, which is what this used to do: cache reads are\n * usually the largest bucket by a wide margin in an agentic session, so the value was muted to\n * stop the biggest number reading as the dominant cost driver. That priced the treatment to the\n * wrong thing — a dimmed 0 (every Gemini cache write) looked disabled next to a normal 0, and a\n * rate is a property of the bucket, not of this turn's figure.\n *\n * Sized down and nudged up rather than tinted: the label is already the hint colour, so a\n * dimmer marker would vanish and a brighter one would out-shout the word it qualifies.\n */\n .settings-token-bucket-rate {\n font-size: 8px;\n line-height: 1;\n vertical-align: 0.15em;\n letter-spacing: 0;\n }\n\n /*\n * Usage-row overrides. Placed after the base rules they refine rather than up beside\n * .settings-usage-row itself, because stylelint's no-descending-specificity rejects a\n * compound selector appearing before the plain one it overrides.\n */\n\n /* Sized by its content; the buckets take the rest, since four cells need the width. */\n .settings-usage-row > .settings-build-stat {\n flex: 0 1 auto;\n }\n\n .settings-usage-row .settings-token-breakdown {\n flex: 1 1 auto;\n\n /* The row owns the spacing now; this centres the column against the taller cost box. */\n justify-content: center;\n margin-bottom: 0;\n }\n\n /*\n * Basis auto, not 0: a zero basis splits the row into four equal columns, so CACHE WRITE is\n * squeezed exactly as hard as INPUT despite being twice the label. Sizing from content gives the\n * long labels the room their text needs and lets the short ones concede it, which is what makes\n * white-space: nowrap above safe — every column starts at least as wide as its own content,\n * then shares the slack. Still grows and shrinks, so the four stay flush edge to edge.\n */\n .settings-usage-row .settings-token-bucket {\n flex: 1 1 auto;\n }\n\n .settings-model-tags {\n display: flex;\n flex-wrap: wrap;\n gap: calc(var(--design-unit) * 2px);\n }\n\n .settings-model-tag {\n font-size: 11px;\n font-weight: 600;\n padding: 3px 9px;\n border-radius: 20px;\n font-family: ui-monospace, monospace;\n border: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-model-tag,\n .settings-cost-history-icon {\n --model-tag-color: var(--neutral-foreground-rest);\n\n background: color-mix(\n in srgb,\n var(--model-tag-color) var(--ai-tier-badge-bg-mix),\n var(--neutral-layer-1)\n );\n border-color: color-mix(in srgb, var(--model-tag-color) 20%, var(--neutral-layer-1));\n color: color-mix(in srgb, var(--model-tag-color), white var(--ai-tier-badge-text-lighten));\n }\n\n .settings-cost-history-title {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--neutral-foreground-hint);\n font-weight: 600;\n margin: calc(var(--design-unit) * 4px) 0 calc(var(--design-unit) * 2px);\n }\n\n /*\n * The heading labels the lifetime card as well as the rows, so the card gives up its own top\n * margin and the gap becomes the heading's alone. Adjacent siblings collapse to the LARGER of\n * the two margins, so leaving both would space the caps 3 units off the block they label while\n * the rows below sit at 2 — reading as though the heading belonged to neither.\n */\n .settings-cost-history-title + .settings-lifetime-usage {\n margin-top: 0;\n }\n\n .settings-cost-history {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 2px);\n padding-bottom: calc(var(--design-unit) * 2px);\n }\n\n .settings-cost-history-icon {\n flex: 0 0 auto;\n width: 36px;\n height: 36px;\n border-radius: calc(var(--control-corner-radius) * 1px);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n font-weight: 700;\n border: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-cost-history-row {\n display: flex;\n flex-direction: column;\n background: var(--neutral-layer-1);\n border: 1px solid var(--neutral-stroke-rest);\n border-radius: calc(var(--control-corner-radius) * 1.5px);\n padding: calc(var(--design-unit) * 4px);\n }\n\n .settings-cost-history-row-content {\n display: flex;\n align-items: flex-start;\n gap: calc(var(--design-unit) * 2px);\n }\n\n /*\n * All of these carry a ?hidden binding, and all declare display: flex — which silently beat the\n * UA [hidden] { display: none } rule, because author-origin declarations outrank user-agent\n * origin whatever the specificity. Without this, showTokens: false still rendered the full\n * breakdown in the lifetime block, the live block and every history row, and an empty row list\n * still occupied its padding under the lifetime total. Sibling elements that hide correctly do\n * so only by declaring no display at all. Same treatment as .settings-modal-tab-panel[hidden]\n * near the top of this file.\n */\n .settings-usage-row-tokens[hidden],\n .settings-cost-history[hidden],\n .settings-cost-history-row-content[hidden] {\n display: none !important;\n }\n\n /*\n * The buckets inside a history row drop the panel treatment they carry in the summary\n * blocks — the row is already a bordered card, and a second box inside it reads as a\n * nested panel. The adjacent-sibling rule above supplies the separator instead.\n */\n .settings-cost-history-row-breakdown .settings-token-breakdown {\n flex: 1 1 auto;\n margin-bottom: 0;\n padding: 0;\n background: none;\n border: none;\n }\n\n .settings-cost-history-row-content + .settings-cost-history-row-content {\n border-top: 1px solid var(--neutral-stroke-rest);\n margin-top: calc(var(--design-unit) * 2px);\n padding-top: calc(var(--design-unit) * 2px);\n }\n\n .settings-cost-history-row-body {\n flex: 1 1 auto;\n min-width: 0;\n display: flex;\n gap: calc(var(--design-unit) * 2px);\n justify-content: space-between;\n }\n\n /*\n * Holds the cost and the delete button as one centred pair. The button used to be a sibling\n * of the whole row body, kept in place by a -2px nudge tuned for when the metrics column had\n * two lines (cost plus a merged token total). Dropping that second line left the nudge\n * compensating for nothing. Centring the two against each other needs no magic number and\n * cannot drift again if the metrics content changes.\n *\n * NB this rule previously set align-items with no display:flex, so it had no effect at all.\n */\n .settings-cost-history-row-right {\n display: flex;\n align-items: center;\n gap: calc(var(--design-unit) * 1px);\n flex: 0 0 auto;\n }\n\n .settings-cost-history-row-cost,\n .settings-cost-history-row-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--neutral-foreground-rest);\n min-width: 0;\n }\n\n .settings-cost-history-row-metrics {\n display: flex;\n flex-direction: column;\n flex: 0 0 auto;\n font-size: 13px;\n font-family: ui-monospace, monospace;\n color: var(--neutral-foreground-rest);\n white-space: nowrap;\n }\n\n .settings-cost-history-row-date {\n font-size: 12px;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-cost-history-delete {\n flex: 0 0 auto;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-cost-history-delete:hover {\n color: var(--error-color);\n }\n\n .settings-cost-history ::slotted(*) {\n display: block;\n }\n\n .settings-modal-footer {\n width: 100%;\n }\n\n .settings-done-button {\n margin-left: auto;\n }\n\n .settings-modal-footer-actions {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: calc(var(--design-unit) * 2px);\n width: 100%;\n }\n\n .settings-disclaimer {\n font-size: 12px;\n color: var(--neutral-foreground-hint);\n max-width: 60%;\n line-height: 1.4;\n }\n\n /*\n * Inline spinner shown in the \"Download agent log\" button while the log builds\n * (GENC-1351 §5.8) — the lifetime-stitch path is an async provider round-trip.\n * Sized to the button label and tinted with currentColor so it tracks the\n * button's text colour in every appearance / theme.\n */\n [part='download-button'] .download-spinner {\n display: inline-block;\n width: 12px;\n height: 12px;\n margin-right: calc(var(--design-unit) * 1px);\n vertical-align: -1px;\n border: 2px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: download-spin 0.6s linear infinite;\n }\n\n @keyframes download-spin {\n to {\n transform: rotate(360deg);\n }\n }\n`",
|
|
10279
|
+
"description": "Styles for the assistant settings modal (tabs, sections, toggles, cost summary)."
|
|
10280
|
+
}
|
|
10281
|
+
],
|
|
10282
|
+
"exports": [
|
|
10283
|
+
{
|
|
10284
|
+
"kind": "js",
|
|
10285
|
+
"name": "settingsModalStyles",
|
|
10286
|
+
"declaration": {
|
|
10287
|
+
"name": "settingsModalStyles",
|
|
10288
|
+
"module": "src/components/settings-modal/settings-modal.styles.ts"
|
|
10289
|
+
}
|
|
10290
|
+
}
|
|
10291
|
+
]
|
|
10292
|
+
},
|
|
10293
|
+
{
|
|
10294
|
+
"kind": "javascript-module",
|
|
10295
|
+
"path": "src/components/settings-modal/settings-modal.template.ts",
|
|
10296
|
+
"declarations": [
|
|
10297
|
+
{
|
|
10298
|
+
"kind": "function",
|
|
10299
|
+
"name": "SettingsModalTemplate",
|
|
10300
|
+
"return": {
|
|
10301
|
+
"type": {
|
|
10302
|
+
"text": "ViewTemplate<FoundationAiAssistant>"
|
|
10303
|
+
}
|
|
10304
|
+
},
|
|
10305
|
+
"parameters": [
|
|
10222
10306
|
{
|
|
10223
|
-
"
|
|
10224
|
-
"name": "dockProvider",
|
|
10307
|
+
"name": "designSystemPrefix",
|
|
10225
10308
|
"type": {
|
|
10226
|
-
"text": "
|
|
10227
|
-
}
|
|
10228
|
-
|
|
10229
|
-
|
|
10230
|
-
|
|
10309
|
+
"text": "string"
|
|
10310
|
+
}
|
|
10311
|
+
}
|
|
10312
|
+
],
|
|
10313
|
+
"description": "Modal shell for assistant settings — Configuration and Usage tabs, section slots for\napp-specific UI, and built-in chat-bot toggles."
|
|
10314
|
+
}
|
|
10315
|
+
],
|
|
10316
|
+
"exports": [
|
|
10317
|
+
{
|
|
10318
|
+
"kind": "js",
|
|
10319
|
+
"name": "SettingsModalTemplate",
|
|
10320
|
+
"declaration": {
|
|
10321
|
+
"name": "SettingsModalTemplate",
|
|
10322
|
+
"module": "src/components/settings-modal/settings-modal.template.ts"
|
|
10323
|
+
}
|
|
10324
|
+
}
|
|
10325
|
+
]
|
|
10326
|
+
},
|
|
10327
|
+
{
|
|
10328
|
+
"kind": "javascript-module",
|
|
10329
|
+
"path": "src/state/persistence/build-timeline-entries.ts",
|
|
10330
|
+
"declarations": [
|
|
10331
|
+
{
|
|
10332
|
+
"kind": "function",
|
|
10333
|
+
"name": "buildTimelineEntries",
|
|
10334
|
+
"return": {
|
|
10335
|
+
"type": {
|
|
10336
|
+
"text": "DiagnosticEntry[]"
|
|
10337
|
+
}
|
|
10338
|
+
},
|
|
10339
|
+
"parameters": [
|
|
10231
10340
|
{
|
|
10232
|
-
"
|
|
10233
|
-
"name": "isDocked",
|
|
10234
|
-
"type": {
|
|
10235
|
-
"text": "boolean"
|
|
10236
|
-
},
|
|
10237
|
-
"privacy": "private",
|
|
10238
|
-
"default": "false"
|
|
10239
|
-
},
|
|
10240
|
-
{
|
|
10241
|
-
"kind": "field",
|
|
10242
|
-
"name": "unsubBus",
|
|
10243
|
-
"type": {
|
|
10244
|
-
"text": "() => void | undefined"
|
|
10245
|
-
},
|
|
10246
|
-
"privacy": "private"
|
|
10247
|
-
},
|
|
10248
|
-
{
|
|
10249
|
-
"kind": "method",
|
|
10250
|
-
"name": "findAssistant",
|
|
10251
|
-
"privacy": "private",
|
|
10252
|
-
"return": {
|
|
10253
|
-
"type": {
|
|
10254
|
-
"text": "HTMLElement | null"
|
|
10255
|
-
}
|
|
10256
|
-
},
|
|
10257
|
-
"description": "Locate the assistant element currently slotted into the bubble."
|
|
10258
|
-
},
|
|
10259
|
-
{
|
|
10260
|
-
"kind": "method",
|
|
10261
|
-
"name": "adoptAssistant",
|
|
10262
|
-
"return": {
|
|
10263
|
-
"type": {
|
|
10264
|
-
"text": "void"
|
|
10265
|
-
}
|
|
10266
|
-
},
|
|
10267
|
-
"parameters": [
|
|
10268
|
-
{
|
|
10269
|
-
"name": "el",
|
|
10270
|
-
"type": {
|
|
10271
|
-
"text": "HTMLElement"
|
|
10272
|
-
}
|
|
10273
|
-
},
|
|
10274
|
-
{
|
|
10275
|
-
"name": "docked",
|
|
10276
|
-
"type": {
|
|
10277
|
-
"text": "boolean"
|
|
10278
|
-
}
|
|
10279
|
-
}
|
|
10280
|
-
],
|
|
10281
|
-
"description": "Register an externally-created assistant element and its docked state. For\nsingle-element hosts that create the assistant directly in a layout pane (rather\nthan statically in the bubble), so the manager tracks the one element, whether it's\ncurrently docked (for pop-in re-homing), reflects the right `popout-mode` on it\n(drives the header button), and hides the empty bubble."
|
|
10282
|
-
},
|
|
10283
|
-
{
|
|
10284
|
-
"kind": "method",
|
|
10285
|
-
"name": "syncBubbleVisibility",
|
|
10286
|
-
"privacy": "private",
|
|
10287
|
-
"return": {
|
|
10288
|
-
"type": {
|
|
10289
|
-
"text": "void"
|
|
10290
|
-
}
|
|
10291
|
-
},
|
|
10292
|
-
"description": "Hide the floating bubble unless it currently contains the assistant."
|
|
10293
|
-
},
|
|
10294
|
-
{
|
|
10295
|
-
"kind": "method",
|
|
10296
|
-
"name": "canDockChanged"
|
|
10297
|
-
},
|
|
10298
|
-
{
|
|
10299
|
-
"kind": "method",
|
|
10300
|
-
"name": "registerDockProvider",
|
|
10301
|
-
"return": {
|
|
10302
|
-
"type": {
|
|
10303
|
-
"text": "void"
|
|
10304
|
-
}
|
|
10305
|
-
},
|
|
10306
|
-
"parameters": [
|
|
10307
|
-
{
|
|
10308
|
-
"name": "provider",
|
|
10309
|
-
"type": {
|
|
10310
|
-
"text": "AiDockProvider"
|
|
10311
|
-
}
|
|
10312
|
-
}
|
|
10313
|
-
]
|
|
10314
|
-
},
|
|
10315
|
-
{
|
|
10316
|
-
"kind": "method",
|
|
10317
|
-
"name": "deregisterDockProvider",
|
|
10318
|
-
"return": {
|
|
10319
|
-
"type": {
|
|
10320
|
-
"text": "void"
|
|
10321
|
-
}
|
|
10322
|
-
}
|
|
10323
|
-
},
|
|
10324
|
-
{
|
|
10325
|
-
"kind": "method",
|
|
10326
|
-
"name": "collapseIfDocked",
|
|
10327
|
-
"return": {
|
|
10328
|
-
"type": {
|
|
10329
|
-
"text": "Promise<void>"
|
|
10330
|
-
}
|
|
10331
|
-
},
|
|
10332
|
-
"description": "If the assistant is currently docked, collapses it back into the bubble.\nAwait this in `onBeforeNavButtonClick` to ensure cleanup before navigation."
|
|
10333
|
-
}
|
|
10334
|
-
],
|
|
10335
|
-
"superclass": {
|
|
10336
|
-
"name": "GenesisElement",
|
|
10337
|
-
"package": "@genesislcap/web-core"
|
|
10338
|
-
},
|
|
10339
|
-
"tagName": "foundation-ai-popout-manager",
|
|
10340
|
-
"customElement": true
|
|
10341
|
-
},
|
|
10342
|
-
{
|
|
10343
|
-
"kind": "function",
|
|
10344
|
-
"name": "isAiAssistantDocked",
|
|
10345
|
-
"return": {
|
|
10346
|
-
"type": {
|
|
10347
|
-
"text": "boolean"
|
|
10348
|
-
}
|
|
10349
|
-
},
|
|
10350
|
-
"description": "True when the assistant is active in the layout panel (docked) rather than the bubble."
|
|
10351
|
-
},
|
|
10352
|
-
{
|
|
10353
|
-
"kind": "function",
|
|
10354
|
-
"name": "getAiPopoutManager",
|
|
10355
|
-
"return": {
|
|
10356
|
-
"type": {
|
|
10357
|
-
"text": "FoundationAiPopoutManager | undefined"
|
|
10358
|
-
}
|
|
10359
|
-
},
|
|
10360
|
-
"description": "Returns the active `FoundationAiPopoutManager` instance, or `undefined` if none is mounted.\nImport this in pages to call `registerDockProvider` / `deregisterDockProvider`."
|
|
10361
|
-
}
|
|
10362
|
-
],
|
|
10363
|
-
"exports": [
|
|
10364
|
-
{
|
|
10365
|
-
"kind": "js",
|
|
10366
|
-
"name": "FoundationAiPopoutManager",
|
|
10367
|
-
"declaration": {
|
|
10368
|
-
"name": "FoundationAiPopoutManager",
|
|
10369
|
-
"module": "src/components/popout-manager/popout-manager.ts"
|
|
10370
|
-
}
|
|
10371
|
-
},
|
|
10372
|
-
{
|
|
10373
|
-
"kind": "custom-element-definition",
|
|
10374
|
-
"name": "foundation-ai-popout-manager",
|
|
10375
|
-
"declaration": {
|
|
10376
|
-
"name": "FoundationAiPopoutManager",
|
|
10377
|
-
"module": "src/components/popout-manager/popout-manager.ts"
|
|
10378
|
-
}
|
|
10379
|
-
},
|
|
10380
|
-
{
|
|
10381
|
-
"kind": "js",
|
|
10382
|
-
"name": "isAiAssistantDocked",
|
|
10383
|
-
"declaration": {
|
|
10384
|
-
"name": "isAiAssistantDocked",
|
|
10385
|
-
"module": "src/components/popout-manager/popout-manager.ts"
|
|
10386
|
-
}
|
|
10387
|
-
},
|
|
10388
|
-
{
|
|
10389
|
-
"kind": "js",
|
|
10390
|
-
"name": "getAiPopoutManager",
|
|
10391
|
-
"declaration": {
|
|
10392
|
-
"name": "getAiPopoutManager",
|
|
10393
|
-
"module": "src/components/popout-manager/popout-manager.ts"
|
|
10394
|
-
}
|
|
10395
|
-
}
|
|
10396
|
-
]
|
|
10397
|
-
},
|
|
10398
|
-
{
|
|
10399
|
-
"kind": "javascript-module",
|
|
10400
|
-
"path": "src/components/settings-modal/index.ts",
|
|
10401
|
-
"declarations": [],
|
|
10402
|
-
"exports": [
|
|
10403
|
-
{
|
|
10404
|
-
"kind": "js",
|
|
10405
|
-
"name": "SettingsModalTemplate",
|
|
10406
|
-
"declaration": {
|
|
10407
|
-
"name": "SettingsModalTemplate",
|
|
10408
|
-
"module": "./settings-modal.template"
|
|
10409
|
-
}
|
|
10410
|
-
},
|
|
10411
|
-
{
|
|
10412
|
-
"kind": "js",
|
|
10413
|
-
"name": "type",
|
|
10414
|
-
"declaration": {
|
|
10415
|
-
"name": "type",
|
|
10416
|
-
"module": "./settings-modal.template"
|
|
10417
|
-
}
|
|
10418
|
-
},
|
|
10419
|
-
{
|
|
10420
|
-
"kind": "js",
|
|
10421
|
-
"name": "SettingsModalTab",
|
|
10422
|
-
"declaration": {
|
|
10423
|
-
"name": "SettingsModalTab",
|
|
10424
|
-
"module": "./settings-modal.template"
|
|
10425
|
-
}
|
|
10426
|
-
},
|
|
10427
|
-
{
|
|
10428
|
-
"kind": "js",
|
|
10429
|
-
"name": "settingsModalStyles",
|
|
10430
|
-
"declaration": {
|
|
10431
|
-
"name": "settingsModalStyles",
|
|
10432
|
-
"module": "./settings-modal.styles"
|
|
10433
|
-
}
|
|
10434
|
-
}
|
|
10435
|
-
]
|
|
10436
|
-
},
|
|
10437
|
-
{
|
|
10438
|
-
"kind": "javascript-module",
|
|
10439
|
-
"path": "src/components/settings-modal/settings-modal.styles.ts",
|
|
10440
|
-
"declarations": [
|
|
10441
|
-
{
|
|
10442
|
-
"kind": "variable",
|
|
10443
|
-
"name": "settingsModalStyles",
|
|
10444
|
-
"default": "css`\n /*\n * Section headings come from the shared fragment the package also exports, so a host titling\n * its own slotted section applies the same rule rather than a copy of it.\n */\n ${assistantSettingsSectionTitleStyles}\n\n *,\n *::before,\n *::after {\n box-sizing: border-box;\n }\n\n .settings-modal {\n --ai-tier-badge-bg-mix: 14%;\n --ai-tier-badge-text-lighten: 18%;\n }\n\n .settings-modal::part(dialog) {\n max-width: 620px;\n width: calc(100vw - 48px);\n max-height: calc(100vh - 48px);\n padding: 0;\n }\n\n .settings-modal::part(content) {\n display: flex;\n flex-direction: column;\n min-height: 0;\n padding: 0;\n width: 100%;\n }\n\n .settings-modal::part(top) {\n padding: calc(var(--design-unit) * 4px) calc(var(--design-unit) * 5px);\n border-bottom: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-modal::part(bottom) {\n padding: calc(var(--design-unit) * 4px) calc(var(--design-unit) * 5px);\n border-top: 1px solid var(--neutral-stroke-rest);\n border-bottom-left-radius: var(--card-border-radius, calc(var(--control-corner-radius) * 1px));\n border-bottom-right-radius: var(--card-border-radius, calc(var(--control-corner-radius) * 1px));\n background-color: var(--neutral-layer-2);\n }\n\n .settings-modal-header {\n display: flex;\n align-items: center;\n min-width: 0;\n }\n\n .settings-modal-title {\n margin: 0;\n font-size: 16px;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: calc(var(--design-unit) * 2px);\n color: var(--neutral-foreground-rest);\n }\n\n .settings-modal-content {\n display: flex;\n flex-direction: column;\n min-height: 0;\n flex: 1 1 auto;\n }\n\n .settings-modal-tabs::part(tablist) {\n border-bottom: 0;\n padding: 0 calc(var(--design-unit) * 5px);\n column-gap: calc(var(--design-unit) * 5px);\n }\n\n .settings-modal-tabs::part(activeIndicator) {\n height: 2px;\n }\n\n .settings-modal-tab {\n padding: 0;\n font-weight: 600;\n gap: 6px;\n }\n\n .settings-modal-tab[aria-selected='true'] {\n color: var(--neutral-foreground-rest);\n }\n\n .settings-modal-tabs::part(tabpanel) {\n border-top: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-modal-tab-panel {\n display: flex;\n flex-direction: column;\n min-height: 0;\n flex: 1 1 auto;\n padding: 0;\n border-radius: 0;\n }\n\n .settings-modal-tab-panel[hidden] {\n display: none !important;\n }\n\n .settings-modal-body {\n overflow-y: auto;\n padding: 0 calc(var(--design-unit) * 5px) calc(var(--design-unit) * 2px);\n max-height: min(60vh, 520px);\n }\n\n .settings-modal-section {\n padding: calc(var(--design-unit) * 5px) 0;\n border-bottom: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-modal-section:last-child {\n border-bottom: none;\n }\n\n /*\n * Only the spacing. Everything else about this heading comes from the exported fragment\n * above, which the assistant and its hosts share; margin is deliberately not in there,\n * since the gap below a heading depends on the layout around it.\n */\n .ai-settings-section-title {\n margin: 0 0 calc(var(--design-unit) * 3px);\n }\n\n .settings-modal-section-note {\n margin: calc(var(--design-unit) * -2px) 0 calc(var(--design-unit) * 3px);\n font-size: 12px;\n line-height: 1.5;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-modal-section-body {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 4px);\n }\n\n .settings-toggle-row {\n display: flex;\n align-items: flex-start;\n gap: calc(var(--design-unit) * 3px);\n padding: 0 0 calc(var(--design-unit) * 4px) 0;\n border-bottom: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-toggle-row:last-child {\n border-bottom: none;\n padding-bottom: calc(var(--design-unit) * 1px);\n }\n\n .settings-toggle-row.is-stacked {\n flex-direction: column;\n gap: calc(var(--design-unit) * 2px);\n }\n\n /*\n * For rows whose control is a button rather than a switch. The base row top-aligns, which suits\n * a switch (it lands level with the title), but a button is tall enough that top-aligning leaves\n * it above the title-plus-description block it acts on.\n */\n .settings-toggle-row.is-centered {\n align-items: center;\n }\n\n .settings-animation-list {\n display: flex;\n flex-direction: column;\n width: 100%;\n border: 1px solid var(--neutral-stroke-rest);\n border-radius: calc(var(--control-corner-radius) * 1.2px);\n padding: calc(var(--design-unit) * 2px);\n gap: calc(var(--design-unit) * 2px);\n }\n\n .settings-animation-list .settings-toggle-row {\n border: 0;\n }\n\n .settings-animation-category {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 4px);\n }\n\n .settings-animation-category-label {\n font-weight: 600;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-toggle-row + .settings-animation-category-label {\n border-top: 1px solid var(--neutral-stroke-rest);\n padding-top: calc(var(--design-unit) * 2px);\n }\n\n .settings-animation-option {\n padding: 0;\n margin: 0;\n }\n\n .settings-animation-option:last-child {\n border-bottom: none;\n padding-bottom: calc(var(--design-unit) * 2px);\n }\n\n .settings-toggle-text {\n flex: 1;\n min-width: 0;\n }\n\n .settings-toggle-title {\n font-size: 14px;\n font-weight: 500;\n color: var(--neutral-foreground-rest);\n }\n\n .settings-toggle-desc {\n font-size: 12px;\n color: var(--neutral-foreground-hint);\n line-height: 1.5;\n max-width: 92%;\n }\n\n .settings-toggle-control {\n flex: 0 0 auto;\n min-width: 0;\n }\n\n .settings-toggle-control-wide {\n width: 100%;\n max-width: 280px;\n }\n\n .settings-toggle-row.is-stacked .settings-toggle-desc {\n max-width: none;\n }\n\n .settings-toggle-row.is-stacked .settings-toggle-control-wide {\n width: 100%;\n max-width: none;\n }\n\n /*\n * Sub-heading over the provider toggle group. Unlike the section headings it sits INSIDE\n * .settings-modal-section-body, so the parent's 4-unit flex gap already separates it from the\n * first toggle — and flex does not collapse margins, so the shared rule's 3-unit margin-bottom\n * would add to that gap rather than replace it, leaving the label adrift from the rows it\n * names. Zero the margin and pull back 2 of the 4 gap units, expressed in the same token so it\n * tracks if that gap changes.\n */\n .settings-app-toggles-title {\n margin: 0 0 calc(var(--design-unit) * -2px);\n }\n\n .settings-app-toggle-block {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 1px);\n }\n\n .settings-toggle-hint {\n font-size: 12px;\n color: var(--neutral-foreground-hint);\n line-height: 1.4;\n padding-left: calc(var(--design-unit) * 1px);\n font-style: italic;\n }\n\n /*\n * The budget meter (GENC-1464) is the context indicator's money sibling and\n * shares its row anatomy 1:1, so the budget classes JOIN these rules rather\n * than restating them — one place to restyle the header/label/figures shape,\n * and the two indicators cannot drift apart. Design-system tokens only, and\n * unfallbacked: every token here ships a DS default, so a var(--x, y)\n * fallback would be dead code that hides a broken token name (#2411/#2436\n * review rule, pinned by settings-modal.styles.test.ts).\n */\n .settings-context-header,\n .settings-budget-header {\n display: flex;\n justify-content: space-between;\n gap: calc(var(--design-unit) * 2px);\n margin-bottom: calc(var(--design-unit) * 2px);\n font-size: 12px;\n }\n\n .settings-context-label,\n .settings-budget-label {\n color: var(--neutral-foreground-hint);\n font-size: 11px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n }\n\n .settings-context-tokens,\n .settings-budget-figures {\n color: var(--neutral-foreground-rest);\n }\n\n /* Freshness footer (GENC-1464): refresh button + label under the vendor\n rows, left-aligned — a footnote to the figures above it. The button's\n inline padding is pinned and cancelled by the container margin so the\n ICON GLYPH (not the button box) sits flush with the budget labels'\n left edge, whatever the density tokens say. */\n .settings-budget-toolbar {\n display: flex;\n justify-content: flex-start;\n align-items: center;\n gap: 4px;\n margin-inline-start: -4px;\n }\n\n .settings-budget-refresh::part(control) {\n padding-inline: 4px;\n }\n\n .settings-budget-updated {\n color: var(--neutral-foreground-hint);\n font-size: 11px;\n }\n\n /*\n * ONE rhythm for every meter row. The outer wrapper holds the context\n * indicator and the budget meter; the inner one holds the budget meter's\n * vendor rows — and both gap by the same 2 units (half the section body's 4)\n * so that visually identical meter rows are evenly spaced whatever mix of\n * them is on screen. Without the wrapper the context row inherits the body's\n * 4-unit gap while the vendor rows keep 2, and three identical-looking rows\n * read as an uneven 4/2/2. The wrapper renders only when at least one meter\n * does — see settingsUsageMetersTemplate for why an always-on one would cost\n * a stray gap.\n */\n .settings-usage-meters,\n .settings-budget-usage {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 2px);\n }\n\n .settings-current-build,\n .settings-lifetime-usage {\n background: var(--neutral-layer-2);\n border: 1px solid var(--neutral-stroke-rest);\n border-radius: calc(var(--control-corner-radius) * 1.5px);\n padding: calc(var(--design-unit) * 4px);\n margin: calc(var(--design-unit) * 3px) 0;\n }\n\n /*\n * Deliberately quieter than the live block: no pulsing badge and no accent, so the eye lands\n * on what is being built now — which is why that block leads the tab and this one follows,\n * under the history heading whose rows it totals.\n */\n .settings-lifetime-usage-top {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: calc(var(--design-unit) * 2px);\n margin-bottom: calc(var(--design-unit) * 3px);\n }\n\n .settings-lifetime-label {\n font-size: 10px;\n line-height: 1;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-current-build-top {\n display: flex;\n align-items: center;\n flex-wrap: wrap;\n gap: calc(var(--design-unit) * 2px);\n margin-bottom: calc(var(--design-unit) * 3px);\n }\n\n /*\n * Optically centring these 10px caps against the 14px project name beside them. Flex offers\n * only two alignments and neither lands it, because a box centre and a text baseline are\n * different lines:\n * - align-items: center sits the badge baseline about 1.2px high\n * - align-items: baseline matches baselines, but the caps then read as bottom-aligned\n * against the name's ascenders, so the badge looks low\n * The eye wants the midpoint, so: centre the boxes, then translate down by the ~1px of\n * overshoot. This is a nudge, but it corrects a fixed relationship between two font sizes\n * rather than some neighbouring element's layout, so unlike a margin tuned to a sibling it\n * cannot rot when that sibling changes. In em, so it tracks the badge text.\n *\n * display: block, not inline-flex: a flex container has no text baseline of its own and\n * synthesizes one from its first child, which here is the dot, an empty span. As a block box\n * the badge takes the baseline of its first line, i.e. the text.\n */\n .settings-live-badge {\n display: block;\n font-size: 10px;\n line-height: 1;\n font-weight: 700;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--accent-fill-rest);\n white-space: nowrap;\n transform: translateY(0.1em);\n }\n\n .settings-live-dot {\n display: inline-block;\n width: 7px;\n height: 7px;\n\n /* Replaces the flex gap the badge no longer has. */\n margin-right: calc(var(--design-unit) * 1px);\n\n /* Centres the dot on the text beside it without disturbing that text's baseline. */\n vertical-align: middle;\n border-radius: 50%;\n background: var(--accent-fill-rest);\n animation: settings-live-pulse 1.6s ease-out infinite;\n }\n\n @keyframes settings-live-pulse {\n 0% {\n box-shadow: 0 0 0 0 color-mix(in srgb, var(--accent-fill-rest) 55%, transparent);\n }\n\n 70% {\n box-shadow: 0 0 0 7px transparent;\n }\n\n 100% {\n box-shadow: 0 0 0 0 transparent;\n }\n }\n\n .settings-current-build-name {\n font-size: 14px;\n line-height: 1;\n font-weight: 600;\n }\n\n /*\n * Cost and the token buckets side by side: one number in its own box, the four buckets\n * sharing the box next to it. Stretch, so the two are the same height however tall the 22px\n * cost value makes the left one.\n */\n .settings-usage-row {\n display: flex;\n flex-wrap: wrap;\n align-items: stretch;\n gap: calc(var(--design-unit) * 3px);\n margin-bottom: calc(var(--design-unit) * 3px);\n }\n\n .settings-usage-row-tokens {\n display: flex;\n flex: 1 1 auto;\n min-width: 0;\n }\n\n .settings-build-stat {\n min-width: 0;\n background: var(--neutral-layer-1);\n border: 1px solid var(--neutral-stroke-rest);\n border-radius: calc(var(--control-corner-radius) * 1px);\n padding: calc(var(--design-unit) * 3px);\n }\n\n .settings-build-stat-label {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-build-stat-value {\n font-size: 22px;\n font-weight: 700;\n margin-top: calc(var(--design-unit) * 1px);\n color: var(--neutral-foreground-rest);\n }\n\n .settings-build-stat-value .prefix,\n .settings-build-stat-value .suffix {\n color: var(--accent-fill-rest);\n }\n\n /*\n * Per-bucket token split, beneath the headline cost. Small paired label/value cells\n * rather than four more stat cards: they are the detail behind the cost above, so they\n * have to read as subordinate to it rather than compete with it. The four buckets ARE\n * the token figure now — there is no merged total anywhere for them to break down.\n */\n .settings-token-breakdown {\n display: flex;\n flex-direction: column;\n\n /*\n * Tight against the buckets below. One design unit rather than two, because each bucket\n * separates its own label from its value by only 2px — at two units the title sat four\n * times further from the bucket labels than they sit from their own numbers, which read\n * as a gap between unrelated blocks instead of a heading over its content.\n */\n gap: calc(var(--design-unit) * 1px);\n margin-bottom: calc(var(--design-unit) * 3px);\n padding: calc(var(--design-unit) * 2px) calc(var(--design-unit) * 3px);\n background: var(--neutral-layer-1);\n border: 1px solid var(--neutral-stroke-rest);\n border-radius: calc(var(--control-corner-radius) * 1px);\n }\n\n /*\n * Titles the box, because nothing else in it named the unit. Same styling and position as\n * the cost box's label, so two boxes sitting side by side are titled the same way; the\n * hierarchy against the bucket labels comes from position, not a second type size.\n */\n .settings-token-breakdown-label {\n font-size: 10px;\n line-height: 1;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-token-buckets {\n display: flex;\n flex-wrap: wrap;\n gap: calc(var(--design-unit) * 4px);\n }\n\n .settings-token-bucket {\n display: flex;\n\n /*\n * min-content (not 0) so a bucket cannot be shrunk narrower than its own unbreakable label.\n * With the label set to nowrap, a zero minimum would overflow it into the next column instead\n * of wrapping — so the container's flex-wrap takes over and moves a bucket to a second row,\n * which is the degradation we want when the modal is dragged narrow.\n */\n min-width: min-content;\n flex-direction: column;\n gap: 2px;\n }\n\n .settings-token-bucket-label {\n font-size: 10px;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.06em;\n color: var(--neutral-foreground-hint);\n\n /*\n * One line, always. The rate marker is a separate inline box after collapsible whitespace, so\n * a wrappable label gives it a break opportunity of its own — in a narrow column it orphaned\n * onto line 2, which also pushed that bucket's value a line below the other three and broke\n * the row of figures. nowrap removes every break opportunity in the label, the space before\n * the marker included, so no glue character is needed.\n */\n white-space: nowrap;\n }\n\n .settings-token-bucket-value {\n font-size: 13px;\n font-weight: 600;\n color: var(--neutral-foreground-rest);\n }\n\n /*\n * The price-direction marker on a cache bucket's label — down for reads (a fraction of the\n * uncached input rate), up for writes (a premium over it). Three tiers, so a bucket with no\n * marker is the reference rate rather than an unlabelled fourth case.\n *\n * Carried by the label rather than the value, which is what this used to do: cache reads are\n * usually the largest bucket by a wide margin in an agentic session, so the value was muted to\n * stop the biggest number reading as the dominant cost driver. That priced the treatment to the\n * wrong thing — a dimmed 0 (every Gemini cache write) looked disabled next to a normal 0, and a\n * rate is a property of the bucket, not of this turn's figure.\n *\n * Sized down and nudged up rather than tinted: the label is already the hint colour, so a\n * dimmer marker would vanish and a brighter one would out-shout the word it qualifies.\n */\n .settings-token-bucket-rate {\n font-size: 8px;\n line-height: 1;\n vertical-align: 0.15em;\n letter-spacing: 0;\n }\n\n /*\n * Usage-row overrides. Placed after the base rules they refine rather than up beside\n * .settings-usage-row itself, because stylelint's no-descending-specificity rejects a\n * compound selector appearing before the plain one it overrides.\n */\n\n /* Sized by its content; the buckets take the rest, since four cells need the width. */\n .settings-usage-row > .settings-build-stat {\n flex: 0 1 auto;\n }\n\n .settings-usage-row .settings-token-breakdown {\n flex: 1 1 auto;\n\n /* The row owns the spacing now; this centres the column against the taller cost box. */\n justify-content: center;\n margin-bottom: 0;\n }\n\n /*\n * Basis auto, not 0: a zero basis splits the row into four equal columns, so CACHE WRITE is\n * squeezed exactly as hard as INPUT despite being twice the label. Sizing from content gives the\n * long labels the room their text needs and lets the short ones concede it, which is what makes\n * white-space: nowrap above safe — every column starts at least as wide as its own content,\n * then shares the slack. Still grows and shrinks, so the four stay flush edge to edge.\n */\n .settings-usage-row .settings-token-bucket {\n flex: 1 1 auto;\n }\n\n .settings-model-tags {\n display: flex;\n flex-wrap: wrap;\n gap: calc(var(--design-unit) * 2px);\n }\n\n .settings-model-tag {\n font-size: 11px;\n font-weight: 600;\n padding: 3px 9px;\n border-radius: 20px;\n font-family: ui-monospace, monospace;\n border: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-model-tag,\n .settings-cost-history-icon {\n --model-tag-color: var(--neutral-foreground-rest);\n\n background: color-mix(\n in srgb,\n var(--model-tag-color) var(--ai-tier-badge-bg-mix),\n var(--neutral-layer-1)\n );\n border-color: color-mix(in srgb, var(--model-tag-color) 20%, var(--neutral-layer-1));\n color: color-mix(in srgb, var(--model-tag-color), white var(--ai-tier-badge-text-lighten));\n }\n\n .settings-cost-history-title {\n font-size: 11px;\n text-transform: uppercase;\n letter-spacing: 0.08em;\n color: var(--neutral-foreground-hint);\n font-weight: 600;\n margin: calc(var(--design-unit) * 4px) 0 calc(var(--design-unit) * 2px);\n }\n\n /*\n * The heading labels the lifetime card as well as the rows, so the card gives up its own top\n * margin and the gap becomes the heading's alone. Adjacent siblings collapse to the LARGER of\n * the two margins, so leaving both would space the caps 3 units off the block they label while\n * the rows below sit at 2 — reading as though the heading belonged to neither.\n */\n .settings-cost-history-title + .settings-lifetime-usage {\n margin-top: 0;\n }\n\n .settings-cost-history {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 2px);\n padding-bottom: calc(var(--design-unit) * 2px);\n }\n\n .settings-cost-history-icon {\n flex: 0 0 auto;\n width: 36px;\n height: 36px;\n border-radius: calc(var(--control-corner-radius) * 1px);\n display: inline-flex;\n align-items: center;\n justify-content: center;\n font-size: 16px;\n font-weight: 700;\n border: 1px solid var(--neutral-stroke-rest);\n }\n\n .settings-cost-history-row {\n display: flex;\n flex-direction: column;\n background: var(--neutral-layer-1);\n border: 1px solid var(--neutral-stroke-rest);\n border-radius: calc(var(--control-corner-radius) * 1.5px);\n padding: calc(var(--design-unit) * 4px);\n }\n\n .settings-cost-history-row-content {\n display: flex;\n align-items: flex-start;\n gap: calc(var(--design-unit) * 2px);\n }\n\n /*\n * All of these carry a ?hidden binding, and all declare display: flex — which silently beat the\n * UA [hidden] { display: none } rule, because author-origin declarations outrank user-agent\n * origin whatever the specificity. Without this, showTokens: false still rendered the full\n * breakdown in the lifetime block, the live block and every history row, and an empty row list\n * still occupied its padding under the lifetime total. Sibling elements that hide correctly do\n * so only by declaring no display at all. Same treatment as .settings-modal-tab-panel[hidden]\n * near the top of this file.\n */\n .settings-usage-row-tokens[hidden],\n .settings-cost-history[hidden],\n .settings-cost-history-row-content[hidden] {\n display: none !important;\n }\n\n /*\n * The buckets inside a history row drop the panel treatment they carry in the summary\n * blocks — the row is already a bordered card, and a second box inside it reads as a\n * nested panel. The adjacent-sibling rule above supplies the separator instead.\n */\n .settings-cost-history-row-breakdown .settings-token-breakdown {\n flex: 1 1 auto;\n margin-bottom: 0;\n padding: 0;\n background: none;\n border: none;\n }\n\n .settings-cost-history-row-content + .settings-cost-history-row-content {\n border-top: 1px solid var(--neutral-stroke-rest);\n margin-top: calc(var(--design-unit) * 2px);\n padding-top: calc(var(--design-unit) * 2px);\n }\n\n .settings-cost-history-row-body {\n flex: 1 1 auto;\n min-width: 0;\n display: flex;\n gap: calc(var(--design-unit) * 2px);\n justify-content: space-between;\n }\n\n /*\n * Holds the cost and the delete button as one centred pair. The button used to be a sibling\n * of the whole row body, kept in place by a -2px nudge tuned for when the metrics column had\n * two lines (cost plus a merged token total). Dropping that second line left the nudge\n * compensating for nothing. Centring the two against each other needs no magic number and\n * cannot drift again if the metrics content changes.\n *\n * NB this rule previously set align-items with no display:flex, so it had no effect at all.\n */\n .settings-cost-history-row-right {\n display: flex;\n align-items: center;\n gap: calc(var(--design-unit) * 1px);\n flex: 0 0 auto;\n }\n\n .settings-cost-history-row-cost,\n .settings-cost-history-row-title {\n font-size: 14px;\n font-weight: 600;\n color: var(--neutral-foreground-rest);\n min-width: 0;\n }\n\n .settings-cost-history-row-metrics {\n display: flex;\n flex-direction: column;\n flex: 0 0 auto;\n font-size: 13px;\n font-family: ui-monospace, monospace;\n color: var(--neutral-foreground-rest);\n white-space: nowrap;\n }\n\n .settings-cost-history-row-date {\n font-size: 12px;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-cost-history-delete {\n flex: 0 0 auto;\n color: var(--neutral-foreground-hint);\n }\n\n .settings-cost-history-delete:hover {\n color: var(--error-color);\n }\n\n .settings-cost-history ::slotted(*) {\n display: block;\n }\n\n .settings-modal-footer {\n width: 100%;\n }\n\n .settings-done-button {\n margin-left: auto;\n }\n\n .settings-modal-footer-actions {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: calc(var(--design-unit) * 2px);\n width: 100%;\n }\n\n .settings-disclaimer {\n font-size: 12px;\n color: var(--neutral-foreground-hint);\n max-width: 60%;\n line-height: 1.4;\n }\n\n /*\n * Inline spinner shown in the \"Download agent log\" button while the log builds\n * (GENC-1351 §5.8) — the lifetime-stitch path is an async provider round-trip.\n * Sized to the button label and tinted with currentColor so it tracks the\n * button's text colour in every appearance / theme.\n */\n [part='download-button'] .download-spinner {\n display: inline-block;\n width: 12px;\n height: 12px;\n margin-right: calc(var(--design-unit) * 1px);\n vertical-align: -1px;\n border: 2px solid currentColor;\n border-right-color: transparent;\n border-radius: 50%;\n animation: download-spin 0.6s linear infinite;\n }\n\n @keyframes download-spin {\n to {\n transform: rotate(360deg);\n }\n }\n`",
|
|
10445
|
-
"description": "Styles for the assistant settings modal (tabs, sections, toggles, cost summary)."
|
|
10446
|
-
}
|
|
10447
|
-
],
|
|
10448
|
-
"exports": [
|
|
10449
|
-
{
|
|
10450
|
-
"kind": "js",
|
|
10451
|
-
"name": "settingsModalStyles",
|
|
10452
|
-
"declaration": {
|
|
10453
|
-
"name": "settingsModalStyles",
|
|
10454
|
-
"module": "src/components/settings-modal/settings-modal.styles.ts"
|
|
10455
|
-
}
|
|
10456
|
-
}
|
|
10457
|
-
]
|
|
10458
|
-
},
|
|
10459
|
-
{
|
|
10460
|
-
"kind": "javascript-module",
|
|
10461
|
-
"path": "src/components/settings-modal/settings-modal.template.ts",
|
|
10462
|
-
"declarations": [
|
|
10463
|
-
{
|
|
10464
|
-
"kind": "function",
|
|
10465
|
-
"name": "SettingsModalTemplate",
|
|
10466
|
-
"return": {
|
|
10467
|
-
"type": {
|
|
10468
|
-
"text": "ViewTemplate<FoundationAiAssistant>"
|
|
10469
|
-
}
|
|
10470
|
-
},
|
|
10471
|
-
"parameters": [
|
|
10472
|
-
{
|
|
10473
|
-
"name": "designSystemPrefix",
|
|
10474
|
-
"type": {
|
|
10475
|
-
"text": "string"
|
|
10476
|
-
}
|
|
10477
|
-
}
|
|
10478
|
-
],
|
|
10479
|
-
"description": "Modal shell for assistant settings — Configuration and Usage tabs, section slots for\napp-specific UI, and built-in chat-bot toggles."
|
|
10480
|
-
}
|
|
10481
|
-
],
|
|
10482
|
-
"exports": [
|
|
10483
|
-
{
|
|
10484
|
-
"kind": "js",
|
|
10485
|
-
"name": "SettingsModalTemplate",
|
|
10486
|
-
"declaration": {
|
|
10487
|
-
"name": "SettingsModalTemplate",
|
|
10488
|
-
"module": "src/components/settings-modal/settings-modal.template.ts"
|
|
10489
|
-
}
|
|
10490
|
-
}
|
|
10491
|
-
]
|
|
10492
|
-
},
|
|
10493
|
-
{
|
|
10494
|
-
"kind": "javascript-module",
|
|
10495
|
-
"path": "src/state/persistence/build-timeline-entries.ts",
|
|
10496
|
-
"declarations": [
|
|
10497
|
-
{
|
|
10498
|
-
"kind": "function",
|
|
10499
|
-
"name": "buildTimelineEntries",
|
|
10500
|
-
"return": {
|
|
10501
|
-
"type": {
|
|
10502
|
-
"text": "DiagnosticEntry[]"
|
|
10503
|
-
}
|
|
10504
|
-
},
|
|
10505
|
-
"parameters": [
|
|
10506
|
-
{
|
|
10507
|
-
"name": "input",
|
|
10341
|
+
"name": "input",
|
|
10508
10342
|
"type": {
|
|
10509
10343
|
"text": "{\n turnSnapshots: readonly TurnSnapshotLike[];\n messages: readonly ChatMessage[];\n metaEvents: readonly MetaEvent[];\n}"
|
|
10510
10344
|
}
|
|
@@ -10602,7 +10436,31 @@
|
|
|
10602
10436
|
}
|
|
10603
10437
|
}
|
|
10604
10438
|
],
|
|
10605
|
-
"description": "Reassemble diagnostic entries into the `{ readme, timeline, meta }
|
|
10439
|
+
"description": "Reassemble diagnostic entries into the `{ readme, sessionUsage, timeline, meta }`\ndebug-log shape (GENC-1351 §5.8). `timeline` = the `message`/`turn`/`event` entries sorted\nby ISO `timestamp` (kind-rank tie-break). `meta` = the **newest** `meta-snapshot`'s\nblock only — a \"state at export\" photo, matching the single-page log. The older\nsnapshots are intentionally dropped: the per-turn evolution they would show is\nalready in the timeline (`turn.agentSnapshot` + `context.updated` events), so\nkeeping them would just repeat the bulky, near-static `agentSummary`. `readme` =\nthe passed (current) constant. `sessionUsage` = that same newest snapshot's\n`meta.context.sessionUsage`, lifted to the top level. Pure — reused for both the\nlive current-page log and the reassembled lifetime log stitched from the persisted\nstream, so both come out shape-identical.\n\nNOTE for a caller stitching a STORED stream (a headless consumer harvesting its own\nlifetime log, say): the newest stored `meta-snapshot` is frozen at the last\nconfig-signature change, so `meta` and `sessionUsage` are as old as that unless you\npass a fresh snapshot of your own — withFreshMetaSnapshot does exactly that,\nand the element's download path goes through it."
|
|
10440
|
+
},
|
|
10441
|
+
{
|
|
10442
|
+
"kind": "function",
|
|
10443
|
+
"name": "withFreshMetaSnapshot",
|
|
10444
|
+
"return": {
|
|
10445
|
+
"type": {
|
|
10446
|
+
"text": "DiagnosticEntry[]"
|
|
10447
|
+
}
|
|
10448
|
+
},
|
|
10449
|
+
"parameters": [
|
|
10450
|
+
{
|
|
10451
|
+
"name": "stored",
|
|
10452
|
+
"type": {
|
|
10453
|
+
"text": "readonly DiagnosticEntry[]"
|
|
10454
|
+
}
|
|
10455
|
+
},
|
|
10456
|
+
{
|
|
10457
|
+
"name": "fresh",
|
|
10458
|
+
"type": {
|
|
10459
|
+
"text": "DiagnosticEntry"
|
|
10460
|
+
}
|
|
10461
|
+
}
|
|
10462
|
+
],
|
|
10463
|
+
"description": "A stored diagnostics stream with its `meta-snapshot`s replaced by `fresh` — what to\npass assembleDebugLog when reassembling a persisted stream for export.\n\nThe stored snapshots are dropped rather than out-timestamped. `assembleDebugLog` keeps\nwhichever claims the later time, and a stream written on another machine can carry a\nskewed clock; `fresh` is built from live state and so is the more current by\nconstruction. Only one snapshot ever survives reassembly, so the count is unchanged —\nthough a snapshot taken while the driver is unwired (mid-popout) can leave\n`activeFoldStack`/`activeDebugSnapshot` unset where a stored one had them. The figures\nthis exists for — the context block and `sessionUsage` — read the session store and\nelement props, which survive an unwire.\n\nPure, and separate from the element for that reason: the swap it performs is the fix\nfor a silent bug (a lifetime log reporting near-zero spend against a transcript full of\npriced messages), so it needs to be testable without mounting anything."
|
|
10606
10464
|
}
|
|
10607
10465
|
],
|
|
10608
10466
|
"exports": [
|
|
@@ -10613,6 +10471,14 @@
|
|
|
10613
10471
|
"name": "assembleDebugLog",
|
|
10614
10472
|
"module": "src/state/persistence/diagnostics.ts"
|
|
10615
10473
|
}
|
|
10474
|
+
},
|
|
10475
|
+
{
|
|
10476
|
+
"kind": "js",
|
|
10477
|
+
"name": "withFreshMetaSnapshot",
|
|
10478
|
+
"declaration": {
|
|
10479
|
+
"name": "withFreshMetaSnapshot",
|
|
10480
|
+
"module": "src/state/persistence/diagnostics.ts"
|
|
10481
|
+
}
|
|
10616
10482
|
}
|
|
10617
10483
|
]
|
|
10618
10484
|
},
|
|
@@ -10677,6 +10543,14 @@
|
|
|
10677
10543
|
"module": "./diagnostics"
|
|
10678
10544
|
}
|
|
10679
10545
|
},
|
|
10546
|
+
{
|
|
10547
|
+
"kind": "js",
|
|
10548
|
+
"name": "withFreshMetaSnapshot",
|
|
10549
|
+
"declaration": {
|
|
10550
|
+
"name": "withFreshMetaSnapshot",
|
|
10551
|
+
"module": "./diagnostics"
|
|
10552
|
+
}
|
|
10553
|
+
},
|
|
10680
10554
|
{
|
|
10681
10555
|
"kind": "js",
|
|
10682
10556
|
"name": "DiagnosticEntry",
|
|
@@ -11035,6 +10909,225 @@
|
|
|
11035
10909
|
}
|
|
11036
10910
|
}
|
|
11037
10911
|
]
|
|
10912
|
+
},
|
|
10913
|
+
{
|
|
10914
|
+
"kind": "javascript-module",
|
|
10915
|
+
"path": "src/components/popout-manager/index.ts",
|
|
10916
|
+
"declarations": [],
|
|
10917
|
+
"exports": [
|
|
10918
|
+
{
|
|
10919
|
+
"kind": "js",
|
|
10920
|
+
"name": "*",
|
|
10921
|
+
"declaration": {
|
|
10922
|
+
"name": "*",
|
|
10923
|
+
"package": "./popout-manager"
|
|
10924
|
+
}
|
|
10925
|
+
}
|
|
10926
|
+
]
|
|
10927
|
+
},
|
|
10928
|
+
{
|
|
10929
|
+
"kind": "javascript-module",
|
|
10930
|
+
"path": "src/components/popout-manager/popout-manager.ts",
|
|
10931
|
+
"declarations": [
|
|
10932
|
+
{
|
|
10933
|
+
"kind": "class",
|
|
10934
|
+
"description": "App-shell component that owns the pop-out/pop-in lifecycle for the AI assistant bubble.",
|
|
10935
|
+
"name": "FoundationAiPopoutManager",
|
|
10936
|
+
"members": [
|
|
10937
|
+
{
|
|
10938
|
+
"kind": "field",
|
|
10939
|
+
"name": "canDock",
|
|
10940
|
+
"type": {
|
|
10941
|
+
"text": "boolean"
|
|
10942
|
+
},
|
|
10943
|
+
"default": "false",
|
|
10944
|
+
"description": "True when a dock provider is registered — controls expand button visibility."
|
|
10945
|
+
},
|
|
10946
|
+
{
|
|
10947
|
+
"kind": "field",
|
|
10948
|
+
"name": "assistantEl",
|
|
10949
|
+
"type": {
|
|
10950
|
+
"text": "HTMLElement | null"
|
|
10951
|
+
},
|
|
10952
|
+
"privacy": "private",
|
|
10953
|
+
"default": "null",
|
|
10954
|
+
"description": "The single assistant element. Captured while it's in the bubble slot and held\nacross the move (it's the same instance whether docked or in the bubble), so\npop-in can re-home it even though it's no longer a child of this manager."
|
|
10955
|
+
},
|
|
10956
|
+
{
|
|
10957
|
+
"kind": "field",
|
|
10958
|
+
"name": "dockProvider",
|
|
10959
|
+
"type": {
|
|
10960
|
+
"text": "AiDockProvider | null"
|
|
10961
|
+
},
|
|
10962
|
+
"privacy": "private",
|
|
10963
|
+
"default": "null"
|
|
10964
|
+
},
|
|
10965
|
+
{
|
|
10966
|
+
"kind": "field",
|
|
10967
|
+
"name": "isDocked",
|
|
10968
|
+
"type": {
|
|
10969
|
+
"text": "boolean"
|
|
10970
|
+
},
|
|
10971
|
+
"privacy": "private",
|
|
10972
|
+
"default": "false"
|
|
10973
|
+
},
|
|
10974
|
+
{
|
|
10975
|
+
"kind": "field",
|
|
10976
|
+
"name": "unsubBus",
|
|
10977
|
+
"type": {
|
|
10978
|
+
"text": "() => void | undefined"
|
|
10979
|
+
},
|
|
10980
|
+
"privacy": "private"
|
|
10981
|
+
},
|
|
10982
|
+
{
|
|
10983
|
+
"kind": "method",
|
|
10984
|
+
"name": "findAssistant",
|
|
10985
|
+
"privacy": "private",
|
|
10986
|
+
"return": {
|
|
10987
|
+
"type": {
|
|
10988
|
+
"text": "HTMLElement | null"
|
|
10989
|
+
}
|
|
10990
|
+
},
|
|
10991
|
+
"description": "Locate the assistant element currently slotted into the bubble."
|
|
10992
|
+
},
|
|
10993
|
+
{
|
|
10994
|
+
"kind": "method",
|
|
10995
|
+
"name": "adoptAssistant",
|
|
10996
|
+
"return": {
|
|
10997
|
+
"type": {
|
|
10998
|
+
"text": "void"
|
|
10999
|
+
}
|
|
11000
|
+
},
|
|
11001
|
+
"parameters": [
|
|
11002
|
+
{
|
|
11003
|
+
"name": "el",
|
|
11004
|
+
"type": {
|
|
11005
|
+
"text": "HTMLElement"
|
|
11006
|
+
}
|
|
11007
|
+
},
|
|
11008
|
+
{
|
|
11009
|
+
"name": "docked",
|
|
11010
|
+
"type": {
|
|
11011
|
+
"text": "boolean"
|
|
11012
|
+
}
|
|
11013
|
+
}
|
|
11014
|
+
],
|
|
11015
|
+
"description": "Register an externally-created assistant element and its docked state. For\nsingle-element hosts that create the assistant directly in a layout pane (rather\nthan statically in the bubble), so the manager tracks the one element, whether it's\ncurrently docked (for pop-in re-homing), reflects the right `popout-mode` on it\n(drives the header button), and hides the empty bubble."
|
|
11016
|
+
},
|
|
11017
|
+
{
|
|
11018
|
+
"kind": "method",
|
|
11019
|
+
"name": "syncBubbleVisibility",
|
|
11020
|
+
"privacy": "private",
|
|
11021
|
+
"return": {
|
|
11022
|
+
"type": {
|
|
11023
|
+
"text": "void"
|
|
11024
|
+
}
|
|
11025
|
+
},
|
|
11026
|
+
"description": "Hide the floating bubble unless it currently contains the assistant."
|
|
11027
|
+
},
|
|
11028
|
+
{
|
|
11029
|
+
"kind": "method",
|
|
11030
|
+
"name": "canDockChanged"
|
|
11031
|
+
},
|
|
11032
|
+
{
|
|
11033
|
+
"kind": "method",
|
|
11034
|
+
"name": "registerDockProvider",
|
|
11035
|
+
"return": {
|
|
11036
|
+
"type": {
|
|
11037
|
+
"text": "void"
|
|
11038
|
+
}
|
|
11039
|
+
},
|
|
11040
|
+
"parameters": [
|
|
11041
|
+
{
|
|
11042
|
+
"name": "provider",
|
|
11043
|
+
"type": {
|
|
11044
|
+
"text": "AiDockProvider"
|
|
11045
|
+
}
|
|
11046
|
+
}
|
|
11047
|
+
]
|
|
11048
|
+
},
|
|
11049
|
+
{
|
|
11050
|
+
"kind": "method",
|
|
11051
|
+
"name": "deregisterDockProvider",
|
|
11052
|
+
"return": {
|
|
11053
|
+
"type": {
|
|
11054
|
+
"text": "void"
|
|
11055
|
+
}
|
|
11056
|
+
}
|
|
11057
|
+
},
|
|
11058
|
+
{
|
|
11059
|
+
"kind": "method",
|
|
11060
|
+
"name": "collapseIfDocked",
|
|
11061
|
+
"return": {
|
|
11062
|
+
"type": {
|
|
11063
|
+
"text": "Promise<void>"
|
|
11064
|
+
}
|
|
11065
|
+
},
|
|
11066
|
+
"description": "If the assistant is currently docked, collapses it back into the bubble.\nAwait this in `onBeforeNavButtonClick` to ensure cleanup before navigation."
|
|
11067
|
+
}
|
|
11068
|
+
],
|
|
11069
|
+
"superclass": {
|
|
11070
|
+
"name": "GenesisElement",
|
|
11071
|
+
"package": "@genesislcap/web-core"
|
|
11072
|
+
},
|
|
11073
|
+
"tagName": "foundation-ai-popout-manager",
|
|
11074
|
+
"customElement": true
|
|
11075
|
+
},
|
|
11076
|
+
{
|
|
11077
|
+
"kind": "function",
|
|
11078
|
+
"name": "isAiAssistantDocked",
|
|
11079
|
+
"return": {
|
|
11080
|
+
"type": {
|
|
11081
|
+
"text": "boolean"
|
|
11082
|
+
}
|
|
11083
|
+
},
|
|
11084
|
+
"description": "True when the assistant is active in the layout panel (docked) rather than the bubble."
|
|
11085
|
+
},
|
|
11086
|
+
{
|
|
11087
|
+
"kind": "function",
|
|
11088
|
+
"name": "getAiPopoutManager",
|
|
11089
|
+
"return": {
|
|
11090
|
+
"type": {
|
|
11091
|
+
"text": "FoundationAiPopoutManager | undefined"
|
|
11092
|
+
}
|
|
11093
|
+
},
|
|
11094
|
+
"description": "Returns the active `FoundationAiPopoutManager` instance, or `undefined` if none is mounted.\nImport this in pages to call `registerDockProvider` / `deregisterDockProvider`."
|
|
11095
|
+
}
|
|
11096
|
+
],
|
|
11097
|
+
"exports": [
|
|
11098
|
+
{
|
|
11099
|
+
"kind": "js",
|
|
11100
|
+
"name": "FoundationAiPopoutManager",
|
|
11101
|
+
"declaration": {
|
|
11102
|
+
"name": "FoundationAiPopoutManager",
|
|
11103
|
+
"module": "src/components/popout-manager/popout-manager.ts"
|
|
11104
|
+
}
|
|
11105
|
+
},
|
|
11106
|
+
{
|
|
11107
|
+
"kind": "custom-element-definition",
|
|
11108
|
+
"name": "foundation-ai-popout-manager",
|
|
11109
|
+
"declaration": {
|
|
11110
|
+
"name": "FoundationAiPopoutManager",
|
|
11111
|
+
"module": "src/components/popout-manager/popout-manager.ts"
|
|
11112
|
+
}
|
|
11113
|
+
},
|
|
11114
|
+
{
|
|
11115
|
+
"kind": "js",
|
|
11116
|
+
"name": "isAiAssistantDocked",
|
|
11117
|
+
"declaration": {
|
|
11118
|
+
"name": "isAiAssistantDocked",
|
|
11119
|
+
"module": "src/components/popout-manager/popout-manager.ts"
|
|
11120
|
+
}
|
|
11121
|
+
},
|
|
11122
|
+
{
|
|
11123
|
+
"kind": "js",
|
|
11124
|
+
"name": "getAiPopoutManager",
|
|
11125
|
+
"declaration": {
|
|
11126
|
+
"name": "getAiPopoutManager",
|
|
11127
|
+
"module": "src/components/popout-manager/popout-manager.ts"
|
|
11128
|
+
}
|
|
11129
|
+
}
|
|
11130
|
+
]
|
|
11038
11131
|
}
|
|
11039
11132
|
]
|
|
11040
11133
|
}
|