@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/README.md +74 -2
- package/dist/index.cjs +412 -2
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +212 -3
- package/dist/index.d.ts +212 -3
- package/dist/index.js +407 -3
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -55,6 +55,7 @@ container. There are no per-surface forks of the conversation logic.
|
|
|
55
55
|
| `fullscreen` | `FullscreenDashboard` | Full-screen chat + report sidebar. |
|
|
56
56
|
| `split` | `SplitView` | Chat beside a live results/preview pane. |
|
|
57
57
|
| `mobile` | `MobileShell` | Full-height mobile-optimized layout. |
|
|
58
|
+
| `native` | `NativeSurface` | Host-placed, position-agnostic pieces — see [Native variant](#native-variant). |
|
|
58
59
|
|
|
59
60
|
```tsx
|
|
60
61
|
import { AgentSurface } from '@page-speed/agent-everywhere';
|
|
@@ -71,6 +72,75 @@ import { AgentSurface } from '@page-speed/agent-everywhere';
|
|
|
71
72
|
/>;
|
|
72
73
|
```
|
|
73
74
|
|
|
75
|
+
### Native variant
|
|
76
|
+
|
|
77
|
+
The `native` variant is unlike the other placements: it has **no opinion on
|
|
78
|
+
position**. The agent's composer and conversation renderer are native,
|
|
79
|
+
fully-customizable pieces the host places anywhere — a docked bottom bar, a pane,
|
|
80
|
+
a modal, a dashboard card — and styles itself. The two pieces work **disconnected
|
|
81
|
+
from each other**, and a provider lets them **share one live session even when
|
|
82
|
+
rendered in completely separate DOM regions**.
|
|
83
|
+
|
|
84
|
+
**Simple, controlled case** — one component you position yourself:
|
|
85
|
+
|
|
86
|
+
```tsx
|
|
87
|
+
import { AgentSurface } from '@page-speed/agent-everywhere';
|
|
88
|
+
|
|
89
|
+
<AgentSurface
|
|
90
|
+
mode="native"
|
|
91
|
+
messages={messages}
|
|
92
|
+
isLoading={isStreaming}
|
|
93
|
+
inputValue={draft}
|
|
94
|
+
onInputChange={setDraft}
|
|
95
|
+
onSubmit={() => send(draft)}
|
|
96
|
+
/>;
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
**Decoupled case** — one shared session feeding pieces in separate regions of the
|
|
100
|
+
page. The composer sits idle at the bottom; once the user submits, the host swaps
|
|
101
|
+
its own content for the conversation surface:
|
|
102
|
+
|
|
103
|
+
```tsx
|
|
104
|
+
import {
|
|
105
|
+
NativeAgentProvider,
|
|
106
|
+
AgentComposer,
|
|
107
|
+
AgentConversation,
|
|
108
|
+
useNativeAgent,
|
|
109
|
+
} from '@page-speed/agent-everywhere';
|
|
110
|
+
|
|
111
|
+
function PagesDashboard() {
|
|
112
|
+
return (
|
|
113
|
+
<NativeAgentProvider
|
|
114
|
+
// Host supplies the socket URL (or a resolver) — never hardcoded here.
|
|
115
|
+
resolveSocketUrl={resolveSocketUrl}
|
|
116
|
+
websiteId={websiteId}
|
|
117
|
+
pageCategoryId="pages"
|
|
118
|
+
connectionStrategy="lazy" // default: no socket until the first submit
|
|
119
|
+
>
|
|
120
|
+
<Content />
|
|
121
|
+
{/* Place the composer anywhere — here, a docked bottom bar. */}
|
|
122
|
+
<AgentComposer
|
|
123
|
+
className="fixed inset-x-0 bottom-0 m-4"
|
|
124
|
+
footer="Grounded in your connected sources."
|
|
125
|
+
/>
|
|
126
|
+
</NativeAgentProvider>
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
function Content() {
|
|
131
|
+
const { isActive } = useNativeAgent();
|
|
132
|
+
// The host owns the swap — render your own page until the agent is engaged.
|
|
133
|
+
return isActive ? <AgentConversation /> : <PagesTable />;
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Both `AgentComposer` and `AgentConversation` are **dual-mode**: inside a
|
|
138
|
+
`NativeAgentProvider` they wire themselves to the shared session; given explicit
|
|
139
|
+
`value`/`onChange`/`onSubmit` (composer) or `messages` (conversation) props they
|
|
140
|
+
run fully controlled with no provider. For 100%-custom UI, read the session
|
|
141
|
+
directly with `useNativeAgent()`. The connection is lazy by default
|
|
142
|
+
(`connectionStrategy="eager"` to pre-connect on mount).
|
|
143
|
+
|
|
74
144
|
### Inline confirmation / proposed-plan panels
|
|
75
145
|
|
|
76
146
|
Confirmation and proposed-plan panels flow **inline in the transcript** — attach
|
|
@@ -166,9 +236,11 @@ function Designer({ websiteId, pageCategoryId, blocks, onBlocks }) {
|
|
|
166
236
|
```
|
|
167
237
|
|
|
168
238
|
The hook returns `{ messages, connectionState, connectionError, statusLabel,
|
|
169
|
-
isConnected, isStreaming, sendMessage, retry }` and manages connection
|
|
239
|
+
isConnected, isStreaming, sendMessage, retry, reset }` and manages connection
|
|
170
240
|
lifecycle, reconnect with backoff, the streaming message state machine, hidden
|
|
171
|
-
(background) requests, and block-extraction fallbacks.
|
|
241
|
+
(background) requests, and block-extraction fallbacks. Pass
|
|
242
|
+
`seedWelcomeMessage: false` to start with an empty transcript (the `native`
|
|
243
|
+
variant does this for its idle composer).
|
|
172
244
|
|
|
173
245
|
### Low-level client
|
|
174
246
|
|
package/dist/index.cjs
CHANGED
|
@@ -7222,6 +7222,7 @@ function useSemanticBuilder({
|
|
|
7222
7222
|
onGeneratedBlocks,
|
|
7223
7223
|
onUndoRequest,
|
|
7224
7224
|
buildWelcomeMessage,
|
|
7225
|
+
seedWelcomeMessage = true,
|
|
7225
7226
|
webSocketImpl
|
|
7226
7227
|
}) {
|
|
7227
7228
|
const [messages, setMessages] = React4.useState([]);
|
|
@@ -7255,6 +7256,7 @@ function useSemanticBuilder({
|
|
|
7255
7256
|
resolveSocketUrlRef.current = resolveSocketUrl;
|
|
7256
7257
|
}, [resolveSocketUrl]);
|
|
7257
7258
|
React4.useEffect(() => {
|
|
7259
|
+
if (!seedWelcomeMessage) return;
|
|
7258
7260
|
const hasContentBrief = !!contentBrief;
|
|
7259
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.`);
|
|
7260
7262
|
setMessages([
|
|
@@ -7265,7 +7267,7 @@ function useSemanticBuilder({
|
|
|
7265
7267
|
createdAt: Date.now()
|
|
7266
7268
|
}
|
|
7267
7269
|
]);
|
|
7268
|
-
}, [contentBrief, pageName, pageSlug]);
|
|
7270
|
+
}, [contentBrief, pageName, pageSlug, seedWelcomeMessage]);
|
|
7269
7271
|
const handleEnvelope = React4.useCallback((envelope) => {
|
|
7270
7272
|
switch (envelope.type) {
|
|
7271
7273
|
case "connection_ready":
|
|
@@ -7477,6 +7479,14 @@ function useSemanticBuilder({
|
|
|
7477
7479
|
const retry = React4.useCallback(() => {
|
|
7478
7480
|
clientRef.current?.retry();
|
|
7479
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
|
+
}, []);
|
|
7480
7490
|
const isConnected = connectionState === "ready" || connectionState === "streaming";
|
|
7481
7491
|
const isStreaming = connectionState === "streaming";
|
|
7482
7492
|
const statusLabel = React4.useMemo(() => {
|
|
@@ -7503,7 +7513,8 @@ function useSemanticBuilder({
|
|
|
7503
7513
|
isConnected,
|
|
7504
7514
|
isStreaming,
|
|
7505
7515
|
sendMessage,
|
|
7506
|
-
retry
|
|
7516
|
+
retry,
|
|
7517
|
+
reset
|
|
7507
7518
|
};
|
|
7508
7519
|
}
|
|
7509
7520
|
var ScrollArea = React4__namespace.forwardRef(({ className, children, ...props }, ref) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -8007,6 +8018,54 @@ function FullBleedSurface({
|
|
|
8007
8018
|
}
|
|
8008
8019
|
);
|
|
8009
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
|
+
}
|
|
8010
8069
|
function AgentSurface({
|
|
8011
8070
|
mode,
|
|
8012
8071
|
messages,
|
|
@@ -8130,6 +8189,21 @@ function AgentSurface({
|
|
|
8130
8189
|
children: conversation
|
|
8131
8190
|
}
|
|
8132
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
|
+
);
|
|
8133
8207
|
case "panel":
|
|
8134
8208
|
default:
|
|
8135
8209
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -8148,8 +8222,340 @@ function AgentSurface({
|
|
|
8148
8222
|
);
|
|
8149
8223
|
}
|
|
8150
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
|
+
}
|
|
8151
8555
|
|
|
8152
8556
|
exports.AgentAvatar = AgentAvatar;
|
|
8557
|
+
exports.AgentComposer = AgentComposer;
|
|
8558
|
+
exports.AgentConversation = AgentConversation;
|
|
8153
8559
|
exports.AgentHandoff = AgentHandoff;
|
|
8154
8560
|
exports.AgentProvider = AgentProvider;
|
|
8155
8561
|
exports.AgentSurface = AgentSurface;
|
|
@@ -8196,6 +8602,8 @@ exports.MessageWithSteps = MessageWithSteps;
|
|
|
8196
8602
|
exports.MetricsGrid = MetricsGrid;
|
|
8197
8603
|
exports.MobileShell = MobileShell;
|
|
8198
8604
|
exports.MultimodalInput = MultimodalInput;
|
|
8605
|
+
exports.NativeAgentProvider = NativeAgentProvider;
|
|
8606
|
+
exports.NativeSurface = NativeSurface;
|
|
8199
8607
|
exports.OnboardingWizard = OnboardingWizard;
|
|
8200
8608
|
exports.OptionCards = OptionCards;
|
|
8201
8609
|
exports.OverlayModal = OverlayModal;
|
|
@@ -8264,6 +8672,8 @@ exports.useAgentBackend = useAgentBackend;
|
|
|
8264
8672
|
exports.useAgentInput = useAgentInput;
|
|
8265
8673
|
exports.useAgentLayout = useAgentLayout;
|
|
8266
8674
|
exports.useAgentMessages = useAgentMessages;
|
|
8675
|
+
exports.useNativeAgent = useNativeAgent;
|
|
8676
|
+
exports.useNativeAgentOptional = useNativeAgentOptional;
|
|
8267
8677
|
exports.useSemanticBuilder = useSemanticBuilder;
|
|
8268
8678
|
//# sourceMappingURL=index.cjs.map
|
|
8269
8679
|
//# sourceMappingURL=index.cjs.map
|