@page-speed/agent-everywhere 0.4.0 → 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.js CHANGED
@@ -7196,6 +7196,7 @@ function useSemanticBuilder({
7196
7196
  onGeneratedBlocks,
7197
7197
  onUndoRequest,
7198
7198
  buildWelcomeMessage,
7199
+ seedWelcomeMessage = true,
7199
7200
  webSocketImpl
7200
7201
  }) {
7201
7202
  const [messages, setMessages] = useState([]);
@@ -7229,6 +7230,7 @@ function useSemanticBuilder({
7229
7230
  resolveSocketUrlRef.current = resolveSocketUrl;
7230
7231
  }, [resolveSocketUrl]);
7231
7232
  useEffect(() => {
7233
+ if (!seedWelcomeMessage) return;
7232
7234
  const hasContentBrief = !!contentBrief;
7233
7235
  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.`);
7234
7236
  setMessages([
@@ -7239,7 +7241,7 @@ function useSemanticBuilder({
7239
7241
  createdAt: Date.now()
7240
7242
  }
7241
7243
  ]);
7242
- }, [contentBrief, pageName, pageSlug]);
7244
+ }, [contentBrief, pageName, pageSlug, seedWelcomeMessage]);
7243
7245
  const handleEnvelope = useCallback((envelope) => {
7244
7246
  switch (envelope.type) {
7245
7247
  case "connection_ready":
@@ -7451,6 +7453,14 @@ function useSemanticBuilder({
7451
7453
  const retry = useCallback(() => {
7452
7454
  clientRef.current?.retry();
7453
7455
  }, []);
7456
+ const reset = useCallback(() => {
7457
+ pendingHiddenRequestsRef.current = 0;
7458
+ hiddenAssistantMessageIdsRef.current.clear();
7459
+ clientRef.current?.close();
7460
+ setConnectionState("idle");
7461
+ setConnectionError(null);
7462
+ setMessages([]);
7463
+ }, []);
7454
7464
  const isConnected = connectionState === "ready" || connectionState === "streaming";
7455
7465
  const isStreaming = connectionState === "streaming";
7456
7466
  const statusLabel = useMemo(() => {
@@ -7477,7 +7487,8 @@ function useSemanticBuilder({
7477
7487
  isConnected,
7478
7488
  isStreaming,
7479
7489
  sendMessage,
7480
- retry
7490
+ retry,
7491
+ reset
7481
7492
  };
7482
7493
  }
7483
7494
  var ScrollArea = React4.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxs(
@@ -7981,6 +7992,54 @@ function FullBleedSurface({
7981
7992
  }
7982
7993
  );
7983
7994
  }
7995
+ function NativeSurface({
7996
+ children,
7997
+ input,
7998
+ title,
7999
+ subtitle,
8000
+ icon,
8001
+ headerActions,
8002
+ suggestions,
8003
+ footer,
8004
+ isLoading = false,
8005
+ autoScroll = true,
8006
+ className,
8007
+ contentClassName
8008
+ }) {
8009
+ const scrollRef = useRef(null);
8010
+ useEffect(() => {
8011
+ if (autoScroll && scrollRef.current) {
8012
+ scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
8013
+ }
8014
+ }, [children, isLoading, autoScroll]);
8015
+ const showHeader = !!title || !!headerActions || !!icon;
8016
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full min-h-0 flex-col", className), children: [
8017
+ showHeader && /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between border-b px-4 py-3", children: [
8018
+ /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
8019
+ icon,
8020
+ (title || subtitle) && /* @__PURE__ */ jsxs("div", { children: [
8021
+ title && /* @__PURE__ */ jsx("span", { className: "font-medium text-sm", children: title }),
8022
+ subtitle && /* @__PURE__ */ jsx("p", { className: "text-muted-foreground text-xs", children: subtitle })
8023
+ ] })
8024
+ ] }),
8025
+ headerActions && /* @__PURE__ */ jsx("div", { className: "flex items-center gap-2", children: headerActions })
8026
+ ] }),
8027
+ /* @__PURE__ */ jsx(
8028
+ "div",
8029
+ {
8030
+ ref: scrollRef,
8031
+ className: cn("min-h-0 flex-1 overflow-y-auto", contentClassName),
8032
+ children: /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 p-4", children: [
8033
+ children,
8034
+ isLoading && /* @__PURE__ */ jsx(TypingIndicator, {})
8035
+ ] })
8036
+ }
8037
+ ),
8038
+ suggestions && /* @__PURE__ */ jsx("div", { className: "border-t px-4 py-2", children: suggestions }),
8039
+ input,
8040
+ footer && /* @__PURE__ */ jsx("div", { className: "border-t px-4 py-1.5", children: footer })
8041
+ ] });
8042
+ }
7984
8043
  function AgentSurface({
7985
8044
  mode,
7986
8045
  messages,
@@ -8104,6 +8163,21 @@ function AgentSurface({
8104
8163
  children: conversation
8105
8164
  }
8106
8165
  );
8166
+ case "native":
8167
+ return /* @__PURE__ */ jsx(
8168
+ NativeSurface,
8169
+ {
8170
+ title,
8171
+ subtitle,
8172
+ icon,
8173
+ headerActions,
8174
+ input: resolvedInput,
8175
+ suggestions,
8176
+ isLoading,
8177
+ className,
8178
+ children: conversation
8179
+ }
8180
+ );
8107
8181
  case "panel":
8108
8182
  default:
8109
8183
  return /* @__PURE__ */ jsx(
@@ -8122,7 +8196,337 @@ function AgentSurface({
8122
8196
  );
8123
8197
  }
8124
8198
  }
8199
+ var NativeAgentContext = createContext(
8200
+ null
8201
+ );
8202
+ function useNativeAgent() {
8203
+ const ctx = useContext(NativeAgentContext);
8204
+ if (!ctx) {
8205
+ throw new Error(
8206
+ "useNativeAgent must be used within a <NativeAgentProvider>."
8207
+ );
8208
+ }
8209
+ return ctx;
8210
+ }
8211
+ function useNativeAgentOptional() {
8212
+ return useContext(NativeAgentContext);
8213
+ }
8214
+ var EMPTY_BLOCKS = [];
8215
+ var REASONING_STATUS = {
8216
+ active: "active",
8217
+ complete: "complete"
8218
+ };
8219
+ function toAgentMessage(message) {
8220
+ const reasoning = message.thinking ? [
8221
+ {
8222
+ id: `${message.id}__thinking`,
8223
+ label: "Thinking",
8224
+ content: message.thinking,
8225
+ status: message.streaming ? REASONING_STATUS.active : REASONING_STATUS.complete
8226
+ }
8227
+ ] : void 0;
8228
+ return {
8229
+ id: message.id,
8230
+ role: message.role,
8231
+ content: message.content,
8232
+ timestamp: new Date(message.createdAt),
8233
+ reasoning
8234
+ };
8235
+ }
8236
+ function deriveStatus(connectionState) {
8237
+ switch (connectionState) {
8238
+ case "streaming":
8239
+ return "busy";
8240
+ case "ready":
8241
+ return "online";
8242
+ case "connecting":
8243
+ return "away";
8244
+ default:
8245
+ return "offline";
8246
+ }
8247
+ }
8248
+ function NativeAgentProvider({
8249
+ children,
8250
+ socketUrl,
8251
+ resolveSocketUrl,
8252
+ websiteId,
8253
+ pageCategoryId,
8254
+ pageName = "",
8255
+ pageSlug,
8256
+ blocks,
8257
+ contentBrief,
8258
+ onGeneratedBlocks,
8259
+ webSocketImpl,
8260
+ connectionStrategy = "lazy",
8261
+ seedWelcomeMessage = false,
8262
+ onError,
8263
+ onActivate
8264
+ }) {
8265
+ const [enabled, setEnabled] = useState(connectionStrategy === "eager");
8266
+ const [isActive, setIsActive] = useState(false);
8267
+ const [input, setInput] = useState("");
8268
+ const [pendingCount, setPendingCount] = useState(0);
8269
+ const [optimistic, setOptimistic] = useState([]);
8270
+ const blocksValue = blocks ?? EMPTY_BLOCKS;
8271
+ const {
8272
+ messages: builderMessages,
8273
+ connectionState,
8274
+ connectionError,
8275
+ statusLabel,
8276
+ isConnected,
8277
+ isStreaming,
8278
+ sendMessage,
8279
+ retry,
8280
+ reset: resetSession
8281
+ } = useSemanticBuilder({
8282
+ socketUrl,
8283
+ resolveSocketUrl,
8284
+ websiteId,
8285
+ pageCategoryId,
8286
+ pageName,
8287
+ pageSlug,
8288
+ blocks: blocksValue,
8289
+ contentBrief,
8290
+ enabled,
8291
+ onGeneratedBlocks,
8292
+ webSocketImpl,
8293
+ seedWelcomeMessage
8294
+ });
8295
+ const pendingPromptsRef = useRef([]);
8296
+ const optimisticSeqRef = useRef(0);
8297
+ const onActivateRef = useRef(onActivate);
8298
+ const onErrorRef = useRef(onError);
8299
+ useEffect(() => {
8300
+ onActivateRef.current = onActivate;
8301
+ }, [onActivate]);
8302
+ useEffect(() => {
8303
+ onErrorRef.current = onError;
8304
+ }, [onError]);
8305
+ useEffect(() => {
8306
+ if (connectionError) onErrorRef.current?.(connectionError);
8307
+ }, [connectionError]);
8308
+ const markActive = useCallback(() => {
8309
+ setIsActive((prev) => {
8310
+ if (!prev) onActivateRef.current?.();
8311
+ return true;
8312
+ });
8313
+ }, []);
8314
+ useEffect(() => {
8315
+ if (connectionState !== "ready" || pendingPromptsRef.current.length === 0) {
8316
+ return;
8317
+ }
8318
+ const next = pendingPromptsRef.current.shift();
8319
+ if (next === void 0) return;
8320
+ setPendingCount(pendingPromptsRef.current.length);
8321
+ setOptimistic((prev) => prev.slice(1));
8322
+ void sendMessage(next).then((ok) => {
8323
+ if (!ok) {
8324
+ pendingPromptsRef.current.unshift(next);
8325
+ setPendingCount(pendingPromptsRef.current.length);
8326
+ }
8327
+ });
8328
+ }, [connectionState, pendingCount, sendMessage]);
8329
+ const submit = useCallback(
8330
+ (content) => {
8331
+ const text = (content ?? input).trim();
8332
+ if (!text) return;
8333
+ markActive();
8334
+ setEnabled(true);
8335
+ setInput("");
8336
+ pendingPromptsRef.current.push(text);
8337
+ setPendingCount(pendingPromptsRef.current.length);
8338
+ const id = `native-pending-${optimisticSeqRef.current}`;
8339
+ optimisticSeqRef.current += 1;
8340
+ setOptimistic((prev) => [
8341
+ ...prev,
8342
+ { id, role: "user", content: text, timestamp: /* @__PURE__ */ new Date() }
8343
+ ]);
8344
+ },
8345
+ [input, markActive]
8346
+ );
8347
+ const activate = useCallback(() => {
8348
+ markActive();
8349
+ setEnabled(true);
8350
+ }, [markActive]);
8351
+ const reset = useCallback(() => {
8352
+ pendingPromptsRef.current = [];
8353
+ setPendingCount(0);
8354
+ setOptimistic([]);
8355
+ setIsActive(false);
8356
+ setInput("");
8357
+ setEnabled(false);
8358
+ resetSession();
8359
+ }, [resetSession]);
8360
+ const messages = useMemo(
8361
+ () => [...builderMessages.map(toAgentMessage), ...optimistic],
8362
+ [builderMessages, optimistic]
8363
+ );
8364
+ const isResponding = isStreaming || pendingCount > 0 && !connectionError && connectionState !== "error" && connectionState !== "requires_shared_domain";
8365
+ const status = deriveStatus(connectionState);
8366
+ const value = useMemo(
8367
+ () => ({
8368
+ messages,
8369
+ isActive,
8370
+ isConnected,
8371
+ isResponding,
8372
+ isStreaming,
8373
+ connectionState,
8374
+ statusLabel,
8375
+ status,
8376
+ error: connectionError,
8377
+ input,
8378
+ setInput,
8379
+ submit,
8380
+ activate,
8381
+ reset,
8382
+ retry
8383
+ }),
8384
+ [
8385
+ messages,
8386
+ isActive,
8387
+ isConnected,
8388
+ isResponding,
8389
+ isStreaming,
8390
+ connectionState,
8391
+ statusLabel,
8392
+ status,
8393
+ connectionError,
8394
+ input,
8395
+ submit,
8396
+ activate,
8397
+ reset,
8398
+ retry
8399
+ ]
8400
+ );
8401
+ return /* @__PURE__ */ jsx(NativeAgentContext.Provider, { value, children });
8402
+ }
8403
+ var noop = () => {
8404
+ };
8405
+ function warnDev(message) {
8406
+ const env = globalThis.process?.env;
8407
+ if (env && env.NODE_ENV !== "production") {
8408
+ console.warn(`[AgentComposer] ${message}`);
8409
+ }
8410
+ }
8411
+ function AgentComposer({
8412
+ value: valueProp,
8413
+ onChange,
8414
+ onSubmit,
8415
+ loading: loadingProp,
8416
+ disabled: disabledProp,
8417
+ placeholder = "Ask anything\u2026",
8418
+ variant = "default",
8419
+ bare = false,
8420
+ suggestions,
8421
+ footer,
8422
+ leftActions,
8423
+ rightActions,
8424
+ autoFocus = false,
8425
+ className,
8426
+ inputClassName
8427
+ }) {
8428
+ const ctx = useNativeAgentOptional();
8429
+ const [draft, setDraft] = useState("");
8430
+ const propsControlEditing = valueProp !== void 0 || onChange !== void 0;
8431
+ const value = propsControlEditing ? valueProp ?? "" : ctx ? ctx.input : draft;
8432
+ const handleChange = propsControlEditing ? onChange ?? noop : ctx ? ctx.setInput : setDraft;
8433
+ const loading = loadingProp ?? ctx?.isResponding ?? false;
8434
+ const disabled = disabledProp ?? false;
8435
+ const handleSubmit = useCallback(() => {
8436
+ if (onSubmit) {
8437
+ onSubmit(value);
8438
+ return;
8439
+ }
8440
+ if (!propsControlEditing && ctx) {
8441
+ ctx.submit();
8442
+ return;
8443
+ }
8444
+ warnDev(
8445
+ "submit was ignored: provide `onSubmit`, or render inside a <NativeAgentProvider>."
8446
+ );
8447
+ }, [onSubmit, propsControlEditing, ctx, value]);
8448
+ return /* @__PURE__ */ jsxs(
8449
+ "div",
8450
+ {
8451
+ className: cn(
8452
+ !bare && "rounded-2xl border bg-background shadow-sm",
8453
+ className
8454
+ ),
8455
+ children: [
8456
+ suggestions && /* @__PURE__ */ jsx("div", { className: cn("px-3", bare ? "pb-2" : "pt-3"), children: suggestions }),
8457
+ /* @__PURE__ */ jsx(
8458
+ PromptInput,
8459
+ {
8460
+ value,
8461
+ onChange: handleChange,
8462
+ onSubmit: handleSubmit,
8463
+ placeholder,
8464
+ loading,
8465
+ disabled,
8466
+ variant,
8467
+ autoFocus,
8468
+ leftActions,
8469
+ rightActions,
8470
+ inputClassName
8471
+ }
8472
+ ),
8473
+ footer && /* @__PURE__ */ jsx("div", { className: "px-4 pb-2 text-muted-foreground text-xs", children: footer })
8474
+ ]
8475
+ }
8476
+ );
8477
+ }
8478
+ var EMPTY_MESSAGES = [];
8479
+ function AgentConversation({
8480
+ messages: messagesProp,
8481
+ isLoading: isLoadingProp,
8482
+ header,
8483
+ emptyState,
8484
+ showAvatars = true,
8485
+ renderMessage,
8486
+ onFeedback,
8487
+ onConfirmAction,
8488
+ autoScroll = true,
8489
+ className,
8490
+ contentClassName
8491
+ }) {
8492
+ const ctx = useNativeAgentOptional();
8493
+ const messages = useMemo(
8494
+ () => messagesProp ?? ctx?.messages ?? EMPTY_MESSAGES,
8495
+ [messagesProp, ctx?.messages]
8496
+ );
8497
+ const isLoading = isLoadingProp ?? ctx?.isResponding ?? false;
8498
+ const scrollRef = useRef(null);
8499
+ useEffect(() => {
8500
+ if (autoScroll && scrollRef.current) {
8501
+ scrollRef.current.scrollTop = scrollRef.current.scrollHeight;
8502
+ }
8503
+ }, [messages, isLoading, autoScroll]);
8504
+ const showEmptyState = messages.length === 0 && !isLoading && !!emptyState;
8505
+ return /* @__PURE__ */ jsxs("div", { className: cn("flex h-full min-h-0 flex-col", className), children: [
8506
+ header,
8507
+ /* @__PURE__ */ jsx(
8508
+ "div",
8509
+ {
8510
+ ref: scrollRef,
8511
+ className: cn("min-h-0 flex-1 overflow-y-auto", contentClassName),
8512
+ children: showEmptyState ? /* @__PURE__ */ jsx("div", { className: "flex h-full items-center justify-center p-6", children: emptyState }) : /* @__PURE__ */ jsxs("div", { className: "flex flex-col gap-4 p-4", children: [
8513
+ /* @__PURE__ */ jsx(
8514
+ MessageList,
8515
+ {
8516
+ messages,
8517
+ showAvatars,
8518
+ renderMessage,
8519
+ onFeedback,
8520
+ onConfirmAction
8521
+ }
8522
+ ),
8523
+ isLoading && /* @__PURE__ */ jsx(TypingIndicator, {})
8524
+ ] })
8525
+ }
8526
+ )
8527
+ ] });
8528
+ }
8125
8529
 
8126
- export { AgentAvatar, AgentHandoff, AgentProvider, AgentSurface, AllocationBreakdown, AnalyticsDashboard, Avatar, AvatarFallback, AvatarImage, Badge, Button, ChartContainer, ChatPanel, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ConfirmationPanel, ControlGrid, ConversationAnalytics, ConversationArtifact, DataPayloadView, DataTable, DynamicRenderer, EntityCard, FileDropZone, FloatingWidget, FullBleedSurface, FullscreenDashboard, GuidedLessonFlow, ImageGenerator, InlineSuggestionsInput, Input, ListingFeed, MediaEditorCanvas, MediaGallery, MessageActions, MessageBubble, MessageContainer, MessageContent, MessageList, MessageWithAttachments, MessageWithFeedback, MessageWithReasoning, MessageWithSteps, MetricsGrid, MobileShell, MultimodalInput, OnboardingWizard, OptionCards, OverlayModal, PerformanceMetrics, PersonaSelector, Progress, ProgressTracker, PromptInput, PromptLibrary, QuickReplies, QuizCard, RecommendationCards, ReportView, ScheduleTimeline, ScrollArea, ScrollBar, SemanticBuilderSocketClient, SentimentDisplay, SettingsPanel, SlotRenderer, SplitView, StatusBadge, SystemMessage, TemplateSelector, Textarea, Timestamp, Tooltip4 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TypingIndicator, WritingAssistant, badgeVariants, buildSocketUrl, buttonVariants, calculatePercentage, cn, componentManifest, componentMap, componentRegistry, copyToClipboard, createMockBackend, debounce, delay, findComponentsByCapability, findComponentsByCategory, findComponentsBySurface, formatBytes, formatCurrency, formatNumber, formatRelativeTime, formatTime, generateId, getInitials, getManifestEntry, getSentimentBgColor, getSentimentColor, isBrowser, isInIframe, normalizeWebsiteId, parseTextWithBold, registerAllComponents, truncate, useAgent, useAgentBackend, useAgentInput, useAgentLayout, useAgentMessages, useSemanticBuilder };
8530
+ export { AgentAvatar, AgentComposer, AgentConversation, AgentHandoff, AgentProvider, AgentSurface, AllocationBreakdown, AnalyticsDashboard, Avatar, AvatarFallback, AvatarImage, Badge, Button, ChartContainer, ChatPanel, Collapsible, CollapsibleContent2 as CollapsibleContent, CollapsibleTrigger2 as CollapsibleTrigger, ConfirmationPanel, ControlGrid, ConversationAnalytics, ConversationArtifact, DataPayloadView, DataTable, DynamicRenderer, EntityCard, FileDropZone, FloatingWidget, FullBleedSurface, FullscreenDashboard, GuidedLessonFlow, ImageGenerator, InlineSuggestionsInput, Input, ListingFeed, MediaEditorCanvas, MediaGallery, MessageActions, MessageBubble, MessageContainer, MessageContent, MessageList, MessageWithAttachments, MessageWithFeedback, MessageWithReasoning, MessageWithSteps, MetricsGrid, MobileShell, MultimodalInput, NativeAgentProvider, NativeSurface, OnboardingWizard, OptionCards, OverlayModal, PerformanceMetrics, PersonaSelector, Progress, ProgressTracker, PromptInput, PromptLibrary, QuickReplies, QuizCard, RecommendationCards, ReportView, ScheduleTimeline, ScrollArea, ScrollBar, SemanticBuilderSocketClient, SentimentDisplay, SettingsPanel, SlotRenderer, SplitView, StatusBadge, SystemMessage, TemplateSelector, Textarea, Timestamp, Tooltip4 as Tooltip, TooltipContent, TooltipProvider, TooltipTrigger, TypingIndicator, WritingAssistant, badgeVariants, buildSocketUrl, buttonVariants, calculatePercentage, cn, componentManifest, componentMap, componentRegistry, copyToClipboard, createMockBackend, debounce, delay, findComponentsByCapability, findComponentsByCategory, findComponentsBySurface, formatBytes, formatCurrency, formatNumber, formatRelativeTime, formatTime, generateId, getInitials, getManifestEntry, getSentimentBgColor, getSentimentColor, isBrowser, isInIframe, normalizeWebsiteId, parseTextWithBold, registerAllComponents, truncate, useAgent, useAgentBackend, useAgentInput, useAgentLayout, useAgentMessages, useNativeAgent, useNativeAgentOptional, useSemanticBuilder };
8127
8531
  //# sourceMappingURL=index.js.map
8128
8532
  //# sourceMappingURL=index.js.map