@optilogic/chat 1.3.4 → 1.3.5

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@optilogic/chat",
3
- "version": "1.3.4",
3
+ "version": "1.3.5",
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/editor": "1.3.4",
28
- "@optilogic/core": "1.3.4"
27
+ "@optilogic/core": "1.3.5",
28
+ "@optilogic/editor": "1.3.5"
29
29
  },
30
30
  "peerDependencies": {
31
31
  "react": "^18.0.0 || ^19.0.0",
@@ -22,6 +22,42 @@ export interface AgentResponseClassNames {
22
22
  response?: string;
23
23
  }
24
24
 
25
+ /**
26
+ * Tour anchors (`data-tour` attribute values) to attach to specific elements
27
+ * inside an AgentResponse so a tour or test harness can target them.
28
+ *
29
+ * Each value, when provided, is rendered as `data-tour={value}` on the
30
+ * corresponding element. Omit a field to skip stamping the attribute on that
31
+ * element. Pair with the matching CSS selector form:
32
+ *
33
+ * <AgentResponse anchors={{ copyAction: "chat-action-copy" }} />
34
+ * // selector: '[data-tour="chat-action-copy"]'
35
+ *
36
+ * This is the standard convention in the @optilogic component library for
37
+ * threading tour IDs into elements that are rendered by internal
38
+ * sub-components and not otherwise reachable from the caller.
39
+ */
40
+ export interface AgentResponseAnchors {
41
+ /** Status updates popover trigger in the metadata row (live status indicator). */
42
+ statusUpdate?: string;
43
+ /** Thinking expand/collapse toggle button in the metadata row. */
44
+ thinkingToggle?: string;
45
+ /** Thinking section content panel (when expanded). */
46
+ thinkingSection?: string;
47
+ /** Tool calls popover trigger in the metadata row. */
48
+ toolCalls?: string;
49
+ /** Knowledge popover trigger in the metadata row. */
50
+ knowledge?: string;
51
+ /** Memory popover trigger in the metadata row. */
52
+ memory?: string;
53
+ /** Copy button in the action bar. */
54
+ copyAction?: string;
55
+ /** Thumbs up button in the action bar. */
56
+ thumbsUp?: string;
57
+ /** Thumbs down button in the action bar. */
58
+ thumbsDown?: string;
59
+ }
60
+
25
61
  export interface AgentResponseProps extends React.HTMLAttributes<HTMLDivElement> {
26
62
  /** The response state to render */
27
63
  state: AgentResponseState;
@@ -121,6 +157,22 @@ export interface AgentResponseProps extends React.HTMLAttributes<HTMLDivElement>
121
157
  * />
122
158
  */
123
159
  classNames?: AgentResponseClassNames;
160
+
161
+ /**
162
+ * Tour anchors threaded into internal sub-components. See
163
+ * {@link AgentResponseAnchors} for the available element keys.
164
+ *
165
+ * @example
166
+ * <AgentResponse
167
+ * state={state}
168
+ * anchors={{
169
+ * copyAction: "chat-action-copy",
170
+ * thumbsUp: "chat-action-thumbs-up",
171
+ * thumbsDown: "chat-action-thumbs-down",
172
+ * }}
173
+ * />
174
+ */
175
+ anchors?: AgentResponseAnchors;
124
176
  }
125
177
 
126
178
  /**
@@ -175,6 +227,7 @@ const AgentResponse = React.forwardRef<HTMLDivElement, AgentResponseProps>(
175
227
  renderThinkingMarkdown,
176
228
  timelineMaxHeight,
177
229
  classNames,
230
+ anchors,
178
231
  className,
179
232
  ...props
180
233
  },
@@ -280,12 +333,17 @@ const AgentResponse = React.forwardRef<HTMLDivElement, AgentResponseProps>(
280
333
  statusContent={statusContent}
281
334
  status={state.status}
282
335
  elapsedTime={elapsedTime}
336
+ thinkingToggleAnchor={anchors?.thinkingToggle}
337
+ statusUpdateAnchor={anchors?.statusUpdate}
338
+ toolCallsAnchor={anchors?.toolCalls}
339
+ knowledgeAnchor={anchors?.knowledge}
340
+ memoryAnchor={anchors?.memory}
283
341
  />
284
342
 
285
343
  {/* Thinking Content - AgentTimeline when timeline entries exist, ThinkingSection otherwise */}
286
344
  {hasTimelineEntries ? (
287
345
  thinkingExpanded && (
288
- <div className="pb-3 border-t border-border">
346
+ <div className="pb-3 border-t border-border" data-tour={anchors?.thinkingSection}>
289
347
  <AgentTimeline
290
348
  entries={state.timelineEntries!}
291
349
  renderMarkdown={renderThinkingMarkdown}
@@ -296,6 +354,7 @@ const AgentResponse = React.forwardRef<HTMLDivElement, AgentResponseProps>(
296
354
  )
297
355
  ) : (
298
356
  <ThinkingSection
357
+ data-tour={anchors?.thinkingSection}
299
358
  content={
300
359
  state.thinkingSteps && state.thinkingSteps.length > 0
301
360
  ? state.thinkingSteps
@@ -343,6 +402,9 @@ const AgentResponse = React.forwardRef<HTMLDivElement, AgentResponseProps>(
343
402
  feedback={feedback}
344
403
  onFeedbackChange={onFeedbackChange}
345
404
  onResponseCopy={onResponseCopy}
405
+ copyAnchor={anchors?.copyAction}
406
+ thumbsUpAnchor={anchors?.thumbsUp}
407
+ thumbsDownAnchor={anchors?.thumbsDown}
346
408
  />
347
409
  )}
348
410
  </div>
@@ -24,6 +24,15 @@ export interface ActionBarProps extends React.HTMLAttributes<HTMLDivElement> {
24
24
  onFeedbackChange?: (feedback: FeedbackValue) => void;
25
25
  /** Callback when response is copied */
26
26
  onResponseCopy?: (response: string) => void;
27
+ /**
28
+ * Tour anchor (rendered as `data-tour`) on the copy button.
29
+ * Use with the `data-tour` convention to target this button from a tour step.
30
+ */
31
+ copyAnchor?: string;
32
+ /** Tour anchor (`data-tour`) on the thumbs up button. */
33
+ thumbsUpAnchor?: string;
34
+ /** Tour anchor (`data-tour`) on the thumbs down button. */
35
+ thumbsDownAnchor?: string;
27
36
  }
28
37
 
29
38
  /**
@@ -51,6 +60,9 @@ const ActionBar = React.forwardRef<HTMLDivElement, ActionBarProps>(
51
60
  feedback,
52
61
  onFeedbackChange,
53
62
  onResponseCopy,
63
+ copyAnchor,
64
+ thumbsUpAnchor,
65
+ thumbsDownAnchor,
54
66
  className,
55
67
  ...props
56
68
  },
@@ -97,6 +109,7 @@ const ActionBar = React.forwardRef<HTMLDivElement, ActionBarProps>(
97
109
  <div className="flex items-center gap-1">
98
110
  {/* Copy button */}
99
111
  <button
112
+ data-tour={copyAnchor}
100
113
  onClick={handleCopy}
101
114
  className="p-1.5 rounded hover:bg-muted transition-colors text-muted-foreground hover:text-foreground"
102
115
  title={copied ? "Copied!" : "Copy response"}
@@ -110,6 +123,7 @@ const ActionBar = React.forwardRef<HTMLDivElement, ActionBarProps>(
110
123
 
111
124
  {/* Thumbs up */}
112
125
  <button
126
+ data-tour={thumbsUpAnchor}
113
127
  onClick={handleThumbsUp}
114
128
  className={cn(
115
129
  "p-1.5 rounded hover:bg-muted transition-colors",
@@ -124,6 +138,7 @@ const ActionBar = React.forwardRef<HTMLDivElement, ActionBarProps>(
124
138
 
125
139
  {/* Thumbs down */}
126
140
  <button
141
+ data-tour={thumbsDownAnchor}
127
142
  onClick={handleThumbsDown}
128
143
  className={cn(
129
144
  "p-1.5 rounded hover:bg-muted transition-colors",
@@ -18,6 +18,14 @@ export interface ActivityIndicatorsProps extends React.HTMLAttributes<HTMLDivEle
18
18
  memory: MemoryItem[];
19
19
  /** Status updates to display */
20
20
  statusUpdates?: StatusItem[];
21
+ /** Tour anchor (`data-tour`) on the status updates popover trigger. */
22
+ statusUpdateAnchor?: string;
23
+ /** Tour anchor (`data-tour`) on the tool calls popover trigger. */
24
+ toolCallsAnchor?: string;
25
+ /** Tour anchor (`data-tour`) on the knowledge popover trigger. */
26
+ knowledgeAnchor?: string;
27
+ /** Tour anchor (`data-tour`) on the memory popover trigger. */
28
+ memoryAnchor?: string;
21
29
  }
22
30
 
23
31
  /**
@@ -34,7 +42,21 @@ export interface ActivityIndicatorsProps extends React.HTMLAttributes<HTMLDivEle
34
42
  * />
35
43
  */
36
44
  const ActivityIndicators = React.forwardRef<HTMLDivElement, ActivityIndicatorsProps>(
37
- ({ toolCalls, knowledge, memory, statusUpdates = [], className, ...props }, ref) => {
45
+ (
46
+ {
47
+ toolCalls,
48
+ knowledge,
49
+ memory,
50
+ statusUpdates = [],
51
+ statusUpdateAnchor,
52
+ toolCallsAnchor,
53
+ knowledgeAnchor,
54
+ memoryAnchor,
55
+ className,
56
+ ...props
57
+ },
58
+ ref,
59
+ ) => {
38
60
  const hasAnyActivity =
39
61
  toolCalls.length > 0 || knowledge.length > 0 || memory.length > 0 || statusUpdates.length > 0;
40
62
 
@@ -47,6 +69,7 @@ const ActivityIndicators = React.forwardRef<HTMLDivElement, ActivityIndicatorsPr
47
69
  <Popover>
48
70
  <PopoverTrigger asChild>
49
71
  <button
72
+ data-tour={statusUpdateAnchor}
50
73
  className="flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors"
51
74
  onClick={(e) => e.stopPropagation()}
52
75
  >
@@ -77,6 +100,7 @@ const ActivityIndicators = React.forwardRef<HTMLDivElement, ActivityIndicatorsPr
77
100
  <Popover>
78
101
  <PopoverTrigger asChild>
79
102
  <button
103
+ data-tour={toolCallsAnchor}
80
104
  className="flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors"
81
105
  onClick={(e) => e.stopPropagation()}
82
106
  >
@@ -109,6 +133,7 @@ const ActivityIndicators = React.forwardRef<HTMLDivElement, ActivityIndicatorsPr
109
133
  <Popover>
110
134
  <PopoverTrigger asChild>
111
135
  <button
136
+ data-tour={knowledgeAnchor}
112
137
  className="flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors"
113
138
  onClick={(e) => e.stopPropagation()}
114
139
  >
@@ -139,6 +164,7 @@ const ActivityIndicators = React.forwardRef<HTMLDivElement, ActivityIndicatorsPr
139
164
  <Popover>
140
165
  <PopoverTrigger asChild>
141
166
  <button
167
+ data-tour={memoryAnchor}
142
168
  className="flex items-center gap-1 text-muted-foreground hover:text-foreground transition-colors"
143
169
  onClick={(e) => e.stopPropagation()}
144
170
  >
@@ -32,6 +32,16 @@ export interface MetadataRowProps extends React.HTMLAttributes<HTMLDivElement> {
32
32
  status: AgentResponseStatus;
33
33
  /** Elapsed time in seconds */
34
34
  elapsedTime: number;
35
+ /** Tour anchor (`data-tour`) on the thinking expand/collapse toggle button. */
36
+ thinkingToggleAnchor?: string;
37
+ /** Tour anchor forwarded to the status updates popover trigger inside ActivityIndicators. */
38
+ statusUpdateAnchor?: string;
39
+ /** Tour anchor forwarded to the tool calls popover trigger inside ActivityIndicators. */
40
+ toolCallsAnchor?: string;
41
+ /** Tour anchor forwarded to the knowledge popover trigger inside ActivityIndicators. */
42
+ knowledgeAnchor?: string;
43
+ /** Tour anchor forwarded to the memory popover trigger inside ActivityIndicators. */
44
+ memoryAnchor?: string;
35
45
  }
36
46
 
37
47
  /**
@@ -65,6 +75,11 @@ const MetadataRow = React.forwardRef<HTMLDivElement, MetadataRowProps>(
65
75
  statusContent,
66
76
  status,
67
77
  elapsedTime,
78
+ thinkingToggleAnchor,
79
+ statusUpdateAnchor,
80
+ toolCallsAnchor,
81
+ knowledgeAnchor,
82
+ memoryAnchor,
68
83
  className,
69
84
  ...props
70
85
  },
@@ -127,6 +142,7 @@ const MetadataRow = React.forwardRef<HTMLDivElement, MetadataRowProps>(
127
142
  {/* Left content - clickable when there's thinking */}
128
143
  {hasThinking ? (
129
144
  <button
145
+ data-tour={thinkingToggleAnchor}
130
146
  onClick={onToggle}
131
147
  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"
132
148
  >
@@ -150,6 +166,10 @@ const MetadataRow = React.forwardRef<HTMLDivElement, MetadataRowProps>(
150
166
  knowledge={knowledge}
151
167
  memory={memory}
152
168
  statusUpdates={statusUpdates}
169
+ statusUpdateAnchor={statusUpdateAnchor}
170
+ toolCallsAnchor={toolCallsAnchor}
171
+ knowledgeAnchor={knowledgeAnchor}
172
+ memoryAnchor={memoryAnchor}
153
173
  />
154
174
  </div>
155
175
  );
@@ -7,7 +7,11 @@
7
7
 
8
8
  // Main component
9
9
  export { AgentResponse } from "./AgentResponse";
10
- export type { AgentResponseProps, AgentResponseClassNames } from "./AgentResponse";
10
+ export type {
11
+ AgentResponseProps,
12
+ AgentResponseClassNames,
13
+ AgentResponseAnchors,
14
+ } from "./AgentResponse";
11
15
 
12
16
  // Sub-components (for advanced customization)
13
17
  export {
@@ -155,6 +155,7 @@ export const UserPromptInput = React.forwardRef<
155
155
  enableTags = false,
156
156
  onTagCreate,
157
157
  onTagDelete,
158
+ anchors,
158
159
  className,
159
160
  ...props
160
161
  },
@@ -298,6 +299,7 @@ export const UserPromptInput = React.forwardRef<
298
299
  {isSubmitting && onStop ? (
299
300
  <Tooltip content={stopTooltip} disabled={!stopTooltip}>
300
301
  <IconButton
302
+ data-tour={anchors?.stopButton}
301
303
  icon={<Square />}
302
304
  variant="filled"
303
305
  size="sm"
@@ -308,6 +310,7 @@ export const UserPromptInput = React.forwardRef<
308
310
  </Tooltip>
309
311
  ) : (
310
312
  <IconButton
313
+ data-tour={anchors?.sendButton}
311
314
  icon={
312
315
  isSubmitting ? (
313
316
  <Loader2 className="animate-spin" />
@@ -42,6 +42,19 @@ export interface UserPromptInputProps
42
42
  onTagCreate?: (tag: string) => void;
43
43
  /** Callback when a tag is deleted */
44
44
  onTagDelete?: (tag: string) => void;
45
+ /** Tour anchors threaded onto internal sub-elements. */
46
+ anchors?: UserPromptInputAnchors;
47
+ }
48
+
49
+ /**
50
+ * Tour anchors (`data-tour` attribute values) for elements inside the
51
+ * UserPromptInput that the caller cannot otherwise reach.
52
+ */
53
+ export interface UserPromptInputAnchors {
54
+ /** Send button (rendered when not submitting). */
55
+ sendButton?: string;
56
+ /** Stop button (rendered while submitting if `onStop` is provided). */
57
+ stopButton?: string;
45
58
  }
46
59
 
47
60
  export interface UserPromptInputRef {
package/src/index.ts CHANGED
@@ -9,6 +9,8 @@ export {
9
9
  // Main component
10
10
  AgentResponse,
11
11
  type AgentResponseProps,
12
+ type AgentResponseClassNames,
13
+ type AgentResponseAnchors,
12
14
 
13
15
  // Sub-components (for advanced customization)
14
16
  ActivityIndicators,