@genesislcap/ai-assistant 14.403.0-ai-assistant.1

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 (244) hide show
  1. package/api-extractor.json +4 -0
  2. package/dist/ai-assistant.api.json +4028 -0
  3. package/dist/ai-assistant.d.ts +396 -0
  4. package/dist/dts/channel/ai-activity-channel.d.ts +32 -0
  5. package/dist/dts/channel/ai-activity-channel.d.ts.map +1 -0
  6. package/dist/dts/components/activity-halo/activity-halo.d.ts +31 -0
  7. package/dist/dts/components/activity-halo/activity-halo.d.ts.map +1 -0
  8. package/dist/dts/components/chat-bubble/chat-bubble.d.ts +52 -0
  9. package/dist/dts/components/chat-bubble/chat-bubble.d.ts.map +1 -0
  10. package/dist/dts/components/chat-bubble/chat-bubble.styles.d.ts +2 -0
  11. package/dist/dts/components/chat-bubble/chat-bubble.styles.d.ts.map +1 -0
  12. package/dist/dts/components/chat-bubble/chat-bubble.template.d.ts +4 -0
  13. package/dist/dts/components/chat-bubble/chat-bubble.template.d.ts.map +1 -0
  14. package/dist/dts/components/chat-bubble/index.d.ts +2 -0
  15. package/dist/dts/components/chat-bubble/index.d.ts.map +1 -0
  16. package/dist/dts/components/chat-driver/chat-driver.d.ts +49 -0
  17. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -0
  18. package/dist/dts/components/chat-driver/index.d.ts +2 -0
  19. package/dist/dts/components/chat-driver/index.d.ts.map +1 -0
  20. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts +19 -0
  21. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.d.ts.map +1 -0
  22. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.d.ts +2 -0
  23. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.d.ts.map +1 -0
  24. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.template.d.ts +3 -0
  25. package/dist/dts/components/chat-interaction-wrapper/chat-interaction-wrapper.template.d.ts.map +1 -0
  26. package/dist/dts/components/chat-interaction-wrapper/index.d.ts +4 -0
  27. package/dist/dts/components/chat-interaction-wrapper/index.d.ts.map +1 -0
  28. package/dist/dts/components/chat-markdown/chat-markdown.d.ts +6 -0
  29. package/dist/dts/components/chat-markdown/chat-markdown.d.ts.map +1 -0
  30. package/dist/dts/components/chat-markdown/index.d.ts +2 -0
  31. package/dist/dts/components/chat-markdown/index.d.ts.map +1 -0
  32. package/dist/dts/components/halo-overlay.d.ts +25 -0
  33. package/dist/dts/components/halo-overlay.d.ts.map +1 -0
  34. package/dist/dts/config/config.d.ts +51 -0
  35. package/dist/dts/config/config.d.ts.map +1 -0
  36. package/dist/dts/config/configure.d.ts +1 -0
  37. package/dist/dts/config/configure.d.ts.map +1 -0
  38. package/dist/dts/config/index.d.ts +2 -0
  39. package/dist/dts/config/index.d.ts.map +1 -0
  40. package/dist/dts/index.d.ts +10 -0
  41. package/dist/dts/index.d.ts.map +1 -0
  42. package/dist/dts/main/index.d.ts +5 -0
  43. package/dist/dts/main/index.d.ts.map +1 -0
  44. package/dist/dts/main/main.d.ts +103 -0
  45. package/dist/dts/main/main.d.ts.map +1 -0
  46. package/dist/dts/main/main.styles.d.ts +2 -0
  47. package/dist/dts/main/main.styles.d.ts.map +1 -0
  48. package/dist/dts/main/main.template.d.ts +4 -0
  49. package/dist/dts/main/main.template.d.ts.map +1 -0
  50. package/dist/dts/main/main.types.d.ts +54 -0
  51. package/dist/dts/main/main.types.d.ts.map +1 -0
  52. package/dist/dts/styles/index.d.ts +2 -0
  53. package/dist/dts/styles/index.d.ts.map +1 -0
  54. package/dist/dts/styles/styles.d.ts +5 -0
  55. package/dist/dts/styles/styles.d.ts.map +1 -0
  56. package/dist/dts/tags/index.d.ts +1 -0
  57. package/dist/dts/tags/index.d.ts.map +1 -0
  58. package/dist/dts/types/ai-chat-widget.d.ts +12 -0
  59. package/dist/dts/types/ai-chat-widget.d.ts.map +1 -0
  60. package/dist/dts/utils/index.d.ts +2 -0
  61. package/dist/dts/utils/index.d.ts.map +1 -0
  62. package/dist/dts/utils/logger.d.ts +2 -0
  63. package/dist/dts/utils/logger.d.ts.map +1 -0
  64. package/dist/esm/channel/ai-activity-channel.js +2 -0
  65. package/dist/esm/components/activity-halo/activity-halo.js +119 -0
  66. package/dist/esm/components/chat-bubble/chat-bubble.js +381 -0
  67. package/dist/esm/components/chat-bubble/chat-bubble.styles.js +193 -0
  68. package/dist/esm/components/chat-bubble/chat-bubble.template.js +50 -0
  69. package/dist/esm/components/chat-bubble/index.js +1 -0
  70. package/dist/esm/components/chat-driver/chat-driver.js +209 -0
  71. package/dist/esm/components/chat-driver/index.js +1 -0
  72. package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.js +90 -0
  73. package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.js +6 -0
  74. package/dist/esm/components/chat-interaction-wrapper/chat-interaction-wrapper.template.js +4 -0
  75. package/dist/esm/components/chat-interaction-wrapper/index.js +3 -0
  76. package/dist/esm/components/chat-markdown/chat-markdown.js +95 -0
  77. package/dist/esm/components/chat-markdown/index.js +1 -0
  78. package/dist/esm/components/halo-overlay.js +118 -0
  79. package/dist/esm/config/config.js +16 -0
  80. package/dist/esm/config/configure.js +0 -0
  81. package/dist/esm/config/index.js +1 -0
  82. package/dist/esm/index.js +8 -0
  83. package/dist/esm/main/index.js +4 -0
  84. package/dist/esm/main/main.js +491 -0
  85. package/dist/esm/main/main.styles.js +356 -0
  86. package/dist/esm/main/main.template.js +272 -0
  87. package/dist/esm/main/main.types.js +22 -0
  88. package/dist/esm/styles/index.js +1 -0
  89. package/dist/esm/styles/styles.js +237 -0
  90. package/dist/esm/tags/index.js +0 -0
  91. package/dist/esm/types/ai-chat-widget.js +1 -0
  92. package/dist/esm/utils/index.js +1 -0
  93. package/dist/esm/utils/logger.js +2 -0
  94. package/dist/tsconfig.tsbuildinfo +1 -0
  95. package/dist/tsdoc-metadata.json +11 -0
  96. package/docs/.gitattributes +2 -0
  97. package/docs/api/ai-assistant.ai_activity_channel_name.md +11 -0
  98. package/docs/api/ai-assistant.aiactivityevents.md +24 -0
  99. package/docs/api/ai-assistant.aiactivityhalo.channelname.md +16 -0
  100. package/docs/api/ai-assistant.aiactivityhalo.connectedcallback.md +18 -0
  101. package/docs/api/ai-assistant.aiactivityhalo.disconnectedcallback.md +18 -0
  102. package/docs/api/ai-assistant.aiactivityhalo.haloactive.md +14 -0
  103. package/docs/api/ai-assistant.aiactivityhalo.md +176 -0
  104. package/docs/api/ai-assistant.aiactivityhalo.minshowtime.md +16 -0
  105. package/docs/api/ai-assistant.aiactivityhalo.tools.md +16 -0
  106. package/docs/api/ai-assistant.aiassistantanimation.md +18 -0
  107. package/docs/api/ai-assistant.aiassistantanimationdef.label.md +16 -0
  108. package/docs/api/ai-assistant.aiassistantanimationdef.md +80 -0
  109. package/docs/api/ai-assistant.aiassistantanimationdef.tooltip.md +16 -0
  110. package/docs/api/ai-assistant.aiassistantconfig.chatconfig.md +16 -0
  111. package/docs/api/ai-assistant.aiassistantconfig.debugstatefactory.md +16 -0
  112. package/docs/api/ai-assistant.aiassistantconfig.headertitle.md +16 -0
  113. package/docs/api/ai-assistant.aiassistantconfig.md +157 -0
  114. package/docs/api/ai-assistant.aiassistantconfig.systemprompt.md +16 -0
  115. package/docs/api/ai-assistant.aiassistantconfig.tooldefinitions.md +16 -0
  116. package/docs/api/ai-assistant.aiassistantconfig.toolhandlers.md +16 -0
  117. package/docs/api/ai-assistant.aiassistantserializedstate.enabledanimations.md +14 -0
  118. package/docs/api/ai-assistant.aiassistantserializedstate.md +118 -0
  119. package/docs/api/ai-assistant.aiassistantserializedstate.messages.md +14 -0
  120. package/docs/api/ai-assistant.aiassistantserializedstate.showthinkingsteps.md +14 -0
  121. package/docs/api/ai-assistant.aiassistantserializedstate.showtoolcalls.md +14 -0
  122. package/docs/api/ai-assistant.aiassistantstate.md +16 -0
  123. package/docs/api/ai-assistant.aichatbubble.bubbleleft.md +11 -0
  124. package/docs/api/ai-assistant.aichatbubble.bubbletop.md +11 -0
  125. package/docs/api/ai-assistant.aichatbubble.channelname.md +11 -0
  126. package/docs/api/ai-assistant.aichatbubble.connectedcallback.md +15 -0
  127. package/docs/api/ai-assistant.aichatbubble.designsystemprefix.md +11 -0
  128. package/docs/api/ai-assistant.aichatbubble.dialogcontent.md +11 -0
  129. package/docs/api/ai-assistant.aichatbubble.dialogcontentchanged.md +64 -0
  130. package/docs/api/ai-assistant.aichatbubble.dialogheight.md +11 -0
  131. package/docs/api/ai-assistant.aichatbubble.dialogleft.md +11 -0
  132. package/docs/api/ai-assistant.aichatbubble.dialogopen.md +11 -0
  133. package/docs/api/ai-assistant.aichatbubble.dialogopenchanged.md +64 -0
  134. package/docs/api/ai-assistant.aichatbubble.dialogtop.md +11 -0
  135. package/docs/api/ai-assistant.aichatbubble.dialogwidth.md +11 -0
  136. package/docs/api/ai-assistant.aichatbubble.disconnectedcallback.md +15 -0
  137. package/docs/api/ai-assistant.aichatbubble.hovered.md +11 -0
  138. package/docs/api/ai-assistant.aichatbubble.imagesrc.md +11 -0
  139. package/docs/api/ai-assistant.aichatbubble.md +396 -0
  140. package/docs/api/ai-assistant.aichatbubble.onbubblemousedown.md +50 -0
  141. package/docs/api/ai-assistant.aichatbubble.onclosedialog.md +15 -0
  142. package/docs/api/ai-assistant.aichatbubble.ondialogheadermousedown.md +53 -0
  143. package/docs/api/ai-assistant.aichatbubble.onpopout.md +15 -0
  144. package/docs/api/ai-assistant.aichatbubble.title.md +11 -0
  145. package/docs/api/ai-assistant.aichatbubble.tooltipstyle.md +11 -0
  146. package/docs/api/ai-assistant.aichatwidget.data.md +14 -0
  147. package/docs/api/ai-assistant.aichatwidget.md +80 -0
  148. package/docs/api/ai-assistant.aichatwidget.resolved.md +16 -0
  149. package/docs/api/ai-assistant.animation_defs.md +25 -0
  150. package/docs/api/ai-assistant.chatdriver._constructor_.md +99 -0
  151. package/docs/api/ai-assistant.chatdriver.gethistory.md +18 -0
  152. package/docs/api/ai-assistant.chatdriver.isbusy.md +18 -0
  153. package/docs/api/ai-assistant.chatdriver.loadhistory.md +55 -0
  154. package/docs/api/ai-assistant.chatdriver.md +158 -0
  155. package/docs/api/ai-assistant.chatdriver.requestinteraction.md +73 -0
  156. package/docs/api/ai-assistant.chatdriver.resolveinteraction.md +69 -0
  157. package/docs/api/ai-assistant.chatdriver.sendmessage.md +69 -0
  158. package/docs/api/ai-assistant.chathistoryupdatedevent.md +16 -0
  159. package/docs/api/ai-assistant.defaultaiassistantconfig.md +16 -0
  160. package/docs/api/ai-assistant.foundationaiassistant.aiprovider.md +14 -0
  161. package/docs/api/ai-assistant.foundationaiassistant.applystate.md +55 -0
  162. package/docs/api/ai-assistant.foundationaiassistant.attachmenterrors.md +14 -0
  163. package/docs/api/ai-assistant.foundationaiassistant.attachments.md +14 -0
  164. package/docs/api/ai-assistant.foundationaiassistant.channelname.md +14 -0
  165. package/docs/api/ai-assistant.foundationaiassistant.chatconfig.md +14 -0
  166. package/docs/api/ai-assistant.foundationaiassistant.connectedcallback.md +18 -0
  167. package/docs/api/ai-assistant.foundationaiassistant.debugstatefactory.md +14 -0
  168. package/docs/api/ai-assistant.foundationaiassistant.designsystemprefix.md +14 -0
  169. package/docs/api/ai-assistant.foundationaiassistant.disconnectedcallback.md +18 -0
  170. package/docs/api/ai-assistant.foundationaiassistant.downloadhistory.md +18 -0
  171. package/docs/api/ai-assistant.foundationaiassistant.enabledanimations.md +16 -0
  172. package/docs/api/ai-assistant.foundationaiassistant.handlefileselect.md +53 -0
  173. package/docs/api/ai-assistant.foundationaiassistant.handleinteractioncompleted.md +53 -0
  174. package/docs/api/ai-assistant.foundationaiassistant.handlepopout.md +20 -0
  175. package/docs/api/ai-assistant.foundationaiassistant.handlesendclick.md +18 -0
  176. package/docs/api/ai-assistant.foundationaiassistant.hasactivependinginteraction.md +16 -0
  177. package/docs/api/ai-assistant.foundationaiassistant.headertitle.md +14 -0
  178. package/docs/api/ai-assistant.foundationaiassistant.imagesrc.md +14 -0
  179. package/docs/api/ai-assistant.foundationaiassistant.inputvalue.md +14 -0
  180. package/docs/api/ai-assistant.foundationaiassistant.md +826 -0
  181. package/docs/api/ai-assistant.foundationaiassistant.messages.md +14 -0
  182. package/docs/api/ai-assistant.foundationaiassistant.messageschanged.md +18 -0
  183. package/docs/api/ai-assistant.foundationaiassistant.onchatheadermousedown.md +53 -0
  184. package/docs/api/ai-assistant.foundationaiassistant.placeholder.md +14 -0
  185. package/docs/api/ai-assistant.foundationaiassistant.popoutmode.md +16 -0
  186. package/docs/api/ai-assistant.foundationaiassistant.removeattachment.md +53 -0
  187. package/docs/api/ai-assistant.foundationaiassistant.removeattachmenterror.md +53 -0
  188. package/docs/api/ai-assistant.foundationaiassistant.setenabledanimations.md +53 -0
  189. package/docs/api/ai-assistant.foundationaiassistant.settingsopen.md +16 -0
  190. package/docs/api/ai-assistant.foundationaiassistant.showhalo.md +16 -0
  191. package/docs/api/ai-assistant.foundationaiassistant.showhalochanged.md +18 -0
  192. package/docs/api/ai-assistant.foundationaiassistant.showloadingindicator.md +16 -0
  193. package/docs/api/ai-assistant.foundationaiassistant.showloadingindicatorchanged.md +18 -0
  194. package/docs/api/ai-assistant.foundationaiassistant.showthinkingsteps.md +16 -0
  195. package/docs/api/ai-assistant.foundationaiassistant.showtoolcalls.md +16 -0
  196. package/docs/api/ai-assistant.foundationaiassistant.state.md +14 -0
  197. package/docs/api/ai-assistant.foundationaiassistant.statechanged.md +18 -0
  198. package/docs/api/ai-assistant.foundationaiassistant.systemprompt.md +14 -0
  199. package/docs/api/ai-assistant.foundationaiassistant.togglesettings.md +18 -0
  200. package/docs/api/ai-assistant.foundationaiassistant.toggleshowthinkingsteps.md +18 -0
  201. package/docs/api/ai-assistant.foundationaiassistant.toggleshowtoolcalls.md +18 -0
  202. package/docs/api/ai-assistant.foundationaiassistant.tooldefinitions.md +14 -0
  203. package/docs/api/ai-assistant.foundationaiassistant.toolhandlers.md +14 -0
  204. package/docs/api/ai-assistant.foundationaiassistant.triggerfileinput.md +18 -0
  205. package/docs/api/ai-assistant.foundationaiassistant.visiblemessages.md +16 -0
  206. package/docs/api/ai-assistant.foundationaiassistanttemplate.md +50 -0
  207. package/docs/api/ai-assistant.md +262 -0
  208. package/docs/api/ai-assistant.popoutmode.md +16 -0
  209. package/docs/api/index.md +30 -0
  210. package/docs/api-report.md.api.md +280 -0
  211. package/license.txt +46 -0
  212. package/package.json +92 -0
  213. package/src/channel/ai-activity-channel.ts +30 -0
  214. package/src/components/activity-halo/activity-halo.ts +113 -0
  215. package/src/components/chat-bubble/chat-bubble.styles.ts +194 -0
  216. package/src/components/chat-bubble/chat-bubble.template.ts +63 -0
  217. package/src/components/chat-bubble/chat-bubble.ts +389 -0
  218. package/src/components/chat-bubble/index.ts +1 -0
  219. package/src/components/chat-driver/chat-driver.ts +254 -0
  220. package/src/components/chat-driver/index.ts +1 -0
  221. package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts +7 -0
  222. package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts +6 -0
  223. package/src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts +89 -0
  224. package/src/components/chat-interaction-wrapper/index.ts +3 -0
  225. package/src/components/chat-markdown/chat-markdown.ts +87 -0
  226. package/src/components/chat-markdown/index.ts +1 -0
  227. package/src/components/halo-overlay.ts +115 -0
  228. package/src/config/config.ts +59 -0
  229. package/src/config/configure.ts +0 -0
  230. package/src/config/index.ts +1 -0
  231. package/src/index.ts +9 -0
  232. package/src/main/index.ts +4 -0
  233. package/src/main/main.styles.ts +357 -0
  234. package/src/main/main.template.ts +364 -0
  235. package/src/main/main.ts +474 -0
  236. package/src/main/main.types.ts +58 -0
  237. package/src/styles/index.ts +1 -0
  238. package/src/styles/styles.ts +238 -0
  239. package/src/tags/index.ts +0 -0
  240. package/src/types/ai-chat-widget.ts +11 -0
  241. package/src/utils/index.ts +1 -0
  242. package/src/utils/logger.ts +3 -0
  243. package/temp/api-report.md.api.md +280 -0
  244. package/tsconfig.json +11 -0
@@ -0,0 +1,209 @@
1
+ import { __awaiter } from "tslib";
2
+ import { MalformedFunctionCallError } from '@genesislcap/foundation-ai';
3
+ import { logger } from '../../utils/logger';
4
+ const MAX_TOOL_ITERATIONS = 10;
5
+ const MAX_MALFORMED_RETRIES = 2;
6
+ /**
7
+ * Plain TS class that drives a multi-turn chat conversation, including the tool-call loop.
8
+ * Owned by `FoundationAiAssistant` — created in `connectedCallback`, torn down in `disconnectedCallback`.
9
+ *
10
+ * Dispatches `'history-updated'` events on itself so the owning element can observe changes.
11
+ *
12
+ * @beta
13
+ */
14
+ export class ChatDriver extends EventTarget {
15
+ constructor(aiProvider, toolHandlers = {}, toolDefinitions = [], systemPrompt) {
16
+ super();
17
+ this.aiProvider = aiProvider;
18
+ this.toolHandlers = toolHandlers;
19
+ this.toolDefinitions = toolDefinitions;
20
+ this.systemPrompt = systemPrompt;
21
+ this.history = [];
22
+ this.busy = false;
23
+ this.pendingInteractions = new Map();
24
+ }
25
+ getHistory() {
26
+ return this.history;
27
+ }
28
+ isBusy() {
29
+ return this.busy;
30
+ }
31
+ /**
32
+ * Request a custom UI interaction. Emits a new message with the interaction.
33
+ * Tool handlers can call this to pause execution until the user completes the UI interaction.
34
+ *
35
+ * @param componentName - The custom element name to render.
36
+ * @param data - Data to pass to the component.
37
+ */
38
+ requestInteraction(componentName, data) {
39
+ return __awaiter(this, void 0, void 0, function* () {
40
+ const interactionId = crypto.randomUUID();
41
+ return new Promise((resolve, reject) => {
42
+ this.pendingInteractions.set(interactionId, { resolve, reject });
43
+ this.appendToHistory({
44
+ role: 'assistant',
45
+ content: '',
46
+ interaction: { interactionId, componentName, data },
47
+ });
48
+ });
49
+ });
50
+ }
51
+ /**
52
+ * Resolve a pending interaction. The wrapper component calls this on completion.
53
+ * Marks the interaction message as resolved so it renders read-only on re-render.
54
+ */
55
+ resolveInteraction(interactionId, result) {
56
+ const interaction = this.pendingInteractions.get(interactionId);
57
+ if (interaction) {
58
+ // Mark the message as resolved before resolving the promise so the next
59
+ // history-updated event carries the updated flag.
60
+ const msg = this.history.find((m) => { var _a; return ((_a = m.interaction) === null || _a === void 0 ? void 0 : _a.interactionId) === interactionId; });
61
+ if (msg === null || msg === void 0 ? void 0 : msg.interaction) {
62
+ msg.interaction.resolved = true;
63
+ this.dispatchEvent(new CustomEvent('history-updated', {
64
+ detail: this.history,
65
+ }));
66
+ }
67
+ interaction.resolve(result);
68
+ this.pendingInteractions.delete(interactionId);
69
+ }
70
+ else {
71
+ logger.warn(`Interaction with ID ${interactionId} not found.`);
72
+ }
73
+ }
74
+ /**
75
+ * Seeds the driver with a prior conversation history so a new component instance
76
+ * can continue an existing conversation. Call this before the first user message.
77
+ */
78
+ loadHistory(messages) {
79
+ this.history = [...messages];
80
+ }
81
+ sendMessage(userInput, attachments) {
82
+ return __awaiter(this, void 0, void 0, function* () {
83
+ if (this.busy || (!userInput.trim() && !(attachments === null || attachments === void 0 ? void 0 : attachments.length)))
84
+ return;
85
+ if (!this.aiProvider.chat) {
86
+ logger.warn('ChatDriver: AIProvider does not implement chat()');
87
+ return;
88
+ }
89
+ this.busy = true;
90
+ this.appendToHistory({ role: 'user', content: userInput, attachments });
91
+ try {
92
+ yield this.runToolLoop(userInput, attachments);
93
+ }
94
+ catch (e) {
95
+ logger.error('ChatDriver error:', e);
96
+ this.appendToHistory({ role: 'assistant', content: 'Sorry, something went wrong.' });
97
+ }
98
+ finally {
99
+ this.busy = false;
100
+ }
101
+ });
102
+ }
103
+ runToolLoop(userInput, attachments) {
104
+ return __awaiter(this, void 0, void 0, function* () {
105
+ var _a, _b, _c, _d, _e;
106
+ const baseOptions = {
107
+ systemPrompt: this.systemPrompt,
108
+ tools: this.toolDefinitions.length ? this.toolDefinitions : undefined,
109
+ };
110
+ // History has the user message at the end — pass everything before it as history,
111
+ // and the user input as the userMessage argument.
112
+ let currentInput = userInput;
113
+ let currentAttachments = attachments;
114
+ let iterations = 0;
115
+ let malformedAttempts = 0;
116
+ while (iterations < MAX_TOOL_ITERATIONS) {
117
+ iterations += 1;
118
+ // On the first iteration, the last item in history is the user message which is
119
+ // passed separately as currentInput — exclude it. On subsequent iterations, the
120
+ // full history (including tool results) should be sent and currentInput is empty.
121
+ const historyForCall = iterations === 1 ? this.history.slice(0, -1) : [...this.history];
122
+ // On malformed-call retries, augment the system prompt to steer the model
123
+ // away from generating Python-style batched function call syntax.
124
+ const systemPrompt = malformedAttempts > 0
125
+ ? `${(_a = baseOptions.systemPrompt) !== null && _a !== void 0 ? _a : ''}\n\nIMPORTANT: Use only the structured function-call API to invoke tools. Do not write Python code or use Python-style syntax to call tools.`
126
+ : baseOptions.systemPrompt;
127
+ const options = Object.assign(Object.assign({}, baseOptions), { systemPrompt, attachments: currentAttachments });
128
+ let response;
129
+ try {
130
+ // eslint-disable-next-line no-await-in-loop
131
+ response = yield this.aiProvider.chat(historyForCall, currentInput, options);
132
+ }
133
+ catch (e) {
134
+ if (e instanceof MalformedFunctionCallError) {
135
+ malformedAttempts += 1;
136
+ if (malformedAttempts < MAX_MALFORMED_RETRIES) {
137
+ logger.warn(`ChatDriver: MALFORMED_FUNCTION_CALL, retrying (${malformedAttempts}/${MAX_MALFORMED_RETRIES})`);
138
+ iterations -= 1; // don't consume an iteration budget slot for a failed attempt
139
+ continue;
140
+ }
141
+ logger.error('ChatDriver: MALFORMED_FUNCTION_CALL, max retries reached');
142
+ this.appendToHistory({
143
+ role: 'assistant',
144
+ content: "I'm sorry, I wasn't able to complete that request. Please try rephrasing or breaking it into smaller steps.",
145
+ });
146
+ return;
147
+ }
148
+ throw e;
149
+ }
150
+ currentAttachments = undefined; // attachments only sent on first call
151
+ const isThinkingStep = response.content && ((_b = response.toolCalls) === null || _b === void 0 ? void 0 : _b.length);
152
+ const isEmptyResponse = !((_c = response.content) === null || _c === void 0 ? void 0 : _c.trim()) && !((_d = response.toolCalls) === null || _d === void 0 ? void 0 : _d.length);
153
+ if (isEmptyResponse) {
154
+ // Do nothing, discard empty/whitespace-only responses
155
+ }
156
+ else if (isThinkingStep) {
157
+ // Separate thinking message and tool call message
158
+ this.appendToHistory(Object.assign(Object.assign({}, response), { toolCalls: undefined, thinking: true }));
159
+ this.appendToHistory(Object.assign(Object.assign({}, response), { content: '' }));
160
+ }
161
+ else {
162
+ this.appendToHistory(response);
163
+ }
164
+ if (!((_e = response.toolCalls) === null || _e === void 0 ? void 0 : _e.length)) {
165
+ // Terminal text response — done
166
+ break;
167
+ }
168
+ // Execute all tool calls for this iteration concurrently, then append results in order
169
+ // eslint-disable-next-line no-await-in-loop
170
+ const toolResults = yield Promise.all(response.toolCalls.map((tc) => __awaiter(this, void 0, void 0, function* () {
171
+ const handler = this.toolHandlers[tc.name];
172
+ if (!handler) {
173
+ logger.warn(`ChatDriver: no handler registered for tool "${tc.name}"`);
174
+ return { toolCallId: tc.id, content: `Unknown tool: ${tc.name}` };
175
+ }
176
+ try {
177
+ const result = yield handler(tc.args, {
178
+ requestInteraction: (componentName, data) => this.requestInteraction(componentName, data),
179
+ });
180
+ const content = typeof result === 'string' ? result : JSON.stringify(result);
181
+ return { toolCallId: tc.id, content };
182
+ }
183
+ catch (e) {
184
+ logger.error(`ChatDriver tool "${tc.name}" failed:`, e);
185
+ return { toolCallId: tc.id, content: `Tool error: ${e.message}` };
186
+ }
187
+ })));
188
+ for (const result of toolResults) {
189
+ this.appendToHistory({
190
+ role: 'tool',
191
+ content: '',
192
+ toolResult: result,
193
+ });
194
+ }
195
+ // Next iteration sends an empty string — the tool results are in history
196
+ currentInput = '';
197
+ }
198
+ if (iterations >= MAX_TOOL_ITERATIONS) {
199
+ logger.warn('ChatDriver: reached max tool iterations, stopping');
200
+ }
201
+ });
202
+ }
203
+ appendToHistory(message) {
204
+ this.history = [...this.history, message];
205
+ this.dispatchEvent(new CustomEvent('history-updated', {
206
+ detail: this.history,
207
+ }));
208
+ }
209
+ }
@@ -0,0 +1 @@
1
+ export * from './chat-driver';
@@ -0,0 +1,90 @@
1
+ import { __decorate } from "tslib";
2
+ import { customElement, GenesisElement, observable } from '@genesislcap/web-core';
3
+ import { logger } from '../../utils/logger';
4
+ import { AiChatInteractionWrapperStyles } from './chat-interaction-wrapper.styles';
5
+ import { AiChatInteractionWrapperTemplate } from './chat-interaction-wrapper.template';
6
+ let AiChatInteractionWrapper = class AiChatInteractionWrapper extends GenesisElement {
7
+ constructor() {
8
+ super(...arguments);
9
+ this.componentName = '';
10
+ this.interactionId = '';
11
+ /** When true, the interaction has already been resolved. Forwarded to the rendered component. */
12
+ this.resolved = false;
13
+ }
14
+ connectedCallback() {
15
+ super.connectedCallback();
16
+ this.renderComponent();
17
+ }
18
+ componentNameChanged() {
19
+ this.renderComponent();
20
+ }
21
+ resolvedChanged() {
22
+ var _a;
23
+ // TODO: switch to FAST ref() or slotted children directives instead of querying the container
24
+ // imperatively — this would allow property bindings to flow naturally through the template.
25
+ const container = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.container');
26
+ const element = container === null || container === void 0 ? void 0 : container.firstElementChild;
27
+ if (element) {
28
+ element.resolved = this.resolved;
29
+ }
30
+ }
31
+ renderComponent() {
32
+ var _a;
33
+ const container = (_a = this.shadowRoot) === null || _a === void 0 ? void 0 : _a.querySelector('.container');
34
+ if (!container || !this.componentName)
35
+ return;
36
+ // Clear children without using innerHTML
37
+ container.replaceChildren();
38
+ if (!customElements.get(this.componentName)) {
39
+ logger.warn(`Interactive component "\${this.componentName}" is not registered in the customElements registry.`);
40
+ const errorDiv = document.createElement('div');
41
+ errorDiv.textContent = `Error: Component "\${this.componentName}" is not available in this application.`;
42
+ container.appendChild(errorDiv);
43
+ return;
44
+ }
45
+ try {
46
+ const element = document.createElement(this.componentName);
47
+ // Pass data and resolved state to the component
48
+ if (this.data) {
49
+ element.data = this.data;
50
+ }
51
+ element.resolved = this.resolved;
52
+ // Handle completion from the inner component.
53
+ // Guard against re-emission if the interaction was already resolved
54
+ // (e.g. auto-resolve components fire on connectedCallback when rendering history).
55
+ element.addEventListener('interaction-completed', (e) => {
56
+ e.stopPropagation();
57
+ if (this.resolved)
58
+ return;
59
+ this.$emit('interaction-completed', Object.assign({ interactionId: this.interactionId }, e.detail));
60
+ });
61
+ container.appendChild(element);
62
+ }
63
+ catch (e) {
64
+ logger.error(`Failed to create interactive component: \${this.componentName}`, e);
65
+ const errorDiv = document.createElement('div');
66
+ errorDiv.textContent = `Error: Could not load component \${this.componentName}`;
67
+ container.appendChild(errorDiv);
68
+ }
69
+ }
70
+ };
71
+ __decorate([
72
+ observable
73
+ ], AiChatInteractionWrapper.prototype, "componentName", void 0);
74
+ __decorate([
75
+ observable
76
+ ], AiChatInteractionWrapper.prototype, "data", void 0);
77
+ __decorate([
78
+ observable
79
+ ], AiChatInteractionWrapper.prototype, "interactionId", void 0);
80
+ __decorate([
81
+ observable
82
+ ], AiChatInteractionWrapper.prototype, "resolved", void 0);
83
+ AiChatInteractionWrapper = __decorate([
84
+ customElement({
85
+ name: 'ai-chat-interaction-wrapper',
86
+ template: AiChatInteractionWrapperTemplate,
87
+ styles: AiChatInteractionWrapperStyles,
88
+ })
89
+ ], AiChatInteractionWrapper);
90
+ export { AiChatInteractionWrapper };
@@ -0,0 +1,6 @@
1
+ import { css } from '@genesislcap/web-core';
2
+ export const AiChatInteractionWrapperStyles = css `
3
+ :host {
4
+ display: block;
5
+ }
6
+ `;
@@ -0,0 +1,4 @@
1
+ import { html } from '@genesislcap/web-core';
2
+ export const AiChatInteractionWrapperTemplate = html `
3
+ <div class="container" part="container"></div>
4
+ `;
@@ -0,0 +1,3 @@
1
+ export * from './chat-interaction-wrapper';
2
+ export * from './chat-interaction-wrapper.styles';
3
+ export * from './chat-interaction-wrapper.template';
@@ -0,0 +1,95 @@
1
+ import { __decorate } from "tslib";
2
+ import { css, customElement, GenesisElement, html, observable } from '@genesislcap/web-core';
3
+ import DOMPurify from 'dompurify';
4
+ import { marked } from 'marked';
5
+ const styles = css `
6
+ :host {
7
+ display: block;
8
+ font-size: var(--type-ramp-base-font-size);
9
+ line-height: var(--type-ramp-base-line-height);
10
+ }
11
+
12
+ p {
13
+ margin: 0 0 calc(var(--design-unit, 4) * 2px);
14
+ }
15
+
16
+ p:last-child {
17
+ margin-bottom: 0;
18
+ }
19
+
20
+ ul,
21
+ ol {
22
+ margin: 0 0 calc(var(--design-unit, 4) * 2px);
23
+ padding-left: calc(var(--design-unit, 4) * 5px);
24
+ }
25
+
26
+ code {
27
+ background-color: var(--neutral-fill-rest);
28
+ padding: 2px 4px;
29
+ border-radius: calc(var(--design-unit, 4) * 0.5px);
30
+ font-family: monospace;
31
+ }
32
+
33
+ pre {
34
+ background-color: var(--neutral-fill-rest);
35
+ padding: calc(var(--design-unit, 4) * 2px);
36
+ border-radius: calc(var(--design-unit, 4) * 1px);
37
+ overflow-x: auto;
38
+ border: 1px solid var(--neutral-stroke-rest);
39
+ margin: calc(var(--design-unit, 4) * 2px) 0;
40
+ }
41
+
42
+ pre code {
43
+ background-color: transparent;
44
+ padding: 0;
45
+ border-radius: 0;
46
+ border: none;
47
+ font-family: inherit;
48
+ color: inherit;
49
+ }
50
+
51
+ table {
52
+ display: block;
53
+ overflow-x: auto;
54
+ border-collapse: collapse;
55
+ max-width: 100%;
56
+ margin: calc(var(--design-unit, 4) * 2px) 0;
57
+ }
58
+
59
+ th,
60
+ td {
61
+ border: 1px solid var(--neutral-stroke-rest);
62
+ padding: calc(var(--design-unit, 4) * 1px) calc(var(--design-unit, 4) * 2.5px);
63
+ white-space: nowrap;
64
+ }
65
+
66
+ th {
67
+ background-color: var(--neutral-fill-stealth-rest);
68
+ font-weight: 600;
69
+ }
70
+ `;
71
+ let AiChatMarkdown = class AiChatMarkdown extends GenesisElement {
72
+ constructor() {
73
+ super(...arguments);
74
+ this.content = '';
75
+ }
76
+ renderMarkdown() {
77
+ if (!this.content)
78
+ return '';
79
+ const rawHtml = marked.parse(this.content);
80
+ return DOMPurify.sanitize(rawHtml);
81
+ }
82
+ };
83
+ __decorate([
84
+ observable
85
+ ], AiChatMarkdown.prototype, "content", void 0);
86
+ AiChatMarkdown = __decorate([
87
+ customElement({
88
+ name: 'ai-chat-markdown',
89
+ template: html `
90
+ <div :innerHTML="${(x) => x.renderMarkdown()}"></div>
91
+ `,
92
+ styles,
93
+ })
94
+ ], AiChatMarkdown);
95
+ export { AiChatMarkdown };
@@ -0,0 +1 @@
1
+ export * from './chat-markdown';
@@ -0,0 +1,118 @@
1
+ var AiHaloOverlay_1;
2
+ import { __decorate } from "tslib";
3
+ import { attr, css, customElement, GenesisElement, html } from '@genesislcap/web-core';
4
+ /**
5
+ * Animated halo overlay — rotating conic-gradient border with an inward glow.
6
+ *
7
+ * Drop inside any `position: relative; overflow: hidden` container and toggle
8
+ * the `active` attribute to show/hide the effect.
9
+ *
10
+ * @example
11
+ * ```html
12
+ * <ai-halo-overlay ?active="${(x) => x.isLoading}"></ai-halo-overlay>
13
+ * ```
14
+ *
15
+ * @beta
16
+ */
17
+ let AiHaloOverlay = AiHaloOverlay_1 = class AiHaloOverlay extends GenesisElement {
18
+ constructor() {
19
+ super(...arguments);
20
+ this.active = false;
21
+ this.angle = 0;
22
+ }
23
+ connectedCallback() {
24
+ super.connectedCallback();
25
+ this.tick();
26
+ }
27
+ disconnectedCallback() {
28
+ super.disconnectedCallback();
29
+ if (this.animFrame !== undefined) {
30
+ cancelAnimationFrame(this.animFrame);
31
+ }
32
+ }
33
+ tick() {
34
+ this.angle = (this.angle + AiHaloOverlay_1.DEG_PER_FRAME) % AiHaloOverlay_1.FULL_ROTATION_DEG;
35
+ this.style.setProperty('--halo-angle', `${this.angle}deg`);
36
+ this.animFrame = requestAnimationFrame(() => this.tick());
37
+ }
38
+ };
39
+ // TODO: The rAF loop is fine for demos but has two drawbacks vs a pure CSS @property animation:
40
+ // 1. It runs on the main thread, so heavy JS work can cause the animation to stutter.
41
+ // 2. The loop ticks even when `active` is false (idle cost is negligible but non-zero).
42
+ // Once @property inside Shadow DOM has solid cross-browser support, consider switching back
43
+ // to a CSS @keyframes approach and removing connectedCallback/disconnectedCallback/tick().
44
+ // 1.5° per frame @ 60 fps ≈ 4 s per full revolution
45
+ AiHaloOverlay.DEG_PER_FRAME = 1.5;
46
+ AiHaloOverlay.FULL_ROTATION_DEG = 360;
47
+ __decorate([
48
+ attr({ mode: 'boolean' })
49
+ ], AiHaloOverlay.prototype, "active", void 0);
50
+ AiHaloOverlay = AiHaloOverlay_1 = __decorate([
51
+ customElement({
52
+ name: 'ai-halo-overlay',
53
+ template: html `
54
+ <slot></slot>
55
+ `,
56
+ styles: css `
57
+ :host {
58
+ display: block;
59
+ position: absolute;
60
+ inset: 0;
61
+ border-radius: inherit;
62
+ pointer-events: none;
63
+ z-index: 1000;
64
+ opacity: 0;
65
+ transition: opacity 0.4s ease;
66
+ }
67
+
68
+ :host([active]) {
69
+ opacity: 1;
70
+ }
71
+
72
+ /* Rotating solid border */
73
+ :host::before {
74
+ content: '';
75
+ position: absolute;
76
+ inset: 0;
77
+ border-radius: inherit;
78
+ padding: 3px;
79
+ background: repeating-conic-gradient(
80
+ from var(--halo-angle, 0deg),
81
+ #feb60a,
82
+ #ff0062,
83
+ #00dbf9,
84
+ #da00f7,
85
+ #feb60a
86
+ );
87
+ -webkit-mask:
88
+ linear-gradient(#000 0 0) content-box,
89
+ linear-gradient(#000 0 0);
90
+ mask:
91
+ linear-gradient(#000 0 0) content-box,
92
+ linear-gradient(#000 0 0);
93
+ -webkit-mask-composite: destination-out;
94
+ mask-composite: exclude;
95
+ }
96
+
97
+ /* Inward glow — radial mask makes centre transparent, edges coloured */
98
+ :host::after {
99
+ content: '';
100
+ position: absolute;
101
+ inset: 0;
102
+ border-radius: inherit;
103
+ background: repeating-conic-gradient(
104
+ from var(--halo-angle, 0deg),
105
+ #feb60a,
106
+ #ff0062,
107
+ #00dbf9,
108
+ #da00f7,
109
+ #feb60a
110
+ );
111
+ opacity: 0.35;
112
+ -webkit-mask-image: radial-gradient(ellipse at center, transparent 70%, black 100%);
113
+ mask-image: radial-gradient(ellipse at center, transparent 70%, black 100%);
114
+ }
115
+ `,
116
+ })
117
+ ], AiHaloOverlay);
118
+ export { AiHaloOverlay };
@@ -0,0 +1,16 @@
1
+ import { DI } from '@genesislcap/web-core';
2
+ /**
3
+ * Default AiAssistantConfig DI implementation.
4
+ *
5
+ * @beta
6
+ */
7
+ export const defaultAiAssistantConfig = {
8
+ name: 'foundation-ai-assistant',
9
+ chatConfig: {},
10
+ };
11
+ /**
12
+ * AiAssistantConfig DI key.
13
+ *
14
+ * @internal
15
+ */
16
+ export const AiAssistantConfig = DI.createInterface((x) => x.instance(defaultAiAssistantConfig));
File without changes
@@ -0,0 +1 @@
1
+ export * from './config';
@@ -0,0 +1,8 @@
1
+ export * from './main/main';
2
+ export * from './main/main.types';
3
+ export * from './main/main.template';
4
+ export * from './components/chat-bubble';
5
+ export * from './components/chat-driver';
6
+ export * from './components/activity-halo/activity-halo';
7
+ export * from './channel/ai-activity-channel';
8
+ export * from './config/config';
@@ -0,0 +1,4 @@
1
+ export * from './main.template';
2
+ export * from '../styles';
3
+ export * from './main';
4
+ export * from './main.types';