@genesislcap/ai-assistant 14.421.1 → 14.422.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 (37) hide show
  1. package/dist/ai-assistant.api.json +191 -1
  2. package/dist/ai-assistant.d.ts +60 -0
  3. package/dist/dts/components/chat-driver/chat-driver.d.ts +33 -0
  4. package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
  5. package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
  6. package/dist/dts/config/config.d.ts +20 -0
  7. package/dist/dts/config/config.d.ts.map +1 -1
  8. package/dist/dts/main/main.d.ts +6 -0
  9. package/dist/dts/main/main.d.ts.map +1 -1
  10. package/dist/dts/main/main.styles.d.ts.map +1 -1
  11. package/dist/dts/main/main.template.d.ts +16 -0
  12. package/dist/dts/main/main.template.d.ts.map +1 -1
  13. package/dist/dts/state/ai-assistant-slice.d.ts +6 -0
  14. package/dist/dts/state/ai-assistant-slice.d.ts.map +1 -1
  15. package/dist/dts/state/session-store.d.ts +2 -0
  16. package/dist/dts/state/session-store.d.ts.map +1 -1
  17. package/dist/dts/utils/history-transform.d.ts +13 -0
  18. package/dist/dts/utils/history-transform.d.ts.map +1 -0
  19. package/dist/esm/components/chat-driver/chat-driver.js +127 -16
  20. package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +8 -20
  21. package/dist/esm/config/config.js +18 -1
  22. package/dist/esm/main/main.js +43 -11
  23. package/dist/esm/main/main.styles.js +62 -0
  24. package/dist/esm/main/main.template.js +122 -71
  25. package/dist/esm/state/ai-assistant-slice.js +8 -0
  26. package/dist/esm/utils/history-transform.js +35 -0
  27. package/dist/tsconfig.tsbuildinfo +1 -1
  28. package/docs/sub_agent.md +149 -211
  29. package/package.json +16 -16
  30. package/src/components/chat-driver/chat-driver.ts +169 -15
  31. package/src/components/orchestrating-driver/orchestrating-driver.ts +10 -22
  32. package/src/config/config.ts +24 -0
  33. package/src/main/main.styles.ts +62 -0
  34. package/src/main/main.template.ts +189 -117
  35. package/src/main/main.ts +43 -9
  36. package/src/state/ai-assistant-slice.ts +12 -0
  37. package/src/utils/history-transform.ts +40 -0
@@ -1,3 +1,19 @@
1
+ /**
2
+ * Whitespace in FAST templates
3
+ * ────────────────────────────
4
+ * The formatter adds newlines/indentation to static template string parts,
5
+ * which FAST renders as real text nodes. With `white-space: pre-wrap` these
6
+ * are visible as blank lines. To avoid this:
7
+ *
8
+ * - Apply `white-space: pre-wrap` only on leaf elements whose *content* needs
9
+ * it, never on containers.
10
+ * - Inside pre-wrap elements keep content on the same line as the opening tag:
11
+ * GOOD `<div>${expr}</div>` / BAD `<div>\n ${expr}\n</div>`
12
+ * - Extract shared or deeply-nested templates as named module-level consts to
13
+ * keep indentation shallow.
14
+ * - Chain adjacent `when()` calls as `${when(a,tA)}${when(b,tB)}` — separate
15
+ * lines let the formatter inject whitespace between them.
16
+ */
1
17
  import { isChatToolCallUnknown } from '@genesislcap/foundation-ai';
2
18
  import { html, ref, repeat, when } from '@genesislcap/web-core';
3
19
  import { ANIMATION_DEFS } from './main.types';
@@ -63,6 +79,41 @@ const senderLabel = {
63
79
  interaction: 'Assistant',
64
80
  ai: 'Assistant',
65
81
  };
82
+ // ─── Sub-agent trace fragments ────────────────────────────────────────────────
83
+ const subAgentAssistantTemplate = html `
84
+ <div class="sub-agent-message sub-agent-assistant">${(m) => m.content}</div>
85
+ `;
86
+ const subAgentToolCallTemplate = html `
87
+ <div class="sub-agent-message sub-agent-tool-call">
88
+ ${repeat((m) => m.toolCalls, html `
89
+ <span class="sub-agent-tool-name">${(tc) => tc.name}</span>
90
+ `)}
91
+ </div>
92
+ `;
93
+ const subAgentToolResultTemplate = html `
94
+ <div class="sub-agent-message sub-agent-tool-result">${(m) => m.toolResult.content}</div>
95
+ `;
96
+ /** Renders one row of a sub-agent trace (assistant text, tool call, or tool result). */
97
+ const subAgentMessageRowTemplate = html `
98
+ ${when((m) => { var _a; return m.role === 'assistant' && !((_a = m.toolCalls) === null || _a === void 0 ? void 0 : _a.length) && !!m.content; }, subAgentAssistantTemplate)}${when((m) => { var _a; return !!((_a = m.toolCalls) === null || _a === void 0 ? void 0 : _a.length); }, subAgentToolCallTemplate)}${when((m) => { var _a; return m.role === 'tool' && !!((_a = m.toolResult) === null || _a === void 0 ? void 0 : _a.content); }, subAgentToolResultTemplate)}
99
+ `;
100
+ /** Collapsed <details> trace shown inside a tool-call card once the sub-agent finishes. */
101
+ const subAgentTraceTemplate = html `
102
+ <details class="sub-agent-trace">
103
+ <summary class="sub-agent-trace-summary">
104
+ ${(tc) => { var _a, _b; return (_b = (_a = tc.subAgentTrace[0]) === null || _a === void 0 ? void 0 : _a.agentName) !== null && _b !== void 0 ? _b : 'Sub-agent'; }} trace
105
+ </summary>
106
+ ${repeat((tc) => tc.subAgentTrace.filter((m) => m.role !== 'user'), subAgentMessageRowTemplate)}
107
+ </details>
108
+ `;
109
+ /** Live streaming trace panel shown while a sub-agent is actively running. */
110
+ const liveSubAgentTraceTemplate = html `
111
+ <div class="live-sub-agent-trace" part="live-sub-agent-trace">
112
+ <span class="live-sub-agent-name">${(x) => { var _a; return (_a = x.liveSubAgentName) !== null && _a !== void 0 ? _a : 'Sub-agent'; }}</span>
113
+ ${repeat((x) => x.liveSubAgentTrace.filter((m) => m.role !== 'user'), subAgentMessageRowTemplate)}
114
+ </div>
115
+ `;
116
+ // ─── Public factory ───────────────────────────────────────────────────────────
66
117
  /** @internal */
67
118
  export const FoundationAiAssistantTemplate = (designSystemPrefix) => {
68
119
  const buttonTag = `${designSystemPrefix}-button`;
@@ -71,6 +122,75 @@ export const FoundationAiAssistantTemplate = (designSystemPrefix) => {
71
122
  const textareaTag = `${designSystemPrefix}-text-area`;
72
123
  const iconTag = `${designSystemPrefix}-icon`;
73
124
  const progressTag = `${designSystemPrefix}-progress`;
125
+ // ── Tool call item ──────────────────────────────────────────────────────────
126
+ const toolCallItemTemplate = html `
127
+ ${when((tc) => tc.foldEvent === 'open', html `
128
+ <pre class="payload fold-event fold-open">&#9658; ${(tc) => tc.name}</pre>
129
+ `)}
130
+ ${when((tc) => tc.foldEvent === 'close', html `
131
+ <pre class="payload fold-event fold-close">&#9668; ${(tc) => tc.name}</pre>
132
+ `)}
133
+ ${when((tc) => !tc.foldEvent && !isChatToolCallUnknown(tc), html `
134
+ <pre class="payload">
135
+ ${(tc) => { var _a; return (((_a = tc.foldPath) === null || _a === void 0 ? void 0 : _a.length) ? `${tc.foldPath.join(' › ')} › ` : ''); }}<strong>${(tc) => tc.name}</strong>(${(tc) => JSON.stringify(tc.args, null, 2)})</pre
136
+ >
137
+ `)}
138
+ ${when(isChatToolCallUnknown, html `
139
+ <pre class="payload unknown-tool">${(tc) => unknownToolPayload(tc)}</pre>
140
+ `)}
141
+ ${when((tc) => { var _a; return !!((_a = tc.subAgentTrace) === null || _a === void 0 ? void 0 : _a.length); }, subAgentTraceTemplate)}
142
+ `;
143
+ // ── Message row ─────────────────────────────────────────────────────────────
144
+ const messageRowTemplate = html `
145
+ ${when((m) => m.role === 'system-event', html `
146
+ <div class="agent-switch-indicator" part="agent-switch-indicator">
147
+ <span class="agent-switch-label">${(m) => m.content}</span>
148
+ </div>
149
+ `)}
150
+ ${when((m) => m.role !== 'system-event', html `
151
+ <div class="message-row ${(m) => messageType(m)}">
152
+ ${when((m) => m.role !== 'user', html `
153
+ <div class="avatar ${(m) => messageType(m)}">
154
+ ${when((m, c) => !!c.parent.imageSrc, html `
155
+ <img
156
+ src="${(m, c) => c.parent.imageSrc}"
157
+ alt="Assistant"
158
+ class="avatar-img"
159
+ />
160
+ `)}
161
+ ${when((m, c) => !c.parent.imageSrc, genesisIconTemplate)}
162
+ </div>
163
+ `)}
164
+ <div class="message ${(m) => messageType(m)}">
165
+ <div class="sender">
166
+ ${(m, c) => messageType(m) === 'ai-function' &&
167
+ m.agentName &&
168
+ c.parent.showAgentSwitchIndicator
169
+ ? `Tool Call · ${m.agentName}`
170
+ : senderLabel[messageType(m)]}
171
+ </div>
172
+ <div class="content">
173
+ ${when((m) => m.content, html `
174
+ <ai-chat-markdown :content="${(m) => m.content}"></ai-chat-markdown>
175
+ `)}
176
+ ${when((m) => m.toolCalls, html `
177
+ ${repeat((m) => { var _a; return (_a = m.toolCalls) !== null && _a !== void 0 ? _a : []; }, toolCallItemTemplate)}
178
+ `)}
179
+ ${when((m) => m.interaction, html `
180
+ <ai-chat-interaction-wrapper
181
+ :componentName=${(m) => m.interaction.componentName}
182
+ :data=${(m) => m.interaction.data}
183
+ :interactionId=${(m) => m.interaction.interactionId}
184
+ :resolved=${(m) => m.interaction.resolved}
185
+ @interaction-completed=${(m, c) => c.parent.handleInteractionCompleted(c.event)}
186
+ ></ai-chat-interaction-wrapper>
187
+ `)}
188
+ </div>
189
+ </div>
190
+ </div>
191
+ `)}
192
+ `;
193
+ // ── Root template ───────────────────────────────────────────────────────────
74
194
  return html `
75
195
  <div class="chat-wrapper" part="chat-wrapper">
76
196
  ${when((x) => { var _a; return !!((_a = x.chatConfig.ui) === null || _a === void 0 ? void 0 : _a.acceptedFiles); }, html `
@@ -204,77 +324,8 @@ export const FoundationAiAssistantTemplate = (designSystemPrefix) => {
204
324
  </div>
205
325
 
206
326
  <div class="messages" part="messages" ${ref('messagesEl')}>
207
-
208
- ${repeat((x) => x.visibleMessages, html `
209
- ${when((m) => m.role === 'system-event', html `
210
- <div class="agent-switch-indicator" part="agent-switch-indicator">
211
- <span class="agent-switch-label">${(m) => m.content}</span>
212
- </div>
213
- `)}
214
- ${when((m) => m.role !== 'system-event', html `
215
- <div class="message-row ${(m) => messageType(m)}">
216
- ${when((m) => m.role !== 'user', html `
217
- <div class="avatar ${(m) => messageType(m)}">
218
- ${when((m, c) => !!c.parent.imageSrc, html `
219
- <img
220
- src="${(m, c) => c.parent.imageSrc}"
221
- alt="Assistant"
222
- class="avatar-img"
223
- />
224
- `)}
225
- ${when((m, c) => !c.parent.imageSrc, genesisIconTemplate)}
226
- </div>
227
- `)}
228
- <div class="message ${(m) => messageType(m)}">
229
- <div class="sender">
230
- ${(m, c) => messageType(m) === 'ai-function' &&
231
- m.agentName &&
232
- c.parent.showAgentSwitchIndicator
233
- ? `Tool Call · ${m.agentName}`
234
- : senderLabel[messageType(m)]}
235
- </div>
236
- <div class="content">
237
- ${when((m) => m.content, html `
238
- <ai-chat-markdown :content="${(m) => m.content}"></ai-chat-markdown>
239
- `)}
240
- ${when((m) => m.toolCalls, html `
241
- ${repeat((m) => { var _a; return (_a = m.toolCalls) !== null && _a !== void 0 ? _a : []; }, html `
242
- ${when((tc) => tc.foldEvent === 'open', html `
243
- <pre class="payload fold-event fold-open">
244
- &#9658; ${(tc) => tc.name}</pre
245
- >
246
- `)}
247
- ${when((tc) => tc.foldEvent === 'close', html `
248
- <pre class="payload fold-event fold-close">
249
- &#9668; ${(tc) => tc.name}</pre
250
- >
251
- `)}
252
- ${when((tc) => !tc.foldEvent && !isChatToolCallUnknown(tc), html `
253
- <pre class="payload">
254
- ${(tc) => { var _a; return (((_a = tc.foldPath) === null || _a === void 0 ? void 0 : _a.length) ? `${tc.foldPath.join(' › ')} › ` : ''); }}<strong>${(tc) => tc.name}</strong>(${(tc) => JSON.stringify(tc.args, null, 2)})</pre
255
- >
256
- `)}
257
- ${when(isChatToolCallUnknown, html `
258
- <pre class="payload unknown-tool">
259
- ${(tc) => unknownToolPayload(tc)}</pre
260
- >
261
- `)}
262
- `)}
263
- `)}
264
- ${when((m) => m.interaction, html `
265
- <ai-chat-interaction-wrapper
266
- :componentName=${(m) => m.interaction.componentName}
267
- :data=${(m) => m.interaction.data}
268
- :interactionId=${(m) => m.interaction.interactionId}
269
- :resolved=${(m) => m.interaction.resolved}
270
- @interaction-completed=${(m, c) => c.parent.handleInteractionCompleted(c.event)}
271
- ></ai-chat-interaction-wrapper>
272
- `)}
273
- </div>
274
- </div>
275
- </div>
276
- `)}
277
- `)}
327
+ ${repeat((x) => x.visibleMessages, messageRowTemplate)}
328
+ ${when((x) => x.liveSubAgentTrace.length > 0 && x.showToolCalls, liveSubAgentTraceTemplate)}
278
329
  ${when((x) => {
279
330
  var _a;
280
331
  return x.showLoadingIndicator &&
@@ -11,6 +11,8 @@ export const defaultSessionState = {
11
11
  contextLimit: undefined,
12
12
  activeAgent: undefined,
13
13
  inputValue: '',
14
+ liveSubAgentTrace: [],
15
+ liveSubAgentName: null,
14
16
  };
15
17
  export const aiAssistantSlice = createSlice({
16
18
  name: 'aiAssistant',
@@ -49,6 +51,12 @@ export const aiAssistantSlice = createSlice({
49
51
  setInputValue(state, action) {
50
52
  state.inputValue = action.payload;
51
53
  },
54
+ setLiveSubAgentTrace(state, action) {
55
+ state.liveSubAgentTrace = action.payload;
56
+ },
57
+ setLiveSubAgentName(state, action) {
58
+ state.liveSubAgentName = action.payload;
59
+ },
52
60
  },
53
61
  selectors: {},
54
62
  });
@@ -0,0 +1,35 @@
1
+ /**
2
+ * Masks the tool-specific payload of a single message — clears tool call args
3
+ * and replaces tool result content with a placeholder. Used when passing history
4
+ * to an agent that should not see another agent's implementation detail.
5
+ */
6
+ function maskToolPayload(msg) {
7
+ var _a;
8
+ if ((_a = msg.toolCalls) === null || _a === void 0 ? void 0 : _a.length) {
9
+ return Object.assign(Object.assign({}, msg), { toolCalls: msg.toolCalls.map((tc) => (Object.assign(Object.assign({}, tc), { args: {} }))) });
10
+ }
11
+ if (msg.toolResult) {
12
+ return Object.assign(Object.assign({}, msg), { toolResult: Object.assign(Object.assign({}, msg.toolResult), { content: "[other agent's tool result omitted]" }) });
13
+ }
14
+ return msg;
15
+ }
16
+ /**
17
+ * Prepares history for the LLM only: masks tool call args and results from other
18
+ * agents so the active specialist is not confused by tools it does not have.
19
+ * Canonical history in `ChatDriver` stays unmasked for UI and logging.
20
+ */
21
+ export function transformHistoryForAgent(history, agentName) {
22
+ return history.map((msg) => {
23
+ if (!msg.agentName || msg.agentName === agentName)
24
+ return msg;
25
+ return maskToolPayload(msg);
26
+ });
27
+ }
28
+ /**
29
+ * Applies a history cap for sub-agent context: the last `cap` messages are passed
30
+ * verbatim; older messages have their tool payloads masked.
31
+ */
32
+ export function applyHistoryCap(history, cap) {
33
+ const cutoff = history.length - cap;
34
+ return history.map((msg, i) => (i < cutoff ? maskToolPayload(msg) : msg));
35
+ }
@@ -1 +1 @@
1
- {"root":["../src/index.ts","../src/channel/ai-activity-bus.ts","../src/channel/ai-activity-channel.ts","../src/components/halo-overlay.ts","../src/components/activity-halo/activity-halo.ts","../src/components/ai-driver/ai-driver.ts","../src/components/ai-driver/index.ts","../src/components/chat-bubble/chat-bubble.styles.ts","../src/components/chat-bubble/chat-bubble.template.ts","../src/components/chat-bubble/chat-bubble.ts","../src/components/chat-bubble/index.ts","../src/components/chat-driver/chat-driver.ts","../src/components/chat-driver/index.ts","../src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts","../src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts","../src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts","../src/components/chat-interaction-wrapper/index.ts","../src/components/chat-markdown/chat-markdown.ts","../src/components/chat-markdown/index.ts","../src/components/orchestrating-driver/index.ts","../src/components/orchestrating-driver/orchestrating-driver.ts","../src/components/popout-manager/index.ts","../src/components/popout-manager/popout-manager.ts","../src/config/config.ts","../src/config/fallback-agents.ts","../src/config/index.ts","../src/main/index.ts","../src/main/main.styles.ts","../src/main/main.template.ts","../src/main/main.ts","../src/main/main.types.ts","../src/state/ai-assistant-slice.ts","../src/state/driver-registry.ts","../src/state/session-store.ts","../src/styles/ai-colours.ts","../src/styles/index.ts","../src/styles/styles.ts","../src/suggestions/chat-suggestions.ts","../src/tags/index.ts","../src/types/ai-chat-widget.ts","../src/utils/index.ts","../src/utils/logger.ts","../src/utils/tool-fold.ts"],"version":"5.9.2"}
1
+ {"root":["../src/index.ts","../src/channel/ai-activity-bus.ts","../src/channel/ai-activity-channel.ts","../src/components/halo-overlay.ts","../src/components/activity-halo/activity-halo.ts","../src/components/ai-driver/ai-driver.ts","../src/components/ai-driver/index.ts","../src/components/chat-bubble/chat-bubble.styles.ts","../src/components/chat-bubble/chat-bubble.template.ts","../src/components/chat-bubble/chat-bubble.ts","../src/components/chat-bubble/index.ts","../src/components/chat-driver/chat-driver.ts","../src/components/chat-driver/index.ts","../src/components/chat-interaction-wrapper/chat-interaction-wrapper.styles.ts","../src/components/chat-interaction-wrapper/chat-interaction-wrapper.template.ts","../src/components/chat-interaction-wrapper/chat-interaction-wrapper.ts","../src/components/chat-interaction-wrapper/index.ts","../src/components/chat-markdown/chat-markdown.ts","../src/components/chat-markdown/index.ts","../src/components/orchestrating-driver/index.ts","../src/components/orchestrating-driver/orchestrating-driver.ts","../src/components/popout-manager/index.ts","../src/components/popout-manager/popout-manager.ts","../src/config/config.ts","../src/config/fallback-agents.ts","../src/config/index.ts","../src/main/index.ts","../src/main/main.styles.ts","../src/main/main.template.ts","../src/main/main.ts","../src/main/main.types.ts","../src/state/ai-assistant-slice.ts","../src/state/driver-registry.ts","../src/state/session-store.ts","../src/styles/ai-colours.ts","../src/styles/index.ts","../src/styles/styles.ts","../src/suggestions/chat-suggestions.ts","../src/tags/index.ts","../src/types/ai-chat-widget.ts","../src/utils/history-transform.ts","../src/utils/index.ts","../src/utils/logger.ts","../src/utils/tool-fold.ts"],"version":"5.9.2"}