@genesislcap/ai-assistant 15.59.0 → 15.60.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.
Files changed (27) hide show
  1. package/dist/ai-assistant.d.ts +17 -0
  2. package/dist/custom-elements.json +1808 -1410
  3. package/dist/dts/components/message-feedback/index.d.ts +2 -0
  4. package/dist/dts/components/message-feedback/index.d.ts.map +1 -0
  5. package/dist/dts/components/message-feedback/message-feedback.d.ts +61 -0
  6. package/dist/dts/components/message-feedback/message-feedback.d.ts.map +1 -0
  7. package/dist/dts/components/message-feedback/message-feedback.styles.d.ts +2 -0
  8. package/dist/dts/components/message-feedback/message-feedback.styles.d.ts.map +1 -0
  9. package/dist/dts/components/message-feedback/message-feedback.template.d.ts +4 -0
  10. package/dist/dts/components/message-feedback/message-feedback.template.d.ts.map +1 -0
  11. package/dist/dts/main/main.d.ts +17 -1
  12. package/dist/dts/main/main.d.ts.map +1 -1
  13. package/dist/dts/main/main.styles.d.ts.map +1 -1
  14. package/dist/dts/main/main.template.d.ts.map +1 -1
  15. package/dist/dts/react.d.ts +10 -0
  16. package/dist/esm/components/message-feedback/index.js +1 -0
  17. package/dist/esm/components/message-feedback/message-feedback.js +241 -0
  18. package/dist/esm/components/message-feedback/message-feedback.styles.js +94 -0
  19. package/dist/esm/components/message-feedback/message-feedback.template.js +80 -0
  20. package/dist/esm/main/main.js +44 -1
  21. package/dist/esm/main/main.styles.js +27 -0
  22. package/dist/esm/main/main.template.js +13 -0
  23. package/dist/react.cjs +7 -0
  24. package/dist/react.mjs +6 -0
  25. package/package.json +17 -17
  26. package/sandbox/README.md +1 -1
  27. package/sandbox/sandbox.ts +35 -0
@@ -1858,211 +1858,6 @@
1858
1858
  }
1859
1859
  ]
1860
1860
  },
1861
- {
1862
- "kind": "javascript-module",
1863
- "path": "src/config/config.ts",
1864
- "declarations": [
1865
- {
1866
- "kind": "function",
1867
- "name": "defineAgent",
1868
- "description": "Identity helper that infers the narrowest possible type for an agent config,\npreserving string literal types (including `name`) without requiring `as const`.\n\nUse this when you need `typeof myAgent` to carry the literal `name` type —\nfor example, when wiring `ChatToolHandlers<typeof myAgent>`.\n\n```ts\nconst myAgent = defineAgent({ name: 'my_agent', ... });\ntype Handlers = ChatToolHandlers<typeof myAgent>;\n// requestSubAgent name param is now typed as 'my_agent'\n```"
1869
- }
1870
- ],
1871
- "exports": [
1872
- {
1873
- "kind": "js",
1874
- "name": "CachePolicy",
1875
- "declaration": {
1876
- "name": "CachePolicy",
1877
- "module": "src/config/config.ts"
1878
- }
1879
- },
1880
- {
1881
- "kind": "js",
1882
- "name": "ChatFallback",
1883
- "declaration": {
1884
- "name": "ChatFallback",
1885
- "module": "src/config/config.ts"
1886
- }
1887
- },
1888
- {
1889
- "kind": "js",
1890
- "name": "ChatInputDuringExecutionMode",
1891
- "declaration": {
1892
- "name": "ChatInputDuringExecutionMode",
1893
- "module": "src/config/config.ts"
1894
- }
1895
- },
1896
- {
1897
- "kind": "js",
1898
- "name": "ChatThinkingPolicy",
1899
- "declaration": {
1900
- "name": "ChatThinkingPolicy",
1901
- "module": "src/config/config.ts"
1902
- }
1903
- },
1904
- {
1905
- "kind": "js",
1906
- "name": "ChatToolChoice",
1907
- "declaration": {
1908
- "name": "ChatToolChoice",
1909
- "module": "src/config/config.ts"
1910
- }
1911
- },
1912
- {
1913
- "kind": "js",
1914
- "name": "defineAgent",
1915
- "declaration": {
1916
- "name": "defineAgent",
1917
- "module": "src/config/config.ts"
1918
- }
1919
- }
1920
- ]
1921
- },
1922
- {
1923
- "kind": "javascript-module",
1924
- "path": "src/config/define-stateful-agent.ts",
1925
- "declarations": [
1926
- {
1927
- "kind": "function",
1928
- "name": "restoreMachine",
1929
- "return": {
1930
- "type": {
1931
- "text": "void"
1932
- }
1933
- },
1934
- "parameters": [
1935
- {
1936
- "name": "machine",
1937
- "type": {
1938
- "text": "{ stop: () => void; start: (options?: { state?: unknown }) => void }"
1939
- },
1940
- "description": "the machine to restore (already constructed/started)."
1941
- },
1942
- {
1943
- "name": "restored",
1944
- "type": {
1945
- "text": "unknown"
1946
- },
1947
- "description": "the agent's serialized image (`ctx.restored` in `init`)."
1948
- },
1949
- {
1950
- "name": "key",
1951
- "default": "'machine'",
1952
- "description": "the property the machine occupies in the snapshot; defaults to\n`'machine'` to match the conventional `{ machine }` state bag."
1953
- }
1954
- ],
1955
- "description": "Restore a foundation-state-machine instance from a snapshot produced by the\ndefault serializer (or `machine.getPersistedSnapshot()`). Call inside a\nstateful agent's `init` to resume the machine in its exact prior place:\n\n```ts\ninit: ({ restored }) => {\n const machine = new MyMachine();\n restoreMachine(machine, restored); // resume, or no-op on a fresh start\n return { machine };\n}\n```\n\nNo-ops when there is nothing to restore (a fresh session), leaving the\nfreshly-constructed machine in its initial state."
1956
- },
1957
- {
1958
- "kind": "function",
1959
- "name": "defineStatefulAgent",
1960
- "return": {
1961
- "type": {
1962
- "text": "AgentConfig"
1963
- }
1964
- },
1965
- "parameters": [
1966
- {
1967
- "name": "opts",
1968
- "type": {
1969
- "text": "StatefulAgentInit<S>"
1970
- }
1971
- }
1972
- ],
1973
- "description": "Build an `AgentConfig` whose `systemPrompt`, `toolDefinitions`, and tool\nhandlers all close over a long-lived state object created on activation.\n\nThe framework wires the lifecycle: `init` on `onActivate`, `dispose` on\n`onDeactivate`. State is held inside the helper's closure — never exposed on\nthe resulting `AgentConfig` — so the redux serializer doesn't see it."
1974
- }
1975
- ],
1976
- "exports": [
1977
- {
1978
- "kind": "js",
1979
- "name": "restoreMachine",
1980
- "declaration": {
1981
- "name": "restoreMachine",
1982
- "module": "src/config/define-stateful-agent.ts"
1983
- }
1984
- },
1985
- {
1986
- "kind": "js",
1987
- "name": "defineStatefulAgent",
1988
- "declaration": {
1989
- "name": "defineStatefulAgent",
1990
- "module": "src/config/define-stateful-agent.ts"
1991
- }
1992
- }
1993
- ]
1994
- },
1995
- {
1996
- "kind": "javascript-module",
1997
- "path": "src/config/fallback-agents.ts",
1998
- "declarations": [
1999
- {
2000
- "kind": "variable",
2001
- "name": "friendlyFallbackAgent",
2002
- "type": {
2003
- "text": "FallbackAgentConfig"
2004
- },
2005
- "default": "{\n name: 'Assistant',\n fallback: true,\n systemPrompt: `You are a warm, friendly assistant. For general conversation like \"Hi\" or \"How are you\", you can have a friendly chat. For anything more complex, you cannot directly help, but you can explain what specialists are available. The available specialists are:\\n\\n{{agents}}\\n\\nPolitely let the user know what you can help with and invite them to rephrase their request if it is outside your scope.`,\n}",
2006
- "description": "A warm, conversational fallback agent. Acknowledges it can't help directly,\nexplains what the available specialists can do, and invites the user to retry.\n\nThe system prompt is generated at runtime by `OrchestratingDriver` from the\nspecialist list — no manual authoring required."
2007
- },
2008
- {
2009
- "kind": "variable",
2010
- "name": "strictFallbackAgent",
2011
- "type": {
2012
- "text": "FallbackAgentConfig"
2013
- },
2014
- "default": "{\n name: 'Assistant',\n fallback: true,\n systemPrompt: `You are a concise assistant. The user's request is outside your scope. The available specialists are: {{agents}}.\n\n{{unroutable}}\n\nAnswer in a single short sentence. Do not elaborate.`,\n}",
2015
- "description": "A brief, professional fallback agent. States what is available without\nelaboration. The `{{agents}}` placeholder is replaced at runtime by\n`OrchestratingDriver` with the generated specialist list.\n\nThe `{{unroutable}}` placeholder positions `UNROUTABLE_INSTRUCTION` — the framework's\ninstruction for a substantive request no specialist covers, which is otherwise APPENDED to a\nstring-form prompt. Positioned rather than appended for one reason: this preset's whole point is\nbrevity, and appended text would be the last thing the model reads. Putting the block above the\nbrevity rule leaves \"a single short sentence\" with the recency, so the two compose instead of\ncompeting. A prompt whose tone rules matter should do the same."
2016
- }
2017
- ],
2018
- "exports": [
2019
- {
2020
- "kind": "js",
2021
- "name": "friendlyFallbackAgent",
2022
- "declaration": {
2023
- "name": "friendlyFallbackAgent",
2024
- "module": "src/config/fallback-agents.ts"
2025
- }
2026
- },
2027
- {
2028
- "kind": "js",
2029
- "name": "strictFallbackAgent",
2030
- "declaration": {
2031
- "name": "strictFallbackAgent",
2032
- "module": "src/config/fallback-agents.ts"
2033
- }
2034
- }
2035
- ]
2036
- },
2037
- {
2038
- "kind": "javascript-module",
2039
- "path": "src/config/index.ts",
2040
- "declarations": [],
2041
- "exports": [
2042
- {
2043
- "kind": "js",
2044
- "name": "*",
2045
- "declaration": {
2046
- "name": "*",
2047
- "package": "./config"
2048
- }
2049
- },
2050
- {
2051
- "kind": "js",
2052
- "name": "*",
2053
- "declaration": {
2054
- "name": "*",
2055
- "package": "./fallback-agents"
2056
- }
2057
- }
2058
- ]
2059
- },
2060
- {
2061
- "kind": "javascript-module",
2062
- "path": "src/config/validate-providers.ts",
2063
- "declarations": [],
2064
- "exports": []
2065
- },
2066
1861
  {
2067
1862
  "kind": "javascript-module",
2068
1863
  "path": "src/genesis/calendar.ts",
@@ -3248,443 +3043,912 @@
3248
3043
  },
3249
3044
  {
3250
3045
  "kind": "javascript-module",
3251
- "path": "src/main/attachment-controller.ts",
3252
- "declarations": [],
3253
- "exports": []
3254
- },
3255
- {
3256
- "kind": "javascript-module",
3257
- "path": "src/main/budget-controller.ts",
3258
- "declarations": [],
3259
- "exports": []
3260
- },
3261
- {
3262
- "kind": "javascript-module",
3263
- "path": "src/main/composer-menu-controller.ts",
3264
- "declarations": [],
3265
- "exports": []
3266
- },
3267
- {
3268
- "kind": "javascript-module",
3269
- "path": "src/main/composer-resize-controller.ts",
3270
- "declarations": [],
3271
- "exports": []
3272
- },
3273
- {
3274
- "kind": "javascript-module",
3275
- "path": "src/main/context-gate-controller.ts",
3276
- "declarations": [],
3277
- "exports": []
3278
- },
3279
- {
3280
- "kind": "javascript-module",
3281
- "path": "src/main/cost-ledger-controller.ts",
3282
- "declarations": [],
3283
- "exports": []
3284
- },
3285
- {
3286
- "kind": "javascript-module",
3287
- "path": "src/main/index.ts",
3288
- "declarations": [],
3046
+ "path": "src/config/config.ts",
3047
+ "declarations": [
3048
+ {
3049
+ "kind": "function",
3050
+ "name": "defineAgent",
3051
+ "description": "Identity helper that infers the narrowest possible type for an agent config,\npreserving string literal types (including `name`) without requiring `as const`.\n\nUse this when you need `typeof myAgent` to carry the literal `name` type —\nfor example, when wiring `ChatToolHandlers<typeof myAgent>`.\n\n```ts\nconst myAgent = defineAgent({ name: 'my_agent', ... });\ntype Handlers = ChatToolHandlers<typeof myAgent>;\n// requestSubAgent name param is now typed as 'my_agent'\n```"
3052
+ }
3053
+ ],
3289
3054
  "exports": [
3290
3055
  {
3291
3056
  "kind": "js",
3292
- "name": "*",
3057
+ "name": "CachePolicy",
3293
3058
  "declaration": {
3294
- "name": "*",
3295
- "package": "./main.template"
3296
- }
3059
+ "name": "CachePolicy",
3060
+ "module": "src/config/config.ts"
3061
+ }
3297
3062
  },
3298
3063
  {
3299
3064
  "kind": "js",
3300
- "name": "*",
3065
+ "name": "ChatFallback",
3301
3066
  "declaration": {
3302
- "name": "*",
3303
- "package": "./main"
3067
+ "name": "ChatFallback",
3068
+ "module": "src/config/config.ts"
3304
3069
  }
3305
3070
  },
3306
3071
  {
3307
3072
  "kind": "js",
3308
- "name": "*",
3073
+ "name": "ChatInputDuringExecutionMode",
3309
3074
  "declaration": {
3310
- "name": "*",
3311
- "package": "./main.types"
3075
+ "name": "ChatInputDuringExecutionMode",
3076
+ "module": "src/config/config.ts"
3312
3077
  }
3313
- }
3314
- ]
3315
- },
3316
- {
3317
- "kind": "javascript-module",
3318
- "path": "src/main/main.styles.ts",
3319
- "declarations": [
3078
+ },
3320
3079
  {
3321
- "kind": "variable",
3322
- "name": "styles",
3323
- "default": "css`\n ${baseStyles}\n ${\n /* The session menu's rows. Same partial the agent picker imports into its own\n shadow root — the one thing that keeps the two menus looking alike. */ ''\n }\n ${menuItemStyles}\n ${settingsModalStyles}\n`"
3324
- }
3325
- ],
3326
- "exports": [
3080
+ "kind": "js",
3081
+ "name": "ChatThinkingPolicy",
3082
+ "declaration": {
3083
+ "name": "ChatThinkingPolicy",
3084
+ "module": "src/config/config.ts"
3085
+ }
3086
+ },
3327
3087
  {
3328
3088
  "kind": "js",
3329
- "name": "styles",
3089
+ "name": "ChatToolChoice",
3330
3090
  "declaration": {
3331
- "name": "styles",
3332
- "module": "src/main/main.styles.ts"
3091
+ "name": "ChatToolChoice",
3092
+ "module": "src/config/config.ts"
3093
+ }
3094
+ },
3095
+ {
3096
+ "kind": "js",
3097
+ "name": "defineAgent",
3098
+ "declaration": {
3099
+ "name": "defineAgent",
3100
+ "module": "src/config/config.ts"
3333
3101
  }
3334
3102
  }
3335
3103
  ]
3336
3104
  },
3337
3105
  {
3338
3106
  "kind": "javascript-module",
3339
- "path": "src/main/main.template.ts",
3107
+ "path": "src/config/define-stateful-agent.ts",
3340
3108
  "declarations": [
3341
3109
  {
3342
- "kind": "variable",
3343
- "name": "messageTimestampTemplate",
3344
- "default": "html<ChatMessage, FoundationAiAssistant>`\n <time\n class=\"message-timestamp\"\n part=\"message-timestamp\"\n datetime=\"${(m) => messageTimestampDateTime(m.timestamp)}\"\n >\n <span aria-hidden=\"true\">\n ${(m, c) => formatMessageTimestamp(m.timestamp, c.parent.timestampClock)}\n </span>\n <span class=\"visually-hidden\">${(m) => formatAbsoluteTimestamp(m.timestamp)}</span>\n </time>\n`",
3345
- "description": "The timestamp shown beside the sender name (GENC-1257).\n\nTwo strings, not one. A screen reader announces a `<time>` element's TEXT — it has no\nimplicit ARIA role, and the `datetime` attribute is never surfaced to the user — so the\nrelative text is hidden from assistive tech and paired with a visually-hidden absolute\nstring. Otherwise AT would hear \"5 minutes ago\" with nothing to anchor it, and in\n`'hover'` mode would hear it for a timestamp sighted users never asked to see.\n`datetime` stays because it is correct HTML and useful to tooling, not for a11y.\n\nOnly the VISUAL reveal is hover-gated, in CSS — see `.message-timestamp`. `opacity: 0`\nleaves the element in the accessibility tree, so AT gets a time in both visible modes;\n`'off'` is the only mode that removes it.\n\nReads `timestampClock` rather than `Date.now()` so every row shares one invalidatable\nclock and a tick re-evaluates them all; see `FoundationAiAssistant.timestampClock`."
3110
+ "kind": "function",
3111
+ "name": "restoreMachine",
3112
+ "return": {
3113
+ "type": {
3114
+ "text": "void"
3115
+ }
3116
+ },
3117
+ "parameters": [
3118
+ {
3119
+ "name": "machine",
3120
+ "type": {
3121
+ "text": "{ stop: () => void; start: (options?: { state?: unknown }) => void }"
3122
+ },
3123
+ "description": "the machine to restore (already constructed/started)."
3124
+ },
3125
+ {
3126
+ "name": "restored",
3127
+ "type": {
3128
+ "text": "unknown"
3129
+ },
3130
+ "description": "the agent's serialized image (`ctx.restored` in `init`)."
3131
+ },
3132
+ {
3133
+ "name": "key",
3134
+ "default": "'machine'",
3135
+ "description": "the property the machine occupies in the snapshot; defaults to\n`'machine'` to match the conventional `{ machine }` state bag."
3136
+ }
3137
+ ],
3138
+ "description": "Restore a foundation-state-machine instance from a snapshot produced by the\ndefault serializer (or `machine.getPersistedSnapshot()`). Call inside a\nstateful agent's `init` to resume the machine in its exact prior place:\n\n```ts\ninit: ({ restored }) => {\n const machine = new MyMachine();\n restoreMachine(machine, restored); // resume, or no-op on a fresh start\n return { machine };\n}\n```\n\nNo-ops when there is nothing to restore (a fresh session), leaving the\nfreshly-constructed machine in its initial state."
3346
3139
  },
3347
3140
  {
3348
3141
  "kind": "function",
3349
- "name": "FoundationAiAssistantTemplate",
3142
+ "name": "defineStatefulAgent",
3350
3143
  "return": {
3351
3144
  "type": {
3352
- "text": "ViewTemplate<FoundationAiAssistant>"
3145
+ "text": "AgentConfig"
3353
3146
  }
3354
3147
  },
3355
3148
  "parameters": [
3356
3149
  {
3357
- "name": "designSystemPrefix",
3150
+ "name": "opts",
3358
3151
  "type": {
3359
- "text": "string"
3152
+ "text": "StatefulAgentInit<S>"
3360
3153
  }
3361
3154
  }
3362
- ]
3155
+ ],
3156
+ "description": "Build an `AgentConfig` whose `systemPrompt`, `toolDefinitions`, and tool\nhandlers all close over a long-lived state object created on activation.\n\nThe framework wires the lifecycle: `init` on `onActivate`, `dispose` on\n`onDeactivate`. State is held inside the helper's closure — never exposed on\nthe resulting `AgentConfig` — so the redux serializer doesn't see it."
3363
3157
  }
3364
3158
  ],
3365
3159
  "exports": [
3366
3160
  {
3367
3161
  "kind": "js",
3368
- "name": "messageTimestampTemplate",
3162
+ "name": "restoreMachine",
3369
3163
  "declaration": {
3370
- "name": "messageTimestampTemplate",
3371
- "module": "src/main/main.template.ts"
3164
+ "name": "restoreMachine",
3165
+ "module": "src/config/define-stateful-agent.ts"
3372
3166
  }
3373
3167
  },
3374
3168
  {
3375
3169
  "kind": "js",
3376
- "name": "FoundationAiAssistantTemplate",
3170
+ "name": "defineStatefulAgent",
3377
3171
  "declaration": {
3378
- "name": "FoundationAiAssistantTemplate",
3379
- "module": "src/main/main.template.ts"
3172
+ "name": "defineStatefulAgent",
3173
+ "module": "src/config/define-stateful-agent.ts"
3380
3174
  }
3381
3175
  }
3382
3176
  ]
3383
3177
  },
3384
3178
  {
3385
3179
  "kind": "javascript-module",
3386
- "path": "src/main/main.ts",
3180
+ "path": "src/config/fallback-agents.ts",
3387
3181
  "declarations": [
3388
3182
  {
3389
3183
  "kind": "variable",
3390
- "name": "sparkleIconSvg",
3391
- "default": "`<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.5 5 C9.5 11.4 11.1 13 17.5 13 C11.1 13 9.5 14.6 9.5 21 C9.5 14.6 7.9 13 1.5 13 C7.9 13 9.5 11.4 9.5 5 Z\" fill=\"currentColor\"/><path d=\"M17 2.5 C17 5.7 17.8 6.5 21 6.5 C17.8 6.5 17 7.3 17 10.5 C17 7.3 16.2 6.5 13 6.5 C16.2 6.5 17 5.7 17 2.5 Z\" fill=\"currentColor\"/><path d=\"M17.5 15 C17.5 17 18 17.5 20 17.5 C18 17.5 17.5 18 17.5 20 C17.5 18 17 17.5 15 17.5 C17 17.5 17.5 17 17.5 15 Z\" fill=\"currentColor\"/></svg>`",
3392
- "description": "Three-star AI \"sparkle\" mark — the conventional AI signifier; default assistant avatar."
3184
+ "name": "friendlyFallbackAgent",
3185
+ "type": {
3186
+ "text": "FallbackAgentConfig"
3187
+ },
3188
+ "default": "{\n name: 'Assistant',\n fallback: true,\n systemPrompt: `You are a warm, friendly assistant. For general conversation like \"Hi\" or \"How are you\", you can have a friendly chat. For anything more complex, you cannot directly help, but you can explain what specialists are available. The available specialists are:\\n\\n{{agents}}\\n\\nPolitely let the user know what you can help with and invite them to rephrase their request if it is outside your scope.`,\n}",
3189
+ "description": "A warm, conversational fallback agent. Acknowledges it can't help directly,\nexplains what the available specialists can do, and invites the user to retry.\n\nThe system prompt is generated at runtime by `OrchestratingDriver` from the\nspecialist list — no manual authoring required."
3393
3190
  },
3394
3191
  {
3395
3192
  "kind": "variable",
3396
- "name": "userIconSvg",
3397
- "default": "`<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\" fill=\"currentColor\"/></svg>`",
3398
- "description": "Person silhouette — default user avatar."
3193
+ "name": "strictFallbackAgent",
3194
+ "type": {
3195
+ "text": "FallbackAgentConfig"
3196
+ },
3197
+ "default": "{\n name: 'Assistant',\n fallback: true,\n systemPrompt: `You are a concise assistant. The user's request is outside your scope. The available specialists are: {{agents}}.\n\n{{unroutable}}\n\nAnswer in a single short sentence. Do not elaborate.`,\n}",
3198
+ "description": "A brief, professional fallback agent. States what is available without\nelaboration. The `{{agents}}` placeholder is replaced at runtime by\n`OrchestratingDriver` with the generated specialist list.\n\nThe `{{unroutable}}` placeholder positions `UNROUTABLE_INSTRUCTION` — the framework's\ninstruction for a substantive request no specialist covers, which is otherwise APPENDED to a\nstring-form prompt. Positioned rather than appended for one reason: this preset's whole point is\nbrevity, and appended text would be the last thing the model reads. Putting the block above the\nbrevity rule leaves \"a single short sentence\" with the recency, so the two compose instead of\ncompeting. A prompt whose tone rules matter should do the same."
3199
+ }
3200
+ ],
3201
+ "exports": [
3202
+ {
3203
+ "kind": "js",
3204
+ "name": "friendlyFallbackAgent",
3205
+ "declaration": {
3206
+ "name": "friendlyFallbackAgent",
3207
+ "module": "src/config/fallback-agents.ts"
3208
+ }
3399
3209
  },
3400
3210
  {
3401
- "kind": "variable",
3402
- "name": "genesisIconSvg",
3403
- "default": "`<svg viewBox=\"-4 0 30 26\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M18.7702 23.0437C18.7702 22.4675 18.8526 21.8089 19.0995 21.3149C19.3465 20.7386 19.6758 20.2447 20.0874 19.833C20.4991 19.4214 20.993 19.0921 21.5693 18.8451C22.1456 18.5982 22.7219 18.5158 23.2981 18.5158H25.9326V11.6828H19.1819V14.3172C19.1819 15.5521 18.6879 16.7047 17.8647 17.5279C17.0414 18.3512 15.8888 18.8451 14.7363 18.9275H6.7507V6.99025H16.4651V0.157227H3.54C2.63442 0.157227 1.72884 0.568855 1.07023 1.22746C0.411628 1.88606 0 2.79165 0 3.77955V22.2205C0 23.1261 0.411628 24.0316 1.07023 24.7726C1.72884 25.4312 2.63442 25.8428 3.54 25.8428H18.7702V23.0437Z\" fill=\"currentColor\"/></svg>`",
3404
- "description": "Genesis G-mark — opt-in assistant avatar (the default before the sparkle mark)."
3211
+ "kind": "js",
3212
+ "name": "strictFallbackAgent",
3213
+ "declaration": {
3214
+ "name": "strictFallbackAgent",
3215
+ "module": "src/config/fallback-agents.ts"
3216
+ }
3217
+ }
3218
+ ]
3219
+ },
3220
+ {
3221
+ "kind": "javascript-module",
3222
+ "path": "src/config/index.ts",
3223
+ "declarations": [],
3224
+ "exports": [
3225
+ {
3226
+ "kind": "js",
3227
+ "name": "*",
3228
+ "declaration": {
3229
+ "name": "*",
3230
+ "package": "./config"
3231
+ }
3405
3232
  },
3233
+ {
3234
+ "kind": "js",
3235
+ "name": "*",
3236
+ "declaration": {
3237
+ "name": "*",
3238
+ "package": "./fallback-agents"
3239
+ }
3240
+ }
3241
+ ]
3242
+ },
3243
+ {
3244
+ "kind": "javascript-module",
3245
+ "path": "src/config/validate-providers.ts",
3246
+ "declarations": [],
3247
+ "exports": []
3248
+ },
3249
+ {
3250
+ "kind": "javascript-module",
3251
+ "path": "src/provider/ai-provider-switcher.ts",
3252
+ "declarations": [
3253
+ {
3254
+ "kind": "variable",
3255
+ "name": "AIProviderSwitcher",
3256
+ "description": "The DI token for the (AIProviderSwitcher:interface). Resolves a noop until the app\nregisters one."
3257
+ }
3258
+ ],
3259
+ "exports": [
3260
+ {
3261
+ "kind": "js",
3262
+ "name": "AIProviderSwitcher",
3263
+ "declaration": {
3264
+ "name": "AIProviderSwitcher",
3265
+ "module": "src/provider/ai-provider-switcher.ts"
3266
+ }
3267
+ }
3268
+ ]
3269
+ },
3270
+ {
3271
+ "kind": "javascript-module",
3272
+ "path": "src/provider/assistant-app-settings.ts",
3273
+ "declarations": [
3274
+ {
3275
+ "kind": "variable",
3276
+ "name": "AssistantAppSettingsProvider",
3277
+ "description": "The DI token for the (AssistantAppSettingsProvider:interface). Resolves a noop\nuntil the host registers one."
3278
+ }
3279
+ ],
3280
+ "exports": [
3281
+ {
3282
+ "kind": "js",
3283
+ "name": "AssistantAppSettingsProvider",
3284
+ "declaration": {
3285
+ "name": "AssistantAppSettingsProvider",
3286
+ "module": "src/provider/assistant-app-settings.ts"
3287
+ }
3288
+ }
3289
+ ]
3290
+ },
3291
+ {
3292
+ "kind": "javascript-module",
3293
+ "path": "src/provider/tiered-provider-switcher.ts",
3294
+ "declarations": [
3406
3295
  {
3407
3296
  "kind": "class",
3408
- "description": "Foundation AI Assistant component.",
3409
- "name": "FoundationAiAssistant",
3297
+ "description": "Which cloud vendor backs the tier-shaped provider registry, plus the means to move it at\nruntime (GENC-1610).",
3298
+ "name": "TieredAIProviderSwitcher",
3410
3299
  "members": [
3411
3300
  {
3412
3301
  "kind": "field",
3413
- "name": "composerResize",
3414
- "privacy": "private",
3415
- "readonly": true,
3416
- "default": "new ComposerResizeController({\n enabled: () => this.chatConfig.ui?.resizableInput !== false,\n inputEl: () => this.chatInputEl,\n messagesEl: () => this.messagesEl,\n })"
3302
+ "name": "vendors",
3303
+ "type": {
3304
+ "text": "readonly AITierVendor[]"
3305
+ },
3306
+ "readonly": true
3417
3307
  },
3418
3308
  {
3419
3309
  "kind": "field",
3420
- "name": "composerMenus",
3310
+ "name": "options",
3311
+ "type": {
3312
+ "text": "TieredAIProviderSwitcherOptions"
3313
+ },
3421
3314
  "privacy": "private",
3422
3315
  "readonly": true,
3423
- "default": "new ComposerMenuController(this, {\n agentPickerOpen: this.accessor('agentPickerOpen'),\n sessionMenuOpen: this.accessor('sessionMenuOpen'),\n focusInput: () => this.chatInputEl?.focus(),\n resetSessionConfirmations: () => {\n this.confirmingClear = false;\n this.confirmingCompact = false;\n },\n logMeta: (type, detail) => this.logMeta(type, detail),\n })"
3316
+ "default": "options"
3424
3317
  },
3425
3318
  {
3426
3319
  "kind": "field",
3427
- "name": "attachmentCtrl",
3320
+ "name": "defaultTier",
3321
+ "type": {
3322
+ "text": "AITierId"
3323
+ },
3428
3324
  "privacy": "private",
3429
- "readonly": true,
3430
- "default": "new AttachmentController(this, {\n acceptedFiles: () => this.chatConfig.ui?.acceptedFiles,\n logMeta: (type, detail) => this.logMeta(type, detail),\n })"
3325
+ "readonly": true
3431
3326
  },
3432
3327
  {
3433
3328
  "kind": "field",
3434
- "name": "contextGateCtrl",
3435
- "privacy": "private",
3436
- "readonly": true,
3437
- "default": "new ContextGateController({\n chatConfig: () => this.chatConfig,\n messages: () => this.messages,\n contextTokens: () => this.contextTokens,\n contextLimit: () => this.contextLimit,\n gateContextTokens: () => this._gateContextTokens,\n contextReserve: () => this.contextReserve,\n preambleTokens: () => this.driver?.getPreambleTokens?.(),\n compactionPlanFor: (options) => this.driver?.getCompactionPlan?.(options) ?? null,\n bannerVisible: () => this.bannerVisible,\n effectiveBlockedReason: () => this.effectiveBlockedReason,\n flowOwnerAgentName: () => this.flowOwnerAgentName,\n })",
3438
- "description": "Pure derivation — owns no state. Reaches the driver only through the two\ncallbacks below, so it stays clear of the stateful-agent surface (§11.2\nconstraint 2) and of redux entirely."
3439
- },
3440
- {
3441
- "kind": "field",
3442
- "name": "costLedger",
3443
- "privacy": "private",
3444
- "readonly": true,
3445
- "default": "new CostLedgerController({\n chatConfig: () => this.chatConfig,\n messages: () => this.messages,\n sessionUsage: () => this.sessionUsage,\n providerStatuses: () => this.providerStatuses,\n persistenceActive: () => this.persistenceActive,\n stateKey: () => this.getStateKey(),\n headerTitle: () => this.headerTitle,\n provider: () => this.persistence.provider,\n elementId: () => this.id,\n })",
3446
- "description": "Cost accounting and the persisted build-history ledger (GENC-1475). Reads the live\nsession through callbacks and owns the rows, the load/write latches and the debounce\ntimer — the element keeps only the names the settings modal binds."
3447
- },
3448
- {
3449
- "kind": "field",
3450
- "name": "budget",
3329
+ "name": "registry",
3330
+ "type": {
3331
+ "text": "MutableAIProviderRegistry"
3332
+ },
3451
3333
  "privacy": "private",
3452
- "readonly": true,
3453
- "default": "new BudgetController({\n sessionRef: () => this._sessionRef,\n providerStatuses: () => this.providerStatuses,\n providerRegistry: () => this.providerRegistry,\n chatConfig: () => this.chatConfig,\n })",
3454
- "description": "The AI-spend budget: vendor walls, the derived composer lock, the banner copy\nand the settings meter (GENC-1464).\n\nTakes the session store itself rather than a callback per field — see\n`BudgetDeps` for why this one differs from its siblings."
3334
+ "readonly": true
3455
3335
  },
3456
3336
  {
3457
3337
  "kind": "field",
3458
- "name": "settings",
3338
+ "name": "listeners",
3459
3339
  "privacy": "private",
3460
3340
  "readonly": true,
3461
- "default": "new SettingsModalController({\n chatConfig: () => this.chatConfig,\n contextTokens: () => this.contextTokens,\n contextLimit: () => this.contextLimit,\n budgetUsageVisible: () => this.budget.settingsUsageVisible,\n costConfig: () => this.costLedger.config,\n costHistoryLength: () => this.costLedger.history.length,\n liveCostSessionTitle: () => this.costLedger.liveTitle,\n providerStatusCount: () => this.providerStatuses.length,\n sessionRef: () => this._sessionRef,\n stateKey: () => this.getStateKey(),\n popoutMode: () => this.popoutMode,\n headerTitle: () => this.headerTitle,\n appSettingsProvider: () => this.appSettingsProvider,\n modal: () => this.settingsModal,\n tabsEl: () => this.settingsTabsEl,\n requestBudgetRefresh: () => this.requestBudgetRefresh(),\n logMeta: (type, detail) => this.logMeta(type, detail),\n })",
3462
- "description": "The settings modal (`docs/code-health.md` §3). Reaches the two design-system\nrefs through callbacks, because the template writes them by name — see\n`SettingsModalDeps`."
3463
- },
3464
- {
3465
- "kind": "field",
3466
- "name": "providerRegistry",
3467
- "type": {
3468
- "text": "AIProviderRegistry"
3469
- }
3470
- },
3471
- {
3472
- "kind": "field",
3473
- "name": "appSettingsProvider",
3474
- "type": {
3475
- "text": "AssistantAppSettingsProvider"
3476
- }
3477
- },
3478
- {
3479
- "kind": "field",
3480
- "name": "designSystemPrefix",
3481
- "type": {
3482
- "text": "string"
3483
- },
3484
- "default": "'rapid'"
3485
- },
3486
- {
3487
- "kind": "field",
3488
- "name": "headerTitle",
3489
- "type": {
3490
- "text": "string"
3491
- },
3492
- "default": "'Genesis Assistant'"
3493
- },
3494
- {
3495
- "kind": "field",
3496
- "name": "sessionKey",
3497
- "type": {
3498
- "text": "string | undefined"
3499
- },
3500
- "description": "Explicit session/persistence key (GENC-1351 §5.12). When set, this is the\nsession identity — the key for the driver/store/persister/diagnostics\nregistries and the `sessionKey` passed to the persistence provider — taking\nprecedence over the DOM `id`. A host that scopes persistence per-entity\n(e.g. one chat session per project) binds this to a stable per-entity id;\nchanging it on a **connected** element re-keys the session in place — tears\ndown the current conversation and restores the new key's — via\n`switchSession`. Falls back to `id` when unset,\nso existing consumers are unaffected."
3501
- },
3502
- {
3503
- "kind": "field",
3504
- "name": "imageSrc",
3505
- "type": {
3506
- "text": "string | undefined"
3507
- }
3508
- },
3509
- {
3510
- "kind": "field",
3511
- "name": "userImageSrc",
3512
- "type": {
3513
- "text": "string | undefined"
3514
- }
3341
+ "default": "new Set<(vendor: AITierVendor) => void>()"
3515
3342
  },
3516
3343
  {
3517
3344
  "kind": "field",
3518
- "name": "assistantIcon",
3345
+ "name": "_vendor",
3519
3346
  "type": {
3520
- "text": "string | undefined"
3347
+ "text": "AITierVendor"
3521
3348
  },
3522
- "description": "Inline SVG markup overriding the default assistant \"sparkle\" avatar. The\nmarkup is sanitized (SVG profile) before rendering and uses the avatar's\ntheme colour via `currentColor`. For a raster/photo avatar set `imageSrc`\ninstead, which takes precedence. Set to `genesisIconSvg` to restore the\nGenesis G-mark."
3349
+ "privacy": "private"
3523
3350
  },
3524
3351
  {
3525
3352
  "kind": "field",
3526
- "name": "assistantIconSafe",
3353
+ "name": "vendor",
3527
3354
  "type": {
3528
- "text": "string"
3355
+ "text": "AITierVendor"
3529
3356
  },
3530
- "default": "`<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.5 5 C9.5 11.4 11.1 13 17.5 13 C11.1 13 9.5 14.6 9.5 21 C9.5 14.6 7.9 13 1.5 13 C7.9 13 9.5 11.4 9.5 5 Z\" fill=\"currentColor\"/><path d=\"M17 2.5 C17 5.7 17.8 6.5 21 6.5 C17.8 6.5 17 7.3 17 10.5 C17 7.3 16.2 6.5 13 6.5 C16.2 6.5 17 5.7 17 2.5 Z\" fill=\"currentColor\"/><path d=\"M17.5 15 C17.5 17 18 17.5 20 17.5 C18 17.5 17.5 18 17.5 20 C17.5 18 17 17.5 15 17.5 C17 17.5 17.5 17 17.5 15 Z\" fill=\"currentColor\"/></svg>`",
3531
- "description": "Sanitized `assistantIcon`, or the default sparkle mark; bound into the template. @internal"
3357
+ "readonly": true
3532
3358
  },
3533
3359
  {
3534
3360
  "kind": "method",
3535
- "name": "assistantIconChanged",
3536
- "privacy": "protected",
3361
+ "name": "switchTo",
3537
3362
  "return": {
3538
3363
  "type": {
3539
3364
  "text": "void"
3540
3365
  }
3541
- }
3542
- },
3543
- {
3544
- "kind": "field",
3545
- "name": "userIcon",
3546
- "type": {
3547
- "text": "string | undefined"
3548
- },
3549
- "description": "Inline SVG markup overriding the default user \"person\" avatar. The markup is\nsanitized (SVG profile) before rendering and uses the avatar's theme colour\nvia `currentColor`. For a raster/photo avatar set `userImageSrc` instead,\nwhich takes precedence."
3550
- },
3551
- {
3552
- "kind": "field",
3553
- "name": "userIconSafe",
3554
- "type": {
3555
- "text": "string"
3556
3366
  },
3557
- "default": "`<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\" fill=\"currentColor\"/></svg>`",
3558
- "description": "Sanitized `userIcon`, or the default person mark; bound into the template. @internal"
3367
+ "parameters": [
3368
+ {
3369
+ "name": "vendor",
3370
+ "type": {
3371
+ "text": "string"
3372
+ }
3373
+ }
3374
+ ],
3375
+ "description": "A user-driven switch: move the registry, then tell the app so it can persist the choice.\nAn unknown vendor is ignored."
3559
3376
  },
3560
3377
  {
3561
3378
  "kind": "method",
3562
- "name": "userIconChanged",
3563
- "privacy": "protected",
3379
+ "name": "adoptPersistedVendor",
3564
3380
  "return": {
3565
3381
  "type": {
3566
3382
  "text": "void"
3567
3383
  }
3568
- }
3569
- },
3570
- {
3571
- "kind": "field",
3572
- "name": "placeholder",
3573
- "type": {
3574
- "text": "string"
3575
- },
3576
- "default": "'Message assistant...'"
3577
- },
3578
- {
3579
- "kind": "field",
3580
- "name": "popoutMode",
3581
- "type": {
3582
- "text": "PopoutMode | undefined"
3583
3384
  },
3584
- "description": "Controls the pop-out button shown next to the settings cog.\n\"expand\" — in bubble, expands to layout panel (fires chat-popout).\n\"collapse\" — in layout panel, collapses back to bubble (fires chat-popin).\nAbsent — no button (default standalone behaviour, no breaking change)."
3385
+ "parameters": [
3386
+ {
3387
+ "name": "vendor",
3388
+ "type": {
3389
+ "text": "string"
3390
+ }
3391
+ }
3392
+ ],
3393
+ "description": "Adopt a vendor the app read back from its own store — the same registry move as\nTieredAIProviderSwitcher.switchTo, without the `onSwitch` callback, because this\nvalue came FROM the store and writing it back would be a pointless round-trip on load.\n\nExists because registration has to stay synchronous: an element that connects before the\ntoken is registered caches the platform's no-op fallback, so an app cannot await its\nstored preference before constructing this. It boots on `initialVendor` and adopts the\nstored one a moment later, through a registry that is mutable and held by reference."
3585
3394
  },
3586
3395
  {
3587
- "kind": "field",
3588
- "name": "agents",
3589
- "type": {
3590
- "text": "AgentConfig[] | undefined"
3396
+ "kind": "method",
3397
+ "name": "subscribe",
3398
+ "return": {
3399
+ "type": {
3400
+ "text": "() => void"
3401
+ }
3591
3402
  },
3592
- "description": "Agent configuration. Each user message is routed to the appropriate specialist\nbased on intent. With a single entry, orchestration is skipped."
3403
+ "parameters": [
3404
+ {
3405
+ "name": "listener",
3406
+ "type": {
3407
+ "text": "(vendor: string) => void"
3408
+ }
3409
+ }
3410
+ ]
3593
3411
  },
3594
3412
  {
3595
- "kind": "field",
3596
- "name": "chatConfig",
3597
- "type": {
3598
- "text": "ChatConfig"
3413
+ "kind": "method",
3414
+ "name": "apply",
3415
+ "privacy": "private",
3416
+ "return": {
3417
+ "type": {
3418
+ "text": "void"
3419
+ }
3599
3420
  },
3600
- "default": "{}"
3421
+ "parameters": [
3422
+ {
3423
+ "name": "vendor",
3424
+ "type": {
3425
+ "text": "AITierVendor"
3426
+ }
3427
+ }
3428
+ ],
3429
+ "description": "The registry move both entry points share, and nothing else."
3601
3430
  },
3602
3431
  {
3603
- "kind": "field",
3604
- "name": "persistence",
3605
- "type": {
3606
- "text": "SessionPersistenceConfig"
3432
+ "kind": "method",
3433
+ "name": "build",
3434
+ "privacy": "private",
3435
+ "return": {
3436
+ "type": {
3437
+ "text": "Record<string, AIProvider>"
3438
+ }
3607
3439
  },
3608
- "default": "{}",
3609
- "description": "Optional session persistence (GENC-1351). Off by default — set `enabled`\nand a `provider` (e.g. a `WebStorageSessionProvider`) to have the assistant\nautosave on idle and auto-restore the conversation on page reload. Exposed\nas a top-level property (like `agents`/`providerRegistry`) rather than via\n`chatConfig`, since the provider type lives in this package while\n`ChatConfig` lives in `foundation-ai`."
3440
+ "parameters": [
3441
+ {
3442
+ "name": "vendor",
3443
+ "type": {
3444
+ "text": "AITierVendor"
3445
+ }
3446
+ }
3447
+ ]
3610
3448
  },
3611
3449
  {
3612
- "kind": "field",
3613
- "name": "aiServiceErrorMessages",
3614
- "type": {
3615
- "text": "Partial<Record<AIServiceRefusal, string>> | undefined"
3450
+ "kind": "method",
3451
+ "name": "isKnownVendor",
3452
+ "privacy": "private",
3453
+ "return": {
3454
+ "type": {
3455
+ "text": "vendor is AITierVendor"
3456
+ }
3616
3457
  },
3617
- "description": "Replaces the transcript sentence shown when the app's AI service refuses a request with one of\n`AI_SERVICE_ERROR_CODES`, or its router with one of `AI_SERVICE_ACCESS_REFUSALS` (GENC-1611), per\ncode; a code with no entry keeps\n`DEFAULT_AI_SERVICE_ERROR_MESSAGES`. Read when the driver is created, so set it before the\nelement connects."
3618
- },
3458
+ "parameters": [
3459
+ {
3460
+ "name": "vendor",
3461
+ "type": {
3462
+ "text": "string"
3463
+ }
3464
+ }
3465
+ ]
3466
+ }
3467
+ ]
3468
+ },
3469
+ {
3470
+ "kind": "function",
3471
+ "name": "registerTieredAIProviders",
3472
+ "return": {
3473
+ "type": {
3474
+ "text": "TieredAIProviderSwitcher"
3475
+ }
3476
+ },
3477
+ "parameters": [
3619
3478
  {
3620
- "kind": "field",
3621
- "name": "agentPicker",
3479
+ "name": "container",
3622
3480
  "type": {
3623
- "text": "AgentPickerMode"
3624
- },
3625
- "description": "Resolved agent picker mode from `chatConfig.picker.mode`. Defaults to\n`'disabled'`.",
3626
- "readonly": true
3481
+ "text": "Container"
3482
+ }
3627
3483
  },
3628
3484
  {
3629
- "kind": "field",
3630
- "name": "composerHiddenByConfig",
3485
+ "name": "options",
3631
3486
  "type": {
3632
- "text": "boolean"
3633
- },
3634
- "description": "Whether the built-in composer (input row + attachment chips) is hidden by\nthe host's `chatConfig.ui.hideComposer` setting. Used by the template to\ngate those blocks. Marked `@volatile` because the `'while-splash'` branch\nreads `showingSplash` only conditionally, so FAST cannot rely on cached\ndependency tracking.",
3635
- "readonly": true
3636
- },
3487
+ "text": "Omit<TieredAIProviderSwitcherOptions, 'container'>"
3488
+ }
3489
+ }
3490
+ ],
3491
+ "description": "Build a TieredAIProviderSwitcher — which registers the tier-shaped provider\nregistry — and put it on the (AIProviderSwitcher:variable) token. Call once at app\nbootstrap."
3492
+ }
3493
+ ],
3494
+ "exports": [
3495
+ {
3496
+ "kind": "js",
3497
+ "name": "TieredAIProviderSwitcher",
3498
+ "declaration": {
3499
+ "name": "TieredAIProviderSwitcher",
3500
+ "module": "src/provider/tiered-provider-switcher.ts"
3501
+ }
3502
+ },
3503
+ {
3504
+ "kind": "js",
3505
+ "name": "registerTieredAIProviders",
3506
+ "declaration": {
3507
+ "name": "registerTieredAIProviders",
3508
+ "module": "src/provider/tiered-provider-switcher.ts"
3509
+ }
3510
+ }
3511
+ ]
3512
+ },
3513
+ {
3514
+ "kind": "javascript-module",
3515
+ "path": "src/main/attachment-controller.ts",
3516
+ "declarations": [],
3517
+ "exports": []
3518
+ },
3519
+ {
3520
+ "kind": "javascript-module",
3521
+ "path": "src/main/budget-controller.ts",
3522
+ "declarations": [],
3523
+ "exports": []
3524
+ },
3525
+ {
3526
+ "kind": "javascript-module",
3527
+ "path": "src/main/composer-menu-controller.ts",
3528
+ "declarations": [],
3529
+ "exports": []
3530
+ },
3531
+ {
3532
+ "kind": "javascript-module",
3533
+ "path": "src/main/composer-resize-controller.ts",
3534
+ "declarations": [],
3535
+ "exports": []
3536
+ },
3537
+ {
3538
+ "kind": "javascript-module",
3539
+ "path": "src/main/context-gate-controller.ts",
3540
+ "declarations": [],
3541
+ "exports": []
3542
+ },
3543
+ {
3544
+ "kind": "javascript-module",
3545
+ "path": "src/main/cost-ledger-controller.ts",
3546
+ "declarations": [],
3547
+ "exports": []
3548
+ },
3549
+ {
3550
+ "kind": "javascript-module",
3551
+ "path": "src/main/index.ts",
3552
+ "declarations": [],
3553
+ "exports": [
3554
+ {
3555
+ "kind": "js",
3556
+ "name": "*",
3557
+ "declaration": {
3558
+ "name": "*",
3559
+ "package": "./main.template"
3560
+ }
3561
+ },
3562
+ {
3563
+ "kind": "js",
3564
+ "name": "*",
3565
+ "declaration": {
3566
+ "name": "*",
3567
+ "package": "./main"
3568
+ }
3569
+ },
3570
+ {
3571
+ "kind": "js",
3572
+ "name": "*",
3573
+ "declaration": {
3574
+ "name": "*",
3575
+ "package": "./main.types"
3576
+ }
3577
+ }
3578
+ ]
3579
+ },
3580
+ {
3581
+ "kind": "javascript-module",
3582
+ "path": "src/main/main.styles.ts",
3583
+ "declarations": [
3584
+ {
3585
+ "kind": "variable",
3586
+ "name": "styles",
3587
+ "default": "css`\n ${baseStyles}\n ${\n /* The session menu's rows. Same partial the agent picker imports into its own\n shadow root — the one thing that keeps the two menus looking alike. */ ''\n }\n ${menuItemStyles}\n ${settingsModalStyles}\n`"
3588
+ }
3589
+ ],
3590
+ "exports": [
3591
+ {
3592
+ "kind": "js",
3593
+ "name": "styles",
3594
+ "declaration": {
3595
+ "name": "styles",
3596
+ "module": "src/main/main.styles.ts"
3597
+ }
3598
+ }
3599
+ ]
3600
+ },
3601
+ {
3602
+ "kind": "javascript-module",
3603
+ "path": "src/main/main.template.ts",
3604
+ "declarations": [
3605
+ {
3606
+ "kind": "variable",
3607
+ "name": "messageTimestampTemplate",
3608
+ "default": "html<ChatMessage, FoundationAiAssistant>`\n <time\n class=\"message-timestamp\"\n part=\"message-timestamp\"\n datetime=\"${(m) => messageTimestampDateTime(m.timestamp)}\"\n >\n <span aria-hidden=\"true\">\n ${(m, c) => formatMessageTimestamp(m.timestamp, c.parent.timestampClock)}\n </span>\n <span class=\"visually-hidden\">${(m) => formatAbsoluteTimestamp(m.timestamp)}</span>\n </time>\n`",
3609
+ "description": "The timestamp shown beside the sender name (GENC-1257).\n\nTwo strings, not one. A screen reader announces a `<time>` element's TEXT — it has no\nimplicit ARIA role, and the `datetime` attribute is never surfaced to the user — so the\nrelative text is hidden from assistive tech and paired with a visually-hidden absolute\nstring. Otherwise AT would hear \"5 minutes ago\" with nothing to anchor it, and in\n`'hover'` mode would hear it for a timestamp sighted users never asked to see.\n`datetime` stays because it is correct HTML and useful to tooling, not for a11y.\n\nOnly the VISUAL reveal is hover-gated, in CSS — see `.message-timestamp`. `opacity: 0`\nleaves the element in the accessibility tree, so AT gets a time in both visible modes;\n`'off'` is the only mode that removes it.\n\nReads `timestampClock` rather than `Date.now()` so every row shares one invalidatable\nclock and a tick re-evaluates them all; see `FoundationAiAssistant.timestampClock`."
3610
+ },
3611
+ {
3612
+ "kind": "function",
3613
+ "name": "FoundationAiAssistantTemplate",
3614
+ "return": {
3615
+ "type": {
3616
+ "text": "ViewTemplate<FoundationAiAssistant>"
3617
+ }
3618
+ },
3619
+ "parameters": [
3637
3620
  {
3638
- "kind": "field",
3639
- "name": "debugStateFactory",
3621
+ "name": "designSystemPrefix",
3640
3622
  "type": {
3641
- "text": "() => unknown | undefined"
3623
+ "text": "string"
3642
3624
  }
3625
+ }
3626
+ ]
3627
+ }
3628
+ ],
3629
+ "exports": [
3630
+ {
3631
+ "kind": "js",
3632
+ "name": "messageTimestampTemplate",
3633
+ "declaration": {
3634
+ "name": "messageTimestampTemplate",
3635
+ "module": "src/main/main.template.ts"
3636
+ }
3637
+ },
3638
+ {
3639
+ "kind": "js",
3640
+ "name": "FoundationAiAssistantTemplate",
3641
+ "declaration": {
3642
+ "name": "FoundationAiAssistantTemplate",
3643
+ "module": "src/main/main.template.ts"
3644
+ }
3645
+ }
3646
+ ]
3647
+ },
3648
+ {
3649
+ "kind": "javascript-module",
3650
+ "path": "src/main/main.ts",
3651
+ "declarations": [
3652
+ {
3653
+ "kind": "variable",
3654
+ "name": "sparkleIconSvg",
3655
+ "default": "`<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.5 5 C9.5 11.4 11.1 13 17.5 13 C11.1 13 9.5 14.6 9.5 21 C9.5 14.6 7.9 13 1.5 13 C7.9 13 9.5 11.4 9.5 5 Z\" fill=\"currentColor\"/><path d=\"M17 2.5 C17 5.7 17.8 6.5 21 6.5 C17.8 6.5 17 7.3 17 10.5 C17 7.3 16.2 6.5 13 6.5 C16.2 6.5 17 5.7 17 2.5 Z\" fill=\"currentColor\"/><path d=\"M17.5 15 C17.5 17 18 17.5 20 17.5 C18 17.5 17.5 18 17.5 20 C17.5 18 17 17.5 15 17.5 C17 17.5 17.5 17 17.5 15 Z\" fill=\"currentColor\"/></svg>`",
3656
+ "description": "Three-star AI \"sparkle\" mark — the conventional AI signifier; default assistant avatar."
3657
+ },
3658
+ {
3659
+ "kind": "variable",
3660
+ "name": "userIconSvg",
3661
+ "default": "`<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\" fill=\"currentColor\"/></svg>`",
3662
+ "description": "Person silhouette — default user avatar."
3663
+ },
3664
+ {
3665
+ "kind": "variable",
3666
+ "name": "genesisIconSvg",
3667
+ "default": "`<svg viewBox=\"-4 0 30 26\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M18.7702 23.0437C18.7702 22.4675 18.8526 21.8089 19.0995 21.3149C19.3465 20.7386 19.6758 20.2447 20.0874 19.833C20.4991 19.4214 20.993 19.0921 21.5693 18.8451C22.1456 18.5982 22.7219 18.5158 23.2981 18.5158H25.9326V11.6828H19.1819V14.3172C19.1819 15.5521 18.6879 16.7047 17.8647 17.5279C17.0414 18.3512 15.8888 18.8451 14.7363 18.9275H6.7507V6.99025H16.4651V0.157227H3.54C2.63442 0.157227 1.72884 0.568855 1.07023 1.22746C0.411628 1.88606 0 2.79165 0 3.77955V22.2205C0 23.1261 0.411628 24.0316 1.07023 24.7726C1.72884 25.4312 2.63442 25.8428 3.54 25.8428H18.7702V23.0437Z\" fill=\"currentColor\"/></svg>`",
3668
+ "description": "Genesis G-mark — opt-in assistant avatar (the default before the sparkle mark)."
3669
+ },
3670
+ {
3671
+ "kind": "class",
3672
+ "description": "Foundation AI Assistant component.",
3673
+ "name": "FoundationAiAssistant",
3674
+ "members": [
3675
+ {
3676
+ "kind": "field",
3677
+ "name": "composerResize",
3678
+ "privacy": "private",
3679
+ "readonly": true,
3680
+ "default": "new ComposerResizeController({\n enabled: () => this.chatConfig.ui?.resizableInput !== false,\n inputEl: () => this.chatInputEl,\n messagesEl: () => this.messagesEl,\n })"
3643
3681
  },
3644
3682
  {
3645
3683
  "kind": "field",
3646
- "name": "debugRedux",
3647
- "type": {
3648
- "text": "boolean"
3649
- },
3650
- "default": "false",
3651
- "description": "When set, enables Redux DevTools for this instance's session store."
3684
+ "name": "composerMenus",
3685
+ "privacy": "private",
3686
+ "readonly": true,
3687
+ "default": "new ComposerMenuController(this, {\n agentPickerOpen: this.accessor('agentPickerOpen'),\n sessionMenuOpen: this.accessor('sessionMenuOpen'),\n focusInput: () => this.chatInputEl?.focus(),\n resetSessionConfirmations: () => {\n this.confirmingClear = false;\n this.confirmingCompact = false;\n },\n logMeta: (type, detail) => this.logMeta(type, detail),\n })"
3652
3688
  },
3653
3689
  {
3654
3690
  "kind": "field",
3655
- "name": "_sessionRef",
3656
- "type": {
3657
- "text": "SessionStoreReturn | undefined"
3658
- },
3691
+ "name": "attachmentCtrl",
3659
3692
  "privacy": "private",
3660
- "description": "Pointer to this session's redux store. `@observable` (GENC-1351 §5.12) so that\n**swapping** it — the in-place session switch/re-key (`switchSession`) —\nforces every store-backed getter binding to re-evaluate against the NEW store.\nWithout this, FAST's per-store slice tracking would leave the view subscribed\nto the old store after a swap and it wouldn't re-render. (A same-store reset via\nredux actions re-renders without this; a store *swap* needs it.)"
3693
+ "readonly": true,
3694
+ "default": "new AttachmentController(this, {\n acceptedFiles: () => this.chatConfig.ui?.acceptedFiles,\n logMeta: (type, detail) => this.logMeta(type, detail),\n })"
3661
3695
  },
3662
3696
  {
3663
3697
  "kind": "field",
3664
- "name": "_gateContextTokens",
3665
- "type": {
3666
- "text": "number | undefined"
3667
- },
3698
+ "name": "contextGateCtrl",
3668
3699
  "privacy": "private",
3669
- "description": "FoundationAiAssistant.contextTokens as of the last moment no turn was\nrunning — the figure FoundationAiAssistant.contextGate is judged\nagainst (GENC-1582).\n\n**Why the gate reads a held figure and the gauge does not.** They answer\ndifferent questions. The gauge is a meter: \"how much context is in play right\nnow\", and a build that momentarily fills 900k of a 1M window should say so.\nThe gate answers \"may the next turn START\", which is only meaningful when no\nturn is running — the composer is disabled by `busy` throughout one anyway, so\na warning raised mid-turn is unactionable by construction.\n\nReading the live figure meant the pill went amber part-way through every large\nbuild and cleared itself at the end, because a `condenseWhen` agent's context\npeaks mid-turn and is shed before the turn finishes. A signal that fires and\nwithdraws on its own each time teaches people to ignore it.\n\n**Held, not latched.** The distinction matters, because `contextGate` is\ndocumented as derived-never-latched and the reason is a real dead end: a figure\npinned to a conversation that has since shrunk blocks the user out of the very\nactions that would fix it. This holds only for the duration of a turn and is\nrefreshed the moment one settles, so no shrink can outlive it — a compaction\nruns under `compacting` rather than `busy` and therefore updates it as it goes,\nand Clear drops it outright. What it costs is one turn of lag: a turn that\nballoons the resting size does not warn until it ends, which is the same trade\nthe flow-owner soften already makes deliberately.\n\nUnset falls back to the live figure, which is correct wherever there is no held\nvalue yet — first paint, and a remount, both of which happen at rest."
3700
+ "readonly": true,
3701
+ "default": "new ContextGateController({\n chatConfig: () => this.chatConfig,\n messages: () => this.messages,\n contextTokens: () => this.contextTokens,\n contextLimit: () => this.contextLimit,\n gateContextTokens: () => this._gateContextTokens,\n contextReserve: () => this.contextReserve,\n preambleTokens: () => this.driver?.getPreambleTokens?.(),\n compactionPlanFor: (options) => this.driver?.getCompactionPlan?.(options) ?? null,\n bannerVisible: () => this.bannerVisible,\n effectiveBlockedReason: () => this.effectiveBlockedReason,\n flowOwnerAgentName: () => this.flowOwnerAgentName,\n })",
3702
+ "description": "Pure derivation — owns no state. Reaches the driver only through the two\ncallbacks below, so it stays clear of the stateful-agent surface (§11.2\nconstraint 2) and of redux entirely."
3670
3703
  },
3671
3704
  {
3672
3705
  "kind": "field",
3673
- "name": "messages",
3674
- "type": {
3675
- "text": "ChatMessage[]"
3676
- }
3706
+ "name": "costLedger",
3707
+ "privacy": "private",
3708
+ "readonly": true,
3709
+ "default": "new CostLedgerController({\n chatConfig: () => this.chatConfig,\n messages: () => this.messages,\n sessionUsage: () => this.sessionUsage,\n providerStatuses: () => this.providerStatuses,\n persistenceActive: () => this.persistenceActive,\n stateKey: () => this.getStateKey(),\n headerTitle: () => this.headerTitle,\n provider: () => this.persistence.provider,\n elementId: () => this.id,\n })",
3710
+ "description": "Cost accounting and the persisted build-history ledger (GENC-1475). Reads the live\nsession through callbacks and owns the rows, the load/write latches and the debounce\ntimer — the element keeps only the names the settings modal binds."
3677
3711
  },
3678
3712
  {
3679
3713
  "kind": "field",
3680
- "name": "state",
3714
+ "name": "budget",
3715
+ "privacy": "private",
3716
+ "readonly": true,
3717
+ "default": "new BudgetController({\n sessionRef: () => this._sessionRef,\n providerStatuses: () => this.providerStatuses,\n providerRegistry: () => this.providerRegistry,\n chatConfig: () => this.chatConfig,\n })",
3718
+ "description": "The AI-spend budget: vendor walls, the derived composer lock, the banner copy\nand the settings meter (GENC-1464).\n\nTakes the session store itself rather than a callback per field — see\n`BudgetDeps` for why this one differs from its siblings."
3719
+ },
3720
+ {
3721
+ "kind": "field",
3722
+ "name": "settings",
3723
+ "privacy": "private",
3724
+ "readonly": true,
3725
+ "default": "new SettingsModalController({\n chatConfig: () => this.chatConfig,\n contextTokens: () => this.contextTokens,\n contextLimit: () => this.contextLimit,\n budgetUsageVisible: () => this.budget.settingsUsageVisible,\n costConfig: () => this.costLedger.config,\n costHistoryLength: () => this.costLedger.history.length,\n liveCostSessionTitle: () => this.costLedger.liveTitle,\n providerStatusCount: () => this.providerStatuses.length,\n sessionRef: () => this._sessionRef,\n stateKey: () => this.getStateKey(),\n popoutMode: () => this.popoutMode,\n headerTitle: () => this.headerTitle,\n appSettingsProvider: () => this.appSettingsProvider,\n modal: () => this.settingsModal,\n tabsEl: () => this.settingsTabsEl,\n requestBudgetRefresh: () => this.requestBudgetRefresh(),\n logMeta: (type, detail) => this.logMeta(type, detail),\n })",
3726
+ "description": "The settings modal (`docs/code-health.md` §3). Reaches the two design-system\nrefs through callbacks, because the template writes them by name — see\n`SettingsModalDeps`."
3727
+ },
3728
+ {
3729
+ "kind": "field",
3730
+ "name": "providerRegistry",
3681
3731
  "type": {
3682
- "text": "AiAssistantState"
3732
+ "text": "AIProviderRegistry"
3683
3733
  }
3684
3734
  },
3685
3735
  {
3686
- "kind": "method",
3687
- "name": "isBusyState",
3736
+ "kind": "field",
3737
+ "name": "appSettingsProvider",
3738
+ "type": {
3739
+ "text": "AssistantAppSettingsProvider"
3740
+ }
3741
+ },
3742
+ {
3743
+ "kind": "field",
3744
+ "name": "designSystemPrefix",
3745
+ "type": {
3746
+ "text": "string"
3747
+ },
3748
+ "default": "'rapid'"
3749
+ },
3750
+ {
3751
+ "kind": "field",
3752
+ "name": "headerTitle",
3753
+ "type": {
3754
+ "text": "string"
3755
+ },
3756
+ "default": "'Genesis Assistant'"
3757
+ },
3758
+ {
3759
+ "kind": "field",
3760
+ "name": "sessionKey",
3761
+ "type": {
3762
+ "text": "string | undefined"
3763
+ },
3764
+ "description": "Explicit session/persistence key (GENC-1351 §5.12). When set, this is the\nsession identity — the key for the driver/store/persister/diagnostics\nregistries and the `sessionKey` passed to the persistence provider — taking\nprecedence over the DOM `id`. A host that scopes persistence per-entity\n(e.g. one chat session per project) binds this to a stable per-entity id;\nchanging it on a **connected** element re-keys the session in place — tears\ndown the current conversation and restores the new key's — via\n`switchSession`. Falls back to `id` when unset,\nso existing consumers are unaffected."
3765
+ },
3766
+ {
3767
+ "kind": "field",
3768
+ "name": "imageSrc",
3769
+ "type": {
3770
+ "text": "string | undefined"
3771
+ }
3772
+ },
3773
+ {
3774
+ "kind": "field",
3775
+ "name": "userImageSrc",
3776
+ "type": {
3777
+ "text": "string | undefined"
3778
+ }
3779
+ },
3780
+ {
3781
+ "kind": "field",
3782
+ "name": "assistantIcon",
3783
+ "type": {
3784
+ "text": "string | undefined"
3785
+ },
3786
+ "description": "Inline SVG markup overriding the default assistant \"sparkle\" avatar. The\nmarkup is sanitized (SVG profile) before rendering and uses the avatar's\ntheme colour via `currentColor`. For a raster/photo avatar set `imageSrc`\ninstead, which takes precedence. Set to `genesisIconSvg` to restore the\nGenesis G-mark."
3787
+ },
3788
+ {
3789
+ "kind": "field",
3790
+ "name": "assistantIconSafe",
3791
+ "type": {
3792
+ "text": "string"
3793
+ },
3794
+ "default": "`<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.5 5 C9.5 11.4 11.1 13 17.5 13 C11.1 13 9.5 14.6 9.5 21 C9.5 14.6 7.9 13 1.5 13 C7.9 13 9.5 11.4 9.5 5 Z\" fill=\"currentColor\"/><path d=\"M17 2.5 C17 5.7 17.8 6.5 21 6.5 C17.8 6.5 17 7.3 17 10.5 C17 7.3 16.2 6.5 13 6.5 C16.2 6.5 17 5.7 17 2.5 Z\" fill=\"currentColor\"/><path d=\"M17.5 15 C17.5 17 18 17.5 20 17.5 C18 17.5 17.5 18 17.5 20 C17.5 18 17 17.5 15 17.5 C17 17.5 17.5 17 17.5 15 Z\" fill=\"currentColor\"/></svg>`",
3795
+ "description": "Sanitized `assistantIcon`, or the default sparkle mark; bound into the template. @internal"
3796
+ },
3797
+ {
3798
+ "kind": "method",
3799
+ "name": "assistantIconChanged",
3800
+ "privacy": "protected",
3801
+ "return": {
3802
+ "type": {
3803
+ "text": "void"
3804
+ }
3805
+ }
3806
+ },
3807
+ {
3808
+ "kind": "field",
3809
+ "name": "userIcon",
3810
+ "type": {
3811
+ "text": "string | undefined"
3812
+ },
3813
+ "description": "Inline SVG markup overriding the default user \"person\" avatar. The markup is\nsanitized (SVG profile) before rendering and uses the avatar's theme colour\nvia `currentColor`. For a raster/photo avatar set `userImageSrc` instead,\nwhich takes precedence."
3814
+ },
3815
+ {
3816
+ "kind": "field",
3817
+ "name": "userIconSafe",
3818
+ "type": {
3819
+ "text": "string"
3820
+ },
3821
+ "default": "`<svg viewBox=\"0 0 24 24\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M12 12c2.21 0 4-1.79 4-4s-1.79-4-4-4-4 1.79-4 4 1.79 4 4 4zm0 2c-2.67 0-8 1.34-8 4v2h16v-2c0-2.66-5.33-4-8-4z\" fill=\"currentColor\"/></svg>`",
3822
+ "description": "Sanitized `userIcon`, or the default person mark; bound into the template. @internal"
3823
+ },
3824
+ {
3825
+ "kind": "method",
3826
+ "name": "userIconChanged",
3827
+ "privacy": "protected",
3828
+ "return": {
3829
+ "type": {
3830
+ "text": "void"
3831
+ }
3832
+ }
3833
+ },
3834
+ {
3835
+ "kind": "field",
3836
+ "name": "placeholder",
3837
+ "type": {
3838
+ "text": "string"
3839
+ },
3840
+ "default": "'Message assistant...'"
3841
+ },
3842
+ {
3843
+ "kind": "field",
3844
+ "name": "popoutMode",
3845
+ "type": {
3846
+ "text": "PopoutMode | undefined"
3847
+ },
3848
+ "description": "Controls the pop-out button shown next to the settings cog.\n\"expand\" — in bubble, expands to layout panel (fires chat-popout).\n\"collapse\" — in layout panel, collapses back to bubble (fires chat-popin).\nAbsent — no button (default standalone behaviour, no breaking change)."
3849
+ },
3850
+ {
3851
+ "kind": "field",
3852
+ "name": "agents",
3853
+ "type": {
3854
+ "text": "AgentConfig[] | undefined"
3855
+ },
3856
+ "description": "Agent configuration. Each user message is routed to the appropriate specialist\nbased on intent. With a single entry, orchestration is skipped."
3857
+ },
3858
+ {
3859
+ "kind": "field",
3860
+ "name": "chatConfig",
3861
+ "type": {
3862
+ "text": "ChatConfig"
3863
+ },
3864
+ "default": "{}"
3865
+ },
3866
+ {
3867
+ "kind": "field",
3868
+ "name": "persistence",
3869
+ "type": {
3870
+ "text": "SessionPersistenceConfig"
3871
+ },
3872
+ "default": "{}",
3873
+ "description": "Optional session persistence (GENC-1351). Off by default — set `enabled`\nand a `provider` (e.g. a `WebStorageSessionProvider`) to have the assistant\nautosave on idle and auto-restore the conversation on page reload. Exposed\nas a top-level property (like `agents`/`providerRegistry`) rather than via\n`chatConfig`, since the provider type lives in this package while\n`ChatConfig` lives in `foundation-ai`."
3874
+ },
3875
+ {
3876
+ "kind": "field",
3877
+ "name": "aiServiceErrorMessages",
3878
+ "type": {
3879
+ "text": "Partial<Record<AIServiceRefusal, string>> | undefined"
3880
+ },
3881
+ "description": "Replaces the transcript sentence shown when the app's AI service refuses a request with one of\n`AI_SERVICE_ERROR_CODES`, or its router with one of `AI_SERVICE_ACCESS_REFUSALS` (GENC-1611), per\ncode; a code with no entry keeps\n`DEFAULT_AI_SERVICE_ERROR_MESSAGES`. Read when the driver is created, so set it before the\nelement connects."
3882
+ },
3883
+ {
3884
+ "kind": "field",
3885
+ "name": "agentPicker",
3886
+ "type": {
3887
+ "text": "AgentPickerMode"
3888
+ },
3889
+ "description": "Resolved agent picker mode from `chatConfig.picker.mode`. Defaults to\n`'disabled'`.",
3890
+ "readonly": true
3891
+ },
3892
+ {
3893
+ "kind": "field",
3894
+ "name": "composerHiddenByConfig",
3895
+ "type": {
3896
+ "text": "boolean"
3897
+ },
3898
+ "description": "Whether the built-in composer (input row + attachment chips) is hidden by\nthe host's `chatConfig.ui.hideComposer` setting. Used by the template to\ngate those blocks. Marked `@volatile` because the `'while-splash'` branch\nreads `showingSplash` only conditionally, so FAST cannot rely on cached\ndependency tracking.",
3899
+ "readonly": true
3900
+ },
3901
+ {
3902
+ "kind": "field",
3903
+ "name": "debugStateFactory",
3904
+ "type": {
3905
+ "text": "() => unknown | undefined"
3906
+ }
3907
+ },
3908
+ {
3909
+ "kind": "field",
3910
+ "name": "debugRedux",
3911
+ "type": {
3912
+ "text": "boolean"
3913
+ },
3914
+ "default": "false",
3915
+ "description": "When set, enables Redux DevTools for this instance's session store."
3916
+ },
3917
+ {
3918
+ "kind": "field",
3919
+ "name": "_sessionRef",
3920
+ "type": {
3921
+ "text": "SessionStoreReturn | undefined"
3922
+ },
3923
+ "privacy": "private",
3924
+ "description": "Pointer to this session's redux store. `@observable` (GENC-1351 §5.12) so that\n**swapping** it — the in-place session switch/re-key (`switchSession`) —\nforces every store-backed getter binding to re-evaluate against the NEW store.\nWithout this, FAST's per-store slice tracking would leave the view subscribed\nto the old store after a swap and it wouldn't re-render. (A same-store reset via\nredux actions re-renders without this; a store *swap* needs it.)"
3925
+ },
3926
+ {
3927
+ "kind": "field",
3928
+ "name": "_gateContextTokens",
3929
+ "type": {
3930
+ "text": "number | undefined"
3931
+ },
3932
+ "privacy": "private",
3933
+ "description": "FoundationAiAssistant.contextTokens as of the last moment no turn was\nrunning — the figure FoundationAiAssistant.contextGate is judged\nagainst (GENC-1582).\n\n**Why the gate reads a held figure and the gauge does not.** They answer\ndifferent questions. The gauge is a meter: \"how much context is in play right\nnow\", and a build that momentarily fills 900k of a 1M window should say so.\nThe gate answers \"may the next turn START\", which is only meaningful when no\nturn is running — the composer is disabled by `busy` throughout one anyway, so\na warning raised mid-turn is unactionable by construction.\n\nReading the live figure meant the pill went amber part-way through every large\nbuild and cleared itself at the end, because a `condenseWhen` agent's context\npeaks mid-turn and is shed before the turn finishes. A signal that fires and\nwithdraws on its own each time teaches people to ignore it.\n\n**Held, not latched.** The distinction matters, because `contextGate` is\ndocumented as derived-never-latched and the reason is a real dead end: a figure\npinned to a conversation that has since shrunk blocks the user out of the very\nactions that would fix it. This holds only for the duration of a turn and is\nrefreshed the moment one settles, so no shrink can outlive it — a compaction\nruns under `compacting` rather than `busy` and therefore updates it as it goes,\nand Clear drops it outright. What it costs is one turn of lag: a turn that\nballoons the resting size does not warn until it ends, which is the same trade\nthe flow-owner soften already makes deliberately.\n\nUnset falls back to the live figure, which is correct wherever there is no held\nvalue yet — first paint, and a remount, both of which happen at rest."
3934
+ },
3935
+ {
3936
+ "kind": "field",
3937
+ "name": "messages",
3938
+ "type": {
3939
+ "text": "ChatMessage[]"
3940
+ }
3941
+ },
3942
+ {
3943
+ "kind": "field",
3944
+ "name": "state",
3945
+ "type": {
3946
+ "text": "AiAssistantState"
3947
+ }
3948
+ },
3949
+ {
3950
+ "kind": "method",
3951
+ "name": "isBusyState",
3688
3952
  "privacy": "private",
3689
3953
  "return": {
3690
3954
  "type": {
@@ -6360,672 +6624,116 @@
6360
6624
  }
6361
6625
  },
6362
6626
  {
6363
- "name": "driver",
6364
- "type": {
6365
- "text": "AiDriver | undefined"
6366
- }
6367
- }
6368
- ],
6369
- "description": "Whether the session restored for `key` is no longer the one on screen (GENC-1662): switched in\nplace, or the element disconnected, while the load was in flight."
6370
- },
6371
- {
6372
- "kind": "method",
6373
- "name": "reactivateRestoredFlow",
6374
- "privacy": "private",
6375
- "return": {
6376
- "type": {
6377
- "text": "Promise<void>"
6378
- }
6379
- },
6380
- "parameters": [
6381
- {
6382
- "name": "driver",
6383
- "type": {
6384
- "text": "AiDriver | undefined"
6385
- }
6386
- }
6387
- ],
6388
- "description": "Re-activate a restored flow owner (GENC-1662), so a stateful agent's `init({ restored })` — and\nanything the host hangs off it, like a progress stepper — runs straight after the reload\ninstead of on the next message."
6389
- },
6390
- {
6391
- "kind": "method",
6392
- "name": "resumeInterruptedTurn",
6393
- "privacy": "private",
6394
- "return": {
6395
- "type": {
6396
- "text": "Promise<void>"
6397
- }
6398
- },
6399
- "parameters": [
6400
- {
6401
- "name": "key",
6402
- "type": {
6403
- "text": "string"
6404
- }
6405
- },
6406
- {
6407
- "name": "driver",
6408
- "type": {
6409
- "text": "AiDriver | undefined"
6410
- }
6411
- },
6412
- {
6413
- "name": "ref",
6414
- "type": {
6415
- "text": "SessionStoreReturn | undefined"
6416
- }
6417
- },
6418
- {
6419
- "name": "outcome",
6420
- "type": {
6421
- "text": "RestoreOutcome"
6422
- }
6423
- }
6424
- ],
6425
- "description": "Run the turn a reload interrupted (GENC-1662), shown as busy exactly as a send is — or, when it\ncannot run, withdraw the resume the restore divider promised."
6426
- },
6427
- {
6428
- "kind": "method",
6429
- "name": "triggerFileInput",
6430
- "return": {
6431
- "type": {
6432
- "text": "void"
6433
- }
6434
- }
6435
- },
6436
- {
6437
- "kind": "method",
6438
- "name": "handleFileSelect",
6439
- "return": {
6440
- "type": {
6441
- "text": "void"
6442
- }
6443
- },
6444
- "parameters": [
6445
- {
6446
- "name": "e",
6447
- "type": {
6448
- "text": "Event"
6449
- }
6450
- }
6451
- ]
6452
- },
6453
- {
6454
- "kind": "method",
6455
- "name": "removeAttachment",
6456
- "return": {
6457
- "type": {
6458
- "text": "void"
6459
- }
6460
- },
6461
- "parameters": [
6462
- {
6463
- "name": "attachment",
6464
- "type": {
6465
- "text": "ChatAttachment"
6466
- }
6467
- }
6468
- ]
6469
- },
6470
- {
6471
- "kind": "method",
6472
- "name": "removeAttachmentError",
6473
- "return": {
6474
- "type": {
6475
- "text": "void"
6476
- }
6477
- },
6478
- "parameters": [
6479
- {
6480
- "name": "message",
6481
- "type": {
6482
- "text": "string"
6483
- }
6484
- }
6485
- ]
6486
- },
6487
- {
6488
- "kind": "method",
6489
- "name": "handleSendClick"
6490
- },
6491
- {
6492
- "kind": "method",
6493
- "name": "handleStopClick",
6494
- "description": "User clicked Stop. Cancels the current turn via the driver and flips the\nbutton to \"Stopping…\" until the turn winds down (a tool mid-execution\nfinishes first). Guarded so a second click is a no-op."
6495
- },
6496
- {
6497
- "kind": "method",
6498
- "name": "handleSuggestionClick",
6499
- "parameters": [
6500
- {
6501
- "name": "suggestion",
6502
- "type": {
6503
- "text": "string"
6504
- }
6505
- }
6506
- ]
6507
- },
6508
- {
6509
- "kind": "method",
6510
- "name": "submitMessage",
6511
- "return": {
6512
- "type": {
6513
- "text": "Promise<SubmitMessageResult>"
6514
- }
6515
- },
6516
- "parameters": [
6517
- {
6518
- "name": "input",
6519
- "type": {
6520
- "text": "{ text?: string; files?: File[] }"
6521
- }
6522
- }
6523
- ],
6524
- "description": "Programmatically submit a message. Equivalent to the user typing into the\nbuilt-in composer and pressing send, but callable from external code — most\ncommonly a custom input rendered inside `slot=\"splash\"` when paired with\n`chatConfig.ui.hideComposer`.\n\nThe input fully describes the turn: `text` and `files` REPLACE any current\ncomposer state (they are not appended to it). Files are validated against\n`chatConfig.ui.acceptedFiles` using the same pipeline as the composer's\nattach button.\n\nAtomic on validation: if any file fails validation, no attachments are\ncommitted and no send is dispatched. Failure messages are returned in\n`errors` AND appended to the `attachmentErrors` observable so the built-in\nchip UI still surfaces them when visible.\n\nResolves once the underlying send has been kicked off — it does NOT await\nthe assistant's response."
6525
- },
6526
- {
6527
- "kind": "method",
6528
- "name": "fetchSuggestions",
6529
- "privacy": "private"
6530
- },
6531
- {
6532
- "kind": "field",
6533
- "name": "_pendingSendPrompt",
6534
- "type": {
6535
- "text": "string | undefined"
6536
- },
6537
- "privacy": "private",
6538
- "description": "User text of the message currently being sent, stashed for the lifetime of `send()`.\n`flow-owner-changed` fires while the driver routes this turn — before the message is\nappended to raw history — so the flow-activation-prompt capture reads this rather than\na stale raw-history lookup. Cleared once the send settles. (GENC-1351 §5.9)"
6539
- },
6540
- {
6541
- "kind": "method",
6542
- "name": "send",
6543
- "privacy": "private"
6544
- },
6545
- {
6546
- "kind": "method",
6547
- "name": "settleAfterTurn",
6548
- "privacy": "private",
6549
- "return": {
6550
- "type": {
6551
- "text": "void"
6552
- }
6553
- },
6554
- "parameters": [
6555
- {
6556
- "name": "capturedSessionRef",
6557
- "type": {
6558
- "text": "SessionStoreReturn | null | undefined"
6559
- }
6560
- }
6561
- ],
6562
- "description": "The post-turn settle shared by `send()` and a resumed restore turn: back to idle through\nthe session ref captured at turn start, then the cleanup the state setter would have done."
6563
- },
6564
- {
6565
- "kind": "method",
6566
- "name": "onChatHeaderMouseDown",
6567
- "parameters": [
6568
- {
6569
- "name": "e",
6570
- "type": {
6571
- "text": "MouseEvent"
6572
- }
6573
- }
6574
- ]
6575
- },
6576
- {
6577
- "kind": "method",
6578
- "name": "handleInteractionCompleted",
6579
- "parameters": [
6580
- {
6581
- "name": "e",
6582
- "type": {
6583
- "text": "Event"
6584
- }
6585
- }
6586
- ]
6587
- },
6588
- {
6589
- "kind": "method",
6590
- "name": "handleInteractionCost",
6591
- "parameters": [
6592
- {
6593
- "name": "e",
6594
- "type": {
6595
- "text": "Event"
6596
- }
6597
- }
6598
- ],
6599
- "description": "A widget reporting spend it incurred AFTER resolving.\n\nNote what this deliberately does NOT do: no `startLoadingTimer()`. This is bookkeeping about a\nturn that already finished, so it must be invisible — showing a spinner would tell the user the\nassistant is working when nothing is pending."
6600
- },
6601
- {
6602
- "kind": "field",
6603
- "name": "stopButtonVisible",
6604
- "type": {
6605
- "text": "boolean"
6606
- },
6607
- "description": "Whether the Stop control is showing.\n\nWhile a turn runs Stop REPLACES Send rather than sitting beside it: the two\nare mutually exclusive actions, and a disabled Send next to a live Stop just\ngives the eye a dead control to skip past. Reads `busy`, so `cancelling`\nkeeps it up (in its \"Stopping…\" state) until the turn actually winds down.",
6608
- "readonly": true
6609
- },
6610
- {
6611
- "kind": "field",
6612
- "name": "sendButtonVisible",
6613
- "type": {
6614
- "text": "boolean"
6615
- },
6616
- "description": "Whether Send is rendered at all. Hidden exactly when Stop has taken its\nplace — so a host that suppressed Stop via `hideStopButton` keeps Send\nthroughout, disabled for the duration, and the slot is never left empty\nmid-turn.",
6617
- "readonly": true
6618
- },
6619
- {
6620
- "kind": "field",
6621
- "name": "isComposerResizable",
6622
- "type": {
6623
- "text": "boolean"
6624
- },
6625
- "description": "Whether the message input shows a drag handle to resize its height.",
6626
- "readonly": true
6627
- },
6628
- {
6629
- "kind": "field",
6630
- "name": "composerHeightStyle",
6631
- "type": {
6632
- "text": "string"
6633
- },
6634
- "description": "Inline style carrying the dragged height into `--composer-height`.",
6635
- "readonly": true
6636
- },
6637
- {
6638
- "kind": "method",
6639
- "name": "onComposerResizeStart",
6640
- "return": {
6641
- "type": {
6642
- "text": "void"
6643
- }
6644
- },
6645
- "parameters": [
6646
- {
6647
- "name": "e",
6648
- "type": {
6649
- "text": "PointerEvent"
6650
- }
6651
- }
6652
- ]
6653
- },
6654
- {
6655
- "kind": "method",
6656
- "name": "onComposerResizeMove",
6657
- "return": {
6658
- "type": {
6659
- "text": "void"
6660
- }
6661
- },
6662
- "parameters": [
6663
- {
6664
- "name": "e",
6665
- "type": {
6666
- "text": "PointerEvent"
6667
- }
6668
- }
6669
- ]
6670
- },
6671
- {
6672
- "kind": "method",
6673
- "name": "onComposerResizeEnd",
6674
- "return": {
6675
- "type": {
6676
- "text": "void"
6677
- }
6678
- },
6679
- "parameters": [
6680
- {
6681
- "name": "e",
6682
- "type": {
6683
- "text": "PointerEvent"
6684
- }
6685
- }
6686
- ]
6687
- }
6688
- ],
6689
- "events": [
6690
- {
6691
- "name": "budget-refresh-requested",
6692
- "type": {
6693
- "text": "CustomEvent"
6694
- }
6695
- },
6696
- {
6697
- "type": {
6698
- "text": "CustomEvent"
6699
- }
6700
- },
6701
- {
6702
- "description": "Fired when the user presses the chat header in `popout-mode=\"expand\"` (for drag-to-popout hosts). Bubbles and composed. detail: `ChatHeaderMouseDownDetail`",
6703
- "name": "chat-header-mousedown"
6704
- },
6705
- {
6706
- "description": "Fired after the session is wiped (the lifecycle menu's Clear). The payload is captured before teardown so the host can clean up any external state the active agent was working on. Bubbles and composed. detail: `SessionClearedDetail`",
6707
- "name": "session-cleared"
6708
- }
6709
- ],
6710
- "attributes": [
6711
- {
6712
- "name": "header-title",
6713
- "type": {
6714
- "text": "string"
6715
- },
6716
- "default": "'Genesis Assistant'",
6717
- "fieldName": "headerTitle"
6718
- },
6719
- {
6720
- "name": "session-key",
6721
- "type": {
6722
- "text": "string | undefined"
6723
- },
6724
- "description": "Explicit session/persistence key (GENC-1351 §5.12). When set, this is the\nsession identity — the key for the driver/store/persister/diagnostics\nregistries and the `sessionKey` passed to the persistence provider — taking\nprecedence over the DOM `id`. A host that scopes persistence per-entity\n(e.g. one chat session per project) binds this to a stable per-entity id;\nchanging it on a **connected** element re-keys the session in place — tears\ndown the current conversation and restores the new key's — via\n`switchSession`. Falls back to `id` when unset,\nso existing consumers are unaffected.",
6725
- "fieldName": "sessionKey"
6726
- },
6727
- {
6728
- "name": "image-src",
6729
- "type": {
6730
- "text": "string | undefined"
6731
- },
6732
- "fieldName": "imageSrc"
6733
- },
6734
- {
6735
- "name": "user-image-src",
6736
- "type": {
6737
- "text": "string | undefined"
6738
- },
6739
- "fieldName": "userImageSrc"
6740
- },
6741
- {
6742
- "name": "placeholder",
6743
- "type": {
6744
- "text": "string"
6745
- },
6746
- "default": "'Message assistant...'",
6747
- "fieldName": "placeholder"
6748
- },
6749
- {
6750
- "name": "popout-mode",
6751
- "type": {
6752
- "text": "PopoutMode | undefined"
6753
- },
6754
- "description": "Controls the pop-out button shown next to the settings cog.\n\"expand\" — in bubble, expands to layout panel (fires chat-popout).\n\"collapse\" — in layout panel, collapses back to bubble (fires chat-popin).\nAbsent — no button (default standalone behaviour, no breaking change).",
6755
- "fieldName": "popoutMode"
6756
- },
6757
- {
6758
- "name": "debug-redux",
6759
- "type": {
6760
- "text": "boolean"
6761
- },
6762
- "default": "false",
6763
- "description": "When set, enables Redux DevTools for this instance's session store.",
6764
- "fieldName": "debugRedux"
6765
- }
6766
- ],
6767
- "superclass": {
6768
- "name": "GenesisElement",
6769
- "package": "@genesislcap/web-core"
6770
- },
6771
- "tagName": "foundation-ai-assistant",
6772
- "customElement": true
6773
- }
6774
- ],
6775
- "exports": [
6776
- {
6777
- "kind": "js",
6778
- "name": "sparkleIconSvg",
6779
- "declaration": {
6780
- "name": "sparkleIconSvg",
6781
- "module": "src/main/main.ts"
6782
- }
6783
- },
6784
- {
6785
- "kind": "js",
6786
- "name": "userIconSvg",
6787
- "declaration": {
6788
- "name": "userIconSvg",
6789
- "module": "src/main/main.ts"
6790
- }
6791
- },
6792
- {
6793
- "kind": "js",
6794
- "name": "genesisIconSvg",
6795
- "declaration": {
6796
- "name": "genesisIconSvg",
6797
- "module": "src/main/main.ts"
6798
- }
6799
- },
6800
- {
6801
- "kind": "js",
6802
- "name": "budgetPercentOf",
6803
- "declaration": {
6804
- "name": "budgetPercentOf",
6805
- "module": "./budget-controller"
6806
- }
6807
- },
6808
- {
6809
- "kind": "js",
6810
- "name": "formatBlockedReason",
6811
- "declaration": {
6812
- "name": "formatBlockedReason",
6813
- "module": "./budget-controller"
6814
- }
6815
- },
6816
- {
6817
- "kind": "js",
6818
- "name": "FoundationAiAssistant",
6819
- "declaration": {
6820
- "name": "FoundationAiAssistant",
6821
- "module": "src/main/main.ts"
6822
- }
6823
- },
6824
- {
6825
- "kind": "custom-element-definition",
6826
- "name": "foundation-ai-assistant",
6827
- "declaration": {
6828
- "name": "FoundationAiAssistant",
6829
- "module": "src/main/main.ts"
6830
- }
6831
- }
6832
- ]
6833
- },
6834
- {
6835
- "kind": "javascript-module",
6836
- "path": "src/main/main.types.ts",
6837
- "declarations": [
6838
- {
6839
- "kind": "variable",
6840
- "name": "AiAssistantEvent",
6841
- "type": {
6842
- "text": "{\n /** Session wiped via the lifecycle menu's Clear. `detail`: `SessionClearedDetail`. */\n SessionCleared: 'session-cleared',\n /** Header pressed in `popout-mode=\"expand\"` (drag-to-popout hosts). `detail`: `ChatHeaderMouseDownDetail`. */\n ChatHeaderMouseDown: 'chat-header-mousedown',\n}"
6843
- },
6844
- "default": "{\n /** Session wiped via the lifecycle menu's Clear. `detail`: `SessionClearedDetail`. */\n SessionCleared: 'session-cleared',\n /** Header pressed in `popout-mode=\"expand\"` (drag-to-popout hosts). `detail`: `ChatHeaderMouseDownDetail`. */\n ChatHeaderMouseDown: 'chat-header-mousedown',\n}",
6845
- "description": "DOM events the `<foundation-ai-assistant>` element dispatches to its host.\nAll bubble and are `composed` (they cross the shadow boundary), so a host can\nlisten on the element — or any ancestor — to react. Use these constants to\nwire listeners instead of hand-typing event-name strings.\n\nAn `as const` map (not a TS `enum` — this package ships none), so it serves as\nboth the listener-name value and, via the same-named type below, a union."
6846
- },
6847
- {
6848
- "kind": "variable",
6849
- "name": "ANIMATION_DEFS",
6850
- "type": {
6851
- "text": "object"
6852
- },
6853
- "default": "{\n loading: {\n label: 'Dots',\n description: 'Shows pulsing dots while the assistant is generating a response.',\n category: 'Loading style',\n },\n waves: {\n label: 'Waves',\n description:\n 'Shows glowing sine waves inside a circle while the assistant is generating a response.',\n category: 'Loading style',\n },\n flowingWaves: {\n label: 'Flowing waves',\n description:\n 'Shows coloured waves rising and settling from a line while the assistant is generating a response.',\n category: 'Loading style',\n },\n plasma: {\n label: 'Plasma orb',\n description:\n 'Shows a glowing plasma sphere with drifting energy while the assistant is generating a response.',\n category: 'Loading style',\n },\n halo: {\n label: 'Halo',\n description:\n 'Displays a glowing halo around the assistant avatar while a response is streaming.',\n category: 'Effects',\n },\n}",
6854
- "description": "Registry of all available animations with their display metadata.\nAdding an entry here automatically extends the AiAssistantAnimation type."
6855
- },
6856
- {
6857
- "kind": "variable",
6858
- "name": "satisfies",
6859
- "description": "Registry of all available animations with their display metadata.\nAdding an entry here automatically extends the AiAssistantAnimation type."
6860
- },
6861
- {
6862
- "kind": "variable",
6863
- "name": "Record",
6864
- "description": "Registry of all available animations with their display metadata.\nAdding an entry here automatically extends the AiAssistantAnimation type."
6865
- }
6866
- ],
6867
- "exports": [
6868
- {
6869
- "kind": "js",
6870
- "name": "AgentPickerMode",
6871
- "declaration": {
6872
- "name": "AgentPickerMode",
6873
- "package": "@genesislcap/foundation-ai"
6874
- }
6875
- },
6876
- {
6877
- "kind": "js",
6878
- "name": "AiAssistantEvent",
6879
- "declaration": {
6880
- "name": "AiAssistantEvent",
6881
- "module": "src/main/main.types.ts"
6882
- }
6883
- },
6884
- {
6885
- "kind": "js",
6886
- "name": "ANIMATION_DEFS",
6887
- "declaration": {
6888
- "name": "ANIMATION_DEFS",
6889
- "module": "src/main/main.types.ts"
6890
- }
6891
- },
6892
- {
6893
- "kind": "js",
6894
- "name": "satisfies",
6895
- "declaration": {
6896
- "name": "satisfies",
6897
- "module": "src/main/main.types.ts"
6898
- }
6899
- },
6900
- {
6901
- "kind": "js",
6902
- "name": "Record",
6903
- "declaration": {
6904
- "name": "Record",
6905
- "module": "src/main/main.types.ts"
6906
- }
6907
- }
6908
- ]
6909
- },
6910
- {
6911
- "kind": "javascript-module",
6912
- "path": "src/main/meta-snapshot.ts",
6913
- "declarations": [],
6914
- "exports": []
6915
- },
6916
- {
6917
- "kind": "javascript-module",
6918
- "path": "src/provider/ai-provider-switcher.ts",
6919
- "declarations": [
6920
- {
6921
- "kind": "variable",
6922
- "name": "AIProviderSwitcher",
6923
- "description": "The DI token for the (AIProviderSwitcher:interface). Resolves a noop until the app\nregisters one."
6924
- }
6925
- ],
6926
- "exports": [
6927
- {
6928
- "kind": "js",
6929
- "name": "AIProviderSwitcher",
6930
- "declaration": {
6931
- "name": "AIProviderSwitcher",
6932
- "module": "src/provider/ai-provider-switcher.ts"
6933
- }
6934
- }
6935
- ]
6936
- },
6937
- {
6938
- "kind": "javascript-module",
6939
- "path": "src/provider/assistant-app-settings.ts",
6940
- "declarations": [
6941
- {
6942
- "kind": "variable",
6943
- "name": "AssistantAppSettingsProvider",
6944
- "description": "The DI token for the (AssistantAppSettingsProvider:interface). Resolves a noop\nuntil the host registers one."
6945
- }
6946
- ],
6947
- "exports": [
6948
- {
6949
- "kind": "js",
6950
- "name": "AssistantAppSettingsProvider",
6951
- "declaration": {
6952
- "name": "AssistantAppSettingsProvider",
6953
- "module": "src/provider/assistant-app-settings.ts"
6954
- }
6955
- }
6956
- ]
6957
- },
6958
- {
6959
- "kind": "javascript-module",
6960
- "path": "src/provider/tiered-provider-switcher.ts",
6961
- "declarations": [
6962
- {
6963
- "kind": "class",
6964
- "description": "Which cloud vendor backs the tier-shaped provider registry, plus the means to move it at\nruntime (GENC-1610).",
6965
- "name": "TieredAIProviderSwitcher",
6966
- "members": [
6967
- {
6968
- "kind": "field",
6969
- "name": "vendors",
6970
- "type": {
6971
- "text": "readonly AITierVendor[]"
6972
- },
6973
- "readonly": true
6974
- },
6975
- {
6976
- "kind": "field",
6977
- "name": "options",
6978
- "type": {
6979
- "text": "TieredAIProviderSwitcherOptions"
6980
- },
6981
- "privacy": "private",
6982
- "readonly": true,
6983
- "default": "options"
6627
+ "name": "driver",
6628
+ "type": {
6629
+ "text": "AiDriver | undefined"
6630
+ }
6631
+ }
6632
+ ],
6633
+ "description": "Whether the session restored for `key` is no longer the one on screen (GENC-1662): switched in\nplace, or the element disconnected, while the load was in flight."
6984
6634
  },
6985
6635
  {
6986
- "kind": "field",
6987
- "name": "defaultTier",
6988
- "type": {
6989
- "text": "AITierId"
6990
- },
6636
+ "kind": "method",
6637
+ "name": "reactivateRestoredFlow",
6991
6638
  "privacy": "private",
6992
- "readonly": true
6639
+ "return": {
6640
+ "type": {
6641
+ "text": "Promise<void>"
6642
+ }
6643
+ },
6644
+ "parameters": [
6645
+ {
6646
+ "name": "driver",
6647
+ "type": {
6648
+ "text": "AiDriver | undefined"
6649
+ }
6650
+ }
6651
+ ],
6652
+ "description": "Re-activate a restored flow owner (GENC-1662), so a stateful agent's `init({ restored })` — and\nanything the host hangs off it, like a progress stepper — runs straight after the reload\ninstead of on the next message."
6993
6653
  },
6994
6654
  {
6995
- "kind": "field",
6996
- "name": "registry",
6997
- "type": {
6998
- "text": "MutableAIProviderRegistry"
6999
- },
6655
+ "kind": "method",
6656
+ "name": "resumeInterruptedTurn",
7000
6657
  "privacy": "private",
7001
- "readonly": true
6658
+ "return": {
6659
+ "type": {
6660
+ "text": "Promise<void>"
6661
+ }
6662
+ },
6663
+ "parameters": [
6664
+ {
6665
+ "name": "key",
6666
+ "type": {
6667
+ "text": "string"
6668
+ }
6669
+ },
6670
+ {
6671
+ "name": "driver",
6672
+ "type": {
6673
+ "text": "AiDriver | undefined"
6674
+ }
6675
+ },
6676
+ {
6677
+ "name": "ref",
6678
+ "type": {
6679
+ "text": "SessionStoreReturn | undefined"
6680
+ }
6681
+ },
6682
+ {
6683
+ "name": "outcome",
6684
+ "type": {
6685
+ "text": "RestoreOutcome"
6686
+ }
6687
+ }
6688
+ ],
6689
+ "description": "Run the turn a reload interrupted (GENC-1662), shown as busy exactly as a send is — or, when it\ncannot run, withdraw the resume the restore divider promised."
7002
6690
  },
7003
6691
  {
7004
- "kind": "field",
7005
- "name": "listeners",
7006
- "privacy": "private",
7007
- "readonly": true,
7008
- "default": "new Set<(vendor: AITierVendor) => void>()"
6692
+ "kind": "method",
6693
+ "name": "triggerFileInput",
6694
+ "return": {
6695
+ "type": {
6696
+ "text": "void"
6697
+ }
6698
+ }
7009
6699
  },
7010
6700
  {
7011
- "kind": "field",
7012
- "name": "_vendor",
7013
- "type": {
7014
- "text": "AITierVendor"
6701
+ "kind": "method",
6702
+ "name": "handleFileSelect",
6703
+ "return": {
6704
+ "type": {
6705
+ "text": "void"
6706
+ }
7015
6707
  },
7016
- "privacy": "private"
6708
+ "parameters": [
6709
+ {
6710
+ "name": "e",
6711
+ "type": {
6712
+ "text": "Event"
6713
+ }
6714
+ }
6715
+ ]
7017
6716
  },
7018
6717
  {
7019
- "kind": "field",
7020
- "name": "vendor",
7021
- "type": {
7022
- "text": "AITierVendor"
6718
+ "kind": "method",
6719
+ "name": "removeAttachment",
6720
+ "return": {
6721
+ "type": {
6722
+ "text": "void"
6723
+ }
7023
6724
  },
7024
- "readonly": true
6725
+ "parameters": [
6726
+ {
6727
+ "name": "attachment",
6728
+ "type": {
6729
+ "text": "ChatAttachment"
6730
+ }
6731
+ }
6732
+ ]
7025
6733
  },
7026
6734
  {
7027
6735
  "kind": "method",
7028
- "name": "switchTo",
6736
+ "name": "removeAttachmentError",
7029
6737
  "return": {
7030
6738
  "type": {
7031
6739
  "text": "void"
@@ -7033,53 +6741,166 @@
7033
6741
  },
7034
6742
  "parameters": [
7035
6743
  {
7036
- "name": "vendor",
6744
+ "name": "message",
7037
6745
  "type": {
7038
6746
  "text": "string"
7039
6747
  }
7040
6748
  }
7041
- ],
7042
- "description": "A user-driven switch: move the registry, then tell the app so it can persist the choice.\nAn unknown vendor is ignored."
6749
+ ]
7043
6750
  },
7044
6751
  {
7045
6752
  "kind": "method",
7046
- "name": "adoptPersistedVendor",
6753
+ "name": "handleSendClick"
6754
+ },
6755
+ {
6756
+ "kind": "method",
6757
+ "name": "handleStopClick",
6758
+ "description": "User clicked Stop. Cancels the current turn via the driver and flips the\nbutton to \"Stopping…\" until the turn winds down (a tool mid-execution\nfinishes first). Guarded so a second click is a no-op."
6759
+ },
6760
+ {
6761
+ "kind": "method",
6762
+ "name": "handleSuggestionClick",
6763
+ "parameters": [
6764
+ {
6765
+ "name": "suggestion",
6766
+ "type": {
6767
+ "text": "string"
6768
+ }
6769
+ }
6770
+ ]
6771
+ },
6772
+ {
6773
+ "kind": "method",
6774
+ "name": "submitMessage",
7047
6775
  "return": {
7048
6776
  "type": {
7049
- "text": "void"
6777
+ "text": "Promise<SubmitMessageResult>"
7050
6778
  }
7051
6779
  },
7052
6780
  "parameters": [
7053
6781
  {
7054
- "name": "vendor",
6782
+ "name": "input",
7055
6783
  "type": {
7056
- "text": "string"
6784
+ "text": "{ text?: string; files?: File[] }"
7057
6785
  }
7058
6786
  }
7059
6787
  ],
7060
- "description": "Adopt a vendor the app read back from its own store — the same registry move as\nTieredAIProviderSwitcher.switchTo, without the `onSwitch` callback, because this\nvalue came FROM the store and writing it back would be a pointless round-trip on load.\n\nExists because registration has to stay synchronous: an element that connects before the\ntoken is registered caches the platform's no-op fallback, so an app cannot await its\nstored preference before constructing this. It boots on `initialVendor` and adopts the\nstored one a moment later, through a registry that is mutable and held by reference."
6788
+ "description": "Programmatically submit a message. Equivalent to the user typing into the\nbuilt-in composer and pressing send, but callable from external code — most\ncommonly a custom input rendered inside `slot=\"splash\"` when paired with\n`chatConfig.ui.hideComposer`.\n\nThe input fully describes the turn: `text` and `files` REPLACE any current\ncomposer state (they are not appended to it). Files are validated against\n`chatConfig.ui.acceptedFiles` using the same pipeline as the composer's\nattach button.\n\nAtomic on validation: if any file fails validation, no attachments are\ncommitted and no send is dispatched. Failure messages are returned in\n`errors` AND appended to the `attachmentErrors` observable so the built-in\nchip UI still surfaces them when visible.\n\nResolves once the underlying send has been kicked off — it does NOT await\nthe assistant's response."
7061
6789
  },
7062
6790
  {
7063
6791
  "kind": "method",
7064
- "name": "subscribe",
6792
+ "name": "fetchSuggestions",
6793
+ "privacy": "private"
6794
+ },
6795
+ {
6796
+ "kind": "field",
6797
+ "name": "_pendingSendPrompt",
6798
+ "type": {
6799
+ "text": "string | undefined"
6800
+ },
6801
+ "privacy": "private",
6802
+ "description": "User text of the message currently being sent, stashed for the lifetime of `send()`.\n`flow-owner-changed` fires while the driver routes this turn — before the message is\nappended to raw history — so the flow-activation-prompt capture reads this rather than\na stale raw-history lookup. Cleared once the send settles. (GENC-1351 §5.9)"
6803
+ },
6804
+ {
6805
+ "kind": "method",
6806
+ "name": "send",
6807
+ "privacy": "private"
6808
+ },
6809
+ {
6810
+ "kind": "method",
6811
+ "name": "settleAfterTurn",
6812
+ "privacy": "private",
7065
6813
  "return": {
7066
6814
  "type": {
7067
- "text": "() => void"
6815
+ "text": "void"
7068
6816
  }
7069
6817
  },
7070
6818
  "parameters": [
7071
6819
  {
7072
- "name": "listener",
6820
+ "name": "capturedSessionRef",
7073
6821
  "type": {
7074
- "text": "(vendor: string) => void"
6822
+ "text": "SessionStoreReturn | null | undefined"
6823
+ }
6824
+ }
6825
+ ],
6826
+ "description": "The post-turn settle shared by `send()` and a resumed restore turn: back to idle through\nthe session ref captured at turn start, then the cleanup the state setter would have done."
6827
+ },
6828
+ {
6829
+ "kind": "method",
6830
+ "name": "onChatHeaderMouseDown",
6831
+ "parameters": [
6832
+ {
6833
+ "name": "e",
6834
+ "type": {
6835
+ "text": "MouseEvent"
6836
+ }
6837
+ }
6838
+ ]
6839
+ },
6840
+ {
6841
+ "kind": "method",
6842
+ "name": "handleInteractionCompleted",
6843
+ "parameters": [
6844
+ {
6845
+ "name": "e",
6846
+ "type": {
6847
+ "text": "Event"
7075
6848
  }
7076
6849
  }
7077
6850
  ]
7078
6851
  },
7079
6852
  {
7080
6853
  "kind": "method",
7081
- "name": "apply",
7082
- "privacy": "private",
6854
+ "name": "handleInteractionCost",
6855
+ "parameters": [
6856
+ {
6857
+ "name": "e",
6858
+ "type": {
6859
+ "text": "Event"
6860
+ }
6861
+ }
6862
+ ],
6863
+ "description": "A widget reporting spend it incurred AFTER resolving.\n\nNote what this deliberately does NOT do: no `startLoadingTimer()`. This is bookkeeping about a\nturn that already finished, so it must be invisible — showing a spinner would tell the user the\nassistant is working when nothing is pending."
6864
+ },
6865
+ {
6866
+ "kind": "field",
6867
+ "name": "stopButtonVisible",
6868
+ "type": {
6869
+ "text": "boolean"
6870
+ },
6871
+ "description": "Whether the Stop control is showing.\n\nWhile a turn runs Stop REPLACES Send rather than sitting beside it: the two\nare mutually exclusive actions, and a disabled Send next to a live Stop just\ngives the eye a dead control to skip past. Reads `busy`, so `cancelling`\nkeeps it up (in its \"Stopping…\" state) until the turn actually winds down.",
6872
+ "readonly": true
6873
+ },
6874
+ {
6875
+ "kind": "field",
6876
+ "name": "sendButtonVisible",
6877
+ "type": {
6878
+ "text": "boolean"
6879
+ },
6880
+ "description": "Whether Send is rendered at all. Hidden exactly when Stop has taken its\nplace — so a host that suppressed Stop via `hideStopButton` keeps Send\nthroughout, disabled for the duration, and the slot is never left empty\nmid-turn.",
6881
+ "readonly": true
6882
+ },
6883
+ {
6884
+ "kind": "field",
6885
+ "name": "isComposerResizable",
6886
+ "type": {
6887
+ "text": "boolean"
6888
+ },
6889
+ "description": "Whether the message input shows a drag handle to resize its height.",
6890
+ "readonly": true
6891
+ },
6892
+ {
6893
+ "kind": "field",
6894
+ "name": "composerHeightStyle",
6895
+ "type": {
6896
+ "text": "string"
6897
+ },
6898
+ "description": "Inline style carrying the dragged height into `--composer-height`.",
6899
+ "readonly": true
6900
+ },
6901
+ {
6902
+ "kind": "method",
6903
+ "name": "onComposerResizeStart",
7083
6904
  "return": {
7084
6905
  "type": {
7085
6906
  "text": "void"
@@ -7087,96 +6908,275 @@
7087
6908
  },
7088
6909
  "parameters": [
7089
6910
  {
7090
- "name": "vendor",
6911
+ "name": "e",
7091
6912
  "type": {
7092
- "text": "AITierVendor"
6913
+ "text": "PointerEvent"
7093
6914
  }
7094
6915
  }
7095
- ],
7096
- "description": "The registry move both entry points share, and nothing else."
6916
+ ]
7097
6917
  },
7098
6918
  {
7099
6919
  "kind": "method",
7100
- "name": "build",
7101
- "privacy": "private",
6920
+ "name": "onComposerResizeMove",
7102
6921
  "return": {
7103
6922
  "type": {
7104
- "text": "Record<string, AIProvider>"
6923
+ "text": "void"
7105
6924
  }
7106
6925
  },
7107
6926
  "parameters": [
7108
6927
  {
7109
- "name": "vendor",
6928
+ "name": "e",
7110
6929
  "type": {
7111
- "text": "AITierVendor"
6930
+ "text": "PointerEvent"
7112
6931
  }
7113
6932
  }
7114
6933
  ]
7115
6934
  },
7116
6935
  {
7117
6936
  "kind": "method",
7118
- "name": "isKnownVendor",
7119
- "privacy": "private",
6937
+ "name": "onComposerResizeEnd",
7120
6938
  "return": {
7121
6939
  "type": {
7122
- "text": "vendor is AITierVendor"
6940
+ "text": "void"
7123
6941
  }
7124
6942
  },
7125
6943
  "parameters": [
7126
6944
  {
7127
- "name": "vendor",
6945
+ "name": "e",
7128
6946
  "type": {
7129
- "text": "string"
6947
+ "text": "PointerEvent"
7130
6948
  }
7131
6949
  }
7132
6950
  ]
7133
6951
  }
7134
- ]
7135
- },
7136
- {
7137
- "kind": "function",
7138
- "name": "registerTieredAIProviders",
7139
- "return": {
7140
- "type": {
7141
- "text": "TieredAIProviderSwitcher"
7142
- }
7143
- },
7144
- "parameters": [
6952
+ ],
6953
+ "events": [
7145
6954
  {
7146
- "name": "container",
6955
+ "name": "budget-refresh-requested",
7147
6956
  "type": {
7148
- "text": "Container"
6957
+ "text": "CustomEvent"
7149
6958
  }
7150
6959
  },
7151
6960
  {
7152
- "name": "options",
7153
6961
  "type": {
7154
- "text": "Omit<TieredAIProviderSwitcherOptions, 'container'>"
6962
+ "text": "CustomEvent"
7155
6963
  }
6964
+ },
6965
+ {
6966
+ "description": "Fired when the user presses the chat header in `popout-mode=\"expand\"` (for drag-to-popout hosts). Bubbles and composed. detail: `ChatHeaderMouseDownDetail`",
6967
+ "name": "chat-header-mousedown"
6968
+ },
6969
+ {
6970
+ "description": "Fired after the session is wiped (the lifecycle menu's Clear). The payload is captured before teardown so the host can clean up any external state the active agent was working on. Bubbles and composed. detail: `SessionClearedDetail`",
6971
+ "name": "session-cleared"
7156
6972
  }
7157
6973
  ],
7158
- "description": "Build a TieredAIProviderSwitcher — which registers the tier-shaped provider\nregistry — and put it on the (AIProviderSwitcher:variable) token. Call once at app\nbootstrap."
6974
+ "attributes": [
6975
+ {
6976
+ "name": "header-title",
6977
+ "type": {
6978
+ "text": "string"
6979
+ },
6980
+ "default": "'Genesis Assistant'",
6981
+ "fieldName": "headerTitle"
6982
+ },
6983
+ {
6984
+ "name": "session-key",
6985
+ "type": {
6986
+ "text": "string | undefined"
6987
+ },
6988
+ "description": "Explicit session/persistence key (GENC-1351 §5.12). When set, this is the\nsession identity — the key for the driver/store/persister/diagnostics\nregistries and the `sessionKey` passed to the persistence provider — taking\nprecedence over the DOM `id`. A host that scopes persistence per-entity\n(e.g. one chat session per project) binds this to a stable per-entity id;\nchanging it on a **connected** element re-keys the session in place — tears\ndown the current conversation and restores the new key's — via\n`switchSession`. Falls back to `id` when unset,\nso existing consumers are unaffected.",
6989
+ "fieldName": "sessionKey"
6990
+ },
6991
+ {
6992
+ "name": "image-src",
6993
+ "type": {
6994
+ "text": "string | undefined"
6995
+ },
6996
+ "fieldName": "imageSrc"
6997
+ },
6998
+ {
6999
+ "name": "user-image-src",
7000
+ "type": {
7001
+ "text": "string | undefined"
7002
+ },
7003
+ "fieldName": "userImageSrc"
7004
+ },
7005
+ {
7006
+ "name": "placeholder",
7007
+ "type": {
7008
+ "text": "string"
7009
+ },
7010
+ "default": "'Message assistant...'",
7011
+ "fieldName": "placeholder"
7012
+ },
7013
+ {
7014
+ "name": "popout-mode",
7015
+ "type": {
7016
+ "text": "PopoutMode | undefined"
7017
+ },
7018
+ "description": "Controls the pop-out button shown next to the settings cog.\n\"expand\" — in bubble, expands to layout panel (fires chat-popout).\n\"collapse\" — in layout panel, collapses back to bubble (fires chat-popin).\nAbsent — no button (default standalone behaviour, no breaking change).",
7019
+ "fieldName": "popoutMode"
7020
+ },
7021
+ {
7022
+ "name": "debug-redux",
7023
+ "type": {
7024
+ "text": "boolean"
7025
+ },
7026
+ "default": "false",
7027
+ "description": "When set, enables Redux DevTools for this instance's session store.",
7028
+ "fieldName": "debugRedux"
7029
+ }
7030
+ ],
7031
+ "superclass": {
7032
+ "name": "GenesisElement",
7033
+ "package": "@genesislcap/web-core"
7034
+ },
7035
+ "tagName": "foundation-ai-assistant",
7036
+ "customElement": true
7159
7037
  }
7160
7038
  ],
7161
7039
  "exports": [
7162
7040
  {
7163
7041
  "kind": "js",
7164
- "name": "TieredAIProviderSwitcher",
7042
+ "name": "sparkleIconSvg",
7165
7043
  "declaration": {
7166
- "name": "TieredAIProviderSwitcher",
7167
- "module": "src/provider/tiered-provider-switcher.ts"
7044
+ "name": "sparkleIconSvg",
7045
+ "module": "src/main/main.ts"
7168
7046
  }
7169
7047
  },
7170
7048
  {
7171
7049
  "kind": "js",
7172
- "name": "registerTieredAIProviders",
7050
+ "name": "userIconSvg",
7173
7051
  "declaration": {
7174
- "name": "registerTieredAIProviders",
7175
- "module": "src/provider/tiered-provider-switcher.ts"
7052
+ "name": "userIconSvg",
7053
+ "module": "src/main/main.ts"
7054
+ }
7055
+ },
7056
+ {
7057
+ "kind": "js",
7058
+ "name": "genesisIconSvg",
7059
+ "declaration": {
7060
+ "name": "genesisIconSvg",
7061
+ "module": "src/main/main.ts"
7062
+ }
7063
+ },
7064
+ {
7065
+ "kind": "js",
7066
+ "name": "budgetPercentOf",
7067
+ "declaration": {
7068
+ "name": "budgetPercentOf",
7069
+ "module": "./budget-controller"
7070
+ }
7071
+ },
7072
+ {
7073
+ "kind": "js",
7074
+ "name": "formatBlockedReason",
7075
+ "declaration": {
7076
+ "name": "formatBlockedReason",
7077
+ "module": "./budget-controller"
7078
+ }
7079
+ },
7080
+ {
7081
+ "kind": "js",
7082
+ "name": "FoundationAiAssistant",
7083
+ "declaration": {
7084
+ "name": "FoundationAiAssistant",
7085
+ "module": "src/main/main.ts"
7086
+ }
7087
+ },
7088
+ {
7089
+ "kind": "custom-element-definition",
7090
+ "name": "foundation-ai-assistant",
7091
+ "declaration": {
7092
+ "name": "FoundationAiAssistant",
7093
+ "module": "src/main/main.ts"
7094
+ }
7095
+ }
7096
+ ]
7097
+ },
7098
+ {
7099
+ "kind": "javascript-module",
7100
+ "path": "src/main/main.types.ts",
7101
+ "declarations": [
7102
+ {
7103
+ "kind": "variable",
7104
+ "name": "AiAssistantEvent",
7105
+ "type": {
7106
+ "text": "{\n /** Session wiped via the lifecycle menu's Clear. `detail`: `SessionClearedDetail`. */\n SessionCleared: 'session-cleared',\n /** Header pressed in `popout-mode=\"expand\"` (drag-to-popout hosts). `detail`: `ChatHeaderMouseDownDetail`. */\n ChatHeaderMouseDown: 'chat-header-mousedown',\n}"
7107
+ },
7108
+ "default": "{\n /** Session wiped via the lifecycle menu's Clear. `detail`: `SessionClearedDetail`. */\n SessionCleared: 'session-cleared',\n /** Header pressed in `popout-mode=\"expand\"` (drag-to-popout hosts). `detail`: `ChatHeaderMouseDownDetail`. */\n ChatHeaderMouseDown: 'chat-header-mousedown',\n}",
7109
+ "description": "DOM events the `<foundation-ai-assistant>` element dispatches to its host.\nAll bubble and are `composed` (they cross the shadow boundary), so a host can\nlisten on the element — or any ancestor — to react. Use these constants to\nwire listeners instead of hand-typing event-name strings.\n\nAn `as const` map (not a TS `enum` — this package ships none), so it serves as\nboth the listener-name value and, via the same-named type below, a union."
7110
+ },
7111
+ {
7112
+ "kind": "variable",
7113
+ "name": "ANIMATION_DEFS",
7114
+ "type": {
7115
+ "text": "object"
7116
+ },
7117
+ "default": "{\n loading: {\n label: 'Dots',\n description: 'Shows pulsing dots while the assistant is generating a response.',\n category: 'Loading style',\n },\n waves: {\n label: 'Waves',\n description:\n 'Shows glowing sine waves inside a circle while the assistant is generating a response.',\n category: 'Loading style',\n },\n flowingWaves: {\n label: 'Flowing waves',\n description:\n 'Shows coloured waves rising and settling from a line while the assistant is generating a response.',\n category: 'Loading style',\n },\n plasma: {\n label: 'Plasma orb',\n description:\n 'Shows a glowing plasma sphere with drifting energy while the assistant is generating a response.',\n category: 'Loading style',\n },\n halo: {\n label: 'Halo',\n description:\n 'Displays a glowing halo around the assistant avatar while a response is streaming.',\n category: 'Effects',\n },\n}",
7118
+ "description": "Registry of all available animations with their display metadata.\nAdding an entry here automatically extends the AiAssistantAnimation type."
7119
+ },
7120
+ {
7121
+ "kind": "variable",
7122
+ "name": "satisfies",
7123
+ "description": "Registry of all available animations with their display metadata.\nAdding an entry here automatically extends the AiAssistantAnimation type."
7124
+ },
7125
+ {
7126
+ "kind": "variable",
7127
+ "name": "Record",
7128
+ "description": "Registry of all available animations with their display metadata.\nAdding an entry here automatically extends the AiAssistantAnimation type."
7129
+ }
7130
+ ],
7131
+ "exports": [
7132
+ {
7133
+ "kind": "js",
7134
+ "name": "AgentPickerMode",
7135
+ "declaration": {
7136
+ "name": "AgentPickerMode",
7137
+ "package": "@genesislcap/foundation-ai"
7138
+ }
7139
+ },
7140
+ {
7141
+ "kind": "js",
7142
+ "name": "AiAssistantEvent",
7143
+ "declaration": {
7144
+ "name": "AiAssistantEvent",
7145
+ "module": "src/main/main.types.ts"
7146
+ }
7147
+ },
7148
+ {
7149
+ "kind": "js",
7150
+ "name": "ANIMATION_DEFS",
7151
+ "declaration": {
7152
+ "name": "ANIMATION_DEFS",
7153
+ "module": "src/main/main.types.ts"
7154
+ }
7155
+ },
7156
+ {
7157
+ "kind": "js",
7158
+ "name": "satisfies",
7159
+ "declaration": {
7160
+ "name": "satisfies",
7161
+ "module": "src/main/main.types.ts"
7162
+ }
7163
+ },
7164
+ {
7165
+ "kind": "js",
7166
+ "name": "Record",
7167
+ "declaration": {
7168
+ "name": "Record",
7169
+ "module": "src/main/main.types.ts"
7176
7170
  }
7177
7171
  }
7178
7172
  ]
7179
7173
  },
7174
+ {
7175
+ "kind": "javascript-module",
7176
+ "path": "src/main/meta-snapshot.ts",
7177
+ "declarations": [],
7178
+ "exports": []
7179
+ },
7180
7180
  {
7181
7181
  "kind": "javascript-module",
7182
7182
  "path": "src/state/ai-assistant-slice.ts",
@@ -15678,384 +15678,782 @@
15678
15678
  "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."
15679
15679
  },
15680
15680
  {
15681
- "kind": "method",
15682
- "name": "forwardSubAgent",
15683
- "return": {
15684
- "type": {
15685
- "text": "void"
15686
- }
15681
+ "kind": "method",
15682
+ "name": "forwardSubAgent",
15683
+ "return": {
15684
+ "type": {
15685
+ "text": "void"
15686
+ }
15687
+ },
15688
+ "parameters": [
15689
+ {
15690
+ "name": "childSnapshots",
15691
+ "type": {
15692
+ "text": "ReadonlyArray<TurnSnapshot>"
15693
+ }
15694
+ }
15695
+ ],
15696
+ "description": "Merge a sub-agent's turn snapshots into this driver's buffer so they surface\nas `kind:'turn'` entries in the exported debug log. The child runs as a\nseparate, discarded driver, so its snapshots would otherwise be lost. Each is\nre-labelled under the parent turn that activated the sub-agent: the child's\nown (numeric) turns become `\"<parentTurn>-1\"`, `\"-2\"`, … (1-based, in order);\nany already-forwarded grand-child labels (strings) have their leading segment\nremapped the same way, so nesting composes (`\"5-2\"` → `\"5-2-1\"`).\n\nNote: two sub-agents invoked in the *same* parent turn share the prefix, so\ntheir labels can repeat — `agentName` on each snapshot disambiguates them."
15697
+ },
15698
+ {
15699
+ "kind": "method",
15700
+ "name": "foldDiagnostics",
15701
+ "return": {
15702
+ "type": {
15703
+ "text": "void"
15704
+ }
15705
+ },
15706
+ "parameters": [
15707
+ {
15708
+ "name": "interactionId",
15709
+ "type": {
15710
+ "text": "string"
15711
+ }
15712
+ },
15713
+ {
15714
+ "name": "harvested",
15715
+ "type": {
15716
+ "text": "unknown"
15717
+ }
15718
+ }
15719
+ ],
15720
+ "description": "Fold a widget's out-of-band diagnostics into this session — typically a server-side\nChatDriver's collated log, arriving on `InteractionResult.diagnostics` — so the host's debug\nlog and persisted diagnostics stream include them. Independent of the interaction's own\nmessage: these describe the widget's work, not that message. A non-array or empty harvest is\na no-op."
15721
+ },
15722
+ {
15723
+ "kind": "method",
15724
+ "name": "trim",
15725
+ "privacy": "private",
15726
+ "return": {
15727
+ "type": {
15728
+ "text": "void"
15729
+ }
15730
+ },
15731
+ "description": "Hold the ring buffer at its cap, dropping oldest-first."
15732
+ }
15733
+ ]
15734
+ }
15735
+ ],
15736
+ "exports": [
15737
+ {
15738
+ "kind": "js",
15739
+ "name": "TurnRecorder",
15740
+ "declaration": {
15741
+ "name": "TurnRecorder",
15742
+ "module": "src/components/chat-driver/turn-recorder.ts"
15743
+ }
15744
+ }
15745
+ ]
15746
+ },
15747
+ {
15748
+ "kind": "javascript-module",
15749
+ "path": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts",
15750
+ "declarations": [
15751
+ {
15752
+ "kind": "variable",
15753
+ "name": "AiChatInteractionWrapperStyles",
15754
+ "default": "css`\n :host {\n display: block;\n }\n`"
15755
+ }
15756
+ ],
15757
+ "exports": [
15758
+ {
15759
+ "kind": "js",
15760
+ "name": "AiChatInteractionWrapperStyles",
15761
+ "declaration": {
15762
+ "name": "AiChatInteractionWrapperStyles",
15763
+ "module": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts"
15764
+ }
15765
+ }
15766
+ ]
15767
+ },
15768
+ {
15769
+ "kind": "javascript-module",
15770
+ "path": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts",
15771
+ "declarations": [
15772
+ {
15773
+ "kind": "variable",
15774
+ "name": "AiChatInteractionWrapperTemplate",
15775
+ "default": "html<AiChatInteractionWrapper>`\n <div ${ref('container')} class=\"container\" part=\"container\"></div>\n`"
15776
+ }
15777
+ ],
15778
+ "exports": [
15779
+ {
15780
+ "kind": "js",
15781
+ "name": "AiChatInteractionWrapperTemplate",
15782
+ "declaration": {
15783
+ "name": "AiChatInteractionWrapperTemplate",
15784
+ "module": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts"
15785
+ }
15786
+ }
15787
+ ]
15788
+ },
15789
+ {
15790
+ "kind": "javascript-module",
15791
+ "path": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts",
15792
+ "declarations": [
15793
+ {
15794
+ "kind": "class",
15795
+ "description": "Hosts an interactive AI chat sub-component by tag name.",
15796
+ "name": "AiChatInteractionWrapper",
15797
+ "members": [
15798
+ {
15799
+ "kind": "field",
15800
+ "name": "resolved",
15801
+ "type": {
15802
+ "text": "InteractionResult<unknown> | undefined"
15803
+ },
15804
+ "default": "undefined",
15805
+ "description": "The resolved result once the interaction has completed. Forwarded to the rendered component. @internal"
15806
+ },
15807
+ {
15808
+ "kind": "field",
15809
+ "name": "outcome",
15810
+ "type": {
15811
+ "text": "unknown"
15812
+ },
15813
+ "default": "undefined",
15814
+ "description": "See `AiChatInteraction`'s resolved `outcome`: recorded after the answer, by the tool."
15815
+ },
15816
+ {
15817
+ "kind": "field",
15818
+ "name": "_resizeObserver",
15819
+ "type": {
15820
+ "text": "ResizeObserver | undefined"
15821
+ },
15822
+ "privacy": "private",
15823
+ "description": "Observes the rendered widget for mid-lifecycle size changes — see observeWidgetResize."
15824
+ },
15825
+ {
15826
+ "kind": "method",
15827
+ "name": "componentNameChanged"
15828
+ },
15829
+ {
15830
+ "kind": "method",
15831
+ "name": "interactionIdChanged",
15832
+ "description": "Re-render the hosted widget when the interaction identity changes. This\nensures widgets don't go stale with them being rendered with `recycle: true`\nwhen messages are dynamically filtered, showing/hiding thinking/tool calls\n\n`interactionId` is a per-interaction UUID, so it changes exactly when the\nhosted interaction does. Property bindings apply in template order\n(componentName, data, interactionId), so `data` is already rebound by the\ntime this fires and the fresh widget is built with the correct data."
15833
+ },
15834
+ {
15835
+ "kind": "method",
15836
+ "name": "resolvedChanged"
15837
+ },
15838
+ {
15839
+ "kind": "method",
15840
+ "name": "outcomeChanged",
15841
+ "description": "An outcome recorded after the answer reaches a widget already showing that answer."
15842
+ },
15843
+ {
15844
+ "kind": "method",
15845
+ "name": "resolvedInteraction",
15846
+ "privacy": "private",
15847
+ "return": {
15848
+ "type": {
15849
+ "text": "AiChatInteraction"
15850
+ }
15851
+ },
15852
+ "description": "The resolved descriptor, with the outcome when one has been recorded."
15853
+ },
15854
+ {
15855
+ "kind": "method",
15856
+ "name": "observeWidgetResize",
15857
+ "privacy": "private",
15858
+ "parameters": [
15859
+ {
15860
+ "name": "element",
15861
+ "type": {
15862
+ "text": "Element"
15863
+ }
15864
+ }
15865
+ ],
15866
+ "description": "Watch the rendered widget element for box-size changes. When the widget\ngrows or shrinks mid-lifecycle (e.g. expanding a \"More info\" panel,\nappending an SSE status row, revealing generated code), bubble a\n`request-scroll-to-bottom` event so `FoundationAiAssistant` re-snaps to\nthe bottom. `scrollToBottom` respects `_userScrolledAway`, so a user\nreading old messages is not yanked back.\n\nThe first ResizeObserver callback fires synchronously with the initial\nsize when `observe()` is called; we skip it so freshly-rendered widgets\ndon't double up with the existing `handleMessagesUpdate` auto-scroll for\nnew messages."
15867
+ },
15868
+ {
15869
+ "kind": "method",
15870
+ "name": "renderComponent",
15871
+ "privacy": "private"
15872
+ },
15873
+ {
15874
+ "kind": "method",
15875
+ "name": "buildInteraction",
15876
+ "privacy": "private",
15877
+ "return": {
15878
+ "type": {
15879
+ "text": "AiChatInteraction"
15880
+ }
15881
+ },
15882
+ "parameters": [
15883
+ {
15884
+ "name": "host",
15885
+ "type": {
15886
+ "text": "InteractionHost | null"
15887
+ }
15888
+ }
15889
+ ],
15890
+ "description": "Project the wrapper's current `data`/`resolved`/`interactionId` into the\ndiscriminated AiChatInteraction the widget consumes (GENC-1390)."
15891
+ }
15892
+ ],
15893
+ "events": [
15894
+ {
15895
+ "name": "request-scroll-to-bottom",
15896
+ "type": {
15897
+ "text": "CustomEvent"
15898
+ }
15899
+ },
15900
+ {
15901
+ "description": "Fired when the interaction finishes. detail: `InteractionCompletedEventDetail`",
15902
+ "name": "interaction-completed"
15903
+ },
15904
+ {
15905
+ "description": "Fired when a widget spends money AFTER resolving. detail: `InteractionCostEventDetail`",
15906
+ "name": "interaction-cost"
15907
+ }
15908
+ ],
15909
+ "superclass": {
15910
+ "name": "GenesisElement",
15911
+ "package": "@genesislcap/web-core"
15912
+ },
15913
+ "tagName": "ai-chat-interaction-wrapper",
15914
+ "customElement": true
15915
+ }
15916
+ ],
15917
+ "exports": [
15918
+ {
15919
+ "kind": "js",
15920
+ "name": "AiChatInteractionWrapper",
15921
+ "declaration": {
15922
+ "name": "AiChatInteractionWrapper",
15923
+ "module": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts"
15924
+ }
15925
+ },
15926
+ {
15927
+ "kind": "custom-element-definition",
15928
+ "name": "ai-chat-interaction-wrapper",
15929
+ "declaration": {
15930
+ "name": "AiChatInteractionWrapper",
15931
+ "module": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts"
15932
+ }
15933
+ }
15934
+ ]
15935
+ },
15936
+ {
15937
+ "kind": "javascript-module",
15938
+ "path": "src/components/chat-interaction-wrapper/index.ts",
15939
+ "declarations": [],
15940
+ "exports": [
15941
+ {
15942
+ "kind": "js",
15943
+ "name": "*",
15944
+ "declaration": {
15945
+ "name": "*",
15946
+ "package": "./chat-interaction-wrapper"
15947
+ }
15948
+ },
15949
+ {
15950
+ "kind": "js",
15951
+ "name": "*",
15952
+ "declaration": {
15953
+ "name": "*",
15954
+ "package": "./chat-interaction-wrapper.styles"
15955
+ }
15956
+ },
15957
+ {
15958
+ "kind": "js",
15959
+ "name": "*",
15960
+ "declaration": {
15961
+ "name": "*",
15962
+ "package": "./chat-interaction-wrapper.template"
15963
+ }
15964
+ }
15965
+ ]
15966
+ },
15967
+ {
15968
+ "kind": "javascript-module",
15969
+ "path": "src/components/chat-markdown/chat-markdown.ts",
15970
+ "declarations": [
15971
+ {
15972
+ "kind": "variable",
15973
+ "name": "MARKDOWN_EXPORTPARTS",
15974
+ "type": {
15975
+ "text": "string"
15976
+ },
15977
+ "description": "Every part this component exposes, as an `exportparts` value.\n\n`::part()` crosses exactly one shadow boundary, so a host that renders `<ai-chat-markdown>` in\nits own shadow root has to forward these for an app to reach them at all. Built from the map\nabove rather than written out, so the forwarded list cannot drift from what is emitted."
15978
+ },
15979
+ {
15980
+ "kind": "class",
15981
+ "description": "",
15982
+ "name": "AiChatMarkdown",
15983
+ "members": [
15984
+ {
15985
+ "kind": "field",
15986
+ "name": "content",
15987
+ "type": {
15988
+ "text": "string"
15687
15989
  },
15688
- "parameters": [
15689
- {
15690
- "name": "childSnapshots",
15691
- "type": {
15692
- "text": "ReadonlyArray<TurnSnapshot>"
15693
- }
15694
- }
15695
- ],
15696
- "description": "Merge a sub-agent's turn snapshots into this driver's buffer so they surface\nas `kind:'turn'` entries in the exported debug log. The child runs as a\nseparate, discarded driver, so its snapshots would otherwise be lost. Each is\nre-labelled under the parent turn that activated the sub-agent: the child's\nown (numeric) turns become `\"<parentTurn>-1\"`, `\"-2\"`, … (1-based, in order);\nany already-forwarded grand-child labels (strings) have their leading segment\nremapped the same way, so nesting composes (`\"5-2\"` → `\"5-2-1\"`).\n\nNote: two sub-agents invoked in the *same* parent turn share the prefix, so\ntheir labels can repeat — `agentName` on each snapshot disambiguates them."
15990
+ "default": "''",
15991
+ "description": "The markdown string to render."
15697
15992
  },
15698
15993
  {
15699
15994
  "kind": "method",
15700
- "name": "foldDiagnostics",
15995
+ "name": "annotateParts",
15996
+ "privacy": "private",
15701
15997
  "return": {
15702
15998
  "type": {
15703
- "text": "void"
15999
+ "text": "string"
15704
16000
  }
15705
16001
  },
15706
16002
  "parameters": [
15707
16003
  {
15708
- "name": "interactionId",
15709
- "type": {
15710
- "text": "string"
15711
- }
15712
- },
15713
- {
15714
- "name": "harvested",
16004
+ "name": "fragment",
15715
16005
  "type": {
15716
- "text": "unknown"
16006
+ "text": "DocumentFragment"
15717
16007
  }
15718
16008
  }
15719
16009
  ],
15720
- "description": "Fold a widget's out-of-band diagnostics into this session — typically a server-side\nChatDriver's collated log, arriving on `InteractionResult.diagnostics` — so the host's debug\nlog and persisted diagnostics stream include them. Independent of the interaction's own\nmessage: these describe the widget's work, not that message. A non-array or empty harvest is\na no-op."
15721
- },
15722
- {
15723
- "kind": "method",
15724
- "name": "trim",
15725
- "privacy": "private",
15726
- "return": {
15727
- "type": {
15728
- "text": "void"
15729
- }
15730
- },
15731
- "description": "Hold the ring buffer at its cap, dropping oldest-first."
16010
+ "description": "Tag the generated elements with shadow parts so an embedding app can style them.\n\nTakes the tree DOMPurify built rather than re-parsing its serialised output: `content` changes\non every streamed chunk, so a second parse/serialise round trip would run per chunk over the\nwhole message, and the string the browser finally parses is then serialised straight from the\ntree DOMPurify checked. Parse/serialise mismatches are where mXSS bypasses have historically\nlived, and this walk has no need to introduce one.\n\nOnly ever *adds* attributes, to DOM that has already been cleared - so it is not itself\nsanitiser surface.\n\nLists additionally carry a level: a top-level list is `md-ul md-ul-level-1`, a list nested\ninside it is `md-ul-level-2`, and an `li` takes the level of the list holding it. Levels are\nclamped at `MAX_LIST_LEVEL`, so a list deeper than that answers to the deepest level\nrather than to a name no host forwards. Chat markdown rarely nests, so this is a safety valve\nrather than a feature - without it, every list at every depth would answer to one selector and\nthere would be no way to tell them apart afterwards. Depth comes from walking the tree rather\nthan from marked's renderers, which are invoked innermost-first and so cannot count downwards."
15732
16011
  }
15733
- ]
16012
+ ],
16013
+ "superclass": {
16014
+ "name": "GenesisElement",
16015
+ "package": "@genesislcap/web-core"
16016
+ },
16017
+ "tagName": "ai-chat-markdown",
16018
+ "customElement": true
15734
16019
  }
15735
16020
  ],
15736
16021
  "exports": [
15737
16022
  {
15738
16023
  "kind": "js",
15739
- "name": "TurnRecorder",
16024
+ "name": "MARKDOWN_EXPORTPARTS",
15740
16025
  "declaration": {
15741
- "name": "TurnRecorder",
15742
- "module": "src/components/chat-driver/turn-recorder.ts"
16026
+ "name": "MARKDOWN_EXPORTPARTS",
16027
+ "module": "src/components/chat-markdown/chat-markdown.ts"
16028
+ }
16029
+ },
16030
+ {
16031
+ "kind": "js",
16032
+ "name": "AiChatMarkdown",
16033
+ "declaration": {
16034
+ "name": "AiChatMarkdown",
16035
+ "module": "src/components/chat-markdown/chat-markdown.ts"
16036
+ }
16037
+ },
16038
+ {
16039
+ "kind": "custom-element-definition",
16040
+ "name": "ai-chat-markdown",
16041
+ "declaration": {
16042
+ "name": "AiChatMarkdown",
16043
+ "module": "src/components/chat-markdown/chat-markdown.ts"
15743
16044
  }
15744
16045
  }
15745
16046
  ]
15746
16047
  },
15747
16048
  {
15748
16049
  "kind": "javascript-module",
15749
- "path": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts",
16050
+ "path": "src/components/chat-markdown/index.ts",
16051
+ "declarations": [],
16052
+ "exports": [
16053
+ {
16054
+ "kind": "js",
16055
+ "name": "*",
16056
+ "declaration": {
16057
+ "name": "*",
16058
+ "package": "./chat-markdown"
16059
+ }
16060
+ }
16061
+ ]
16062
+ },
16063
+ {
16064
+ "kind": "javascript-module",
16065
+ "path": "src/components/message-feedback/index.ts",
16066
+ "declarations": [],
16067
+ "exports": [
16068
+ {
16069
+ "kind": "js",
16070
+ "name": "*",
16071
+ "declaration": {
16072
+ "name": "*",
16073
+ "package": "./message-feedback"
16074
+ }
16075
+ }
16076
+ ]
16077
+ },
16078
+ {
16079
+ "kind": "javascript-module",
16080
+ "path": "src/components/message-feedback/message-feedback.styles.ts",
15750
16081
  "declarations": [
15751
16082
  {
15752
16083
  "kind": "variable",
15753
- "name": "AiChatInteractionWrapperStyles",
15754
- "default": "css`\n :host {\n display: block;\n }\n`"
16084
+ "name": "styles",
16085
+ "default": "css`\n :host {\n display: block;\n margin-top: calc(var(--design-unit) * 1.5px);\n font-size: 13px;\n }\n\n .thumbs {\n display: flex;\n gap: 2px;\n }\n\n .thumb {\n appearance: none;\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n padding: 0;\n border: none;\n border-radius: calc(var(--control-corner-radius) * 1px);\n background: transparent;\n color: inherit;\n font-size: 12px;\n opacity: 65%;\n cursor: pointer;\n }\n\n .thumb:hover,\n .thumb:focus-visible,\n .thumb[aria-pressed='true'] {\n opacity: 100%;\n }\n\n .thumb:hover {\n background: var(--neutral-fill-stealth-hover);\n }\n\n .thumb:focus-visible {\n outline: calc(var(--focus-stroke-width) * 1px) solid var(--focus-stroke-outer);\n outline-offset: 1px;\n }\n\n .thumb:disabled {\n cursor: default;\n }\n\n .panel {\n display: flex;\n flex-direction: column;\n gap: calc(var(--design-unit) * 2px);\n margin-top: calc(var(--design-unit) * 1px);\n }\n\n .panel-title {\n margin: 0;\n font-weight: 600;\n }\n\n .note {\n width: 100%;\n }\n\n .hint {\n margin: 0;\n font-size: 11px;\n line-height: 1.4;\n color: var(--neutral-foreground-hint);\n }\n\n .hint.is-error {\n color: var(--error-color);\n }\n\n .actions {\n display: flex;\n justify-content: flex-end;\n gap: calc(var(--design-unit) * 2px);\n }\n\n .visually-hidden {\n position: absolute;\n width: 1px;\n height: 1px;\n margin: -1px;\n padding: 0;\n overflow: hidden;\n clip-path: inset(50%);\n white-space: nowrap;\n border: 0;\n }\n`"
15755
16086
  }
15756
16087
  ],
15757
16088
  "exports": [
15758
16089
  {
15759
16090
  "kind": "js",
15760
- "name": "AiChatInteractionWrapperStyles",
16091
+ "name": "styles",
15761
16092
  "declaration": {
15762
- "name": "AiChatInteractionWrapperStyles",
15763
- "module": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts"
16093
+ "name": "styles",
16094
+ "module": "src/components/message-feedback/message-feedback.styles.ts"
15764
16095
  }
15765
16096
  }
15766
16097
  ]
15767
16098
  },
15768
16099
  {
15769
16100
  "kind": "javascript-module",
15770
- "path": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts",
16101
+ "path": "src/components/message-feedback/message-feedback.template.ts",
15771
16102
  "declarations": [
15772
16103
  {
15773
- "kind": "variable",
15774
- "name": "AiChatInteractionWrapperTemplate",
15775
- "default": "html<AiChatInteractionWrapper>`\n <div ${ref('container')} class=\"container\" part=\"container\"></div>\n`"
16104
+ "kind": "function",
16105
+ "name": "MessageFeedbackTemplate",
16106
+ "return": {
16107
+ "type": {
16108
+ "text": "ViewTemplate<MessageFeedback>"
16109
+ }
16110
+ },
16111
+ "parameters": [
16112
+ {
16113
+ "name": "designSystemPrefix",
16114
+ "type": {
16115
+ "text": "string"
16116
+ }
16117
+ }
16118
+ ]
15776
16119
  }
15777
16120
  ],
15778
16121
  "exports": [
15779
16122
  {
15780
16123
  "kind": "js",
15781
- "name": "AiChatInteractionWrapperTemplate",
16124
+ "name": "MessageFeedbackTemplate",
15782
16125
  "declaration": {
15783
- "name": "AiChatInteractionWrapperTemplate",
15784
- "module": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts"
16126
+ "name": "MessageFeedbackTemplate",
16127
+ "module": "src/components/message-feedback/message-feedback.template.ts"
15785
16128
  }
15786
16129
  }
15787
16130
  ]
15788
16131
  },
15789
16132
  {
15790
16133
  "kind": "javascript-module",
15791
- "path": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts",
16134
+ "path": "src/components/message-feedback/message-feedback.ts",
15792
16135
  "declarations": [
16136
+ {
16137
+ "kind": "function",
16138
+ "name": "isRateableReply",
16139
+ "return": {
16140
+ "type": {
16141
+ "text": "boolean"
16142
+ }
16143
+ },
16144
+ "parameters": [
16145
+ {
16146
+ "name": "m",
16147
+ "type": {
16148
+ "text": "ChatMessage"
16149
+ }
16150
+ }
16151
+ ],
16152
+ "description": "A final assistant reply, including the assistant's own notices: not reasoning, narration, a\ntool call, a tool result or a widget. Agrees with `filterVisibleMessages` on what is shown."
16153
+ },
16154
+ {
16155
+ "kind": "function",
16156
+ "name": "replyKey",
16157
+ "return": {
16158
+ "type": {
16159
+ "text": "string"
16160
+ }
16161
+ },
16162
+ "parameters": [
16163
+ {
16164
+ "name": "m",
16165
+ "type": {
16166
+ "text": "ChatMessage"
16167
+ }
16168
+ }
16169
+ ],
16170
+ "description": "Survives the message object being replaced and the session being reloaded, which object\nidentity does not. Replies saved before timestamps existed fall back to their content."
16171
+ },
16172
+ {
16173
+ "kind": "variable",
16174
+ "name": "MESSAGE_FEEDBACK_EXPORTPARTS",
16175
+ "description": "Forwarded by the assistant so `::part()` reaches inside from the host app."
16176
+ },
15793
16177
  {
15794
16178
  "kind": "class",
15795
- "description": "Hosts an interactive AI chat sub-component by tag name.",
15796
- "name": "AiChatInteractionWrapper",
16179
+ "description": "Thumbs up / thumbs down under one assistant reply, with a note panel for the pressed thumb.\nRendered by the assistant only when `chatConfig.ui.messageFeedback` is set.",
16180
+ "name": "MessageFeedback",
15797
16181
  "members": [
15798
16182
  {
15799
16183
  "kind": "field",
15800
- "name": "resolved",
16184
+ "name": "designSystemPrefix",
16185
+ "type": {
16186
+ "text": "string"
16187
+ },
16188
+ "default": "'rapid'"
16189
+ },
16190
+ {
16191
+ "kind": "field",
16192
+ "name": "message",
16193
+ "type": {
16194
+ "text": "ChatMessage | undefined"
16195
+ }
16196
+ },
16197
+ {
16198
+ "kind": "field",
16199
+ "name": "description",
16200
+ "type": {
16201
+ "text": "string"
16202
+ },
16203
+ "default": "''"
16204
+ },
16205
+ {
16206
+ "kind": "field",
16207
+ "name": "submit",
16208
+ "type": {
16209
+ "text": "MessageFeedbackSubmit | undefined"
16210
+ }
16211
+ },
16212
+ {
16213
+ "kind": "field",
16214
+ "name": "open",
16215
+ "type": {
16216
+ "text": "boolean"
16217
+ },
16218
+ "default": "false",
16219
+ "description": "Reflected so the assistant's reveal CSS can keep an open panel visible."
16220
+ },
16221
+ {
16222
+ "kind": "field",
16223
+ "name": "draftRating",
15801
16224
  "type": {
15802
- "text": "InteractionResult<unknown> | undefined"
16225
+ "text": "ChatMessageFeedbackRating | null"
15803
16226
  },
15804
- "default": "undefined",
15805
- "description": "The resolved result once the interaction has completed. Forwarded to the rendered component. @internal"
16227
+ "default": "null",
16228
+ "description": "The thumb the open panel belongs to."
15806
16229
  },
15807
16230
  {
15808
16231
  "kind": "field",
15809
- "name": "outcome",
16232
+ "name": "sentRating",
15810
16233
  "type": {
15811
- "text": "unknown"
16234
+ "text": "ChatMessageFeedbackRating | null"
15812
16235
  },
15813
- "default": "undefined",
15814
- "description": "See `AiChatInteraction`'s resolved `outcome`: recorded after the answer, by the tool."
16236
+ "default": "null",
16237
+ "description": "The rating last sent for this reply; reflected so a rated reply keeps its thumbs visible."
15815
16238
  },
15816
16239
  {
15817
16240
  "kind": "field",
15818
- "name": "_resizeObserver",
16241
+ "name": "note",
15819
16242
  "type": {
15820
- "text": "ResizeObserver | undefined"
16243
+ "text": "string"
15821
16244
  },
15822
- "privacy": "private",
15823
- "description": "Observes the rendered widget for mid-lifecycle size changes — see observeWidgetResize."
16245
+ "default": "''"
15824
16246
  },
15825
16247
  {
15826
- "kind": "method",
15827
- "name": "componentNameChanged"
16248
+ "kind": "field",
16249
+ "name": "status",
16250
+ "type": {
16251
+ "text": "MessageFeedbackStatus"
16252
+ },
16253
+ "default": "'idle'"
15828
16254
  },
15829
16255
  {
15830
- "kind": "method",
15831
- "name": "interactionIdChanged",
15832
- "description": "Re-render the hosted widget when the interaction identity changes. This\nensures widgets don't go stale with them being rendered with `recycle: true`\nwhen messages are dynamically filtered, showing/hiding thinking/tool calls\n\n`interactionId` is a per-interaction UUID, so it changes exactly when the\nhosted interaction does. Property bindings apply in template order\n(componentName, data, interactionId), so `data` is already rebound by the\ntime this fires and the fresh widget is built with the correct data."
16256
+ "kind": "field",
16257
+ "name": "announcement",
16258
+ "type": {
16259
+ "text": "string"
16260
+ },
16261
+ "default": "''"
16262
+ },
16263
+ {
16264
+ "kind": "field",
16265
+ "name": "sendGeneration",
16266
+ "type": {
16267
+ "text": "number"
16268
+ },
16269
+ "privacy": "private",
16270
+ "default": "0",
16271
+ "description": "Bumped to disown an in-flight send: on Cancel, and when the row is rebound."
15833
16272
  },
15834
16273
  {
15835
16274
  "kind": "method",
15836
- "name": "resolvedChanged"
16275
+ "name": "messageChanged",
16276
+ "return": {
16277
+ "type": {
16278
+ "text": "void"
16279
+ }
16280
+ },
16281
+ "parameters": [
16282
+ {
16283
+ "name": "prev",
16284
+ "optional": true,
16285
+ "type": {
16286
+ "text": "ChatMessage"
16287
+ }
16288
+ },
16289
+ {
16290
+ "name": "next",
16291
+ "optional": true,
16292
+ "type": {
16293
+ "text": "ChatMessage"
16294
+ }
16295
+ }
16296
+ ]
16297
+ },
16298
+ {
16299
+ "kind": "field",
16300
+ "name": "activeRating",
16301
+ "type": {
16302
+ "text": "ChatMessageFeedbackRating | null"
16303
+ },
16304
+ "description": "The thumb that reads as pressed: the open panel's, else the one already sent.",
16305
+ "readonly": true
15837
16306
  },
15838
16307
  {
15839
16308
  "kind": "method",
15840
- "name": "outcomeChanged",
15841
- "description": "An outcome recorded after the answer reaches a widget already showing that answer."
16309
+ "name": "toggle",
16310
+ "return": {
16311
+ "type": {
16312
+ "text": "void"
16313
+ }
16314
+ },
16315
+ "parameters": [
16316
+ {
16317
+ "name": "rating",
16318
+ "type": {
16319
+ "text": "ChatMessageFeedbackRating"
16320
+ }
16321
+ }
16322
+ ]
15842
16323
  },
15843
16324
  {
15844
16325
  "kind": "method",
15845
- "name": "resolvedInteraction",
15846
- "privacy": "private",
16326
+ "name": "cancel",
15847
16327
  "return": {
15848
16328
  "type": {
15849
- "text": "AiChatInteraction"
16329
+ "text": "void"
15850
16330
  }
15851
16331
  },
15852
- "description": "The resolved descriptor, with the outcome when one has been recorded."
16332
+ "description": "Also abandons an in-flight send, so a hung transport cannot trap the user in the panel."
15853
16333
  },
15854
16334
  {
15855
16335
  "kind": "method",
15856
- "name": "observeWidgetResize",
15857
- "privacy": "private",
16336
+ "name": "noteInput",
16337
+ "return": {
16338
+ "type": {
16339
+ "text": "void"
16340
+ }
16341
+ },
15858
16342
  "parameters": [
15859
16343
  {
15860
- "name": "element",
16344
+ "name": "value",
15861
16345
  "type": {
15862
- "text": "Element"
16346
+ "text": "string"
15863
16347
  }
15864
16348
  }
15865
- ],
15866
- "description": "Watch the rendered widget element for box-size changes. When the widget\ngrows or shrinks mid-lifecycle (e.g. expanding a \"More info\" panel,\nappending an SSE status row, revealing generated code), bubble a\n`request-scroll-to-bottom` event so `FoundationAiAssistant` re-snaps to\nthe bottom. `scrollToBottom` respects `_userScrolledAway`, so a user\nreading old messages is not yanked back.\n\nThe first ResizeObserver callback fires synchronously with the initial\nsize when `observe()` is called; we skip it so freshly-rendered widgets\ndon't double up with the existing `handleMessagesUpdate` auto-scroll for\nnew messages."
16349
+ ]
15867
16350
  },
15868
16351
  {
15869
16352
  "kind": "method",
15870
- "name": "renderComponent",
15871
- "privacy": "private"
16353
+ "name": "send",
16354
+ "return": {
16355
+ "type": {
16356
+ "text": "Promise<void>"
16357
+ }
16358
+ }
15872
16359
  },
15873
16360
  {
15874
16361
  "kind": "method",
15875
- "name": "buildInteraction",
16362
+ "name": "restoreThumbFocus",
15876
16363
  "privacy": "private",
15877
16364
  "return": {
15878
16365
  "type": {
15879
- "text": "AiChatInteraction"
16366
+ "text": "void"
15880
16367
  }
15881
16368
  },
15882
16369
  "parameters": [
15883
16370
  {
15884
- "name": "host",
16371
+ "name": "rating",
15885
16372
  "type": {
15886
- "text": "InteractionHost | null"
16373
+ "text": "ChatMessageFeedbackRating | null"
15887
16374
  }
15888
16375
  }
15889
16376
  ],
15890
- "description": "Project the wrapper's current `data`/`resolved`/`interactionId` into the\ndiscriminated AiChatInteraction the widget consumes (GENC-1390)."
16377
+ "description": "Closing the panel unmounts the focused note; hand focus back to the thumb that opened it."
16378
+ },
16379
+ {
16380
+ "kind": "method",
16381
+ "name": "ownsFocus",
16382
+ "privacy": "private",
16383
+ "return": {
16384
+ "type": {
16385
+ "text": "boolean"
16386
+ }
16387
+ },
16388
+ "description": "Focus is ours to move only while it is nowhere in particular or still inside this element —\nnot once the user has gone on to type in the composer during a slow send. Walks the shadow\nroots, since `document.activeElement` is the assistant host for both."
15891
16389
  }
15892
16390
  ],
15893
- "events": [
16391
+ "attributes": [
15894
16392
  {
15895
- "name": "request-scroll-to-bottom",
15896
16393
  "type": {
15897
- "text": "CustomEvent"
15898
- }
15899
- },
15900
- {
15901
- "description": "Fired when the interaction finishes. detail: `InteractionCompletedEventDetail`",
15902
- "name": "interaction-completed"
16394
+ "text": "boolean"
16395
+ },
16396
+ "default": "false",
16397
+ "description": "Reflected so the assistant's reveal CSS can keep an open panel visible.",
16398
+ "fieldName": "open"
15903
16399
  },
15904
16400
  {
15905
- "description": "Fired when a widget spends money AFTER resolving. detail: `InteractionCostEventDetail`",
15906
- "name": "interaction-cost"
16401
+ "name": "rated",
16402
+ "type": {
16403
+ "text": "ChatMessageFeedbackRating | null"
16404
+ },
16405
+ "default": "null",
16406
+ "description": "The rating last sent for this reply; reflected so a rated reply keeps its thumbs visible.",
16407
+ "fieldName": "sentRating"
15907
16408
  }
15908
16409
  ],
15909
16410
  "superclass": {
15910
16411
  "name": "GenesisElement",
15911
16412
  "package": "@genesislcap/web-core"
15912
16413
  },
15913
- "tagName": "ai-chat-interaction-wrapper",
16414
+ "tagName": "foundation-ai-message-feedback",
15914
16415
  "customElement": true
15915
16416
  }
15916
16417
  ],
15917
16418
  "exports": [
15918
16419
  {
15919
16420
  "kind": "js",
15920
- "name": "AiChatInteractionWrapper",
15921
- "declaration": {
15922
- "name": "AiChatInteractionWrapper",
15923
- "module": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts"
15924
- }
15925
- },
15926
- {
15927
- "kind": "custom-element-definition",
15928
- "name": "ai-chat-interaction-wrapper",
15929
- "declaration": {
15930
- "name": "AiChatInteractionWrapper",
15931
- "module": "src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts"
15932
- }
15933
- }
15934
- ]
15935
- },
15936
- {
15937
- "kind": "javascript-module",
15938
- "path": "src/components/chat-interaction-wrapper/index.ts",
15939
- "declarations": [],
15940
- "exports": [
15941
- {
15942
- "kind": "js",
15943
- "name": "*",
15944
- "declaration": {
15945
- "name": "*",
15946
- "package": "./chat-interaction-wrapper"
15947
- }
15948
- },
15949
- {
15950
- "kind": "js",
15951
- "name": "*",
16421
+ "name": "isRateableReply",
15952
16422
  "declaration": {
15953
- "name": "*",
15954
- "package": "./chat-interaction-wrapper.styles"
16423
+ "name": "isRateableReply",
16424
+ "module": "src/components/message-feedback/message-feedback.ts"
15955
16425
  }
15956
16426
  },
15957
16427
  {
15958
16428
  "kind": "js",
15959
- "name": "*",
16429
+ "name": "replyKey",
15960
16430
  "declaration": {
15961
- "name": "*",
15962
- "package": "./chat-interaction-wrapper.template"
16431
+ "name": "replyKey",
16432
+ "module": "src/components/message-feedback/message-feedback.ts"
15963
16433
  }
15964
- }
15965
- ]
15966
- },
15967
- {
15968
- "kind": "javascript-module",
15969
- "path": "src/components/chat-markdown/chat-markdown.ts",
15970
- "declarations": [
15971
- {
15972
- "kind": "variable",
15973
- "name": "MARKDOWN_EXPORTPARTS",
15974
- "type": {
15975
- "text": "string"
15976
- },
15977
- "description": "Every part this component exposes, as an `exportparts` value.\n\n`::part()` crosses exactly one shadow boundary, so a host that renders `<ai-chat-markdown>` in\nits own shadow root has to forward these for an app to reach them at all. Built from the map\nabove rather than written out, so the forwarded list cannot drift from what is emitted."
15978
16434
  },
15979
- {
15980
- "kind": "class",
15981
- "description": "",
15982
- "name": "AiChatMarkdown",
15983
- "members": [
15984
- {
15985
- "kind": "field",
15986
- "name": "content",
15987
- "type": {
15988
- "text": "string"
15989
- },
15990
- "default": "''",
15991
- "description": "The markdown string to render."
15992
- },
15993
- {
15994
- "kind": "method",
15995
- "name": "annotateParts",
15996
- "privacy": "private",
15997
- "return": {
15998
- "type": {
15999
- "text": "string"
16000
- }
16001
- },
16002
- "parameters": [
16003
- {
16004
- "name": "fragment",
16005
- "type": {
16006
- "text": "DocumentFragment"
16007
- }
16008
- }
16009
- ],
16010
- "description": "Tag the generated elements with shadow parts so an embedding app can style them.\n\nTakes the tree DOMPurify built rather than re-parsing its serialised output: `content` changes\non every streamed chunk, so a second parse/serialise round trip would run per chunk over the\nwhole message, and the string the browser finally parses is then serialised straight from the\ntree DOMPurify checked. Parse/serialise mismatches are where mXSS bypasses have historically\nlived, and this walk has no need to introduce one.\n\nOnly ever *adds* attributes, to DOM that has already been cleared - so it is not itself\nsanitiser surface.\n\nLists additionally carry a level: a top-level list is `md-ul md-ul-level-1`, a list nested\ninside it is `md-ul-level-2`, and an `li` takes the level of the list holding it. Levels are\nclamped at `MAX_LIST_LEVEL`, so a list deeper than that answers to the deepest level\nrather than to a name no host forwards. Chat markdown rarely nests, so this is a safety valve\nrather than a feature - without it, every list at every depth would answer to one selector and\nthere would be no way to tell them apart afterwards. Depth comes from walking the tree rather\nthan from marked's renderers, which are invoked innermost-first and so cannot count downwards."
16011
- }
16012
- ],
16013
- "superclass": {
16014
- "name": "GenesisElement",
16015
- "package": "@genesislcap/web-core"
16016
- },
16017
- "tagName": "ai-chat-markdown",
16018
- "customElement": true
16019
- }
16020
- ],
16021
- "exports": [
16022
16435
  {
16023
16436
  "kind": "js",
16024
- "name": "MARKDOWN_EXPORTPARTS",
16437
+ "name": "MESSAGE_FEEDBACK_EXPORTPARTS",
16025
16438
  "declaration": {
16026
- "name": "MARKDOWN_EXPORTPARTS",
16027
- "module": "src/components/chat-markdown/chat-markdown.ts"
16439
+ "name": "MESSAGE_FEEDBACK_EXPORTPARTS",
16440
+ "module": "src/components/message-feedback/message-feedback.ts"
16028
16441
  }
16029
16442
  },
16030
16443
  {
16031
16444
  "kind": "js",
16032
- "name": "AiChatMarkdown",
16445
+ "name": "MessageFeedback",
16033
16446
  "declaration": {
16034
- "name": "AiChatMarkdown",
16035
- "module": "src/components/chat-markdown/chat-markdown.ts"
16447
+ "name": "MessageFeedback",
16448
+ "module": "src/components/message-feedback/message-feedback.ts"
16036
16449
  }
16037
16450
  },
16038
16451
  {
16039
16452
  "kind": "custom-element-definition",
16040
- "name": "ai-chat-markdown",
16041
- "declaration": {
16042
- "name": "AiChatMarkdown",
16043
- "module": "src/components/chat-markdown/chat-markdown.ts"
16044
- }
16045
- }
16046
- ]
16047
- },
16048
- {
16049
- "kind": "javascript-module",
16050
- "path": "src/components/chat-markdown/index.ts",
16051
- "declarations": [],
16052
- "exports": [
16053
- {
16054
- "kind": "js",
16055
- "name": "*",
16453
+ "name": "foundation-ai-message-feedback",
16056
16454
  "declaration": {
16057
- "name": "*",
16058
- "package": "./chat-markdown"
16455
+ "name": "MessageFeedback",
16456
+ "module": "src/components/message-feedback/message-feedback.ts"
16059
16457
  }
16060
16458
  }
16061
16459
  ]