@heroui/agent 0.2.0-beta.1 → 0.2.0-beta.3

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.
@@ -33,7 +33,7 @@ import {
33
33
  shouldRestoreActiveAgentPermissionMode,
34
34
  storeAgentPermissionMode,
35
35
  takeAgentShellHandoff
36
- } from "./chunk-RQCTC4JB.js";
36
+ } from "./chunk-EXFDD3K3.js";
37
37
  import {
38
38
  ActionButton,
39
39
  CodeBlock,
@@ -141,6 +141,41 @@ function decodeTokenPayload(token) {
141
141
  }
142
142
  }
143
143
 
144
+ // ../agent-client/src/presence.ts
145
+ var AGENT_CONVERSATION_PRESENCE_ROOM = "agentConversationPresence";
146
+ var presenceDatabases = /* @__PURE__ */ new Map();
147
+ function getPresenceDatabase(appId) {
148
+ const existing = presenceDatabases.get(appId);
149
+ if (existing) return existing;
150
+ const database = import("@instantdb/core").then(({ init }) => init({ appId, devtool: false })).catch((error) => {
151
+ presenceDatabases.delete(appId);
152
+ throw error;
153
+ });
154
+ presenceDatabases.set(appId, database);
155
+ return database;
156
+ }
157
+ function syncAgentConversationPresence({
158
+ agentId,
159
+ appId,
160
+ conversationId,
161
+ userId
162
+ }) {
163
+ let disposed = false;
164
+ let leaveRoom;
165
+ void getPresenceDatabase(appId).then((database) => {
166
+ const room = database.joinRoom(AGENT_CONVERSATION_PRESENCE_ROOM, agentId, {
167
+ initialPresence: { conversationId, userId }
168
+ });
169
+ if (disposed) room.leaveRoom();
170
+ else leaveRoom = room.leaveRoom;
171
+ }).catch(() => {
172
+ });
173
+ return () => {
174
+ disposed = true;
175
+ leaveRoom?.();
176
+ };
177
+ }
178
+
144
179
  // ../agent-client/src/conversation-target.ts
145
180
  function isConversationId(value) {
146
181
  return Boolean(
@@ -1743,7 +1778,7 @@ var agentModelIdSchema = z2.preprocess(
1743
1778
 
1744
1779
  // src/contracts/version.ts
1745
1780
  var HEROUI_AGENT_PROTOCOL_VERSION = 5;
1746
- var HEROUI_AGENT_SDK_VERSION = "0.2.0-beta.1";
1781
+ var HEROUI_AGENT_SDK_VERSION = "0.2.0-beta.3";
1747
1782
  var HEROUI_AGENT_TASK_ID = "heroui-agents-runtime";
1748
1783
 
1749
1784
  // src/contracts/identity.ts
@@ -1869,6 +1904,11 @@ var agentProjectConfigSchema = z3.object({
1869
1904
  agentId: z3.string(),
1870
1905
  minimumProtocolVersion: z3.literal(HEROUI_AGENT_PROTOCOL_VERSION),
1871
1906
  name: z3.string().trim().min(1).max(120),
1907
+ /**
1908
+ * InstantDB app used for ephemeral live-conversation presence. Optional so
1909
+ * newer SDKs remain compatible with older Agent API deployments.
1910
+ */
1911
+ presence: z3.object({ appId: z3.uuid() }).optional(),
1872
1912
  protocolVersion: z3.literal(HEROUI_AGENT_PROTOCOL_VERSION),
1873
1913
  /**
1874
1914
  * Internal streaming infrastructure endpoint, resolved server-side so
@@ -2093,74 +2133,86 @@ var activityIcons = {
2093
2133
  search: Magnifier,
2094
2134
  thinking: Wrench
2095
2135
  };
2136
+ function formatActivityDuration(durationMs) {
2137
+ const totalSeconds = Math.max(1, Math.round(durationMs / 1e3));
2138
+ const hours = Math.floor(totalSeconds / 3600);
2139
+ const minutes = Math.floor(totalSeconds % 3600 / 60);
2140
+ const seconds = totalSeconds % 60;
2141
+ if (hours > 0) return `${hours}h ${minutes}m`;
2142
+ if (minutes > 0) return `${minutes}m ${seconds}s`;
2143
+ return `${seconds}s`;
2144
+ }
2145
+ function ActivityStatusIcon({ kind }) {
2146
+ const Icon = kind === "complete" ? CircleCheck : activityIcons[kind];
2147
+ return /* @__PURE__ */ jsx8("span", { className: "ha-activity-status-icon", children: /* @__PURE__ */ jsx8(Icon, { "aria-hidden": "true" }) }, kind);
2148
+ }
2149
+ function ActivityStatus({ label }) {
2150
+ return /* @__PURE__ */ jsxs5("div", { className: "ha-progress ha-activity-status", children: [
2151
+ /* @__PURE__ */ jsx8(ActivityStatusIcon, { kind: inferActivityKind(label) }),
2152
+ /* @__PURE__ */ jsx8(AnimatedStatusText, { className: "ha-progress-shimmer", role: "status", children: label })
2153
+ ] });
2154
+ }
2096
2155
  function ActivityTrail({
2097
- completionDetail = "Done",
2098
- completionLabel = "Completed",
2156
+ completedAt,
2099
2157
  defaultOpen = false,
2100
2158
  isStreaming,
2101
2159
  items,
2102
- progress
2160
+ progress,
2161
+ startedAt
2103
2162
  }) {
2104
- const [expandedOverride, setExpandedOverride] = useState4(null);
2163
+ const [isExpanded, setIsExpanded] = useState4(defaultOpen);
2105
2164
  const panelRef = useRef5(null);
2106
2165
  const activeItem = items.findLast((item) => item.active);
2107
- const summary = isStreaming ? progress ?? activeItem?.label ?? "Thinking\u2026" : "Activity";
2108
- const isExpanded = expandedOverride ?? (isStreaming || defaultOpen);
2166
+ const latestItem = items.at(-1);
2167
+ const activeLabel = activeItem?.label ?? latestItem?.label ?? progress ?? "Understanding your request\u2026";
2168
+ const elapsedMs = startedAt !== void 0 && !isStreaming ? Math.max(0, (completedAt ?? Date.now()) - startedAt) : null;
2169
+ const summary = isStreaming ? activeLabel : elapsedMs === null ? "Activity" : `Worked for ${formatActivityDuration(elapsedMs)}`;
2170
+ const summaryKind = isStreaming ? activeItem?.kind ?? inferActivityKind(activeLabel) : "complete";
2109
2171
  useScrollShadow(panelRef);
2110
2172
  useFollowNewestStep(panelRef, items.length, isStreaming, isExpanded);
2111
- return /* @__PURE__ */ jsxs5(
2112
- Disclosure2,
2113
- {
2114
- className: "ha-activity",
2115
- isExpanded,
2116
- onExpandedChange: setExpandedOverride,
2117
- children: [
2118
- /* @__PURE__ */ jsx8(Disclosure2.Heading, { children: /* @__PURE__ */ jsxs5(Disclosure2.Trigger, { className: "ha-activity-trigger", children: [
2119
- isStreaming ? /* @__PURE__ */ jsx8(
2120
- AnimatedStatusText,
2121
- {
2122
- className: "ha-activity-summary-label ha-progress-shimmer",
2123
- role: "status",
2124
- children: summary
2125
- }
2126
- ) : /* @__PURE__ */ jsx8("span", { children: summary }),
2127
- /* @__PURE__ */ jsx8(Disclosure2.Indicator, { className: "ha-activity-chevron" })
2128
- ] }) }),
2129
- /* @__PURE__ */ jsx8(Disclosure2.Content, { className: "ha-activity-disclosure-content", children: /* @__PURE__ */ jsx8(Disclosure2.Body, { children: /* @__PURE__ */ jsx8("div", { ref: panelRef, className: "ha-activity-panel", children: /* @__PURE__ */ jsxs5("ol", { "aria-label": "Thinking steps", children: [
2130
- items.map((item) => {
2131
- const Icon = activityIcons[item.kind ?? inferActivityKind(item.label)];
2132
- return /* @__PURE__ */ jsxs5(
2133
- "li",
2134
- {
2135
- "aria-current": item.active ? "step" : void 0,
2136
- className: "ha-activity-item",
2137
- "data-active": item.active || void 0,
2138
- children: [
2139
- /* @__PURE__ */ jsx8("span", { className: "ha-activity-icon", children: /* @__PURE__ */ jsx8(Icon, { "aria-hidden": "true" }) }),
2140
- /* @__PURE__ */ jsxs5("span", { className: "ha-activity-content", children: [
2141
- item.active ? /* @__PURE__ */ jsx8(AnimatedStatusText, { className: "ha-progress-shimmer", children: item.label }) : /* @__PURE__ */ jsx8("span", { children: item.label }),
2142
- item.detail ? /* @__PURE__ */ jsx8("small", { children: item.detail }) : null,
2143
- item.sources?.length ? /* @__PURE__ */ jsx8("span", { "aria-label": "Sources", className: "ha-activity-sources", children: item.sources.map((source) => /* @__PURE__ */ jsxs5("span", { className: "ha-activity-source", children: [
2144
- /* @__PURE__ */ jsx8(Globe, { "aria-hidden": "true" }),
2145
- source.label
2146
- ] }, source.label)) }) : null
2147
- ] })
2148
- ]
2149
- },
2150
- item.id
2151
- );
2152
- }),
2153
- !isStreaming ? /* @__PURE__ */ jsxs5("li", { className: "ha-activity-item", "data-complete": "true", children: [
2154
- /* @__PURE__ */ jsx8("span", { className: "ha-activity-icon", children: /* @__PURE__ */ jsx8(CircleCheck, { "aria-hidden": "true" }) }),
2155
- /* @__PURE__ */ jsxs5("span", { className: "ha-activity-content", children: [
2156
- /* @__PURE__ */ jsx8("span", { children: completionLabel }),
2157
- /* @__PURE__ */ jsx8("small", { children: completionDetail })
2158
- ] })
2159
- ] }) : null
2160
- ] }) }) }) })
2161
- ]
2162
- }
2163
- );
2173
+ return /* @__PURE__ */ jsxs5(Disclosure2, { className: "ha-activity", isExpanded, onExpandedChange: setIsExpanded, children: [
2174
+ /* @__PURE__ */ jsx8(Disclosure2.Heading, { children: /* @__PURE__ */ jsxs5(Disclosure2.Trigger, { className: "ha-activity-trigger", children: [
2175
+ /* @__PURE__ */ jsx8(ActivityStatusIcon, { kind: summaryKind }),
2176
+ isStreaming ? /* @__PURE__ */ jsx8(
2177
+ AnimatedStatusText,
2178
+ {
2179
+ className: "ha-activity-summary-label ha-progress-shimmer",
2180
+ role: "status",
2181
+ children: summary
2182
+ }
2183
+ ) : /* @__PURE__ */ jsx8("span", { children: summary }),
2184
+ /* @__PURE__ */ jsx8(Disclosure2.Indicator, { className: "ha-activity-chevron" })
2185
+ ] }) }),
2186
+ /* @__PURE__ */ jsx8(Disclosure2.Content, { className: "ha-activity-disclosure-content", children: /* @__PURE__ */ jsx8(Disclosure2.Body, { children: /* @__PURE__ */ jsx8("div", { ref: panelRef, className: "ha-activity-panel", children: /* @__PURE__ */ jsxs5("ol", { "aria-label": "Thinking steps", children: [
2187
+ items.map((item) => {
2188
+ const Icon = activityIcons[item.kind ?? inferActivityKind(item.label)];
2189
+ return /* @__PURE__ */ jsxs5(
2190
+ "li",
2191
+ {
2192
+ "aria-current": item.active ? "step" : void 0,
2193
+ className: "ha-activity-item",
2194
+ "data-active": item.active || void 0,
2195
+ children: [
2196
+ /* @__PURE__ */ jsx8("span", { className: "ha-activity-icon", children: /* @__PURE__ */ jsx8(Icon, { "aria-hidden": "true" }) }),
2197
+ /* @__PURE__ */ jsxs5("span", { className: "ha-activity-content", children: [
2198
+ item.active ? /* @__PURE__ */ jsx8(AnimatedStatusText, { className: "ha-progress-shimmer", children: item.label }) : /* @__PURE__ */ jsx8("span", { children: item.label }),
2199
+ item.detail ? /* @__PURE__ */ jsx8("small", { children: item.detail }) : null,
2200
+ item.sources?.length ? /* @__PURE__ */ jsx8("span", { "aria-label": "Sources", className: "ha-activity-sources", children: item.sources.map((source) => /* @__PURE__ */ jsxs5("span", { className: "ha-activity-source", children: [
2201
+ /* @__PURE__ */ jsx8(Globe, { "aria-hidden": "true" }),
2202
+ source.label
2203
+ ] }, source.label)) }) : null
2204
+ ] })
2205
+ ]
2206
+ },
2207
+ item.id
2208
+ );
2209
+ }),
2210
+ !isStreaming ? /* @__PURE__ */ jsxs5("li", { className: "ha-activity-item", "data-complete": "true", children: [
2211
+ /* @__PURE__ */ jsx8("span", { className: "ha-activity-icon", children: /* @__PURE__ */ jsx8(CircleCheck, { "aria-hidden": "true" }) }),
2212
+ /* @__PURE__ */ jsx8("span", { className: "ha-activity-content", children: /* @__PURE__ */ jsx8("span", { children: "Done" }) })
2213
+ ] }) : null
2214
+ ] }) }) }) })
2215
+ ] });
2164
2216
  }
2165
2217
 
2166
2218
  // src/embed/agent-api.ts
@@ -2815,36 +2867,16 @@ var ConversationMarkdown = memo(function ConversationMarkdown2({
2815
2867
 
2816
2868
  // src/embed/conversation-presence.tsx
2817
2869
  import { useEffect as useEffect7 } from "react";
2818
- var PRESENCE_HEARTBEAT_MS = 2e4;
2819
- async function sendPresence(apiBaseUrl, conversationId, tokenManager) {
2820
- try {
2821
- await fetch(`${apiBaseUrl}/v1/conversations/${encodeURIComponent(conversationId)}/presence`, {
2822
- // The API gates every embed route on the protocol pair; sending only the
2823
- // credential gets the heartbeat rejected with 426.
2824
- headers: agentRequestHeaders(await tokenManager.get()),
2825
- keepalive: true,
2826
- method: "POST"
2827
- });
2828
- } catch {
2829
- }
2830
- }
2831
2870
  function AgentConversationPresence({
2832
- apiBaseUrl,
2871
+ agentId,
2872
+ appId,
2833
2873
  conversationId,
2834
- tokenManager
2874
+ userId
2835
2875
  }) {
2836
- useEffect7(() => {
2837
- let cancelled = false;
2838
- const beat = () => {
2839
- if (!cancelled) void sendPresence(apiBaseUrl, conversationId, tokenManager);
2840
- };
2841
- beat();
2842
- const timer = setInterval(beat, PRESENCE_HEARTBEAT_MS);
2843
- return () => {
2844
- cancelled = true;
2845
- clearInterval(timer);
2846
- };
2847
- }, [apiBaseUrl, conversationId, tokenManager]);
2876
+ useEffect7(
2877
+ () => syncAgentConversationPresence({ agentId, appId, conversationId, userId }),
2878
+ [agentId, appId, conversationId, userId]
2879
+ );
2848
2880
  return null;
2849
2881
  }
2850
2882
 
@@ -2864,7 +2896,7 @@ function getConversationPresentation({
2864
2896
  return { showHome, standaloneStatus: null };
2865
2897
  }
2866
2898
  if (isActiveTurn) {
2867
- return { showHome, standaloneStatus: progress ?? "Planning next moves\u2026" };
2899
+ return { showHome, standaloneStatus: progress ?? "Understanding your request\u2026" };
2868
2900
  }
2869
2901
  if (isAwaitingActiveConversation) {
2870
2902
  return { showHome, standaloneStatus: "Loading chat\u2026" };
@@ -3158,7 +3190,7 @@ function ConversationViewport({
3158
3190
  import { Suspense as Suspense2, lazy as lazy2 } from "react";
3159
3191
  import { jsx as jsx15 } from "react/jsx-runtime";
3160
3192
  var LazyComponentRenderer = lazy2(
3161
- () => import("./component-renderer-IBJDNXSO.js").then((module) => ({
3193
+ () => import("./component-renderer-EOOT6ONY.js").then((module) => ({
3162
3194
  default: module.ComponentRenderer
3163
3195
  }))
3164
3196
  );
@@ -5406,6 +5438,7 @@ function EmbedRuntime({
5406
5438
  bootstrapCacheRef.current = {
5407
5439
  config,
5408
5440
  historyKey,
5441
+ presenceUserId: subjectHash,
5409
5442
  storageKey
5410
5443
  };
5411
5444
  setHistory(bootstrappedHistory);
@@ -5414,6 +5447,7 @@ function EmbedRuntime({
5414
5447
  conversationId,
5415
5448
  historyKey,
5416
5449
  initialMessages: bootstrap.messages ?? [],
5450
+ presenceUserId: subjectHash,
5417
5451
  status: bootstrap.status,
5418
5452
  storageKey
5419
5453
  });
@@ -5575,12 +5609,13 @@ function EmbedRuntime({
5575
5609
  const activeConversationTitle = history.find((conversation) => conversation.id === activeConversationId)?.title ?? "New chat";
5576
5610
  const loadingMessage = bootstrapCacheRef.current ? "Loading chat\u2026" : "Loading assistant\u2026";
5577
5611
  return /* @__PURE__ */ jsxs17(Fragment4, { children: [
5578
- open && runtime ? /* @__PURE__ */ jsx25(
5612
+ open && runtime?.config.presence ? /* @__PURE__ */ jsx25(
5579
5613
  AgentConversationPresence,
5580
5614
  {
5581
- apiBaseUrl,
5615
+ agentId,
5616
+ appId: runtime.config.presence.appId,
5582
5617
  conversationId: runtime.conversationId,
5583
- tokenManager
5618
+ userId: runtime.presenceUserId
5584
5619
  }
5585
5620
  ) : null,
5586
5621
  /* @__PURE__ */ jsxs17(
@@ -5725,6 +5760,7 @@ function ChatRuntime({
5725
5760
  const restoredMode = storedMode ?? (shouldRestoreActivePermission ? "ask" : void 0);
5726
5761
  return restoredMode ? { modelId: void 0, permissionMode: restoredMode } : void 0;
5727
5762
  });
5763
+ const [activityTimings, setActivityTimings] = useState13({});
5728
5764
  const [feedbackByMessage, setFeedbackByMessage] = useState13({});
5729
5765
  const [isComposerExpanded, setIsComposerExpanded] = useState13(false);
5730
5766
  const [input, setInput] = useState13("");
@@ -5815,7 +5851,9 @@ function ChatRuntime({
5815
5851
  const sendAcknowledgedRef = useRef14(false);
5816
5852
  const sendErrorRef = useRef14(null);
5817
5853
  const streamedMessageIdsRef = useRef14(/* @__PURE__ */ new Set());
5854
+ const timedMessageIdRef = useRef14(null);
5818
5855
  const transportFailureRef = useRef14(null);
5856
+ const turnStartedAtRef = useRef14(null);
5819
5857
  const needsReconciliationRef = useRef14(false);
5820
5858
  const clearChatErrorRef = useRef14(() => void 0);
5821
5859
  const fileInputRef = useRef14(null);
@@ -6100,6 +6138,28 @@ function ChatRuntime({
6100
6138
  const hasStreamingActivity = Boolean(
6101
6139
  streamingAssistantMessage && collectActivity(streamingAssistantMessage, clientToolsByName, { isStreaming: true }).length > 0
6102
6140
  );
6141
+ useEffect12(() => {
6142
+ if (hasActiveTurn && streamingAssistantMessageId) {
6143
+ if (timedMessageIdRef.current === streamingAssistantMessageId) return;
6144
+ const startedAt = turnStartedAtRef.current ?? Date.now();
6145
+ timedMessageIdRef.current = streamingAssistantMessageId;
6146
+ setActivityTimings((current) => ({
6147
+ ...current,
6148
+ [streamingAssistantMessageId]: { startedAt }
6149
+ }));
6150
+ return;
6151
+ }
6152
+ const completedMessageId = timedMessageIdRef.current;
6153
+ if (hasActiveTurn || !completedMessageId) return;
6154
+ const completedAt = Date.now();
6155
+ setActivityTimings((current) => {
6156
+ const timing = current[completedMessageId];
6157
+ if (!timing || timing.completedAt) return current;
6158
+ return { ...current, [completedMessageId]: { ...timing, completedAt } };
6159
+ });
6160
+ timedMessageIdRef.current = null;
6161
+ turnStartedAtRef.current = null;
6162
+ }, [hasActiveTurn, streamingAssistantMessageId]);
6103
6163
  const submitToolOutput = useCallback11(
6104
6164
  (tool, toolCallId, output) => chatState.addToolOutput({ output, tool, toolCallId }),
6105
6165
  [chatState.addToolOutput]
@@ -6290,6 +6350,8 @@ function ChatRuntime({
6290
6350
  modelId: message.modelId,
6291
6351
  permissionMode: messagePermissionMode
6292
6352
  });
6353
+ timedMessageIdRef.current = null;
6354
+ turnStartedAtRef.current = Date.now();
6293
6355
  prepareTransportSend();
6294
6356
  setLocalPending(true);
6295
6357
  setRecoveryError(false);
@@ -6643,6 +6705,8 @@ function ChatRuntime({
6643
6705
  applyAgentPermissionMode(options.tools, composerPermissionMode)
6644
6706
  );
6645
6707
  clientToolManifestRef.current = retryClientToolManifest;
6708
+ timedMessageIdRef.current = null;
6709
+ turnStartedAtRef.current = Date.now();
6646
6710
  activateTurnSelection({
6647
6711
  modelId: composerModelId,
6648
6712
  permissionMode: composerPermissionMode
@@ -6701,6 +6765,7 @@ function ChatRuntime({
6701
6765
  ] }) : chatState.messages.map((message) => /* @__PURE__ */ jsx25(
6702
6766
  Message,
6703
6767
  {
6768
+ activityTiming: activityTimings[message.id],
6704
6769
  actions: options.messageActions,
6705
6770
  canRetry: message.id === lastAssistantMessageId && !isBusy,
6706
6771
  clientTools: clientToolsByName,
@@ -6722,7 +6787,7 @@ function ChatRuntime({
6722
6787
  },
6723
6788
  message.id
6724
6789
  )),
6725
- standaloneStatus ? /* @__PURE__ */ jsx25("div", { className: "ha-message", "data-role": "assistant", "data-stream-anchor": "true", children: /* @__PURE__ */ jsx25("div", { className: "ha-message-body", children: /* @__PURE__ */ jsx25(AnimatedStatusText, { className: "ha-progress ha-progress-shimmer", role: "status", children: standaloneStatus }) }) }) : null,
6790
+ standaloneStatus ? /* @__PURE__ */ jsx25("div", { className: "ha-message", "data-role": "assistant", "data-stream-anchor": "true", children: /* @__PURE__ */ jsx25("div", { className: "ha-message-body", children: /* @__PURE__ */ jsx25(ActivityStatus, { label: standaloneStatus }) }) }) : null,
6726
6791
  chatState.error || recoveryError ? /* @__PURE__ */ jsxs17("div", { className: "ha-error", role: "alert", children: [
6727
6792
  /* @__PURE__ */ jsx25("span", { children: "The request could not be completed." }),
6728
6793
  /* @__PURE__ */ jsx25("button", { type: "button", onClick: retryLastResponse, children: "Retry" })
@@ -6952,6 +7017,7 @@ function ChatRuntime({
6952
7017
  }
6953
7018
  function Message({
6954
7019
  actions,
7020
+ activityTiming,
6955
7021
  canRetry,
6956
7022
  clientTools,
6957
7023
  exportFormats,
@@ -7074,7 +7140,16 @@ function Message({
7074
7140
  "data-role": "assistant",
7075
7141
  "data-stream-anchor": isStreaming ? true : void 0,
7076
7142
  children: /* @__PURE__ */ jsxs17("div", { className: "ha-message-body", children: [
7077
- activity.length > 0 ? /* @__PURE__ */ jsx25(ActivityTrail, { isStreaming, items: activity, progress }) : null,
7143
+ activity.length > 0 ? /* @__PURE__ */ jsx25(
7144
+ ActivityTrail,
7145
+ {
7146
+ completedAt: activityTiming?.completedAt,
7147
+ isStreaming,
7148
+ items: activity,
7149
+ progress,
7150
+ startedAt: activityTiming?.startedAt
7151
+ }
7152
+ ) : null,
7078
7153
  content.length > 0 ? /* @__PURE__ */ jsx25("div", { className: "ha-message-content", children: content }) : null,
7079
7154
  /* @__PURE__ */ jsx25(MessageSources, { sources: visibleSources }),
7080
7155
  !isStreaming && content.length > 0 && actions.length > 0 ? /* @__PURE__ */ jsx25(
@@ -132,6 +132,9 @@ declare const agentProjectConfigSchema: z.ZodObject<{
132
132
  agentId: z.ZodString;
133
133
  minimumProtocolVersion: z.ZodLiteral<5>;
134
134
  name: z.ZodString;
135
+ presence: z.ZodOptional<z.ZodObject<{
136
+ appId: z.ZodUUID;
137
+ }, z.core.$strip>>;
135
138
  protocolVersion: z.ZodLiteral<5>;
136
139
  realtime: z.ZodOptional<z.ZodObject<{
137
140
  url: z.ZodURL;
package/dist/index.d.ts CHANGED
@@ -125,11 +125,11 @@ type AgentModelOption = {
125
125
  tier: AgentModelTier;
126
126
  };
127
127
  /**
128
- * Recommended default selected when the optional picker first opens. Luna
128
+ * Recommended default selected when the optional picker first opens. Gemini
129
129
  * matches the hosted runtime's baked-in default (`DEFAULT_CHAT_MODEL_IDS.herouiAgent`),
130
130
  * so what users see in the picker is what actually runs by default.
131
131
  */
132
- declare const DEFAULT_AGENT_PICKER_MODEL_ID = "openai/gpt-5.6-luna";
132
+ declare const DEFAULT_AGENT_PICKER_MODEL_ID = "google/gemini-3.6-flash";
133
133
  /**
134
134
  * Small, tool-capable model catalog for HeroUI Agent. These ids are the
135
135
  * server-side allowlist as well as the browser picker source of truth.
@@ -571,7 +571,7 @@ type AgentController = {
571
571
  };
572
572
 
573
573
  /**
574
- * Imperative controls for the embedded agent. Safe to call before
574
+ * Imperative controls for the agent embed. Safe to call before
575
575
  * `<HeroUIAgent />` mounts (calls are ignored with a console warning). Pass a
576
576
  * `agentId` when rendering more than one agent on the same page.
577
577
  */
package/dist/index.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HeroUIAgent,
3
3
  useAgent
4
- } from "./chunk-GDDNN2XY.js";
4
+ } from "./chunk-5FDSKYU6.js";
5
5
  import {
6
6
  AGENT_DESIGN_THEMES,
7
7
  AGENT_MODEL_IDS,
@@ -12,7 +12,7 @@ import {
12
12
  getAgentModelTier,
13
13
  isAgentModelId,
14
14
  resolveAgentModelId
15
- } from "./chunk-RQCTC4JB.js";
15
+ } from "./chunk-EXFDD3K3.js";
16
16
  export {
17
17
  AGENT_DESIGN_THEMES,
18
18
  AGENT_MODEL_IDS,
package/dist/next.js CHANGED
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  HeroUIAgent,
3
3
  useAgent
4
- } from "./chunk-GDDNN2XY.js";
4
+ } from "./chunk-5FDSKYU6.js";
5
5
  import {
6
6
  AGENT_MODEL_IDS,
7
7
  AGENT_MODEL_OPTIONS,
@@ -9,7 +9,7 @@ import {
9
9
  createToolHelper,
10
10
  getAgentModelTier,
11
11
  isAgentModelId
12
- } from "./chunk-RQCTC4JB.js";
12
+ } from "./chunk-EXFDD3K3.js";
13
13
  export {
14
14
  AGENT_MODEL_IDS,
15
15
  AGENT_MODEL_OPTIONS,
package/dist/server.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { a as AgentAuthIdentity, b as AgentAuthProfile, c as AgentAuthToken } from './identity-NYCXY1mT.js';
1
+ import { a as AgentAuthIdentity, b as AgentAuthProfile, c as AgentAuthToken } from './identity-hIGFpObN.js';
2
2
  import 'zod';
3
3
 
4
4
  type CreateAuthTokenOptions = {
package/dist/server.js CHANGED
@@ -66,7 +66,7 @@ var agentModelIdSchema = z2.preprocess(
66
66
 
67
67
  // src/contracts/version.ts
68
68
  var HEROUI_AGENT_PROTOCOL_VERSION = 5;
69
- var HEROUI_AGENT_SDK_VERSION = "0.2.0-beta.1";
69
+ var HEROUI_AGENT_SDK_VERSION = "0.2.0-beta.3";
70
70
 
71
71
  // src/contracts/identity.ts
72
72
  var agentThemeSchema = z3.enum(["light", "dark", "system"]);
@@ -191,6 +191,11 @@ var agentProjectConfigSchema = z3.object({
191
191
  agentId: z3.string(),
192
192
  minimumProtocolVersion: z3.literal(HEROUI_AGENT_PROTOCOL_VERSION),
193
193
  name: z3.string().trim().min(1).max(120),
194
+ /**
195
+ * InstantDB app used for ephemeral live-conversation presence. Optional so
196
+ * newer SDKs remain compatible with older Agent API deployments.
197
+ */
198
+ presence: z3.object({ appId: z3.uuid() }).optional(),
194
199
  protocolVersion: z3.literal(HEROUI_AGENT_PROTOCOL_VERSION),
195
200
  /**
196
201
  * Internal streaming infrastructure endpoint, resolved server-side so
package/package.json CHANGED
@@ -1,14 +1,14 @@
1
1
  {
2
2
  "name": "@heroui/agent",
3
- "version": "0.2.0-beta.1",
3
+ "version": "0.2.0-beta.3",
4
4
  "description": "Embed a hosted HeroUI Agent that turns application data into interactive UI.",
5
5
  "homepage": "https://www.heroui.com/agents",
6
6
  "bugs": {
7
- "url": "https://github.com/heroui-inc/heroui-platform/issues"
7
+ "url": "https://github.com/heroui-inc/heroui-pro/issues"
8
8
  },
9
9
  "repository": {
10
10
  "type": "git",
11
- "url": "git+https://github.com/heroui-inc/heroui-platform.git",
11
+ "url": "git+https://github.com/heroui-inc/heroui-pro.git",
12
12
  "directory": "packages/agent"
13
13
  },
14
14
  "keywords": [
@@ -64,27 +64,11 @@
64
64
  "engines": {
65
65
  "node": ">=20"
66
66
  },
67
- "scripts": {
68
- "build": "rm -rf dist && tsup && pnpm build:styles",
69
- "build:contracts": "rm -rf dist && tsup --config tsup.contracts.config.ts",
70
- "build:styles": "node scripts/build-styles.mjs",
71
- "check:bundle": "node scripts/check-bundle-size.mjs",
72
- "check:package": "publint && attw --pack . --profile esm-only --exclude-entrypoints css css/index.css",
73
- "check:styles": "node scripts/build-styles.mjs --check",
74
- "clean": "rm -rf dist node_modules .turbo",
75
- "lint": "eslint src/",
76
- "lint:fix": "eslint src/ --fix",
77
- "prepublishOnly": "export npm_config_dry_run=false && pnpm --dir ../.. exec turbo run build --filter=@heroui/agent && pnpm lint && pnpm typecheck && pnpm test && pnpm check:package && pnpm check:bundle && pnpm verify:pack",
78
- "release": "pnpm prepublishOnly && pnpm version:bump",
79
- "test": "NODE_OPTIONS=\"${NODE_OPTIONS:+$NODE_OPTIONS }--no-experimental-webstorage\" vitest run",
80
- "typecheck": "tsc --noEmit",
81
- "version:bump": "bumpp package.json src/contracts/version.ts ../../apps/frontend/src/app/dashboard/agents/_preview/contracts/version.ts --commit \"chore(agent): release heroui-agent-v%s\" --tag \"heroui-agent-v%s\"",
82
- "verify:pack": "node scripts/verify-packed-package.mjs"
83
- },
84
67
  "dependencies": {
85
68
  "@ai-sdk/react": "4.0.12",
86
69
  "@gravity-ui/icons": "2.18.0",
87
70
  "@heroui/react": "3.2.2",
71
+ "@instantdb/core": "1.0.49",
88
72
  "@internationalized/date": "3.12.2",
89
73
  "@react-aria/utils": "3.34.1",
90
74
  "@react-stately/utils": "3.12.1",
@@ -110,10 +94,6 @@
110
94
  ],
111
95
  "devDependencies": {
112
96
  "@arethetypeswrong/cli": "0.18.5",
113
- "@heroui-pro/config": "workspace:*",
114
- "@heroui-pro/react": "workspace:*",
115
- "@heroui/agent-client": "workspace:*",
116
- "@heroui/agent-ui": "workspace:*",
117
97
  "@heroui/styles": "3.2.2",
118
98
  "@tailwindcss/cli": "4.2.2",
119
99
  "@types/react": "19.2.14",
@@ -128,6 +108,25 @@
128
108
  "tailwindcss": "4.2.2",
129
109
  "tsup": "8.5.0",
130
110
  "typescript": "5.9.3",
131
- "vitest": "4.1.0"
111
+ "vitest": "4.1.0",
112
+ "@heroui-pro/react": "1.0.0-beta.7",
113
+ "@heroui-pro/config": "0.0.0",
114
+ "@heroui/agent-client": "0.0.0",
115
+ "@heroui/agent-ui": "0.0.0"
116
+ },
117
+ "scripts": {
118
+ "build": "rm -rf dist && tsup && pnpm build:styles",
119
+ "build:contracts": "rm -rf dist && tsup --config tsup.contracts.config.ts",
120
+ "build:styles": "node scripts/build-styles.mjs",
121
+ "check:bundle": "node scripts/check-bundle-size.mjs",
122
+ "check:package": "publint && attw --pack . --profile esm-only --exclude-entrypoints css css/index.css",
123
+ "check:styles": "node scripts/build-styles.mjs --check",
124
+ "clean": "rm -rf dist node_modules .turbo",
125
+ "lint": "eslint src/",
126
+ "lint:fix": "eslint src/ --fix",
127
+ "release": "pnpm prepublishOnly && bumpp package.json src/contracts/version.ts ../../apps/frontend/src/app/dashboard/agents/_preview/contracts/version.ts --commit \"chore(agent): release heroui-agent-v%s\" --tag \"heroui-agent-v%s\"",
128
+ "test": "NODE_OPTIONS=\"${NODE_OPTIONS:+$NODE_OPTIONS }--no-experimental-webstorage\" vitest run",
129
+ "typecheck": "tsc --noEmit",
130
+ "verify:pack": "node scripts/verify-packed-package.mjs"
132
131
  }
133
- }
132
+ }