@optilogic/chat 1.0.0-beta.9 → 1.0.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 (31) hide show
  1. package/README.md +43 -0
  2. package/dist/index.cjs +709 -79
  3. package/dist/index.cjs.map +1 -1
  4. package/dist/index.d.cts +283 -4
  5. package/dist/index.d.ts +283 -4
  6. package/dist/index.js +674 -53
  7. package/dist/index.js.map +1 -1
  8. package/package.json +3 -3
  9. package/src/components/agent-response/AgentResponse.tsx +59 -13
  10. package/src/components/agent-response/components/MetadataRow.tsx +15 -4
  11. package/src/components/agent-response/components/TruncatedMessage.tsx +52 -0
  12. package/src/components/agent-response/components/index.ts +3 -0
  13. package/src/components/agent-response/hooks/useAgentResponseAccumulator.ts +65 -8
  14. package/src/components/agent-response/index.ts +19 -0
  15. package/src/components/agent-response/types.ts +61 -1
  16. package/src/components/agent-timeline/AgentTimeline.tsx +256 -0
  17. package/src/components/agent-timeline/TimelineAgentBlock.tsx +84 -0
  18. package/src/components/agent-timeline/TimelineItem.tsx +97 -0
  19. package/src/components/agent-timeline/index.ts +14 -0
  20. package/src/components/agent-timeline/types.ts +49 -0
  21. package/src/components/agent-timeline/utils.ts +189 -0
  22. package/src/components/hitl-interactions/HITLQuestionPanel.tsx +35 -21
  23. package/src/components/hitl-interactions/index.ts +1 -1
  24. package/src/components/inline-actions/ActionMarkdownRenderer.tsx +60 -0
  25. package/src/components/inline-actions/index.ts +18 -0
  26. package/src/components/inline-actions/parseResponseSegments.ts +66 -0
  27. package/src/components/inline-actions/prompts.ts +41 -0
  28. package/src/components/inline-actions/types.ts +57 -0
  29. package/src/components/user-prompt-input/UserPromptInput.tsx +13 -8
  30. package/src/components/user-prompt-input/types.ts +4 -0
  31. package/src/index.ts +29 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optilogic/chat",
3
- "version": "1.0.0-beta.9",
3
+ "version": "1.0.0",
4
4
  "description": "Chat UI components for Optilogic - AgentResponse and related components for LLM interactions",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -24,8 +24,8 @@
24
24
  "README.md"
25
25
  ],
26
26
  "dependencies": {
27
- "@optilogic/core": "1.0.0-beta.9",
28
- "@optilogic/editor": "1.0.0-beta.9"
27
+ "@optilogic/core": "1.0.0",
28
+ "@optilogic/editor": "1.0.0"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "react": "^18.0.0 || ^19.0.0",
@@ -6,12 +6,14 @@
6
6
  */
7
7
 
8
8
  import * as React from "react";
9
- import { useState, useMemo, useCallback } from "react";
9
+ import { useState, useRef, useMemo, useCallback } from "react";
10
10
  import { cn } from "@optilogic/core";
11
11
  import { MetadataRow, ThinkingSection, ActionBar, HITLSection } from "./components";
12
12
  import { useThinkingTimer } from "./hooks";
13
13
  import type { AgentResponseState, FeedbackValue } from "./types";
14
14
  import type { HITLInteraction } from "../hitl-interactions";
15
+ import { AgentTimeline, createTimelineUIState } from "../agent-timeline";
16
+ import type { TimelineUIState } from "../agent-timeline";
15
17
 
16
18
  export interface AgentResponseProps extends React.HTMLAttributes<HTMLDivElement> {
17
19
  /** The response state to render */
@@ -49,6 +51,24 @@ export interface AgentResponseProps extends React.HTMLAttributes<HTMLDivElement>
49
51
  /** Whether the HITL section starts expanded (default: false) */
50
52
  defaultHITLExpanded?: boolean;
51
53
 
54
+ /**
55
+ * Optional content to display in the MetadataRow's middle area,
56
+ * between the thinking toggle (left) and activity indicators (right).
57
+ * Typically used for ephemeral status messages during processing.
58
+ * The parent is responsible for setting and clearing this content.
59
+ *
60
+ * @example
61
+ * <AgentResponse
62
+ * state={state}
63
+ * statusContent={
64
+ * state.status !== 'complete'
65
+ * ? <TruncatedMessage message="Analyzing data..." />
66
+ * : undefined
67
+ * }
68
+ * />
69
+ */
70
+ statusContent?: React.ReactNode;
71
+
52
72
  /**
53
73
  * Custom markdown renderer for the response content.
54
74
  * If not provided, the response will be rendered as plain text.
@@ -72,6 +92,12 @@ export interface AgentResponseProps extends React.HTMLAttributes<HTMLDivElement>
72
92
  * />
73
93
  */
74
94
  renderThinkingMarkdown?: (content: string) => React.ReactNode;
95
+
96
+ /**
97
+ * Maximum height of the AgentTimeline scrollable container.
98
+ * Defaults to "300px". Set to "none" to disable the constraint.
99
+ */
100
+ timelineMaxHeight?: string;
75
101
  }
76
102
 
77
103
  /**
@@ -121,13 +147,18 @@ const AgentResponse = React.forwardRef<HTMLDivElement, AgentResponseProps>(
121
147
  actionsVisible = "hover",
122
148
  hitlInteractions,
123
149
  defaultHITLExpanded = false,
150
+ statusContent,
124
151
  renderMarkdown,
125
152
  renderThinkingMarkdown,
153
+ timelineMaxHeight,
126
154
  className,
127
155
  ...props
128
156
  },
129
157
  ref
130
158
  ) => {
159
+ // Ref-backed timeline UI state (survives remounts during streaming)
160
+ const timelineUIStateRef = useRef<TimelineUIState>(createTimelineUIState());
161
+
131
162
  // Uncontrolled thinking expanded state
132
163
  const [uncontrolledExpanded, setUncontrolledExpanded] = useState(defaultThinkingExpanded);
133
164
 
@@ -163,9 +194,10 @@ const AgentResponse = React.forwardRef<HTMLDivElement, AgentResponseProps>(
163
194
  return (state.responseCompleteTime - state.firstMessageTime) / 1000;
164
195
  }, [state.firstMessageTime, state.responseCompleteTime]);
165
196
 
166
- // Check if we have any thinking content (plain text or structured)
197
+ // Check if we have any thinking content (plain text, structured, or timeline)
198
+ const hasTimelineEntries = !!(state.timelineEntries && state.timelineEntries.length > 0);
167
199
  const hasThinkingContent =
168
- !!state.thinking || (state.thinkingSteps && state.thinkingSteps.length > 0) || false;
200
+ !!state.thinking || (state.thinkingSteps && state.thinkingSteps.length > 0) || hasTimelineEntries || false;
169
201
 
170
202
  const hasHITLInteractions =
171
203
  hitlInteractions && hitlInteractions.length > 0;
@@ -221,20 +253,34 @@ const AgentResponse = React.forwardRef<HTMLDivElement, AgentResponseProps>(
221
253
  knowledge={state.knowledge}
222
254
  memory={state.memory}
223
255
  statusUpdates={state.statusUpdates}
256
+ statusContent={statusContent}
224
257
  status={state.status}
225
258
  elapsedTime={elapsedTime}
226
259
  />
227
260
 
228
- {/* Thinking Content - collapsible with max-height */}
229
- <ThinkingSection
230
- content={
231
- state.thinkingSteps && state.thinkingSteps.length > 0
232
- ? state.thinkingSteps
233
- : state.thinking
234
- }
235
- isExpanded={thinkingExpanded}
236
- renderMarkdown={renderThinkingMarkdown}
237
- />
261
+ {/* Thinking Content - AgentTimeline when timeline entries exist, ThinkingSection otherwise */}
262
+ {hasTimelineEntries ? (
263
+ thinkingExpanded && (
264
+ <div className="pb-3 border-t border-border">
265
+ <AgentTimeline
266
+ entries={state.timelineEntries!}
267
+ renderMarkdown={renderThinkingMarkdown}
268
+ uiState={timelineUIStateRef.current}
269
+ maxHeight={timelineMaxHeight}
270
+ />
271
+ </div>
272
+ )
273
+ ) : (
274
+ <ThinkingSection
275
+ content={
276
+ state.thinkingSteps && state.thinkingSteps.length > 0
277
+ ? state.thinkingSteps
278
+ : state.thinking
279
+ }
280
+ isExpanded={thinkingExpanded}
281
+ renderMarkdown={renderThinkingMarkdown}
282
+ />
283
+ )}
238
284
  </>
239
285
  )}
240
286
 
@@ -26,6 +26,8 @@ export interface MetadataRowProps extends React.HTMLAttributes<HTMLDivElement> {
26
26
  memory: MemoryItem[];
27
27
  /** Status updates to display */
28
28
  statusUpdates?: StatusItem[];
29
+ /** Optional content to display in the middle area between left content and activity indicators */
30
+ statusContent?: React.ReactNode;
29
31
  /** Current response status */
30
32
  status: AgentResponseStatus;
31
33
  /** Elapsed time in seconds */
@@ -60,6 +62,7 @@ const MetadataRow = React.forwardRef<HTMLDivElement, MetadataRowProps>(
60
62
  knowledge,
61
63
  memory,
62
64
  statusUpdates = [],
65
+ statusContent,
63
66
  status,
64
67
  elapsedTime,
65
68
  className,
@@ -108,8 +111,8 @@ const MetadataRow = React.forwardRef<HTMLDivElement, MetadataRowProps>(
108
111
 
109
112
  const leftContent = renderLeftContent();
110
113
 
111
- // If nothing to show (no thinking, not processing, no activity), hide the row
112
- if (!leftContent && !hasActivity) {
114
+ // If nothing to show (no thinking, not processing, no activity, no status content), hide the row
115
+ if (!leftContent && !hasActivity && !statusContent) {
113
116
  return null;
114
117
  }
115
118
 
@@ -125,15 +128,23 @@ const MetadataRow = React.forwardRef<HTMLDivElement, MetadataRowProps>(
125
128
  {hasThinking ? (
126
129
  <button
127
130
  onClick={onToggle}
128
- className="flex items-center gap-1.5 hover:bg-muted/50 -ml-1.5 pl-1.5 pr-2 py-0.5 rounded transition-colors"
131
+ className="flex items-center gap-1.5 hover:bg-muted/50 -ml-1.5 pl-1.5 pr-2 py-0.5 rounded transition-colors shrink-0"
129
132
  >
130
133
  {leftContent}
131
134
  </button>
132
135
  ) : (
133
- <div className="flex items-center gap-1.5">
136
+ <div className="flex items-center gap-1.5 shrink-0">
134
137
  {leftContent}
135
138
  </div>
136
139
  )}
140
+
141
+ {/* Middle content - status content slot */}
142
+ {statusContent && (
143
+ <div className="flex-1 min-w-0 mx-2">
144
+ {statusContent}
145
+ </div>
146
+ )}
147
+
137
148
  <ActivityIndicators
138
149
  toolCalls={toolCalls}
139
150
  knowledge={knowledge}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Truncated Message Component
3
+ *
4
+ * Renders a single-line text message with CSS-based truncation (text-overflow: ellipsis).
5
+ * Designed as a standalone utility that can be used anywhere, including as
6
+ * the statusContent slot in MetadataRow.
7
+ */
8
+
9
+ import * as React from "react";
10
+ import { cn } from "@optilogic/core";
11
+
12
+ export interface TruncatedMessageProps extends React.HTMLAttributes<HTMLDivElement> {
13
+ /** The message string to display (truncated with ellipsis if it overflows) */
14
+ message: string;
15
+ }
16
+
17
+ /**
18
+ * TruncatedMessage Component
19
+ *
20
+ * Displays a single-line text message that truncates with an ellipsis when
21
+ * it overflows its container. Uses CSS text-overflow for zero-JS truncation.
22
+ *
23
+ * @example
24
+ * <TruncatedMessage message="Searching the knowledge base for relevant documents..." />
25
+ *
26
+ * @example
27
+ * // Inside MetadataRow's statusContent slot
28
+ * <AgentResponse
29
+ * state={state}
30
+ * statusContent={<TruncatedMessage message="Running analysis..." />}
31
+ * />
32
+ */
33
+ const TruncatedMessage = React.forwardRef<HTMLDivElement, TruncatedMessageProps>(
34
+ ({ message, className, ...props }, ref) => {
35
+ return (
36
+ <div
37
+ ref={ref}
38
+ className={cn(
39
+ "text-xs text-muted-foreground truncate min-w-0",
40
+ className
41
+ )}
42
+ title={message}
43
+ {...props}
44
+ >
45
+ {message}
46
+ </div>
47
+ );
48
+ }
49
+ );
50
+ TruncatedMessage.displayName = "TruncatedMessage";
51
+
52
+ export { TruncatedMessage };
@@ -16,3 +16,6 @@ export type { ActionBarProps } from "./ActionBar";
16
16
 
17
17
  export { HITLSection } from "./HITLSection";
18
18
  export type { HITLSectionProps } from "./HITLSection";
19
+
20
+ export { TruncatedMessage } from "./TruncatedMessage";
21
+ export type { TruncatedMessageProps } from "./TruncatedMessage";
@@ -15,7 +15,9 @@ import {
15
15
  type MemoryItem,
16
16
  type StatusItem,
17
17
  type ThinkingStep,
18
+ type PotentialResponse,
18
19
  } from "../types";
20
+ import { buildTimelineEntries } from "../../agent-timeline/utils";
19
21
 
20
22
  export interface UseAgentResponseAccumulatorOptions {
21
23
  /** WebSocket topic to filter messages (optional, for convenience) */
@@ -94,33 +96,50 @@ export function useAgentResponseAccumulator(
94
96
  id: payload.thinkingStep.id || `step-${Date.now()}`,
95
97
  label: payload.thinkingStep.label,
96
98
  content: payload.thinkingStep.content,
97
- depth: payload.thinkingStep.depth ?? 0,
99
+ depth: payload.thinkingStep.depth ?? payload.depth ?? 0,
98
100
  isCollapsed: payload.thinkingStep.isCollapsed,
101
+ timestamp: Date.now(),
102
+ agentName: payload.agentName,
103
+ parentAgent: payload.parentAgent,
99
104
  };
100
105
  const thinkingStartTime = prev.thinkingStartTime ?? Date.now();
101
- return {
106
+ const next = {
102
107
  ...prev,
103
108
  status: newStatus,
104
109
  thinkingSteps: [...(prev.thinkingSteps || []), newStep],
105
110
  thinkingStartTime,
106
111
  firstMessageTime,
107
112
  };
113
+ return { ...next, timelineEntries: buildTimelineEntries(next) };
108
114
  }
109
115
 
110
- // Plain text thinking (existing behavior)
116
+ // Plain text thinking concatenate for backward compat AND
117
+ // push a ThinkingStep so the timeline gets individual entries.
111
118
  const newThinking = payload.message || payload.content || "";
112
119
  // Add line break between thinking messages
113
120
  const separator = prev.thinking && newThinking ? "\n\n" : "";
114
121
  // Set thinkingStartTime on first thinking message
115
122
  const thinkingStartTime =
116
123
  prev.thinkingStartTime ?? (newThinking ? Date.now() : null);
117
- return {
124
+ const prevSteps = prev.thinkingSteps || [];
125
+ const plainStep: ThinkingStep = {
126
+ id: `step-${prevSteps.length}`,
127
+ label: newThinking,
128
+ content: newThinking,
129
+ depth: payload.depth ?? 0,
130
+ timestamp: Date.now(),
131
+ agentName: payload.agentName,
132
+ parentAgent: payload.parentAgent,
133
+ };
134
+ const next = {
118
135
  ...prev,
119
136
  status: newStatus,
120
137
  thinking: prev.thinking + separator + newThinking,
138
+ thinkingSteps: [...prevSteps, plainStep],
121
139
  thinkingStartTime,
122
140
  firstMessageTime,
123
141
  };
142
+ return { ...next, timelineEntries: buildTimelineEntries(next) };
124
143
  }
125
144
 
126
145
  case "tool_call": {
@@ -132,13 +151,17 @@ export function useAgentResponseAccumulator(
132
151
  name: toolName,
133
152
  arguments: payload.tool?.arguments,
134
153
  timestamp: Date.now(),
154
+ agentName: payload.agentName,
155
+ parentAgent: payload.parentAgent,
156
+ depth: payload.depth,
135
157
  };
136
- return {
158
+ const next = {
137
159
  ...prev,
138
160
  status: newStatus,
139
161
  toolCalls: [...prev.toolCalls, newToolCall],
140
162
  firstMessageTime,
141
163
  };
164
+ return { ...next, timelineEntries: buildTimelineEntries(next) };
142
165
  }
143
166
  return { ...prev, status: newStatus, firstMessageTime };
144
167
  }
@@ -152,13 +175,17 @@ export function useAgentResponseAccumulator(
152
175
  source: payload.knowledge?.source || "unknown",
153
176
  content: knowledgeContent,
154
177
  timestamp: Date.now(),
178
+ agentName: payload.agentName,
179
+ parentAgent: payload.parentAgent,
180
+ depth: payload.depth,
155
181
  };
156
- return {
182
+ const next = {
157
183
  ...prev,
158
184
  status: newStatus,
159
185
  knowledge: [...prev.knowledge, newKnowledge],
160
186
  firstMessageTime,
161
187
  };
188
+ return { ...next, timelineEntries: buildTimelineEntries(next) };
162
189
  }
163
190
  return { ...prev, status: newStatus, firstMessageTime };
164
191
  }
@@ -172,13 +199,17 @@ export function useAgentResponseAccumulator(
172
199
  type: payload.memory?.type || "unknown",
173
200
  content: memoryContent,
174
201
  timestamp: Date.now(),
202
+ agentName: payload.agentName,
203
+ parentAgent: payload.parentAgent,
204
+ depth: payload.depth,
175
205
  };
176
- return {
206
+ const next = {
177
207
  ...prev,
178
208
  status: newStatus,
179
209
  memory: [...prev.memory, newMemory],
180
210
  firstMessageTime,
181
211
  };
212
+ return { ...next, timelineEntries: buildTimelineEntries(next) };
182
213
  }
183
214
  return { ...prev, status: newStatus, firstMessageTime };
184
215
  }
@@ -200,13 +231,39 @@ export function useAgentResponseAccumulator(
200
231
  message: statusMessage,
201
232
  agent: payload.statusUpdate?.agent,
202
233
  timestamp: Date.now(),
234
+ agentName: payload.agentName,
235
+ parentAgent: payload.parentAgent,
236
+ depth: payload.depth,
203
237
  };
204
- return {
238
+ const next = {
205
239
  ...prev,
206
240
  status: newStatus,
207
241
  statusUpdates: [...prev.statusUpdates, newStatusItem],
208
242
  firstMessageTime,
209
243
  };
244
+ return { ...next, timelineEntries: buildTimelineEntries(next) };
245
+ }
246
+ return { ...prev, status: newStatus, firstMessageTime };
247
+ }
248
+
249
+ case "potential_response": {
250
+ const respContent = payload.message || payload.content || "";
251
+ if (respContent) {
252
+ const newResp: PotentialResponse = {
253
+ id: `resp-${Date.now()}`,
254
+ content: respContent,
255
+ timestamp: Date.now(),
256
+ agentName: payload.agentName,
257
+ parentAgent: payload.parentAgent,
258
+ depth: payload.depth,
259
+ };
260
+ const next = {
261
+ ...prev,
262
+ status: newStatus,
263
+ potentialResponses: [...(prev.potentialResponses || []), newResp],
264
+ firstMessageTime,
265
+ };
266
+ return { ...next, timelineEntries: buildTimelineEntries(next) };
210
267
  }
211
268
  return { ...prev, status: newStatus, firstMessageTime };
212
269
  }
@@ -16,11 +16,13 @@ export {
16
16
  ThinkingSection,
17
17
  ActionBar,
18
18
  HITLSection,
19
+ TruncatedMessage,
19
20
  type ActivityIndicatorsProps,
20
21
  type MetadataRowProps,
21
22
  type ThinkingSectionProps,
22
23
  type ActionBarProps,
23
24
  type HITLSectionProps,
25
+ type TruncatedMessageProps,
24
26
  } from "./components";
25
27
 
26
28
  // Hooks
@@ -43,6 +45,7 @@ export type {
43
45
  StatusItem,
44
46
  ThinkingStep,
45
47
  ThinkingContent,
48
+ PotentialResponse,
46
49
  AgentMessage,
47
50
  GenericWebSocketMessage,
48
51
  } from "./types";
@@ -51,3 +54,19 @@ export { initialAgentResponseState } from "./types";
51
54
 
52
55
  // Utilities
53
56
  export { formatTime, formatTotalTime } from "./utils";
57
+
58
+ // Agent Timeline (replaces ThinkingSection for rich execution visibility)
59
+ export {
60
+ AgentTimeline,
61
+ createTimelineUIState,
62
+ buildTimelineEntries,
63
+ groupIntoAgentRuns,
64
+ deduplicateEntries,
65
+ } from "../agent-timeline";
66
+ export type {
67
+ TimelineUIState,
68
+ TimelineEntry,
69
+ TimelineEntryType,
70
+ AgentRun,
71
+ DisplayEntry,
72
+ } from "../agent-timeline";
@@ -4,6 +4,8 @@
4
4
  * Type definitions for the library-ready agent response component
5
5
  */
6
6
 
7
+ import type { TimelineEntry } from "../agent-timeline/types";
8
+
7
9
  /**
8
10
  * Status of the agent response cycle
9
11
  */
@@ -22,6 +24,12 @@ export interface ToolCall {
22
24
  name: string;
23
25
  arguments?: Record<string, unknown>;
24
26
  timestamp: number;
27
+ /** Agent that made this call (multi-agent scenarios) */
28
+ agentName?: string | null;
29
+ /** Parent agent name */
30
+ parentAgent?: string | null;
31
+ /** Nesting depth in agent hierarchy */
32
+ depth?: number;
25
33
  }
26
34
 
27
35
  /**
@@ -32,6 +40,12 @@ export interface KnowledgeItem {
32
40
  source: string;
33
41
  content: string;
34
42
  timestamp: number;
43
+ /** Agent that retrieved this (multi-agent scenarios) */
44
+ agentName?: string | null;
45
+ /** Parent agent name */
46
+ parentAgent?: string | null;
47
+ /** Nesting depth in agent hierarchy */
48
+ depth?: number;
35
49
  }
36
50
 
37
51
  /**
@@ -42,6 +56,24 @@ export interface MemoryItem {
42
56
  type: string;
43
57
  content: string;
44
58
  timestamp: number;
59
+ /** Agent that accessed this (multi-agent scenarios) */
60
+ agentName?: string | null;
61
+ /** Parent agent name */
62
+ parentAgent?: string | null;
63
+ /** Nesting depth in agent hierarchy */
64
+ depth?: number;
65
+ }
66
+
67
+ /**
68
+ * Potential response (sub-agent intermediate AI response)
69
+ */
70
+ export interface PotentialResponse {
71
+ id: string;
72
+ content: string;
73
+ timestamp: number;
74
+ agentName?: string | null;
75
+ parentAgent?: string | null;
76
+ depth?: number;
45
77
  }
46
78
 
47
79
  /**
@@ -53,6 +85,12 @@ export interface StatusItem {
53
85
  timestamp: number;
54
86
  /** Optional agent name if in multi-agent scenario */
55
87
  agent?: string;
88
+ /** Agent that produced this (multi-agent scenarios) */
89
+ agentName?: string | null;
90
+ /** Parent agent name */
91
+ parentAgent?: string | null;
92
+ /** Nesting depth in agent hierarchy */
93
+ depth?: number;
56
94
  }
57
95
 
58
96
  /**
@@ -69,6 +107,12 @@ export interface ThinkingStep {
69
107
  depth: number;
70
108
  /** Whether this step should start collapsed (default: false) */
71
109
  isCollapsed?: boolean;
110
+ /** Timestamp for timeline ordering */
111
+ timestamp?: number;
112
+ /** Agent that produced this (multi-agent scenarios) */
113
+ agentName?: string | null;
114
+ /** Parent agent name */
115
+ parentAgent?: string | null;
72
116
  }
73
117
 
74
118
  /**
@@ -96,8 +140,14 @@ export interface AgentResponseState {
96
140
  memory: MemoryItem[];
97
141
  /** Status updates from the agent */
98
142
  statusUpdates: StatusItem[];
143
+ /** Potential responses (sub-agent intermediate AI responses) */
144
+ potentialResponses?: PotentialResponse[];
145
+ /** Custom timeline entries (consumer-provided) */
146
+ customTimelineEntries?: TimelineEntry[];
99
147
  /** Final response text */
100
148
  response: string;
149
+ /** Timeline entries derived from all accumulator arrays (for AgentTimeline) */
150
+ timelineEntries?: TimelineEntry[];
101
151
  /** Timestamp when first thinking message was received (for timer) */
102
152
  thinkingStartTime: number | null;
103
153
  /** Timestamp when response was completed (for final timer display) */
@@ -110,13 +160,21 @@ export interface AgentResponseState {
110
160
  * WebSocket message payload for agent responses
111
161
  */
112
162
  export interface AgentMessage {
113
- type: "status" | "thinking" | "tool_call" | "knowledge" | "memory" | "response" | "status_update";
163
+ type: "status" | "thinking" | "tool_call" | "knowledge" | "memory" | "response" | "status_update" | "potential_response";
114
164
  /** Message content - for simple string payloads */
115
165
  message?: string;
116
166
  /** Alternative content field */
117
167
  content?: string;
118
168
  /** For status messages */
119
169
  status?: string;
170
+ /** Agent name (multi-agent scenarios) */
171
+ agentName?: string | null;
172
+ /** Parent agent name (multi-agent scenarios) */
173
+ parentAgent?: string | null;
174
+ /** Agent nesting depth (0 = root) */
175
+ depth?: number;
176
+ /** Title/label for timeline display */
177
+ title?: string | null;
120
178
  /** For tool_call messages */
121
179
  tool?: {
122
180
  id: string;
@@ -170,6 +228,8 @@ export const initialAgentResponseState: AgentResponseState = {
170
228
  knowledge: [],
171
229
  memory: [],
172
230
  statusUpdates: [],
231
+ potentialResponses: [],
232
+ customTimelineEntries: [],
173
233
  response: "",
174
234
  thinkingStartTime: null,
175
235
  responseCompleteTime: null,