@invergent/agent-chat-react 1.5.10 → 1.6.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 +332 -37
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +21 -2
- package/dist/index.d.ts +21 -2
- package/dist/index.js +329 -37
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -6,9 +6,9 @@ var react = require('react');
|
|
|
6
6
|
var auto = require('chart.js/auto');
|
|
7
7
|
var nextThemes = require('next-themes');
|
|
8
8
|
var jsxRuntime = require('react/jsx-runtime');
|
|
9
|
+
var lucideReact = require('lucide-react');
|
|
9
10
|
var classVarianceAuthority = require('class-variance-authority');
|
|
10
11
|
var radixUi = require('radix-ui');
|
|
11
|
-
var lucideReact = require('lucide-react');
|
|
12
12
|
var useStickToBottom = require('use-stick-to-bottom');
|
|
13
13
|
var cjk = require('@streamdown/cjk');
|
|
14
14
|
var code = require('@streamdown/code');
|
|
@@ -263,6 +263,117 @@ function Button({
|
|
|
263
263
|
}
|
|
264
264
|
);
|
|
265
265
|
}
|
|
266
|
+
function BrowserControlBar({
|
|
267
|
+
sessionId,
|
|
268
|
+
hasControl,
|
|
269
|
+
adapter
|
|
270
|
+
}) {
|
|
271
|
+
const [pending, setPending] = react.useState(false);
|
|
272
|
+
const [error, setError] = react.useState(null);
|
|
273
|
+
async function toggleControl() {
|
|
274
|
+
if (!sessionId || pending) return;
|
|
275
|
+
setPending(true);
|
|
276
|
+
setError(null);
|
|
277
|
+
try {
|
|
278
|
+
if (hasControl) {
|
|
279
|
+
await adapter.releaseBrowserControl(sessionId);
|
|
280
|
+
} else {
|
|
281
|
+
await adapter.acquireBrowserControl(sessionId);
|
|
282
|
+
}
|
|
283
|
+
} catch (nextError) {
|
|
284
|
+
setError(nextError.message);
|
|
285
|
+
} finally {
|
|
286
|
+
setPending(false);
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex min-h-11 items-center gap-2 border-t border-line bg-card px-3 py-2", children: [
|
|
290
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
291
|
+
Button,
|
|
292
|
+
{
|
|
293
|
+
type: "button",
|
|
294
|
+
size: "xs",
|
|
295
|
+
variant: hasControl ? "secondary" : "default",
|
|
296
|
+
disabled: !sessionId || pending,
|
|
297
|
+
onClick: () => void toggleControl(),
|
|
298
|
+
children: [
|
|
299
|
+
hasControl ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.RotateCcwIcon, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.MousePointer2Icon, { className: "size-3", "aria-hidden": "true" }),
|
|
300
|
+
hasControl ? "Return control" : "Take control"
|
|
301
|
+
]
|
|
302
|
+
}
|
|
303
|
+
),
|
|
304
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-auto flex items-center gap-1.5 text-[11px] text-muted-foreground", children: [
|
|
305
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "size-1.5 rounded-full bg-red-500", "aria-hidden": "true" }),
|
|
306
|
+
"Live"
|
|
307
|
+
] }),
|
|
308
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "max-w-40 truncate text-[11px] text-destructive", children: error })
|
|
309
|
+
] });
|
|
310
|
+
}
|
|
311
|
+
function BrowserLiveView({ src }) {
|
|
312
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
313
|
+
"iframe",
|
|
314
|
+
{
|
|
315
|
+
"data-testid": "browser-iframe",
|
|
316
|
+
title: "Browser live view",
|
|
317
|
+
src,
|
|
318
|
+
className: "h-full w-full border-0 bg-black",
|
|
319
|
+
allow: "clipboard-read; clipboard-write"
|
|
320
|
+
}
|
|
321
|
+
);
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// src/components/browser/browser-status-dot.tsx
|
|
325
|
+
init_utils();
|
|
326
|
+
function BrowserStatusDot({
|
|
327
|
+
status
|
|
328
|
+
}) {
|
|
329
|
+
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
330
|
+
"span",
|
|
331
|
+
{
|
|
332
|
+
"aria-hidden": "true",
|
|
333
|
+
className: cn(
|
|
334
|
+
"inline-block size-2 shrink-0 rounded-full",
|
|
335
|
+
status === "live" && "bg-emerald-500",
|
|
336
|
+
status === "user-control" && "bg-amber-500",
|
|
337
|
+
status === "provisioning" && "animate-pulse bg-sky-500",
|
|
338
|
+
status === "closed" && "bg-muted-foreground"
|
|
339
|
+
)
|
|
340
|
+
}
|
|
341
|
+
);
|
|
342
|
+
}
|
|
343
|
+
function BrowserPane({ sessionId, state, adapter }) {
|
|
344
|
+
const liveViewUrl = react.useMemo(
|
|
345
|
+
() => adapter.browserLiveViewUrl(sessionId),
|
|
346
|
+
[adapter, sessionId]
|
|
347
|
+
);
|
|
348
|
+
const hasLiveView = state.status !== "provisioning" && state.status !== "closed";
|
|
349
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
350
|
+
"div",
|
|
351
|
+
{
|
|
352
|
+
"data-testid": "browser-pane",
|
|
353
|
+
className: "flex h-full min-h-0 flex-col bg-background",
|
|
354
|
+
children: [
|
|
355
|
+
/* @__PURE__ */ jsxRuntime.jsxs("header", { className: "flex min-h-10 items-center gap-2 border-b border-line bg-card px-3 text-xs text-foreground", children: [
|
|
356
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ZapIcon, { className: "size-3.5 text-muted-foreground", "aria-hidden": "true" }),
|
|
357
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium", children: "Browser" }),
|
|
358
|
+
/* @__PURE__ */ jsxRuntime.jsx(BrowserStatusDot, { status: state.status }),
|
|
359
|
+
state.controlOwner && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 truncate text-amber-500", children: [
|
|
360
|
+
state.controlOwner,
|
|
361
|
+
" has control"
|
|
362
|
+
] })
|
|
363
|
+
] }),
|
|
364
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1 bg-black", children: state.status === "provisioning" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center bg-background text-sm text-muted-foreground", children: "Starting browser..." }) : state.status === "closed" ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex h-full items-center justify-center bg-background text-sm text-muted-foreground", children: "Browser closed." }) : /* @__PURE__ */ jsxRuntime.jsx(BrowserLiveView, { src: liveViewUrl }) }),
|
|
365
|
+
hasLiveView && /* @__PURE__ */ jsxRuntime.jsx(
|
|
366
|
+
BrowserControlBar,
|
|
367
|
+
{
|
|
368
|
+
sessionId,
|
|
369
|
+
hasControl: state.status === "user-control",
|
|
370
|
+
adapter
|
|
371
|
+
}
|
|
372
|
+
)
|
|
373
|
+
]
|
|
374
|
+
}
|
|
375
|
+
);
|
|
376
|
+
}
|
|
266
377
|
|
|
267
378
|
// src/components/ai-elements/conversation.tsx
|
|
268
379
|
init_utils();
|
|
@@ -767,6 +878,80 @@ function TimelineSeparator({
|
|
|
767
878
|
}
|
|
768
879
|
);
|
|
769
880
|
}
|
|
881
|
+
function BrowserActivityGroup({ calls }) {
|
|
882
|
+
const [open, setOpen] = react.useState(false);
|
|
883
|
+
const latest = calls[calls.length - 1];
|
|
884
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-none border border-line bg-card text-xs", children: [
|
|
885
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
886
|
+
"button",
|
|
887
|
+
{
|
|
888
|
+
type: "button",
|
|
889
|
+
onClick: () => setOpen((current) => !current),
|
|
890
|
+
className: "flex w-full items-center gap-2 px-3 py-2 text-left hover:bg-muted/40",
|
|
891
|
+
children: [
|
|
892
|
+
open ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronDownIcon, { className: "size-3 shrink-0", "aria-hidden": "true" }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRightIcon, { className: "size-3 shrink-0", "aria-hidden": "true" }),
|
|
893
|
+
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ZapIcon, { className: "size-3 shrink-0 text-amber-500", "aria-hidden": "true" }),
|
|
894
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-semibold text-foreground", children: "browser" }),
|
|
895
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "min-w-0 truncate text-muted-foreground", children: [
|
|
896
|
+
"(",
|
|
897
|
+
calls.length,
|
|
898
|
+
" ",
|
|
899
|
+
calls.length === 1 ? "action" : "actions",
|
|
900
|
+
" - latest:",
|
|
901
|
+
" ",
|
|
902
|
+
latest ? summarise(latest) : "none",
|
|
903
|
+
")"
|
|
904
|
+
] })
|
|
905
|
+
]
|
|
906
|
+
}
|
|
907
|
+
),
|
|
908
|
+
open && /* @__PURE__ */ jsxRuntime.jsx("ul", { className: "border-t border-line py-1", children: calls.map((call) => {
|
|
909
|
+
const error = stringValue(parseJson(call.result).error);
|
|
910
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
911
|
+
"li",
|
|
912
|
+
{
|
|
913
|
+
className: "flex items-center gap-2 px-6 py-1 font-mono text-[11px]",
|
|
914
|
+
children: [
|
|
915
|
+
error && /* @__PURE__ */ jsxRuntime.jsx(
|
|
916
|
+
lucideReact.AlertCircleIcon,
|
|
917
|
+
{
|
|
918
|
+
"data-testid": `activity-error-${call.id}`,
|
|
919
|
+
className: "size-3 shrink-0 text-destructive",
|
|
920
|
+
"aria-hidden": "true"
|
|
921
|
+
}
|
|
922
|
+
),
|
|
923
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 truncate", children: summarise(call) }),
|
|
924
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-auto max-w-40 truncate text-destructive", children: error })
|
|
925
|
+
]
|
|
926
|
+
},
|
|
927
|
+
call.id
|
|
928
|
+
);
|
|
929
|
+
}) })
|
|
930
|
+
] });
|
|
931
|
+
}
|
|
932
|
+
function summarise(call) {
|
|
933
|
+
const verb = call.toolName.replace(/^browser_/, "");
|
|
934
|
+
const args = parseJson(call.args);
|
|
935
|
+
const ref = stringValue(args.ref);
|
|
936
|
+
const url = stringValue(args.url);
|
|
937
|
+
const text = stringValue(args.text);
|
|
938
|
+
if (url) return `${verb} ${url}`;
|
|
939
|
+
if (ref) return `${verb} ${ref}`;
|
|
940
|
+
if (text) return `${verb} "${text.slice(0, 24)}"`;
|
|
941
|
+
return verb;
|
|
942
|
+
}
|
|
943
|
+
function parseJson(raw) {
|
|
944
|
+
if (!raw) return {};
|
|
945
|
+
try {
|
|
946
|
+
const parsed = JSON.parse(raw);
|
|
947
|
+
return typeof parsed === "object" && parsed !== null && !Array.isArray(parsed) ? parsed : {};
|
|
948
|
+
} catch {
|
|
949
|
+
return {};
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
function stringValue(value) {
|
|
953
|
+
return typeof value === "string" ? value : "";
|
|
954
|
+
}
|
|
770
955
|
init_utils();
|
|
771
956
|
|
|
772
957
|
// src/components/chat/tools/shared.ts
|
|
@@ -6178,6 +6363,32 @@ function messageToEntries(msg, isLast, artifactFallbacks) {
|
|
|
6178
6363
|
}
|
|
6179
6364
|
return entries;
|
|
6180
6365
|
}
|
|
6366
|
+
function groupBrowserActivityEntries(entries) {
|
|
6367
|
+
const grouped = [];
|
|
6368
|
+
let buffer = [];
|
|
6369
|
+
const flush = () => {
|
|
6370
|
+
if (buffer.length === 0) return;
|
|
6371
|
+
grouped.push({
|
|
6372
|
+
kind: "browser_activity",
|
|
6373
|
+
key: `browser-activity-${buffer[0]?.id}-${buffer[buffer.length - 1]?.id}`,
|
|
6374
|
+
calls: buffer
|
|
6375
|
+
});
|
|
6376
|
+
buffer = [];
|
|
6377
|
+
};
|
|
6378
|
+
for (const entry of entries) {
|
|
6379
|
+
if (entry.kind === "tool" && isBrowserToolCall(entry.tc)) {
|
|
6380
|
+
buffer.push(entry.tc);
|
|
6381
|
+
continue;
|
|
6382
|
+
}
|
|
6383
|
+
flush();
|
|
6384
|
+
grouped.push(entry);
|
|
6385
|
+
}
|
|
6386
|
+
flush();
|
|
6387
|
+
return grouped;
|
|
6388
|
+
}
|
|
6389
|
+
function isBrowserToolCall(call) {
|
|
6390
|
+
return call.toolName.startsWith("browser_");
|
|
6391
|
+
}
|
|
6181
6392
|
function groupMessages(messages) {
|
|
6182
6393
|
const groups = [];
|
|
6183
6394
|
let pendingSystem = [];
|
|
@@ -6334,6 +6545,15 @@ function TimelineEntryItem({
|
|
|
6334
6545
|
] }) })
|
|
6335
6546
|
] });
|
|
6336
6547
|
}
|
|
6548
|
+
if (entry.kind === "browser_activity") {
|
|
6549
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(TimelineItem, { step, children: [
|
|
6550
|
+
/* @__PURE__ */ jsxRuntime.jsxs(TimelineHeader, { children: [
|
|
6551
|
+
/* @__PURE__ */ jsxRuntime.jsx(TimelineSeparator, { style: { backgroundColor: "var(--color-border)" } }),
|
|
6552
|
+
/* @__PURE__ */ jsxRuntime.jsx(TimelineIndicator, { className: "size-2 border-none bg-amber-500" })
|
|
6553
|
+
] }),
|
|
6554
|
+
/* @__PURE__ */ jsxRuntime.jsx(TimelineContent, { children: /* @__PURE__ */ jsxRuntime.jsx(BrowserActivityGroup, { calls: entry.calls }) })
|
|
6555
|
+
] });
|
|
6556
|
+
}
|
|
6337
6557
|
if (entry.kind === "text") {
|
|
6338
6558
|
return /* @__PURE__ */ jsxRuntime.jsxs(TimelineItem, { step, children: [
|
|
6339
6559
|
/* @__PURE__ */ jsxRuntime.jsxs(TimelineHeader, { children: [
|
|
@@ -6395,11 +6615,12 @@ function AssistantGroup({
|
|
|
6395
6615
|
onFileSelect,
|
|
6396
6616
|
onRetry
|
|
6397
6617
|
}) {
|
|
6398
|
-
|
|
6618
|
+
let entries = [];
|
|
6399
6619
|
for (let i = 0; i < messages.length; i++) {
|
|
6400
6620
|
const isLast = i === messages.length - 1 && lastGlobalIndex === totalMessages - 1;
|
|
6401
6621
|
entries.push(...messageToEntries(messages[i], isLast, artifactFallbacks));
|
|
6402
6622
|
}
|
|
6623
|
+
entries = groupBrowserActivityEntries(entries);
|
|
6403
6624
|
const isTailGroup = lastGlobalIndex === totalMessages - 1;
|
|
6404
6625
|
const lastEntry = entries[entries.length - 1];
|
|
6405
6626
|
const hasRunningTool = entries.some(
|
|
@@ -7476,6 +7697,7 @@ function WorkspacePanel({
|
|
|
7476
7697
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
7477
7698
|
"aside",
|
|
7478
7699
|
{
|
|
7700
|
+
"data-testid": "workspace-panel",
|
|
7479
7701
|
role: "button",
|
|
7480
7702
|
tabIndex: 0,
|
|
7481
7703
|
className: "relative z-10 flex min-h-0 w-10 shrink-0 cursor-pointer items-center justify-center border-l border-muted-foreground/20 bg-card text-muted-foreground transition-colors hover:bg-muted/50 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring/30",
|
|
@@ -7494,6 +7716,7 @@ function WorkspacePanel({
|
|
|
7494
7716
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7495
7717
|
"aside",
|
|
7496
7718
|
{
|
|
7719
|
+
"data-testid": "workspace-panel",
|
|
7497
7720
|
className: "relative z-10 flex min-h-0 flex-col overflow-hidden border-l border-muted-foreground/20 bg-card",
|
|
7498
7721
|
style: { width, minWidth: MIN_WIDTH, maxWidth: MAX_WIDTH },
|
|
7499
7722
|
children: [
|
|
@@ -7735,6 +7958,10 @@ var AGENT_CHAT_LISTENED_EVENTS = [
|
|
|
7735
7958
|
"expert.override",
|
|
7736
7959
|
"artifact.created",
|
|
7737
7960
|
"artifact.updated",
|
|
7961
|
+
"browser.provisioned",
|
|
7962
|
+
"browser.destroyed",
|
|
7963
|
+
"browser.control_granted",
|
|
7964
|
+
"browser.control_returned",
|
|
7738
7965
|
"clarify.response"
|
|
7739
7966
|
];
|
|
7740
7967
|
|
|
@@ -7759,7 +7986,8 @@ function createInitialAgentChatState(options = {}) {
|
|
|
7759
7986
|
sessionDone: false,
|
|
7760
7987
|
hadDeltas: false,
|
|
7761
7988
|
terminal: false,
|
|
7762
|
-
workspaceRefreshKey: 0
|
|
7989
|
+
workspaceRefreshKey: 0,
|
|
7990
|
+
browser: null
|
|
7763
7991
|
};
|
|
7764
7992
|
}
|
|
7765
7993
|
function applyAgentChatEvent(state, event) {
|
|
@@ -7783,7 +8011,7 @@ function applyAgentChatEvent(state, event) {
|
|
|
7783
8011
|
{
|
|
7784
8012
|
id: `evt-${event.eventId}`,
|
|
7785
8013
|
role: "system",
|
|
7786
|
-
content:
|
|
8014
|
+
content: stringValue2(event.data.skill),
|
|
7787
8015
|
createdAt: /* @__PURE__ */ new Date(),
|
|
7788
8016
|
status: "complete",
|
|
7789
8017
|
systemKind: "skill_invoked",
|
|
@@ -7800,7 +8028,7 @@ function applyAgentChatEvent(state, event) {
|
|
|
7800
8028
|
{
|
|
7801
8029
|
id: `evt-${event.eventId}`,
|
|
7802
8030
|
role: "system",
|
|
7803
|
-
content:
|
|
8031
|
+
content: stringValue2(event.data.name),
|
|
7804
8032
|
createdAt: /* @__PURE__ */ new Date(),
|
|
7805
8033
|
status: "complete",
|
|
7806
8034
|
systemKind: "artifact",
|
|
@@ -7813,6 +8041,23 @@ function applyAgentChatEvent(state, event) {
|
|
|
7813
8041
|
}
|
|
7814
8042
|
}
|
|
7815
8043
|
]);
|
|
8044
|
+
case "browser.provisioned":
|
|
8045
|
+
return applyBrowserEvent(nextState, event, {
|
|
8046
|
+
status: "live",
|
|
8047
|
+
controlOwner: null
|
|
8048
|
+
});
|
|
8049
|
+
case "browser.control_granted":
|
|
8050
|
+
return applyBrowserEvent(nextState, event, {
|
|
8051
|
+
status: "user-control",
|
|
8052
|
+
controlOwner: stringValue2(event.data.owner_user_id) || null
|
|
8053
|
+
});
|
|
8054
|
+
case "browser.control_returned":
|
|
8055
|
+
return applyBrowserEvent(nextState, event, {
|
|
8056
|
+
status: "live",
|
|
8057
|
+
controlOwner: null
|
|
8058
|
+
});
|
|
8059
|
+
case "browser.destroyed":
|
|
8060
|
+
return applyBrowserEvent(nextState, event, null);
|
|
7816
8061
|
case "llm.delta":
|
|
7817
8062
|
return applyLlmDelta(nextState, event);
|
|
7818
8063
|
case "llm.response":
|
|
@@ -7822,7 +8067,7 @@ function applyAgentChatEvent(state, event) {
|
|
|
7822
8067
|
case "tool.call":
|
|
7823
8068
|
return applyToolCall(nextState, event);
|
|
7824
8069
|
case "tool.result": {
|
|
7825
|
-
const toolCallId =
|
|
8070
|
+
const toolCallId = stringValue2(event.data.tool_call_id);
|
|
7826
8071
|
const toolName = findToolNameById(nextState.messages, toolCallId);
|
|
7827
8072
|
const messages = applyToolResult(nextState.messages, event.data);
|
|
7828
8073
|
const mutatesWorkspace = toolName !== null && WORKSPACE_MUTATING_TOOLS.has(toolName);
|
|
@@ -7892,8 +8137,8 @@ function applyRetryIndicator(state, event) {
|
|
|
7892
8137
|
case "session.done":
|
|
7893
8138
|
return { ...state, retryIndicator: null };
|
|
7894
8139
|
case "harness.crash": {
|
|
7895
|
-
const title =
|
|
7896
|
-
const detail =
|
|
8140
|
+
const title = stringValue2(event.data.error_title) || "A transient error occurred, retrying...";
|
|
8141
|
+
const detail = stringValue2(event.data.error_detail) || stringValue2(event.data.error);
|
|
7897
8142
|
return {
|
|
7898
8143
|
...state,
|
|
7899
8144
|
retryIndicator: {
|
|
@@ -7908,7 +8153,7 @@ function applyRetryIndicator(state, event) {
|
|
|
7908
8153
|
}
|
|
7909
8154
|
}
|
|
7910
8155
|
function applyUserMessage(messages, eventId, data) {
|
|
7911
|
-
const content =
|
|
8156
|
+
const content = stringValue2(data.content);
|
|
7912
8157
|
const next = [...messages];
|
|
7913
8158
|
const localIdx = next.findIndex(
|
|
7914
8159
|
(m) => m.role === "user" && m.id.startsWith("local-") && m.content === content
|
|
@@ -7926,9 +8171,47 @@ function applyUserMessage(messages, eventId, data) {
|
|
|
7926
8171
|
});
|
|
7927
8172
|
return next;
|
|
7928
8173
|
}
|
|
8174
|
+
function applyBrowserEvent(state, event, browser) {
|
|
8175
|
+
return withMessages(
|
|
8176
|
+
{ ...state, browser },
|
|
8177
|
+
[...state.messages, browserMarker(event)]
|
|
8178
|
+
);
|
|
8179
|
+
}
|
|
8180
|
+
function browserMarker(event) {
|
|
8181
|
+
const labels = {
|
|
8182
|
+
"browser.provisioned": {
|
|
8183
|
+
content: "Browser ready.",
|
|
8184
|
+
warning: false
|
|
8185
|
+
},
|
|
8186
|
+
"browser.control_granted": {
|
|
8187
|
+
content: "A user took control of the browser.",
|
|
8188
|
+
warning: true
|
|
8189
|
+
},
|
|
8190
|
+
"browser.control_returned": {
|
|
8191
|
+
content: "Browser control returned to the agent.",
|
|
8192
|
+
warning: false
|
|
8193
|
+
},
|
|
8194
|
+
"browser.destroyed": {
|
|
8195
|
+
content: "Browser closed.",
|
|
8196
|
+
warning: false
|
|
8197
|
+
}
|
|
8198
|
+
};
|
|
8199
|
+
const label = labels[event.type] ?? {
|
|
8200
|
+
content: "Browser updated.",
|
|
8201
|
+
warning: false
|
|
8202
|
+
};
|
|
8203
|
+
return {
|
|
8204
|
+
id: `browser-marker-${event.eventId}`,
|
|
8205
|
+
role: "system",
|
|
8206
|
+
content: label.content,
|
|
8207
|
+
createdAt: /* @__PURE__ */ new Date(),
|
|
8208
|
+
status: "complete",
|
|
8209
|
+
systemKind: label.warning ? "browser_marker_warning" : "browser_marker"
|
|
8210
|
+
};
|
|
8211
|
+
}
|
|
7929
8212
|
function applyLlmDelta(state, event) {
|
|
7930
|
-
const deltaContent =
|
|
7931
|
-
const deltaReasoning =
|
|
8213
|
+
const deltaContent = stringValue2(event.data.content);
|
|
8214
|
+
const deltaReasoning = stringValue2(event.data.reasoning);
|
|
7932
8215
|
const messages = [...state.messages];
|
|
7933
8216
|
const lastIdx = findLastAssistantIndex(messages);
|
|
7934
8217
|
const lastMsg = lastIdx >= 0 ? messages[lastIdx] : null;
|
|
@@ -7965,7 +8248,7 @@ function applyLlmDelta(state, event) {
|
|
|
7965
8248
|
function applyLlmResponse(state, event) {
|
|
7966
8249
|
const messages = [...state.messages];
|
|
7967
8250
|
const message = objectValue(event.data.message);
|
|
7968
|
-
const responseContent =
|
|
8251
|
+
const responseContent = stringValue2(message?.content) || stringValue2(event.data.content);
|
|
7969
8252
|
const toolCalls = Array.isArray(message?.tool_calls) ? message?.tool_calls : [];
|
|
7970
8253
|
const hasToolCalls = toolCalls.length > 0;
|
|
7971
8254
|
const idx = findLastAssistantIndex(messages);
|
|
@@ -8023,12 +8306,12 @@ function applyLlmResponse(state, event) {
|
|
|
8023
8306
|
cachedInputTokens: numberValue(event.data.cache_read_tokens),
|
|
8024
8307
|
totalTokens: inputTokens + outputTokens,
|
|
8025
8308
|
contextWindow: numberValue(event.data.context_window),
|
|
8026
|
-
model:
|
|
8309
|
+
model: stringValue2(event.data.model)
|
|
8027
8310
|
}
|
|
8028
8311
|
};
|
|
8029
8312
|
}
|
|
8030
8313
|
function applyLlmThinking(state, event) {
|
|
8031
|
-
const reasoningText =
|
|
8314
|
+
const reasoningText = stringValue2(event.data.reasoning) || stringValue2(event.data.content);
|
|
8032
8315
|
const messages = [...state.messages];
|
|
8033
8316
|
const idx = findLastAssistantIndex(messages);
|
|
8034
8317
|
const prev = idx >= 0 ? messages[idx] : null;
|
|
@@ -8076,11 +8359,11 @@ function applyToolCall(state, event) {
|
|
|
8076
8359
|
messages[assistantIdx] = assistant;
|
|
8077
8360
|
}
|
|
8078
8361
|
const existingCalls = assistant.toolCalls ?? [];
|
|
8079
|
-
const toolCallId =
|
|
8362
|
+
const toolCallId = stringValue2(event.data.tool_call_id) || `tc-${event.eventId}`;
|
|
8080
8363
|
if (!existingCalls.some((tc) => tc.id === toolCallId)) {
|
|
8081
8364
|
const entry = {
|
|
8082
8365
|
id: toolCallId,
|
|
8083
|
-
toolName:
|
|
8366
|
+
toolName: stringValue2(event.data.name) || stringValue2(event.data.tool_name) || "unknown",
|
|
8084
8367
|
args: typeof event.data.arguments === "string" ? event.data.arguments : JSON.stringify(event.data.arguments ?? {}),
|
|
8085
8368
|
status: "running"
|
|
8086
8369
|
};
|
|
@@ -8096,7 +8379,7 @@ function applyToolCall(state, event) {
|
|
|
8096
8379
|
};
|
|
8097
8380
|
}
|
|
8098
8381
|
function applyToolResult(messages, data) {
|
|
8099
|
-
const targetId =
|
|
8382
|
+
const targetId = stringValue2(data.tool_call_id);
|
|
8100
8383
|
let matchIdx = -1;
|
|
8101
8384
|
for (let i = messages.length - 1; i >= 0; i--) {
|
|
8102
8385
|
if (messages[i]?.role === "assistant" && messages[i]?.toolCalls?.some((tc) => tc.id === targetId)) {
|
|
@@ -8165,8 +8448,8 @@ function buildErrorInfo(event) {
|
|
|
8165
8448
|
}
|
|
8166
8449
|
return {
|
|
8167
8450
|
category: event.data.error_category,
|
|
8168
|
-
title:
|
|
8169
|
-
detail:
|
|
8451
|
+
title: stringValue2(event.data.error_title) || "The session failed due to an internal error.",
|
|
8452
|
+
detail: stringValue2(event.data.error_detail) || stringValue2(event.data.error),
|
|
8170
8453
|
retryable: Boolean(event.data.retryable)
|
|
8171
8454
|
};
|
|
8172
8455
|
}
|
|
@@ -8210,7 +8493,7 @@ function applyExpertFeedback(messages, type, data) {
|
|
|
8210
8493
|
return messages;
|
|
8211
8494
|
}
|
|
8212
8495
|
function applyClarifyResponse(messages, data) {
|
|
8213
|
-
const targetToolId =
|
|
8496
|
+
const targetToolId = stringValue2(data.tool_call_id);
|
|
8214
8497
|
const responses = Array.isArray(data.responses) ? data.responses : void 0;
|
|
8215
8498
|
if (!targetToolId || !responses) return messages;
|
|
8216
8499
|
const next = [...messages];
|
|
@@ -8225,8 +8508,8 @@ function applyClarifyResponse(messages, data) {
|
|
|
8225
8508
|
clarifyAnswers: responses.map((response) => {
|
|
8226
8509
|
const row = objectValue(response) ?? {};
|
|
8227
8510
|
return {
|
|
8228
|
-
question:
|
|
8229
|
-
answer:
|
|
8511
|
+
question: stringValue2(row.question),
|
|
8512
|
+
answer: stringValue2(row.answer),
|
|
8230
8513
|
is_other: Boolean(row.is_other)
|
|
8231
8514
|
};
|
|
8232
8515
|
})
|
|
@@ -8246,7 +8529,7 @@ function applyPolicyDenied(state, data) {
|
|
|
8246
8529
|
...policyMsg,
|
|
8247
8530
|
content: `${policyMsg.content}
|
|
8248
8531
|
|
|
8249
|
-
**Policy denied**: ${
|
|
8532
|
+
**Policy denied**: ${stringValue2(data.reason) || "Action blocked by governance policy."}`,
|
|
8250
8533
|
status: "error"
|
|
8251
8534
|
};
|
|
8252
8535
|
}
|
|
@@ -8298,7 +8581,7 @@ function objectValue(value) {
|
|
|
8298
8581
|
}
|
|
8299
8582
|
return void 0;
|
|
8300
8583
|
}
|
|
8301
|
-
function
|
|
8584
|
+
function stringValue2(value) {
|
|
8302
8585
|
return typeof value === "string" ? value : "";
|
|
8303
8586
|
}
|
|
8304
8587
|
function numberValue(value) {
|
|
@@ -8532,6 +8815,7 @@ function useAgentChatRuntime({
|
|
|
8532
8815
|
}
|
|
8533
8816
|
}, [adapter, sessionId]);
|
|
8534
8817
|
return {
|
|
8818
|
+
state,
|
|
8535
8819
|
session,
|
|
8536
8820
|
messages: state.messages,
|
|
8537
8821
|
isRunning: state.isRunning,
|
|
@@ -8583,6 +8867,7 @@ function AgentChat({
|
|
|
8583
8867
|
const isReadOnlySession = isScheduledRunSession(runtime.session);
|
|
8584
8868
|
const effectiveDisabled = disabled || isReadOnlySession;
|
|
8585
8869
|
const disabledReason = isReadOnlySession ? "Scheduled run is read-only" : void 0;
|
|
8870
|
+
const browserState = runtime.state.browser;
|
|
8586
8871
|
react.useEffect(() => {
|
|
8587
8872
|
onMessagesChange?.(runtime.messages);
|
|
8588
8873
|
}, [onMessagesChange, runtime.messages]);
|
|
@@ -8619,19 +8904,29 @@ function AgentChat({
|
|
|
8619
8904
|
retryIndicator: runtime.retryIndicator
|
|
8620
8905
|
}
|
|
8621
8906
|
) }),
|
|
8622
|
-
/* @__PURE__ */ jsxRuntime.
|
|
8623
|
-
|
|
8624
|
-
|
|
8625
|
-
|
|
8626
|
-
|
|
8627
|
-
|
|
8628
|
-
|
|
8629
|
-
|
|
8630
|
-
|
|
8631
|
-
|
|
8632
|
-
|
|
8633
|
-
|
|
8634
|
-
|
|
8907
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { "data-testid": "right-stack", className: "flex min-h-0 shrink-0 flex-col", children: [
|
|
8908
|
+
browserState !== null && sessionId && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "min-h-0 flex-1 border-b border-line", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
8909
|
+
BrowserPane,
|
|
8910
|
+
{
|
|
8911
|
+
sessionId,
|
|
8912
|
+
state: browserState,
|
|
8913
|
+
adapter
|
|
8914
|
+
}
|
|
8915
|
+
) }),
|
|
8916
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
8917
|
+
WorkspacePanel,
|
|
8918
|
+
{
|
|
8919
|
+
adapter,
|
|
8920
|
+
sessionId,
|
|
8921
|
+
selectedPath: workspacePath,
|
|
8922
|
+
onSelectedPathChange: setWorkspacePath,
|
|
8923
|
+
collapsed: workspaceCollapsed,
|
|
8924
|
+
onCollapsedChange: setWorkspaceCollapsed,
|
|
8925
|
+
refreshSignal: runtime.workspaceRefreshKey,
|
|
8926
|
+
disabled: effectiveDisabled
|
|
8927
|
+
}
|
|
8928
|
+
)
|
|
8929
|
+
] })
|
|
8635
8930
|
] }) })
|
|
8636
8931
|
}
|
|
8637
8932
|
);
|