@genesislcap/ai-assistant 14.421.0 → 14.421.1-FUI-2511.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-assistant.api.json +191 -1
- package/dist/ai-assistant.d.ts +60 -0
- package/dist/dts/components/chat-driver/chat-driver.d.ts +33 -0
- package/dist/dts/components/chat-driver/chat-driver.d.ts.map +1 -1
- package/dist/dts/components/orchestrating-driver/orchestrating-driver.d.ts.map +1 -1
- package/dist/dts/config/config.d.ts +20 -0
- package/dist/dts/config/config.d.ts.map +1 -1
- package/dist/dts/main/main.d.ts +6 -0
- package/dist/dts/main/main.d.ts.map +1 -1
- package/dist/dts/main/main.styles.d.ts.map +1 -1
- package/dist/dts/main/main.template.d.ts +16 -0
- package/dist/dts/main/main.template.d.ts.map +1 -1
- package/dist/dts/state/ai-assistant-slice.d.ts +6 -0
- package/dist/dts/state/ai-assistant-slice.d.ts.map +1 -1
- package/dist/dts/state/session-store.d.ts +2 -0
- package/dist/dts/state/session-store.d.ts.map +1 -1
- package/dist/dts/utils/history-transform.d.ts +13 -0
- package/dist/dts/utils/history-transform.d.ts.map +1 -0
- package/dist/esm/components/chat-driver/chat-driver.js +119 -12
- package/dist/esm/components/orchestrating-driver/orchestrating-driver.js +8 -20
- package/dist/esm/config/config.js +18 -1
- package/dist/esm/main/main.js +43 -11
- package/dist/esm/main/main.styles.js +62 -0
- package/dist/esm/main/main.template.js +122 -71
- package/dist/esm/state/ai-assistant-slice.js +8 -0
- package/dist/esm/utils/history-transform.js +35 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/docs/sub_agent.md +149 -211
- package/package.json +16 -16
- package/src/components/chat-driver/chat-driver.ts +161 -11
- package/src/components/orchestrating-driver/orchestrating-driver.ts +10 -22
- package/src/config/config.ts +24 -0
- package/src/main/main.styles.ts +62 -0
- package/src/main/main.template.ts +189 -117
- package/src/main/main.ts +43 -9
- package/src/state/ai-assistant-slice.ts +12 -0
- package/src/utils/history-transform.ts +40 -0
|
@@ -7,9 +7,11 @@ import type {
|
|
|
7
7
|
ChatToolCall,
|
|
8
8
|
ChatToolDefinition,
|
|
9
9
|
ChatToolHandlers,
|
|
10
|
+
SubAgentRequestOptions,
|
|
10
11
|
} from '@genesislcap/foundation-ai';
|
|
11
12
|
import { MalformedFunctionCallError } from '@genesislcap/foundation-ai';
|
|
12
13
|
import type { AgentConfig } from '../../config/config';
|
|
14
|
+
import { applyHistoryCap } from '../../utils/history-transform';
|
|
13
15
|
import { logger } from '../../utils/logger';
|
|
14
16
|
import { TOOL_FOLD_SYMBOL, type ToolFold } from '../../utils/tool-fold';
|
|
15
17
|
import type { AiDriver, AllAgentSummary } from '../ai-driver/ai-driver';
|
|
@@ -77,6 +79,16 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
77
79
|
private consecutiveUnknownToolCalls = 0;
|
|
78
80
|
private readonly maxFoldOperations: number;
|
|
79
81
|
|
|
82
|
+
/** Sub-agents declared on the active agent config, keyed by name. */
|
|
83
|
+
private subAgentsMap: Map<string, AgentConfig> = new Map();
|
|
84
|
+
/**
|
|
85
|
+
* Set by `completeSubAgent` inside a sub-agent tool handler. Checked at the
|
|
86
|
+
* same point in the loop as `REQUEST_CONTINUATION_TOOL` — after tool results
|
|
87
|
+
* are appended — so the exit path mirrors the system-call pattern.
|
|
88
|
+
* `undefined` means the loop has not been stopped early.
|
|
89
|
+
*/
|
|
90
|
+
private subAgentCompletion: { result: unknown } | undefined;
|
|
91
|
+
|
|
80
92
|
constructor(
|
|
81
93
|
private readonly aiProvider: AIProvider,
|
|
82
94
|
toolHandlers: ChatToolHandlers = {},
|
|
@@ -104,11 +116,20 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
104
116
|
this.toolHandlers = config.toolHandlers ?? {};
|
|
105
117
|
this.primerHistory = config.primerHistory;
|
|
106
118
|
this.activeAgentName = config.name;
|
|
119
|
+
this.subAgentsMap = new Map((config.subAgents ?? []).map((s) => [s.name, s]));
|
|
107
120
|
// Reset fold state when agent changes — each specialist starts fresh
|
|
108
121
|
this.foldStack = [];
|
|
109
122
|
this.consecutiveFoldOps = 0;
|
|
110
123
|
}
|
|
111
124
|
|
|
125
|
+
/**
|
|
126
|
+
* Returns the early-stop result set by `completeSubAgent`, if any.
|
|
127
|
+
* Called by a parent `ChatDriver` after running this instance as a sub-agent.
|
|
128
|
+
*/
|
|
129
|
+
getSubAgentCompletion(): { result: unknown } | undefined {
|
|
130
|
+
return this.subAgentCompletion;
|
|
131
|
+
}
|
|
132
|
+
|
|
112
133
|
/**
|
|
113
134
|
* Optional transform applied to conversation history immediately before each LLM request.
|
|
114
135
|
* Cleared when `undefined`. Does not alter stored history.
|
|
@@ -281,6 +302,7 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
281
302
|
}
|
|
282
303
|
|
|
283
304
|
this.busy = true;
|
|
305
|
+
this.subAgentCompletion = undefined;
|
|
284
306
|
this.appendToHistory({ role: 'user', content: userInput, attachments });
|
|
285
307
|
|
|
286
308
|
try {
|
|
@@ -294,6 +316,116 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
294
316
|
}
|
|
295
317
|
}
|
|
296
318
|
|
|
319
|
+
/**
|
|
320
|
+
* Builds the context object passed to every tool handler call.
|
|
321
|
+
* Centralised here so fold shortcut dispatch and the main tool loop use the
|
|
322
|
+
* same context without duplication.
|
|
323
|
+
*
|
|
324
|
+
* @param traceCapture - Optional per-invocation slot. When provided, the trace
|
|
325
|
+
* from any sub-agent call is written here rather than to shared instance state,
|
|
326
|
+
* so parallel tool calls each capture their own trace independently.
|
|
327
|
+
*/
|
|
328
|
+
private buildHandlerContext(traceCapture?: { trace?: ChatMessage[] }) {
|
|
329
|
+
return {
|
|
330
|
+
requestInteraction: <T>(componentName: string, data: any): Promise<T> =>
|
|
331
|
+
this.requestInteraction(componentName, data),
|
|
332
|
+
...(this.subAgentsMap.size > 0 && {
|
|
333
|
+
requestSubAgent: <T = never>(
|
|
334
|
+
name: string,
|
|
335
|
+
options?: SubAgentRequestOptions,
|
|
336
|
+
): Promise<T | string> =>
|
|
337
|
+
this.invokeSubAgent<T>(name, options).then(({ result, trace }) => {
|
|
338
|
+
if (traceCapture) traceCapture.trace = trace;
|
|
339
|
+
return result;
|
|
340
|
+
}),
|
|
341
|
+
}),
|
|
342
|
+
completeSubAgent: (result: unknown): void => {
|
|
343
|
+
if (this.subAgentCompletion) {
|
|
344
|
+
logger.warn(
|
|
345
|
+
`ChatDriver(${this.activeAgentName ?? 'unknown'}): completeSubAgent called more than once — ignoring`,
|
|
346
|
+
);
|
|
347
|
+
return;
|
|
348
|
+
}
|
|
349
|
+
this.subAgentCompletion = { result };
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
/**
|
|
355
|
+
* Creates a child `ChatDriver` for the named sub-agent, runs it to completion,
|
|
356
|
+
* and returns its structured result (or final text fallback) together with the
|
|
357
|
+
* full child conversation trace. Callers receive both values so each parallel
|
|
358
|
+
* invocation can capture its own trace without touching shared instance state.
|
|
359
|
+
*/
|
|
360
|
+
private async invokeSubAgent<T = never>(
|
|
361
|
+
name: string,
|
|
362
|
+
options?: SubAgentRequestOptions,
|
|
363
|
+
): Promise<{ result: T | string; trace: ChatMessage[] }> {
|
|
364
|
+
const subConfig = this.subAgentsMap.get(name);
|
|
365
|
+
if (!subConfig) {
|
|
366
|
+
const available = [...this.subAgentsMap.keys()].join(', ') || '(none)';
|
|
367
|
+
throw new Error(
|
|
368
|
+
`Sub-agent "${name}" not found on agent "${this.activeAgentName}". Available: ${available}`,
|
|
369
|
+
);
|
|
370
|
+
}
|
|
371
|
+
|
|
372
|
+
const { task, historyCap, context } = options ?? {};
|
|
373
|
+
|
|
374
|
+
// Exclude the current in-flight assistant message (the one with tool calls that
|
|
375
|
+
// triggered this invocation) — it has unresolved tool calls that would confuse
|
|
376
|
+
// the sub-agent into thinking it needs to handle tools it doesn't own.
|
|
377
|
+
const lastMsg = this.history[this.history.length - 1];
|
|
378
|
+
const baseHistory =
|
|
379
|
+
lastMsg?.role === 'assistant' && lastMsg.toolCalls?.length
|
|
380
|
+
? this.history.slice(0, -1)
|
|
381
|
+
: this.history;
|
|
382
|
+
|
|
383
|
+
const snapshotHistory =
|
|
384
|
+
historyCap != null ? applyHistoryCap(baseHistory, historyCap) : [...baseHistory];
|
|
385
|
+
|
|
386
|
+
const contextMessages: ChatMessage[] = context
|
|
387
|
+
? [{ role: 'user', content: `[Sub-agent context]: ${JSON.stringify(context)}` }]
|
|
388
|
+
: [];
|
|
389
|
+
|
|
390
|
+
const effectivePrimer: ChatMessage[] = [
|
|
391
|
+
...snapshotHistory,
|
|
392
|
+
...contextMessages,
|
|
393
|
+
...(subConfig.primerHistory ?? []),
|
|
394
|
+
];
|
|
395
|
+
|
|
396
|
+
const child = new ChatDriver(this.aiProvider);
|
|
397
|
+
child.applyAgent({ ...subConfig, primerHistory: effectivePrimer });
|
|
398
|
+
|
|
399
|
+
const forwardTrace = (e: Event) => {
|
|
400
|
+
this.dispatchEvent(
|
|
401
|
+
new CustomEvent('sub-agent-history-updated', {
|
|
402
|
+
detail: { agentName: subConfig.name, history: (e as CustomEvent<ChatMessage[]>).detail },
|
|
403
|
+
}),
|
|
404
|
+
);
|
|
405
|
+
};
|
|
406
|
+
child.addEventListener('history-updated', forwardTrace);
|
|
407
|
+
|
|
408
|
+
this.dispatchEvent(new CustomEvent('sub-agent-start', { detail: { name } }));
|
|
409
|
+
try {
|
|
410
|
+
await child.sendMessage(task ?? '');
|
|
411
|
+
} finally {
|
|
412
|
+
child.removeEventListener('history-updated', forwardTrace);
|
|
413
|
+
this.dispatchEvent(new CustomEvent('sub-agent-stop', { detail: { name } }));
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
const trace = child.getHistory() as ChatMessage[];
|
|
417
|
+
const completion = child.getSubAgentCompletion();
|
|
418
|
+
|
|
419
|
+
if (completion) {
|
|
420
|
+
return { result: completion.result as T, trace };
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
const finalMsg = [...trace]
|
|
424
|
+
.reverse()
|
|
425
|
+
.find((m) => m.role === 'assistant' && !m.toolCalls?.length && m.content?.trim());
|
|
426
|
+
return { result: (finalMsg?.content ?? '') as string, trace };
|
|
427
|
+
}
|
|
428
|
+
|
|
297
429
|
/**
|
|
298
430
|
* Continue the tool loop from current history without appending a new user message.
|
|
299
431
|
* Used by OrchestratingDriver after an agent handoff.
|
|
@@ -306,6 +438,7 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
306
438
|
}
|
|
307
439
|
|
|
308
440
|
this.busy = true;
|
|
441
|
+
this.subAgentCompletion = undefined;
|
|
309
442
|
try {
|
|
310
443
|
return await this.runToolLoop('', undefined, transientPrimer);
|
|
311
444
|
} catch (e) {
|
|
@@ -400,9 +533,9 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
400
533
|
typeof args[key] === 'object' && args[key] !== null
|
|
401
534
|
? (args[key] as Record<string, unknown>)
|
|
402
535
|
: {};
|
|
403
|
-
return innerHandler(innerArgs,
|
|
404
|
-
|
|
405
|
-
|
|
536
|
+
return innerHandler(innerArgs, this.buildHandlerContext()).then((r) =>
|
|
537
|
+
typeof r === 'string' ? r : JSON.stringify(r),
|
|
538
|
+
);
|
|
406
539
|
}
|
|
407
540
|
}
|
|
408
541
|
|
|
@@ -487,7 +620,11 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
487
620
|
let currentAttachments: ChatAttachment[] | undefined = attachments;
|
|
488
621
|
let iterations = 0;
|
|
489
622
|
let malformedAttempts = 0;
|
|
490
|
-
|
|
623
|
+
// True only for the very first LLM call. Used to exclude the pending user message
|
|
624
|
+
// from history (it is passed separately as currentInput). Must not be derived from
|
|
625
|
+
// `iterations` because fold operations decrement iterations, which would incorrectly
|
|
626
|
+
// re-trigger the slice on subsequent calls after a fold open/close.
|
|
627
|
+
let firstLlmCall = !!currentInput;
|
|
491
628
|
|
|
492
629
|
while (iterations < this.maxToolIterations) {
|
|
493
630
|
iterations += 1;
|
|
@@ -498,7 +635,8 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
498
635
|
: foldSuffix || undefined;
|
|
499
636
|
|
|
500
637
|
const primer = [...(this.primerHistory ?? []), ...(transientPrimer ?? [])];
|
|
501
|
-
const baseHistory =
|
|
638
|
+
const baseHistory = firstLlmCall ? this.history.slice(0, -1) : this.history;
|
|
639
|
+
firstLlmCall = false;
|
|
502
640
|
const historyForProvider = this.providerHistoryTransform
|
|
503
641
|
? this.providerHistoryTransform([...baseHistory])
|
|
504
642
|
: baseHistory;
|
|
@@ -581,7 +719,10 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
581
719
|
[[], []],
|
|
582
720
|
);
|
|
583
721
|
|
|
584
|
-
const executedById = new Map<
|
|
722
|
+
const executedById = new Map<
|
|
723
|
+
string,
|
|
724
|
+
{ toolCallId: string; content: string; subAgentTrace?: ChatMessage[] }
|
|
725
|
+
>();
|
|
585
726
|
const unknownToolIds = new Set<string>();
|
|
586
727
|
let anyRealToolExecuted = false;
|
|
587
728
|
let hitUnknownToolLimit = false;
|
|
@@ -660,12 +801,14 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
660
801
|
|
|
661
802
|
// Real tool execution
|
|
662
803
|
try {
|
|
663
|
-
const
|
|
664
|
-
|
|
665
|
-
this.requestInteraction(componentName, data),
|
|
666
|
-
});
|
|
804
|
+
const traceCapture: { trace?: ChatMessage[] } = {};
|
|
805
|
+
const result = await handler(tc.args, this.buildHandlerContext(traceCapture));
|
|
667
806
|
const content = typeof result === 'string' ? result : JSON.stringify(result);
|
|
668
|
-
executedById.set(tc.id, {
|
|
807
|
+
executedById.set(tc.id, {
|
|
808
|
+
toolCallId: tc.id,
|
|
809
|
+
content,
|
|
810
|
+
subAgentTrace: traceCapture.trace,
|
|
811
|
+
});
|
|
669
812
|
anyRealToolExecuted = true;
|
|
670
813
|
} catch (e) {
|
|
671
814
|
logger.error(`ChatDriver tool "${tc.name}" failed:`, e);
|
|
@@ -734,6 +877,7 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
734
877
|
foldPath: !isFoldOpen && !isFoldClose && foldPath.length > 0 ? foldPath : undefined,
|
|
735
878
|
unknown: isUnknown || undefined,
|
|
736
879
|
availableTools: isUnknown ? availableToolNames : undefined,
|
|
880
|
+
subAgentTrace: executedById.get(tc.id)?.subAgentTrace,
|
|
737
881
|
};
|
|
738
882
|
});
|
|
739
883
|
this.history[tcMsgIdx] = { ...tcMsg, toolCalls: annotatedCalls };
|
|
@@ -765,6 +909,12 @@ export class ChatDriver extends EventTarget implements AiDriver {
|
|
|
765
909
|
return { reason: 'agent-handoff', summary, remainingTask };
|
|
766
910
|
}
|
|
767
911
|
|
|
912
|
+
// Sub-agent early exit — checked here so the exit point mirrors the
|
|
913
|
+
// system-call pattern above. Set by completeSubAgent() in a tool handler.
|
|
914
|
+
if (this.subAgentCompletion) {
|
|
915
|
+
return { reason: 'done' };
|
|
916
|
+
}
|
|
917
|
+
|
|
768
918
|
currentInput = '';
|
|
769
919
|
}
|
|
770
920
|
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
ChatRequestOptions,
|
|
7
7
|
} from '@genesislcap/foundation-ai';
|
|
8
8
|
import type { AgentConfig, FallbackAgentConfig, SpecialistAgentConfig } from '../../config/config';
|
|
9
|
+
import { transformHistoryForAgent } from '../../utils/history-transform';
|
|
9
10
|
import { logger } from '../../utils/logger';
|
|
10
11
|
import type { AiDriver, AllAgentSummary } from '../ai-driver/ai-driver';
|
|
11
12
|
import { ChatDriver, REQUEST_CONTINUATION_TOOL } from '../chat-driver/chat-driver';
|
|
@@ -54,27 +55,6 @@ function buildFallbackSystemPrompt(
|
|
|
54
55
|
return `You are a helpful assistant. You cannot directly help with the user's request, but the following specialists are available:\n\n${agentList}\n\nPolitely let the user know what you can help with and invite them to rephrase their request.`;
|
|
55
56
|
}
|
|
56
57
|
|
|
57
|
-
/**
|
|
58
|
-
* Prepares history for the LLM only: masks tool call args and results from other
|
|
59
|
-
* agents so the active specialist is not confused by tools it does not have.
|
|
60
|
-
* Canonical history in `ChatDriver` stays unmasked for UI and logging.
|
|
61
|
-
*/
|
|
62
|
-
function transformHistoryForAgent(history: ChatMessage[], agentName: string): ChatMessage[] {
|
|
63
|
-
return history.map((msg) => {
|
|
64
|
-
if (!msg.agentName || msg.agentName === agentName) return msg;
|
|
65
|
-
if (msg.toolCalls?.length) {
|
|
66
|
-
return { ...msg, toolCalls: msg.toolCalls.map((tc) => ({ ...tc, args: {} })) };
|
|
67
|
-
}
|
|
68
|
-
if (msg.toolResult) {
|
|
69
|
-
return {
|
|
70
|
-
...msg,
|
|
71
|
-
toolResult: { ...msg.toolResult, content: "[other agent's tool result omitted]" },
|
|
72
|
-
};
|
|
73
|
-
}
|
|
74
|
-
return msg;
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
|
-
|
|
78
58
|
/**
|
|
79
59
|
* Orchestrates multiple specialist agents. Sits between `FoundationAiAssistant`
|
|
80
60
|
* and `ChatDriver`, classifying each user message and routing it to the right
|
|
@@ -132,10 +112,18 @@ export class OrchestratingDriver extends EventTarget implements AiDriver {
|
|
|
132
112
|
options.maxFoldOperations,
|
|
133
113
|
);
|
|
134
114
|
|
|
135
|
-
// Proxy
|
|
115
|
+
// Proxy events from the shared driver
|
|
136
116
|
this.chatDriver.addEventListener('history-updated', (e: Event) => {
|
|
137
117
|
this.dispatchEvent(new CustomEvent('history-updated', { detail: (e as CustomEvent).detail }));
|
|
138
118
|
});
|
|
119
|
+
this.chatDriver.addEventListener('sub-agent-history-updated', (e: Event) => {
|
|
120
|
+
this.dispatchEvent(
|
|
121
|
+
new CustomEvent('sub-agent-history-updated', { detail: (e as CustomEvent).detail }),
|
|
122
|
+
);
|
|
123
|
+
});
|
|
124
|
+
this.chatDriver.addEventListener('sub-agent-stop', (e: Event) => {
|
|
125
|
+
this.dispatchEvent(new CustomEvent('sub-agent-stop', { detail: (e as CustomEvent).detail }));
|
|
126
|
+
});
|
|
139
127
|
}
|
|
140
128
|
|
|
141
129
|
resolveInteraction(interactionId: string, result: unknown): void {
|
package/src/config/config.ts
CHANGED
|
@@ -22,6 +22,10 @@ interface BaseAgentConfig {
|
|
|
22
22
|
* Used to establish agent identity and behavioural rules.
|
|
23
23
|
*/
|
|
24
24
|
primerHistory?: ChatMessage[];
|
|
25
|
+
/**
|
|
26
|
+
* Sub-agents available to this agent's tool handlers via `requestSubAgent`.
|
|
27
|
+
*/
|
|
28
|
+
subAgents?: AgentConfig[];
|
|
25
29
|
}
|
|
26
30
|
|
|
27
31
|
/**
|
|
@@ -67,3 +71,23 @@ export interface FallbackAgentConfig extends BaseAgentConfig {
|
|
|
67
71
|
* @beta
|
|
68
72
|
*/
|
|
69
73
|
export type AgentConfig = SpecialistAgentConfig | FallbackAgentConfig;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Identity helper that infers the narrowest possible type for an agent config,
|
|
77
|
+
* preserving string literal types (including `name`) without requiring `as const`.
|
|
78
|
+
*
|
|
79
|
+
* Use this when you need `typeof myAgent` to carry the literal `name` type —
|
|
80
|
+
* for example, when wiring `ChatToolHandlers<typeof myAgent>`.
|
|
81
|
+
*
|
|
82
|
+
* ```ts
|
|
83
|
+
* const myAgent = defineAgent({ name: 'my_agent', ... });
|
|
84
|
+
* type Handlers = ChatToolHandlers<typeof myAgent>;
|
|
85
|
+
* // requestSubAgent name param is now typed as 'my_agent'
|
|
86
|
+
* ```
|
|
87
|
+
*
|
|
88
|
+
* @beta
|
|
89
|
+
*/
|
|
90
|
+
|
|
91
|
+
export function defineAgent<const T extends AgentConfig>(config: T): T {
|
|
92
|
+
return config;
|
|
93
|
+
}
|
package/src/main/main.styles.ts
CHANGED
|
@@ -451,6 +451,68 @@ export const styles = css`
|
|
|
451
451
|
padding-left: 8px;
|
|
452
452
|
}
|
|
453
453
|
|
|
454
|
+
.live-sub-agent-trace {
|
|
455
|
+
animation: slide-in-left 0.25s ease-out;
|
|
456
|
+
border-left: 2px solid var(--neutral-stroke-rest);
|
|
457
|
+
padding: 4px 8px;
|
|
458
|
+
margin: 4px 0;
|
|
459
|
+
opacity: 80%;
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.live-sub-agent-name {
|
|
463
|
+
font-family: monospace;
|
|
464
|
+
font-size: 0.8em;
|
|
465
|
+
opacity: 70%;
|
|
466
|
+
font-style: italic;
|
|
467
|
+
display: block;
|
|
468
|
+
margin-bottom: 2px;
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
.sub-agent-trace {
|
|
472
|
+
margin-top: 6px;
|
|
473
|
+
border-left: 2px solid var(--neutral-stroke-rest);
|
|
474
|
+
padding-left: 8px;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
.sub-agent-trace-summary {
|
|
478
|
+
font-family: monospace;
|
|
479
|
+
font-size: 0.85em;
|
|
480
|
+
opacity: 70%;
|
|
481
|
+
cursor: pointer;
|
|
482
|
+
user-select: none;
|
|
483
|
+
padding: 2px 0;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
.sub-agent-trace-summary:hover {
|
|
487
|
+
opacity: 100%;
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
.sub-agent-message {
|
|
491
|
+
font-family: monospace;
|
|
492
|
+
font-size: 0.85em;
|
|
493
|
+
margin-top: 4px;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.sub-agent-assistant {
|
|
497
|
+
opacity: 85%;
|
|
498
|
+
white-space: pre-wrap;
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
.sub-agent-tool-call {
|
|
502
|
+
opacity: 60%;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
.sub-agent-tool-name::before {
|
|
506
|
+
content: '⚙ ';
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.sub-agent-tool-result {
|
|
510
|
+
opacity: 50%;
|
|
511
|
+
border-left: 1px solid var(--neutral-stroke-rest);
|
|
512
|
+
padding-left: 6px;
|
|
513
|
+
white-space: pre-wrap;
|
|
514
|
+
}
|
|
515
|
+
|
|
454
516
|
.input-row {
|
|
455
517
|
display: flex;
|
|
456
518
|
gap: calc(var(--design-unit) * 2px);
|