@yieldfabric/terminal 1.0.0 → 1.1.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/LICENSE.md +293 -0
- package/NOTICE.md +28 -0
- package/README.md +78 -9
- package/dist/index.cjs +1354 -768
- package/dist/index.d.cts +231 -4
- package/dist/index.d.ts +231 -4
- package/dist/index.js +922 -343
- package/package.json +18 -8
package/dist/index.js
CHANGED
|
@@ -1,8 +1,15 @@
|
|
|
1
1
|
"use client";
|
|
2
|
-
|
|
2
|
+
/*!
|
|
3
|
+
* Copyright (c) 2026 YieldFabric Technologies Ltd, DIFC, UAE.
|
|
4
|
+
* All rights reserved. Proprietary and confidential.
|
|
5
|
+
* Source review requires written authorization; see package LICENSE.md and NOTICE.md.
|
|
6
|
+
* Runtime use requires a separate express license.
|
|
7
|
+
*/
|
|
8
|
+
import React15, { createContext, memo, useMemo, useRef, useEffect, useCallback, useContext, useState, useReducer } from 'react';
|
|
3
9
|
import { X, Check, Plus, FileText, MessageCircle, ChevronRight, Paperclip, FolderOpen, Brain, XCircle, Loader2, Minimize2, Maximize2, AlertTriangle, HelpCircle, ChevronLeft, Pencil, ChevronDown, ExternalLink, Search, Network, Boxes, Settings, Terminal, CheckCircle, ArrowRight, Users, Eye, AlertCircle, CheckCircle2, Copy, Zap, Download, Trash2, Link2 } from 'lucide-react';
|
|
4
10
|
import { jsx, jsxs, Fragment } from 'react/jsx-runtime';
|
|
5
11
|
import ReactMarkdown from 'react-markdown';
|
|
12
|
+
import remarkGfm from 'remark-gfm';
|
|
6
13
|
import { createAvatar } from '@dicebear/core';
|
|
7
14
|
import { avataaars } from '@dicebear/collection';
|
|
8
15
|
import { motion } from 'framer-motion';
|
|
@@ -68,6 +75,7 @@ var BUILT_IN_COMMANDS = [
|
|
|
68
75
|
{ id: "files", label: "/files", description: "List uploaded files for this page working group", category: "built-in" },
|
|
69
76
|
{ id: "ask", label: "/ask", description: "Ask the AI assistant for analysis (streaming)", category: "built-in" },
|
|
70
77
|
{ id: "note", label: "/note", description: "Save a free-form note in this workspace. Type @name to link an entity.", category: "built-in" },
|
|
78
|
+
{ id: "log", label: "/log", description: "Capture what you did or decided as a work item on this workspace\u2019s board.", category: "built-in" },
|
|
71
79
|
{ id: "personal", label: "/personal", description: "Save a free-form note in your personal notebook (visible only to you, even from a team workspace).", category: "built-in" }
|
|
72
80
|
];
|
|
73
81
|
function getBuiltInCommands() {
|
|
@@ -89,23 +97,45 @@ function processStreamLines(buffer, onJsonLine) {
|
|
|
89
97
|
for (const line of lines) {
|
|
90
98
|
const trimmed = line.trim();
|
|
91
99
|
if (!trimmed) continue;
|
|
92
|
-
if (trimmed.startsWith("data:
|
|
93
|
-
const jsonStr = trimmed.substring(
|
|
100
|
+
if (trimmed.startsWith("data:")) {
|
|
101
|
+
const jsonStr = trimmed.substring(5).trimStart();
|
|
102
|
+
let parsed2;
|
|
94
103
|
try {
|
|
95
|
-
|
|
104
|
+
parsed2 = JSON.parse(jsonStr);
|
|
96
105
|
} catch {
|
|
106
|
+
continue;
|
|
97
107
|
}
|
|
108
|
+
onJsonLine(parsed2);
|
|
98
109
|
continue;
|
|
99
110
|
}
|
|
100
111
|
if (trimmed.startsWith(":")) continue;
|
|
112
|
+
let parsed;
|
|
101
113
|
try {
|
|
102
|
-
|
|
114
|
+
parsed = JSON.parse(trimmed);
|
|
103
115
|
} catch {
|
|
116
|
+
continue;
|
|
104
117
|
}
|
|
118
|
+
onJsonLine(parsed);
|
|
105
119
|
}
|
|
106
120
|
return remainder;
|
|
107
121
|
}
|
|
108
122
|
|
|
123
|
+
// src/utils/streamStall.ts
|
|
124
|
+
var SSE_KEEPALIVE_MS = 15e3;
|
|
125
|
+
var SSE_STALL_MS = SSE_KEEPALIVE_MS * 3;
|
|
126
|
+
async function withStallTimeout(work, ms = SSE_STALL_MS, sleep = (d) => new Promise((wake) => setTimeout(wake, d))) {
|
|
127
|
+
let done = false;
|
|
128
|
+
const settled = work.then((value) => {
|
|
129
|
+
done = true;
|
|
130
|
+
return value;
|
|
131
|
+
});
|
|
132
|
+
const stalled = sleep(ms).then(() => {
|
|
133
|
+
if (!done) throw new Error("the connection went quiet");
|
|
134
|
+
return void 0;
|
|
135
|
+
});
|
|
136
|
+
return Promise.race([settled, stalled]);
|
|
137
|
+
}
|
|
138
|
+
|
|
109
139
|
// src/utils/streamingHandler.ts
|
|
110
140
|
async function handleStreamingResponse(url, requestBody, onChunk, onComplete, onError) {
|
|
111
141
|
try {
|
|
@@ -147,6 +177,14 @@ async function handleStreamingResponse(url, requestBody, onChunk, onComplete, on
|
|
|
147
177
|
var handleSSEStream = async (url, body, onChunk, onComplete, onError, options) => {
|
|
148
178
|
const signal = options?.signal;
|
|
149
179
|
const method = options?.method || "POST";
|
|
180
|
+
const stallMs = options?.stallMs ?? SSE_STALL_MS;
|
|
181
|
+
const stallAbort = new AbortController();
|
|
182
|
+
const abortFromCaller = () => stallAbort.abort();
|
|
183
|
+
let reader;
|
|
184
|
+
if (signal) {
|
|
185
|
+
if (signal.aborted) stallAbort.abort();
|
|
186
|
+
else signal.addEventListener("abort", abortFromCaller, { once: true });
|
|
187
|
+
}
|
|
150
188
|
try {
|
|
151
189
|
const requestHeaders = {
|
|
152
190
|
Accept: "text/event-stream",
|
|
@@ -159,7 +197,7 @@ var handleSSEStream = async (url, body, onChunk, onComplete, onError, options) =
|
|
|
159
197
|
headers: requestHeaders,
|
|
160
198
|
body: method === "GET" || method === "HEAD" ? void 0 : JSON.stringify(body),
|
|
161
199
|
cache: "no-store",
|
|
162
|
-
signal
|
|
200
|
+
signal: stallAbort.signal
|
|
163
201
|
});
|
|
164
202
|
if (response.status === 410 && options?.onGone) {
|
|
165
203
|
options.onGone(await response.text());
|
|
@@ -169,19 +207,32 @@ var handleSSEStream = async (url, body, onChunk, onComplete, onError, options) =
|
|
|
169
207
|
const errorText = await response.text();
|
|
170
208
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
171
209
|
}
|
|
172
|
-
|
|
210
|
+
reader = response.body?.getReader();
|
|
173
211
|
if (!reader) {
|
|
174
212
|
throw new Error("No response body reader available");
|
|
175
213
|
}
|
|
176
214
|
const decoder = new TextDecoder();
|
|
177
215
|
let buffer = "";
|
|
178
216
|
let receivedData = false;
|
|
217
|
+
let finalSeen = false;
|
|
218
|
+
let failed = false;
|
|
219
|
+
const dispatch = (chunk) => {
|
|
220
|
+
if (failed) return;
|
|
221
|
+
if (chunk.error) {
|
|
222
|
+
failed = true;
|
|
223
|
+
onError(typeof chunk.error === "string" ? chunk.error : "The assistant could not finish this answer.");
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
if (chunk.is_final === true) finalSeen = true;
|
|
227
|
+
onChunk(chunk);
|
|
228
|
+
};
|
|
179
229
|
while (true) {
|
|
180
230
|
let readResult;
|
|
181
231
|
try {
|
|
182
|
-
readResult = await reader.read();
|
|
232
|
+
readResult = stallMs > 0 ? await withStallTimeout(reader.read(), stallMs) : await reader.read();
|
|
183
233
|
} catch (readError) {
|
|
184
234
|
if (signal?.aborted) return;
|
|
235
|
+
stallAbort.abort();
|
|
185
236
|
console.warn(
|
|
186
237
|
"SSE reader error (connection may have been interrupted):",
|
|
187
238
|
readError.message
|
|
@@ -195,16 +246,31 @@ var handleSSEStream = async (url, body, onChunk, onComplete, onError, options) =
|
|
|
195
246
|
}
|
|
196
247
|
const { done, value } = readResult;
|
|
197
248
|
if (done) {
|
|
198
|
-
|
|
249
|
+
buffer += decoder.decode();
|
|
250
|
+
if (buffer.trim()) processStreamLines(buffer + "\n", dispatch);
|
|
251
|
+
if (failed) return;
|
|
252
|
+
if ((options?.requireFinal ?? true) && !finalSeen) {
|
|
253
|
+
onError("Connection interrupted before the answer was complete. The assistant may still be working.");
|
|
254
|
+
} else onComplete();
|
|
199
255
|
break;
|
|
200
256
|
}
|
|
201
257
|
buffer += decoder.decode(value, { stream: true });
|
|
202
258
|
receivedData = true;
|
|
203
|
-
buffer = processStreamLines(buffer,
|
|
259
|
+
buffer = processStreamLines(buffer, dispatch);
|
|
260
|
+
if (failed) return;
|
|
204
261
|
}
|
|
205
262
|
} catch (error) {
|
|
206
263
|
if (signal?.aborted) return;
|
|
207
264
|
onError(error.message || "Streaming error");
|
|
265
|
+
} finally {
|
|
266
|
+
signal?.removeEventListener("abort", abortFromCaller);
|
|
267
|
+
if (reader) {
|
|
268
|
+
try {
|
|
269
|
+
await reader.cancel();
|
|
270
|
+
} catch {
|
|
271
|
+
}
|
|
272
|
+
reader.releaseLock();
|
|
273
|
+
}
|
|
208
274
|
}
|
|
209
275
|
};
|
|
210
276
|
|
|
@@ -850,7 +916,7 @@ function ScopedReasoningProvider({
|
|
|
850
916
|
() => ({ hasOwnedKgId }),
|
|
851
917
|
[hasOwnedKgId]
|
|
852
918
|
);
|
|
853
|
-
return
|
|
919
|
+
return React15.createElement(
|
|
854
920
|
ScopedReasoningContext.Provider,
|
|
855
921
|
{ value },
|
|
856
922
|
children
|
|
@@ -1079,12 +1145,13 @@ function ShareButton({ content, title }) {
|
|
|
1079
1145
|
"button",
|
|
1080
1146
|
{
|
|
1081
1147
|
onClick: handleShare,
|
|
1082
|
-
className: "
|
|
1148
|
+
className: "inline-flex h-6 w-6 items-center justify-center rounded-md transition-all duration-200 hover:scale-110",
|
|
1083
1149
|
style: {
|
|
1084
1150
|
backgroundColor: done ? "rgba(74,222,128,0.15)" : t.bgRaisedHover,
|
|
1085
1151
|
color: done ? t.success : t.textMuted
|
|
1086
1152
|
},
|
|
1087
1153
|
title: state === "copied" ? "Copied!" : state === "shared" ? "Shared!" : "Share",
|
|
1154
|
+
"aria-label": state === "copied" ? "Link copied" : state === "shared" ? "Shared" : "Share message",
|
|
1088
1155
|
children: done ? /* @__PURE__ */ jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx("path", { d: "M5 12l5 5L20 7" }) }) : /* @__PURE__ */ jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1089
1156
|
/* @__PURE__ */ jsx("path", { d: "M4 12v7a2 2 0 002 2h12a2 2 0 002-2v-7" }),
|
|
1090
1157
|
/* @__PURE__ */ jsx("polyline", { points: "16 6 12 2 8 6" }),
|
|
@@ -1093,11 +1160,30 @@ function ShareButton({ content, title }) {
|
|
|
1093
1160
|
}
|
|
1094
1161
|
);
|
|
1095
1162
|
}
|
|
1163
|
+
|
|
1164
|
+
// src/utils/stripInternalIds.ts
|
|
1165
|
+
var UUID = "[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}";
|
|
1166
|
+
var PREFIXED = `(?:KG|DOC|FRAME|SET|NODE|CHUNK):${UUID}`;
|
|
1167
|
+
var WRAP = "[*_`]*";
|
|
1168
|
+
var PAREN_PREFIXED = new RegExp(`\\s*\\(\\s*${WRAP}${PREFIXED}${WRAP}\\s*\\)`, "g");
|
|
1169
|
+
var PAREN_BARE = new RegExp(`\\s*\\(\\s*${WRAP}${UUID}${WRAP}\\s*\\)`, "g");
|
|
1170
|
+
var BARE_PREFIXED = new RegExp(`${WRAP}${PREFIXED}${WRAP}`, "g");
|
|
1171
|
+
var ID_PHRASE = new RegExp(
|
|
1172
|
+
`\\s*(?:\\(\\s*)?(?:for\\s+|with\\s+)?(?:suggestion|proposal|item|thread|entity|message|document)\\s+id[:\\s]+${WRAP}${UUID}${WRAP}(?:\\s*\\))?`,
|
|
1173
|
+
"gi"
|
|
1174
|
+
);
|
|
1175
|
+
var BARE_UUID = new RegExp(`${WRAP}${UUID}${WRAP}`, "g");
|
|
1176
|
+
function stripInternalIds(text) {
|
|
1177
|
+
if (!text || !/(?:KG|DOC|FRAME|SET|NODE|CHUNK):|-[0-9a-fA-F]{4}-/.test(text)) return text;
|
|
1178
|
+
return text.split(/(```[\s\S]*?```)/g).map(
|
|
1179
|
+
(part) => part.startsWith("```") ? part : part.replace(PAREN_PREFIXED, "").replace(PAREN_BARE, "").replace(BARE_PREFIXED, "").replace(ID_PHRASE, "").replace(BARE_UUID, "").replace(/[ \t]+([,.;:)])/g, "$1").replace(/([^\n ]) {2,}(?=\S)/g, "$1 ")
|
|
1180
|
+
).join("");
|
|
1181
|
+
}
|
|
1096
1182
|
function TimestampRenderer({ timestamp }) {
|
|
1097
1183
|
const t = useTheme();
|
|
1098
1184
|
const [timeString, setTimeString] = useState("");
|
|
1099
1185
|
useEffect(() => {
|
|
1100
|
-
setTimeString(timestamp.toLocaleTimeString());
|
|
1186
|
+
setTimeString(timestamp.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }));
|
|
1101
1187
|
}, [timestamp]);
|
|
1102
1188
|
return /* @__PURE__ */ jsx("div", { className: "text-xs ml-6 mt-1", style: { color: t.textMuted }, children: timeString });
|
|
1103
1189
|
}
|
|
@@ -1118,20 +1204,20 @@ async function gql(url, token, query, variables) {
|
|
|
1118
1204
|
return res.json();
|
|
1119
1205
|
}
|
|
1120
1206
|
function InteractiveActionCard({
|
|
1121
|
-
action,
|
|
1207
|
+
action: action2,
|
|
1122
1208
|
onExecute,
|
|
1123
1209
|
graphqlUrl = "",
|
|
1124
1210
|
authToken = ""
|
|
1125
1211
|
}) {
|
|
1126
1212
|
const t = useTheme();
|
|
1127
1213
|
const initialValues = useMemo(() => {
|
|
1128
|
-
const amount2 =
|
|
1129
|
-
const assetId =
|
|
1130
|
-
const entityId =
|
|
1131
|
-
const walletId =
|
|
1214
|
+
const amount2 = action2.metadata?.formatted_amount || (action2.payload?.arguments?.amount && action2.payload.arguments.amount !== "0" ? action2.payload.arguments.amount : "") || "";
|
|
1215
|
+
const assetId = action2.payload?.arguments?.asset_id || "";
|
|
1216
|
+
const entityId = action2.payload?.arguments?.destination_id || "";
|
|
1217
|
+
const walletId = action2.payload?.arguments?.destination_wallet_id || "";
|
|
1132
1218
|
return { amount: amount2, assetId, entityId, walletId };
|
|
1133
|
-
}, [
|
|
1134
|
-
const [editedAction, setEditedAction] = useState(
|
|
1219
|
+
}, [action2]);
|
|
1220
|
+
const [editedAction, setEditedAction] = useState(action2);
|
|
1135
1221
|
const [entities, setEntities] = useState([]);
|
|
1136
1222
|
const [wallets, setWallets] = useState([]);
|
|
1137
1223
|
const [assets, setAssets] = useState([]);
|
|
@@ -1245,14 +1331,14 @@ function InteractiveActionCard({
|
|
|
1245
1331
|
[assets, entities, wallets]
|
|
1246
1332
|
);
|
|
1247
1333
|
useEffect(() => {
|
|
1248
|
-
if (
|
|
1334
|
+
if (action2.payload?.tool_name === "yieldfabric/send_instant_payment") {
|
|
1249
1335
|
fetchEntities();
|
|
1250
1336
|
fetchAssets();
|
|
1251
1337
|
if (initialValues.entityId) fetchWallets(initialValues.entityId);
|
|
1252
1338
|
}
|
|
1253
1339
|
}, []);
|
|
1254
1340
|
useEffect(() => {
|
|
1255
|
-
if (selectedEntityId &&
|
|
1341
|
+
if (selectedEntityId && action2.payload?.tool_name === "yieldfabric/send_instant_payment") {
|
|
1256
1342
|
const shouldFetch = selectedEntityId !== initialValues.entityId || wallets.length === 0;
|
|
1257
1343
|
if (shouldFetch) fetchWallets(selectedEntityId);
|
|
1258
1344
|
if (selectedEntityId !== initialValues.entityId) {
|
|
@@ -1262,14 +1348,14 @@ function InteractiveActionCard({
|
|
|
1262
1348
|
}
|
|
1263
1349
|
}, [selectedEntityId]);
|
|
1264
1350
|
useEffect(() => {
|
|
1265
|
-
if (
|
|
1351
|
+
if (action2.payload?.tool_name !== "yieldfabric/send_instant_payment") return;
|
|
1266
1352
|
if (initialValues.assetId && assets.length > 0) {
|
|
1267
1353
|
const match = assets.find((a) => a.id === initialValues.assetId) || assets.find(
|
|
1268
1354
|
(a) => a.id.toUpperCase() === initialValues.assetId.toUpperCase()
|
|
1269
1355
|
) || assets.find(
|
|
1270
1356
|
(a) => initialValues.assetId.toUpperCase() === "CBDC" && a.name?.toUpperCase().includes("CBDC")
|
|
1271
|
-
) ||
|
|
1272
|
-
(a) => a.id ===
|
|
1357
|
+
) || action2.metadata?.asset_id && assets.find(
|
|
1358
|
+
(a) => a.id === action2.metadata.asset_id || a.id.toUpperCase() === action2.metadata.asset_id.toUpperCase()
|
|
1273
1359
|
);
|
|
1274
1360
|
if (match && selectedAssetId !== match.id) {
|
|
1275
1361
|
setSelectedAssetId(match.id);
|
|
@@ -1293,11 +1379,11 @@ function InteractiveActionCard({
|
|
|
1293
1379
|
updateActionField("amount", initialValues.amount);
|
|
1294
1380
|
}
|
|
1295
1381
|
}, [assets, entities, wallets]);
|
|
1296
|
-
if (
|
|
1382
|
+
if (action2.payload?.tool_name === "yieldfabric/swap_credit_for_cash") {
|
|
1297
1383
|
return /* @__PURE__ */ jsx(
|
|
1298
1384
|
RedeemCreditCard,
|
|
1299
1385
|
{
|
|
1300
|
-
action,
|
|
1386
|
+
action: action2,
|
|
1301
1387
|
onExecute,
|
|
1302
1388
|
graphqlUrl,
|
|
1303
1389
|
authToken,
|
|
@@ -1308,20 +1394,20 @@ function InteractiveActionCard({
|
|
|
1308
1394
|
}
|
|
1309
1395
|
);
|
|
1310
1396
|
}
|
|
1311
|
-
if (
|
|
1312
|
-
return /* @__PURE__ */ jsx(CompleteSwapCard, { action, onExecute });
|
|
1397
|
+
if (action2.payload?.tool_name === "yieldfabric/complete_swap") {
|
|
1398
|
+
return /* @__PURE__ */ jsx(CompleteSwapCard, { action: action2, onExecute });
|
|
1313
1399
|
}
|
|
1314
|
-
if (
|
|
1315
|
-
return /* @__PURE__ */ jsx(AcceptPaymentCard, { action, onExecute });
|
|
1400
|
+
if (action2.payload?.tool_name === "yieldfabric/accept_payment") {
|
|
1401
|
+
return /* @__PURE__ */ jsx(AcceptPaymentCard, { action: action2, onExecute });
|
|
1316
1402
|
}
|
|
1317
|
-
if (
|
|
1318
|
-
return /* @__PURE__ */ jsx(FileControlsCard, { action, onExecute });
|
|
1403
|
+
if (action2.action_type === "file_controls") {
|
|
1404
|
+
return /* @__PURE__ */ jsx(FileControlsCard, { action: action2, onExecute });
|
|
1319
1405
|
}
|
|
1320
|
-
if (
|
|
1321
|
-
return /* @__PURE__ */ jsx(DownloadSourceCard, { action, onExecute });
|
|
1406
|
+
if (action2.action_type === "download_source") {
|
|
1407
|
+
return /* @__PURE__ */ jsx(DownloadSourceCard, { action: action2, onExecute });
|
|
1322
1408
|
}
|
|
1323
|
-
if (
|
|
1324
|
-
return /* @__PURE__ */ jsx(GenericActionCard, { action, onExecute });
|
|
1409
|
+
if (action2.payload?.tool_name !== "yieldfabric/send_instant_payment") {
|
|
1410
|
+
return /* @__PURE__ */ jsx(GenericActionCard, { action: action2, onExecute });
|
|
1325
1411
|
}
|
|
1326
1412
|
return /* @__PURE__ */ jsxs(
|
|
1327
1413
|
"div",
|
|
@@ -1468,7 +1554,7 @@ function InteractiveActionCard({
|
|
|
1468
1554
|
);
|
|
1469
1555
|
}
|
|
1470
1556
|
function RedeemCreditCard({
|
|
1471
|
-
action,
|
|
1557
|
+
action: action2,
|
|
1472
1558
|
onExecute,
|
|
1473
1559
|
graphqlUrl,
|
|
1474
1560
|
authToken,
|
|
@@ -1478,14 +1564,14 @@ function RedeemCreditCard({
|
|
|
1478
1564
|
setLoadingObligor
|
|
1479
1565
|
}) {
|
|
1480
1566
|
const t = useTheme();
|
|
1481
|
-
const metadata =
|
|
1567
|
+
const metadata = action2.metadata || {};
|
|
1482
1568
|
const formattedAmount = metadata.formatted_amount || metadata.amount || "0.00";
|
|
1483
1569
|
const currency = metadata.currency || "Unknown";
|
|
1484
1570
|
const obligor = metadata.obligor || metadata.obligor_id || "Unknown";
|
|
1485
1571
|
const obligorId = metadata.obligor_id || obligor;
|
|
1486
1572
|
const assetDisplay = formatAssetDisplay(metadata, currency);
|
|
1487
1573
|
useEffect(() => {
|
|
1488
|
-
if (
|
|
1574
|
+
if (action2.payload?.tool_name !== "yieldfabric/swap_credit_for_cash") return;
|
|
1489
1575
|
if (obligorId === "Unknown" || obligor.includes("@")) return;
|
|
1490
1576
|
if (metadata.obligor_name && metadata.obligor_name !== obligorId && !obligorId.includes("-"))
|
|
1491
1577
|
return;
|
|
@@ -1516,7 +1602,7 @@ function RedeemCreditCard({
|
|
|
1516
1602
|
setLoadingObligor(false);
|
|
1517
1603
|
}
|
|
1518
1604
|
})();
|
|
1519
|
-
}, [obligorId,
|
|
1605
|
+
}, [obligorId, action2.payload?.tool_name]);
|
|
1520
1606
|
const obligorDisplay = (() => {
|
|
1521
1607
|
if (obligorEntity?.name) return obligorEntity.name;
|
|
1522
1608
|
if (metadata.obligor_name && metadata.obligor_name !== obligorId && metadata.obligor_name !== obligor)
|
|
@@ -1568,7 +1654,7 @@ function RedeemCreditCard({
|
|
|
1568
1654
|
onClick: (e) => {
|
|
1569
1655
|
e.preventDefault();
|
|
1570
1656
|
e.stopPropagation();
|
|
1571
|
-
onExecute(
|
|
1657
|
+
onExecute(action2);
|
|
1572
1658
|
},
|
|
1573
1659
|
className: "w-full py-2 px-4 text-sm font-medium rounded transition-colors flex items-center justify-center gap-2",
|
|
1574
1660
|
style: { backgroundColor: t.success, color: t.textInverse },
|
|
@@ -1583,12 +1669,12 @@ function RedeemCreditCard({
|
|
|
1583
1669
|
);
|
|
1584
1670
|
}
|
|
1585
1671
|
function CompleteSwapCard({
|
|
1586
|
-
action,
|
|
1672
|
+
action: action2,
|
|
1587
1673
|
onExecute
|
|
1588
1674
|
}) {
|
|
1589
1675
|
const t = useTheme();
|
|
1590
|
-
const metadata =
|
|
1591
|
-
const swapId = metadata.swap_id ||
|
|
1676
|
+
const metadata = action2.metadata || {};
|
|
1677
|
+
const swapId = metadata.swap_id || action2.payload?.arguments?.swap_id || "Unknown";
|
|
1592
1678
|
const initiator = metadata.initiator || "Unknown";
|
|
1593
1679
|
const status = metadata.status || "PENDING";
|
|
1594
1680
|
const deadline = metadata.deadline ? new Date(metadata.deadline).toLocaleString() : "N/A";
|
|
@@ -1650,7 +1736,7 @@ function CompleteSwapCard({
|
|
|
1650
1736
|
onClick: (e) => {
|
|
1651
1737
|
e.preventDefault();
|
|
1652
1738
|
e.stopPropagation();
|
|
1653
|
-
onExecute(
|
|
1739
|
+
onExecute(action2);
|
|
1654
1740
|
},
|
|
1655
1741
|
className: "w-full py-2 px-4 text-sm font-medium rounded transition-colors flex items-center justify-center gap-2",
|
|
1656
1742
|
style: { backgroundColor: t.success, color: t.textInverse },
|
|
@@ -1692,11 +1778,11 @@ function PaymentLeg({
|
|
|
1692
1778
|
] });
|
|
1693
1779
|
}
|
|
1694
1780
|
function AcceptPaymentCard({
|
|
1695
|
-
action,
|
|
1781
|
+
action: action2,
|
|
1696
1782
|
onExecute
|
|
1697
1783
|
}) {
|
|
1698
1784
|
const t = useTheme();
|
|
1699
|
-
const metadata =
|
|
1785
|
+
const metadata = action2.metadata || {};
|
|
1700
1786
|
const formattedAmount = metadata.formatted_amount || metadata.amount || "0.00";
|
|
1701
1787
|
const currency = metadata.currency || "Unknown";
|
|
1702
1788
|
const from = metadata.from || "Unknown";
|
|
@@ -1756,7 +1842,7 @@ function AcceptPaymentCard({
|
|
|
1756
1842
|
onClick: (e) => {
|
|
1757
1843
|
e.preventDefault();
|
|
1758
1844
|
e.stopPropagation();
|
|
1759
|
-
onExecute(
|
|
1845
|
+
onExecute(action2);
|
|
1760
1846
|
},
|
|
1761
1847
|
className: "w-full py-1.5 px-3 text-xs font-medium rounded transition-colors flex items-center justify-center gap-1.5 mt-auto",
|
|
1762
1848
|
style: { backgroundColor: t.success, color: t.textInverse },
|
|
@@ -1771,12 +1857,12 @@ function AcceptPaymentCard({
|
|
|
1771
1857
|
);
|
|
1772
1858
|
}
|
|
1773
1859
|
function FileControlsCard({
|
|
1774
|
-
action,
|
|
1860
|
+
action: action2,
|
|
1775
1861
|
onExecute
|
|
1776
1862
|
}) {
|
|
1777
1863
|
const t = useTheme();
|
|
1778
|
-
const title =
|
|
1779
|
-
const documentId =
|
|
1864
|
+
const title = action2.payload?.title || "Document";
|
|
1865
|
+
const documentId = action2.payload?.document_id;
|
|
1780
1866
|
const doDownload = (e) => {
|
|
1781
1867
|
e.preventDefault();
|
|
1782
1868
|
e.stopPropagation();
|
|
@@ -1835,18 +1921,18 @@ function FileControlsCard({
|
|
|
1835
1921
|
);
|
|
1836
1922
|
}
|
|
1837
1923
|
function DownloadSourceCard({
|
|
1838
|
-
action,
|
|
1924
|
+
action: action2,
|
|
1839
1925
|
onExecute
|
|
1840
1926
|
}) {
|
|
1841
1927
|
const t = useTheme();
|
|
1842
|
-
const title =
|
|
1928
|
+
const title = action2.payload?.title || action2.metadata?.display_text || action2.description || "Document";
|
|
1843
1929
|
return /* @__PURE__ */ jsx(
|
|
1844
1930
|
"button",
|
|
1845
1931
|
{
|
|
1846
1932
|
onClick: (e) => {
|
|
1847
1933
|
e.preventDefault();
|
|
1848
1934
|
e.stopPropagation();
|
|
1849
|
-
onExecute(
|
|
1935
|
+
onExecute(action2);
|
|
1850
1936
|
},
|
|
1851
1937
|
className: "relative overflow-hidden w-full p-3 rounded-lg transition-all duration-200 text-left group",
|
|
1852
1938
|
style: { backgroundColor: t.buttonBg, border: `1px solid ${t.border}` },
|
|
@@ -1866,7 +1952,7 @@ function DownloadSourceCard({
|
|
|
1866
1952
|
);
|
|
1867
1953
|
}
|
|
1868
1954
|
function GenericActionCard({
|
|
1869
|
-
action,
|
|
1955
|
+
action: action2,
|
|
1870
1956
|
onExecute
|
|
1871
1957
|
}) {
|
|
1872
1958
|
const t = useTheme();
|
|
@@ -1876,14 +1962,14 @@ function GenericActionCard({
|
|
|
1876
1962
|
onClick: (e) => {
|
|
1877
1963
|
e.preventDefault();
|
|
1878
1964
|
e.stopPropagation();
|
|
1879
|
-
onExecute(
|
|
1965
|
+
onExecute(action2);
|
|
1880
1966
|
},
|
|
1881
1967
|
className: "flex items-center space-x-3 p-3 rounded-lg transition-colors text-left group",
|
|
1882
1968
|
style: { backgroundColor: GREEN_ACTION.bg, border: GREEN_ACTION.borderStyle },
|
|
1883
1969
|
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = GREEN_ACTION.bgHover,
|
|
1884
1970
|
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = GREEN_ACTION.bg,
|
|
1885
1971
|
children: [
|
|
1886
|
-
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx("div", { className: "font-medium text-sm mb-1.5", style: { color: t.success }, children:
|
|
1972
|
+
/* @__PURE__ */ jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsx("div", { className: "font-medium text-sm mb-1.5", style: { color: t.success }, children: action2.metadata?.display_text || action2.description || `Execute ${action2.action_type}` }) }),
|
|
1887
1973
|
/* @__PURE__ */ jsx(ArrowRight, { className: "w-5 h-5 transition-colors flex-shrink-0 ml-2", style: { color: t.success } })
|
|
1888
1974
|
]
|
|
1889
1975
|
}
|
|
@@ -2131,13 +2217,29 @@ function CopyButton({ content }) {
|
|
|
2131
2217
|
"button",
|
|
2132
2218
|
{
|
|
2133
2219
|
onClick: handleCopy,
|
|
2134
|
-
className: "
|
|
2220
|
+
className: "inline-flex h-6 w-6 items-center justify-center rounded transition-colors hover:scale-110",
|
|
2135
2221
|
style: { backgroundColor: t.bgRaisedHover, color: t.textSecondary },
|
|
2136
2222
|
title: "Copy",
|
|
2223
|
+
"aria-label": copied ? "Copied" : "Copy message",
|
|
2137
2224
|
children: copied ? /* @__PURE__ */ jsx(Check, { className: "w-3.5 h-3.5", style: { color: t.success } }) : /* @__PURE__ */ jsx(Copy, { className: "w-3.5 h-3.5" })
|
|
2138
2225
|
}
|
|
2139
2226
|
);
|
|
2140
2227
|
}
|
|
2228
|
+
function AgentCompletionNotice({ completion }) {
|
|
2229
|
+
const t = useTheme();
|
|
2230
|
+
if (!completion || completion.stop_reason === "answered") return null;
|
|
2231
|
+
const message = {
|
|
2232
|
+
rounds_exhausted: "Partial answer \u2014 I reached the step limit. Ask a narrower follow-up to continue.",
|
|
2233
|
+
budget_exhausted: "Partial answer \u2014 this question needs more context than fits in one answer. Try narrowing the question.",
|
|
2234
|
+
awaiting_tool_results: "This answer paused before its next step. Ask again to review a fresh answer.",
|
|
2235
|
+
empty: "No answer was returned. Please try again.",
|
|
2236
|
+
failed: "The answer could not be completed. What arrived so far is kept here.",
|
|
2237
|
+
interrupted: "Connection interrupted. The assistant may still be working; check the conversation before sending again.",
|
|
2238
|
+
cancelled: "Stopped. You can change your question and ask again."
|
|
2239
|
+
}[completion.stop_reason];
|
|
2240
|
+
if (!message) return null;
|
|
2241
|
+
return /* @__PURE__ */ jsx("p", { role: "status", className: "mt-2 rounded-md px-3 py-2 text-xs", style: { color: t.textSecondary, backgroundColor: t.bgRaisedAlt, border: `1px solid ${t.border}` }, children: message });
|
|
2242
|
+
}
|
|
2141
2243
|
var AGENT_PALETTE = [
|
|
2142
2244
|
"a78bfa",
|
|
2143
2245
|
// violet-400
|
|
@@ -2213,7 +2315,7 @@ function TimeLabel({ timestamp }) {
|
|
|
2213
2315
|
const t = useTheme();
|
|
2214
2316
|
const [timeStr, setTimeStr] = useState("");
|
|
2215
2317
|
useEffect(() => {
|
|
2216
|
-
setTimeStr(timestamp.toLocaleTimeString());
|
|
2318
|
+
setTimeStr(timestamp.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }));
|
|
2217
2319
|
}, [timestamp]);
|
|
2218
2320
|
return /* @__PURE__ */ jsx("span", { className: "text-[10px] mt-0.5", style: { color: t.textSecondary }, children: timeStr });
|
|
2219
2321
|
}
|
|
@@ -2531,7 +2633,10 @@ function hashTypeColor(type) {
|
|
|
2531
2633
|
for (let i = 0; i < type.length; i++) h = (h << 5) - h + type.charCodeAt(i) | 0;
|
|
2532
2634
|
return SOURCE_TYPE_PALETTE[Math.abs(h) % SOURCE_TYPE_PALETTE.length];
|
|
2533
2635
|
}
|
|
2534
|
-
function SourceCard({
|
|
2636
|
+
function SourceCard({
|
|
2637
|
+
source,
|
|
2638
|
+
onActivate
|
|
2639
|
+
}) {
|
|
2535
2640
|
const t = useTheme();
|
|
2536
2641
|
const [expanded, setExpanded] = useState(false);
|
|
2537
2642
|
const showType = source.type && source.type.toLowerCase() !== "unknown";
|
|
@@ -2539,13 +2644,25 @@ function SourceCard({ source }) {
|
|
|
2539
2644
|
const displayLabel = formatSourceLabel(source.label);
|
|
2540
2645
|
return /* @__PURE__ */ jsxs("div", { className: "rounded", style: { border: `1px solid ${t.border}`, backgroundColor: t.bgRaisedAlt }, children: [
|
|
2541
2646
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 px-2.5 py-1.5", children: [
|
|
2542
|
-
source.description ? /* @__PURE__ */ jsx(
|
|
2543
|
-
|
|
2647
|
+
source.description ? /* @__PURE__ */ jsx(
|
|
2648
|
+
"button",
|
|
2544
2649
|
{
|
|
2545
|
-
|
|
2546
|
-
|
|
2650
|
+
type: "button",
|
|
2651
|
+
onClick: (event) => {
|
|
2652
|
+
event.stopPropagation();
|
|
2653
|
+
setExpanded(!expanded);
|
|
2654
|
+
},
|
|
2655
|
+
className: "flex-shrink-0 rounded-sm focus:outline-none focus-visible:ring-2",
|
|
2656
|
+
"aria-label": expanded ? `Collapse ${displayLabel} details` : `Expand ${displayLabel} details`,
|
|
2657
|
+
children: /* @__PURE__ */ jsx(
|
|
2658
|
+
ChevronRight,
|
|
2659
|
+
{
|
|
2660
|
+
className: "w-3 h-3 transition-transform",
|
|
2661
|
+
style: { color: t.textMuted, transform: expanded ? "rotate(90deg)" : "none" }
|
|
2662
|
+
}
|
|
2663
|
+
)
|
|
2547
2664
|
}
|
|
2548
|
-
)
|
|
2665
|
+
) : /* @__PURE__ */ jsx("div", { className: "w-3 h-3 flex-shrink-0 flex items-center justify-center", children: /* @__PURE__ */ jsx("div", { className: "w-1.5 h-1.5 rounded-full", style: { backgroundColor: badgeColor } }) }),
|
|
2549
2666
|
showType && /* @__PURE__ */ jsx(
|
|
2550
2667
|
"span",
|
|
2551
2668
|
{
|
|
@@ -2554,11 +2671,28 @@ function SourceCard({ source }) {
|
|
|
2554
2671
|
children: source.type
|
|
2555
2672
|
}
|
|
2556
2673
|
),
|
|
2557
|
-
/* @__PURE__ */ jsx(
|
|
2674
|
+
onActivate ? /* @__PURE__ */ jsx(
|
|
2675
|
+
"button",
|
|
2676
|
+
{
|
|
2677
|
+
type: "button",
|
|
2678
|
+
className: "text-[11px] truncate flex-1 cursor-pointer text-left rounded-sm hover:underline focus:outline-none focus-visible:ring-2",
|
|
2679
|
+
style: { color: t.text },
|
|
2680
|
+
onClick: (event) => {
|
|
2681
|
+
event.stopPropagation();
|
|
2682
|
+
onActivate(source);
|
|
2683
|
+
},
|
|
2684
|
+
"aria-label": `Open ${displayLabel}`,
|
|
2685
|
+
children: displayLabel
|
|
2686
|
+
}
|
|
2687
|
+
) : /* @__PURE__ */ jsx("span", { className: "text-[11px] truncate flex-1", style: { color: t.text }, children: displayLabel })
|
|
2558
2688
|
] }),
|
|
2559
2689
|
expanded && source.description && /* @__PURE__ */ jsx("div", { className: "px-2.5 pb-2 text-[10px] leading-relaxed", style: { color: t.textSecondary, borderTop: `1px solid ${t.border}` }, children: source.description })
|
|
2560
2690
|
] });
|
|
2561
2691
|
}
|
|
2692
|
+
var REMARK_PLUGINS = [remarkGfm];
|
|
2693
|
+
function isBlockCode(className, text) {
|
|
2694
|
+
return /language-/.test(typeof className === "string" ? className : "") || text.includes("\n");
|
|
2695
|
+
}
|
|
2562
2696
|
function getMarkdownComponents(t) {
|
|
2563
2697
|
return {
|
|
2564
2698
|
h1: ({ node, ...props }) => /* @__PURE__ */ jsx("h1", { className: "text-xl font-bold mt-4 mb-2", style: { color: t.headingText }, ...props }),
|
|
@@ -2570,10 +2704,38 @@ function getMarkdownComponents(t) {
|
|
|
2570
2704
|
li: ({ node, ...props }) => /* @__PURE__ */ jsx("li", { className: "ml-2", ...props }),
|
|
2571
2705
|
strong: ({ node, ...props }) => /* @__PURE__ */ jsx("strong", { className: "font-bold", style: { color: t.text }, ...props }),
|
|
2572
2706
|
em: ({ node, ...props }) => /* @__PURE__ */ jsx("em", { className: "italic", style: { color: t.textSecondary }, ...props }),
|
|
2573
|
-
code: ({ node, inline, children, ...props }) =>
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
|
|
2707
|
+
code: ({ node, inline, children, ...props }) => {
|
|
2708
|
+
const text = String(children ?? "");
|
|
2709
|
+
const isInline = inline ?? !isBlockCode(props.className, text);
|
|
2710
|
+
return isInline ? /* @__PURE__ */ jsx("code", { className: "px-1 py-0.5 rounded font-mono text-xs", style: { backgroundColor: t.codeBg, color: t.codeText }, ...props, children }) : /* @__PURE__ */ jsxs("div", { className: "relative group/code", children: [
|
|
2711
|
+
/* @__PURE__ */ jsx(CopyButton, { content: text }),
|
|
2712
|
+
/* @__PURE__ */ jsx("code", { className: "block p-2 rounded my-2 font-mono text-xs overflow-x-auto", style: { backgroundColor: t.codeBg, color: t.codeText }, ...props, children })
|
|
2713
|
+
] });
|
|
2714
|
+
},
|
|
2715
|
+
// Tables are why remark-gfm is here. The wrapper is not decoration:
|
|
2716
|
+
// this renders inside a chat rail the user can drag down to ~360px,
|
|
2717
|
+
// and a table holding a term plus a few numbers will exceed that. It
|
|
2718
|
+
// has to scroll INSIDE its own box — without the wrapper the reply
|
|
2719
|
+
// column itself widens and every other line in the conversation
|
|
2720
|
+
// starts scrolling sideways along with it.
|
|
2721
|
+
table: ({ node, ...p }) => /* @__PURE__ */ jsx(
|
|
2722
|
+
"div",
|
|
2723
|
+
{
|
|
2724
|
+
className: "my-2 max-w-full overflow-x-auto rounded",
|
|
2725
|
+
style: { border: `1px solid ${t.codeBg}` },
|
|
2726
|
+
children: /* @__PURE__ */ jsx("table", { className: "w-full border-collapse text-xs", ...p })
|
|
2727
|
+
}
|
|
2728
|
+
),
|
|
2729
|
+
thead: ({ node, ...p }) => /* @__PURE__ */ jsx("thead", { style: { backgroundColor: t.codeBg }, ...p }),
|
|
2730
|
+
th: ({ node, ...p }) => /* @__PURE__ */ jsx(
|
|
2731
|
+
"th",
|
|
2732
|
+
{
|
|
2733
|
+
className: "px-2.5 py-1.5 text-left font-semibold whitespace-nowrap",
|
|
2734
|
+
style: { color: t.headingText, borderBottom: `1px solid ${t.codeBg}` },
|
|
2735
|
+
...p
|
|
2736
|
+
}
|
|
2737
|
+
),
|
|
2738
|
+
td: ({ node, ...p }) => /* @__PURE__ */ jsx("td", { className: "px-2.5 py-1.5 align-top", style: { borderBottom: `1px solid ${t.codeBg}` }, ...p })
|
|
2577
2739
|
};
|
|
2578
2740
|
}
|
|
2579
2741
|
function TerminalEntryRenderer({
|
|
@@ -2588,6 +2750,7 @@ function TerminalEntryRenderer({
|
|
|
2588
2750
|
authToken,
|
|
2589
2751
|
onPageNavigation,
|
|
2590
2752
|
onSourcesActivate,
|
|
2753
|
+
onSourceActivate,
|
|
2591
2754
|
renderEntryExtra,
|
|
2592
2755
|
renderEntry,
|
|
2593
2756
|
widgets,
|
|
@@ -2605,7 +2768,7 @@ function TerminalEntryRenderer({
|
|
|
2605
2768
|
const isError = entry.type === "error";
|
|
2606
2769
|
const isSuccess = entry.type === "success";
|
|
2607
2770
|
const isEmpty = !entry.content || entry.content.trim() === "";
|
|
2608
|
-
const useAttribution = isCollaborative && entry.sender && !isSystem && !isEmpty;
|
|
2771
|
+
const useAttribution = (isCollaborative || entry.sender?.type === "agent") && entry.sender && !isSystem && !isEmpty;
|
|
2609
2772
|
const isGrouped = useAttribution && !!prevEntry?.sender && !!entry.sender && prevEntry.sender.entity_id === entry.sender.entity_id && prevEntry.sender.type === entry.sender.type && !(!prevEntry.content || prevEntry.content.trim() === "") && entry.timestamp.getTime() - prevEntry.timestamp.getTime() < 5 * 60 * 1e3 && prevEntry.type !== "system";
|
|
2610
2773
|
const beforeWidgets = widgets?.filter((w) => w.position === "before" && w.match(entry)) || [];
|
|
2611
2774
|
const afterWidgets = widgets?.filter((w) => (!w.position || w.position === "after") && w.match(entry)) || [];
|
|
@@ -2618,12 +2781,12 @@ function TerminalEntryRenderer({
|
|
|
2618
2781
|
timestamp: entry.timestamp,
|
|
2619
2782
|
isOwnMessage: entry.sender.entity_id === currentUser?.entity_id,
|
|
2620
2783
|
grouped: isGrouped,
|
|
2621
|
-
children: entry.sender?.type === "agent" ? /* @__PURE__ */ jsxs("div", { className: "text-sm prose prose-invert prose-sm max-w-
|
|
2784
|
+
children: entry.sender?.type === "agent" ? /* @__PURE__ */ jsxs("div", { className: "text-sm prose prose-invert prose-sm max-w-[72ch] group relative", style: { color: t.text }, children: [
|
|
2622
2785
|
/* @__PURE__ */ jsxs("div", { className: "absolute -top-9 right-0 flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity z-10", children: [
|
|
2623
2786
|
/* @__PURE__ */ jsx(CopyButton, { content: entry.content }),
|
|
2624
2787
|
/* @__PURE__ */ jsx(ShareButton, { content: entry.content })
|
|
2625
2788
|
] }),
|
|
2626
|
-
/* @__PURE__ */ jsx(ReactMarkdown, { components: markdownComponents, children: entry.content })
|
|
2789
|
+
/* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: REMARK_PLUGINS, components: markdownComponents, children: stripInternalIds(entry.content) })
|
|
2627
2790
|
] }) : /* @__PURE__ */ jsxs("div", { className: "text-sm whitespace-pre-wrap group relative", style: { color: isError ? t.error : t.text }, children: [
|
|
2628
2791
|
/* @__PURE__ */ jsxs("div", { className: "absolute -top-9 right-0 flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity z-10", children: [
|
|
2629
2792
|
/* @__PURE__ */ jsx(CopyButton, { content: entry.content }),
|
|
@@ -2634,7 +2797,6 @@ function TerminalEntryRenderer({
|
|
|
2634
2797
|
}
|
|
2635
2798
|
) : /* @__PURE__ */ jsxs("div", { className: "flex items-start space-x-2", children: [
|
|
2636
2799
|
isSystem && !isEmpty && /* @__PURE__ */ jsx(Terminal, { className: "w-4 h-4 mt-0.5 flex-shrink-0", style: { color: t.textSystem } }),
|
|
2637
|
-
isCommand && !isEmpty && /* @__PURE__ */ jsx(Brain, { className: "w-4 h-4 mt-0.5 flex-shrink-0", style: { color: t.info } }),
|
|
2638
2800
|
isInfo && !isEmpty && /* @__PURE__ */ jsx(CheckCircle, { className: "w-4 h-4 mt-0.5 flex-shrink-0", style: { color: t.info } }),
|
|
2639
2801
|
isSuccess && !isEmpty && /* @__PURE__ */ jsx(CheckCircle, { className: "w-4 h-4 mt-0.5 flex-shrink-0", style: { color: t.success } }),
|
|
2640
2802
|
isError && !isEmpty && /* @__PURE__ */ jsx(XCircle, { className: "w-4 h-4 mt-0.5 flex-shrink-0", style: { color: t.error } }),
|
|
@@ -2647,12 +2809,30 @@ function TerminalEntryRenderer({
|
|
|
2647
2809
|
/* @__PURE__ */ jsx(
|
|
2648
2810
|
ReactMarkdown,
|
|
2649
2811
|
{
|
|
2812
|
+
remarkPlugins: REMARK_PLUGINS,
|
|
2650
2813
|
components: markdownComponents,
|
|
2651
|
-
children: entry.content
|
|
2814
|
+
children: stripInternalIds(entry.content)
|
|
2652
2815
|
},
|
|
2653
2816
|
`${entry.id || index}-${entry.content.length}`
|
|
2654
2817
|
)
|
|
2655
|
-
] }) :
|
|
2818
|
+
] }) : isCommand && !isSystem ? (
|
|
2819
|
+
// What the person typed: a quiet bubble on the right, the way the
|
|
2820
|
+
// console shows it — not a monospace line that reads as a log.
|
|
2821
|
+
/* @__PURE__ */ jsxs("div", { className: "group relative flex w-full flex-1 justify-end", children: [
|
|
2822
|
+
/* @__PURE__ */ jsxs("div", { className: "absolute -top-5 right-0 flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity z-10", children: [
|
|
2823
|
+
/* @__PURE__ */ jsx(CopyButton, { content: entry.content }),
|
|
2824
|
+
/* @__PURE__ */ jsx(ShareButton, { content: entry.content })
|
|
2825
|
+
] }),
|
|
2826
|
+
/* @__PURE__ */ jsx(
|
|
2827
|
+
"p",
|
|
2828
|
+
{
|
|
2829
|
+
className: "max-w-[80%] whitespace-pre-wrap rounded-lg border px-4 py-2.5 text-sm leading-relaxed",
|
|
2830
|
+
style: { color: t.text, borderColor: t.borderStrong, backgroundColor: "rgba(255,255,255,0.05)" },
|
|
2831
|
+
children: entry.content
|
|
2832
|
+
}
|
|
2833
|
+
)
|
|
2834
|
+
] })
|
|
2835
|
+
) : /* @__PURE__ */ jsxs("div", { className: "group relative", children: [
|
|
2656
2836
|
/* @__PURE__ */ jsxs("div", { className: "absolute -top-5 right-0 flex items-center gap-0.5 opacity-0 group-hover:opacity-100 transition-opacity z-10", children: [
|
|
2657
2837
|
/* @__PURE__ */ jsx(CopyButton, { content: entry.content }),
|
|
2658
2838
|
/* @__PURE__ */ jsx(ShareButton, { content: entry.content })
|
|
@@ -2660,9 +2840,9 @@ function TerminalEntryRenderer({
|
|
|
2660
2840
|
/* @__PURE__ */ jsx(
|
|
2661
2841
|
"pre",
|
|
2662
2842
|
{
|
|
2663
|
-
className: "font-mono text-sm whitespace-pre-wrap",
|
|
2843
|
+
className: "font-mono text-sm whitespace-pre-wrap max-w-[72ch]",
|
|
2664
2844
|
style: {
|
|
2665
|
-
color: isSystem ? t.textSystem :
|
|
2845
|
+
color: isSystem ? t.textSystem : isSuccess ? t.success : isError ? t.error : t.text
|
|
2666
2846
|
},
|
|
2667
2847
|
children: entry.content
|
|
2668
2848
|
}
|
|
@@ -2793,7 +2973,14 @@ function TerminalEntryRenderer({
|
|
|
2793
2973
|
{
|
|
2794
2974
|
summary: `${entry.sources.length} source${entry.sources.length !== 1 ? "s" : ""}`,
|
|
2795
2975
|
defaultExpanded: false,
|
|
2796
|
-
children: /* @__PURE__ */ jsx("div", { className: "space-y-1 py-1", children: entry.sources.map((src) => /* @__PURE__ */ jsx(
|
|
2976
|
+
children: /* @__PURE__ */ jsx("div", { className: "space-y-1 py-1", children: entry.sources.map((src) => /* @__PURE__ */ jsx(
|
|
2977
|
+
SourceCard,
|
|
2978
|
+
{
|
|
2979
|
+
source: src,
|
|
2980
|
+
onActivate: onSourceActivate ? () => onSourceActivate(src, entry) : void 0
|
|
2981
|
+
},
|
|
2982
|
+
src.id
|
|
2983
|
+
)) })
|
|
2797
2984
|
}
|
|
2798
2985
|
)
|
|
2799
2986
|
}
|
|
@@ -2813,11 +3000,11 @@ function TerminalEntryRenderer({
|
|
|
2813
3000
|
/* @__PURE__ */ jsx("span", { className: "font-medium text-sm", style: { color: t.success }, children: "Actions" }),
|
|
2814
3001
|
/* @__PURE__ */ jsx("span", { className: "text-xs", style: { color: t.textMuted }, children: "click to execute" })
|
|
2815
3002
|
] }),
|
|
2816
|
-
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2", children: entry.suggested_actions.map((
|
|
3003
|
+
/* @__PURE__ */ jsx("div", { className: "grid grid-cols-1 gap-2", children: entry.suggested_actions.map((action2, idx) => /* @__PURE__ */ jsxs("div", { children: [
|
|
2817
3004
|
/* @__PURE__ */ jsx(
|
|
2818
3005
|
InteractiveActionCard,
|
|
2819
3006
|
{
|
|
2820
|
-
action,
|
|
3007
|
+
action: action2,
|
|
2821
3008
|
graphqlUrl: config.graphqlUrl,
|
|
2822
3009
|
authToken: authToken || "",
|
|
2823
3010
|
onExecute: (updatedAction) => {
|
|
@@ -2826,15 +3013,15 @@ function TerminalEntryRenderer({
|
|
|
2826
3013
|
}
|
|
2827
3014
|
}
|
|
2828
3015
|
),
|
|
2829
|
-
|
|
3016
|
+
action2.approval && /* @__PURE__ */ jsx(
|
|
2830
3017
|
ApprovalTracker,
|
|
2831
3018
|
{
|
|
2832
|
-
approval:
|
|
3019
|
+
approval: action2.approval,
|
|
2833
3020
|
currentUserId: currentUser?.entity_id,
|
|
2834
3021
|
onApprove: () => {
|
|
2835
3022
|
window.dispatchEvent(
|
|
2836
3023
|
new CustomEvent("terminal-approval-decision", {
|
|
2837
|
-
detail: { action, decision: "approved", entity_id: currentUser?.entity_id },
|
|
3024
|
+
detail: { action: action2, decision: "approved", entity_id: currentUser?.entity_id },
|
|
2838
3025
|
bubbles: true
|
|
2839
3026
|
})
|
|
2840
3027
|
);
|
|
@@ -2842,7 +3029,7 @@ function TerminalEntryRenderer({
|
|
|
2842
3029
|
onReject: () => {
|
|
2843
3030
|
window.dispatchEvent(
|
|
2844
3031
|
new CustomEvent("terminal-approval-decision", {
|
|
2845
|
-
detail: { action, decision: "rejected", entity_id: currentUser?.entity_id },
|
|
3032
|
+
detail: { action: action2, decision: "rejected", entity_id: currentUser?.entity_id },
|
|
2846
3033
|
bubbles: true
|
|
2847
3034
|
})
|
|
2848
3035
|
);
|
|
@@ -2890,9 +3077,10 @@ function TerminalEntryRenderer({
|
|
|
2890
3077
|
] });
|
|
2891
3078
|
const isTurnStart = !!prevEntry && isCommand && prevEntry.type !== "system";
|
|
2892
3079
|
const defaultRender = () => /* @__PURE__ */ jsxs("div", { className: `${isGrouped ? "" : "mb-5"} ${isTurnStart ? "mt-6" : ""}`, children: [
|
|
2893
|
-
beforeWidgets.map((w) => /* @__PURE__ */ jsx(
|
|
2894
|
-
replaceWidget ? /* @__PURE__ */ jsx(
|
|
2895
|
-
afterWidgets.map((w) => /* @__PURE__ */ jsx(
|
|
3080
|
+
beforeWidgets.map((w) => /* @__PURE__ */ jsx(React15.Fragment, { children: w.render({ entry, index }) }, w.name)),
|
|
3081
|
+
replaceWidget ? /* @__PURE__ */ jsx(React15.Fragment, { children: replaceWidget.render({ entry, index }) }, replaceWidget.name) : builtInContent,
|
|
3082
|
+
afterWidgets.map((w) => /* @__PURE__ */ jsx(React15.Fragment, { children: w.render({ entry, index }) }, w.name)),
|
|
3083
|
+
/* @__PURE__ */ jsx(AgentCompletionNotice, { completion: entry.metadata?.completion }),
|
|
2896
3084
|
renderEntryExtra?.(entry, index)
|
|
2897
3085
|
] });
|
|
2898
3086
|
if (renderEntry) {
|
|
@@ -2901,6 +3089,9 @@ function TerminalEntryRenderer({
|
|
|
2901
3089
|
}
|
|
2902
3090
|
return defaultRender();
|
|
2903
3091
|
}
|
|
3092
|
+
|
|
3093
|
+
// src/types/terminal.types.ts
|
|
3094
|
+
var DEFAULT_AGENT_LABEL = "YieldFabric Agent";
|
|
2904
3095
|
function LiveKGBridge({ progressState, onLiveKGUpdate }) {
|
|
2905
3096
|
const onUpdateRef = useRef(onLiveKGUpdate);
|
|
2906
3097
|
onUpdateRef.current = onLiveKGUpdate;
|
|
@@ -2929,14 +3120,17 @@ function TerminalShell({
|
|
|
2929
3120
|
className = "",
|
|
2930
3121
|
style,
|
|
2931
3122
|
showHeader = true,
|
|
3123
|
+
agentLabel = DEFAULT_AGENT_LABEL,
|
|
2932
3124
|
focusInput,
|
|
2933
3125
|
setTerminalHistory,
|
|
2934
3126
|
terminalBodyRef,
|
|
2935
3127
|
workingGroupContext,
|
|
3128
|
+
showWorkingGroupBanner = true,
|
|
2936
3129
|
progressState,
|
|
2937
3130
|
streamTransparency,
|
|
2938
3131
|
streamNowMs,
|
|
2939
3132
|
isExecuting,
|
|
3133
|
+
showBusyIndicator,
|
|
2940
3134
|
handleCancelReasoning,
|
|
2941
3135
|
onViewKnowledgeGraph,
|
|
2942
3136
|
onLiveKGUpdate,
|
|
@@ -2954,6 +3148,9 @@ function TerminalShell({
|
|
|
2954
3148
|
className: `border-0 flex flex-col ${className}`,
|
|
2955
3149
|
style: { minHeight: "300px", borderRadius: "12px", backgroundColor: "transparent", ...style },
|
|
2956
3150
|
onClick: () => {
|
|
3151
|
+
if (typeof window !== "undefined" && window.matchMedia?.("(pointer: coarse)").matches) {
|
|
3152
|
+
return;
|
|
3153
|
+
}
|
|
2957
3154
|
const sel = window.getSelection();
|
|
2958
3155
|
if (!sel || sel.toString().length === 0) focusInput();
|
|
2959
3156
|
},
|
|
@@ -2972,7 +3169,7 @@ function TerminalShell({
|
|
|
2972
3169
|
"button",
|
|
2973
3170
|
{
|
|
2974
3171
|
onClick: () => setTerminalHistory([
|
|
2975
|
-
{ type: "system", content:
|
|
3172
|
+
{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() },
|
|
2976
3173
|
{ type: "system", content: "Terminal cleared.", timestamp: /* @__PURE__ */ new Date() }
|
|
2977
3174
|
]),
|
|
2978
3175
|
className: "hover:opacity-80",
|
|
@@ -2990,7 +3187,7 @@ function TerminalShell({
|
|
|
2990
3187
|
className: "p-6 flex-1 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-700 scrollbar-track-transparent",
|
|
2991
3188
|
style: { minHeight: "200px", display: "flex", flexDirection: "column", backgroundColor: "transparent" },
|
|
2992
3189
|
children: [
|
|
2993
|
-
workingGroupContext && /* @__PURE__ */ jsxs(
|
|
3190
|
+
workingGroupContext && showWorkingGroupBanner && /* @__PURE__ */ jsxs(
|
|
2994
3191
|
"div",
|
|
2995
3192
|
{
|
|
2996
3193
|
className: "mb-3 ml-1 mr-1 px-3 py-2 rounded-md text-xs flex items-center justify-between",
|
|
@@ -3015,7 +3212,7 @@ function TerminalShell({
|
|
|
3015
3212
|
}
|
|
3016
3213
|
),
|
|
3017
3214
|
/* @__PURE__ */ jsx(LiveKGBridge, { progressState, onLiveKGUpdate }),
|
|
3018
|
-
isExecuting && !progressState && /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2 px-6 py-2 flex-shrink-0 border-t", style: { color: t.text, borderColor: t.border }, children: [
|
|
3215
|
+
isExecuting && !progressState && showBusyIndicator !== false && /* @__PURE__ */ jsxs("div", { className: "flex items-center space-x-2 px-6 py-2 flex-shrink-0 border-t", style: { color: t.text, borderColor: t.border }, children: [
|
|
3019
3216
|
/* @__PURE__ */ jsxs("div", { className: "flex space-x-1", children: [
|
|
3020
3217
|
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 rounded-full animate-pulse", style: { backgroundColor: t.info } }),
|
|
3021
3218
|
/* @__PURE__ */ jsx("div", { className: "w-2 h-2 rounded-full animate-pulse", style: { backgroundColor: t.info, animationDelay: "150ms" } }),
|
|
@@ -3145,11 +3342,24 @@ function splitInputByMentions(command, knownMentionNames) {
|
|
|
3145
3342
|
segments.push({ kind: "text", value: command.slice(cursor) });
|
|
3146
3343
|
return segments;
|
|
3147
3344
|
}
|
|
3345
|
+
var INPUT_MAX_HEIGHT = 120;
|
|
3346
|
+
function fitToContent(input) {
|
|
3347
|
+
resetHeight(input);
|
|
3348
|
+
if (!input.value.trim()) return;
|
|
3349
|
+
const needed = input.scrollHeight;
|
|
3350
|
+
input.style.height = `${Math.min(needed, INPUT_MAX_HEIGHT)}px`;
|
|
3351
|
+
if (needed > INPUT_MAX_HEIGHT) input.style.overflowY = "auto";
|
|
3352
|
+
}
|
|
3353
|
+
function resetHeight(input) {
|
|
3354
|
+
input.style.height = "auto";
|
|
3355
|
+
input.style.overflowY = "";
|
|
3356
|
+
}
|
|
3148
3357
|
function TerminalInputBar({
|
|
3149
3358
|
inputRef,
|
|
3150
3359
|
fileInputRef,
|
|
3151
3360
|
currentCommand,
|
|
3152
3361
|
isExecuting,
|
|
3362
|
+
disabled = false,
|
|
3153
3363
|
placeholder = "Ask anything...",
|
|
3154
3364
|
onInputChange,
|
|
3155
3365
|
onKeyDown,
|
|
@@ -3172,20 +3382,27 @@ function TerminalInputBar({
|
|
|
3172
3382
|
inputBarExtra,
|
|
3173
3383
|
modeSelector,
|
|
3174
3384
|
compactToolbar = false,
|
|
3175
|
-
submitTitle = "Send"
|
|
3385
|
+
submitTitle = "Send",
|
|
3386
|
+
autoFocus = true
|
|
3176
3387
|
}) {
|
|
3177
3388
|
const t = useTheme();
|
|
3389
|
+
useEffect(() => {
|
|
3390
|
+
if (!autoFocus) return;
|
|
3391
|
+
inputRef.current?.focus({ preventScroll: true });
|
|
3392
|
+
}, []);
|
|
3393
|
+
const [focused, setFocused] = React15.useState(false);
|
|
3394
|
+
const chipsVisible = focused || currentCommand.trim().length > 0;
|
|
3178
3395
|
const isLight = t.bgRaised === "#ffffff";
|
|
3179
3396
|
const hasCommand = Boolean(currentCommand.trim());
|
|
3180
|
-
const placeholderColor = isLight ?
|
|
3181
|
-
const panelBorder = isLight ?
|
|
3182
|
-
const panelBg =
|
|
3183
|
-
const toolbarButtonBg = isLight ? "rgba(
|
|
3184
|
-
const toolbarButtonHover = isLight ?
|
|
3185
|
-
const toolbarButtonText = isLight ?
|
|
3397
|
+
const placeholderColor = isLight ? t.textMuted : "rgba(255,255,255,0.52)";
|
|
3398
|
+
const panelBorder = isLight ? t.border : "rgba(255,255,255,0.10)";
|
|
3399
|
+
const panelBg = t.bgInput;
|
|
3400
|
+
const toolbarButtonBg = isLight ? "rgba(255,255,255,0.72)" : "rgba(255,255,255,0.05)";
|
|
3401
|
+
const toolbarButtonHover = isLight ? t.bgRaised : "rgba(255,255,255,0.14)";
|
|
3402
|
+
const toolbarButtonText = isLight ? t.textSecondary : "rgba(255,255,255,0.52)";
|
|
3186
3403
|
const toolbarButtonStyle = {
|
|
3187
3404
|
backgroundColor: toolbarButtonBg,
|
|
3188
|
-
border: `1px solid ${isLight ?
|
|
3405
|
+
border: `1px solid ${isLight ? t.border : "rgba(255,255,255,0.08)"}`,
|
|
3189
3406
|
boxShadow: "none",
|
|
3190
3407
|
color: toolbarButtonText
|
|
3191
3408
|
};
|
|
@@ -3198,8 +3415,11 @@ function TerminalInputBar({
|
|
|
3198
3415
|
}
|
|
3199
3416
|
const el = toolbarRef.current;
|
|
3200
3417
|
if (!el || typeof ResizeObserver === "undefined") return;
|
|
3418
|
+
let lastWidth = -1;
|
|
3201
3419
|
const ro = new ResizeObserver((entries) => {
|
|
3202
|
-
const w = entries[0]?.contentRect.width ?? 0;
|
|
3420
|
+
const w = Math.round(entries[0]?.contentRect.width ?? 0);
|
|
3421
|
+
if (w === lastWidth) return;
|
|
3422
|
+
lastWidth = w;
|
|
3203
3423
|
setCompact((prev) => prev ? w < 520 : w < 480);
|
|
3204
3424
|
});
|
|
3205
3425
|
ro.observe(el);
|
|
@@ -3209,10 +3429,7 @@ function TerminalInputBar({
|
|
|
3209
3429
|
useEffect(() => {
|
|
3210
3430
|
const input = inputRef.current;
|
|
3211
3431
|
if (!input) return;
|
|
3212
|
-
input
|
|
3213
|
-
if (currentCommand.trim()) {
|
|
3214
|
-
input.style.height = Math.min(input.scrollHeight, 120) + "px";
|
|
3215
|
-
}
|
|
3432
|
+
fitToContent(input);
|
|
3216
3433
|
}, [currentCommand, inputRef]);
|
|
3217
3434
|
return /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3218
3435
|
/* @__PURE__ */ jsx("style", { children: `.yf-input-bar::placeholder { color: ${placeholderColor}; }` }),
|
|
@@ -3254,16 +3471,16 @@ function TerminalInputBar({
|
|
|
3254
3471
|
/* @__PURE__ */ jsx(
|
|
3255
3472
|
"div",
|
|
3256
3473
|
{
|
|
3257
|
-
className: `relative z-20 flex-shrink-0 px-3 pb-3 pt-2 transition-opacity duration-300 sm:px-4 ${isExecuting ? "opacity-40 pointer-events-none" : ""}`,
|
|
3474
|
+
className: `relative z-20 flex-shrink-0 px-3 pb-3 pt-2 transition-opacity duration-300 sm:px-4 ${isExecuting || disabled ? "opacity-40 pointer-events-none" : ""}`,
|
|
3258
3475
|
children: /* @__PURE__ */ jsxs(
|
|
3259
3476
|
"div",
|
|
3260
3477
|
{
|
|
3261
|
-
className:
|
|
3478
|
+
className: `rounded-xl border px-3 transition-[box-shadow,border-color] sm:px-4 ${focused ? "yf-input-focused" : ""}`,
|
|
3262
3479
|
style: {
|
|
3263
3480
|
backgroundColor: panelBg,
|
|
3264
3481
|
backdropFilter: "blur(18px)",
|
|
3265
|
-
borderColor: panelBorder,
|
|
3266
|
-
boxShadow: isLight ? "0 18px 70px -38px rgba(30,30,58,0.45)" : "0 18px 70px -38px rgba(0,0,0,0.95)",
|
|
3482
|
+
borderColor: focused ? t.primary : panelBorder,
|
|
3483
|
+
boxShadow: focused ? `0 0 0 3px ${t.primaryMuted || "rgba(5,78,146,0.18)"}` : isLight ? "0 18px 70px -38px rgba(30,30,58,0.45)" : "0 18px 70px -38px rgba(0,0,0,0.95)",
|
|
3267
3484
|
WebkitBackdropFilter: "blur(18px)"
|
|
3268
3485
|
},
|
|
3269
3486
|
children: [
|
|
@@ -3333,8 +3550,7 @@ function TerminalInputBar({
|
|
|
3333
3550
|
onInputChange(`${prefixRaw}${e.target.value}`);
|
|
3334
3551
|
onCaretChange?.(prefixRaw.length + (e.target.selectionStart ?? e.target.value.length));
|
|
3335
3552
|
onTyping?.();
|
|
3336
|
-
e.target
|
|
3337
|
-
e.target.style.height = Math.min(e.target.scrollHeight, 120) + "px";
|
|
3553
|
+
fitToContent(e.target);
|
|
3338
3554
|
},
|
|
3339
3555
|
onSelect: (e) => {
|
|
3340
3556
|
const ta = e.currentTarget;
|
|
@@ -3361,17 +3577,19 @@ function TerminalInputBar({
|
|
|
3361
3577
|
if (e.key === "Enter" && !e.shiftKey && !e.defaultPrevented) {
|
|
3362
3578
|
e.preventDefault();
|
|
3363
3579
|
onSubmit();
|
|
3364
|
-
if (inputRef.current) inputRef.current
|
|
3580
|
+
if (inputRef.current) resetHeight(inputRef.current);
|
|
3365
3581
|
}
|
|
3366
3582
|
},
|
|
3367
|
-
disabled: isExecuting,
|
|
3583
|
+
disabled: isExecuting || disabled,
|
|
3584
|
+
"aria-label": placeholder ?? "Message",
|
|
3368
3585
|
placeholder: isExecuting ? "Processing..." : placeholder,
|
|
3369
3586
|
rows: 1,
|
|
3370
|
-
className: "yf-input-bar flex-1 min-w-[100px] bg-transparent focus:outline-none text-[16px] leading-6 resize-none overflow-hidden sm:text-
|
|
3587
|
+
className: "yf-input-bar flex-1 min-w-[100px] bg-transparent focus:outline-none text-[16px] leading-6 resize-none overflow-hidden sm:text-sm sm:leading-5",
|
|
3588
|
+
onFocus: () => setFocused(true),
|
|
3589
|
+
onBlur: () => setFocused(false),
|
|
3371
3590
|
style: { color: t.text, caretColor: t.cursor },
|
|
3372
3591
|
spellCheck: false,
|
|
3373
3592
|
autoComplete: "off",
|
|
3374
|
-
autoFocus: true,
|
|
3375
3593
|
tabIndex: 0
|
|
3376
3594
|
}
|
|
3377
3595
|
)
|
|
@@ -3380,67 +3598,78 @@ function TerminalInputBar({
|
|
|
3380
3598
|
"button",
|
|
3381
3599
|
{
|
|
3382
3600
|
type: "submit",
|
|
3383
|
-
disabled: !hasCommand || isExecuting,
|
|
3384
|
-
className: "h-10 w-10 rounded-xl disabled:opacity-
|
|
3601
|
+
disabled: !hasCommand || isExecuting || disabled,
|
|
3602
|
+
className: "h-10 w-10 rounded-xl disabled:opacity-60 disabled:cursor-not-allowed flex items-center justify-center transition-all duration-200 shrink-0 sm:h-8 sm:w-8",
|
|
3385
3603
|
style: {
|
|
3386
|
-
backgroundColor: hasCommand ?
|
|
3387
|
-
|
|
3604
|
+
backgroundColor: hasCommand ? t.primary : isLight ? t.bgRaisedAlt : "rgba(255,255,255,0.08)",
|
|
3605
|
+
// `textInverse` is the theme's "text on a filled button".
|
|
3606
|
+
// `bgBase` was used here before and is `transparent` in
|
|
3607
|
+
// every app theme — so the chevron vanished the moment
|
|
3608
|
+
// there was something to send.
|
|
3609
|
+
color: hasCommand ? t.textInverse : isLight ? t.textMuted : "rgba(255,255,255,0.72)"
|
|
3388
3610
|
},
|
|
3389
3611
|
onMouseEnter: (e) => {
|
|
3390
|
-
|
|
3612
|
+
if (hasCommand) {
|
|
3613
|
+
e.currentTarget.style.filter = "brightness(1.15)";
|
|
3614
|
+
} else {
|
|
3615
|
+
e.currentTarget.style.backgroundColor = toolbarButtonHover;
|
|
3616
|
+
}
|
|
3391
3617
|
},
|
|
3392
3618
|
onMouseLeave: (e) => {
|
|
3393
|
-
e.currentTarget.style.
|
|
3619
|
+
e.currentTarget.style.filter = "";
|
|
3620
|
+
e.currentTarget.style.backgroundColor = hasCommand ? t.primary : isLight ? t.bgRaisedAlt : "rgba(255,255,255,0.08)";
|
|
3394
3621
|
},
|
|
3395
3622
|
title: submitTitle,
|
|
3396
3623
|
"aria-label": submitTitle,
|
|
3397
|
-
children: isExecuting ? /* @__PURE__ */ jsx("div", { className: "w-3 h-3 rounded-full animate-spin", style: { border: `1.5px solid ${hasCommand ?
|
|
3624
|
+
children: isExecuting ? /* @__PURE__ */ jsx("div", { className: "w-3 h-3 rounded-full animate-spin", style: { border: `1.5px solid ${hasCommand ? t.textInverse : t.textMuted}`, borderTopColor: "transparent" } }) : /* @__PURE__ */ jsx(ChevronRight, { className: "h-5 w-5 sm:h-4 sm:w-4" })
|
|
3398
3625
|
}
|
|
3399
3626
|
)
|
|
3400
3627
|
] });
|
|
3401
3628
|
})(),
|
|
3402
3629
|
/* @__PURE__ */ jsxs("div", { ref: toolbarRef, className: "flex items-center justify-between pt-2.5 gap-2", children: [
|
|
3403
|
-
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-[
|
|
3404
|
-
/* @__PURE__ */
|
|
3405
|
-
|
|
3406
|
-
|
|
3407
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
e
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
e
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
e
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
e
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3630
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 text-[11px] min-w-0 flex-wrap", children: [
|
|
3631
|
+
chipsVisible && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
3632
|
+
/* @__PURE__ */ jsx(
|
|
3633
|
+
"button",
|
|
3634
|
+
{
|
|
3635
|
+
type: "button",
|
|
3636
|
+
onClick: () => {
|
|
3637
|
+
onInputChange("@");
|
|
3638
|
+
inputRef.current?.focus();
|
|
3639
|
+
},
|
|
3640
|
+
title: "Insert @ mention",
|
|
3641
|
+
className: `${toolbarIsCompact ? "px-2" : "px-2.5"} py-1 min-h-[40px] sm:min-h-0 inline-flex items-center rounded-lg transition-colors font-semibold flex-shrink-0`,
|
|
3642
|
+
style: toolbarButtonStyle,
|
|
3643
|
+
onMouseEnter: (e) => {
|
|
3644
|
+
e.currentTarget.style.backgroundColor = toolbarButtonHover;
|
|
3645
|
+
},
|
|
3646
|
+
onMouseLeave: (e) => {
|
|
3647
|
+
e.currentTarget.style.backgroundColor = toolbarButtonBg;
|
|
3648
|
+
},
|
|
3649
|
+
children: toolbarIsCompact ? "@" : "@ mention"
|
|
3650
|
+
}
|
|
3651
|
+
),
|
|
3652
|
+
/* @__PURE__ */ jsx(
|
|
3653
|
+
"button",
|
|
3654
|
+
{
|
|
3655
|
+
type: "button",
|
|
3656
|
+
onClick: () => {
|
|
3657
|
+
onInputChange("/");
|
|
3658
|
+
inputRef.current?.focus();
|
|
3659
|
+
},
|
|
3660
|
+
title: "Insert / command",
|
|
3661
|
+
className: `${toolbarIsCompact ? "px-2" : "px-2.5"} py-1 min-h-[40px] sm:min-h-0 inline-flex items-center rounded-lg transition-colors font-semibold flex-shrink-0`,
|
|
3662
|
+
style: toolbarButtonStyle,
|
|
3663
|
+
onMouseEnter: (e) => {
|
|
3664
|
+
e.currentTarget.style.backgroundColor = toolbarButtonHover;
|
|
3665
|
+
},
|
|
3666
|
+
onMouseLeave: (e) => {
|
|
3667
|
+
e.currentTarget.style.backgroundColor = toolbarButtonBg;
|
|
3668
|
+
},
|
|
3669
|
+
children: toolbarIsCompact ? "/" : "/ commands"
|
|
3670
|
+
}
|
|
3671
|
+
)
|
|
3672
|
+
] }),
|
|
3444
3673
|
availableKGs && availableKGs.length > 0 && /* @__PURE__ */ jsx(Fragment, { children: activeKGScope ? /* @__PURE__ */ jsxs("span", { className: "inline-flex items-center gap-1.5 px-2 py-0.5 rounded-md text-[10px] min-w-0", title: activeKGScope.label, style: { backgroundColor: "rgba(255,140,66,0.08)", border: "1px solid rgba(255,140,66,0.15)", color: "rgba(255,140,66,0.8)" }, children: [
|
|
3445
3674
|
/* @__PURE__ */ jsxs("svg", { className: "w-3 h-3 opacity-60 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: [
|
|
3446
3675
|
/* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M13.828 10.172a4 4 0 00-5.656 0l-4 4a4 4 0 105.656 5.656l1.102-1.101" }),
|
|
@@ -3454,7 +3683,7 @@ function TerminalInputBar({
|
|
|
3454
3683
|
] }),
|
|
3455
3684
|
/* @__PURE__ */ jsx("button", { type: "button", onClick: () => onKGScopeChange?.(null), className: "ml-0.5 opacity-40 hover:opacity-100 transition-opacity", children: "\u2715" })
|
|
3456
3685
|
] }) : /* @__PURE__ */ jsx(KGScopeDropdown, { items: availableKGs, onSelect: (scope) => onKGScopeChange?.(scope), compact: toolbarIsCompact }) }),
|
|
3457
|
-
modeSelector ?? (onReasoningModeChange && /* @__PURE__ */ jsx(ReasoningModeSelector, { current: reasoningMode || null, onChange: onReasoningModeChange, compact: toolbarIsCompact }))
|
|
3686
|
+
chipsVisible && (modeSelector ?? (onReasoningModeChange && /* @__PURE__ */ jsx(ReasoningModeSelector, { current: reasoningMode || null, onChange: onReasoningModeChange, compact: toolbarIsCompact })))
|
|
3458
3687
|
] }),
|
|
3459
3688
|
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-1.5 flex-shrink-0", children: [
|
|
3460
3689
|
inputBarExtra,
|
|
@@ -3462,8 +3691,8 @@ function TerminalInputBar({
|
|
|
3462
3691
|
"button",
|
|
3463
3692
|
{
|
|
3464
3693
|
type: "button",
|
|
3465
|
-
disabled: isExecuting,
|
|
3466
|
-
className: "h-8 w-8 rounded-xl disabled:opacity-30 disabled:cursor-not-allowed flex items-center justify-center transition-all duration-200",
|
|
3694
|
+
disabled: isExecuting || disabled,
|
|
3695
|
+
className: "h-10 w-10 sm:h-8 sm:w-8 rounded-xl disabled:opacity-30 disabled:cursor-not-allowed flex items-center justify-center transition-all duration-200",
|
|
3467
3696
|
style: toolbarButtonStyle,
|
|
3468
3697
|
title: "Upload files",
|
|
3469
3698
|
onClick: () => fileInputRef.current?.click(),
|
|
@@ -3480,8 +3709,8 @@ function TerminalInputBar({
|
|
|
3480
3709
|
"button",
|
|
3481
3710
|
{
|
|
3482
3711
|
type: "button",
|
|
3483
|
-
disabled: isExecuting,
|
|
3484
|
-
className: "h-8 w-8 rounded-xl disabled:opacity-30 disabled:cursor-not-allowed flex items-center justify-center transition-all duration-200",
|
|
3712
|
+
disabled: isExecuting || disabled,
|
|
3713
|
+
className: "h-10 w-10 sm:h-8 sm:w-8 rounded-xl disabled:opacity-30 disabled:cursor-not-allowed flex items-center justify-center transition-all duration-200",
|
|
3485
3714
|
style: toolbarButtonStyle,
|
|
3486
3715
|
title: "List files",
|
|
3487
3716
|
onClick: () => onListFilesCommand(),
|
|
@@ -3601,16 +3830,15 @@ function useCommandHistory() {
|
|
|
3601
3830
|
}, []);
|
|
3602
3831
|
return { commandHistory, historyIndex, pushCommand, navigateUp, navigateDown, resetIndex };
|
|
3603
3832
|
}
|
|
3604
|
-
function useFocusManagement() {
|
|
3833
|
+
function useFocusManagement(autoFocus = true) {
|
|
3605
3834
|
const inputRef = useRef(null);
|
|
3606
3835
|
const focusInput = useCallback(() => {
|
|
3607
3836
|
const selection = window.getSelection();
|
|
3608
3837
|
if (selection && selection.toString().length > 0) return;
|
|
3609
|
-
|
|
3610
|
-
inputRef.current.focus();
|
|
3611
|
-
}
|
|
3838
|
+
inputRef.current?.focus({ preventScroll: true });
|
|
3612
3839
|
}, []);
|
|
3613
3840
|
useEffect(() => {
|
|
3841
|
+
if (!autoFocus) return;
|
|
3614
3842
|
const timer = setTimeout(focusInput, 100);
|
|
3615
3843
|
const handleVisibilityChange = () => {
|
|
3616
3844
|
if (!document.hidden) {
|
|
@@ -3622,11 +3850,12 @@ function useFocusManagement() {
|
|
|
3622
3850
|
clearTimeout(timer);
|
|
3623
3851
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
3624
3852
|
};
|
|
3625
|
-
}, [focusInput]);
|
|
3853
|
+
}, [focusInput, autoFocus]);
|
|
3626
3854
|
return { inputRef, focusInput };
|
|
3627
3855
|
}
|
|
3628
3856
|
function useStreamingChat({
|
|
3629
3857
|
config,
|
|
3858
|
+
authToken,
|
|
3630
3859
|
onStreamRequest,
|
|
3631
3860
|
reasoningMode,
|
|
3632
3861
|
setTerminalHistory,
|
|
@@ -3635,11 +3864,14 @@ function useStreamingChat({
|
|
|
3635
3864
|
currentUser,
|
|
3636
3865
|
sourceKGNodes
|
|
3637
3866
|
}) {
|
|
3867
|
+
const authTokenRef = useRef(authToken);
|
|
3868
|
+
authTokenRef.current = authToken;
|
|
3638
3869
|
const sourceKGNodesRef = useRef(sourceKGNodes);
|
|
3639
3870
|
sourceKGNodesRef.current = sourceKGNodes;
|
|
3640
3871
|
const reasoningModeRef = useRef(reasoningMode);
|
|
3641
3872
|
reasoningModeRef.current = reasoningMode;
|
|
3642
3873
|
const [isExecuting, setIsExecuting] = useState(false);
|
|
3874
|
+
const turnSequence = useRef(0);
|
|
3643
3875
|
const [isStreaming, setIsStreaming] = useState(false);
|
|
3644
3876
|
const [progressState, setProgressState] = useState(null);
|
|
3645
3877
|
const [activityEvents, setActivityEvents] = useState([]);
|
|
@@ -3655,6 +3887,15 @@ function useStreamingChat({
|
|
|
3655
3887
|
const currentStreamingLineId = useRef(null);
|
|
3656
3888
|
const liveRunIdRef = useRef(null);
|
|
3657
3889
|
liveRunIdRef.current = liveRunId;
|
|
3890
|
+
const mountEpoch = useRef(0);
|
|
3891
|
+
useEffect(() => {
|
|
3892
|
+
const epoch = ++mountEpoch.current;
|
|
3893
|
+
return () => {
|
|
3894
|
+
void Promise.resolve().then(() => {
|
|
3895
|
+
if (mountEpoch.current === epoch) currentStreamingLineId.current = null;
|
|
3896
|
+
});
|
|
3897
|
+
};
|
|
3898
|
+
}, []);
|
|
3658
3899
|
useEffect(() => {
|
|
3659
3900
|
progressStateRef.current = progressState;
|
|
3660
3901
|
}, [progressState]);
|
|
@@ -3707,45 +3948,54 @@ function useStreamingChat({
|
|
|
3707
3948
|
currentStreamingLineId.current = null;
|
|
3708
3949
|
setTimeout(() => focusInput(), 50);
|
|
3709
3950
|
}, [focusInput]);
|
|
3710
|
-
const
|
|
3711
|
-
|
|
3712
|
-
|
|
3713
|
-
|
|
3714
|
-
|
|
3715
|
-
|
|
3716
|
-
|
|
3717
|
-
|
|
3718
|
-
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
|
|
3729
|
-
console.error("Failed to send pipeline input:", e);
|
|
3730
|
-
}
|
|
3731
|
-
},
|
|
3732
|
-
[config.agentsApiUrl]
|
|
3733
|
-
);
|
|
3951
|
+
const postPipelineAction = useCallback(async (runId, action2, body) => {
|
|
3952
|
+
const headers = config.getAuthHeaders?.() ?? (authTokenRef.current ? { Authorization: `Bearer ${authTokenRef.current}` } : {});
|
|
3953
|
+
const response = await fetch(`${config.agentsApiUrl || "http://localhost:3001"}/pipelines/${runId}/${action2}`, {
|
|
3954
|
+
method: "POST",
|
|
3955
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
3956
|
+
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
3957
|
+
});
|
|
3958
|
+
if (!response.ok) throw new Error(`The request was not accepted (${response.status}). Please try again.`);
|
|
3959
|
+
}, [config]);
|
|
3960
|
+
const handleHilSubmit = useCallback(async (message) => {
|
|
3961
|
+
const runId = liveRunIdRef.current;
|
|
3962
|
+
if (!runId) return;
|
|
3963
|
+
try {
|
|
3964
|
+
if (message.trim()) await postPipelineAction(runId, "input", { kind: "guidance", content: message });
|
|
3965
|
+
await postPipelineAction(runId, "input", { kind: "proceed" });
|
|
3966
|
+
} catch (error) {
|
|
3967
|
+
addTerminalLine("error", `Your input was not sent. ${error.message}`);
|
|
3968
|
+
}
|
|
3969
|
+
}, [postPipelineAction, addTerminalLine]);
|
|
3734
3970
|
const handleCancelReasoning = useCallback(async () => {
|
|
3735
3971
|
const runId = liveRunIdRef.current;
|
|
3736
3972
|
if (!runId) return;
|
|
3737
|
-
const apiUrl = config.agentsApiUrl || "http://localhost:3001";
|
|
3738
|
-
setProgressState(null);
|
|
3739
|
-
resetStreamState();
|
|
3740
3973
|
try {
|
|
3741
|
-
await
|
|
3742
|
-
|
|
3743
|
-
|
|
3744
|
-
|
|
3745
|
-
} catch (
|
|
3746
|
-
|
|
3974
|
+
await postPipelineAction(runId, "cancel");
|
|
3975
|
+
setProgressState(null);
|
|
3976
|
+
resetStreamState();
|
|
3977
|
+
addTerminalLine("info", "Stopped the analysis.");
|
|
3978
|
+
} catch (error) {
|
|
3979
|
+
addTerminalLine("error", `The analysis is still running. ${error.message}`);
|
|
3747
3980
|
}
|
|
3748
|
-
}, [
|
|
3981
|
+
}, [postPipelineAction, resetStreamState, addTerminalLine]);
|
|
3982
|
+
const settleAgentSteps = useCallback(
|
|
3983
|
+
(lineId) => {
|
|
3984
|
+
setTerminalHistory((prev) => {
|
|
3985
|
+
const idx = prev.findIndex((line) => line.id === lineId);
|
|
3986
|
+
if (idx === -1) return prev;
|
|
3987
|
+
const meta = prev[idx].metadata;
|
|
3988
|
+
if (!meta?.agentStepsLive) return prev;
|
|
3989
|
+
const updated = [...prev];
|
|
3990
|
+
updated[idx] = {
|
|
3991
|
+
...updated[idx],
|
|
3992
|
+
metadata: { ...updated[idx].metadata || {}, agentStepsLive: false }
|
|
3993
|
+
};
|
|
3994
|
+
return updated;
|
|
3995
|
+
});
|
|
3996
|
+
},
|
|
3997
|
+
[setTerminalHistory]
|
|
3998
|
+
);
|
|
3749
3999
|
const handleStreamingChat = useCallback(
|
|
3750
4000
|
async (cmd) => {
|
|
3751
4001
|
if (isProcessingRef.current || !onStreamRequest) return;
|
|
@@ -3757,8 +4007,9 @@ function useStreamingChat({
|
|
|
3757
4007
|
const startMs = Date.now();
|
|
3758
4008
|
setStreamTransparency({ startedAtMs: startMs, lastEventAtMs: startMs });
|
|
3759
4009
|
setActivityEvents([]);
|
|
3760
|
-
const
|
|
3761
|
-
const
|
|
4010
|
+
const turnKey = `${Date.now()}-${++turnSequence.current}`;
|
|
4011
|
+
const userCommandId = `${turnKey}:question`;
|
|
4012
|
+
const streamingLineId = `${turnKey}:answer`;
|
|
3762
4013
|
currentStreamingLineId.current = streamingLineId;
|
|
3763
4014
|
const userCommandEntry = {
|
|
3764
4015
|
id: userCommandId,
|
|
@@ -3784,14 +4035,14 @@ function useStreamingChat({
|
|
|
3784
4035
|
setTerminalHistory((prev) => [
|
|
3785
4036
|
...prev,
|
|
3786
4037
|
{
|
|
3787
|
-
id:
|
|
4038
|
+
id: `${turnKey}:before-question`,
|
|
3788
4039
|
type: "info",
|
|
3789
4040
|
content: "",
|
|
3790
4041
|
timestamp: /* @__PURE__ */ new Date()
|
|
3791
4042
|
},
|
|
3792
4043
|
userCommandEntry,
|
|
3793
4044
|
{
|
|
3794
|
-
id:
|
|
4045
|
+
id: `${turnKey}:before-answer`,
|
|
3795
4046
|
type: "info",
|
|
3796
4047
|
content: "",
|
|
3797
4048
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -3805,10 +4056,37 @@ function useStreamingChat({
|
|
|
3805
4056
|
let sources;
|
|
3806
4057
|
let kgId;
|
|
3807
4058
|
let runId;
|
|
4059
|
+
const steps = /* @__PURE__ */ new Map();
|
|
4060
|
+
const fail = (error) => {
|
|
4061
|
+
if (currentStreamingLineId.current !== streamingLineId) return;
|
|
4062
|
+
settleAgentSteps(streamingLineId);
|
|
4063
|
+
updateStreamingLine(
|
|
4064
|
+
streamingLineId,
|
|
4065
|
+
fullResponse,
|
|
4066
|
+
pageSuggestions,
|
|
4067
|
+
suggestedActions,
|
|
4068
|
+
progressStateRef.current ? captureReasoningSnapshot(progressStateRef.current, true) : void 0,
|
|
4069
|
+
pipelineDraft,
|
|
4070
|
+
sources,
|
|
4071
|
+
kgId,
|
|
4072
|
+
runId
|
|
4073
|
+
);
|
|
4074
|
+
setTerminalHistory((prev) => prev.map((entry) => entry.id === streamingLineId ? { ...entry, metadata: { ...entry.metadata, completion: { stop_reason: /connection|interrupt/i.test(error) ? "interrupted" : "failed" } } } : entry));
|
|
4075
|
+
addTerminalLine("error", error);
|
|
4076
|
+
setProgressState(null);
|
|
4077
|
+
resetStreamState();
|
|
4078
|
+
};
|
|
3808
4079
|
try {
|
|
3809
4080
|
await onStreamRequest(cmd, {
|
|
3810
4081
|
onChunk: (chunk) => {
|
|
4082
|
+
if (currentStreamingLineId.current !== streamingLineId) return;
|
|
4083
|
+
if (chunk.entryMetadata) {
|
|
4084
|
+
setTerminalHistory((prev) => prev.map((entry) => entry.id === streamingLineId ? { ...entry, metadata: { ...entry.metadata, ...chunk.entryMetadata } } : entry));
|
|
4085
|
+
}
|
|
3811
4086
|
const eventMs = Date.now();
|
|
4087
|
+
if (chunk.completion) {
|
|
4088
|
+
setTerminalHistory((prev) => prev.map((entry) => entry.id === streamingLineId ? { ...entry, metadata: { ...entry.metadata, completion: chunk.completion } } : entry));
|
|
4089
|
+
}
|
|
3812
4090
|
if (chunk.sender) {
|
|
3813
4091
|
setStreamingLineSender(streamingLineId, chunk.sender);
|
|
3814
4092
|
if (currentUser) {
|
|
@@ -3821,6 +4099,28 @@ function useStreamingChat({
|
|
|
3821
4099
|
if (chunk.collaboration) {
|
|
3822
4100
|
setCollaborationState(chunk.collaboration);
|
|
3823
4101
|
}
|
|
4102
|
+
if (chunk.step) {
|
|
4103
|
+
steps.set(chunk.step.seq, chunk.step);
|
|
4104
|
+
const ordered = Array.from(steps.values()).sort((a, b) => a.seq - b.seq);
|
|
4105
|
+
setTerminalHistory((prev) => {
|
|
4106
|
+
const idx = prev.findIndex((line) => line.id === streamingLineId);
|
|
4107
|
+
if (idx === -1) return prev;
|
|
4108
|
+
const updated = [...prev];
|
|
4109
|
+
updated[idx] = {
|
|
4110
|
+
...updated[idx],
|
|
4111
|
+
metadata: {
|
|
4112
|
+
...updated[idx].metadata || {},
|
|
4113
|
+
agentSteps: ordered,
|
|
4114
|
+
// Explicit rather than inferred from the streaming cursor:
|
|
4115
|
+
// a tool loop runs to completion BEFORE the first answer
|
|
4116
|
+
// token, so during the whole loop the entry's content is
|
|
4117
|
+
// empty and carries no cursor to read.
|
|
4118
|
+
agentStepsLive: true
|
|
4119
|
+
}
|
|
4120
|
+
};
|
|
4121
|
+
return updated;
|
|
4122
|
+
});
|
|
4123
|
+
}
|
|
3824
4124
|
const ckgId = extractKgId(chunk, chunk.progress);
|
|
3825
4125
|
const cRunId = chunk.run_id || chunk.progress?.run_id;
|
|
3826
4126
|
const ctId = chunk.thread_id || chunk.progress?.thread_id || chunk.reasoning_thread_id || chunk.progress?.reasoning_thread_id;
|
|
@@ -3964,49 +4264,14 @@ function useStreamingChat({
|
|
|
3964
4264
|
kgId,
|
|
3965
4265
|
runId
|
|
3966
4266
|
);
|
|
4267
|
+
settleAgentSteps(streamingLineId);
|
|
3967
4268
|
resetStreamState();
|
|
3968
4269
|
}
|
|
3969
4270
|
},
|
|
3970
|
-
onError:
|
|
3971
|
-
if (currentStreamingLineId.current === streamingLineId) {
|
|
3972
|
-
if (progressStateRef.current) {
|
|
3973
|
-
const snap = captureReasoningSnapshot(
|
|
3974
|
-
progressStateRef.current,
|
|
3975
|
-
true
|
|
3976
|
-
);
|
|
3977
|
-
updateStreamingLine(
|
|
3978
|
-
streamingLineId,
|
|
3979
|
-
fullResponse || "",
|
|
3980
|
-
void 0,
|
|
3981
|
-
void 0,
|
|
3982
|
-
snap
|
|
3983
|
-
);
|
|
3984
|
-
setProgressState(null);
|
|
3985
|
-
} else {
|
|
3986
|
-
addTerminalLine("error", `STREAMING ERROR: ${error}`);
|
|
3987
|
-
setProgressState(null);
|
|
3988
|
-
}
|
|
3989
|
-
resetStreamState();
|
|
3990
|
-
}
|
|
3991
|
-
}
|
|
4271
|
+
onError: fail
|
|
3992
4272
|
}, reasoningModeRef.current ? { reasoningMode: reasoningModeRef.current } : void 0);
|
|
3993
4273
|
} catch (error) {
|
|
3994
|
-
|
|
3995
|
-
const snap = captureReasoningSnapshot(
|
|
3996
|
-
progressStateRef.current,
|
|
3997
|
-
true
|
|
3998
|
-
);
|
|
3999
|
-
updateStreamingLine(
|
|
4000
|
-
currentStreamingLineId.current,
|
|
4001
|
-
fullResponse || "",
|
|
4002
|
-
void 0,
|
|
4003
|
-
void 0,
|
|
4004
|
-
snap
|
|
4005
|
-
);
|
|
4006
|
-
}
|
|
4007
|
-
addTerminalLine("error", `STREAMING EXCEPTION: ${error.message}`);
|
|
4008
|
-
setProgressState(null);
|
|
4009
|
-
resetStreamState();
|
|
4274
|
+
fail(error?.message || "The answer could not be completed.");
|
|
4010
4275
|
}
|
|
4011
4276
|
},
|
|
4012
4277
|
[
|
|
@@ -4015,7 +4280,9 @@ function useStreamingChat({
|
|
|
4015
4280
|
updateStreamingLine,
|
|
4016
4281
|
setStreamingLineSender,
|
|
4017
4282
|
resetStreamState,
|
|
4018
|
-
addTerminalLine
|
|
4283
|
+
addTerminalLine,
|
|
4284
|
+
settleAgentSteps,
|
|
4285
|
+
currentUser
|
|
4019
4286
|
]
|
|
4020
4287
|
);
|
|
4021
4288
|
const clearReasoningSession = useCallback(() => {
|
|
@@ -4108,6 +4375,7 @@ function useTerminalCore({
|
|
|
4108
4375
|
onReasoningModeChangeProp,
|
|
4109
4376
|
reasoningRef,
|
|
4110
4377
|
workingGroupContextProp = null,
|
|
4378
|
+
autoFocusInput = true,
|
|
4111
4379
|
onResolveWorkingGroup,
|
|
4112
4380
|
onRagFileUpload,
|
|
4113
4381
|
onListRagFiles,
|
|
@@ -4125,12 +4393,13 @@ function useTerminalCore({
|
|
|
4125
4393
|
pollIntervalMs,
|
|
4126
4394
|
authToken
|
|
4127
4395
|
}) {
|
|
4396
|
+
const agentLabel = config.agentLabel?.trim() || DEFAULT_AGENT_LABEL;
|
|
4128
4397
|
const [internalReasoningMode, setInternalReasoningMode] = useState(null);
|
|
4129
4398
|
const reasoningMode = reasoningModeProp !== void 0 ? reasoningModeProp : internalReasoningMode;
|
|
4130
4399
|
const onReasoningModeChange = onReasoningModeChangeProp || setInternalReasoningMode;
|
|
4131
4400
|
const [terminalHistory, setTerminalHistory] = useState(() => {
|
|
4132
4401
|
if (initialHistory && initialHistory.length > 0) return initialHistory;
|
|
4133
|
-
return [{ type: "system", content:
|
|
4402
|
+
return [{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() }];
|
|
4134
4403
|
});
|
|
4135
4404
|
useEffect(() => {
|
|
4136
4405
|
if (historyRef) {
|
|
@@ -4143,7 +4412,7 @@ function useTerminalCore({
|
|
|
4143
4412
|
const enrichedHistory = useMemo(() => {
|
|
4144
4413
|
if (!sourceKGNodes?.length) return terminalHistory;
|
|
4145
4414
|
let changed = false;
|
|
4146
|
-
const
|
|
4415
|
+
const result2 = terminalHistory.map((entry) => {
|
|
4147
4416
|
if ((entry.type === "response" || entry.type === "success") && entry.content && entry.content.length > 20 && !entry.sources?.length) {
|
|
4148
4417
|
const sources = extractKGSources(entry.content, sourceKGNodes);
|
|
4149
4418
|
if (sources.length > 0) {
|
|
@@ -4153,7 +4422,7 @@ function useTerminalCore({
|
|
|
4153
4422
|
}
|
|
4154
4423
|
return entry;
|
|
4155
4424
|
});
|
|
4156
|
-
return changed ?
|
|
4425
|
+
return changed ? result2 : terminalHistory;
|
|
4157
4426
|
}, [terminalHistory, sourceKGNodes]);
|
|
4158
4427
|
useEffect(() => {
|
|
4159
4428
|
if (initialHistory && initialHistory.length > 0) {
|
|
@@ -4173,6 +4442,7 @@ function useTerminalCore({
|
|
|
4173
4442
|
setTerminalHistory((prev) => [...prev, { id: Date.now().toString(), type: "response", content, timestamp: /* @__PURE__ */ new Date(), suggested_actions: actions }]);
|
|
4174
4443
|
}, []);
|
|
4175
4444
|
const [currentCommand, setCurrentCommand] = useState("");
|
|
4445
|
+
const [pendingSubmit, setPendingSubmit] = useState(null);
|
|
4176
4446
|
const [workingGroupContext, setWorkingGroupContext] = useState(workingGroupContextProp);
|
|
4177
4447
|
const [hasShownWelcome, setHasShownWelcome] = useState(false);
|
|
4178
4448
|
const [isInputFocused, setIsInputFocused] = useState(true);
|
|
@@ -4185,13 +4455,16 @@ function useTerminalCore({
|
|
|
4185
4455
|
for (const ctrl of uploadAbortsRef.current) ctrl.abort();
|
|
4186
4456
|
uploadAbortsRef.current = [];
|
|
4187
4457
|
}, []);
|
|
4188
|
-
const { inputRef, focusInput } = useFocusManagement();
|
|
4458
|
+
const { inputRef, focusInput } = useFocusManagement(autoFocusInput);
|
|
4189
4459
|
useEffect(() => {
|
|
4190
4460
|
function onPrefill(e) {
|
|
4191
4461
|
const detail = e.detail;
|
|
4192
4462
|
if (!detail || typeof detail.value !== "string") return;
|
|
4193
4463
|
const value = detail.value;
|
|
4194
4464
|
setCurrentCommand(value);
|
|
4465
|
+
if (e.detail?.submit) {
|
|
4466
|
+
setPendingSubmit(value);
|
|
4467
|
+
}
|
|
4195
4468
|
requestAnimationFrame(() => {
|
|
4196
4469
|
focusInput();
|
|
4197
4470
|
const el = inputRef.current;
|
|
@@ -4205,6 +4478,9 @@ function useTerminalCore({
|
|
|
4205
4478
|
window.removeEventListener("yieldfabric:terminal:prefill", onPrefill);
|
|
4206
4479
|
};
|
|
4207
4480
|
}, [focusInput, inputRef]);
|
|
4481
|
+
const restoreInputFocus = useCallback(() => {
|
|
4482
|
+
if (autoFocusInput) focusInput();
|
|
4483
|
+
}, [autoFocusInput, focusInput]);
|
|
4208
4484
|
const {
|
|
4209
4485
|
isExecuting,
|
|
4210
4486
|
setIsExecuting,
|
|
@@ -4224,11 +4500,12 @@ function useTerminalCore({
|
|
|
4224
4500
|
activityEvents
|
|
4225
4501
|
} = useStreamingChat({
|
|
4226
4502
|
config,
|
|
4503
|
+
authToken,
|
|
4227
4504
|
onStreamRequest,
|
|
4228
4505
|
reasoningMode,
|
|
4229
4506
|
setTerminalHistory,
|
|
4230
4507
|
addTerminalLine,
|
|
4231
|
-
focusInput,
|
|
4508
|
+
focusInput: restoreInputFocus,
|
|
4232
4509
|
currentUser,
|
|
4233
4510
|
sourceKGNodes
|
|
4234
4511
|
});
|
|
@@ -4291,12 +4568,12 @@ function useTerminalCore({
|
|
|
4291
4568
|
}, [onResolveWorkingGroup]);
|
|
4292
4569
|
useEffect(() => {
|
|
4293
4570
|
const handleActionResult = (event) => {
|
|
4294
|
-
const
|
|
4295
|
-
if (
|
|
4571
|
+
const result2 = event.detail;
|
|
4572
|
+
if (result2.success) {
|
|
4296
4573
|
addTerminalLine("success", "Action executed successfully!");
|
|
4297
|
-
if (
|
|
4574
|
+
if (result2.data) addTerminalLine("response", JSON.stringify(result2.data, null, 2));
|
|
4298
4575
|
} else {
|
|
4299
|
-
addTerminalLine("error", `Action failed: ${
|
|
4576
|
+
addTerminalLine("error", `Action failed: ${result2.error || "Unknown error"}`);
|
|
4300
4577
|
}
|
|
4301
4578
|
};
|
|
4302
4579
|
window.addEventListener("terminal-action-result", handleActionResult);
|
|
@@ -4308,7 +4585,7 @@ function useTerminalCore({
|
|
|
4308
4585
|
const fullMessage = config.welcomeMessage;
|
|
4309
4586
|
const typingLineId = Date.now().toString();
|
|
4310
4587
|
setTerminalHistory([
|
|
4311
|
-
{ type: "system", content:
|
|
4588
|
+
{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() },
|
|
4312
4589
|
{ id: typingLineId, type: "info", content: "", timestamp: /* @__PURE__ */ new Date() }
|
|
4313
4590
|
]);
|
|
4314
4591
|
let i = 0;
|
|
@@ -4364,7 +4641,7 @@ function useTerminalCore({
|
|
|
4364
4641
|
}, [commandPaletteItems, selectedPaletteItem]);
|
|
4365
4642
|
const handleClearCommand = useCallback(() => {
|
|
4366
4643
|
setTerminalHistory([
|
|
4367
|
-
{ type: "system", content:
|
|
4644
|
+
{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() },
|
|
4368
4645
|
{ type: "system", content: "Terminal cleared.", timestamp: /* @__PURE__ */ new Date() }
|
|
4369
4646
|
]);
|
|
4370
4647
|
setCurrentCommand("");
|
|
@@ -4387,11 +4664,11 @@ function useTerminalCore({
|
|
|
4387
4664
|
addTerminalLine("info", `Uploading ${files.length} file(s)...`);
|
|
4388
4665
|
setIsExecuting(true);
|
|
4389
4666
|
try {
|
|
4390
|
-
const
|
|
4391
|
-
if (
|
|
4392
|
-
addTerminalLine("success", `Started ${
|
|
4393
|
-
if (
|
|
4394
|
-
const runs =
|
|
4667
|
+
const result2 = await onRagFileUpload(files, workingGroupContext);
|
|
4668
|
+
if (result2.success) {
|
|
4669
|
+
addTerminalLine("success", `Started ${result2.pipelineRuns?.length ?? result2.documentsIngested ?? files.length} ingestion pipeline(s)`);
|
|
4670
|
+
if (result2.message) addTerminalLine("response", result2.message);
|
|
4671
|
+
const runs = result2.pipelineRuns ?? [];
|
|
4395
4672
|
if (runs.length > 0) {
|
|
4396
4673
|
const apiUrl = config.agentsApiUrl || "http://localhost:3001";
|
|
4397
4674
|
const remaining = new Set(runs.map((r) => r.run_id));
|
|
@@ -4478,7 +4755,7 @@ function useTerminalCore({
|
|
|
4478
4755
|
await handleListFilesCommand();
|
|
4479
4756
|
}
|
|
4480
4757
|
} else {
|
|
4481
|
-
addTerminalLine("error", `Upload failed${
|
|
4758
|
+
addTerminalLine("error", `Upload failed${result2.message ? `: ${result2.message}` : ""}`);
|
|
4482
4759
|
}
|
|
4483
4760
|
} catch (error) {
|
|
4484
4761
|
addTerminalLine("error", `Upload exception: ${error?.message || "Unknown error"}`);
|
|
@@ -4487,7 +4764,7 @@ function useTerminalCore({
|
|
|
4487
4764
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
4488
4765
|
setTimeout(() => focusInput(), 50);
|
|
4489
4766
|
}
|
|
4490
|
-
}, [onRagFileUpload, onListRagFiles, workingGroupContext, addTerminalLine, setIsExecuting, focusInput, config.agentsApiUrl]);
|
|
4767
|
+
}, [onRagFileUpload, onListRagFiles, workingGroupContext, addTerminalLine, setIsExecuting, focusInput, config.agentsApiUrl, authToken]);
|
|
4491
4768
|
const handleListFilesCommand = useCallback(async () => {
|
|
4492
4769
|
addTerminalLine("info", "");
|
|
4493
4770
|
addTerminalLine("command", "files");
|
|
@@ -4497,12 +4774,12 @@ function useTerminalCore({
|
|
|
4497
4774
|
}
|
|
4498
4775
|
setIsExecuting(true);
|
|
4499
4776
|
try {
|
|
4500
|
-
const
|
|
4501
|
-
if (!
|
|
4502
|
-
addTerminalLine("error", `Could not load files${
|
|
4777
|
+
const result2 = await onListRagFiles(workingGroupContext);
|
|
4778
|
+
if (!result2.success) {
|
|
4779
|
+
addTerminalLine("error", `Could not load files${result2.message ? `: ${result2.message}` : ""}`);
|
|
4503
4780
|
return;
|
|
4504
4781
|
}
|
|
4505
|
-
const files =
|
|
4782
|
+
const files = result2.files || [];
|
|
4506
4783
|
if (files.length === 0) {
|
|
4507
4784
|
addTerminalLine("info", "No files uploaded yet for this page working group.");
|
|
4508
4785
|
return;
|
|
@@ -4531,12 +4808,12 @@ function useTerminalCore({
|
|
|
4531
4808
|
return;
|
|
4532
4809
|
}
|
|
4533
4810
|
const title = payload.title || payload.document_id;
|
|
4534
|
-
const
|
|
4535
|
-
if (
|
|
4811
|
+
const result2 = await onDeleteRagFile(String(payload.document_id), workingGroupContext);
|
|
4812
|
+
if (result2.success) {
|
|
4536
4813
|
addTerminalLine("success", `Removed ${title}`);
|
|
4537
4814
|
await handleListFilesCommand();
|
|
4538
4815
|
} else {
|
|
4539
|
-
addTerminalLine("error", `Failed to remove ${title}${
|
|
4816
|
+
addTerminalLine("error", `Failed to remove ${title}${result2.message ? `: ${result2.message}` : ""}`);
|
|
4540
4817
|
}
|
|
4541
4818
|
return;
|
|
4542
4819
|
}
|
|
@@ -4546,9 +4823,9 @@ function useTerminalCore({
|
|
|
4546
4823
|
return;
|
|
4547
4824
|
}
|
|
4548
4825
|
const title = payload.title || payload.document_id;
|
|
4549
|
-
const
|
|
4550
|
-
if (
|
|
4551
|
-
else addTerminalLine("error", `Download failed for ${title}${
|
|
4826
|
+
const result2 = await onDownloadRagFile(String(payload.document_id), title, workingGroupContext);
|
|
4827
|
+
if (result2.success) addTerminalLine("success", `Download started: ${title}`);
|
|
4828
|
+
else addTerminalLine("error", `Download failed for ${title}${result2.message ? `: ${result2.message}` : ""}`);
|
|
4552
4829
|
return;
|
|
4553
4830
|
}
|
|
4554
4831
|
if (actionType === "resume_pipeline_run") {
|
|
@@ -4587,6 +4864,8 @@ function useTerminalCore({
|
|
|
4587
4864
|
window.dispatchEvent(new CustomEvent("terminal-action-execute", { detail: updatedAction, bubbles: true }));
|
|
4588
4865
|
}, [onDeleteRagFile, onDownloadRagFile, workingGroupContext, addTerminalLine, handleListFilesCommand, config.agentsApiUrl]);
|
|
4589
4866
|
return {
|
|
4867
|
+
// Identity
|
|
4868
|
+
agentLabel,
|
|
4590
4869
|
// History
|
|
4591
4870
|
terminalHistory,
|
|
4592
4871
|
setTerminalHistory,
|
|
@@ -4615,6 +4894,8 @@ function useTerminalCore({
|
|
|
4615
4894
|
// Command input
|
|
4616
4895
|
currentCommand,
|
|
4617
4896
|
setCurrentCommand,
|
|
4897
|
+
pendingSubmit,
|
|
4898
|
+
setPendingSubmit,
|
|
4618
4899
|
commandPaletteItems,
|
|
4619
4900
|
setCommandPaletteItems,
|
|
4620
4901
|
selectedPaletteItem,
|
|
@@ -4737,6 +5018,7 @@ function extractQuery(input, caret, enabledCommands, requireSlashCommand) {
|
|
|
4737
5018
|
return { query: tail, command: cmd };
|
|
4738
5019
|
}
|
|
4739
5020
|
function StandardTerminal({
|
|
5021
|
+
showBusyIndicator,
|
|
4740
5022
|
theme: themeOverrides,
|
|
4741
5023
|
config,
|
|
4742
5024
|
onCommandExecute,
|
|
@@ -4756,9 +5038,15 @@ function StandardTerminal({
|
|
|
4756
5038
|
onDeleteRagFile,
|
|
4757
5039
|
onDownloadRagFile,
|
|
4758
5040
|
workingGroupContext: workingGroupContextProp = null,
|
|
5041
|
+
showWorkingGroupBanner = true,
|
|
5042
|
+
autoFocusInput = true,
|
|
5043
|
+
inputPlaceholder,
|
|
5044
|
+
submitRequest,
|
|
5045
|
+
onSubmitRequest,
|
|
4759
5046
|
onPipelineDraftEdit,
|
|
4760
5047
|
onPipelineDraftReject,
|
|
4761
5048
|
onSubmitNote,
|
|
5049
|
+
onSubmitLog,
|
|
4762
5050
|
onMentionResolve,
|
|
4763
5051
|
onMentionPicked,
|
|
4764
5052
|
availableKGs,
|
|
@@ -4779,6 +5067,7 @@ function StandardTerminal({
|
|
|
4779
5067
|
widgets,
|
|
4780
5068
|
slots,
|
|
4781
5069
|
onSourcesActivate,
|
|
5070
|
+
onSourceActivate,
|
|
4782
5071
|
onPollMessages,
|
|
4783
5072
|
pollIntervalMs,
|
|
4784
5073
|
historyRef
|
|
@@ -4794,6 +5083,7 @@ function StandardTerminal({
|
|
|
4794
5083
|
reasoningRef,
|
|
4795
5084
|
workingGroupContextProp,
|
|
4796
5085
|
onResolveWorkingGroup,
|
|
5086
|
+
autoFocusInput,
|
|
4797
5087
|
onRagFileUpload,
|
|
4798
5088
|
onListRagFiles,
|
|
4799
5089
|
onDeleteRagFile,
|
|
@@ -4809,17 +5099,32 @@ function StandardTerminal({
|
|
|
4809
5099
|
showWelcomeMessage
|
|
4810
5100
|
});
|
|
4811
5101
|
const { pushCommand, navigateUp, navigateDown, resetIndex } = useCommandHistory();
|
|
5102
|
+
const consumedRequest = useRef(null);
|
|
5103
|
+
React15.useEffect(() => {
|
|
5104
|
+
if (!submitRequest || consumedRequest.current === submitRequest.id || !submitRequest.value.trim() || !onStreamRequest || core.isExecuting || core.isStreaming || core.currentStreamingLineId.current) return;
|
|
5105
|
+
consumedRequest.current = submitRequest.id;
|
|
5106
|
+
onSubmitRequest?.(submitRequest.id);
|
|
5107
|
+
void core.handleStreamingChat(submitRequest.value.trim());
|
|
5108
|
+
}, [
|
|
5109
|
+
submitRequest,
|
|
5110
|
+
onSubmitRequest,
|
|
5111
|
+
onStreamRequest,
|
|
5112
|
+
core.isExecuting,
|
|
5113
|
+
core.isStreaming,
|
|
5114
|
+
core.currentStreamingLineId,
|
|
5115
|
+
core.handleStreamingChat
|
|
5116
|
+
]);
|
|
4812
5117
|
const [suggestions, setSuggestions] = useState([]);
|
|
4813
5118
|
const [selectedSuggestion, setSelectedSuggestion] = useState(0);
|
|
4814
5119
|
const [internalAuthToken, setInternalAuthToken] = useState(authToken);
|
|
4815
5120
|
const authTokenRef = useRef(internalAuthToken);
|
|
4816
5121
|
authTokenRef.current = internalAuthToken;
|
|
4817
|
-
|
|
5122
|
+
React15.useEffect(() => {
|
|
4818
5123
|
if (authToken !== internalAuthToken) setInternalAuthToken(authToken);
|
|
4819
5124
|
}, [authToken]);
|
|
4820
5125
|
const [caretIndex, setCaretIndex] = useState(0);
|
|
4821
5126
|
const [slashPickedNames, setSlashPickedNames] = useState([]);
|
|
4822
|
-
const liveSlashPickedNames =
|
|
5127
|
+
const liveSlashPickedNames = React15.useMemo(
|
|
4823
5128
|
() => slashPickedNames.filter(
|
|
4824
5129
|
(n) => core.currentCommand.toLowerCase().includes(`@${n.toLowerCase()}`)
|
|
4825
5130
|
),
|
|
@@ -4906,6 +5211,11 @@ function StandardTerminal({
|
|
|
4906
5211
|
setSuggestions([]);
|
|
4907
5212
|
}
|
|
4908
5213
|
};
|
|
5214
|
+
React15.useEffect(() => {
|
|
5215
|
+
if (!core.pendingSubmit) return;
|
|
5216
|
+
core.setPendingSubmit(null);
|
|
5217
|
+
void handleSubmit();
|
|
5218
|
+
}, [core.pendingSubmit]);
|
|
4909
5219
|
const handleSubmit = async () => {
|
|
4910
5220
|
if (!core.currentCommand.trim() || core.isExecuting || core.isStreaming || core.currentStreamingLineId.current) return;
|
|
4911
5221
|
const rawCmd = core.currentCommand.trim();
|
|
@@ -4953,6 +5263,21 @@ function StandardTerminal({
|
|
|
4953
5263
|
setTimeout(() => core.focusInput(), 50);
|
|
4954
5264
|
return;
|
|
4955
5265
|
}
|
|
5266
|
+
if (command === "log") {
|
|
5267
|
+
const prose = args.join(" ");
|
|
5268
|
+
core.addTerminalLine("command", prose.trim() ? `log ${prose}` : "log");
|
|
5269
|
+
if (!onSubmitLog) {
|
|
5270
|
+
core.addTerminalLine("error", "Work capture is not available in this context.");
|
|
5271
|
+
} else if (!prose.trim()) {
|
|
5272
|
+
core.addTerminalLine("info", "Usage: /log <what you did or decided>");
|
|
5273
|
+
} else {
|
|
5274
|
+
const result2 = await onSubmitLog(prose);
|
|
5275
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
5276
|
+
}
|
|
5277
|
+
core.setCurrentCommand("");
|
|
5278
|
+
setTimeout(() => core.focusInput(), 50);
|
|
5279
|
+
return;
|
|
5280
|
+
}
|
|
4956
5281
|
if (isNaturalLanguage(cmd, config.endpoints) && onStreamRequest) {
|
|
4957
5282
|
await core.handleStreamingChat(cmd);
|
|
4958
5283
|
core.setCurrentCommand("");
|
|
@@ -5008,8 +5333,8 @@ function StandardTerminal({
|
|
|
5008
5333
|
);
|
|
5009
5334
|
return;
|
|
5010
5335
|
}
|
|
5011
|
-
const
|
|
5012
|
-
core.addTerminalLine(
|
|
5336
|
+
const result2 = await onSubmitNote(prose, scope);
|
|
5337
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
5013
5338
|
};
|
|
5014
5339
|
const handleTokenCommand = (args) => {
|
|
5015
5340
|
core.addTerminalLine("command", `token ${args.join(" ")}`);
|
|
@@ -5037,18 +5362,18 @@ Method: ${parsed.endpoint.method}
|
|
|
5037
5362
|
Path: ${parsed.endpoint.path}`);
|
|
5038
5363
|
core.addTerminalLine("info", "");
|
|
5039
5364
|
try {
|
|
5040
|
-
const
|
|
5041
|
-
if (
|
|
5042
|
-
core.addTerminalLine("success",
|
|
5043
|
-
if (
|
|
5044
|
-
if (parsed.endpoint.id.includes("login") &&
|
|
5045
|
-
setInternalAuthToken(
|
|
5046
|
-
onAuthTokenChange?.(
|
|
5365
|
+
const result2 = await onCommandExecute(cmd, parsed.endpoint, parsed.args);
|
|
5366
|
+
if (result2.success) {
|
|
5367
|
+
core.addTerminalLine("success", result2.message || "RESPONSE: SUCCESS");
|
|
5368
|
+
if (result2.data) core.addTerminalLine("response", JSON.stringify(result2.data, null, 2));
|
|
5369
|
+
if (parsed.endpoint.id.includes("login") && result2.data?.token) {
|
|
5370
|
+
setInternalAuthToken(result2.data.token);
|
|
5371
|
+
onAuthTokenChange?.(result2.data.token);
|
|
5047
5372
|
core.addTerminalLine("success", "AUTH TOKEN AUTO-SAVED");
|
|
5048
5373
|
}
|
|
5049
5374
|
} else {
|
|
5050
|
-
core.addTerminalLine("error", `ERROR: ${
|
|
5051
|
-
if (
|
|
5375
|
+
core.addTerminalLine("error", `ERROR: ${result2.error || "Request failed"}`);
|
|
5376
|
+
if (result2.data) core.addTerminalLine("response", JSON.stringify(result2.data, null, 2));
|
|
5052
5377
|
}
|
|
5053
5378
|
} catch (error) {
|
|
5054
5379
|
core.addTerminalLine("error", `SYSTEM ERROR: ${error.message}`);
|
|
@@ -5071,14 +5396,17 @@ Path: ${parsed.endpoint.path}`);
|
|
|
5071
5396
|
className,
|
|
5072
5397
|
style,
|
|
5073
5398
|
showHeader,
|
|
5399
|
+
agentLabel: core.agentLabel,
|
|
5074
5400
|
focusInput: core.focusInput,
|
|
5075
5401
|
setTerminalHistory: core.setTerminalHistory,
|
|
5076
5402
|
terminalBodyRef: core.terminalBodyRef,
|
|
5077
5403
|
workingGroupContext: core.workingGroupContext,
|
|
5404
|
+
showWorkingGroupBanner,
|
|
5078
5405
|
progressState: core.progressState,
|
|
5079
5406
|
streamTransparency: core.streamTransparency,
|
|
5080
5407
|
streamNowMs: core.streamNowMs,
|
|
5081
5408
|
isExecuting: core.isExecuting,
|
|
5409
|
+
showBusyIndicator,
|
|
5082
5410
|
handleCancelReasoning: core.handleCancelReasoning,
|
|
5083
5411
|
onViewKnowledgeGraph,
|
|
5084
5412
|
onLiveKGUpdate,
|
|
@@ -5153,11 +5481,12 @@ Path: ${parsed.endpoint.path}`);
|
|
|
5153
5481
|
inputBar: /* @__PURE__ */ jsx(
|
|
5154
5482
|
TerminalInputBar,
|
|
5155
5483
|
{
|
|
5484
|
+
autoFocus: autoFocusInput,
|
|
5156
5485
|
inputRef: core.inputRef,
|
|
5157
5486
|
fileInputRef: core.fileInputRef,
|
|
5158
5487
|
currentCommand: core.currentCommand,
|
|
5159
5488
|
isExecuting: core.isExecuting,
|
|
5160
|
-
placeholder: activeKGScope ? `Ask about ${activeKGScope.label}...` : "Ask anything...",
|
|
5489
|
+
placeholder: activeKGScope ? `Ask about ${activeKGScope.label}...` : inputPlaceholder ?? "Ask anything...",
|
|
5161
5490
|
onInputChange: handleInputChange,
|
|
5162
5491
|
onKeyDown: handleKeyDown,
|
|
5163
5492
|
onSubmit: handleSubmit,
|
|
@@ -5194,6 +5523,7 @@ Path: ${parsed.endpoint.path}`);
|
|
|
5194
5523
|
authToken: authTokenRef.current,
|
|
5195
5524
|
onPageNavigation,
|
|
5196
5525
|
onSourcesActivate,
|
|
5526
|
+
onSourceActivate,
|
|
5197
5527
|
renderEntryExtra,
|
|
5198
5528
|
renderEntry,
|
|
5199
5529
|
widgets,
|
|
@@ -5484,6 +5814,7 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5484
5814
|
};
|
|
5485
5815
|
}
|
|
5486
5816
|
function ChatTerminal({
|
|
5817
|
+
showBusyIndicator,
|
|
5487
5818
|
theme: themeOverrides,
|
|
5488
5819
|
config,
|
|
5489
5820
|
className = "",
|
|
@@ -5499,6 +5830,8 @@ function ChatTerminal({
|
|
|
5499
5830
|
onDeleteRagFile,
|
|
5500
5831
|
onDownloadRagFile,
|
|
5501
5832
|
workingGroupContext: workingGroupContextProp = null,
|
|
5833
|
+
showWorkingGroupBanner = true,
|
|
5834
|
+
autoFocusInput = true,
|
|
5502
5835
|
onPipelineDraftEdit,
|
|
5503
5836
|
onPipelineDraftReject,
|
|
5504
5837
|
onPageNavigation,
|
|
@@ -5521,6 +5854,7 @@ function ChatTerminal({
|
|
|
5521
5854
|
widgets,
|
|
5522
5855
|
slots,
|
|
5523
5856
|
onSourcesActivate,
|
|
5857
|
+
onSourceActivate,
|
|
5524
5858
|
historyRef,
|
|
5525
5859
|
currentUser,
|
|
5526
5860
|
onSendMessage,
|
|
@@ -5530,8 +5864,10 @@ function ChatTerminal({
|
|
|
5530
5864
|
typingUsers,
|
|
5531
5865
|
onTyping,
|
|
5532
5866
|
onSubmitNote,
|
|
5867
|
+
onSubmitLog,
|
|
5533
5868
|
onMentionResolve,
|
|
5534
|
-
onMentionPicked
|
|
5869
|
+
onMentionPicked,
|
|
5870
|
+
authToken
|
|
5535
5871
|
}) {
|
|
5536
5872
|
const core = useTerminalCore({
|
|
5537
5873
|
config,
|
|
@@ -5544,6 +5880,7 @@ function ChatTerminal({
|
|
|
5544
5880
|
reasoningRef,
|
|
5545
5881
|
workingGroupContextProp,
|
|
5546
5882
|
onResolveWorkingGroup,
|
|
5883
|
+
autoFocusInput,
|
|
5547
5884
|
onRagFileUpload,
|
|
5548
5885
|
onListRagFiles,
|
|
5549
5886
|
onDeleteRagFile,
|
|
@@ -5557,7 +5894,8 @@ function ChatTerminal({
|
|
|
5557
5894
|
showWelcomeMessage,
|
|
5558
5895
|
currentUser,
|
|
5559
5896
|
onPollMessages,
|
|
5560
|
-
pollIntervalMs
|
|
5897
|
+
pollIntervalMs,
|
|
5898
|
+
authToken
|
|
5561
5899
|
});
|
|
5562
5900
|
useEffect(() => {
|
|
5563
5901
|
onActivityEventsChange?.(core.activityEvents);
|
|
@@ -5701,11 +6039,26 @@ function ChatTerminal({
|
|
|
5701
6039
|
`Usage: /${command} <prose>. Use @name to link an entity.`
|
|
5702
6040
|
);
|
|
5703
6041
|
} else {
|
|
5704
|
-
const
|
|
6042
|
+
const result2 = await onSubmitNote(
|
|
5705
6043
|
prose,
|
|
5706
6044
|
command === "personal" ? "personal" : "workspace"
|
|
5707
6045
|
);
|
|
5708
|
-
core.addTerminalLine(
|
|
6046
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
6047
|
+
}
|
|
6048
|
+
core.setCurrentCommand("");
|
|
6049
|
+
setTimeout(() => core.focusInput(), 50);
|
|
6050
|
+
return;
|
|
6051
|
+
}
|
|
6052
|
+
if (command === "log") {
|
|
6053
|
+
const prose = args.join(" ");
|
|
6054
|
+
core.addTerminalLine("command", prose.trim() ? `log ${prose}` : "log");
|
|
6055
|
+
if (!onSubmitLog) {
|
|
6056
|
+
core.addTerminalLine("error", "Work capture is not available in this context.");
|
|
6057
|
+
} else if (!prose.trim()) {
|
|
6058
|
+
core.addTerminalLine("info", "Usage: /log <what you did or decided>");
|
|
6059
|
+
} else {
|
|
6060
|
+
const result2 = await onSubmitLog(prose);
|
|
6061
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
5709
6062
|
}
|
|
5710
6063
|
core.setCurrentCommand("");
|
|
5711
6064
|
setTimeout(() => core.focusInput(), 50);
|
|
@@ -5752,14 +6105,17 @@ function ChatTerminal({
|
|
|
5752
6105
|
className,
|
|
5753
6106
|
style,
|
|
5754
6107
|
showHeader,
|
|
6108
|
+
agentLabel: core.agentLabel,
|
|
5755
6109
|
focusInput: core.focusInput,
|
|
5756
6110
|
setTerminalHistory: core.setTerminalHistory,
|
|
5757
6111
|
terminalBodyRef: core.terminalBodyRef,
|
|
5758
6112
|
workingGroupContext: core.workingGroupContext,
|
|
6113
|
+
showWorkingGroupBanner,
|
|
5759
6114
|
progressState: core.progressState,
|
|
5760
6115
|
streamTransparency: core.streamTransparency,
|
|
5761
6116
|
streamNowMs: core.streamNowMs,
|
|
5762
6117
|
isExecuting: core.isExecuting,
|
|
6118
|
+
showBusyIndicator,
|
|
5763
6119
|
handleCancelReasoning: core.handleCancelReasoning,
|
|
5764
6120
|
onViewKnowledgeGraph,
|
|
5765
6121
|
onLiveKGUpdate,
|
|
@@ -5796,6 +6152,7 @@ function ChatTerminal({
|
|
|
5796
6152
|
inputBar: /* @__PURE__ */ jsx(
|
|
5797
6153
|
TerminalInputBar,
|
|
5798
6154
|
{
|
|
6155
|
+
autoFocus: autoFocusInput,
|
|
5799
6156
|
inputRef: core.inputRef,
|
|
5800
6157
|
fileInputRef: core.fileInputRef,
|
|
5801
6158
|
currentCommand: core.currentCommand,
|
|
@@ -5848,6 +6205,7 @@ function ChatTerminal({
|
|
|
5848
6205
|
config,
|
|
5849
6206
|
onPageNavigation,
|
|
5850
6207
|
onSourcesActivate,
|
|
6208
|
+
onSourceActivate,
|
|
5851
6209
|
renderEntryExtra,
|
|
5852
6210
|
renderEntry,
|
|
5853
6211
|
widgets,
|
|
@@ -7004,6 +7362,227 @@ function ReasoningHistoryCard({
|
|
|
7004
7362
|
}
|
|
7005
7363
|
);
|
|
7006
7364
|
}
|
|
7365
|
+
function subject(step) {
|
|
7366
|
+
const idx = step.detail.indexOf(": ");
|
|
7367
|
+
const s = idx > -1 ? step.detail.slice(idx + 2).trim() : "";
|
|
7368
|
+
return s.length ? s : null;
|
|
7369
|
+
}
|
|
7370
|
+
function bare(tool) {
|
|
7371
|
+
return tool.replace(/^yf_kg_/, "").replace(/^yf_/, "");
|
|
7372
|
+
}
|
|
7373
|
+
function action(step) {
|
|
7374
|
+
const subj = subject(step);
|
|
7375
|
+
const quoted = subj ? `\u201C${subj}\u201D` : null;
|
|
7376
|
+
switch (bare(step.tool)) {
|
|
7377
|
+
case "graphs":
|
|
7378
|
+
return "Listed knowledge collections";
|
|
7379
|
+
case "search":
|
|
7380
|
+
return quoted ? `Searched for ${quoted}` : "Searched the documents";
|
|
7381
|
+
case "count":
|
|
7382
|
+
return quoted ? `Counted mentions of ${quoted}` : "Counted mentions";
|
|
7383
|
+
case "enumerate":
|
|
7384
|
+
return quoted ? `Listed every match for ${quoted}` : "Listed every match";
|
|
7385
|
+
case "fetch":
|
|
7386
|
+
return "Read a document";
|
|
7387
|
+
case "entities":
|
|
7388
|
+
return "Listed the people and things found";
|
|
7389
|
+
case "explore":
|
|
7390
|
+
return quoted ? `Followed connections from ${quoted}` : "Followed connections";
|
|
7391
|
+
case "sets":
|
|
7392
|
+
return "Listed frozen document sets";
|
|
7393
|
+
case "get_set":
|
|
7394
|
+
return "Read a frozen document set";
|
|
7395
|
+
case "count_in_set":
|
|
7396
|
+
return quoted ? `Counted ${quoted} inside a set` : "Counted inside a set";
|
|
7397
|
+
case "think":
|
|
7398
|
+
return "Thought it through";
|
|
7399
|
+
default:
|
|
7400
|
+
return subj ? `${bare(step.tool).replace(/_/g, " ")} ${subj}` : bare(step.tool).replace(/_/g, " ");
|
|
7401
|
+
}
|
|
7402
|
+
}
|
|
7403
|
+
function took(step) {
|
|
7404
|
+
if (step.status === "running") return null;
|
|
7405
|
+
const ms = Number(step.ms);
|
|
7406
|
+
if (!Number.isFinite(ms) || ms < 1e3) return null;
|
|
7407
|
+
return ms < 1e4 ? `${(ms / 1e3).toFixed(1)}s` : `${Math.round(ms / 1e3)}s`;
|
|
7408
|
+
}
|
|
7409
|
+
function groupTook(g) {
|
|
7410
|
+
const slowest = g.steps.reduce(
|
|
7411
|
+
(worst, s) => Number(s.ms) > Number(worst.ms) ? s : worst,
|
|
7412
|
+
g.steps[0]
|
|
7413
|
+
);
|
|
7414
|
+
return took(slowest);
|
|
7415
|
+
}
|
|
7416
|
+
function result(step) {
|
|
7417
|
+
if (step.status === "running") return null;
|
|
7418
|
+
if (step.status === "error") return "unavailable";
|
|
7419
|
+
const n = Number(step.outcome);
|
|
7420
|
+
if (!Number.isFinite(n)) return null;
|
|
7421
|
+
const [one, many] = {
|
|
7422
|
+
graphs: ["collection", "collections"],
|
|
7423
|
+
search: ["result", "results"],
|
|
7424
|
+
count: ["document", "documents"],
|
|
7425
|
+
enumerate: ["match", "matches"],
|
|
7426
|
+
entities: ["entity", "entities"],
|
|
7427
|
+
explore: ["connection", "connections"],
|
|
7428
|
+
sets: ["set", "sets"]
|
|
7429
|
+
}[bare(step.tool)] ?? ["result", "results"];
|
|
7430
|
+
if (n === 0) return "nothing found";
|
|
7431
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
7432
|
+
}
|
|
7433
|
+
function group(steps) {
|
|
7434
|
+
const out = [];
|
|
7435
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
7436
|
+
for (const step of steps) {
|
|
7437
|
+
const label = action(step);
|
|
7438
|
+
const key = `${step.round ?? ""}\0${label}`;
|
|
7439
|
+
const existing = byKey.get(key);
|
|
7440
|
+
if (existing) {
|
|
7441
|
+
existing.steps.push(step);
|
|
7442
|
+
continue;
|
|
7443
|
+
}
|
|
7444
|
+
const g = { key: step.seq, label, round: step.round, steps: [step] };
|
|
7445
|
+
byKey.set(key, g);
|
|
7446
|
+
out.push(g);
|
|
7447
|
+
}
|
|
7448
|
+
return out;
|
|
7449
|
+
}
|
|
7450
|
+
function groupResult(g) {
|
|
7451
|
+
if (g.steps.length === 1) return result(g.steps[0]);
|
|
7452
|
+
const done = g.steps.filter((s) => s.status !== "running");
|
|
7453
|
+
if (!done.length) return null;
|
|
7454
|
+
const hits = done.filter((s) => Number(s.outcome) > 0).length;
|
|
7455
|
+
if (hits === 0) return "nothing found";
|
|
7456
|
+
return `found in ${hits} of ${done.length}`;
|
|
7457
|
+
}
|
|
7458
|
+
function roundCount(steps) {
|
|
7459
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7460
|
+
for (const s of steps) if (typeof s.round === "number") seen.add(s.round);
|
|
7461
|
+
return seen.size ? seen.size : null;
|
|
7462
|
+
}
|
|
7463
|
+
function AgentStepTrace({ steps, working }) {
|
|
7464
|
+
const t = useTheme();
|
|
7465
|
+
const failed = steps.some((s) => s.status === "error");
|
|
7466
|
+
const prominent = working || failed;
|
|
7467
|
+
const [open, setOpen] = useState(prominent);
|
|
7468
|
+
const [touched, setTouched] = useState(false);
|
|
7469
|
+
const [hover, setHover] = useState(false);
|
|
7470
|
+
useEffect(() => {
|
|
7471
|
+
if (!touched) setOpen(prominent);
|
|
7472
|
+
}, [prominent, touched]);
|
|
7473
|
+
if (!steps.length) return null;
|
|
7474
|
+
const groups = group(steps);
|
|
7475
|
+
const rounds = roundCount(steps);
|
|
7476
|
+
const n = rounds ?? groups.length;
|
|
7477
|
+
const count = `${n} ${rounds ? "round" : "step"}${n === 1 ? "" : "s"}`;
|
|
7478
|
+
const only = groups.length === 1 ? groups[0] : null;
|
|
7479
|
+
const summary = working ? `${action(steps[steps.length - 1])}\u2026` : failed ? `${count}, some unavailable` : only ? [
|
|
7480
|
+
only.label + (only.steps.length > 1 ? ` \xD7${only.steps.length}` : ""),
|
|
7481
|
+
groupResult(only)
|
|
7482
|
+
].filter(Boolean).join(" \u2014 ") : count;
|
|
7483
|
+
const toggle = /* @__PURE__ */ jsxs(
|
|
7484
|
+
"button",
|
|
7485
|
+
{
|
|
7486
|
+
type: "button",
|
|
7487
|
+
onClick: () => {
|
|
7488
|
+
setTouched(true);
|
|
7489
|
+
setOpen((o) => !o);
|
|
7490
|
+
},
|
|
7491
|
+
onMouseEnter: () => setHover(true),
|
|
7492
|
+
onMouseLeave: () => setHover(false),
|
|
7493
|
+
"aria-expanded": open,
|
|
7494
|
+
className: "flex w-full items-center gap-2 text-left text-xs",
|
|
7495
|
+
style: { color: failed ? t.error : hover ? t.text : t.textMuted },
|
|
7496
|
+
children: [
|
|
7497
|
+
working && /* @__PURE__ */ jsx(
|
|
7498
|
+
"span",
|
|
7499
|
+
{
|
|
7500
|
+
"aria-hidden": true,
|
|
7501
|
+
className: "inline-block h-1.5 w-1.5 shrink-0 rounded-full motion-safe:animate-pulse",
|
|
7502
|
+
style: { backgroundColor: t.primary }
|
|
7503
|
+
}
|
|
7504
|
+
),
|
|
7505
|
+
/* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate", children: summary }),
|
|
7506
|
+
!(only && !working && !failed) && /* @__PURE__ */ jsx("span", { "aria-hidden": true, className: "shrink-0", children: open ? "\u2212" : "+" })
|
|
7507
|
+
]
|
|
7508
|
+
}
|
|
7509
|
+
);
|
|
7510
|
+
const rows = /* @__PURE__ */ jsx("ol", { className: "mt-2 space-y-1", children: groups.map((g, i) => {
|
|
7511
|
+
const res = groupResult(g);
|
|
7512
|
+
const slow = groupTook(g);
|
|
7513
|
+
const anyError = g.steps.some((s) => s.status === "error");
|
|
7514
|
+
const running = g.steps.some((s) => s.status === "running");
|
|
7515
|
+
const startsRound = g.round !== void 0 && g.round !== groups[i - 1]?.round;
|
|
7516
|
+
return /* @__PURE__ */ jsxs("li", { className: "flex items-baseline gap-2 text-xs", children: [
|
|
7517
|
+
rounds !== null && /* @__PURE__ */ jsx(
|
|
7518
|
+
"span",
|
|
7519
|
+
{
|
|
7520
|
+
className: "w-3 shrink-0 text-right tabular-nums",
|
|
7521
|
+
style: { color: t.textMuted },
|
|
7522
|
+
"aria-hidden": !startsRound,
|
|
7523
|
+
children: startsRound ? g.round : ""
|
|
7524
|
+
}
|
|
7525
|
+
),
|
|
7526
|
+
/* @__PURE__ */ jsx(
|
|
7527
|
+
"span",
|
|
7528
|
+
{
|
|
7529
|
+
"aria-hidden": true,
|
|
7530
|
+
className: "w-3 shrink-0 text-[10px]",
|
|
7531
|
+
style: { color: anyError ? t.error : t.textMuted },
|
|
7532
|
+
children: running ? "\xB7" : anyError ? "!" : "\u2713"
|
|
7533
|
+
}
|
|
7534
|
+
),
|
|
7535
|
+
/* @__PURE__ */ jsxs(
|
|
7536
|
+
"span",
|
|
7537
|
+
{
|
|
7538
|
+
className: "min-w-0 flex-1 truncate",
|
|
7539
|
+
style: { color: t.textSecondary },
|
|
7540
|
+
title: g.label,
|
|
7541
|
+
children: [
|
|
7542
|
+
g.label,
|
|
7543
|
+
g.steps.length > 1 && /* @__PURE__ */ jsxs("span", { style: { color: t.textMuted }, children: [
|
|
7544
|
+
" \xD7",
|
|
7545
|
+
g.steps.length
|
|
7546
|
+
] })
|
|
7547
|
+
]
|
|
7548
|
+
}
|
|
7549
|
+
),
|
|
7550
|
+
slow && /* @__PURE__ */ jsx(
|
|
7551
|
+
"span",
|
|
7552
|
+
{
|
|
7553
|
+
className: "shrink-0 tabular-nums",
|
|
7554
|
+
style: { color: t.textMuted },
|
|
7555
|
+
children: slow
|
|
7556
|
+
}
|
|
7557
|
+
),
|
|
7558
|
+
res && /* @__PURE__ */ jsx("span", { className: "shrink-0", style: { color: anyError ? t.error : t.textMuted }, children: res })
|
|
7559
|
+
] }, g.key);
|
|
7560
|
+
}) });
|
|
7561
|
+
if (!prominent) {
|
|
7562
|
+
return /* @__PURE__ */ jsxs("div", { className: "mt-2", children: [
|
|
7563
|
+
toggle,
|
|
7564
|
+
open && !only && rows
|
|
7565
|
+
] });
|
|
7566
|
+
}
|
|
7567
|
+
return /* @__PURE__ */ jsxs(
|
|
7568
|
+
"div",
|
|
7569
|
+
{
|
|
7570
|
+
className: "mt-2 rounded-lg p-3",
|
|
7571
|
+
style: { backgroundColor: t.bgRaisedAlt, border: `1px solid ${t.border}` },
|
|
7572
|
+
children: [
|
|
7573
|
+
toggle,
|
|
7574
|
+
open && rows
|
|
7575
|
+
]
|
|
7576
|
+
}
|
|
7577
|
+
);
|
|
7578
|
+
}
|
|
7579
|
+
function agentStepTraceExtra(entry) {
|
|
7580
|
+
const meta = entry.metadata;
|
|
7581
|
+
const steps = meta?.agentSteps;
|
|
7582
|
+
if (!steps?.length) return null;
|
|
7583
|
+
const working = meta?.agentStepsLive ?? entry.content.endsWith("\u258B");
|
|
7584
|
+
return /* @__PURE__ */ jsx(AgentStepTrace, { steps, working });
|
|
7585
|
+
}
|
|
7007
7586
|
|
|
7008
7587
|
// src/knowledge/graphTheme.ts
|
|
7009
7588
|
var NODE_TYPE_COLORS = {
|
|
@@ -7479,7 +8058,7 @@ var MarkdownContent = memo(function MarkdownContent2({
|
|
|
7479
8058
|
if (!entities || entities.length === 0) return MARKDOWN_COMPONENTS;
|
|
7480
8059
|
return { ...MARKDOWN_COMPONENTS, ...buildHighlightOverrides(entities, onEntityClick) };
|
|
7481
8060
|
}, [entities, onEntityClick]);
|
|
7482
|
-
return /* @__PURE__ */ jsx("div", { className: `text-xs leading-relaxed text-gray-300 break-words ${className}`, children: /* @__PURE__ */ jsx(ReactMarkdown, { components, children }) });
|
|
8061
|
+
return /* @__PURE__ */ jsx("div", { className: `text-xs leading-relaxed text-gray-300 break-words ${className}`, children: /* @__PURE__ */ jsx(ReactMarkdown, { remarkPlugins: [remarkGfm], components, children }) });
|
|
7483
8062
|
});
|
|
7484
8063
|
function escapeRegex(s) {
|
|
7485
8064
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -7545,13 +8124,13 @@ function highlightText(text, regex, entityMap, onEntityClick) {
|
|
|
7545
8124
|
return parts;
|
|
7546
8125
|
}
|
|
7547
8126
|
function highlightChildren(children, regex, entityMap, onEntityClick) {
|
|
7548
|
-
return
|
|
8127
|
+
return React15.Children.map(children, (child) => {
|
|
7549
8128
|
if (typeof child === "string") {
|
|
7550
8129
|
const highlighted = highlightText(child, regex, entityMap, onEntityClick);
|
|
7551
8130
|
return highlighted.length === 1 && typeof highlighted[0] === "string" ? child : /* @__PURE__ */ jsx(Fragment, { children: highlighted });
|
|
7552
8131
|
}
|
|
7553
|
-
if (
|
|
7554
|
-
return
|
|
8132
|
+
if (React15.isValidElement(child) && child.props.children) {
|
|
8133
|
+
return React15.cloneElement(child, {
|
|
7555
8134
|
...child.props,
|
|
7556
8135
|
children: highlightChildren(child.props.children, regex, entityMap, onEntityClick)
|
|
7557
8136
|
});
|
|
@@ -8022,10 +8601,10 @@ var SAVE_STAGE_MESSAGES = {
|
|
|
8022
8601
|
extracting: "re-analyzing entities with AI\u2026",
|
|
8023
8602
|
finishing: "almost done \xB7 finalizing graph\u2026"
|
|
8024
8603
|
};
|
|
8025
|
-
function summarizeSaveResult(
|
|
8026
|
-
if (!
|
|
8027
|
-
const added =
|
|
8028
|
-
const removed =
|
|
8604
|
+
function summarizeSaveResult(result2) {
|
|
8605
|
+
if (!result2?.diff) return "Saved";
|
|
8606
|
+
const added = result2.diff.added_node_keys?.length ?? 0;
|
|
8607
|
+
const removed = result2.diff.removed_node_keys?.length ?? 0;
|
|
8029
8608
|
if (added === 0 && removed === 0) return "Saved \xB7 graph unchanged";
|
|
8030
8609
|
const parts = [];
|
|
8031
8610
|
if (added > 0) parts.push(`+${added}`);
|
|
@@ -8104,11 +8683,11 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8104
8683
|
setIsSaving(true);
|
|
8105
8684
|
try {
|
|
8106
8685
|
const rawResult = await onSaveDescription(draftAtSaveTime);
|
|
8107
|
-
const
|
|
8686
|
+
const result2 = rawResult ?? null;
|
|
8108
8687
|
if (currentNodeIdRef.current === savingForNodeId) {
|
|
8109
8688
|
setLocalDescription(draftAtSaveTime);
|
|
8110
8689
|
setIsEditing(false);
|
|
8111
|
-
setLastSaveResult(
|
|
8690
|
+
setLastSaveResult(result2);
|
|
8112
8691
|
if (savedPillTimerRef.current) clearTimeout(savedPillTimerRef.current);
|
|
8113
8692
|
savedPillTimerRef.current = setTimeout(() => {
|
|
8114
8693
|
setLastSaveResult(null);
|
|
@@ -8644,11 +9223,11 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8644
9223
|
renderedClaims.length,
|
|
8645
9224
|
")"
|
|
8646
9225
|
] }),
|
|
8647
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: claimGroups.map((
|
|
8648
|
-
const isRelated =
|
|
9226
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-2", children: claimGroups.map((group2) => {
|
|
9227
|
+
const isRelated = group2.predicate === "(related)";
|
|
8649
9228
|
return /* @__PURE__ */ jsxs("div", { children: [
|
|
8650
|
-
|
|
8651
|
-
/* @__PURE__ */ jsx("div", { className: "space-y-0.5", children:
|
|
9229
|
+
group2.items.length > 1 && /* @__PURE__ */ jsx("div", { className: "text-[10px] text-gray-500 italic mb-0.5 px-2", children: group2.predicate }),
|
|
9230
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-0.5", children: group2.items.map((claim) => {
|
|
8652
9231
|
const cnColors = getNodeColors(claim.targetType);
|
|
8653
9232
|
return /* @__PURE__ */ jsxs(
|
|
8654
9233
|
"button",
|
|
@@ -8686,7 +9265,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8686
9265
|
claim.key
|
|
8687
9266
|
);
|
|
8688
9267
|
}) })
|
|
8689
|
-
] },
|
|
9268
|
+
] }, group2.predicate);
|
|
8690
9269
|
}) })
|
|
8691
9270
|
] }),
|
|
8692
9271
|
Object.keys(visibleProperties).length > 0 && /* @__PURE__ */ jsxs("div", { children: [
|
|
@@ -9301,7 +9880,7 @@ var RECRUITING_LINES = [
|
|
|
9301
9880
|
];
|
|
9302
9881
|
function RecruitingHint() {
|
|
9303
9882
|
const [idx, setIdx] = useState(0);
|
|
9304
|
-
|
|
9883
|
+
React15.useEffect(() => {
|
|
9305
9884
|
const t = setInterval(() => setIdx((i) => (i + 1) % RECRUITING_LINES.length), 2500);
|
|
9306
9885
|
return () => clearInterval(t);
|
|
9307
9886
|
}, []);
|
|
@@ -9404,7 +9983,7 @@ function RelationshipSentence({ rel }) {
|
|
|
9404
9983
|
const hasRange = rel.range.length > 0;
|
|
9405
9984
|
return /* @__PURE__ */ jsxs("div", { style: { lineHeight: 2, color: "#888", fontSize: 13, wordBreak: "break-word" }, children: [
|
|
9406
9985
|
hasDomain && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9407
|
-
rel.domain.map((d, i) => /* @__PURE__ */ jsxs(
|
|
9986
|
+
rel.domain.map((d, i) => /* @__PURE__ */ jsxs(React15.Fragment, { children: [
|
|
9408
9987
|
i > 0 && /* @__PURE__ */ jsx("span", { style: { color: "#666" }, children: " or " }),
|
|
9409
9988
|
/* @__PURE__ */ jsx(TypeChip, { name: d })
|
|
9410
9989
|
] }, d)),
|
|
@@ -9413,7 +9992,7 @@ function RelationshipSentence({ rel }) {
|
|
|
9413
9992
|
/* @__PURE__ */ jsx("span", { style: { color: "#ddd", fontStyle: "italic", fontWeight: 500 }, children: verb }),
|
|
9414
9993
|
hasRange && /* @__PURE__ */ jsxs(Fragment, { children: [
|
|
9415
9994
|
" ",
|
|
9416
|
-
rel.range.map((r, i) => /* @__PURE__ */ jsxs(
|
|
9995
|
+
rel.range.map((r, i) => /* @__PURE__ */ jsxs(React15.Fragment, { children: [
|
|
9417
9996
|
i > 0 && /* @__PURE__ */ jsx("span", { style: { color: "#666" }, children: " and " }),
|
|
9418
9997
|
/* @__PURE__ */ jsx(TypeChip, { name: r })
|
|
9419
9998
|
] }, r))
|
|
@@ -9933,7 +10512,7 @@ function DocumentProcessingProgress() {
|
|
|
9933
10512
|
if (!state) return null;
|
|
9934
10513
|
const currentIdx = DOCUMENT_PIPELINE_STEPS.findIndex((s) => s.key === state.step);
|
|
9935
10514
|
return /* @__PURE__ */ jsxs("div", { className: "px-3 py-1.5 flex flex-col gap-1", style: { borderBottom: "1px solid #282828", backgroundColor: "#1a1a1a" }, children: [
|
|
9936
|
-
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-0", children: DOCUMENT_PIPELINE_STEPS.map((step, i) => /* @__PURE__ */ jsxs(
|
|
10515
|
+
/* @__PURE__ */ jsx("div", { className: "flex items-center gap-0", children: DOCUMENT_PIPELINE_STEPS.map((step, i) => /* @__PURE__ */ jsxs(React15.Fragment, { children: [
|
|
9937
10516
|
i > 0 && /* @__PURE__ */ jsx("div", { className: "w-2 h-px mx-0.5", style: { backgroundColor: i <= currentIdx ? "#10b981" : "#333" } }),
|
|
9938
10517
|
/* @__PURE__ */ jsx(
|
|
9939
10518
|
"span",
|
|
@@ -10217,10 +10796,10 @@ function hydrateAgentIds(ids) {
|
|
|
10217
10796
|
};
|
|
10218
10797
|
});
|
|
10219
10798
|
}
|
|
10220
|
-
function stageReducer(state,
|
|
10221
|
-
switch (
|
|
10799
|
+
function stageReducer(state, action2) {
|
|
10800
|
+
switch (action2.type) {
|
|
10222
10801
|
case "TEAM_SETUP": {
|
|
10223
|
-
const incomingIds = new Set(
|
|
10802
|
+
const incomingIds = new Set(action2.agents.map((a) => a.id));
|
|
10224
10803
|
let isWholesaleReplace = state.lastBackendTeamIds.size > 0;
|
|
10225
10804
|
if (isWholesaleReplace) {
|
|
10226
10805
|
state.lastBackendTeamIds.forEach((id) => {
|
|
@@ -10238,48 +10817,48 @@ function stageReducer(state, action) {
|
|
|
10238
10817
|
return {
|
|
10239
10818
|
...state,
|
|
10240
10819
|
stage: "team_formation",
|
|
10241
|
-
team: [...
|
|
10820
|
+
team: [...action2.agents, ...surviving],
|
|
10242
10821
|
localOnlyAgentIds: nextLocalOnly,
|
|
10243
10822
|
lastBackendTeamIds: incomingIds
|
|
10244
10823
|
};
|
|
10245
10824
|
}
|
|
10246
10825
|
case "PHASE_ADVANCED": {
|
|
10247
|
-
const to =
|
|
10826
|
+
const to = action2.to;
|
|
10248
10827
|
if (to === "team_formation") return { ...state, stage: "team_formation" };
|
|
10249
10828
|
if (to === "schema_seeding") return { ...state, stage: "schema_seeding" };
|
|
10250
10829
|
if (to === "construction" || to === "synthesis" || to === "done") return { ...state, stage: "graph" };
|
|
10251
10830
|
return state;
|
|
10252
10831
|
}
|
|
10253
10832
|
case "UPDATE_AGENT":
|
|
10254
|
-
return { ...state, team: state.team.map((a) => a.id ===
|
|
10833
|
+
return { ...state, team: state.team.map((a) => a.id === action2.id ? { ...a, ...action2.updates } : a) };
|
|
10255
10834
|
case "REMOVE_AGENT": {
|
|
10256
10835
|
const nextLocalOnly = new Set(state.localOnlyAgentIds);
|
|
10257
|
-
nextLocalOnly.delete(
|
|
10836
|
+
nextLocalOnly.delete(action2.id);
|
|
10258
10837
|
return {
|
|
10259
10838
|
...state,
|
|
10260
|
-
team: state.team.filter((a) => a.id !==
|
|
10839
|
+
team: state.team.filter((a) => a.id !== action2.id),
|
|
10261
10840
|
localOnlyAgentIds: nextLocalOnly
|
|
10262
10841
|
};
|
|
10263
10842
|
}
|
|
10264
10843
|
case "ADD_AGENT": {
|
|
10265
10844
|
const nextLocalOnly = new Set(state.localOnlyAgentIds);
|
|
10266
|
-
nextLocalOnly.add(
|
|
10845
|
+
nextLocalOnly.add(action2.agent.id);
|
|
10267
10846
|
return {
|
|
10268
10847
|
...state,
|
|
10269
|
-
team: [...state.team,
|
|
10848
|
+
team: [...state.team, action2.agent],
|
|
10270
10849
|
localOnlyAgentIds: nextLocalOnly
|
|
10271
10850
|
};
|
|
10272
10851
|
}
|
|
10273
10852
|
case "SCHEMA_SEEDED":
|
|
10274
|
-
return { ...state, schemaNodeTypeCount:
|
|
10853
|
+
return { ...state, schemaNodeTypeCount: action2.nodeTypeCount, schemaEdgeTypeCount: action2.edgeTypeCount };
|
|
10275
10854
|
case "SCHEMA_TYPE_ADDED":
|
|
10276
|
-
return { ...state, schemaNodeTypes: state.schemaNodeTypes.includes(
|
|
10855
|
+
return { ...state, schemaNodeTypes: state.schemaNodeTypes.includes(action2.typeName) ? state.schemaNodeTypes : [...state.schemaNodeTypes, action2.typeName] };
|
|
10277
10856
|
case "SCHEMA_TEXT": {
|
|
10278
10857
|
const rels = [];
|
|
10279
10858
|
const nodeTypes2 = new Set(state.schemaNodeTypes);
|
|
10280
10859
|
const relPattern = /(\w+)\s*:\s*\[([^\]]*)\]\s*→\s*\[([^\]]*)\]/g;
|
|
10281
10860
|
let m;
|
|
10282
|
-
while ((m = relPattern.exec(
|
|
10861
|
+
while ((m = relPattern.exec(action2.text)) !== null) {
|
|
10283
10862
|
const name = m[1];
|
|
10284
10863
|
const domain = m[2].split(",").map((s) => s.replace(/"/g, "").trim()).filter(Boolean);
|
|
10285
10864
|
const range = m[3].split(",").map((s) => s.replace(/"/g, "").trim()).filter(Boolean);
|
|
@@ -10294,7 +10873,7 @@ function stageReducer(state, action) {
|
|
|
10294
10873
|
};
|
|
10295
10874
|
}
|
|
10296
10875
|
case "DOC_STEP": {
|
|
10297
|
-
const step =
|
|
10876
|
+
const step = action2.step;
|
|
10298
10877
|
if (step === "complete") return { ...state, stage: "graph" };
|
|
10299
10878
|
if (step === "processing" || step === "vocabulary") return { ...state, stage: "doc_preparing" };
|
|
10300
10879
|
if (step === "extracting") return { ...state, stage: "doc_extracting" };
|
|
@@ -10303,7 +10882,7 @@ function stageReducer(state, action) {
|
|
|
10303
10882
|
return state;
|
|
10304
10883
|
}
|
|
10305
10884
|
case "DOC_ACTIVITY":
|
|
10306
|
-
return { ...state, docActivity: [...state.docActivity,
|
|
10885
|
+
return { ...state, docActivity: [...state.docActivity, action2.item] };
|
|
10307
10886
|
case "FORCE_GRAPH":
|
|
10308
10887
|
return { ...state, stage: "graph" };
|
|
10309
10888
|
default:
|
|
@@ -11169,7 +11748,7 @@ function PipelineProgressBar({ listenForEvents = true, currentPhase: currentPhas
|
|
|
11169
11748
|
PIPELINE_STEPS.map((step, i) => {
|
|
11170
11749
|
const isCompleted = completed.has(step.key) || i < currentIdx;
|
|
11171
11750
|
const isCurrent = step.key === currentPhase;
|
|
11172
|
-
return /* @__PURE__ */ jsxs(
|
|
11751
|
+
return /* @__PURE__ */ jsxs(React15.Fragment, { children: [
|
|
11173
11752
|
i > 0 && /* @__PURE__ */ jsx(
|
|
11174
11753
|
"div",
|
|
11175
11754
|
{
|
|
@@ -12957,19 +13536,19 @@ function KnowledgeGraphView({
|
|
|
12957
13536
|
setSearching(true);
|
|
12958
13537
|
searchTimerRef.current = setTimeout(async () => {
|
|
12959
13538
|
try {
|
|
12960
|
-
const
|
|
12961
|
-
setSearchResult(
|
|
12962
|
-
if (
|
|
13539
|
+
const result2 = data.onSearchNodes ? await data.onSearchNodes(groupId, kgId, q, 10, 2) : { hits: [], traversal: [] };
|
|
13540
|
+
setSearchResult(result2);
|
|
13541
|
+
if (result2.hits.length === 0 && localMatchIds.size === 0) {
|
|
12963
13542
|
restoreFullGraph();
|
|
12964
13543
|
setSearching(false);
|
|
12965
13544
|
return;
|
|
12966
13545
|
}
|
|
12967
|
-
if (
|
|
13546
|
+
if (result2.hits.length === 0) {
|
|
12968
13547
|
setSearching(false);
|
|
12969
13548
|
return;
|
|
12970
13549
|
}
|
|
12971
13550
|
const scoreMap = /* @__PURE__ */ new Map();
|
|
12972
|
-
|
|
13551
|
+
result2.hits.forEach((h) => {
|
|
12973
13552
|
const existing = scoreMap.get(h.node_key) ?? 0;
|
|
12974
13553
|
if ((h.score ?? 0) > existing) scoreMap.set(h.node_key, h.score ?? 0);
|
|
12975
13554
|
});
|
|
@@ -12977,9 +13556,9 @@ function KnowledgeGraphView({
|
|
|
12977
13556
|
if (!scoreMap.has(id)) scoreMap.set(id, 0.5);
|
|
12978
13557
|
});
|
|
12979
13558
|
const traversalIds = /* @__PURE__ */ new Set();
|
|
12980
|
-
|
|
13559
|
+
result2.traversal.forEach((t) => traversalIds.add(t.node_key));
|
|
12981
13560
|
const neighborIds = /* @__PURE__ */ new Set();
|
|
12982
|
-
|
|
13561
|
+
result2.hits.forEach((h) => {
|
|
12983
13562
|
h.neighbors?.forEach((nk) => {
|
|
12984
13563
|
if (!scoreMap.has(nk)) neighborIds.add(nk);
|
|
12985
13564
|
});
|
|
@@ -13468,9 +14047,9 @@ function KnowledgeGraphView({
|
|
|
13468
14047
|
if (!data.onCreateNote || !draftNote || !draftNote.trim()) return;
|
|
13469
14048
|
setSavingDraft(true);
|
|
13470
14049
|
try {
|
|
13471
|
-
const
|
|
14050
|
+
const result2 = await data.onCreateNote(groupId, kgId, draftNote);
|
|
13472
14051
|
setDraftNote(null);
|
|
13473
|
-
setSelectedNodeId(`chunk:${
|
|
14052
|
+
setSelectedNodeId(`chunk:${result2.chunk_id}`);
|
|
13474
14053
|
if (data.onLoadAllChunks) {
|
|
13475
14054
|
try {
|
|
13476
14055
|
const fresh = await data.onLoadAllChunks(groupId, kgId);
|
|
@@ -13479,10 +14058,10 @@ function KnowledgeGraphView({
|
|
|
13479
14058
|
console.warn("[KGV] post-create chunk refetch failed", err);
|
|
13480
14059
|
}
|
|
13481
14060
|
}
|
|
13482
|
-
if (
|
|
14061
|
+
if (result2.run_id && config?.agentsApiUrl) {
|
|
13483
14062
|
setNoteRuns((prev) => [
|
|
13484
14063
|
...prev,
|
|
13485
|
-
{ run_id:
|
|
14064
|
+
{ run_id: result2.run_id, kg_id: kgId }
|
|
13486
14065
|
]);
|
|
13487
14066
|
}
|
|
13488
14067
|
} catch (err) {
|
|
@@ -14037,4 +14616,4 @@ var terminalClassNames = {
|
|
|
14037
14616
|
promptSymbol: "terminal-prompt-symbol"
|
|
14038
14617
|
};
|
|
14039
14618
|
|
|
14040
|
-
export { ADVANCE_PHASE_SIGNAL, AGENT_PALETTE, AgentAvatar, AgentPresenceBar, AnnotationThread, CLAIM_STATUS_COLORS, ChatTerminal, CheckpointCard, ClaimNode, ConstructionProgress, CoreTerminal, DOCUMENT_PIPELINE_STEPS, DocumentProcessingProgress, EDGE_TYPE_COLORS, EdgeDetailDrawer, EdgeMarkerDefs, CoreTerminal as EmbeddedTerminal, ExpandableTerminal, GraphChatPanel, GraphEdge, GraphNode, InlineTerminal, KnowledgeGraphView, LIVE_KG_ID, LiveActivityTicker, MarkdownContent, MarkdownEditor, NODE_TYPE_COLORS, NODE_TYPE_LABELS, NodeDetailDrawer, PROGRESS_EVENT_NAME, PipelineProgressBar, ReasoningHistoryCard, ReasoningOverlay, ReasoningView, SYNTHESIS_DONE_SIGNAL, ScopedReasoningProvider, SettlementBar, SlashMentionPicker, StageCanvas, StandardTerminal, TerminalInputBar, TerminalThemeProvider, agentSeed, avatarColor, blueScope, buildClaimsGraph, buildTerminalCommand, buttonShadow, captureReasoningSnapshot, defaultTheme, dispatchProgressEvent, documentEventToActivity, emeraldCollab, emeraldRevised, eventToActivity, extractKGSources, extractKgId, filterCommands, formatAssetDisplay, formatPaymentAmount, formatTokenAssetId, getAgentColor, getBuiltInCommands, getClaimStatusColors, getEdgeColor, getEdgeTypeLabel, getNodeColors, getNodeTypeLabel, getVocabTypeColors, getVocabTypeLabel, greenAction, handleSSEStream, handleStreamingResponse, hostApp, initials, isFixedKgId, isNaturalLanguage, layoutGraph, mergeTheme, openPipelineEventStream, orangeRebuttal, parseTerminalCommand, pipelineBg, processStreamLines, purple, reduceProgress, renderMarkdownBlock, resolvePaymentAssetDisplay, snapshotToSubgraph, terminalClassNames, terminalColors, useScopedProgressEvent, useSlashMentionPicker, useTheme, warmBg };
|
|
14619
|
+
export { ADVANCE_PHASE_SIGNAL, AGENT_PALETTE, AgentAvatar, AgentPresenceBar, AgentStepTrace, AnnotationThread, CLAIM_STATUS_COLORS, ChatTerminal, CheckpointCard, ClaimNode, ConstructionProgress, CoreTerminal, DEFAULT_AGENT_LABEL, DOCUMENT_PIPELINE_STEPS, DocumentProcessingProgress, EDGE_TYPE_COLORS, EdgeDetailDrawer, EdgeMarkerDefs, CoreTerminal as EmbeddedTerminal, ExpandableTerminal, GraphChatPanel, GraphEdge, GraphNode, InlineTerminal, KnowledgeGraphView, LIVE_KG_ID, LiveActivityTicker, MarkdownContent, MarkdownEditor, NODE_TYPE_COLORS, NODE_TYPE_LABELS, NodeDetailDrawer, PROGRESS_EVENT_NAME, PipelineProgressBar, ReasoningHistoryCard, ReasoningOverlay, ReasoningView, SSE_KEEPALIVE_MS, SSE_STALL_MS, SYNTHESIS_DONE_SIGNAL, ScopedReasoningProvider, SettlementBar, SlashMentionPicker, StageCanvas, StandardTerminal, TerminalInputBar, TerminalThemeProvider, agentSeed, agentStepTraceExtra, avatarColor, blueScope, buildClaimsGraph, buildTerminalCommand, buttonShadow, captureReasoningSnapshot, defaultTheme, dispatchProgressEvent, documentEventToActivity, emeraldCollab, emeraldRevised, eventToActivity, extractKGSources, extractKgId, filterCommands, formatAssetDisplay, formatPaymentAmount, formatTokenAssetId, getAgentColor, getBuiltInCommands, getClaimStatusColors, getEdgeColor, getEdgeTypeLabel, getNodeColors, getNodeTypeLabel, getVocabTypeColors, getVocabTypeLabel, greenAction, handleSSEStream, handleStreamingResponse, hostApp, initials, isFixedKgId, isNaturalLanguage, layoutGraph, mergeTheme, openPipelineEventStream, orangeRebuttal, parseTerminalCommand, pipelineBg, processStreamLines, purple, reduceProgress, renderMarkdownBlock, resolvePaymentAssetDisplay, snapshotToSubgraph, terminalClassNames, terminalColors, useScopedProgressEvent, useSlashMentionPicker, useTheme, warmBg, withStallTimeout };
|