@invergent/agent-chat-react 1.5.8 → 1.5.10
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 +13 -0
- package/dist/index.cjs +430 -29
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +60 -1
- package/dist/index.d.ts +60 -1
- package/dist/index.js +430 -31
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -3,7 +3,7 @@ import { createContext, memo, useRef, useState, useEffect, useCallback, useMemo,
|
|
|
3
3
|
import { cva } from 'class-variance-authority';
|
|
4
4
|
import { Collapsible as Collapsible$1, Slot, Dialog as Dialog$1, ScrollArea as ScrollArea$1, Tooltip as Tooltip$1, Tabs as Tabs$1, Popover as Popover$1, DropdownMenu as DropdownMenu$1, HoverCard as HoverCard$1, Progress as Progress$1 } from 'radix-ui';
|
|
5
5
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
6
|
-
import { ChevronDownIcon, AlertTriangle, ChevronDown, ChevronRight, RefreshCw, ChevronRightIcon, GitBranchIcon, XIcon, ThumbsUpIcon, ThumbsDownIcon, ActivityIcon, Loader2Icon, GlobeIcon, SearchIcon, ListTodoIcon, XCircleIcon, CheckCircle2Icon, Code, CheckIcon, CopyIcon, TerminalIcon, Trash2Icon, CircleDotIcon, CircleCheckIcon, CircleXIcon, SkullIcon, ClockIcon, CheckCircleIcon, CircleIcon, UsersIcon, MessageSquareIcon, FolderOpenIcon, UploadIcon, RefreshCwIcon, AlertCircleIcon, SquareIcon, ArrowDownIcon, DownloadIcon, TrashIcon, ImageIcon, FileTextIcon, Maximize2Icon, FolderIcon, FileIcon, ChevronLeftIcon, MinusIcon, PlusIcon, CornerDownLeftIcon } from 'lucide-react';
|
|
6
|
+
import { ChevronDownIcon, AlertTriangle, ChevronDown, ChevronRight, RefreshCw, ChevronRightIcon, GitBranchIcon, XIcon, ThumbsUpIcon, ThumbsDownIcon, ActivityIcon, Loader2Icon, GlobeIcon, SearchIcon, ListTodoIcon, XCircleIcon, CheckCircle2Icon, Code, CheckIcon, CopyIcon, TerminalIcon, Trash2Icon, CircleDotIcon, CircleCheckIcon, CircleXIcon, SkullIcon, ClockIcon, CheckCircleIcon, CircleIcon, CalendarClockIcon, UsersIcon, MessageSquareIcon, FolderOpenIcon, UploadIcon, RefreshCwIcon, AlertCircleIcon, SquareIcon, ArrowDownIcon, DownloadIcon, TrashIcon, ImageIcon, FileTextIcon, Maximize2Icon, FolderIcon, FileIcon, ChevronLeftIcon, MinusIcon, PlusIcon, CornerDownLeftIcon } from 'lucide-react';
|
|
7
7
|
import { StickToBottom, useStickToBottomContext } from 'use-stick-to-bottom';
|
|
8
8
|
import { cjk } from '@streamdown/cjk';
|
|
9
9
|
import { code } from '@streamdown/code';
|
|
@@ -3304,13 +3304,16 @@ function ClarifyLocked({
|
|
|
3304
3304
|
}) })
|
|
3305
3305
|
] });
|
|
3306
3306
|
}
|
|
3307
|
-
function ArtifactToolBlock({
|
|
3308
|
-
|
|
3307
|
+
function ArtifactToolBlock({
|
|
3308
|
+
tc,
|
|
3309
|
+
resolvedName
|
|
3310
|
+
}) {
|
|
3309
3311
|
const status = effectiveStatus(tc);
|
|
3310
3312
|
const label = status === "running" ? "Creating artifact\u2026" : status === "error" ? "Creating artifact\u2026" : "Created";
|
|
3313
|
+
const name = resolvedName ?? parseArgs(tc.args)?.name;
|
|
3311
3314
|
return /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-sm ", children: [
|
|
3312
3315
|
/* @__PURE__ */ jsx("span", { className: "font-semibold text-foreground", children: label }),
|
|
3313
|
-
|
|
3316
|
+
name && /* @__PURE__ */ jsx("span", { className: "text-muted-foreground truncate", children: name })
|
|
3314
3317
|
] });
|
|
3315
3318
|
}
|
|
3316
3319
|
function firstLine(s) {
|
|
@@ -3636,7 +3639,11 @@ function DefaultToolBlock({ tc }) {
|
|
|
3636
3639
|
] })
|
|
3637
3640
|
] });
|
|
3638
3641
|
}
|
|
3639
|
-
function ToolCallBlock({
|
|
3642
|
+
function ToolCallBlock({
|
|
3643
|
+
tc,
|
|
3644
|
+
resolvedArtifactName,
|
|
3645
|
+
onFileSelect
|
|
3646
|
+
}) {
|
|
3640
3647
|
switch (tc.toolName) {
|
|
3641
3648
|
case "terminal":
|
|
3642
3649
|
return /* @__PURE__ */ jsx(TerminalToolBlock, { tc });
|
|
@@ -3673,7 +3680,7 @@ function ToolCallBlock({ tc, onFileSelect }) {
|
|
|
3673
3680
|
case "clarify":
|
|
3674
3681
|
return /* @__PURE__ */ jsx(ClarifyToolBlock, { tc });
|
|
3675
3682
|
case "create_artifact":
|
|
3676
|
-
return /* @__PURE__ */ jsx(ArtifactToolBlock, { tc });
|
|
3683
|
+
return /* @__PURE__ */ jsx(ArtifactToolBlock, { tc, resolvedName: resolvedArtifactName });
|
|
3677
3684
|
case "delegate_task":
|
|
3678
3685
|
return /* @__PURE__ */ jsx(DelegateToolBlock, { tc });
|
|
3679
3686
|
case "memory":
|
|
@@ -5055,6 +5062,7 @@ function ChatComposerInner({
|
|
|
5055
5062
|
onStop,
|
|
5056
5063
|
isRunning,
|
|
5057
5064
|
disabled = false,
|
|
5065
|
+
disabledReason,
|
|
5058
5066
|
tokenUsage
|
|
5059
5067
|
}) {
|
|
5060
5068
|
const { adapter } = useAgentChatAdapterContext();
|
|
@@ -5083,7 +5091,10 @@ function ChatComposerInner({
|
|
|
5083
5091
|
const slashCommands = useMemo(() => {
|
|
5084
5092
|
const builtin = [
|
|
5085
5093
|
{ value: "/clear", label: "/clear", description: "Clear conversation" },
|
|
5086
|
-
{ value: "/compress", label: "/compress", description: "Compress context" }
|
|
5094
|
+
{ value: "/compress", label: "/compress", description: "Compress context" },
|
|
5095
|
+
{ value: "/loop", label: "/loop", description: "Schedule recurring prompt" },
|
|
5096
|
+
{ value: "/loop list", label: "/loop list", description: "List active loops" },
|
|
5097
|
+
{ value: "/loop cancel", label: "/loop cancel", description: "Cancel a loop by ID" }
|
|
5087
5098
|
];
|
|
5088
5099
|
return [...adapterCommands, ...builtin];
|
|
5089
5100
|
}, [adapterCommands]);
|
|
@@ -5162,7 +5173,7 @@ function ChatComposerInner({
|
|
|
5162
5173
|
/* @__PURE__ */ jsx(PromptInputBody, { children: /* @__PURE__ */ jsx(
|
|
5163
5174
|
PromptInputTextarea,
|
|
5164
5175
|
{
|
|
5165
|
-
placeholder: disabled ? "Session disabled" : "Send a message...",
|
|
5176
|
+
placeholder: disabled ? disabledReason ?? "Session disabled" : "Send a message...",
|
|
5166
5177
|
disabled,
|
|
5167
5178
|
onKeyDown: handleKeyDown
|
|
5168
5179
|
}
|
|
@@ -5807,7 +5818,7 @@ var ErrorMessage = memo(function ErrorMessage2({
|
|
|
5807
5818
|
}
|
|
5808
5819
|
);
|
|
5809
5820
|
});
|
|
5810
|
-
function messageToEntries(msg, isLast) {
|
|
5821
|
+
function messageToEntries(msg, isLast, artifactFallbacks) {
|
|
5811
5822
|
if (msg.role === "system") {
|
|
5812
5823
|
if (msg.systemKind === "skill_invoked") {
|
|
5813
5824
|
return [{
|
|
@@ -5849,6 +5860,18 @@ function messageToEntries(msg, isLast) {
|
|
|
5849
5860
|
}
|
|
5850
5861
|
if (hasToolCalls) {
|
|
5851
5862
|
for (const tc of msg.toolCalls) {
|
|
5863
|
+
if (tc.toolName === "create_artifact") {
|
|
5864
|
+
const resolvedName = parseArgs(tc.args)?.name ?? artifactFallbacks[tc.id];
|
|
5865
|
+
const status = effectiveStatus(tc);
|
|
5866
|
+
if (!resolvedName && status !== "error") continue;
|
|
5867
|
+
entries.push({
|
|
5868
|
+
kind: "tool",
|
|
5869
|
+
key: tc.id,
|
|
5870
|
+
tc,
|
|
5871
|
+
resolvedArtifactName: resolvedName
|
|
5872
|
+
});
|
|
5873
|
+
continue;
|
|
5874
|
+
}
|
|
5852
5875
|
entries.push({ kind: "tool", key: tc.id, tc });
|
|
5853
5876
|
}
|
|
5854
5877
|
}
|
|
@@ -6007,7 +6030,14 @@ function TimelineEntryItem({
|
|
|
6007
6030
|
)
|
|
6008
6031
|
] }),
|
|
6009
6032
|
/* @__PURE__ */ jsx(TimelineContent, { children: entry.tc.cancelled ? /* @__PURE__ */ jsx(CancelledToolRow, { tc: entry.tc }) : /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
6010
|
-
/* @__PURE__ */ jsx(
|
|
6033
|
+
/* @__PURE__ */ jsx(
|
|
6034
|
+
ToolCallBlock,
|
|
6035
|
+
{
|
|
6036
|
+
tc: entry.tc,
|
|
6037
|
+
resolvedArtifactName: entry.resolvedArtifactName,
|
|
6038
|
+
onFileSelect
|
|
6039
|
+
}
|
|
6040
|
+
),
|
|
6011
6041
|
failureSummary ? /* @__PURE__ */ jsx("div", { className: "max-w-full truncate text-xs text-destructive", title: failureSummary, children: failureSummary }) : null
|
|
6012
6042
|
] }) })
|
|
6013
6043
|
] });
|
|
@@ -6069,13 +6099,14 @@ function AssistantGroup({
|
|
|
6069
6099
|
totalMessages,
|
|
6070
6100
|
isRunning,
|
|
6071
6101
|
sessionId,
|
|
6102
|
+
artifactFallbacks,
|
|
6072
6103
|
onFileSelect,
|
|
6073
6104
|
onRetry
|
|
6074
6105
|
}) {
|
|
6075
6106
|
const entries = [];
|
|
6076
6107
|
for (let i = 0; i < messages.length; i++) {
|
|
6077
6108
|
const isLast = i === messages.length - 1 && lastGlobalIndex === totalMessages - 1;
|
|
6078
|
-
entries.push(...messageToEntries(messages[i], isLast));
|
|
6109
|
+
entries.push(...messageToEntries(messages[i], isLast, artifactFallbacks));
|
|
6079
6110
|
}
|
|
6080
6111
|
const isTailGroup = lastGlobalIndex === totalMessages - 1;
|
|
6081
6112
|
const lastEntry = entries[entries.length - 1];
|
|
@@ -6142,11 +6173,34 @@ function ChatThread({
|
|
|
6142
6173
|
onStop,
|
|
6143
6174
|
onFileSelect,
|
|
6144
6175
|
disabled = false,
|
|
6176
|
+
disabledReason,
|
|
6145
6177
|
tokenUsage,
|
|
6146
6178
|
retryIndicator,
|
|
6147
6179
|
onRetry
|
|
6148
6180
|
}) {
|
|
6149
6181
|
const groups = useMemo(() => groupMessages(messages), [messages]);
|
|
6182
|
+
const artifactFallbacks = useMemo(() => {
|
|
6183
|
+
const fallbacks = {};
|
|
6184
|
+
const createArtifactToolCallIds = [];
|
|
6185
|
+
let artifactIdx = 0;
|
|
6186
|
+
for (const msg of messages) {
|
|
6187
|
+
if (msg.role === "assistant" && msg.toolCalls) {
|
|
6188
|
+
for (const tc of msg.toolCalls) {
|
|
6189
|
+
if (tc.toolName === "create_artifact" && !tc.cancelled && tc.status !== "error") {
|
|
6190
|
+
createArtifactToolCallIds.push(tc.id);
|
|
6191
|
+
}
|
|
6192
|
+
}
|
|
6193
|
+
} else if (msg.role === "system" && msg.systemKind === "artifact") {
|
|
6194
|
+
const tcId = createArtifactToolCallIds[artifactIdx];
|
|
6195
|
+
if (tcId) {
|
|
6196
|
+
const { name } = unpackArtifactMeta(msg.systemMeta, msg.content);
|
|
6197
|
+
if (name) fallbacks[tcId] = name;
|
|
6198
|
+
}
|
|
6199
|
+
artifactIdx += 1;
|
|
6200
|
+
}
|
|
6201
|
+
}
|
|
6202
|
+
return fallbacks;
|
|
6203
|
+
}, [messages]);
|
|
6150
6204
|
const activeFailureId = useMemo(() => {
|
|
6151
6205
|
if (messages.length === 0) return null;
|
|
6152
6206
|
const tail = messages[messages.length - 1];
|
|
@@ -6211,6 +6265,7 @@ function ChatThread({
|
|
|
6211
6265
|
totalMessages: messages.length,
|
|
6212
6266
|
isRunning,
|
|
6213
6267
|
sessionId,
|
|
6268
|
+
artifactFallbacks,
|
|
6214
6269
|
onFileSelect,
|
|
6215
6270
|
onRetry: groupRetry
|
|
6216
6271
|
},
|
|
@@ -6223,13 +6278,21 @@ function ChatThread({
|
|
|
6223
6278
|
] }),
|
|
6224
6279
|
/* @__PURE__ */ jsxs("div", { className: "mx-auto w-full max-w-4xl px-6 pb-5 pt-3", children: [
|
|
6225
6280
|
retryIndicator && /* @__PURE__ */ jsx("div", { className: "mb-2", children: /* @__PURE__ */ jsx(RetryBanner, { indicator: retryIndicator }) }),
|
|
6226
|
-
/* @__PURE__ */ jsx(
|
|
6281
|
+
disabled && disabledReason ? /* @__PURE__ */ jsx(
|
|
6282
|
+
"div",
|
|
6283
|
+
{
|
|
6284
|
+
className: "rounded border border-line bg-muted/40 px-3 py-2 text-sm text-muted-foreground",
|
|
6285
|
+
role: "status",
|
|
6286
|
+
children: disabledReason
|
|
6287
|
+
}
|
|
6288
|
+
) : /* @__PURE__ */ jsx(
|
|
6227
6289
|
ChatComposer,
|
|
6228
6290
|
{
|
|
6229
6291
|
onSend,
|
|
6230
6292
|
onStop,
|
|
6231
6293
|
isRunning,
|
|
6232
6294
|
disabled,
|
|
6295
|
+
disabledReason,
|
|
6233
6296
|
tokenUsage
|
|
6234
6297
|
}
|
|
6235
6298
|
)
|
|
@@ -7058,7 +7121,7 @@ function WorkspacePanel({
|
|
|
7058
7121
|
);
|
|
7059
7122
|
const handleDelete = useCallback(
|
|
7060
7123
|
async (path) => {
|
|
7061
|
-
if (!sessionId) return;
|
|
7124
|
+
if (disabled || !sessionId) return;
|
|
7062
7125
|
try {
|
|
7063
7126
|
await adapter.deleteWorkspaceFile({ sessionId, path });
|
|
7064
7127
|
if (selectedPath === path) {
|
|
@@ -7074,7 +7137,7 @@ function WorkspacePanel({
|
|
|
7074
7137
|
setDeleteTarget(null);
|
|
7075
7138
|
}
|
|
7076
7139
|
},
|
|
7077
|
-
[adapter, fetchTree, onSelectedPathChange, selectedPath, sessionId]
|
|
7140
|
+
[adapter, disabled, fetchTree, onSelectedPathChange, selectedPath, sessionId]
|
|
7078
7141
|
);
|
|
7079
7142
|
const onResizeStart = useCallback(
|
|
7080
7143
|
(event) => {
|
|
@@ -7157,7 +7220,7 @@ function WorkspacePanel({
|
|
|
7157
7220
|
/* @__PURE__ */ jsx(FolderOpenIcon, { className: "size-4 shrink-0 text-amber-500" }),
|
|
7158
7221
|
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
7159
7222
|
/* @__PURE__ */ jsx("div", { className: "truncate text-sm font-medium text-foreground", children: rootName }),
|
|
7160
|
-
/* @__PURE__ */ jsx("div", { className: "truncate text-xs text-faint", children: "Workspace" })
|
|
7223
|
+
/* @__PURE__ */ jsx("div", { className: "truncate text-xs text-faint", children: disabled ? "Workspace - Read-only" : "Workspace" })
|
|
7161
7224
|
] }),
|
|
7162
7225
|
/* @__PURE__ */ jsxs(Tooltip, { children: [
|
|
7163
7226
|
/* @__PURE__ */ jsx(TooltipTrigger, { asChild: true, children: /* @__PURE__ */ jsx(
|
|
@@ -7268,7 +7331,7 @@ function WorkspacePanel({
|
|
|
7268
7331
|
sessionId,
|
|
7269
7332
|
path: file.path
|
|
7270
7333
|
}) : null,
|
|
7271
|
-
onDelete: file ? () => setDeleteTarget(file.path) : null,
|
|
7334
|
+
onDelete: file && !disabled ? () => setDeleteTarget(file.path) : null,
|
|
7272
7335
|
onClose: () => {
|
|
7273
7336
|
onSelectedPathChange(null);
|
|
7274
7337
|
setFile(null);
|
|
@@ -7332,6 +7395,13 @@ function ConfirmDialog({
|
|
|
7332
7395
|
);
|
|
7333
7396
|
}
|
|
7334
7397
|
|
|
7398
|
+
// src/lib/sessions.ts
|
|
7399
|
+
function isScheduledRunSession(session) {
|
|
7400
|
+
return Boolean(
|
|
7401
|
+
session?.channel === "scheduled" || session?.config?.scheduled_session_id
|
|
7402
|
+
);
|
|
7403
|
+
}
|
|
7404
|
+
|
|
7335
7405
|
// src/runtime/events.ts
|
|
7336
7406
|
var WORKSPACE_MUTATING_TOOLS = /* @__PURE__ */ new Set([
|
|
7337
7407
|
"terminal",
|
|
@@ -7944,6 +8014,7 @@ function useAgentChatRuntime({
|
|
|
7944
8014
|
const [state, setState] = useState(
|
|
7945
8015
|
() => createInitialAgentChatState({ isLoadingHistory: Boolean(sessionId) })
|
|
7946
8016
|
);
|
|
8017
|
+
const [session, setSession] = useState(null);
|
|
7947
8018
|
const stateRef = useRef(state);
|
|
7948
8019
|
const streamRef = useRef(null);
|
|
7949
8020
|
const reconnectTimerRef = useRef(null);
|
|
@@ -7968,6 +8039,7 @@ function useAgentChatRuntime({
|
|
|
7968
8039
|
clearReconnectTimer();
|
|
7969
8040
|
closeStream();
|
|
7970
8041
|
if (!sessionId) {
|
|
8042
|
+
setSession(null);
|
|
7971
8043
|
setState(createInitialAgentChatState());
|
|
7972
8044
|
return;
|
|
7973
8045
|
}
|
|
@@ -8015,17 +8087,19 @@ function useAgentChatRuntime({
|
|
|
8015
8087
|
isLoadingHistory: true
|
|
8016
8088
|
});
|
|
8017
8089
|
stateRef.current = initialState;
|
|
8090
|
+
setSession(null);
|
|
8018
8091
|
setState(initialState);
|
|
8019
8092
|
connect(0);
|
|
8020
|
-
adapter.getSession({ sessionId }).then((
|
|
8093
|
+
adapter.getSession({ sessionId }).then((loadedSession) => {
|
|
8021
8094
|
if (cancelled) return;
|
|
8022
|
-
|
|
8095
|
+
setSession(loadedSession);
|
|
8096
|
+
if (loadedSession.messageCount === 0) {
|
|
8023
8097
|
setState((prev) => ({
|
|
8024
8098
|
...prev,
|
|
8025
8099
|
isLoadingHistory: false
|
|
8026
8100
|
}));
|
|
8027
8101
|
}
|
|
8028
|
-
if (isTerminalStatus(
|
|
8102
|
+
if (isTerminalStatus(loadedSession.status)) {
|
|
8029
8103
|
setState((prev) => ({
|
|
8030
8104
|
...prev,
|
|
8031
8105
|
terminal: true,
|
|
@@ -8114,9 +8188,9 @@ function useAgentChatRuntime({
|
|
|
8114
8188
|
markSending(content, images);
|
|
8115
8189
|
if (!sessionId) {
|
|
8116
8190
|
try {
|
|
8117
|
-
const
|
|
8118
|
-
onSessionChange?.(
|
|
8119
|
-
await adapter.sendMessage({ sessionId:
|
|
8191
|
+
const session2 = await adapter.createSession({ agentId });
|
|
8192
|
+
onSessionChange?.(session2.id);
|
|
8193
|
+
await adapter.sendMessage({ sessionId: session2.id, content, images });
|
|
8120
8194
|
} catch (error) {
|
|
8121
8195
|
markSendError(error instanceof Error ? error.message : "send failed");
|
|
8122
8196
|
throw error;
|
|
@@ -8157,6 +8231,7 @@ function useAgentChatRuntime({
|
|
|
8157
8231
|
}
|
|
8158
8232
|
}, [adapter, sessionId]);
|
|
8159
8233
|
return {
|
|
8234
|
+
session,
|
|
8160
8235
|
messages: state.messages,
|
|
8161
8236
|
isRunning: state.isRunning,
|
|
8162
8237
|
isLoadingHistory: state.isLoadingHistory,
|
|
@@ -8204,6 +8279,9 @@ function AgentChat({
|
|
|
8204
8279
|
sessionId,
|
|
8205
8280
|
onSessionChange
|
|
8206
8281
|
});
|
|
8282
|
+
const isReadOnlySession = isScheduledRunSession(runtime.session);
|
|
8283
|
+
const effectiveDisabled = disabled || isReadOnlySession;
|
|
8284
|
+
const disabledReason = isReadOnlySession ? "Scheduled run is read-only" : void 0;
|
|
8207
8285
|
useEffect(() => {
|
|
8208
8286
|
onMessagesChange?.(runtime.messages);
|
|
8209
8287
|
}, [onMessagesChange, runtime.messages]);
|
|
@@ -8234,7 +8312,8 @@ function AgentChat({
|
|
|
8234
8312
|
onStop: () => void runtime.stop(),
|
|
8235
8313
|
onRetry: runtime.retry,
|
|
8236
8314
|
onFileSelect: handleFileSelect,
|
|
8237
|
-
disabled,
|
|
8315
|
+
disabled: effectiveDisabled,
|
|
8316
|
+
disabledReason,
|
|
8238
8317
|
tokenUsage: runtime.tokenUsage,
|
|
8239
8318
|
retryIndicator: runtime.retryIndicator
|
|
8240
8319
|
}
|
|
@@ -8249,13 +8328,313 @@ function AgentChat({
|
|
|
8249
8328
|
collapsed: workspaceCollapsed,
|
|
8250
8329
|
onCollapsedChange: setWorkspaceCollapsed,
|
|
8251
8330
|
refreshSignal: runtime.workspaceRefreshKey,
|
|
8252
|
-
disabled
|
|
8331
|
+
disabled: effectiveDisabled
|
|
8253
8332
|
}
|
|
8254
8333
|
)
|
|
8255
8334
|
] }) })
|
|
8256
8335
|
}
|
|
8257
8336
|
);
|
|
8258
8337
|
}
|
|
8338
|
+
var DEFAULT_LIMIT = 50;
|
|
8339
|
+
var DEFAULT_POLL_INTERVAL_MS = 3e4;
|
|
8340
|
+
function fingerprint(items) {
|
|
8341
|
+
return items.map(
|
|
8342
|
+
(item) => `${item.id}:${item.status}:${item.kind ?? ""}:${item.name ?? ""}:${item.prompt}:${item.scheduleDisplay}:${item.runCount}:${item.nextRunAt ?? ""}:${item.lastRunAt ?? ""}:${item.lastSessionId ?? ""}:${item.lastError ?? ""}:${item.updatedAt}`
|
|
8343
|
+
).join("|");
|
|
8344
|
+
}
|
|
8345
|
+
function formatKind(value) {
|
|
8346
|
+
if (value === "dynamic_loop") return "Dynamic loop";
|
|
8347
|
+
if (value === "cron") return "Cron";
|
|
8348
|
+
if (value === "one_shot") return "One-shot";
|
|
8349
|
+
if (value === "scheduled") return "Scheduled";
|
|
8350
|
+
if (!value) return "Scheduled";
|
|
8351
|
+
return value.split(/[_-]+/).filter(Boolean).map((part) => part.charAt(0).toUpperCase() + part.slice(1)).join(" ");
|
|
8352
|
+
}
|
|
8353
|
+
function formatRelative(value, label) {
|
|
8354
|
+
if (!value) return null;
|
|
8355
|
+
const date = new Date(value);
|
|
8356
|
+
if (Number.isNaN(date.getTime())) return null;
|
|
8357
|
+
return `${label} ${formatDistanceToNow(date, { addSuffix: true })}`;
|
|
8358
|
+
}
|
|
8359
|
+
function formatRuns(count) {
|
|
8360
|
+
return `${count} ${count === 1 ? "run" : "runs"}`;
|
|
8361
|
+
}
|
|
8362
|
+
function scheduleTitle(item) {
|
|
8363
|
+
const title = item.name?.trim();
|
|
8364
|
+
if (title) return title;
|
|
8365
|
+
return item.prompt;
|
|
8366
|
+
}
|
|
8367
|
+
function canRunScheduleNow(item) {
|
|
8368
|
+
return item.repeatLimit === 1;
|
|
8369
|
+
}
|
|
8370
|
+
function scheduleDisplay(item) {
|
|
8371
|
+
if (item.kind === "dynamic_loop") return null;
|
|
8372
|
+
return item.scheduleDisplay;
|
|
8373
|
+
}
|
|
8374
|
+
function sortScheduledWork(items) {
|
|
8375
|
+
return [...items].sort((a, b) => {
|
|
8376
|
+
if (a.status === "active" && b.status !== "active") return -1;
|
|
8377
|
+
if (a.status !== "active" && b.status === "active") return 1;
|
|
8378
|
+
const aNext = a.nextRunAt ?? "";
|
|
8379
|
+
const bNext = b.nextRunAt ?? "";
|
|
8380
|
+
if (aNext && bNext && aNext !== bNext) return aNext < bNext ? -1 : 1;
|
|
8381
|
+
if (aNext && !bNext) return -1;
|
|
8382
|
+
if (!aNext && bNext) return 1;
|
|
8383
|
+
return (a.updatedAt ?? "") > (b.updatedAt ?? "") ? -1 : 1;
|
|
8384
|
+
});
|
|
8385
|
+
}
|
|
8386
|
+
function ScheduledWorkRow({
|
|
8387
|
+
item,
|
|
8388
|
+
canRunNow,
|
|
8389
|
+
canCancel,
|
|
8390
|
+
actionScheduleId,
|
|
8391
|
+
onOpenLastRun,
|
|
8392
|
+
onRunNow,
|
|
8393
|
+
onCancel
|
|
8394
|
+
}) {
|
|
8395
|
+
const isActive = item.status === "active";
|
|
8396
|
+
const disabled = actionScheduleId === item.id;
|
|
8397
|
+
const title = scheduleTitle(item);
|
|
8398
|
+
const statusText = item.status === "active" ? null : item.status;
|
|
8399
|
+
const showRunNow = canRunNow && isActive && canRunScheduleNow(item);
|
|
8400
|
+
const lastSessionId = item.lastSessionId ?? null;
|
|
8401
|
+
const meta = [
|
|
8402
|
+
scheduleDisplay(item),
|
|
8403
|
+
formatRelative(item.nextRunAt, "Next"),
|
|
8404
|
+
formatRelative(item.lastRunAt, "Last"),
|
|
8405
|
+
formatRuns(item.runCount),
|
|
8406
|
+
item.expiresAt ? formatRelative(item.expiresAt, "Expires") : null
|
|
8407
|
+
].filter(Boolean);
|
|
8408
|
+
const openLastRun = () => {
|
|
8409
|
+
if (lastSessionId) onOpenLastRun(lastSessionId);
|
|
8410
|
+
};
|
|
8411
|
+
const handleRowKeyDown = (e) => {
|
|
8412
|
+
if (!lastSessionId) return;
|
|
8413
|
+
if (e.key !== "Enter" && e.key !== " ") return;
|
|
8414
|
+
e.preventDefault();
|
|
8415
|
+
openLastRun();
|
|
8416
|
+
};
|
|
8417
|
+
const stopActionClick = (e) => {
|
|
8418
|
+
e.stopPropagation();
|
|
8419
|
+
};
|
|
8420
|
+
return /* @__PURE__ */ jsxs(
|
|
8421
|
+
"div",
|
|
8422
|
+
{
|
|
8423
|
+
className: cn(
|
|
8424
|
+
"group flex min-w-0 items-start gap-2 border-l-2 border-l-transparent px-3 py-2 text-sm transition-colors hover:border-l-primary hover:bg-input",
|
|
8425
|
+
lastSessionId && "cursor-pointer"
|
|
8426
|
+
),
|
|
8427
|
+
onClick: openLastRun,
|
|
8428
|
+
onKeyDown: handleRowKeyDown,
|
|
8429
|
+
role: lastSessionId ? "button" : void 0,
|
|
8430
|
+
tabIndex: lastSessionId ? 0 : void 0,
|
|
8431
|
+
"aria-label": lastSessionId ? `Open last run for ${title}` : void 0,
|
|
8432
|
+
title: lastSessionId ? "Open last run" : void 0,
|
|
8433
|
+
children: [
|
|
8434
|
+
/* @__PURE__ */ jsx("div", { className: "mt-0.5 flex size-5 shrink-0 items-center justify-center text-faint", children: /* @__PURE__ */ jsx(CalendarClockIcon, { className: "size-3.5" }) }),
|
|
8435
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
8436
|
+
/* @__PURE__ */ jsxs("div", { className: "flex min-w-0 items-start gap-2", children: [
|
|
8437
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0 flex-1", children: [
|
|
8438
|
+
/* @__PURE__ */ jsx("div", { className: "truncate text-foreground", children: title }),
|
|
8439
|
+
/* @__PURE__ */ jsx("div", { className: "mt-0.5 flex min-w-0 items-center gap-2", children: /* @__PURE__ */ jsx(Badge, { variant: "secondary", className: "shrink-0", children: formatKind(item.kind) }) }),
|
|
8440
|
+
meta.length > 0 && /* @__PURE__ */ jsx("div", { className: "mt-0.5 space-y-0.5 text-xs text-faint", children: meta.map((line) => /* @__PURE__ */ jsx("div", { className: "truncate", children: line }, line)) })
|
|
8441
|
+
] }),
|
|
8442
|
+
statusText && /* @__PURE__ */ jsx(Badge, { variant: "destructive", className: "shrink-0", children: statusText })
|
|
8443
|
+
] }),
|
|
8444
|
+
item.lastError && /* @__PURE__ */ jsx("div", { className: "mt-1 line-clamp-2 text-xs text-destructive", children: item.lastError })
|
|
8445
|
+
] }),
|
|
8446
|
+
/* @__PURE__ */ jsxs("div", { className: "flex shrink-0 items-center gap-1", children: [
|
|
8447
|
+
showRunNow && /* @__PURE__ */ jsx(
|
|
8448
|
+
"button",
|
|
8449
|
+
{
|
|
8450
|
+
type: "button",
|
|
8451
|
+
className: "rounded p-1 text-faint opacity-70 transition-all hover:bg-line hover:text-foreground disabled:pointer-events-none disabled:opacity-40 group-hover:opacity-100",
|
|
8452
|
+
onClick: (e) => {
|
|
8453
|
+
stopActionClick(e);
|
|
8454
|
+
onRunNow(item.id);
|
|
8455
|
+
},
|
|
8456
|
+
"aria-label": "Run schedule now",
|
|
8457
|
+
title: "Run schedule now",
|
|
8458
|
+
disabled,
|
|
8459
|
+
children: /* @__PURE__ */ jsx(CalendarClockIcon, { className: "size-3.5" })
|
|
8460
|
+
}
|
|
8461
|
+
),
|
|
8462
|
+
canCancel && isActive && /* @__PURE__ */ jsx(
|
|
8463
|
+
"button",
|
|
8464
|
+
{
|
|
8465
|
+
type: "button",
|
|
8466
|
+
className: "rounded p-1 text-faint opacity-70 transition-all hover:bg-destructive/10 hover:text-destructive disabled:pointer-events-none disabled:opacity-40 group-hover:opacity-100",
|
|
8467
|
+
onClick: (e) => {
|
|
8468
|
+
stopActionClick(e);
|
|
8469
|
+
onCancel(item.id);
|
|
8470
|
+
},
|
|
8471
|
+
"aria-label": "Cancel schedule",
|
|
8472
|
+
title: "Cancel schedule",
|
|
8473
|
+
disabled,
|
|
8474
|
+
children: /* @__PURE__ */ jsx(Trash2Icon, { className: "size-3.5" })
|
|
8475
|
+
}
|
|
8476
|
+
)
|
|
8477
|
+
] })
|
|
8478
|
+
]
|
|
8479
|
+
}
|
|
8480
|
+
);
|
|
8481
|
+
}
|
|
8482
|
+
function ScheduledWorkPanel({
|
|
8483
|
+
adapter,
|
|
8484
|
+
agentId,
|
|
8485
|
+
title = "Scheduled Work",
|
|
8486
|
+
limit = DEFAULT_LIMIT,
|
|
8487
|
+
status = "active",
|
|
8488
|
+
hideHeader = false,
|
|
8489
|
+
pollIntervalMs = DEFAULT_POLL_INTERVAL_MS,
|
|
8490
|
+
onSessionSelect,
|
|
8491
|
+
onScheduleCancel,
|
|
8492
|
+
onScheduleRunNow
|
|
8493
|
+
}) {
|
|
8494
|
+
const [items, setItems] = useState([]);
|
|
8495
|
+
const [error, setError] = useState(null);
|
|
8496
|
+
const [hasEverLoaded, setHasEverLoaded] = useState(false);
|
|
8497
|
+
const [actionScheduleId, setActionScheduleId] = useState(null);
|
|
8498
|
+
const [collapsed, setCollapsed] = useState(false);
|
|
8499
|
+
const mounted = useRef(true);
|
|
8500
|
+
const requestId = useRef(0);
|
|
8501
|
+
const lastFingerprint = useRef("");
|
|
8502
|
+
const refetch = useCallback(
|
|
8503
|
+
async (opts) => {
|
|
8504
|
+
if (!adapter.listScheduledWork) {
|
|
8505
|
+
setItems([]);
|
|
8506
|
+
setHasEverLoaded(true);
|
|
8507
|
+
return;
|
|
8508
|
+
}
|
|
8509
|
+
const currentRequestId = ++requestId.current;
|
|
8510
|
+
try {
|
|
8511
|
+
const list = await adapter.listScheduledWork({
|
|
8512
|
+
agentId,
|
|
8513
|
+
status,
|
|
8514
|
+
limit
|
|
8515
|
+
});
|
|
8516
|
+
if (!mounted.current || currentRequestId !== requestId.current) return;
|
|
8517
|
+
const nextItems = sortScheduledWork(list.items);
|
|
8518
|
+
const fp = fingerprint(nextItems);
|
|
8519
|
+
if (fp !== lastFingerprint.current) {
|
|
8520
|
+
lastFingerprint.current = fp;
|
|
8521
|
+
setItems(nextItems);
|
|
8522
|
+
}
|
|
8523
|
+
setError(null);
|
|
8524
|
+
setHasEverLoaded(true);
|
|
8525
|
+
} catch (e) {
|
|
8526
|
+
if (!mounted.current || currentRequestId !== requestId.current) return;
|
|
8527
|
+
if (!opts?.silent) {
|
|
8528
|
+
setError(
|
|
8529
|
+
e instanceof Error ? e.message : "Failed to load scheduled work"
|
|
8530
|
+
);
|
|
8531
|
+
setHasEverLoaded(true);
|
|
8532
|
+
}
|
|
8533
|
+
}
|
|
8534
|
+
},
|
|
8535
|
+
[adapter, agentId, limit, status]
|
|
8536
|
+
);
|
|
8537
|
+
useEffect(() => {
|
|
8538
|
+
mounted.current = true;
|
|
8539
|
+
return () => {
|
|
8540
|
+
mounted.current = false;
|
|
8541
|
+
};
|
|
8542
|
+
}, []);
|
|
8543
|
+
useEffect(() => {
|
|
8544
|
+
setError(null);
|
|
8545
|
+
lastFingerprint.current = "";
|
|
8546
|
+
void refetch();
|
|
8547
|
+
}, [refetch]);
|
|
8548
|
+
useEffect(() => {
|
|
8549
|
+
if (!adapter.listScheduledWork || pollIntervalMs <= 0) return;
|
|
8550
|
+
const id = setInterval(() => {
|
|
8551
|
+
void refetch({ silent: true });
|
|
8552
|
+
}, pollIntervalMs);
|
|
8553
|
+
return () => clearInterval(id);
|
|
8554
|
+
}, [adapter.listScheduledWork, pollIntervalMs, refetch]);
|
|
8555
|
+
const activeCount = useMemo(
|
|
8556
|
+
() => items.filter((item) => item.status === "active").length,
|
|
8557
|
+
[items]
|
|
8558
|
+
);
|
|
8559
|
+
const handleOpenLastRun = useCallback(
|
|
8560
|
+
(sessionId) => {
|
|
8561
|
+
onSessionSelect?.(sessionId);
|
|
8562
|
+
},
|
|
8563
|
+
[onSessionSelect]
|
|
8564
|
+
);
|
|
8565
|
+
const handleRunNow = useCallback(
|
|
8566
|
+
async (scheduleId) => {
|
|
8567
|
+
if (!adapter.runScheduledWorkNow || actionScheduleId) return;
|
|
8568
|
+
setActionScheduleId(scheduleId);
|
|
8569
|
+
try {
|
|
8570
|
+
const result = await adapter.runScheduledWorkNow({ scheduleId });
|
|
8571
|
+
onScheduleRunNow?.(scheduleId, result?.sessionId);
|
|
8572
|
+
await refetch({ silent: true });
|
|
8573
|
+
} catch (e) {
|
|
8574
|
+
setError(e instanceof Error ? e.message : "Failed to run schedule");
|
|
8575
|
+
} finally {
|
|
8576
|
+
if (mounted.current) setActionScheduleId(null);
|
|
8577
|
+
}
|
|
8578
|
+
},
|
|
8579
|
+
[actionScheduleId, adapter, onScheduleRunNow, refetch]
|
|
8580
|
+
);
|
|
8581
|
+
const handleCancel = useCallback(
|
|
8582
|
+
async (scheduleId) => {
|
|
8583
|
+
if (!adapter.cancelScheduledWork || actionScheduleId) return;
|
|
8584
|
+
setActionScheduleId(scheduleId);
|
|
8585
|
+
try {
|
|
8586
|
+
await adapter.cancelScheduledWork({ scheduleId });
|
|
8587
|
+
setItems((current) => {
|
|
8588
|
+
const next = current.filter((item) => item.id !== scheduleId);
|
|
8589
|
+
lastFingerprint.current = fingerprint(next);
|
|
8590
|
+
return next;
|
|
8591
|
+
});
|
|
8592
|
+
onScheduleCancel?.(scheduleId);
|
|
8593
|
+
await refetch({ silent: true });
|
|
8594
|
+
} catch (e) {
|
|
8595
|
+
setError(e instanceof Error ? e.message : "Failed to cancel schedule");
|
|
8596
|
+
} finally {
|
|
8597
|
+
if (mounted.current) setActionScheduleId(null);
|
|
8598
|
+
}
|
|
8599
|
+
},
|
|
8600
|
+
[actionScheduleId, adapter, onScheduleCancel, refetch]
|
|
8601
|
+
);
|
|
8602
|
+
if (!hasEverLoaded) return null;
|
|
8603
|
+
if (!adapter.listScheduledWork) return null;
|
|
8604
|
+
const showBody = hideHeader || !collapsed;
|
|
8605
|
+
return /* @__PURE__ */ jsxs("section", { className: "min-w-0 border-t border-line", children: [
|
|
8606
|
+
!hideHeader && /* @__PURE__ */ jsxs(
|
|
8607
|
+
"button",
|
|
8608
|
+
{
|
|
8609
|
+
type: "button",
|
|
8610
|
+
className: "flex w-full items-center gap-1.5 px-3 py-2 text-left text-xs font-semibold uppercase tracking-wide text-foreground transition-colors hover:bg-input",
|
|
8611
|
+
onClick: () => setCollapsed((current) => !current),
|
|
8612
|
+
"aria-expanded": !collapsed,
|
|
8613
|
+
children: [
|
|
8614
|
+
/* @__PURE__ */ jsx(CalendarClockIcon, { className: "size-3.5" }),
|
|
8615
|
+
/* @__PURE__ */ jsx("span", { className: "truncate", children: title }),
|
|
8616
|
+
activeCount > 0 && /* @__PURE__ */ jsx(Badge, { variant: "default", className: "ml-auto", children: activeCount }),
|
|
8617
|
+
collapsed ? /* @__PURE__ */ jsx(ChevronRightIcon, { className: "size-3.5 shrink-0 text-faint" }) : /* @__PURE__ */ jsx(ChevronDownIcon, { className: "size-3.5 shrink-0 text-faint" })
|
|
8618
|
+
]
|
|
8619
|
+
}
|
|
8620
|
+
),
|
|
8621
|
+
showBody && error && /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-xs text-destructive", children: error }),
|
|
8622
|
+
showBody && !error && items.length === 0 && /* @__PURE__ */ jsx("div", { className: "px-3 py-2 text-xs text-faint", children: "No scheduled work" }),
|
|
8623
|
+
showBody && !error && items.length > 0 && /* @__PURE__ */ jsx("div", { className: cn("pb-2", hideHeader && "pt-1"), children: items.map((item) => /* @__PURE__ */ jsx(
|
|
8624
|
+
ScheduledWorkRow,
|
|
8625
|
+
{
|
|
8626
|
+
item,
|
|
8627
|
+
canRunNow: Boolean(adapter.runScheduledWorkNow),
|
|
8628
|
+
canCancel: Boolean(adapter.cancelScheduledWork),
|
|
8629
|
+
actionScheduleId,
|
|
8630
|
+
onOpenLastRun: handleOpenLastRun,
|
|
8631
|
+
onRunNow: handleRunNow,
|
|
8632
|
+
onCancel: handleCancel
|
|
8633
|
+
},
|
|
8634
|
+
item.id
|
|
8635
|
+
)) })
|
|
8636
|
+
] });
|
|
8637
|
+
}
|
|
8259
8638
|
var POLL_INTERVAL_ACTIVE_MS = 4e3;
|
|
8260
8639
|
var POLL_INTERVAL_IDLE_MS = 3e4;
|
|
8261
8640
|
var DEFAULT_SESSION_LIST_LIMIT = 50;
|
|
@@ -8280,7 +8659,7 @@ function buildTree(nodes) {
|
|
|
8280
8659
|
}
|
|
8281
8660
|
function treeFingerprint(nodes) {
|
|
8282
8661
|
return nodes.map(
|
|
8283
|
-
(n) => `${n.id}:${n.parentId ?? ""}:${n.status}:${n.agentType ?? ""}:${n.messageCount ?? 0}:${n.toolCallCount ?? 0}:${n.updatedAt}`
|
|
8662
|
+
(n) => `${n.id}:${n.parentId ?? ""}:${n.status}:${n.agentType ?? ""}:${n.runKind ?? ""}:${n.title ?? ""}:${n.messageCount ?? 0}:${n.toolCallCount ?? 0}:${n.updatedAt}`
|
|
8284
8663
|
).join("|");
|
|
8285
8664
|
}
|
|
8286
8665
|
function sessionToTreeNode(session) {
|
|
@@ -8290,6 +8669,7 @@ function sessionToTreeNode(session) {
|
|
|
8290
8669
|
parentId: session.parentId ?? null,
|
|
8291
8670
|
agentId: session.agentId,
|
|
8292
8671
|
channel: session.channel,
|
|
8672
|
+
runKind: session.runKind ?? deriveRunKind(session.channel, session.config),
|
|
8293
8673
|
status: session.status,
|
|
8294
8674
|
title: session.title,
|
|
8295
8675
|
model: session.model,
|
|
@@ -8338,6 +8718,23 @@ function formatSessionTime(value) {
|
|
|
8338
8718
|
if (Number.isNaN(date.getTime())) return "";
|
|
8339
8719
|
return formatDistanceToNow(date, { addSuffix: true });
|
|
8340
8720
|
}
|
|
8721
|
+
function deriveRunKind(channel, config) {
|
|
8722
|
+
if (channel === "scheduled" && config?.scheduled_dynamic_loop === true) {
|
|
8723
|
+
return "dynamic_loop";
|
|
8724
|
+
}
|
|
8725
|
+
if (channel === "scheduled") return "scheduled";
|
|
8726
|
+
return null;
|
|
8727
|
+
}
|
|
8728
|
+
function formatRunKind(value) {
|
|
8729
|
+
if (value === "dynamic_loop") return "Loop";
|
|
8730
|
+
if (value === "scheduled") return "Scheduled";
|
|
8731
|
+
return null;
|
|
8732
|
+
}
|
|
8733
|
+
function fallbackSessionTitle(entry) {
|
|
8734
|
+
if (entry.runKind === "dynamic_loop") return "Loop run";
|
|
8735
|
+
if (entry.runKind === "scheduled") return "Scheduled run";
|
|
8736
|
+
return "New session";
|
|
8737
|
+
}
|
|
8341
8738
|
function TreeNodeRow({
|
|
8342
8739
|
entry,
|
|
8343
8740
|
depth,
|
|
@@ -8353,9 +8750,11 @@ function TreeNodeRow({
|
|
|
8353
8750
|
const hasChildren = entry.children.length > 0;
|
|
8354
8751
|
const isActive = entry.id === activeSessionId;
|
|
8355
8752
|
const isRunning = entry.status === "active";
|
|
8356
|
-
const
|
|
8357
|
-
const title = entry.title ??
|
|
8753
|
+
const isChildSession = entry.parentId != null;
|
|
8754
|
+
const title = entry.title ?? fallbackSessionTitle(entry);
|
|
8358
8755
|
const subtitle = [
|
|
8756
|
+
formatRunKind(entry.runKind),
|
|
8757
|
+
entry.agentType,
|
|
8359
8758
|
entry.model ?? "default",
|
|
8360
8759
|
formatSessionTime(entry.updatedAt)
|
|
8361
8760
|
].filter(Boolean).join(" \xB7 ");
|
|
@@ -8393,7 +8792,7 @@ function TreeNodeRow({
|
|
|
8393
8792
|
/* @__PURE__ */ jsx("div", { className: "text-sm truncate", children: title }),
|
|
8394
8793
|
/* @__PURE__ */ jsx("div", { className: "text-xs text-faint truncate", children: subtitle })
|
|
8395
8794
|
] }),
|
|
8396
|
-
isRunning && canStop &&
|
|
8795
|
+
isRunning && canStop && isChildSession && /* @__PURE__ */ jsx(
|
|
8397
8796
|
"button",
|
|
8398
8797
|
{
|
|
8399
8798
|
type: "button",
|
|
@@ -8402,8 +8801,8 @@ function TreeNodeRow({
|
|
|
8402
8801
|
e.stopPropagation();
|
|
8403
8802
|
onStop(entry.id);
|
|
8404
8803
|
},
|
|
8405
|
-
"aria-label": "Stop
|
|
8406
|
-
title: "Stop
|
|
8804
|
+
"aria-label": "Stop child session",
|
|
8805
|
+
title: "Stop child session",
|
|
8407
8806
|
children: /* @__PURE__ */ jsx(SquareIcon, { className: "w-3 h-3", fill: "currentColor" })
|
|
8408
8807
|
}
|
|
8409
8808
|
),
|
|
@@ -8604,6 +9003,6 @@ function SessionTreePanel({
|
|
|
8604
9003
|
] });
|
|
8605
9004
|
}
|
|
8606
9005
|
|
|
8607
|
-
export { AgentChat, AgentChatAdapterProvider, MessageResponse, SessionTreePanel, useAgentChatAdapterContext, useAgentChatRuntime };
|
|
9006
|
+
export { AgentChat, AgentChatAdapterProvider, MessageResponse, ScheduledWorkPanel, SessionTreePanel, useAgentChatAdapterContext, useAgentChatRuntime };
|
|
8608
9007
|
//# sourceMappingURL=index.js.map
|
|
8609
9008
|
//# sourceMappingURL=index.js.map
|