@page-speed/agent-everywhere 0.3.1 → 0.5.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.
package/dist/index.cjs CHANGED
@@ -1238,7 +1238,7 @@ var PromptInput = React4.forwardRef(
1238
1238
  [handleSubmit]
1239
1239
  );
1240
1240
  const variantStyles = {
1241
- default: "border-t px-3 py-2.5",
1241
+ default: "px-3 py-2.5",
1242
1242
  minimal: "px-3 py-2",
1243
1243
  bordered: "border rounded-lg px-3 py-2.5"
1244
1244
  };
@@ -1247,41 +1247,48 @@ var PromptInput = React4.forwardRef(
1247
1247
  minimal: "bg-transparent px-0",
1248
1248
  bordered: "bg-muted/50"
1249
1249
  };
1250
- return /* @__PURE__ */ jsxRuntime.jsx("form", { onSubmit: handleSubmit, className: cn(variantStyles[variant], className), children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-2", children: [
1251
- leftActions,
1252
- /* @__PURE__ */ jsxRuntime.jsx(
1253
- "textarea",
1254
- {
1255
- ref: textareaRef,
1256
- value,
1257
- onChange: (e) => onChange(e.target.value),
1258
- onKeyDown: handleKeyDown,
1259
- placeholder,
1260
- disabled: disabled || loading,
1261
- autoFocus,
1262
- rows: minRows,
1263
- className: cn(
1264
- "flex-1 resize-none border-0 px-0 py-1 text-sm leading-5 shadow-none",
1265
- "placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0",
1266
- "disabled:cursor-not-allowed disabled:opacity-50",
1267
- inputVariantStyles[variant],
1268
- inputClassName
1250
+ return /* @__PURE__ */ jsxRuntime.jsx(
1251
+ "form",
1252
+ {
1253
+ onSubmit: handleSubmit,
1254
+ className: cn(variantStyles[variant], className),
1255
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-end gap-2", children: [
1256
+ leftActions,
1257
+ /* @__PURE__ */ jsxRuntime.jsx(
1258
+ "textarea",
1259
+ {
1260
+ ref: textareaRef,
1261
+ value,
1262
+ onChange: (e) => onChange(e.target.value),
1263
+ onKeyDown: handleKeyDown,
1264
+ placeholder,
1265
+ disabled: disabled || loading,
1266
+ autoFocus,
1267
+ rows: minRows,
1268
+ className: cn(
1269
+ "flex-1 resize-none border-0 px-0 py-1 text-sm leading-5 shadow-none",
1270
+ "placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-0",
1271
+ "disabled:cursor-not-allowed disabled:opacity-50",
1272
+ inputVariantStyles[variant],
1273
+ inputClassName
1274
+ )
1275
+ }
1276
+ ),
1277
+ rightActions,
1278
+ showSendButton && /* @__PURE__ */ jsxRuntime.jsx(
1279
+ Button,
1280
+ {
1281
+ type: "submit",
1282
+ size: "sm",
1283
+ variant: variant === "minimal" ? "ghost" : "outline",
1284
+ disabled: !value.trim() || disabled || loading,
1285
+ className: "size-8 shrink-0 p-0",
1286
+ children: sendButtonContent || /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SendIcon, { className: "size-4" })
1287
+ }
1269
1288
  )
1270
- }
1271
- ),
1272
- rightActions,
1273
- showSendButton && /* @__PURE__ */ jsxRuntime.jsx(
1274
- Button,
1275
- {
1276
- type: "submit",
1277
- size: "sm",
1278
- variant: variant === "minimal" ? "ghost" : "outline",
1279
- disabled: !value.trim() || disabled || loading,
1280
- className: "size-8 shrink-0 p-0",
1281
- children: sendButtonContent || /* @__PURE__ */ jsxRuntime.jsx(lucideReact.SendIcon, { className: "size-4" })
1282
- }
1283
- )
1284
- ] }) });
1289
+ ] })
1290
+ }
1291
+ );
1285
1292
  }
1286
1293
  );
1287
1294
  PromptInput.displayName = "PromptInput";
@@ -7215,6 +7222,7 @@ function useSemanticBuilder({
7215
7222
  onGeneratedBlocks,
7216
7223
  onUndoRequest,
7217
7224
  buildWelcomeMessage,
7225
+ seedWelcomeMessage = true,
7218
7226
  webSocketImpl
7219
7227
  }) {
7220
7228
  const [messages, setMessages] = React4.useState([]);
@@ -7248,6 +7256,7 @@ function useSemanticBuilder({
7248
7256
  resolveSocketUrlRef.current = resolveSocketUrl;
7249
7257
  }, [resolveSocketUrl]);
7250
7258
  React4.useEffect(() => {
7259
+ if (!seedWelcomeMessage) return;
7251
7260
  const hasContentBrief = !!contentBrief;
7252
7261
  const content = buildWelcomeMessage?.({ pageName, hasContentBrief }) ?? (hasContentBrief ? `Connected to ${pageName}. The page brief is loaded and ready. Describe the page you want and I'll stream back layout guidance and design reasoning.` : `Connected to ${pageName}. There is no saved content brief yet, so I'll work from the current page structure and brand context.`);
7253
7262
  setMessages([
@@ -7258,7 +7267,7 @@ function useSemanticBuilder({
7258
7267
  createdAt: Date.now()
7259
7268
  }
7260
7269
  ]);
7261
- }, [contentBrief, pageName, pageSlug]);
7270
+ }, [contentBrief, pageName, pageSlug, seedWelcomeMessage]);
7262
7271
  const handleEnvelope = React4.useCallback((envelope) => {
7263
7272
  switch (envelope.type) {
7264
7273
  case "connection_ready":
@@ -7470,6 +7479,14 @@ function useSemanticBuilder({
7470
7479
  const retry = React4.useCallback(() => {
7471
7480
  clientRef.current?.retry();
7472
7481
  }, []);
7482
+ const reset = React4.useCallback(() => {
7483
+ pendingHiddenRequestsRef.current = 0;
7484
+ hiddenAssistantMessageIdsRef.current.clear();
7485
+ clientRef.current?.close();
7486
+ setConnectionState("idle");
7487
+ setConnectionError(null);
7488
+ setMessages([]);
7489
+ }, []);
7473
7490
  const isConnected = connectionState === "ready" || connectionState === "streaming";
7474
7491
  const isStreaming = connectionState === "streaming";
7475
7492
  const statusLabel = React4.useMemo(() => {
@@ -7496,7 +7513,8 @@ function useSemanticBuilder({
7496
7513
  isConnected,
7497
7514
  isStreaming,
7498
7515
  sendMessage,
7499
- retry
7516
+ retry,
7517
+ reset
7500
7518
  };
7501
7519
  }
7502
7520
  var ScrollArea = React4__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
@@ -7717,10 +7735,58 @@ function ReportView({ report, className }) {
7717
7735
  ))
7718
7736
  ] });
7719
7737
  }
7738
+ function ConfirmationPanel({
7739
+ title = "Proposed plan",
7740
+ summary,
7741
+ body,
7742
+ markdown = true,
7743
+ icon,
7744
+ actions,
7745
+ onAction,
7746
+ ariaLabel,
7747
+ className
7748
+ }) {
7749
+ const hasBody = body !== void 0 && body !== null && body !== "";
7750
+ return /* @__PURE__ */ jsxRuntime.jsxs(
7751
+ react.motion.section,
7752
+ {
7753
+ initial: { opacity: 0, y: 6 },
7754
+ animate: { opacity: 1, y: 0 },
7755
+ transition: { duration: 0.2 },
7756
+ "aria-label": ariaLabel ?? title,
7757
+ className: cn(
7758
+ "flex w-full min-w-0 flex-col rounded-lg border bg-card p-4",
7759
+ className
7760
+ ),
7761
+ children: [
7762
+ /* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex items-center gap-2", children: [
7763
+ /* @__PURE__ */ jsxRuntime.jsx("span", { className: "flex size-6 shrink-0 items-center justify-center rounded-md bg-muted/60 text-muted-foreground", children: icon ?? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ClipboardListIcon, { className: "size-3.5" }) }),
7764
+ /* @__PURE__ */ jsxRuntime.jsx("h4", { className: "min-w-0 flex-1 truncate font-medium text-sm", children: title }),
7765
+ summary && /* @__PURE__ */ jsxRuntime.jsx(Badge, { variant: "secondary", className: "shrink-0 text-[10px] font-normal", children: summary })
7766
+ ] }),
7767
+ hasBody && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-2 min-w-0", children: typeof body === "string" ? /* @__PURE__ */ jsxRuntime.jsx(MessageContent, { markdown, children: body }) : body }),
7768
+ actions && actions.length > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "mt-3 flex flex-wrap gap-2", children: actions.map((action, index) => /* @__PURE__ */ jsxRuntime.jsx(
7769
+ Button,
7770
+ {
7771
+ type: "button",
7772
+ size: "sm",
7773
+ variant: action.variant ?? (index === 0 ? "default" : "outline"),
7774
+ disabled: action.disabled || action.busy,
7775
+ "aria-busy": action.busy || void 0,
7776
+ onClick: () => onAction?.(action.id),
7777
+ children: action.label
7778
+ },
7779
+ action.id
7780
+ )) })
7781
+ ]
7782
+ }
7783
+ );
7784
+ }
7720
7785
  function MessageList({
7721
7786
  messages,
7722
7787
  showAvatars = true,
7723
7788
  renderMessage,
7789
+ onConfirmAction,
7724
7790
  className
7725
7791
  }) {
7726
7792
  return /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("flex flex-col gap-4", className), children: messages.map((message) => {
@@ -7737,7 +7803,18 @@ function MessageList({
7737
7803
  hasSteps && /* @__PURE__ */ jsxRuntime.jsx(MessageWithSteps, { steps: message.steps }),
7738
7804
  message.content && /* @__PURE__ */ jsxRuntime.jsx(MessageBubble, { role: message.role, children: /* @__PURE__ */ jsxRuntime.jsx(MessageContent, { children: message.content }) }),
7739
7805
  hasAttachments && /* @__PURE__ */ jsxRuntime.jsx(MessageWithAttachments, { attachments: message.attachments }),
7740
- message.data && /* @__PURE__ */ jsxRuntime.jsx(DataPayloadView, { payload: message.data })
7806
+ message.data && /* @__PURE__ */ jsxRuntime.jsx(DataPayloadView, { payload: message.data }),
7807
+ message.confirmation && /* @__PURE__ */ jsxRuntime.jsx(
7808
+ ConfirmationPanel,
7809
+ {
7810
+ title: message.confirmation.title,
7811
+ summary: message.confirmation.summary,
7812
+ body: message.confirmation.body,
7813
+ markdown: message.confirmation.markdown,
7814
+ actions: message.confirmation.actions,
7815
+ onAction: (actionId) => onConfirmAction?.(message.id, actionId)
7816
+ }
7817
+ )
7741
7818
  ] })
7742
7819
  ] }, message.id);
7743
7820
  }) });
@@ -7941,6 +8018,54 @@ function FullBleedSurface({
7941
8018
  }
7942
8019
  );
7943
8020
  }
8021
+ function NativeSurface({
8022
+ children,
8023
+ input,
8024
+ title,
8025
+ subtitle,
8026
+ icon,
8027
+ headerActions,
8028
+ suggestions,
8029
+ footer,
8030
+ isLoading = false,
8031
+ autoScroll = true,
8032
+ className,
8033
+ contentClassName
8034
+ }) {
8035
+ const scrollRef = React4.useRef(null);
8036
+ React4.useEffect(() => {
8037
+ if (autoScroll && scrollRef.current) {
8038
+ scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
8039
+ }
8040
+ }, [children, isLoading, autoScroll]);
8041
+ const showHeader = !!title || !!headerActions || !!icon;
8042
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex h-full min-h-0 flex-col", className), children: [
8043
+ showHeader && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [
8044
+ /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
8045
+ icon,
8046
+ (title || subtitle) && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
8047
+ title && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-sm", children: title }),
8048
+ subtitle && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-muted-foreground text-xs", children: subtitle })
8049
+ ] })
8050
+ ] }),
8051
+ headerActions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-2", children: headerActions })
8052
+ ] }),
8053
+ /* @__PURE__ */ jsxRuntime.jsx(
8054
+ "div",
8055
+ {
8056
+ ref: scrollRef,
8057
+ className: cn("min-h-0 flex-1 overflow-y-auto", contentClassName),
8058
+ children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 p-4", children: [
8059
+ children,
8060
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx(TypingIndicator, {})
8061
+ ] })
8062
+ }
8063
+ ),
8064
+ suggestions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t px-4 py-2", children: suggestions }),
8065
+ input,
8066
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t px-4 py-1.5", children: footer })
8067
+ ] });
8068
+ }
7944
8069
  function AgentSurface({
7945
8070
  mode,
7946
8071
  messages,
@@ -7958,6 +8083,7 @@ function AgentSurface({
7958
8083
  showAvatars = true,
7959
8084
  renderMessage,
7960
8085
  onFeedback,
8086
+ onConfirmAction,
7961
8087
  report,
7962
8088
  dataPanel,
7963
8089
  isOpen = true,
@@ -7974,7 +8100,8 @@ function AgentSurface({
7974
8100
  messages,
7975
8101
  showAvatars,
7976
8102
  renderMessage,
7977
- onFeedback
8103
+ onFeedback,
8104
+ onConfirmAction
7978
8105
  }
7979
8106
  );
7980
8107
  const resolvedInput = input ?? (onInputChange && onSubmit !== void 0 ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "border-t p-2", children: /* @__PURE__ */ jsxRuntime.jsx(
@@ -8062,6 +8189,21 @@ function AgentSurface({
8062
8189
  children: conversation
8063
8190
  }
8064
8191
  );
8192
+ case "native":
8193
+ return /* @__PURE__ */ jsxRuntime.jsx(
8194
+ NativeSurface,
8195
+ {
8196
+ title,
8197
+ subtitle,
8198
+ icon,
8199
+ headerActions,
8200
+ input: resolvedInput,
8201
+ suggestions,
8202
+ isLoading,
8203
+ className,
8204
+ children: conversation
8205
+ }
8206
+ );
8065
8207
  case "panel":
8066
8208
  default:
8067
8209
  return /* @__PURE__ */ jsxRuntime.jsx(
@@ -8080,8 +8222,340 @@ function AgentSurface({
8080
8222
  );
8081
8223
  }
8082
8224
  }
8225
+ var NativeAgentContext = React4.createContext(
8226
+ null
8227
+ );
8228
+ function useNativeAgent() {
8229
+ const ctx = React4.useContext(NativeAgentContext);
8230
+ if (!ctx) {
8231
+ throw new Error(
8232
+ "useNativeAgent must be used within a <NativeAgentProvider>."
8233
+ );
8234
+ }
8235
+ return ctx;
8236
+ }
8237
+ function useNativeAgentOptional() {
8238
+ return React4.useContext(NativeAgentContext);
8239
+ }
8240
+ var EMPTY_BLOCKS = [];
8241
+ var REASONING_STATUS = {
8242
+ active: "active",
8243
+ complete: "complete"
8244
+ };
8245
+ function toAgentMessage(message) {
8246
+ const reasoning = message.thinking ? [
8247
+ {
8248
+ id: `${message.id}__thinking`,
8249
+ label: "Thinking",
8250
+ content: message.thinking,
8251
+ status: message.streaming ? REASONING_STATUS.active : REASONING_STATUS.complete
8252
+ }
8253
+ ] : void 0;
8254
+ return {
8255
+ id: message.id,
8256
+ role: message.role,
8257
+ content: message.content,
8258
+ timestamp: new Date(message.createdAt),
8259
+ reasoning
8260
+ };
8261
+ }
8262
+ function deriveStatus(connectionState) {
8263
+ switch (connectionState) {
8264
+ case "streaming":
8265
+ return "busy";
8266
+ case "ready":
8267
+ return "online";
8268
+ case "connecting":
8269
+ return "away";
8270
+ default:
8271
+ return "offline";
8272
+ }
8273
+ }
8274
+ function NativeAgentProvider({
8275
+ children,
8276
+ socketUrl,
8277
+ resolveSocketUrl,
8278
+ websiteId,
8279
+ pageCategoryId,
8280
+ pageName = "",
8281
+ pageSlug,
8282
+ blocks,
8283
+ contentBrief,
8284
+ onGeneratedBlocks,
8285
+ webSocketImpl,
8286
+ connectionStrategy = "lazy",
8287
+ seedWelcomeMessage = false,
8288
+ onError,
8289
+ onActivate
8290
+ }) {
8291
+ const [enabled, setEnabled] = React4.useState(connectionStrategy === "eager");
8292
+ const [isActive, setIsActive] = React4.useState(false);
8293
+ const [input, setInput] = React4.useState("");
8294
+ const [pendingCount, setPendingCount] = React4.useState(0);
8295
+ const [optimistic, setOptimistic] = React4.useState([]);
8296
+ const blocksValue = blocks ?? EMPTY_BLOCKS;
8297
+ const {
8298
+ messages: builderMessages,
8299
+ connectionState,
8300
+ connectionError,
8301
+ statusLabel,
8302
+ isConnected,
8303
+ isStreaming,
8304
+ sendMessage,
8305
+ retry,
8306
+ reset: resetSession
8307
+ } = useSemanticBuilder({
8308
+ socketUrl,
8309
+ resolveSocketUrl,
8310
+ websiteId,
8311
+ pageCategoryId,
8312
+ pageName,
8313
+ pageSlug,
8314
+ blocks: blocksValue,
8315
+ contentBrief,
8316
+ enabled,
8317
+ onGeneratedBlocks,
8318
+ webSocketImpl,
8319
+ seedWelcomeMessage
8320
+ });
8321
+ const pendingPromptsRef = React4.useRef([]);
8322
+ const optimisticSeqRef = React4.useRef(0);
8323
+ const onActivateRef = React4.useRef(onActivate);
8324
+ const onErrorRef = React4.useRef(onError);
8325
+ React4.useEffect(() => {
8326
+ onActivateRef.current = onActivate;
8327
+ }, [onActivate]);
8328
+ React4.useEffect(() => {
8329
+ onErrorRef.current = onError;
8330
+ }, [onError]);
8331
+ React4.useEffect(() => {
8332
+ if (connectionError) onErrorRef.current?.(connectionError);
8333
+ }, [connectionError]);
8334
+ const markActive = React4.useCallback(() => {
8335
+ setIsActive((prev) => {
8336
+ if (!prev) onActivateRef.current?.();
8337
+ return true;
8338
+ });
8339
+ }, []);
8340
+ React4.useEffect(() => {
8341
+ if (connectionState !== "ready" || pendingPromptsRef.current.length === 0) {
8342
+ return;
8343
+ }
8344
+ const next = pendingPromptsRef.current.shift();
8345
+ if (next === void 0) return;
8346
+ setPendingCount(pendingPromptsRef.current.length);
8347
+ setOptimistic((prev) => prev.slice(1));
8348
+ void sendMessage(next).then((ok) => {
8349
+ if (!ok) {
8350
+ pendingPromptsRef.current.unshift(next);
8351
+ setPendingCount(pendingPromptsRef.current.length);
8352
+ }
8353
+ });
8354
+ }, [connectionState, pendingCount, sendMessage]);
8355
+ const submit = React4.useCallback(
8356
+ (content) => {
8357
+ const text = (content ?? input).trim();
8358
+ if (!text) return;
8359
+ markActive();
8360
+ setEnabled(true);
8361
+ setInput("");
8362
+ pendingPromptsRef.current.push(text);
8363
+ setPendingCount(pendingPromptsRef.current.length);
8364
+ const id = `native-pending-${optimisticSeqRef.current}`;
8365
+ optimisticSeqRef.current += 1;
8366
+ setOptimistic((prev) => [
8367
+ ...prev,
8368
+ { id, role: "user", content: text, timestamp: /* @__PURE__ */ new Date() }
8369
+ ]);
8370
+ },
8371
+ [input, markActive]
8372
+ );
8373
+ const activate = React4.useCallback(() => {
8374
+ markActive();
8375
+ setEnabled(true);
8376
+ }, [markActive]);
8377
+ const reset = React4.useCallback(() => {
8378
+ pendingPromptsRef.current = [];
8379
+ setPendingCount(0);
8380
+ setOptimistic([]);
8381
+ setIsActive(false);
8382
+ setInput("");
8383
+ setEnabled(false);
8384
+ resetSession();
8385
+ }, [resetSession]);
8386
+ const messages = React4.useMemo(
8387
+ () => [...builderMessages.map(toAgentMessage), ...optimistic],
8388
+ [builderMessages, optimistic]
8389
+ );
8390
+ const isResponding = isStreaming || pendingCount > 0 && !connectionError && connectionState !== "error" && connectionState !== "requires_shared_domain";
8391
+ const status = deriveStatus(connectionState);
8392
+ const value = React4.useMemo(
8393
+ () => ({
8394
+ messages,
8395
+ isActive,
8396
+ isConnected,
8397
+ isResponding,
8398
+ isStreaming,
8399
+ connectionState,
8400
+ statusLabel,
8401
+ status,
8402
+ error: connectionError,
8403
+ input,
8404
+ setInput,
8405
+ submit,
8406
+ activate,
8407
+ reset,
8408
+ retry
8409
+ }),
8410
+ [
8411
+ messages,
8412
+ isActive,
8413
+ isConnected,
8414
+ isResponding,
8415
+ isStreaming,
8416
+ connectionState,
8417
+ statusLabel,
8418
+ status,
8419
+ connectionError,
8420
+ input,
8421
+ submit,
8422
+ activate,
8423
+ reset,
8424
+ retry
8425
+ ]
8426
+ );
8427
+ return /* @__PURE__ */ jsxRuntime.jsx(NativeAgentContext.Provider, { value, children });
8428
+ }
8429
+ var noop = () => {
8430
+ };
8431
+ function warnDev(message) {
8432
+ const env = globalThis.process?.env;
8433
+ if (env && env.NODE_ENV !== "production") {
8434
+ console.warn(`[AgentComposer] ${message}`);
8435
+ }
8436
+ }
8437
+ function AgentComposer({
8438
+ value: valueProp,
8439
+ onChange,
8440
+ onSubmit,
8441
+ loading: loadingProp,
8442
+ disabled: disabledProp,
8443
+ placeholder = "Ask anything\u2026",
8444
+ variant = "default",
8445
+ bare = false,
8446
+ suggestions,
8447
+ footer,
8448
+ leftActions,
8449
+ rightActions,
8450
+ autoFocus = false,
8451
+ className,
8452
+ inputClassName
8453
+ }) {
8454
+ const ctx = useNativeAgentOptional();
8455
+ const [draft, setDraft] = React4.useState("");
8456
+ const propsControlEditing = valueProp !== void 0 || onChange !== void 0;
8457
+ const value = propsControlEditing ? valueProp ?? "" : ctx ? ctx.input : draft;
8458
+ const handleChange = propsControlEditing ? onChange ?? noop : ctx ? ctx.setInput : setDraft;
8459
+ const loading = loadingProp ?? ctx?.isResponding ?? false;
8460
+ const disabled = disabledProp ?? false;
8461
+ const handleSubmit = React4.useCallback(() => {
8462
+ if (onSubmit) {
8463
+ onSubmit(value);
8464
+ return;
8465
+ }
8466
+ if (!propsControlEditing && ctx) {
8467
+ ctx.submit();
8468
+ return;
8469
+ }
8470
+ warnDev(
8471
+ "submit was ignored: provide `onSubmit`, or render inside a <NativeAgentProvider>."
8472
+ );
8473
+ }, [onSubmit, propsControlEditing, ctx, value]);
8474
+ return /* @__PURE__ */ jsxRuntime.jsxs(
8475
+ "div",
8476
+ {
8477
+ className: cn(
8478
+ !bare && "rounded-2xl border bg-background shadow-sm",
8479
+ className
8480
+ ),
8481
+ children: [
8482
+ suggestions && /* @__PURE__ */ jsxRuntime.jsx("div", { className: cn("px-3", bare ? "pb-2" : "pt-3"), children: suggestions }),
8483
+ /* @__PURE__ */ jsxRuntime.jsx(
8484
+ PromptInput,
8485
+ {
8486
+ value,
8487
+ onChange: handleChange,
8488
+ onSubmit: handleSubmit,
8489
+ placeholder,
8490
+ loading,
8491
+ disabled,
8492
+ variant,
8493
+ autoFocus,
8494
+ leftActions,
8495
+ rightActions,
8496
+ inputClassName
8497
+ }
8498
+ ),
8499
+ footer && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-4 pb-2 text-muted-foreground text-xs", children: footer })
8500
+ ]
8501
+ }
8502
+ );
8503
+ }
8504
+ var EMPTY_MESSAGES = [];
8505
+ function AgentConversation({
8506
+ messages: messagesProp,
8507
+ isLoading: isLoadingProp,
8508
+ header,
8509
+ emptyState,
8510
+ showAvatars = true,
8511
+ renderMessage,
8512
+ onFeedback,
8513
+ onConfirmAction,
8514
+ autoScroll = true,
8515
+ className,
8516
+ contentClassName
8517
+ }) {
8518
+ const ctx = useNativeAgentOptional();
8519
+ const messages = React4.useMemo(
8520
+ () => messagesProp ?? ctx?.messages ?? EMPTY_MESSAGES,
8521
+ [messagesProp, ctx?.messages]
8522
+ );
8523
+ const isLoading = isLoadingProp ?? ctx?.isResponding ?? false;
8524
+ const scrollRef = React4.useRef(null);
8525
+ React4.useEffect(() => {
8526
+ if (autoScroll && scrollRef.current) {
8527
+ scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
8528
+ }
8529
+ }, [messages, isLoading, autoScroll]);
8530
+ const showEmptyState = messages.length === 0 && !isLoading && !!emptyState;
8531
+ return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: cn("flex h-full min-h-0 flex-col", className), children: [
8532
+ header,
8533
+ /* @__PURE__ */ jsxRuntime.jsx(
8534
+ "div",
8535
+ {
8536
+ ref: scrollRef,
8537
+ className: cn("min-h-0 flex-1 overflow-y-auto", contentClassName),
8538
+ children: showEmptyState ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center p-6", children: emptyState }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col gap-4 p-4", children: [
8539
+ /* @__PURE__ */ jsxRuntime.jsx(
8540
+ MessageList,
8541
+ {
8542
+ messages,
8543
+ showAvatars,
8544
+ renderMessage,
8545
+ onFeedback,
8546
+ onConfirmAction
8547
+ }
8548
+ ),
8549
+ isLoading && /* @__PURE__ */ jsxRuntime.jsx(TypingIndicator, {})
8550
+ ] })
8551
+ }
8552
+ )
8553
+ ] });
8554
+ }
8083
8555
 
8084
8556
  exports.AgentAvatar = AgentAvatar;
8557
+ exports.AgentComposer = AgentComposer;
8558
+ exports.AgentConversation = AgentConversation;
8085
8559
  exports.AgentHandoff = AgentHandoff;
8086
8560
  exports.AgentProvider = AgentProvider;
8087
8561
  exports.AgentSurface = AgentSurface;
@@ -8097,6 +8571,7 @@ exports.ChatPanel = ChatPanel;
8097
8571
  exports.Collapsible = Collapsible;
8098
8572
  exports.CollapsibleContent = CollapsibleContent2;
8099
8573
  exports.CollapsibleTrigger = CollapsibleTrigger2;
8574
+ exports.ConfirmationPanel = ConfirmationPanel;
8100
8575
  exports.ControlGrid = ControlGrid;
8101
8576
  exports.ConversationAnalytics = ConversationAnalytics;
8102
8577
  exports.ConversationArtifact = ConversationArtifact;
@@ -8117,6 +8592,8 @@ exports.MediaEditorCanvas = MediaEditorCanvas;
8117
8592
  exports.MediaGallery = MediaGallery;
8118
8593
  exports.MessageActions = MessageActions;
8119
8594
  exports.MessageBubble = MessageBubble;
8595
+ exports.MessageContainer = MessageContainer;
8596
+ exports.MessageContent = MessageContent;
8120
8597
  exports.MessageList = MessageList;
8121
8598
  exports.MessageWithAttachments = MessageWithAttachments;
8122
8599
  exports.MessageWithFeedback = MessageWithFeedback;
@@ -8125,6 +8602,8 @@ exports.MessageWithSteps = MessageWithSteps;
8125
8602
  exports.MetricsGrid = MetricsGrid;
8126
8603
  exports.MobileShell = MobileShell;
8127
8604
  exports.MultimodalInput = MultimodalInput;
8605
+ exports.NativeAgentProvider = NativeAgentProvider;
8606
+ exports.NativeSurface = NativeSurface;
8128
8607
  exports.OnboardingWizard = OnboardingWizard;
8129
8608
  exports.OptionCards = OptionCards;
8130
8609
  exports.OverlayModal = OverlayModal;
@@ -8193,6 +8672,8 @@ exports.useAgentBackend = useAgentBackend;
8193
8672
  exports.useAgentInput = useAgentInput;
8194
8673
  exports.useAgentLayout = useAgentLayout;
8195
8674
  exports.useAgentMessages = useAgentMessages;
8675
+ exports.useNativeAgent = useNativeAgent;
8676
+ exports.useNativeAgentOptional = useNativeAgentOptional;
8196
8677
  exports.useSemanticBuilder = useSemanticBuilder;
8197
8678
  //# sourceMappingURL=index.cjs.map
8198
8679
  //# sourceMappingURL=index.cjs.map