@webless/agent 0.9.1 → 0.9.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/react.d.cts CHANGED
@@ -153,9 +153,11 @@ type AgentTranscriptProps = {
153
153
  agentLabel?: string;
154
154
  visitorLabel?: string;
155
155
  label?: string;
156
+ /** Hide the opening marker when the host already shows the conversation date. */
157
+ showInitialTimestamp?: boolean;
156
158
  formatTimestamp?: (createdAt: number) => string;
157
159
  };
158
160
  /** Renders a stored snapshot; never creates a session or exposes chat actions. */
159
- declare function AgentTranscript({ messages, activities, theme, colorScheme, agentLabel, visitorLabel, label, formatTimestamp, }: AgentTranscriptProps): react.JSX.Element;
161
+ declare function AgentTranscript({ messages, activities, theme, colorScheme, agentLabel, visitorLabel, label, formatTimestamp, showInitialTimestamp, }: AgentTranscriptProps): react.JSX.Element;
160
162
 
161
163
  export { AGENT_ANSWER_FEEDBACK_EVENT_TYPE, AgentColorScheme, AgentInputResponse, AgentMessageFeedback, AgentPlacementConfig, AgentRail, AgentRailPhase, type AgentRailProps, AgentRailState, AgentRailTheme, AgentToolUiSurface, AgentTranscript, type AgentTranscriptActivity, type AgentTranscriptProps, AgentWidget, type AgentWidgetProps, ConversationMessage, FollowUpSuggestion, MessageActions, ResolvedVisitorToolResultPresentation, ToolStep, type UseAgentChatOptions, VisitorToolResultRegistry, buildAgentAnswerFeedbackEvent, createIdleSuggestions, findPrecedingVisitorText, hasVisitorMessages, isAgentBusy, sendAgentAnswerFeedback, useAgentChat };
package/dist/react.d.ts CHANGED
@@ -153,9 +153,11 @@ type AgentTranscriptProps = {
153
153
  agentLabel?: string;
154
154
  visitorLabel?: string;
155
155
  label?: string;
156
+ /** Hide the opening marker when the host already shows the conversation date. */
157
+ showInitialTimestamp?: boolean;
156
158
  formatTimestamp?: (createdAt: number) => string;
157
159
  };
158
160
  /** Renders a stored snapshot; never creates a session or exposes chat actions. */
159
- declare function AgentTranscript({ messages, activities, theme, colorScheme, agentLabel, visitorLabel, label, formatTimestamp, }: AgentTranscriptProps): react.JSX.Element;
161
+ declare function AgentTranscript({ messages, activities, theme, colorScheme, agentLabel, visitorLabel, label, formatTimestamp, showInitialTimestamp, }: AgentTranscriptProps): react.JSX.Element;
160
162
 
161
163
  export { AGENT_ANSWER_FEEDBACK_EVENT_TYPE, AgentColorScheme, AgentInputResponse, AgentMessageFeedback, AgentPlacementConfig, AgentRail, AgentRailPhase, type AgentRailProps, AgentRailState, AgentRailTheme, AgentToolUiSurface, AgentTranscript, type AgentTranscriptActivity, type AgentTranscriptProps, AgentWidget, type AgentWidgetProps, ConversationMessage, FollowUpSuggestion, MessageActions, ResolvedVisitorToolResultPresentation, ToolStep, type UseAgentChatOptions, VisitorToolResultRegistry, buildAgentAnswerFeedbackEvent, createIdleSuggestions, findPrecedingVisitorText, hasVisitorMessages, isAgentBusy, sendAgentAnswerFeedback, useAgentChat };
package/dist/react.js CHANGED
@@ -29,6 +29,9 @@ import {
29
29
  useAgentColorScheme
30
30
  } from "./chunk-3E632FNE.js";
31
31
 
32
+ // src/react/components/AgentTranscript/AgentTranscript.tsx
33
+ import { Fragment as Fragment2 } from "react";
34
+
32
35
  // src/react/components/AgentTranscript/TranscriptActivity.tsx
33
36
  import { Fragment, jsx, jsxs } from "react/jsx-runtime";
34
37
  var statusLabels = {
@@ -56,16 +59,12 @@ function RecordedResult({
56
59
  return /* @__PURE__ */ jsx(VisitorToolResultView, { disabled: true, result });
57
60
  }
58
61
  function TranscriptActivity({
59
- activity,
60
- formatTimestamp
62
+ activity
61
63
  }) {
62
- const date = new Date(activity.createdAt);
63
- const validTimestamp = Number.isFinite(date.getTime());
64
64
  const result = activity.result?.kind === "hidden" ? void 0 : activity.result;
65
65
  const heading = /* @__PURE__ */ jsxs(Fragment, { children: [
66
66
  /* @__PURE__ */ jsx("span", { children: activity.category === "specialist" ? `Specialist \xB7 ${activity.label}` : activity.label }),
67
- activity.status !== "completed" ? /* @__PURE__ */ jsx("span", { className: "agent-transcript__activity-status", children: statusLabels[activity.status] }) : null,
68
- validTimestamp ? /* @__PURE__ */ jsx("time", { dateTime: date.toISOString(), children: formatTimestamp(activity.createdAt) }) : null
67
+ activity.status !== "completed" ? /* @__PURE__ */ jsx("span", { className: "agent-transcript__activity-status", children: statusLabels[activity.status] }) : null
69
68
  ] });
70
69
  return /* @__PURE__ */ jsx("li", { className: "agent-transcript__activity", "data-status": activity.status, children: result ? /* @__PURE__ */ jsxs("details", { children: [
71
70
  /* @__PURE__ */ jsx("summary", { className: "agent-transcript__activity-heading", children: heading }),
@@ -127,7 +126,8 @@ function AgentTranscript({
127
126
  agentLabel = "Agent",
128
127
  visitorLabel = "Visitor",
129
128
  label = "Conversation transcript",
130
- formatTimestamp = defaultTimestamp
129
+ formatTimestamp = defaultTimestamp,
130
+ showInitialTimestamp = true
131
131
  }) {
132
132
  const scheme = useAgentColorScheme(colorScheme);
133
133
  const entries = [
@@ -145,41 +145,31 @@ function AgentTranscript({
145
145
  "data-color-scheme": scheme,
146
146
  "aria-label": label,
147
147
  style: agentThemeStyle(theme, scheme),
148
- children: entries.map((message) => {
149
- if (message.kind === "activity")
150
- return /* @__PURE__ */ jsx2(
151
- TranscriptActivity,
152
- {
153
- activity: message,
154
- formatTimestamp
155
- },
156
- message.id
157
- );
158
- if (message.role === "visitor" && !message.text.trim()) return null;
159
- const date = new Date(message.createdAt);
148
+ children: entries.map((entry, index) => {
149
+ const date = new Date(entry.createdAt);
150
+ const previous = entries[index - 1];
160
151
  const validTimestamp = Number.isFinite(date.getTime());
161
- return /* @__PURE__ */ jsxs2(
162
- "li",
163
- {
164
- className: `agent-transcript__message agent-transcript__message--${message.role}`,
165
- children: [
166
- /* @__PURE__ */ jsxs2("div", { className: "agent-transcript__meta", children: [
167
- /* @__PURE__ */ jsx2("span", { children: message.role === "visitor" ? visitorLabel : agentLabel }),
168
- validTimestamp ? /* @__PURE__ */ jsx2("time", { dateTime: date.toISOString(), children: formatTimestamp(message.createdAt) }) : null
169
- ] }),
170
- message.role === "agent" ? message.toolResults?.map((result) => /* @__PURE__ */ jsx2(VisitorToolResultView, { result }, result.id)) : null,
171
- /* @__PURE__ */ jsx2(
172
- MessageBubble,
173
- {
174
- message: message.role === "agent" ? { ...message, streaming: false } : message,
175
- bookingReadOnly: true,
176
- bookingDisabled: true
177
- }
178
- )
179
- ]
180
- },
181
- message.id
182
- );
152
+ const showTimestamp = validTimestamp && (previous ? entry.createdAt - previous.createdAt >= 5 * 60 * 1e3 || date.toISOString().slice(0, 10) !== new Date(previous.createdAt).toJSON()?.slice(0, 10) : showInitialTimestamp);
153
+ return /* @__PURE__ */ jsxs2(Fragment2, { children: [
154
+ showTimestamp ? /* @__PURE__ */ jsx2("li", { className: "agent-transcript__time-marker", children: /* @__PURE__ */ jsx2("time", { dateTime: date.toISOString(), children: formatTimestamp(entry.createdAt) }) }) : null,
155
+ entry.kind === "activity" ? /* @__PURE__ */ jsx2(TranscriptActivity, { activity: entry }) : /* @__PURE__ */ jsxs2(
156
+ "li",
157
+ {
158
+ className: `agent-transcript__message agent-transcript__message--${entry.role}`,
159
+ children: [
160
+ /* @__PURE__ */ jsx2("div", { className: "agent-transcript__meta", children: /* @__PURE__ */ jsx2("span", { children: entry.role === "visitor" ? visitorLabel : agentLabel }) }),
161
+ /* @__PURE__ */ jsx2(
162
+ MessageBubble,
163
+ {
164
+ message: entry.role === "agent" ? { ...entry, streaming: false } : entry,
165
+ bookingReadOnly: true,
166
+ bookingDisabled: true
167
+ }
168
+ )
169
+ ]
170
+ }
171
+ )
172
+ ] }, `${entry.kind}:${entry.id}`);
183
173
  })
184
174
  }
185
175
  );
package/dist/react.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/react/components/AgentTranscript/TranscriptActivity.tsx","../src/react/components/AgentTranscript/group-activities.ts","../src/react/components/AgentTranscript/AgentTranscript.tsx"],"sourcesContent":["import type { ResolvedVisitorToolResultPresentation } from \"../../lib/tool-result\";\nimport { VisitorToolResultView } from \"../VisitorToolResultView/VisitorToolResultView\";\nimport { SearchReferences } from \"../SearchReferences/SearchReferences\";\nimport { BookingCard } from \"../BookingCard/BookingCard\";\n\nexport type AgentTranscriptActivity = {\n id: string;\n createdAt: number;\n callId: string;\n category: \"tool\" | \"specialist\";\n label: string;\n status: \"started\" | \"completed\" | \"failed\" | \"rejected\";\n result?: ResolvedVisitorToolResultPresentation;\n};\n\nconst statusLabels = {\n started: \"No result recorded\",\n completed: \"\",\n failed: \"Failed\",\n rejected: \"Rejected\",\n};\n\nfunction RecordedResult({\n result,\n}: {\n result: ResolvedVisitorToolResultPresentation;\n}) {\n if (result.kind === \"search\") return <SearchReferences results={[result]} />;\n if (result.kind === \"booking\") {\n const card = result.card;\n if (card.type === \"booking_offer\")\n return <BookingCard readOnly offer={card} />;\n if (card.type === \"booking_confirmed\")\n return (\n <p>Booking confirmed{card.startTime ? ` · ${card.startTime}` : \"\"}</p>\n );\n if (card.type === \"booking_canceled\") return <p>Booking canceled</p>;\n return <p>Information requested</p>;\n }\n return <VisitorToolResultView disabled result={result} />;\n}\n\nexport function TranscriptActivity({\n activity,\n formatTimestamp,\n}: {\n activity: AgentTranscriptActivity;\n formatTimestamp: (createdAt: number) => string;\n}) {\n const date = new Date(activity.createdAt);\n const validTimestamp = Number.isFinite(date.getTime());\n const result =\n activity.result?.kind === \"hidden\" ? undefined : activity.result;\n const heading = (\n <>\n <span>\n {activity.category === \"specialist\"\n ? `Specialist · ${activity.label}`\n : activity.label}\n </span>\n {activity.status !== \"completed\" ? (\n <span className=\"agent-transcript__activity-status\">\n {statusLabels[activity.status]}\n </span>\n ) : null}\n {validTimestamp ? (\n <time dateTime={date.toISOString()}>\n {formatTimestamp(activity.createdAt)}\n </time>\n ) : null}\n </>\n );\n return (\n <li className=\"agent-transcript__activity\" data-status={activity.status}>\n {result ? (\n <details>\n <summary className=\"agent-transcript__activity-heading\">\n {heading}\n </summary>\n <div className=\"agent-transcript__activity-result\">\n <RecordedResult result={result} />\n </div>\n </details>\n ) : (\n <div className=\"agent-transcript__activity-heading\">{heading}</div>\n )}\n </li>\n );\n}\n","import type { AgentTranscriptActivity } from \"./TranscriptActivity\";\n\n/** A paginated snapshot may deliver a call and its result on different pages. */\nexport function groupTranscriptActivities(\n activities: readonly AgentTranscriptActivity[],\n) {\n const calls = new Map<\n string,\n {\n latest: AgentTranscriptActivity;\n id: string;\n startedAt: number;\n label: string;\n }\n >();\n for (const activity of activities) {\n const key = `${activity.category}:${activity.callId}`;\n const previous = calls.get(key);\n if (!previous) {\n calls.set(key, {\n latest: activity,\n id: activity.id,\n startedAt: activity.createdAt,\n label: activity.label,\n });\n continue;\n }\n const previousHasResult = previous.latest.status !== \"started\";\n const nextHasResult = activity.status !== \"started\";\n const useNext =\n (nextHasResult && !previousHasResult) ||\n (nextHasResult === previousHasResult &&\n activity.createdAt >= previous.latest.createdAt);\n const latest = useNext ? activity : previous.latest;\n calls.set(key, {\n latest,\n id: previous.id,\n startedAt: Math.min(previous.startedAt, activity.createdAt),\n label:\n activity.createdAt < previous.startedAt\n ? activity.label\n : previous.label,\n });\n }\n return [...calls.values()].map(({ latest, id, startedAt, label }) => ({\n ...latest,\n id,\n label,\n createdAt: startedAt,\n }));\n}\n","import type {\n ConversationMessage,\n AgentColorScheme,\n AgentRailTheme,\n} from \"../../types/conversation\";\nimport { useAgentColorScheme } from \"../../hooks/useAgentColorScheme\";\nimport { agentThemeStyle } from \"../../lib/agent-theme\";\nimport { VisitorToolResultView } from \"../VisitorToolResultView/VisitorToolResultView\";\nimport { MessageBubble } from \"../MessageBubble/MessageBubble\";\nimport {\n TranscriptActivity,\n type AgentTranscriptActivity,\n} from \"./TranscriptActivity\";\nimport { groupTranscriptActivities } from \"./group-activities\";\nimport \"./AgentTranscript.css\";\n\nexport type { AgentTranscriptActivity } from \"./TranscriptActivity\";\n\nexport type AgentTranscriptProps = {\n messages: readonly ConversationMessage[];\n activities?: readonly AgentTranscriptActivity[];\n theme?: Partial<AgentRailTheme>;\n colorScheme?: AgentColorScheme;\n agentLabel?: string;\n visitorLabel?: string;\n label?: string;\n formatTimestamp?: (createdAt: number) => string;\n};\n\nconst timestampFormat = new Intl.DateTimeFormat(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n timeZone: \"UTC\",\n});\nfunction defaultTimestamp(createdAt: number) {\n return `${timestampFormat.format(createdAt)} UTC`;\n}\n\n/** Renders a stored snapshot; never creates a session or exposes chat actions. */\nexport function AgentTranscript({\n messages,\n activities = [],\n theme,\n colorScheme,\n agentLabel = \"Agent\",\n visitorLabel = \"Visitor\",\n label = \"Conversation transcript\",\n formatTimestamp = defaultTimestamp,\n}: AgentTranscriptProps) {\n const scheme = useAgentColorScheme(colorScheme);\n const entries = [\n ...messages.map((message) => ({ kind: \"message\" as const, ...message })),\n ...groupTranscriptActivities(activities).map((activity) => ({\n kind: \"activity\" as const,\n ...activity,\n })),\n ].sort((left, right) => left.createdAt - right.createdAt);\n return (\n <ol\n className=\"webless-agent-root agent-transcript not-typeset\"\n data-not-typeset=\"\"\n data-color-scheme={scheme}\n aria-label={label}\n style={agentThemeStyle(theme, scheme)}\n >\n {entries.map((message) => {\n if (message.kind === \"activity\")\n return (\n <TranscriptActivity\n key={message.id}\n activity={message}\n formatTimestamp={formatTimestamp}\n />\n );\n if (message.role === \"visitor\" && !message.text.trim()) return null;\n const date = new Date(message.createdAt);\n const validTimestamp = Number.isFinite(date.getTime());\n return (\n <li\n key={message.id}\n className={`agent-transcript__message agent-transcript__message--${message.role}`}\n >\n <div className=\"agent-transcript__meta\">\n <span>\n {message.role === \"visitor\" ? visitorLabel : agentLabel}\n </span>\n {validTimestamp ? (\n <time dateTime={date.toISOString()}>\n {formatTimestamp(message.createdAt)}\n </time>\n ) : null}\n </div>\n {message.role === \"agent\" ? message.toolResults?.map((result) => (\n <VisitorToolResultView key={result.id} result={result} />\n )) : null}\n <MessageBubble\n message={\n message.role === \"agent\"\n ? { ...message, streaming: false }\n : message\n }\n bookingReadOnly\n bookingDisabled\n />\n </li>\n );\n })}\n </ol>\n );\n}\n"],"mappings":"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","names":["jsx","jsxs"]}
1
+ {"version":3,"sources":["../src/react/components/AgentTranscript/AgentTranscript.tsx","../src/react/components/AgentTranscript/TranscriptActivity.tsx","../src/react/components/AgentTranscript/group-activities.ts"],"sourcesContent":["import { Fragment } from \"react\";\nimport type {\n ConversationMessage,\n AgentColorScheme,\n AgentRailTheme,\n} from \"../../types/conversation\";\nimport { useAgentColorScheme } from \"../../hooks/useAgentColorScheme\";\nimport { agentThemeStyle } from \"../../lib/agent-theme\";\nimport { VisitorToolResultView } from \"../VisitorToolResultView/VisitorToolResultView\";\nimport { MessageBubble } from \"../MessageBubble/MessageBubble\";\nimport {\n TranscriptActivity,\n type AgentTranscriptActivity,\n} from \"./TranscriptActivity\";\nimport { groupTranscriptActivities } from \"./group-activities\";\nimport \"./AgentTranscript.css\";\n\nexport type { AgentTranscriptActivity } from \"./TranscriptActivity\";\n\nexport type AgentTranscriptProps = {\n messages: readonly ConversationMessage[];\n activities?: readonly AgentTranscriptActivity[];\n theme?: Partial<AgentRailTheme>;\n colorScheme?: AgentColorScheme;\n agentLabel?: string;\n visitorLabel?: string;\n label?: string;\n /** Hide the opening marker when the host already shows the conversation date. */\n showInitialTimestamp?: boolean;\n formatTimestamp?: (createdAt: number) => string;\n};\n\nconst timestampFormat = new Intl.DateTimeFormat(\"en-US\", {\n month: \"short\",\n day: \"numeric\",\n hour: \"numeric\",\n minute: \"2-digit\",\n timeZone: \"UTC\",\n});\nfunction defaultTimestamp(createdAt: number) {\n return `${timestampFormat.format(createdAt)} UTC`;\n}\n\n/** Renders a stored snapshot; never creates a session or exposes chat actions. */\nexport function AgentTranscript({\n messages,\n activities = [],\n theme,\n colorScheme,\n agentLabel = \"Agent\",\n visitorLabel = \"Visitor\",\n label = \"Conversation transcript\",\n formatTimestamp = defaultTimestamp,\n showInitialTimestamp = true,\n}: AgentTranscriptProps) {\n const scheme = useAgentColorScheme(colorScheme);\n const entries = [\n ...messages.map((message) => ({ kind: \"message\" as const, ...message })),\n ...groupTranscriptActivities(activities).map((activity) => ({\n kind: \"activity\" as const,\n ...activity,\n })),\n ].sort((left, right) => left.createdAt - right.createdAt);\n return (\n <ol\n className=\"webless-agent-root agent-transcript not-typeset\"\n data-not-typeset=\"\"\n data-color-scheme={scheme}\n aria-label={label}\n style={agentThemeStyle(theme, scheme)}\n >\n {entries.map((entry, index) => {\n const date = new Date(entry.createdAt);\n const previous = entries[index - 1];\n const validTimestamp = Number.isFinite(date.getTime());\n const showTimestamp =\n validTimestamp &&\n (previous\n ? entry.createdAt - previous.createdAt >= 5 * 60 * 1000 ||\n date.toISOString().slice(0, 10) !==\n new Date(previous.createdAt).toJSON()?.slice(0, 10)\n : showInitialTimestamp);\n return (\n <Fragment key={`${entry.kind}:${entry.id}`}>\n {showTimestamp ? (\n <li className=\"agent-transcript__time-marker\">\n <time dateTime={date.toISOString()}>\n {formatTimestamp(entry.createdAt)}\n </time>\n </li>\n ) : null}\n {entry.kind === \"activity\" ? (\n <TranscriptActivity activity={entry} />\n ) : (\n <li\n className={`agent-transcript__message agent-transcript__message--${entry.role}`}\n >\n <div className=\"agent-transcript__meta\">\n <span>\n {entry.role === \"visitor\" ? visitorLabel : agentLabel}\n </span>\n </div>\n <MessageBubble\n message={\n entry.role === \"agent\"\n ? { ...entry, streaming: false }\n : entry\n }\n bookingReadOnly\n bookingDisabled\n />\n </li>\n )}\n </Fragment>\n );\n })}\n </ol>\n );\n}\n","import type { ResolvedVisitorToolResultPresentation } from \"../../lib/tool-result\";\nimport { VisitorToolResultView } from \"../VisitorToolResultView/VisitorToolResultView\";\nimport { SearchReferences } from \"../SearchReferences/SearchReferences\";\nimport { BookingCard } from \"../BookingCard/BookingCard\";\n\nexport type AgentTranscriptActivity = {\n id: string;\n createdAt: number;\n callId: string;\n category: \"tool\" | \"specialist\";\n label: string;\n status: \"started\" | \"completed\" | \"failed\" | \"rejected\";\n result?: ResolvedVisitorToolResultPresentation;\n};\n\nconst statusLabels = {\n started: \"No result recorded\",\n completed: \"\",\n failed: \"Failed\",\n rejected: \"Rejected\",\n};\n\nfunction RecordedResult({\n result,\n}: {\n result: ResolvedVisitorToolResultPresentation;\n}) {\n if (result.kind === \"search\") return <SearchReferences results={[result]} />;\n if (result.kind === \"booking\") {\n const card = result.card;\n if (card.type === \"booking_offer\")\n return <BookingCard readOnly offer={card} />;\n if (card.type === \"booking_confirmed\")\n return (\n <p>Booking confirmed{card.startTime ? ` · ${card.startTime}` : \"\"}</p>\n );\n if (card.type === \"booking_canceled\") return <p>Booking canceled</p>;\n return <p>Information requested</p>;\n }\n return <VisitorToolResultView disabled result={result} />;\n}\n\nexport function TranscriptActivity({\n activity,\n}: {\n activity: AgentTranscriptActivity;\n}) {\n const result =\n activity.result?.kind === \"hidden\" ? undefined : activity.result;\n const heading = (\n <>\n <span>\n {activity.category === \"specialist\"\n ? `Specialist · ${activity.label}`\n : activity.label}\n </span>\n {activity.status !== \"completed\" ? (\n <span className=\"agent-transcript__activity-status\">\n {statusLabels[activity.status]}\n </span>\n ) : null}\n </>\n );\n return (\n <li className=\"agent-transcript__activity\" data-status={activity.status}>\n {result ? (\n <details>\n <summary className=\"agent-transcript__activity-heading\">\n {heading}\n </summary>\n <div className=\"agent-transcript__activity-result\">\n <RecordedResult result={result} />\n </div>\n </details>\n ) : (\n <div className=\"agent-transcript__activity-heading\">{heading}</div>\n )}\n </li>\n );\n}\n","import type { AgentTranscriptActivity } from \"./TranscriptActivity\";\n\n/** A paginated snapshot may deliver a call and its result on different pages. */\nexport function groupTranscriptActivities(\n activities: readonly AgentTranscriptActivity[],\n) {\n const calls = new Map<\n string,\n {\n latest: AgentTranscriptActivity;\n id: string;\n startedAt: number;\n label: string;\n }\n >();\n for (const activity of activities) {\n const key = `${activity.category}:${activity.callId}`;\n const previous = calls.get(key);\n if (!previous) {\n calls.set(key, {\n latest: activity,\n id: activity.id,\n startedAt: activity.createdAt,\n label: activity.label,\n });\n continue;\n }\n const previousHasResult = previous.latest.status !== \"started\";\n const nextHasResult = activity.status !== \"started\";\n const useNext =\n (nextHasResult && !previousHasResult) ||\n (nextHasResult === previousHasResult &&\n activity.createdAt >= previous.latest.createdAt);\n const latest = useNext ? activity : previous.latest;\n calls.set(key, {\n latest,\n id: previous.id,\n startedAt: Math.min(previous.startedAt, activity.createdAt),\n label:\n activity.createdAt < previous.startedAt\n ? activity.label\n : previous.label,\n });\n }\n return [...calls.values()].map(({ latest, id, startedAt, label }) => ({\n ...latest,\n id,\n label,\n createdAt: startedAt,\n }));\n}\n"],"mappings":"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","names":["Fragment","jsx","jsxs","Fragment"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@webless/agent",
3
- "version": "0.9.1",
3
+ "version": "0.9.2",
4
4
  "description": "Webless Agent SDK — Eve runtime client, React UI, and embed bundle.",
5
5
  "type": "module",
6
6
  "license": "MIT",