@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.cjs
CHANGED
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
"use client";
|
|
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
|
+
*/
|
|
2
8
|
'use strict';
|
|
3
9
|
|
|
4
|
-
var
|
|
10
|
+
var React15 = require('react');
|
|
5
11
|
var lucideReact = require('lucide-react');
|
|
6
12
|
var jsxRuntime = require('react/jsx-runtime');
|
|
7
13
|
var ReactMarkdown = require('react-markdown');
|
|
14
|
+
var remarkGfm = require('remark-gfm');
|
|
8
15
|
var core = require('@dicebear/core');
|
|
9
16
|
var collection = require('@dicebear/collection');
|
|
10
17
|
var framerMotion = require('framer-motion');
|
|
@@ -16,8 +23,9 @@ var dagre = require('dagre');
|
|
|
16
23
|
|
|
17
24
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
18
25
|
|
|
19
|
-
var
|
|
26
|
+
var React15__default = /*#__PURE__*/_interopDefault(React15);
|
|
20
27
|
var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
|
|
28
|
+
var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
|
|
21
29
|
var dagre__default = /*#__PURE__*/_interopDefault(dagre);
|
|
22
30
|
|
|
23
31
|
// src/core/StandardTerminal.tsx
|
|
@@ -76,6 +84,7 @@ var BUILT_IN_COMMANDS = [
|
|
|
76
84
|
{ id: "files", label: "/files", description: "List uploaded files for this page working group", category: "built-in" },
|
|
77
85
|
{ id: "ask", label: "/ask", description: "Ask the AI assistant for analysis (streaming)", category: "built-in" },
|
|
78
86
|
{ id: "note", label: "/note", description: "Save a free-form note in this workspace. Type @name to link an entity.", category: "built-in" },
|
|
87
|
+
{ id: "log", label: "/log", description: "Capture what you did or decided as a work item on this workspace\u2019s board.", category: "built-in" },
|
|
79
88
|
{ 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" }
|
|
80
89
|
];
|
|
81
90
|
function getBuiltInCommands() {
|
|
@@ -97,23 +106,45 @@ function processStreamLines(buffer, onJsonLine) {
|
|
|
97
106
|
for (const line of lines) {
|
|
98
107
|
const trimmed = line.trim();
|
|
99
108
|
if (!trimmed) continue;
|
|
100
|
-
if (trimmed.startsWith("data:
|
|
101
|
-
const jsonStr = trimmed.substring(
|
|
109
|
+
if (trimmed.startsWith("data:")) {
|
|
110
|
+
const jsonStr = trimmed.substring(5).trimStart();
|
|
111
|
+
let parsed2;
|
|
102
112
|
try {
|
|
103
|
-
|
|
113
|
+
parsed2 = JSON.parse(jsonStr);
|
|
104
114
|
} catch {
|
|
115
|
+
continue;
|
|
105
116
|
}
|
|
117
|
+
onJsonLine(parsed2);
|
|
106
118
|
continue;
|
|
107
119
|
}
|
|
108
120
|
if (trimmed.startsWith(":")) continue;
|
|
121
|
+
let parsed;
|
|
109
122
|
try {
|
|
110
|
-
|
|
123
|
+
parsed = JSON.parse(trimmed);
|
|
111
124
|
} catch {
|
|
125
|
+
continue;
|
|
112
126
|
}
|
|
127
|
+
onJsonLine(parsed);
|
|
113
128
|
}
|
|
114
129
|
return remainder;
|
|
115
130
|
}
|
|
116
131
|
|
|
132
|
+
// src/utils/streamStall.ts
|
|
133
|
+
var SSE_KEEPALIVE_MS = 15e3;
|
|
134
|
+
var SSE_STALL_MS = SSE_KEEPALIVE_MS * 3;
|
|
135
|
+
async function withStallTimeout(work, ms = SSE_STALL_MS, sleep = (d) => new Promise((wake) => setTimeout(wake, d))) {
|
|
136
|
+
let done = false;
|
|
137
|
+
const settled = work.then((value) => {
|
|
138
|
+
done = true;
|
|
139
|
+
return value;
|
|
140
|
+
});
|
|
141
|
+
const stalled = sleep(ms).then(() => {
|
|
142
|
+
if (!done) throw new Error("the connection went quiet");
|
|
143
|
+
return void 0;
|
|
144
|
+
});
|
|
145
|
+
return Promise.race([settled, stalled]);
|
|
146
|
+
}
|
|
147
|
+
|
|
117
148
|
// src/utils/streamingHandler.ts
|
|
118
149
|
async function handleStreamingResponse(url, requestBody, onChunk, onComplete, onError) {
|
|
119
150
|
try {
|
|
@@ -155,6 +186,14 @@ async function handleStreamingResponse(url, requestBody, onChunk, onComplete, on
|
|
|
155
186
|
var handleSSEStream = async (url, body, onChunk, onComplete, onError, options) => {
|
|
156
187
|
const signal = options?.signal;
|
|
157
188
|
const method = options?.method || "POST";
|
|
189
|
+
const stallMs = options?.stallMs ?? SSE_STALL_MS;
|
|
190
|
+
const stallAbort = new AbortController();
|
|
191
|
+
const abortFromCaller = () => stallAbort.abort();
|
|
192
|
+
let reader;
|
|
193
|
+
if (signal) {
|
|
194
|
+
if (signal.aborted) stallAbort.abort();
|
|
195
|
+
else signal.addEventListener("abort", abortFromCaller, { once: true });
|
|
196
|
+
}
|
|
158
197
|
try {
|
|
159
198
|
const requestHeaders = {
|
|
160
199
|
Accept: "text/event-stream",
|
|
@@ -167,7 +206,7 @@ var handleSSEStream = async (url, body, onChunk, onComplete, onError, options) =
|
|
|
167
206
|
headers: requestHeaders,
|
|
168
207
|
body: method === "GET" || method === "HEAD" ? void 0 : JSON.stringify(body),
|
|
169
208
|
cache: "no-store",
|
|
170
|
-
signal
|
|
209
|
+
signal: stallAbort.signal
|
|
171
210
|
});
|
|
172
211
|
if (response.status === 410 && options?.onGone) {
|
|
173
212
|
options.onGone(await response.text());
|
|
@@ -177,19 +216,32 @@ var handleSSEStream = async (url, body, onChunk, onComplete, onError, options) =
|
|
|
177
216
|
const errorText = await response.text();
|
|
178
217
|
throw new Error(`HTTP ${response.status}: ${errorText}`);
|
|
179
218
|
}
|
|
180
|
-
|
|
219
|
+
reader = response.body?.getReader();
|
|
181
220
|
if (!reader) {
|
|
182
221
|
throw new Error("No response body reader available");
|
|
183
222
|
}
|
|
184
223
|
const decoder = new TextDecoder();
|
|
185
224
|
let buffer = "";
|
|
186
225
|
let receivedData = false;
|
|
226
|
+
let finalSeen = false;
|
|
227
|
+
let failed = false;
|
|
228
|
+
const dispatch = (chunk) => {
|
|
229
|
+
if (failed) return;
|
|
230
|
+
if (chunk.error) {
|
|
231
|
+
failed = true;
|
|
232
|
+
onError(typeof chunk.error === "string" ? chunk.error : "The assistant could not finish this answer.");
|
|
233
|
+
return;
|
|
234
|
+
}
|
|
235
|
+
if (chunk.is_final === true) finalSeen = true;
|
|
236
|
+
onChunk(chunk);
|
|
237
|
+
};
|
|
187
238
|
while (true) {
|
|
188
239
|
let readResult;
|
|
189
240
|
try {
|
|
190
|
-
readResult = await reader.read();
|
|
241
|
+
readResult = stallMs > 0 ? await withStallTimeout(reader.read(), stallMs) : await reader.read();
|
|
191
242
|
} catch (readError) {
|
|
192
243
|
if (signal?.aborted) return;
|
|
244
|
+
stallAbort.abort();
|
|
193
245
|
console.warn(
|
|
194
246
|
"SSE reader error (connection may have been interrupted):",
|
|
195
247
|
readError.message
|
|
@@ -203,16 +255,31 @@ var handleSSEStream = async (url, body, onChunk, onComplete, onError, options) =
|
|
|
203
255
|
}
|
|
204
256
|
const { done, value } = readResult;
|
|
205
257
|
if (done) {
|
|
206
|
-
|
|
258
|
+
buffer += decoder.decode();
|
|
259
|
+
if (buffer.trim()) processStreamLines(buffer + "\n", dispatch);
|
|
260
|
+
if (failed) return;
|
|
261
|
+
if ((options?.requireFinal ?? true) && !finalSeen) {
|
|
262
|
+
onError("Connection interrupted before the answer was complete. The assistant may still be working.");
|
|
263
|
+
} else onComplete();
|
|
207
264
|
break;
|
|
208
265
|
}
|
|
209
266
|
buffer += decoder.decode(value, { stream: true });
|
|
210
267
|
receivedData = true;
|
|
211
|
-
buffer = processStreamLines(buffer,
|
|
268
|
+
buffer = processStreamLines(buffer, dispatch);
|
|
269
|
+
if (failed) return;
|
|
212
270
|
}
|
|
213
271
|
} catch (error) {
|
|
214
272
|
if (signal?.aborted) return;
|
|
215
273
|
onError(error.message || "Streaming error");
|
|
274
|
+
} finally {
|
|
275
|
+
signal?.removeEventListener("abort", abortFromCaller);
|
|
276
|
+
if (reader) {
|
|
277
|
+
try {
|
|
278
|
+
await reader.cancel();
|
|
279
|
+
} catch {
|
|
280
|
+
}
|
|
281
|
+
reader.releaseLock();
|
|
282
|
+
}
|
|
216
283
|
}
|
|
217
284
|
};
|
|
218
285
|
|
|
@@ -849,32 +916,32 @@ function dispatchProgressEvent(progress, options = {}) {
|
|
|
849
916
|
};
|
|
850
917
|
window.dispatchEvent(new CustomEvent(PROGRESS_EVENT_NAME, { detail }));
|
|
851
918
|
}
|
|
852
|
-
var ScopedReasoningContext =
|
|
919
|
+
var ScopedReasoningContext = React15.createContext(null);
|
|
853
920
|
function ScopedReasoningProvider({
|
|
854
921
|
hasOwnedKgId,
|
|
855
922
|
children
|
|
856
923
|
}) {
|
|
857
|
-
const value =
|
|
924
|
+
const value = React15.useMemo(
|
|
858
925
|
() => ({ hasOwnedKgId }),
|
|
859
926
|
[hasOwnedKgId]
|
|
860
927
|
);
|
|
861
|
-
return
|
|
928
|
+
return React15__default.default.createElement(
|
|
862
929
|
ScopedReasoningContext.Provider,
|
|
863
930
|
{ value },
|
|
864
931
|
children
|
|
865
932
|
);
|
|
866
933
|
}
|
|
867
934
|
function useScopedProgressEvent(ownKgId, handler, enabled = true) {
|
|
868
|
-
const ctx =
|
|
869
|
-
const handlerRef =
|
|
870
|
-
const ownKgIdRef =
|
|
871
|
-
|
|
935
|
+
const ctx = React15.useContext(ScopedReasoningContext);
|
|
936
|
+
const handlerRef = React15.useRef(handler);
|
|
937
|
+
const ownKgIdRef = React15.useRef(ownKgId);
|
|
938
|
+
React15.useEffect(() => {
|
|
872
939
|
handlerRef.current = handler;
|
|
873
940
|
}, [handler]);
|
|
874
|
-
|
|
941
|
+
React15.useEffect(() => {
|
|
875
942
|
ownKgIdRef.current = ownKgId;
|
|
876
943
|
}, [ownKgId]);
|
|
877
|
-
|
|
944
|
+
React15.useEffect(() => {
|
|
878
945
|
if (!enabled) return;
|
|
879
946
|
const listener = (e) => {
|
|
880
947
|
const detail = e.detail;
|
|
@@ -979,10 +1046,10 @@ var defaultTheme = {
|
|
|
979
1046
|
// Cursor
|
|
980
1047
|
cursor: "#f97316"
|
|
981
1048
|
};
|
|
982
|
-
var ThemeContext =
|
|
1049
|
+
var ThemeContext = React15.createContext(defaultTheme);
|
|
983
1050
|
var TerminalThemeProvider = ThemeContext.Provider;
|
|
984
1051
|
function useTheme() {
|
|
985
|
-
return
|
|
1052
|
+
return React15.useContext(ThemeContext);
|
|
986
1053
|
}
|
|
987
1054
|
function mergeTheme(overrides) {
|
|
988
1055
|
if (!overrides) return defaultTheme;
|
|
@@ -1058,8 +1125,8 @@ var hostApp = {
|
|
|
1058
1125
|
};
|
|
1059
1126
|
function ShareButton({ content, title }) {
|
|
1060
1127
|
const t = useTheme();
|
|
1061
|
-
const [state, setState] =
|
|
1062
|
-
const handleShare =
|
|
1128
|
+
const [state, setState] = React15.useState("idle");
|
|
1129
|
+
const handleShare = React15.useCallback(
|
|
1063
1130
|
async (e) => {
|
|
1064
1131
|
e.stopPropagation();
|
|
1065
1132
|
const shareText = content.slice(0, 500);
|
|
@@ -1087,12 +1154,13 @@ function ShareButton({ content, title }) {
|
|
|
1087
1154
|
"button",
|
|
1088
1155
|
{
|
|
1089
1156
|
onClick: handleShare,
|
|
1090
|
-
className: "
|
|
1157
|
+
className: "inline-flex h-6 w-6 items-center justify-center rounded-md transition-all duration-200 hover:scale-110",
|
|
1091
1158
|
style: {
|
|
1092
1159
|
backgroundColor: done ? "rgba(74,222,128,0.15)" : t.bgRaisedHover,
|
|
1093
1160
|
color: done ? t.success : t.textMuted
|
|
1094
1161
|
},
|
|
1095
1162
|
title: state === "copied" ? "Copied!" : state === "shared" ? "Shared!" : "Share",
|
|
1163
|
+
"aria-label": state === "copied" ? "Link copied" : state === "shared" ? "Shared" : "Share message",
|
|
1096
1164
|
children: done ? /* @__PURE__ */ jsxRuntime.jsx("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsxRuntime.jsx("path", { d: "M5 12l5 5L20 7" }) }) : /* @__PURE__ */ jsxRuntime.jsxs("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
|
|
1097
1165
|
/* @__PURE__ */ jsxRuntime.jsx("path", { d: "M4 12v7a2 2 0 002 2h12a2 2 0 002-2v-7" }),
|
|
1098
1166
|
/* @__PURE__ */ jsxRuntime.jsx("polyline", { points: "16 6 12 2 8 6" }),
|
|
@@ -1101,11 +1169,30 @@ function ShareButton({ content, title }) {
|
|
|
1101
1169
|
}
|
|
1102
1170
|
);
|
|
1103
1171
|
}
|
|
1172
|
+
|
|
1173
|
+
// src/utils/stripInternalIds.ts
|
|
1174
|
+
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}";
|
|
1175
|
+
var PREFIXED = `(?:KG|DOC|FRAME|SET|NODE|CHUNK):${UUID}`;
|
|
1176
|
+
var WRAP = "[*_`]*";
|
|
1177
|
+
var PAREN_PREFIXED = new RegExp(`\\s*\\(\\s*${WRAP}${PREFIXED}${WRAP}\\s*\\)`, "g");
|
|
1178
|
+
var PAREN_BARE = new RegExp(`\\s*\\(\\s*${WRAP}${UUID}${WRAP}\\s*\\)`, "g");
|
|
1179
|
+
var BARE_PREFIXED = new RegExp(`${WRAP}${PREFIXED}${WRAP}`, "g");
|
|
1180
|
+
var ID_PHRASE = new RegExp(
|
|
1181
|
+
`\\s*(?:\\(\\s*)?(?:for\\s+|with\\s+)?(?:suggestion|proposal|item|thread|entity|message|document)\\s+id[:\\s]+${WRAP}${UUID}${WRAP}(?:\\s*\\))?`,
|
|
1182
|
+
"gi"
|
|
1183
|
+
);
|
|
1184
|
+
var BARE_UUID = new RegExp(`${WRAP}${UUID}${WRAP}`, "g");
|
|
1185
|
+
function stripInternalIds(text) {
|
|
1186
|
+
if (!text || !/(?:KG|DOC|FRAME|SET|NODE|CHUNK):|-[0-9a-fA-F]{4}-/.test(text)) return text;
|
|
1187
|
+
return text.split(/(```[\s\S]*?```)/g).map(
|
|
1188
|
+
(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 ")
|
|
1189
|
+
).join("");
|
|
1190
|
+
}
|
|
1104
1191
|
function TimestampRenderer({ timestamp }) {
|
|
1105
1192
|
const t = useTheme();
|
|
1106
|
-
const [timeString, setTimeString] =
|
|
1107
|
-
|
|
1108
|
-
setTimeString(timestamp.toLocaleTimeString());
|
|
1193
|
+
const [timeString, setTimeString] = React15.useState("");
|
|
1194
|
+
React15.useEffect(() => {
|
|
1195
|
+
setTimeString(timestamp.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }));
|
|
1109
1196
|
}, [timestamp]);
|
|
1110
1197
|
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs ml-6 mt-1", style: { color: t.textMuted }, children: timeString });
|
|
1111
1198
|
}
|
|
@@ -1126,36 +1213,36 @@ async function gql(url, token, query, variables) {
|
|
|
1126
1213
|
return res.json();
|
|
1127
1214
|
}
|
|
1128
1215
|
function InteractiveActionCard({
|
|
1129
|
-
action,
|
|
1216
|
+
action: action2,
|
|
1130
1217
|
onExecute,
|
|
1131
1218
|
graphqlUrl = "",
|
|
1132
1219
|
authToken = ""
|
|
1133
1220
|
}) {
|
|
1134
1221
|
const t = useTheme();
|
|
1135
|
-
const initialValues =
|
|
1136
|
-
const amount2 =
|
|
1137
|
-
const assetId =
|
|
1138
|
-
const entityId =
|
|
1139
|
-
const walletId =
|
|
1222
|
+
const initialValues = React15.useMemo(() => {
|
|
1223
|
+
const amount2 = action2.metadata?.formatted_amount || (action2.payload?.arguments?.amount && action2.payload.arguments.amount !== "0" ? action2.payload.arguments.amount : "") || "";
|
|
1224
|
+
const assetId = action2.payload?.arguments?.asset_id || "";
|
|
1225
|
+
const entityId = action2.payload?.arguments?.destination_id || "";
|
|
1226
|
+
const walletId = action2.payload?.arguments?.destination_wallet_id || "";
|
|
1140
1227
|
return { amount: amount2, assetId, entityId, walletId };
|
|
1141
|
-
}, [
|
|
1142
|
-
const [editedAction, setEditedAction] =
|
|
1143
|
-
const [entities, setEntities] =
|
|
1144
|
-
const [wallets, setWallets] =
|
|
1145
|
-
const [assets, setAssets] =
|
|
1146
|
-
const [loadingEntities, setLoadingEntities] =
|
|
1147
|
-
const [loadingWallets, setLoadingWallets] =
|
|
1148
|
-
const [loadingAssets, setLoadingAssets] =
|
|
1149
|
-
const [errorEntities, setErrorEntities] =
|
|
1150
|
-
const [errorWallets, setErrorWallets] =
|
|
1151
|
-
const [errorAssets, setErrorAssets] =
|
|
1152
|
-
const [selectedEntityId, setSelectedEntityId] =
|
|
1153
|
-
const [selectedWalletId, setSelectedWalletId] =
|
|
1154
|
-
const [selectedAssetId, setSelectedAssetId] =
|
|
1155
|
-
const [amount, setAmount] =
|
|
1156
|
-
const [obligorEntity, setObligorEntity] =
|
|
1157
|
-
const [loadingObligor, setLoadingObligor] =
|
|
1158
|
-
const fetchEntities =
|
|
1228
|
+
}, [action2]);
|
|
1229
|
+
const [editedAction, setEditedAction] = React15.useState(action2);
|
|
1230
|
+
const [entities, setEntities] = React15.useState([]);
|
|
1231
|
+
const [wallets, setWallets] = React15.useState([]);
|
|
1232
|
+
const [assets, setAssets] = React15.useState([]);
|
|
1233
|
+
const [loadingEntities, setLoadingEntities] = React15.useState(false);
|
|
1234
|
+
const [loadingWallets, setLoadingWallets] = React15.useState(false);
|
|
1235
|
+
const [loadingAssets, setLoadingAssets] = React15.useState(false);
|
|
1236
|
+
const [errorEntities, setErrorEntities] = React15.useState(null);
|
|
1237
|
+
const [errorWallets, setErrorWallets] = React15.useState(null);
|
|
1238
|
+
const [errorAssets, setErrorAssets] = React15.useState(null);
|
|
1239
|
+
const [selectedEntityId, setSelectedEntityId] = React15.useState(initialValues.entityId);
|
|
1240
|
+
const [selectedWalletId, setSelectedWalletId] = React15.useState(initialValues.walletId);
|
|
1241
|
+
const [selectedAssetId, setSelectedAssetId] = React15.useState(initialValues.assetId);
|
|
1242
|
+
const [amount, setAmount] = React15.useState(initialValues.amount);
|
|
1243
|
+
const [obligorEntity, setObligorEntity] = React15.useState(null);
|
|
1244
|
+
const [loadingObligor, setLoadingObligor] = React15.useState(false);
|
|
1245
|
+
const fetchEntities = React15.useCallback(async () => {
|
|
1159
1246
|
if (!graphqlUrl) return;
|
|
1160
1247
|
setLoadingEntities(true);
|
|
1161
1248
|
try {
|
|
@@ -1176,7 +1263,7 @@ function InteractiveActionCard({
|
|
|
1176
1263
|
setLoadingEntities(false);
|
|
1177
1264
|
}
|
|
1178
1265
|
}, [graphqlUrl, authToken]);
|
|
1179
|
-
const fetchWallets =
|
|
1266
|
+
const fetchWallets = React15.useCallback(
|
|
1180
1267
|
async (entityId) => {
|
|
1181
1268
|
if (!entityId || !graphqlUrl) return;
|
|
1182
1269
|
setLoadingWallets(true);
|
|
@@ -1201,7 +1288,7 @@ function InteractiveActionCard({
|
|
|
1201
1288
|
},
|
|
1202
1289
|
[graphqlUrl, authToken]
|
|
1203
1290
|
);
|
|
1204
|
-
const fetchAssets =
|
|
1291
|
+
const fetchAssets = React15.useCallback(async () => {
|
|
1205
1292
|
if (!graphqlUrl) return;
|
|
1206
1293
|
setLoadingAssets(true);
|
|
1207
1294
|
try {
|
|
@@ -1222,7 +1309,7 @@ function InteractiveActionCard({
|
|
|
1222
1309
|
setLoadingAssets(false);
|
|
1223
1310
|
}
|
|
1224
1311
|
}, [graphqlUrl, authToken]);
|
|
1225
|
-
const updateActionField =
|
|
1312
|
+
const updateActionField = React15.useCallback(
|
|
1226
1313
|
(field, value) => {
|
|
1227
1314
|
setEditedAction((prev) => {
|
|
1228
1315
|
const updated = { ...prev };
|
|
@@ -1252,15 +1339,15 @@ function InteractiveActionCard({
|
|
|
1252
1339
|
},
|
|
1253
1340
|
[assets, entities, wallets]
|
|
1254
1341
|
);
|
|
1255
|
-
|
|
1256
|
-
if (
|
|
1342
|
+
React15.useEffect(() => {
|
|
1343
|
+
if (action2.payload?.tool_name === "yieldfabric/send_instant_payment") {
|
|
1257
1344
|
fetchEntities();
|
|
1258
1345
|
fetchAssets();
|
|
1259
1346
|
if (initialValues.entityId) fetchWallets(initialValues.entityId);
|
|
1260
1347
|
}
|
|
1261
1348
|
}, []);
|
|
1262
|
-
|
|
1263
|
-
if (selectedEntityId &&
|
|
1349
|
+
React15.useEffect(() => {
|
|
1350
|
+
if (selectedEntityId && action2.payload?.tool_name === "yieldfabric/send_instant_payment") {
|
|
1264
1351
|
const shouldFetch = selectedEntityId !== initialValues.entityId || wallets.length === 0;
|
|
1265
1352
|
if (shouldFetch) fetchWallets(selectedEntityId);
|
|
1266
1353
|
if (selectedEntityId !== initialValues.entityId) {
|
|
@@ -1269,15 +1356,15 @@ function InteractiveActionCard({
|
|
|
1269
1356
|
}
|
|
1270
1357
|
}
|
|
1271
1358
|
}, [selectedEntityId]);
|
|
1272
|
-
|
|
1273
|
-
if (
|
|
1359
|
+
React15.useEffect(() => {
|
|
1360
|
+
if (action2.payload?.tool_name !== "yieldfabric/send_instant_payment") return;
|
|
1274
1361
|
if (initialValues.assetId && assets.length > 0) {
|
|
1275
1362
|
const match = assets.find((a) => a.id === initialValues.assetId) || assets.find(
|
|
1276
1363
|
(a) => a.id.toUpperCase() === initialValues.assetId.toUpperCase()
|
|
1277
1364
|
) || assets.find(
|
|
1278
1365
|
(a) => initialValues.assetId.toUpperCase() === "CBDC" && a.name?.toUpperCase().includes("CBDC")
|
|
1279
|
-
) ||
|
|
1280
|
-
(a) => a.id ===
|
|
1366
|
+
) || action2.metadata?.asset_id && assets.find(
|
|
1367
|
+
(a) => a.id === action2.metadata.asset_id || a.id.toUpperCase() === action2.metadata.asset_id.toUpperCase()
|
|
1281
1368
|
);
|
|
1282
1369
|
if (match && selectedAssetId !== match.id) {
|
|
1283
1370
|
setSelectedAssetId(match.id);
|
|
@@ -1301,11 +1388,11 @@ function InteractiveActionCard({
|
|
|
1301
1388
|
updateActionField("amount", initialValues.amount);
|
|
1302
1389
|
}
|
|
1303
1390
|
}, [assets, entities, wallets]);
|
|
1304
|
-
if (
|
|
1391
|
+
if (action2.payload?.tool_name === "yieldfabric/swap_credit_for_cash") {
|
|
1305
1392
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1306
1393
|
RedeemCreditCard,
|
|
1307
1394
|
{
|
|
1308
|
-
action,
|
|
1395
|
+
action: action2,
|
|
1309
1396
|
onExecute,
|
|
1310
1397
|
graphqlUrl,
|
|
1311
1398
|
authToken,
|
|
@@ -1316,20 +1403,20 @@ function InteractiveActionCard({
|
|
|
1316
1403
|
}
|
|
1317
1404
|
);
|
|
1318
1405
|
}
|
|
1319
|
-
if (
|
|
1320
|
-
return /* @__PURE__ */ jsxRuntime.jsx(CompleteSwapCard, { action, onExecute });
|
|
1406
|
+
if (action2.payload?.tool_name === "yieldfabric/complete_swap") {
|
|
1407
|
+
return /* @__PURE__ */ jsxRuntime.jsx(CompleteSwapCard, { action: action2, onExecute });
|
|
1321
1408
|
}
|
|
1322
|
-
if (
|
|
1323
|
-
return /* @__PURE__ */ jsxRuntime.jsx(AcceptPaymentCard, { action, onExecute });
|
|
1409
|
+
if (action2.payload?.tool_name === "yieldfabric/accept_payment") {
|
|
1410
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AcceptPaymentCard, { action: action2, onExecute });
|
|
1324
1411
|
}
|
|
1325
|
-
if (
|
|
1326
|
-
return /* @__PURE__ */ jsxRuntime.jsx(FileControlsCard, { action, onExecute });
|
|
1412
|
+
if (action2.action_type === "file_controls") {
|
|
1413
|
+
return /* @__PURE__ */ jsxRuntime.jsx(FileControlsCard, { action: action2, onExecute });
|
|
1327
1414
|
}
|
|
1328
|
-
if (
|
|
1329
|
-
return /* @__PURE__ */ jsxRuntime.jsx(DownloadSourceCard, { action, onExecute });
|
|
1415
|
+
if (action2.action_type === "download_source") {
|
|
1416
|
+
return /* @__PURE__ */ jsxRuntime.jsx(DownloadSourceCard, { action: action2, onExecute });
|
|
1330
1417
|
}
|
|
1331
|
-
if (
|
|
1332
|
-
return /* @__PURE__ */ jsxRuntime.jsx(GenericActionCard, { action, onExecute });
|
|
1418
|
+
if (action2.payload?.tool_name !== "yieldfabric/send_instant_payment") {
|
|
1419
|
+
return /* @__PURE__ */ jsxRuntime.jsx(GenericActionCard, { action: action2, onExecute });
|
|
1333
1420
|
}
|
|
1334
1421
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1335
1422
|
"div",
|
|
@@ -1476,7 +1563,7 @@ function InteractiveActionCard({
|
|
|
1476
1563
|
);
|
|
1477
1564
|
}
|
|
1478
1565
|
function RedeemCreditCard({
|
|
1479
|
-
action,
|
|
1566
|
+
action: action2,
|
|
1480
1567
|
onExecute,
|
|
1481
1568
|
graphqlUrl,
|
|
1482
1569
|
authToken,
|
|
@@ -1486,14 +1573,14 @@ function RedeemCreditCard({
|
|
|
1486
1573
|
setLoadingObligor
|
|
1487
1574
|
}) {
|
|
1488
1575
|
const t = useTheme();
|
|
1489
|
-
const metadata =
|
|
1576
|
+
const metadata = action2.metadata || {};
|
|
1490
1577
|
const formattedAmount = metadata.formatted_amount || metadata.amount || "0.00";
|
|
1491
1578
|
const currency = metadata.currency || "Unknown";
|
|
1492
1579
|
const obligor = metadata.obligor || metadata.obligor_id || "Unknown";
|
|
1493
1580
|
const obligorId = metadata.obligor_id || obligor;
|
|
1494
1581
|
const assetDisplay = formatAssetDisplay(metadata, currency);
|
|
1495
|
-
|
|
1496
|
-
if (
|
|
1582
|
+
React15.useEffect(() => {
|
|
1583
|
+
if (action2.payload?.tool_name !== "yieldfabric/swap_credit_for_cash") return;
|
|
1497
1584
|
if (obligorId === "Unknown" || obligor.includes("@")) return;
|
|
1498
1585
|
if (metadata.obligor_name && metadata.obligor_name !== obligorId && !obligorId.includes("-"))
|
|
1499
1586
|
return;
|
|
@@ -1524,7 +1611,7 @@ function RedeemCreditCard({
|
|
|
1524
1611
|
setLoadingObligor(false);
|
|
1525
1612
|
}
|
|
1526
1613
|
})();
|
|
1527
|
-
}, [obligorId,
|
|
1614
|
+
}, [obligorId, action2.payload?.tool_name]);
|
|
1528
1615
|
const obligorDisplay = (() => {
|
|
1529
1616
|
if (obligorEntity?.name) return obligorEntity.name;
|
|
1530
1617
|
if (metadata.obligor_name && metadata.obligor_name !== obligorId && metadata.obligor_name !== obligor)
|
|
@@ -1576,7 +1663,7 @@ function RedeemCreditCard({
|
|
|
1576
1663
|
onClick: (e) => {
|
|
1577
1664
|
e.preventDefault();
|
|
1578
1665
|
e.stopPropagation();
|
|
1579
|
-
onExecute(
|
|
1666
|
+
onExecute(action2);
|
|
1580
1667
|
},
|
|
1581
1668
|
className: "w-full py-2 px-4 text-sm font-medium rounded transition-colors flex items-center justify-center gap-2",
|
|
1582
1669
|
style: { backgroundColor: t.success, color: t.textInverse },
|
|
@@ -1591,12 +1678,12 @@ function RedeemCreditCard({
|
|
|
1591
1678
|
);
|
|
1592
1679
|
}
|
|
1593
1680
|
function CompleteSwapCard({
|
|
1594
|
-
action,
|
|
1681
|
+
action: action2,
|
|
1595
1682
|
onExecute
|
|
1596
1683
|
}) {
|
|
1597
1684
|
const t = useTheme();
|
|
1598
|
-
const metadata =
|
|
1599
|
-
const swapId = metadata.swap_id ||
|
|
1685
|
+
const metadata = action2.metadata || {};
|
|
1686
|
+
const swapId = metadata.swap_id || action2.payload?.arguments?.swap_id || "Unknown";
|
|
1600
1687
|
const initiator = metadata.initiator || "Unknown";
|
|
1601
1688
|
const status = metadata.status || "PENDING";
|
|
1602
1689
|
const deadline = metadata.deadline ? new Date(metadata.deadline).toLocaleString() : "N/A";
|
|
@@ -1658,7 +1745,7 @@ function CompleteSwapCard({
|
|
|
1658
1745
|
onClick: (e) => {
|
|
1659
1746
|
e.preventDefault();
|
|
1660
1747
|
e.stopPropagation();
|
|
1661
|
-
onExecute(
|
|
1748
|
+
onExecute(action2);
|
|
1662
1749
|
},
|
|
1663
1750
|
className: "w-full py-2 px-4 text-sm font-medium rounded transition-colors flex items-center justify-center gap-2",
|
|
1664
1751
|
style: { backgroundColor: t.success, color: t.textInverse },
|
|
@@ -1700,11 +1787,11 @@ function PaymentLeg({
|
|
|
1700
1787
|
] });
|
|
1701
1788
|
}
|
|
1702
1789
|
function AcceptPaymentCard({
|
|
1703
|
-
action,
|
|
1790
|
+
action: action2,
|
|
1704
1791
|
onExecute
|
|
1705
1792
|
}) {
|
|
1706
1793
|
const t = useTheme();
|
|
1707
|
-
const metadata =
|
|
1794
|
+
const metadata = action2.metadata || {};
|
|
1708
1795
|
const formattedAmount = metadata.formatted_amount || metadata.amount || "0.00";
|
|
1709
1796
|
const currency = metadata.currency || "Unknown";
|
|
1710
1797
|
const from = metadata.from || "Unknown";
|
|
@@ -1764,7 +1851,7 @@ function AcceptPaymentCard({
|
|
|
1764
1851
|
onClick: (e) => {
|
|
1765
1852
|
e.preventDefault();
|
|
1766
1853
|
e.stopPropagation();
|
|
1767
|
-
onExecute(
|
|
1854
|
+
onExecute(action2);
|
|
1768
1855
|
},
|
|
1769
1856
|
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",
|
|
1770
1857
|
style: { backgroundColor: t.success, color: t.textInverse },
|
|
@@ -1779,12 +1866,12 @@ function AcceptPaymentCard({
|
|
|
1779
1866
|
);
|
|
1780
1867
|
}
|
|
1781
1868
|
function FileControlsCard({
|
|
1782
|
-
action,
|
|
1869
|
+
action: action2,
|
|
1783
1870
|
onExecute
|
|
1784
1871
|
}) {
|
|
1785
1872
|
const t = useTheme();
|
|
1786
|
-
const title =
|
|
1787
|
-
const documentId =
|
|
1873
|
+
const title = action2.payload?.title || "Document";
|
|
1874
|
+
const documentId = action2.payload?.document_id;
|
|
1788
1875
|
const doDownload = (e) => {
|
|
1789
1876
|
e.preventDefault();
|
|
1790
1877
|
e.stopPropagation();
|
|
@@ -1843,18 +1930,18 @@ function FileControlsCard({
|
|
|
1843
1930
|
);
|
|
1844
1931
|
}
|
|
1845
1932
|
function DownloadSourceCard({
|
|
1846
|
-
action,
|
|
1933
|
+
action: action2,
|
|
1847
1934
|
onExecute
|
|
1848
1935
|
}) {
|
|
1849
1936
|
const t = useTheme();
|
|
1850
|
-
const title =
|
|
1937
|
+
const title = action2.payload?.title || action2.metadata?.display_text || action2.description || "Document";
|
|
1851
1938
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
1852
1939
|
"button",
|
|
1853
1940
|
{
|
|
1854
1941
|
onClick: (e) => {
|
|
1855
1942
|
e.preventDefault();
|
|
1856
1943
|
e.stopPropagation();
|
|
1857
|
-
onExecute(
|
|
1944
|
+
onExecute(action2);
|
|
1858
1945
|
},
|
|
1859
1946
|
className: "relative overflow-hidden w-full p-3 rounded-lg transition-all duration-200 text-left group",
|
|
1860
1947
|
style: { backgroundColor: t.buttonBg, border: `1px solid ${t.border}` },
|
|
@@ -1874,7 +1961,7 @@ function DownloadSourceCard({
|
|
|
1874
1961
|
);
|
|
1875
1962
|
}
|
|
1876
1963
|
function GenericActionCard({
|
|
1877
|
-
action,
|
|
1964
|
+
action: action2,
|
|
1878
1965
|
onExecute
|
|
1879
1966
|
}) {
|
|
1880
1967
|
const t = useTheme();
|
|
@@ -1884,14 +1971,14 @@ function GenericActionCard({
|
|
|
1884
1971
|
onClick: (e) => {
|
|
1885
1972
|
e.preventDefault();
|
|
1886
1973
|
e.stopPropagation();
|
|
1887
|
-
onExecute(
|
|
1974
|
+
onExecute(action2);
|
|
1888
1975
|
},
|
|
1889
1976
|
className: "flex items-center space-x-3 p-3 rounded-lg transition-colors text-left group",
|
|
1890
1977
|
style: { backgroundColor: GREEN_ACTION.bg, border: GREEN_ACTION.borderStyle },
|
|
1891
1978
|
onMouseEnter: (e) => e.currentTarget.style.backgroundColor = GREEN_ACTION.bgHover,
|
|
1892
1979
|
onMouseLeave: (e) => e.currentTarget.style.backgroundColor = GREEN_ACTION.bg,
|
|
1893
1980
|
children: [
|
|
1894
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "font-medium text-sm mb-1.5", style: { color: t.success }, children:
|
|
1981
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex-1 min-w-0", children: /* @__PURE__ */ jsxRuntime.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}` }) }),
|
|
1895
1982
|
/* @__PURE__ */ jsxRuntime.jsx(lucideReact.ArrowRight, { className: "w-5 h-5 transition-colors flex-shrink-0 ml-2", style: { color: t.success } })
|
|
1896
1983
|
]
|
|
1897
1984
|
}
|
|
@@ -1957,7 +2044,7 @@ function PipelineDraftCard({
|
|
|
1957
2044
|
className: externalClassName
|
|
1958
2045
|
}) {
|
|
1959
2046
|
const t = useTheme();
|
|
1960
|
-
const [submitting, setSubmitting] =
|
|
2047
|
+
const [submitting, setSubmitting] = React15.useState(false);
|
|
1961
2048
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
1962
2049
|
"div",
|
|
1963
2050
|
{
|
|
@@ -2088,7 +2175,7 @@ function CollapsibleSection({
|
|
|
2088
2175
|
defaultExpanded = false
|
|
2089
2176
|
}) {
|
|
2090
2177
|
const t = useTheme();
|
|
2091
|
-
const [expanded, setExpanded] =
|
|
2178
|
+
const [expanded, setExpanded] = React15.useState(defaultExpanded);
|
|
2092
2179
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
2093
2180
|
"div",
|
|
2094
2181
|
{
|
|
@@ -2122,8 +2209,8 @@ function CollapsibleSection({
|
|
|
2122
2209
|
}
|
|
2123
2210
|
function CopyButton({ content }) {
|
|
2124
2211
|
const t = useTheme();
|
|
2125
|
-
const [copied, setCopied] =
|
|
2126
|
-
const handleCopy =
|
|
2212
|
+
const [copied, setCopied] = React15.useState(false);
|
|
2213
|
+
const handleCopy = React15.useCallback(
|
|
2127
2214
|
async (e) => {
|
|
2128
2215
|
e.stopPropagation();
|
|
2129
2216
|
try {
|
|
@@ -2139,13 +2226,29 @@ function CopyButton({ content }) {
|
|
|
2139
2226
|
"button",
|
|
2140
2227
|
{
|
|
2141
2228
|
onClick: handleCopy,
|
|
2142
|
-
className: "
|
|
2229
|
+
className: "inline-flex h-6 w-6 items-center justify-center rounded transition-colors hover:scale-110",
|
|
2143
2230
|
style: { backgroundColor: t.bgRaisedHover, color: t.textSecondary },
|
|
2144
2231
|
title: "Copy",
|
|
2232
|
+
"aria-label": copied ? "Copied" : "Copy message",
|
|
2145
2233
|
children: copied ? /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Check, { className: "w-3.5 h-3.5", style: { color: t.success } }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Copy, { className: "w-3.5 h-3.5" })
|
|
2146
2234
|
}
|
|
2147
2235
|
);
|
|
2148
2236
|
}
|
|
2237
|
+
function AgentCompletionNotice({ completion }) {
|
|
2238
|
+
const t = useTheme();
|
|
2239
|
+
if (!completion || completion.stop_reason === "answered") return null;
|
|
2240
|
+
const message = {
|
|
2241
|
+
rounds_exhausted: "Partial answer \u2014 I reached the step limit. Ask a narrower follow-up to continue.",
|
|
2242
|
+
budget_exhausted: "Partial answer \u2014 this question needs more context than fits in one answer. Try narrowing the question.",
|
|
2243
|
+
awaiting_tool_results: "This answer paused before its next step. Ask again to review a fresh answer.",
|
|
2244
|
+
empty: "No answer was returned. Please try again.",
|
|
2245
|
+
failed: "The answer could not be completed. What arrived so far is kept here.",
|
|
2246
|
+
interrupted: "Connection interrupted. The assistant may still be working; check the conversation before sending again.",
|
|
2247
|
+
cancelled: "Stopped. You can change your question and ask again."
|
|
2248
|
+
}[completion.stop_reason];
|
|
2249
|
+
if (!message) return null;
|
|
2250
|
+
return /* @__PURE__ */ jsxRuntime.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 });
|
|
2251
|
+
}
|
|
2149
2252
|
var AGENT_PALETTE = [
|
|
2150
2253
|
"a78bfa",
|
|
2151
2254
|
// violet-400
|
|
@@ -2194,7 +2297,7 @@ var AgentAvatar = ({
|
|
|
2194
2297
|
}) => {
|
|
2195
2298
|
const px = typeof size === "number" ? size : SIZE_PX[size];
|
|
2196
2299
|
const seed = canonicalSeed(name);
|
|
2197
|
-
const uri =
|
|
2300
|
+
const uri = React15.useMemo(() => {
|
|
2198
2301
|
const bg = AGENT_PALETTE[paletteIndex(seed)];
|
|
2199
2302
|
return core.createAvatar(collection.avataaars, {
|
|
2200
2303
|
seed,
|
|
@@ -2219,9 +2322,9 @@ var AgentAvatar = ({
|
|
|
2219
2322
|
};
|
|
2220
2323
|
function TimeLabel({ timestamp }) {
|
|
2221
2324
|
const t = useTheme();
|
|
2222
|
-
const [timeStr, setTimeStr] =
|
|
2223
|
-
|
|
2224
|
-
setTimeStr(timestamp.toLocaleTimeString());
|
|
2325
|
+
const [timeStr, setTimeStr] = React15.useState("");
|
|
2326
|
+
React15.useEffect(() => {
|
|
2327
|
+
setTimeStr(timestamp.toLocaleTimeString([], { hour: "numeric", minute: "2-digit" }));
|
|
2225
2328
|
}, [timestamp]);
|
|
2226
2329
|
return /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[10px] mt-0.5", style: { color: t.textSecondary }, children: timeStr });
|
|
2227
2330
|
}
|
|
@@ -2539,21 +2642,36 @@ function hashTypeColor(type) {
|
|
|
2539
2642
|
for (let i = 0; i < type.length; i++) h = (h << 5) - h + type.charCodeAt(i) | 0;
|
|
2540
2643
|
return SOURCE_TYPE_PALETTE[Math.abs(h) % SOURCE_TYPE_PALETTE.length];
|
|
2541
2644
|
}
|
|
2542
|
-
function SourceCard({
|
|
2645
|
+
function SourceCard({
|
|
2646
|
+
source,
|
|
2647
|
+
onActivate
|
|
2648
|
+
}) {
|
|
2543
2649
|
const t = useTheme();
|
|
2544
|
-
const [expanded, setExpanded] =
|
|
2650
|
+
const [expanded, setExpanded] = React15.useState(false);
|
|
2545
2651
|
const showType = source.type && source.type.toLowerCase() !== "unknown";
|
|
2546
2652
|
const badgeColor = source.typeColor || (showType ? hashTypeColor(source.type) : t.textMuted);
|
|
2547
2653
|
const displayLabel = formatSourceLabel(source.label);
|
|
2548
2654
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded", style: { border: `1px solid ${t.border}`, backgroundColor: t.bgRaisedAlt }, children: [
|
|
2549
2655
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 px-2.5 py-1.5", children: [
|
|
2550
|
-
source.description ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2551
|
-
|
|
2656
|
+
source.description ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2657
|
+
"button",
|
|
2552
2658
|
{
|
|
2553
|
-
|
|
2554
|
-
|
|
2659
|
+
type: "button",
|
|
2660
|
+
onClick: (event) => {
|
|
2661
|
+
event.stopPropagation();
|
|
2662
|
+
setExpanded(!expanded);
|
|
2663
|
+
},
|
|
2664
|
+
className: "flex-shrink-0 rounded-sm focus:outline-none focus-visible:ring-2",
|
|
2665
|
+
"aria-label": expanded ? `Collapse ${displayLabel} details` : `Expand ${displayLabel} details`,
|
|
2666
|
+
children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
2667
|
+
lucideReact.ChevronRight,
|
|
2668
|
+
{
|
|
2669
|
+
className: "w-3 h-3 transition-transform",
|
|
2670
|
+
style: { color: t.textMuted, transform: expanded ? "rotate(90deg)" : "none" }
|
|
2671
|
+
}
|
|
2672
|
+
)
|
|
2555
2673
|
}
|
|
2556
|
-
)
|
|
2674
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 flex-shrink-0 flex items-center justify-center", children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-1.5 h-1.5 rounded-full", style: { backgroundColor: badgeColor } }) }),
|
|
2557
2675
|
showType && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2558
2676
|
"span",
|
|
2559
2677
|
{
|
|
@@ -2562,11 +2680,28 @@ function SourceCard({ source }) {
|
|
|
2562
2680
|
children: source.type
|
|
2563
2681
|
}
|
|
2564
2682
|
),
|
|
2565
|
-
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2683
|
+
onActivate ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2684
|
+
"button",
|
|
2685
|
+
{
|
|
2686
|
+
type: "button",
|
|
2687
|
+
className: "text-[11px] truncate flex-1 cursor-pointer text-left rounded-sm hover:underline focus:outline-none focus-visible:ring-2",
|
|
2688
|
+
style: { color: t.text },
|
|
2689
|
+
onClick: (event) => {
|
|
2690
|
+
event.stopPropagation();
|
|
2691
|
+
onActivate(source);
|
|
2692
|
+
},
|
|
2693
|
+
"aria-label": `Open ${displayLabel}`,
|
|
2694
|
+
children: displayLabel
|
|
2695
|
+
}
|
|
2696
|
+
) : /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-[11px] truncate flex-1", style: { color: t.text }, children: displayLabel })
|
|
2566
2697
|
] }),
|
|
2567
2698
|
expanded && source.description && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "px-2.5 pb-2 text-[10px] leading-relaxed", style: { color: t.textSecondary, borderTop: `1px solid ${t.border}` }, children: source.description })
|
|
2568
2699
|
] });
|
|
2569
2700
|
}
|
|
2701
|
+
var REMARK_PLUGINS = [remarkGfm__default.default];
|
|
2702
|
+
function isBlockCode(className, text) {
|
|
2703
|
+
return /language-/.test(typeof className === "string" ? className : "") || text.includes("\n");
|
|
2704
|
+
}
|
|
2570
2705
|
function getMarkdownComponents(t) {
|
|
2571
2706
|
return {
|
|
2572
2707
|
h1: ({ node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("h1", { className: "text-xl font-bold mt-4 mb-2", style: { color: t.headingText }, ...props }),
|
|
@@ -2578,10 +2713,38 @@ function getMarkdownComponents(t) {
|
|
|
2578
2713
|
li: ({ node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("li", { className: "ml-2", ...props }),
|
|
2579
2714
|
strong: ({ node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("strong", { className: "font-bold", style: { color: t.text }, ...props }),
|
|
2580
2715
|
em: ({ node, ...props }) => /* @__PURE__ */ jsxRuntime.jsx("em", { className: "italic", style: { color: t.textSecondary }, ...props }),
|
|
2581
|
-
code: ({ node, inline, children, ...props }) =>
|
|
2582
|
-
|
|
2583
|
-
|
|
2584
|
-
|
|
2716
|
+
code: ({ node, inline, children, ...props }) => {
|
|
2717
|
+
const text = String(children ?? "");
|
|
2718
|
+
const isInline = inline ?? !isBlockCode(props.className, text);
|
|
2719
|
+
return isInline ? /* @__PURE__ */ jsxRuntime.jsx("code", { className: "px-1 py-0.5 rounded font-mono text-xs", style: { backgroundColor: t.codeBg, color: t.codeText }, ...props, children }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative group/code", children: [
|
|
2720
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: text }),
|
|
2721
|
+
/* @__PURE__ */ jsxRuntime.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 })
|
|
2722
|
+
] });
|
|
2723
|
+
},
|
|
2724
|
+
// Tables are why remark-gfm is here. The wrapper is not decoration:
|
|
2725
|
+
// this renders inside a chat rail the user can drag down to ~360px,
|
|
2726
|
+
// and a table holding a term plus a few numbers will exceed that. It
|
|
2727
|
+
// has to scroll INSIDE its own box — without the wrapper the reply
|
|
2728
|
+
// column itself widens and every other line in the conversation
|
|
2729
|
+
// starts scrolling sideways along with it.
|
|
2730
|
+
table: ({ node, ...p }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2731
|
+
"div",
|
|
2732
|
+
{
|
|
2733
|
+
className: "my-2 max-w-full overflow-x-auto rounded",
|
|
2734
|
+
style: { border: `1px solid ${t.codeBg}` },
|
|
2735
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("table", { className: "w-full border-collapse text-xs", ...p })
|
|
2736
|
+
}
|
|
2737
|
+
),
|
|
2738
|
+
thead: ({ node, ...p }) => /* @__PURE__ */ jsxRuntime.jsx("thead", { style: { backgroundColor: t.codeBg }, ...p }),
|
|
2739
|
+
th: ({ node, ...p }) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2740
|
+
"th",
|
|
2741
|
+
{
|
|
2742
|
+
className: "px-2.5 py-1.5 text-left font-semibold whitespace-nowrap",
|
|
2743
|
+
style: { color: t.headingText, borderBottom: `1px solid ${t.codeBg}` },
|
|
2744
|
+
...p
|
|
2745
|
+
}
|
|
2746
|
+
),
|
|
2747
|
+
td: ({ node, ...p }) => /* @__PURE__ */ jsxRuntime.jsx("td", { className: "px-2.5 py-1.5 align-top", style: { borderBottom: `1px solid ${t.codeBg}` }, ...p })
|
|
2585
2748
|
};
|
|
2586
2749
|
}
|
|
2587
2750
|
function TerminalEntryRenderer({
|
|
@@ -2596,6 +2759,7 @@ function TerminalEntryRenderer({
|
|
|
2596
2759
|
authToken,
|
|
2597
2760
|
onPageNavigation,
|
|
2598
2761
|
onSourcesActivate,
|
|
2762
|
+
onSourceActivate,
|
|
2599
2763
|
renderEntryExtra,
|
|
2600
2764
|
renderEntry,
|
|
2601
2765
|
widgets,
|
|
@@ -2613,7 +2777,7 @@ function TerminalEntryRenderer({
|
|
|
2613
2777
|
const isError = entry.type === "error";
|
|
2614
2778
|
const isSuccess = entry.type === "success";
|
|
2615
2779
|
const isEmpty = !entry.content || entry.content.trim() === "";
|
|
2616
|
-
const useAttribution = isCollaborative && entry.sender && !isSystem && !isEmpty;
|
|
2780
|
+
const useAttribution = (isCollaborative || entry.sender?.type === "agent") && entry.sender && !isSystem && !isEmpty;
|
|
2617
2781
|
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";
|
|
2618
2782
|
const beforeWidgets = widgets?.filter((w) => w.position === "before" && w.match(entry)) || [];
|
|
2619
2783
|
const afterWidgets = widgets?.filter((w) => (!w.position || w.position === "after") && w.match(entry)) || [];
|
|
@@ -2626,12 +2790,12 @@ function TerminalEntryRenderer({
|
|
|
2626
2790
|
timestamp: entry.timestamp,
|
|
2627
2791
|
isOwnMessage: entry.sender.entity_id === currentUser?.entity_id,
|
|
2628
2792
|
grouped: isGrouped,
|
|
2629
|
-
children: entry.sender?.type === "agent" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm prose prose-invert prose-sm max-w-
|
|
2793
|
+
children: entry.sender?.type === "agent" ? /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm prose prose-invert prose-sm max-w-[72ch] group relative", style: { color: t.text }, children: [
|
|
2630
2794
|
/* @__PURE__ */ jsxRuntime.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: [
|
|
2631
2795
|
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: entry.content }),
|
|
2632
2796
|
/* @__PURE__ */ jsxRuntime.jsx(ShareButton, { content: entry.content })
|
|
2633
2797
|
] }),
|
|
2634
|
-
/* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown__default.default, { components: markdownComponents, children: entry.content })
|
|
2798
|
+
/* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown__default.default, { remarkPlugins: REMARK_PLUGINS, components: markdownComponents, children: stripInternalIds(entry.content) })
|
|
2635
2799
|
] }) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-sm whitespace-pre-wrap group relative", style: { color: isError ? t.error : t.text }, children: [
|
|
2636
2800
|
/* @__PURE__ */ jsxRuntime.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: [
|
|
2637
2801
|
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: entry.content }),
|
|
@@ -2642,7 +2806,6 @@ function TerminalEntryRenderer({
|
|
|
2642
2806
|
}
|
|
2643
2807
|
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-start space-x-2", children: [
|
|
2644
2808
|
isSystem && !isEmpty && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Terminal, { className: "w-4 h-4 mt-0.5 flex-shrink-0", style: { color: t.textSystem } }),
|
|
2645
|
-
isCommand && !isEmpty && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.Brain, { className: "w-4 h-4 mt-0.5 flex-shrink-0", style: { color: t.info } }),
|
|
2646
2809
|
isInfo && !isEmpty && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { className: "w-4 h-4 mt-0.5 flex-shrink-0", style: { color: t.info } }),
|
|
2647
2810
|
isSuccess && !isEmpty && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.CheckCircle, { className: "w-4 h-4 mt-0.5 flex-shrink-0", style: { color: t.success } }),
|
|
2648
2811
|
isError && !isEmpty && /* @__PURE__ */ jsxRuntime.jsx(lucideReact.XCircle, { className: "w-4 h-4 mt-0.5 flex-shrink-0", style: { color: t.error } }),
|
|
@@ -2655,12 +2818,30 @@ function TerminalEntryRenderer({
|
|
|
2655
2818
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2656
2819
|
ReactMarkdown__default.default,
|
|
2657
2820
|
{
|
|
2821
|
+
remarkPlugins: REMARK_PLUGINS,
|
|
2658
2822
|
components: markdownComponents,
|
|
2659
|
-
children: entry.content
|
|
2823
|
+
children: stripInternalIds(entry.content)
|
|
2660
2824
|
},
|
|
2661
2825
|
`${entry.id || index}-${entry.content.length}`
|
|
2662
2826
|
)
|
|
2663
|
-
] }) :
|
|
2827
|
+
] }) : isCommand && !isSystem ? (
|
|
2828
|
+
// What the person typed: a quiet bubble on the right, the way the
|
|
2829
|
+
// console shows it — not a monospace line that reads as a log.
|
|
2830
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group relative flex w-full flex-1 justify-end", children: [
|
|
2831
|
+
/* @__PURE__ */ jsxRuntime.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: [
|
|
2832
|
+
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: entry.content }),
|
|
2833
|
+
/* @__PURE__ */ jsxRuntime.jsx(ShareButton, { content: entry.content })
|
|
2834
|
+
] }),
|
|
2835
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2836
|
+
"p",
|
|
2837
|
+
{
|
|
2838
|
+
className: "max-w-[80%] whitespace-pre-wrap rounded-lg border px-4 py-2.5 text-sm leading-relaxed",
|
|
2839
|
+
style: { color: t.text, borderColor: t.borderStrong, backgroundColor: "rgba(255,255,255,0.05)" },
|
|
2840
|
+
children: entry.content
|
|
2841
|
+
}
|
|
2842
|
+
)
|
|
2843
|
+
] })
|
|
2844
|
+
) : /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "group relative", children: [
|
|
2664
2845
|
/* @__PURE__ */ jsxRuntime.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: [
|
|
2665
2846
|
/* @__PURE__ */ jsxRuntime.jsx(CopyButton, { content: entry.content }),
|
|
2666
2847
|
/* @__PURE__ */ jsxRuntime.jsx(ShareButton, { content: entry.content })
|
|
@@ -2668,9 +2849,9 @@ function TerminalEntryRenderer({
|
|
|
2668
2849
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2669
2850
|
"pre",
|
|
2670
2851
|
{
|
|
2671
|
-
className: "font-mono text-sm whitespace-pre-wrap",
|
|
2852
|
+
className: "font-mono text-sm whitespace-pre-wrap max-w-[72ch]",
|
|
2672
2853
|
style: {
|
|
2673
|
-
color: isSystem ? t.textSystem :
|
|
2854
|
+
color: isSystem ? t.textSystem : isSuccess ? t.success : isError ? t.error : t.text
|
|
2674
2855
|
},
|
|
2675
2856
|
children: entry.content
|
|
2676
2857
|
}
|
|
@@ -2801,7 +2982,14 @@ function TerminalEntryRenderer({
|
|
|
2801
2982
|
{
|
|
2802
2983
|
summary: `${entry.sources.length} source${entry.sources.length !== 1 ? "s" : ""}`,
|
|
2803
2984
|
defaultExpanded: false,
|
|
2804
|
-
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1 py-1", children: entry.sources.map((src) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2985
|
+
children: /* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-1 py-1", children: entry.sources.map((src) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2986
|
+
SourceCard,
|
|
2987
|
+
{
|
|
2988
|
+
source: src,
|
|
2989
|
+
onActivate: onSourceActivate ? () => onSourceActivate(src, entry) : void 0
|
|
2990
|
+
},
|
|
2991
|
+
src.id
|
|
2992
|
+
)) })
|
|
2805
2993
|
}
|
|
2806
2994
|
)
|
|
2807
2995
|
}
|
|
@@ -2821,11 +3009,11 @@ function TerminalEntryRenderer({
|
|
|
2821
3009
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "font-medium text-sm", style: { color: t.success }, children: "Actions" }),
|
|
2822
3010
|
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs", style: { color: t.textMuted }, children: "click to execute" })
|
|
2823
3011
|
] }),
|
|
2824
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2", children: entry.suggested_actions.map((
|
|
3012
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "grid grid-cols-1 gap-2", children: entry.suggested_actions.map((action2, idx) => /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
2825
3013
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2826
3014
|
InteractiveActionCard,
|
|
2827
3015
|
{
|
|
2828
|
-
action,
|
|
3016
|
+
action: action2,
|
|
2829
3017
|
graphqlUrl: config.graphqlUrl,
|
|
2830
3018
|
authToken: authToken || "",
|
|
2831
3019
|
onExecute: (updatedAction) => {
|
|
@@ -2834,15 +3022,15 @@ function TerminalEntryRenderer({
|
|
|
2834
3022
|
}
|
|
2835
3023
|
}
|
|
2836
3024
|
),
|
|
2837
|
-
|
|
3025
|
+
action2.approval && /* @__PURE__ */ jsxRuntime.jsx(
|
|
2838
3026
|
ApprovalTracker,
|
|
2839
3027
|
{
|
|
2840
|
-
approval:
|
|
3028
|
+
approval: action2.approval,
|
|
2841
3029
|
currentUserId: currentUser?.entity_id,
|
|
2842
3030
|
onApprove: () => {
|
|
2843
3031
|
window.dispatchEvent(
|
|
2844
3032
|
new CustomEvent("terminal-approval-decision", {
|
|
2845
|
-
detail: { action, decision: "approved", entity_id: currentUser?.entity_id },
|
|
3033
|
+
detail: { action: action2, decision: "approved", entity_id: currentUser?.entity_id },
|
|
2846
3034
|
bubbles: true
|
|
2847
3035
|
})
|
|
2848
3036
|
);
|
|
@@ -2850,7 +3038,7 @@ function TerminalEntryRenderer({
|
|
|
2850
3038
|
onReject: () => {
|
|
2851
3039
|
window.dispatchEvent(
|
|
2852
3040
|
new CustomEvent("terminal-approval-decision", {
|
|
2853
|
-
detail: { action, decision: "rejected", entity_id: currentUser?.entity_id },
|
|
3041
|
+
detail: { action: action2, decision: "rejected", entity_id: currentUser?.entity_id },
|
|
2854
3042
|
bubbles: true
|
|
2855
3043
|
})
|
|
2856
3044
|
);
|
|
@@ -2898,9 +3086,10 @@ function TerminalEntryRenderer({
|
|
|
2898
3086
|
] });
|
|
2899
3087
|
const isTurnStart = !!prevEntry && isCommand && prevEntry.type !== "system";
|
|
2900
3088
|
const defaultRender = () => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `${isGrouped ? "" : "mb-5"} ${isTurnStart ? "mt-6" : ""}`, children: [
|
|
2901
|
-
beforeWidgets.map((w) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
2902
|
-
replaceWidget ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
2903
|
-
afterWidgets.map((w) => /* @__PURE__ */ jsxRuntime.jsx(
|
|
3089
|
+
beforeWidgets.map((w) => /* @__PURE__ */ jsxRuntime.jsx(React15__default.default.Fragment, { children: w.render({ entry, index }) }, w.name)),
|
|
3090
|
+
replaceWidget ? /* @__PURE__ */ jsxRuntime.jsx(React15__default.default.Fragment, { children: replaceWidget.render({ entry, index }) }, replaceWidget.name) : builtInContent,
|
|
3091
|
+
afterWidgets.map((w) => /* @__PURE__ */ jsxRuntime.jsx(React15__default.default.Fragment, { children: w.render({ entry, index }) }, w.name)),
|
|
3092
|
+
/* @__PURE__ */ jsxRuntime.jsx(AgentCompletionNotice, { completion: entry.metadata?.completion }),
|
|
2904
3093
|
renderEntryExtra?.(entry, index)
|
|
2905
3094
|
] });
|
|
2906
3095
|
if (renderEntry) {
|
|
@@ -2909,20 +3098,23 @@ function TerminalEntryRenderer({
|
|
|
2909
3098
|
}
|
|
2910
3099
|
return defaultRender();
|
|
2911
3100
|
}
|
|
3101
|
+
|
|
3102
|
+
// src/types/terminal.types.ts
|
|
3103
|
+
var DEFAULT_AGENT_LABEL = "YieldFabric Agent";
|
|
2912
3104
|
function LiveKGBridge({ progressState, onLiveKGUpdate }) {
|
|
2913
|
-
const onUpdateRef =
|
|
3105
|
+
const onUpdateRef = React15.useRef(onLiveKGUpdate);
|
|
2914
3106
|
onUpdateRef.current = onLiveKGUpdate;
|
|
2915
|
-
const prevGkgRef =
|
|
3107
|
+
const prevGkgRef = React15.useRef(null);
|
|
2916
3108
|
const gkg = progressState?.genericKG;
|
|
2917
|
-
|
|
3109
|
+
React15.useEffect(() => {
|
|
2918
3110
|
if (!gkg || !onUpdateRef.current) return;
|
|
2919
3111
|
if (gkg !== prevGkgRef.current) {
|
|
2920
3112
|
prevGkgRef.current = gkg;
|
|
2921
3113
|
onUpdateRef.current(gkg);
|
|
2922
3114
|
}
|
|
2923
3115
|
}, [gkg]);
|
|
2924
|
-
const hasEmitted =
|
|
2925
|
-
|
|
3116
|
+
const hasEmitted = React15.useRef(false);
|
|
3117
|
+
React15.useEffect(() => {
|
|
2926
3118
|
if (progressState && !hasEmitted.current && !gkg && onUpdateRef.current) {
|
|
2927
3119
|
if (!prevGkgRef.current) {
|
|
2928
3120
|
hasEmitted.current = true;
|
|
@@ -2937,14 +3129,17 @@ function TerminalShell({
|
|
|
2937
3129
|
className = "",
|
|
2938
3130
|
style,
|
|
2939
3131
|
showHeader = true,
|
|
3132
|
+
agentLabel = DEFAULT_AGENT_LABEL,
|
|
2940
3133
|
focusInput,
|
|
2941
3134
|
setTerminalHistory,
|
|
2942
3135
|
terminalBodyRef,
|
|
2943
3136
|
workingGroupContext,
|
|
3137
|
+
showWorkingGroupBanner = true,
|
|
2944
3138
|
progressState,
|
|
2945
3139
|
streamTransparency,
|
|
2946
3140
|
streamNowMs,
|
|
2947
3141
|
isExecuting,
|
|
3142
|
+
showBusyIndicator,
|
|
2948
3143
|
handleCancelReasoning,
|
|
2949
3144
|
onViewKnowledgeGraph,
|
|
2950
3145
|
onLiveKGUpdate,
|
|
@@ -2962,6 +3157,9 @@ function TerminalShell({
|
|
|
2962
3157
|
className: `border-0 flex flex-col ${className}`,
|
|
2963
3158
|
style: { minHeight: "300px", borderRadius: "12px", backgroundColor: "transparent", ...style },
|
|
2964
3159
|
onClick: () => {
|
|
3160
|
+
if (typeof window !== "undefined" && window.matchMedia?.("(pointer: coarse)").matches) {
|
|
3161
|
+
return;
|
|
3162
|
+
}
|
|
2965
3163
|
const sel = window.getSelection();
|
|
2966
3164
|
if (!sel || sel.toString().length === 0) focusInput();
|
|
2967
3165
|
},
|
|
@@ -2980,7 +3178,7 @@ function TerminalShell({
|
|
|
2980
3178
|
"button",
|
|
2981
3179
|
{
|
|
2982
3180
|
onClick: () => setTerminalHistory([
|
|
2983
|
-
{ type: "system", content:
|
|
3181
|
+
{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() },
|
|
2984
3182
|
{ type: "system", content: "Terminal cleared.", timestamp: /* @__PURE__ */ new Date() }
|
|
2985
3183
|
]),
|
|
2986
3184
|
className: "hover:opacity-80",
|
|
@@ -2998,7 +3196,7 @@ function TerminalShell({
|
|
|
2998
3196
|
className: "p-6 flex-1 overflow-y-auto scrollbar-thin scrollbar-thumb-gray-700 scrollbar-track-transparent",
|
|
2999
3197
|
style: { minHeight: "200px", display: "flex", flexDirection: "column", backgroundColor: "transparent" },
|
|
3000
3198
|
children: [
|
|
3001
|
-
workingGroupContext && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3199
|
+
workingGroupContext && showWorkingGroupBanner && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3002
3200
|
"div",
|
|
3003
3201
|
{
|
|
3004
3202
|
className: "mb-3 ml-1 mr-1 px-3 py-2 rounded-md text-xs flex items-center justify-between",
|
|
@@ -3023,7 +3221,7 @@ function TerminalShell({
|
|
|
3023
3221
|
}
|
|
3024
3222
|
),
|
|
3025
3223
|
/* @__PURE__ */ jsxRuntime.jsx(LiveKGBridge, { progressState, onLiveKGUpdate }),
|
|
3026
|
-
isExecuting && !progressState && /* @__PURE__ */ jsxRuntime.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: [
|
|
3224
|
+
isExecuting && !progressState && showBusyIndicator !== false && /* @__PURE__ */ jsxRuntime.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: [
|
|
3027
3225
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex space-x-1", children: [
|
|
3028
3226
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 rounded-full animate-pulse", style: { backgroundColor: t.info } }),
|
|
3029
3227
|
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-2 rounded-full animate-pulse", style: { backgroundColor: t.info, animationDelay: "150ms" } }),
|
|
@@ -3039,9 +3237,9 @@ function TerminalShell({
|
|
|
3039
3237
|
}
|
|
3040
3238
|
function KGScopeDropdown({ items, onSelect, compact = false }) {
|
|
3041
3239
|
const t = useTheme();
|
|
3042
|
-
const [open, setOpen] =
|
|
3043
|
-
const ref =
|
|
3044
|
-
|
|
3240
|
+
const [open, setOpen] = React15.useState(false);
|
|
3241
|
+
const ref = React15.useRef(null);
|
|
3242
|
+
React15.useEffect(() => {
|
|
3045
3243
|
if (!open) return;
|
|
3046
3244
|
const handleClick = (e) => {
|
|
3047
3245
|
if (ref.current && !ref.current.contains(e.target)) setOpen(false);
|
|
@@ -3153,11 +3351,24 @@ function splitInputByMentions(command, knownMentionNames) {
|
|
|
3153
3351
|
segments.push({ kind: "text", value: command.slice(cursor) });
|
|
3154
3352
|
return segments;
|
|
3155
3353
|
}
|
|
3354
|
+
var INPUT_MAX_HEIGHT = 120;
|
|
3355
|
+
function fitToContent(input) {
|
|
3356
|
+
resetHeight(input);
|
|
3357
|
+
if (!input.value.trim()) return;
|
|
3358
|
+
const needed = input.scrollHeight;
|
|
3359
|
+
input.style.height = `${Math.min(needed, INPUT_MAX_HEIGHT)}px`;
|
|
3360
|
+
if (needed > INPUT_MAX_HEIGHT) input.style.overflowY = "auto";
|
|
3361
|
+
}
|
|
3362
|
+
function resetHeight(input) {
|
|
3363
|
+
input.style.height = "auto";
|
|
3364
|
+
input.style.overflowY = "";
|
|
3365
|
+
}
|
|
3156
3366
|
function TerminalInputBar({
|
|
3157
3367
|
inputRef,
|
|
3158
3368
|
fileInputRef,
|
|
3159
3369
|
currentCommand,
|
|
3160
3370
|
isExecuting,
|
|
3371
|
+
disabled = false,
|
|
3161
3372
|
placeholder = "Ask anything...",
|
|
3162
3373
|
onInputChange,
|
|
3163
3374
|
onKeyDown,
|
|
@@ -3180,47 +3391,54 @@ function TerminalInputBar({
|
|
|
3180
3391
|
inputBarExtra,
|
|
3181
3392
|
modeSelector,
|
|
3182
3393
|
compactToolbar = false,
|
|
3183
|
-
submitTitle = "Send"
|
|
3394
|
+
submitTitle = "Send",
|
|
3395
|
+
autoFocus = true
|
|
3184
3396
|
}) {
|
|
3185
3397
|
const t = useTheme();
|
|
3398
|
+
React15.useEffect(() => {
|
|
3399
|
+
if (!autoFocus) return;
|
|
3400
|
+
inputRef.current?.focus({ preventScroll: true });
|
|
3401
|
+
}, []);
|
|
3402
|
+
const [focused, setFocused] = React15__default.default.useState(false);
|
|
3403
|
+
const chipsVisible = focused || currentCommand.trim().length > 0;
|
|
3186
3404
|
const isLight = t.bgRaised === "#ffffff";
|
|
3187
3405
|
const hasCommand = Boolean(currentCommand.trim());
|
|
3188
|
-
const placeholderColor = isLight ?
|
|
3189
|
-
const panelBorder = isLight ?
|
|
3190
|
-
const panelBg =
|
|
3191
|
-
const toolbarButtonBg = isLight ? "rgba(
|
|
3192
|
-
const toolbarButtonHover = isLight ?
|
|
3193
|
-
const toolbarButtonText = isLight ?
|
|
3406
|
+
const placeholderColor = isLight ? t.textMuted : "rgba(255,255,255,0.52)";
|
|
3407
|
+
const panelBorder = isLight ? t.border : "rgba(255,255,255,0.10)";
|
|
3408
|
+
const panelBg = t.bgInput;
|
|
3409
|
+
const toolbarButtonBg = isLight ? "rgba(255,255,255,0.72)" : "rgba(255,255,255,0.05)";
|
|
3410
|
+
const toolbarButtonHover = isLight ? t.bgRaised : "rgba(255,255,255,0.14)";
|
|
3411
|
+
const toolbarButtonText = isLight ? t.textSecondary : "rgba(255,255,255,0.52)";
|
|
3194
3412
|
const toolbarButtonStyle = {
|
|
3195
3413
|
backgroundColor: toolbarButtonBg,
|
|
3196
|
-
border: `1px solid ${isLight ?
|
|
3414
|
+
border: `1px solid ${isLight ? t.border : "rgba(255,255,255,0.08)"}`,
|
|
3197
3415
|
boxShadow: "none",
|
|
3198
3416
|
color: toolbarButtonText
|
|
3199
3417
|
};
|
|
3200
|
-
const toolbarRef =
|
|
3201
|
-
const [compact, setCompact] =
|
|
3202
|
-
|
|
3418
|
+
const toolbarRef = React15.useRef(null);
|
|
3419
|
+
const [compact, setCompact] = React15.useState(false);
|
|
3420
|
+
React15.useEffect(() => {
|
|
3203
3421
|
if (compactToolbar) {
|
|
3204
3422
|
setCompact(true);
|
|
3205
3423
|
return;
|
|
3206
3424
|
}
|
|
3207
3425
|
const el = toolbarRef.current;
|
|
3208
3426
|
if (!el || typeof ResizeObserver === "undefined") return;
|
|
3427
|
+
let lastWidth = -1;
|
|
3209
3428
|
const ro = new ResizeObserver((entries) => {
|
|
3210
|
-
const w = entries[0]?.contentRect.width ?? 0;
|
|
3429
|
+
const w = Math.round(entries[0]?.contentRect.width ?? 0);
|
|
3430
|
+
if (w === lastWidth) return;
|
|
3431
|
+
lastWidth = w;
|
|
3211
3432
|
setCompact((prev) => prev ? w < 520 : w < 480);
|
|
3212
3433
|
});
|
|
3213
3434
|
ro.observe(el);
|
|
3214
3435
|
return () => ro.disconnect();
|
|
3215
3436
|
}, [compactToolbar]);
|
|
3216
3437
|
const toolbarIsCompact = compactToolbar || compact;
|
|
3217
|
-
|
|
3438
|
+
React15.useEffect(() => {
|
|
3218
3439
|
const input = inputRef.current;
|
|
3219
3440
|
if (!input) return;
|
|
3220
|
-
input
|
|
3221
|
-
if (currentCommand.trim()) {
|
|
3222
|
-
input.style.height = Math.min(input.scrollHeight, 120) + "px";
|
|
3223
|
-
}
|
|
3441
|
+
fitToContent(input);
|
|
3224
3442
|
}, [currentCommand, inputRef]);
|
|
3225
3443
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3226
3444
|
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `.yf-input-bar::placeholder { color: ${placeholderColor}; }` }),
|
|
@@ -3262,16 +3480,16 @@ function TerminalInputBar({
|
|
|
3262
3480
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3263
3481
|
"div",
|
|
3264
3482
|
{
|
|
3265
|
-
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" : ""}`,
|
|
3483
|
+
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" : ""}`,
|
|
3266
3484
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3267
3485
|
"div",
|
|
3268
3486
|
{
|
|
3269
|
-
className:
|
|
3487
|
+
className: `rounded-xl border px-3 transition-[box-shadow,border-color] sm:px-4 ${focused ? "yf-input-focused" : ""}`,
|
|
3270
3488
|
style: {
|
|
3271
3489
|
backgroundColor: panelBg,
|
|
3272
3490
|
backdropFilter: "blur(18px)",
|
|
3273
|
-
borderColor: panelBorder,
|
|
3274
|
-
boxShadow: isLight ? "0 18px 70px -38px rgba(30,30,58,0.45)" : "0 18px 70px -38px rgba(0,0,0,0.95)",
|
|
3491
|
+
borderColor: focused ? t.primary : panelBorder,
|
|
3492
|
+
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)",
|
|
3275
3493
|
WebkitBackdropFilter: "blur(18px)"
|
|
3276
3494
|
},
|
|
3277
3495
|
children: [
|
|
@@ -3341,8 +3559,7 @@ function TerminalInputBar({
|
|
|
3341
3559
|
onInputChange(`${prefixRaw}${e.target.value}`);
|
|
3342
3560
|
onCaretChange?.(prefixRaw.length + (e.target.selectionStart ?? e.target.value.length));
|
|
3343
3561
|
onTyping?.();
|
|
3344
|
-
e.target
|
|
3345
|
-
e.target.style.height = Math.min(e.target.scrollHeight, 120) + "px";
|
|
3562
|
+
fitToContent(e.target);
|
|
3346
3563
|
},
|
|
3347
3564
|
onSelect: (e) => {
|
|
3348
3565
|
const ta = e.currentTarget;
|
|
@@ -3369,17 +3586,19 @@ function TerminalInputBar({
|
|
|
3369
3586
|
if (e.key === "Enter" && !e.shiftKey && !e.defaultPrevented) {
|
|
3370
3587
|
e.preventDefault();
|
|
3371
3588
|
onSubmit();
|
|
3372
|
-
if (inputRef.current) inputRef.current
|
|
3589
|
+
if (inputRef.current) resetHeight(inputRef.current);
|
|
3373
3590
|
}
|
|
3374
3591
|
},
|
|
3375
|
-
disabled: isExecuting,
|
|
3592
|
+
disabled: isExecuting || disabled,
|
|
3593
|
+
"aria-label": placeholder ?? "Message",
|
|
3376
3594
|
placeholder: isExecuting ? "Processing..." : placeholder,
|
|
3377
3595
|
rows: 1,
|
|
3378
|
-
className: "yf-input-bar flex-1 min-w-[100px] bg-transparent focus:outline-none text-[16px] leading-6 resize-none overflow-hidden sm:text-
|
|
3596
|
+
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",
|
|
3597
|
+
onFocus: () => setFocused(true),
|
|
3598
|
+
onBlur: () => setFocused(false),
|
|
3379
3599
|
style: { color: t.text, caretColor: t.cursor },
|
|
3380
3600
|
spellCheck: false,
|
|
3381
3601
|
autoComplete: "off",
|
|
3382
|
-
autoFocus: true,
|
|
3383
3602
|
tabIndex: 0
|
|
3384
3603
|
}
|
|
3385
3604
|
)
|
|
@@ -3388,67 +3607,78 @@ function TerminalInputBar({
|
|
|
3388
3607
|
"button",
|
|
3389
3608
|
{
|
|
3390
3609
|
type: "submit",
|
|
3391
|
-
disabled: !hasCommand || isExecuting,
|
|
3392
|
-
className: "h-10 w-10 rounded-xl disabled:opacity-
|
|
3610
|
+
disabled: !hasCommand || isExecuting || disabled,
|
|
3611
|
+
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",
|
|
3393
3612
|
style: {
|
|
3394
|
-
backgroundColor: hasCommand ?
|
|
3395
|
-
|
|
3613
|
+
backgroundColor: hasCommand ? t.primary : isLight ? t.bgRaisedAlt : "rgba(255,255,255,0.08)",
|
|
3614
|
+
// `textInverse` is the theme's "text on a filled button".
|
|
3615
|
+
// `bgBase` was used here before and is `transparent` in
|
|
3616
|
+
// every app theme — so the chevron vanished the moment
|
|
3617
|
+
// there was something to send.
|
|
3618
|
+
color: hasCommand ? t.textInverse : isLight ? t.textMuted : "rgba(255,255,255,0.72)"
|
|
3396
3619
|
},
|
|
3397
3620
|
onMouseEnter: (e) => {
|
|
3398
|
-
|
|
3621
|
+
if (hasCommand) {
|
|
3622
|
+
e.currentTarget.style.filter = "brightness(1.15)";
|
|
3623
|
+
} else {
|
|
3624
|
+
e.currentTarget.style.backgroundColor = toolbarButtonHover;
|
|
3625
|
+
}
|
|
3399
3626
|
},
|
|
3400
3627
|
onMouseLeave: (e) => {
|
|
3401
|
-
e.currentTarget.style.
|
|
3628
|
+
e.currentTarget.style.filter = "";
|
|
3629
|
+
e.currentTarget.style.backgroundColor = hasCommand ? t.primary : isLight ? t.bgRaisedAlt : "rgba(255,255,255,0.08)";
|
|
3402
3630
|
},
|
|
3403
3631
|
title: submitTitle,
|
|
3404
3632
|
"aria-label": submitTitle,
|
|
3405
|
-
children: isExecuting ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full animate-spin", style: { border: `1.5px solid ${hasCommand ?
|
|
3633
|
+
children: isExecuting ? /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-3 h-3 rounded-full animate-spin", style: { border: `1.5px solid ${hasCommand ? t.textInverse : t.textMuted}`, borderTopColor: "transparent" } }) : /* @__PURE__ */ jsxRuntime.jsx(lucideReact.ChevronRight, { className: "h-5 w-5 sm:h-4 sm:w-4" })
|
|
3406
3634
|
}
|
|
3407
3635
|
)
|
|
3408
3636
|
] });
|
|
3409
3637
|
})(),
|
|
3410
3638
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { ref: toolbarRef, className: "flex items-center justify-between pt-2.5 gap-2", children: [
|
|
3411
|
-
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-[
|
|
3412
|
-
/* @__PURE__ */ jsxRuntime.
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
3418
|
-
|
|
3419
|
-
|
|
3420
|
-
|
|
3421
|
-
|
|
3422
|
-
|
|
3423
|
-
|
|
3424
|
-
e
|
|
3425
|
-
|
|
3426
|
-
|
|
3427
|
-
e
|
|
3428
|
-
|
|
3429
|
-
|
|
3430
|
-
|
|
3431
|
-
|
|
3432
|
-
|
|
3433
|
-
|
|
3434
|
-
|
|
3435
|
-
|
|
3436
|
-
|
|
3437
|
-
|
|
3438
|
-
|
|
3439
|
-
|
|
3440
|
-
|
|
3441
|
-
|
|
3442
|
-
|
|
3443
|
-
|
|
3444
|
-
e
|
|
3445
|
-
|
|
3446
|
-
|
|
3447
|
-
e
|
|
3448
|
-
|
|
3449
|
-
|
|
3450
|
-
|
|
3451
|
-
|
|
3639
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-[11px] min-w-0 flex-wrap", children: [
|
|
3640
|
+
chipsVisible && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3641
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3642
|
+
"button",
|
|
3643
|
+
{
|
|
3644
|
+
type: "button",
|
|
3645
|
+
onClick: () => {
|
|
3646
|
+
onInputChange("@");
|
|
3647
|
+
inputRef.current?.focus();
|
|
3648
|
+
},
|
|
3649
|
+
title: "Insert @ mention",
|
|
3650
|
+
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`,
|
|
3651
|
+
style: toolbarButtonStyle,
|
|
3652
|
+
onMouseEnter: (e) => {
|
|
3653
|
+
e.currentTarget.style.backgroundColor = toolbarButtonHover;
|
|
3654
|
+
},
|
|
3655
|
+
onMouseLeave: (e) => {
|
|
3656
|
+
e.currentTarget.style.backgroundColor = toolbarButtonBg;
|
|
3657
|
+
},
|
|
3658
|
+
children: toolbarIsCompact ? "@" : "@ mention"
|
|
3659
|
+
}
|
|
3660
|
+
),
|
|
3661
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3662
|
+
"button",
|
|
3663
|
+
{
|
|
3664
|
+
type: "button",
|
|
3665
|
+
onClick: () => {
|
|
3666
|
+
onInputChange("/");
|
|
3667
|
+
inputRef.current?.focus();
|
|
3668
|
+
},
|
|
3669
|
+
title: "Insert / command",
|
|
3670
|
+
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`,
|
|
3671
|
+
style: toolbarButtonStyle,
|
|
3672
|
+
onMouseEnter: (e) => {
|
|
3673
|
+
e.currentTarget.style.backgroundColor = toolbarButtonHover;
|
|
3674
|
+
},
|
|
3675
|
+
onMouseLeave: (e) => {
|
|
3676
|
+
e.currentTarget.style.backgroundColor = toolbarButtonBg;
|
|
3677
|
+
},
|
|
3678
|
+
children: toolbarIsCompact ? "/" : "/ commands"
|
|
3679
|
+
}
|
|
3680
|
+
)
|
|
3681
|
+
] }),
|
|
3452
3682
|
availableKGs && availableKGs.length > 0 && /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: activeKGScope ? /* @__PURE__ */ jsxRuntime.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: [
|
|
3453
3683
|
/* @__PURE__ */ jsxRuntime.jsxs("svg", { className: "w-3 h-3 opacity-60 shrink-0", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2, children: [
|
|
3454
3684
|
/* @__PURE__ */ jsxRuntime.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" }),
|
|
@@ -3462,7 +3692,7 @@ function TerminalInputBar({
|
|
|
3462
3692
|
] }),
|
|
3463
3693
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => onKGScopeChange?.(null), className: "ml-0.5 opacity-40 hover:opacity-100 transition-opacity", children: "\u2715" })
|
|
3464
3694
|
] }) : /* @__PURE__ */ jsxRuntime.jsx(KGScopeDropdown, { items: availableKGs, onSelect: (scope) => onKGScopeChange?.(scope), compact: toolbarIsCompact }) }),
|
|
3465
|
-
modeSelector ?? (onReasoningModeChange && /* @__PURE__ */ jsxRuntime.jsx(ReasoningModeSelector, { current: reasoningMode || null, onChange: onReasoningModeChange, compact: toolbarIsCompact }))
|
|
3695
|
+
chipsVisible && (modeSelector ?? (onReasoningModeChange && /* @__PURE__ */ jsxRuntime.jsx(ReasoningModeSelector, { current: reasoningMode || null, onChange: onReasoningModeChange, compact: toolbarIsCompact })))
|
|
3466
3696
|
] }),
|
|
3467
3697
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-shrink-0", children: [
|
|
3468
3698
|
inputBarExtra,
|
|
@@ -3470,8 +3700,8 @@ function TerminalInputBar({
|
|
|
3470
3700
|
"button",
|
|
3471
3701
|
{
|
|
3472
3702
|
type: "button",
|
|
3473
|
-
disabled: isExecuting,
|
|
3474
|
-
className: "h-8 w-8 rounded-xl disabled:opacity-30 disabled:cursor-not-allowed flex items-center justify-center transition-all duration-200",
|
|
3703
|
+
disabled: isExecuting || disabled,
|
|
3704
|
+
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",
|
|
3475
3705
|
style: toolbarButtonStyle,
|
|
3476
3706
|
title: "Upload files",
|
|
3477
3707
|
onClick: () => fileInputRef.current?.click(),
|
|
@@ -3488,8 +3718,8 @@ function TerminalInputBar({
|
|
|
3488
3718
|
"button",
|
|
3489
3719
|
{
|
|
3490
3720
|
type: "button",
|
|
3491
|
-
disabled: isExecuting,
|
|
3492
|
-
className: "h-8 w-8 rounded-xl disabled:opacity-30 disabled:cursor-not-allowed flex items-center justify-center transition-all duration-200",
|
|
3721
|
+
disabled: isExecuting || disabled,
|
|
3722
|
+
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",
|
|
3493
3723
|
style: toolbarButtonStyle,
|
|
3494
3724
|
title: "List files",
|
|
3495
3725
|
onClick: () => onListFilesCommand(),
|
|
@@ -3575,13 +3805,13 @@ function SlashMentionPicker({ candidates, selectedIndex, onPick }) {
|
|
|
3575
3805
|
);
|
|
3576
3806
|
}
|
|
3577
3807
|
function useCommandHistory() {
|
|
3578
|
-
const [commandHistory, setCommandHistory] =
|
|
3579
|
-
const [historyIndex, setHistoryIndex] =
|
|
3580
|
-
const pushCommand =
|
|
3808
|
+
const [commandHistory, setCommandHistory] = React15.useState([]);
|
|
3809
|
+
const [historyIndex, setHistoryIndex] = React15.useState(-1);
|
|
3810
|
+
const pushCommand = React15.useCallback((cmd) => {
|
|
3581
3811
|
setCommandHistory((prev) => [...prev, cmd]);
|
|
3582
3812
|
setHistoryIndex(-1);
|
|
3583
3813
|
}, []);
|
|
3584
|
-
const navigateUp =
|
|
3814
|
+
const navigateUp = React15.useCallback(
|
|
3585
3815
|
(setCurrentCommand) => {
|
|
3586
3816
|
if (commandHistory.length === 0) return;
|
|
3587
3817
|
const newIndex = historyIndex === -1 ? commandHistory.length - 1 : Math.max(0, historyIndex - 1);
|
|
@@ -3590,7 +3820,7 @@ function useCommandHistory() {
|
|
|
3590
3820
|
},
|
|
3591
3821
|
[commandHistory, historyIndex]
|
|
3592
3822
|
);
|
|
3593
|
-
const navigateDown =
|
|
3823
|
+
const navigateDown = React15.useCallback(
|
|
3594
3824
|
(setCurrentCommand) => {
|
|
3595
3825
|
if (historyIndex === -1) return;
|
|
3596
3826
|
const newIndex = historyIndex + 1;
|
|
@@ -3604,21 +3834,20 @@ function useCommandHistory() {
|
|
|
3604
3834
|
},
|
|
3605
3835
|
[commandHistory, historyIndex]
|
|
3606
3836
|
);
|
|
3607
|
-
const resetIndex =
|
|
3837
|
+
const resetIndex = React15.useCallback(() => {
|
|
3608
3838
|
setHistoryIndex(-1);
|
|
3609
3839
|
}, []);
|
|
3610
3840
|
return { commandHistory, historyIndex, pushCommand, navigateUp, navigateDown, resetIndex };
|
|
3611
3841
|
}
|
|
3612
|
-
function useFocusManagement() {
|
|
3613
|
-
const inputRef =
|
|
3614
|
-
const focusInput =
|
|
3842
|
+
function useFocusManagement(autoFocus = true) {
|
|
3843
|
+
const inputRef = React15.useRef(null);
|
|
3844
|
+
const focusInput = React15.useCallback(() => {
|
|
3615
3845
|
const selection = window.getSelection();
|
|
3616
3846
|
if (selection && selection.toString().length > 0) return;
|
|
3617
|
-
|
|
3618
|
-
inputRef.current.focus();
|
|
3619
|
-
}
|
|
3847
|
+
inputRef.current?.focus({ preventScroll: true });
|
|
3620
3848
|
}, []);
|
|
3621
|
-
|
|
3849
|
+
React15.useEffect(() => {
|
|
3850
|
+
if (!autoFocus) return;
|
|
3622
3851
|
const timer = setTimeout(focusInput, 100);
|
|
3623
3852
|
const handleVisibilityChange = () => {
|
|
3624
3853
|
if (!document.hidden) {
|
|
@@ -3630,11 +3859,12 @@ function useFocusManagement() {
|
|
|
3630
3859
|
clearTimeout(timer);
|
|
3631
3860
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
3632
3861
|
};
|
|
3633
|
-
}, [focusInput]);
|
|
3862
|
+
}, [focusInput, autoFocus]);
|
|
3634
3863
|
return { inputRef, focusInput };
|
|
3635
3864
|
}
|
|
3636
3865
|
function useStreamingChat({
|
|
3637
3866
|
config,
|
|
3867
|
+
authToken,
|
|
3638
3868
|
onStreamRequest,
|
|
3639
3869
|
reasoningMode,
|
|
3640
3870
|
setTerminalHistory,
|
|
@@ -3643,35 +3873,47 @@ function useStreamingChat({
|
|
|
3643
3873
|
currentUser,
|
|
3644
3874
|
sourceKGNodes
|
|
3645
3875
|
}) {
|
|
3646
|
-
const
|
|
3876
|
+
const authTokenRef = React15.useRef(authToken);
|
|
3877
|
+
authTokenRef.current = authToken;
|
|
3878
|
+
const sourceKGNodesRef = React15.useRef(sourceKGNodes);
|
|
3647
3879
|
sourceKGNodesRef.current = sourceKGNodes;
|
|
3648
|
-
const reasoningModeRef =
|
|
3880
|
+
const reasoningModeRef = React15.useRef(reasoningMode);
|
|
3649
3881
|
reasoningModeRef.current = reasoningMode;
|
|
3650
|
-
const [isExecuting, setIsExecuting] =
|
|
3651
|
-
const
|
|
3652
|
-
const [
|
|
3653
|
-
const [
|
|
3654
|
-
const [
|
|
3655
|
-
const [
|
|
3656
|
-
const [
|
|
3657
|
-
const [
|
|
3658
|
-
const [
|
|
3659
|
-
const [
|
|
3660
|
-
const
|
|
3661
|
-
const
|
|
3662
|
-
const
|
|
3663
|
-
const
|
|
3664
|
-
const
|
|
3882
|
+
const [isExecuting, setIsExecuting] = React15.useState(false);
|
|
3883
|
+
const turnSequence = React15.useRef(0);
|
|
3884
|
+
const [isStreaming, setIsStreaming] = React15.useState(false);
|
|
3885
|
+
const [progressState, setProgressState] = React15.useState(null);
|
|
3886
|
+
const [activityEvents, setActivityEvents] = React15.useState([]);
|
|
3887
|
+
const [streamTransparency, setStreamTransparency] = React15.useState(null);
|
|
3888
|
+
const [streamNowMs, setStreamNowMs] = React15.useState(Date.now());
|
|
3889
|
+
const [collaborationState, setCollaborationState] = React15.useState(null);
|
|
3890
|
+
const [liveKgId, setLiveKgId] = React15.useState(null);
|
|
3891
|
+
const [liveRunId, setLiveRunId] = React15.useState(null);
|
|
3892
|
+
const [liveThreadId, setLiveThreadId] = React15.useState(null);
|
|
3893
|
+
const progressStateRef = React15.useRef(null);
|
|
3894
|
+
const lastExecutedCommand = React15.useRef(null);
|
|
3895
|
+
const isProcessingRef = React15.useRef(false);
|
|
3896
|
+
const currentStreamingLineId = React15.useRef(null);
|
|
3897
|
+
const liveRunIdRef = React15.useRef(null);
|
|
3665
3898
|
liveRunIdRef.current = liveRunId;
|
|
3666
|
-
|
|
3899
|
+
const mountEpoch = React15.useRef(0);
|
|
3900
|
+
React15.useEffect(() => {
|
|
3901
|
+
const epoch = ++mountEpoch.current;
|
|
3902
|
+
return () => {
|
|
3903
|
+
void Promise.resolve().then(() => {
|
|
3904
|
+
if (mountEpoch.current === epoch) currentStreamingLineId.current = null;
|
|
3905
|
+
});
|
|
3906
|
+
};
|
|
3907
|
+
}, []);
|
|
3908
|
+
React15.useEffect(() => {
|
|
3667
3909
|
progressStateRef.current = progressState;
|
|
3668
3910
|
}, [progressState]);
|
|
3669
|
-
|
|
3911
|
+
React15.useEffect(() => {
|
|
3670
3912
|
if (!isExecuting && !isStreaming) return;
|
|
3671
3913
|
const t = setInterval(() => setStreamNowMs(Date.now()), 1e3);
|
|
3672
3914
|
return () => clearInterval(t);
|
|
3673
3915
|
}, [isExecuting, isStreaming]);
|
|
3674
|
-
const setStreamingLineSender =
|
|
3916
|
+
const setStreamingLineSender = React15.useCallback(
|
|
3675
3917
|
(lineId, sender) => {
|
|
3676
3918
|
setTerminalHistory((prev) => {
|
|
3677
3919
|
const idx = prev.findIndex((line) => line.id === lineId);
|
|
@@ -3684,7 +3926,7 @@ function useStreamingChat({
|
|
|
3684
3926
|
},
|
|
3685
3927
|
[setTerminalHistory]
|
|
3686
3928
|
);
|
|
3687
|
-
const updateStreamingLine =
|
|
3929
|
+
const updateStreamingLine = React15.useCallback(
|
|
3688
3930
|
(lineId, newContent, suggestions, suggestedActions, reasoningSnapshot, pipelineDraft, sources, kgId, runId) => {
|
|
3689
3931
|
setTerminalHistory((prev) => {
|
|
3690
3932
|
const idx = prev.findIndex((line) => line.id === lineId);
|
|
@@ -3706,7 +3948,7 @@ function useStreamingChat({
|
|
|
3706
3948
|
},
|
|
3707
3949
|
[setTerminalHistory]
|
|
3708
3950
|
);
|
|
3709
|
-
const resetStreamState =
|
|
3951
|
+
const resetStreamState = React15.useCallback(() => {
|
|
3710
3952
|
setIsStreaming(false);
|
|
3711
3953
|
setStreamTransparency(null);
|
|
3712
3954
|
setIsExecuting(false);
|
|
@@ -3715,46 +3957,55 @@ function useStreamingChat({
|
|
|
3715
3957
|
currentStreamingLineId.current = null;
|
|
3716
3958
|
setTimeout(() => focusInput(), 50);
|
|
3717
3959
|
}, [focusInput]);
|
|
3718
|
-
const
|
|
3719
|
-
|
|
3720
|
-
|
|
3721
|
-
|
|
3722
|
-
|
|
3723
|
-
|
|
3724
|
-
|
|
3725
|
-
|
|
3726
|
-
|
|
3727
|
-
|
|
3728
|
-
body: JSON.stringify({ kind: "guidance", content: message })
|
|
3729
|
-
});
|
|
3730
|
-
}
|
|
3731
|
-
await fetch(`${apiUrl}/pipelines/${runId}/input`, {
|
|
3732
|
-
method: "POST",
|
|
3733
|
-
headers: { "Content-Type": "application/json" },
|
|
3734
|
-
body: JSON.stringify({ kind: "proceed" })
|
|
3735
|
-
});
|
|
3736
|
-
} catch (e) {
|
|
3737
|
-
console.error("Failed to send pipeline input:", e);
|
|
3738
|
-
}
|
|
3739
|
-
},
|
|
3740
|
-
[config.agentsApiUrl]
|
|
3741
|
-
);
|
|
3742
|
-
const handleCancelReasoning = React12.useCallback(async () => {
|
|
3960
|
+
const postPipelineAction = React15.useCallback(async (runId, action2, body) => {
|
|
3961
|
+
const headers = config.getAuthHeaders?.() ?? (authTokenRef.current ? { Authorization: `Bearer ${authTokenRef.current}` } : {});
|
|
3962
|
+
const response = await fetch(`${config.agentsApiUrl || "http://localhost:3001"}/pipelines/${runId}/${action2}`, {
|
|
3963
|
+
method: "POST",
|
|
3964
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
3965
|
+
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
3966
|
+
});
|
|
3967
|
+
if (!response.ok) throw new Error(`The request was not accepted (${response.status}). Please try again.`);
|
|
3968
|
+
}, [config]);
|
|
3969
|
+
const handleHilSubmit = React15.useCallback(async (message) => {
|
|
3743
3970
|
const runId = liveRunIdRef.current;
|
|
3744
3971
|
if (!runId) return;
|
|
3745
|
-
const apiUrl = config.agentsApiUrl || "http://localhost:3001";
|
|
3746
|
-
setProgressState(null);
|
|
3747
|
-
resetStreamState();
|
|
3748
3972
|
try {
|
|
3749
|
-
await
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
});
|
|
3753
|
-
} catch (e) {
|
|
3754
|
-
console.error("Failed to cancel pipeline:", e);
|
|
3973
|
+
if (message.trim()) await postPipelineAction(runId, "input", { kind: "guidance", content: message });
|
|
3974
|
+
await postPipelineAction(runId, "input", { kind: "proceed" });
|
|
3975
|
+
} catch (error) {
|
|
3976
|
+
addTerminalLine("error", `Your input was not sent. ${error.message}`);
|
|
3755
3977
|
}
|
|
3756
|
-
}, [
|
|
3757
|
-
const
|
|
3978
|
+
}, [postPipelineAction, addTerminalLine]);
|
|
3979
|
+
const handleCancelReasoning = React15.useCallback(async () => {
|
|
3980
|
+
const runId = liveRunIdRef.current;
|
|
3981
|
+
if (!runId) return;
|
|
3982
|
+
try {
|
|
3983
|
+
await postPipelineAction(runId, "cancel");
|
|
3984
|
+
setProgressState(null);
|
|
3985
|
+
resetStreamState();
|
|
3986
|
+
addTerminalLine("info", "Stopped the analysis.");
|
|
3987
|
+
} catch (error) {
|
|
3988
|
+
addTerminalLine("error", `The analysis is still running. ${error.message}`);
|
|
3989
|
+
}
|
|
3990
|
+
}, [postPipelineAction, resetStreamState, addTerminalLine]);
|
|
3991
|
+
const settleAgentSteps = React15.useCallback(
|
|
3992
|
+
(lineId) => {
|
|
3993
|
+
setTerminalHistory((prev) => {
|
|
3994
|
+
const idx = prev.findIndex((line) => line.id === lineId);
|
|
3995
|
+
if (idx === -1) return prev;
|
|
3996
|
+
const meta = prev[idx].metadata;
|
|
3997
|
+
if (!meta?.agentStepsLive) return prev;
|
|
3998
|
+
const updated = [...prev];
|
|
3999
|
+
updated[idx] = {
|
|
4000
|
+
...updated[idx],
|
|
4001
|
+
metadata: { ...updated[idx].metadata || {}, agentStepsLive: false }
|
|
4002
|
+
};
|
|
4003
|
+
return updated;
|
|
4004
|
+
});
|
|
4005
|
+
},
|
|
4006
|
+
[setTerminalHistory]
|
|
4007
|
+
);
|
|
4008
|
+
const handleStreamingChat = React15.useCallback(
|
|
3758
4009
|
async (cmd) => {
|
|
3759
4010
|
if (isProcessingRef.current || !onStreamRequest) return;
|
|
3760
4011
|
if (lastExecutedCommand.current === cmd) return;
|
|
@@ -3765,8 +4016,9 @@ function useStreamingChat({
|
|
|
3765
4016
|
const startMs = Date.now();
|
|
3766
4017
|
setStreamTransparency({ startedAtMs: startMs, lastEventAtMs: startMs });
|
|
3767
4018
|
setActivityEvents([]);
|
|
3768
|
-
const
|
|
3769
|
-
const
|
|
4019
|
+
const turnKey = `${Date.now()}-${++turnSequence.current}`;
|
|
4020
|
+
const userCommandId = `${turnKey}:question`;
|
|
4021
|
+
const streamingLineId = `${turnKey}:answer`;
|
|
3770
4022
|
currentStreamingLineId.current = streamingLineId;
|
|
3771
4023
|
const userCommandEntry = {
|
|
3772
4024
|
id: userCommandId,
|
|
@@ -3792,14 +4044,14 @@ function useStreamingChat({
|
|
|
3792
4044
|
setTerminalHistory((prev) => [
|
|
3793
4045
|
...prev,
|
|
3794
4046
|
{
|
|
3795
|
-
id:
|
|
4047
|
+
id: `${turnKey}:before-question`,
|
|
3796
4048
|
type: "info",
|
|
3797
4049
|
content: "",
|
|
3798
4050
|
timestamp: /* @__PURE__ */ new Date()
|
|
3799
4051
|
},
|
|
3800
4052
|
userCommandEntry,
|
|
3801
4053
|
{
|
|
3802
|
-
id:
|
|
4054
|
+
id: `${turnKey}:before-answer`,
|
|
3803
4055
|
type: "info",
|
|
3804
4056
|
content: "",
|
|
3805
4057
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -3813,10 +4065,37 @@ function useStreamingChat({
|
|
|
3813
4065
|
let sources;
|
|
3814
4066
|
let kgId;
|
|
3815
4067
|
let runId;
|
|
4068
|
+
const steps = /* @__PURE__ */ new Map();
|
|
4069
|
+
const fail = (error) => {
|
|
4070
|
+
if (currentStreamingLineId.current !== streamingLineId) return;
|
|
4071
|
+
settleAgentSteps(streamingLineId);
|
|
4072
|
+
updateStreamingLine(
|
|
4073
|
+
streamingLineId,
|
|
4074
|
+
fullResponse,
|
|
4075
|
+
pageSuggestions,
|
|
4076
|
+
suggestedActions,
|
|
4077
|
+
progressStateRef.current ? captureReasoningSnapshot(progressStateRef.current, true) : void 0,
|
|
4078
|
+
pipelineDraft,
|
|
4079
|
+
sources,
|
|
4080
|
+
kgId,
|
|
4081
|
+
runId
|
|
4082
|
+
);
|
|
4083
|
+
setTerminalHistory((prev) => prev.map((entry) => entry.id === streamingLineId ? { ...entry, metadata: { ...entry.metadata, completion: { stop_reason: /connection|interrupt/i.test(error) ? "interrupted" : "failed" } } } : entry));
|
|
4084
|
+
addTerminalLine("error", error);
|
|
4085
|
+
setProgressState(null);
|
|
4086
|
+
resetStreamState();
|
|
4087
|
+
};
|
|
3816
4088
|
try {
|
|
3817
4089
|
await onStreamRequest(cmd, {
|
|
3818
4090
|
onChunk: (chunk) => {
|
|
4091
|
+
if (currentStreamingLineId.current !== streamingLineId) return;
|
|
4092
|
+
if (chunk.entryMetadata) {
|
|
4093
|
+
setTerminalHistory((prev) => prev.map((entry) => entry.id === streamingLineId ? { ...entry, metadata: { ...entry.metadata, ...chunk.entryMetadata } } : entry));
|
|
4094
|
+
}
|
|
3819
4095
|
const eventMs = Date.now();
|
|
4096
|
+
if (chunk.completion) {
|
|
4097
|
+
setTerminalHistory((prev) => prev.map((entry) => entry.id === streamingLineId ? { ...entry, metadata: { ...entry.metadata, completion: chunk.completion } } : entry));
|
|
4098
|
+
}
|
|
3820
4099
|
if (chunk.sender) {
|
|
3821
4100
|
setStreamingLineSender(streamingLineId, chunk.sender);
|
|
3822
4101
|
if (currentUser) {
|
|
@@ -3829,6 +4108,28 @@ function useStreamingChat({
|
|
|
3829
4108
|
if (chunk.collaboration) {
|
|
3830
4109
|
setCollaborationState(chunk.collaboration);
|
|
3831
4110
|
}
|
|
4111
|
+
if (chunk.step) {
|
|
4112
|
+
steps.set(chunk.step.seq, chunk.step);
|
|
4113
|
+
const ordered = Array.from(steps.values()).sort((a, b) => a.seq - b.seq);
|
|
4114
|
+
setTerminalHistory((prev) => {
|
|
4115
|
+
const idx = prev.findIndex((line) => line.id === streamingLineId);
|
|
4116
|
+
if (idx === -1) return prev;
|
|
4117
|
+
const updated = [...prev];
|
|
4118
|
+
updated[idx] = {
|
|
4119
|
+
...updated[idx],
|
|
4120
|
+
metadata: {
|
|
4121
|
+
...updated[idx].metadata || {},
|
|
4122
|
+
agentSteps: ordered,
|
|
4123
|
+
// Explicit rather than inferred from the streaming cursor:
|
|
4124
|
+
// a tool loop runs to completion BEFORE the first answer
|
|
4125
|
+
// token, so during the whole loop the entry's content is
|
|
4126
|
+
// empty and carries no cursor to read.
|
|
4127
|
+
agentStepsLive: true
|
|
4128
|
+
}
|
|
4129
|
+
};
|
|
4130
|
+
return updated;
|
|
4131
|
+
});
|
|
4132
|
+
}
|
|
3832
4133
|
const ckgId = extractKgId(chunk, chunk.progress);
|
|
3833
4134
|
const cRunId = chunk.run_id || chunk.progress?.run_id;
|
|
3834
4135
|
const ctId = chunk.thread_id || chunk.progress?.thread_id || chunk.reasoning_thread_id || chunk.progress?.reasoning_thread_id;
|
|
@@ -3972,49 +4273,14 @@ function useStreamingChat({
|
|
|
3972
4273
|
kgId,
|
|
3973
4274
|
runId
|
|
3974
4275
|
);
|
|
4276
|
+
settleAgentSteps(streamingLineId);
|
|
3975
4277
|
resetStreamState();
|
|
3976
4278
|
}
|
|
3977
4279
|
},
|
|
3978
|
-
onError:
|
|
3979
|
-
if (currentStreamingLineId.current === streamingLineId) {
|
|
3980
|
-
if (progressStateRef.current) {
|
|
3981
|
-
const snap = captureReasoningSnapshot(
|
|
3982
|
-
progressStateRef.current,
|
|
3983
|
-
true
|
|
3984
|
-
);
|
|
3985
|
-
updateStreamingLine(
|
|
3986
|
-
streamingLineId,
|
|
3987
|
-
fullResponse || "",
|
|
3988
|
-
void 0,
|
|
3989
|
-
void 0,
|
|
3990
|
-
snap
|
|
3991
|
-
);
|
|
3992
|
-
setProgressState(null);
|
|
3993
|
-
} else {
|
|
3994
|
-
addTerminalLine("error", `STREAMING ERROR: ${error}`);
|
|
3995
|
-
setProgressState(null);
|
|
3996
|
-
}
|
|
3997
|
-
resetStreamState();
|
|
3998
|
-
}
|
|
3999
|
-
}
|
|
4280
|
+
onError: fail
|
|
4000
4281
|
}, reasoningModeRef.current ? { reasoningMode: reasoningModeRef.current } : void 0);
|
|
4001
4282
|
} catch (error) {
|
|
4002
|
-
|
|
4003
|
-
const snap = captureReasoningSnapshot(
|
|
4004
|
-
progressStateRef.current,
|
|
4005
|
-
true
|
|
4006
|
-
);
|
|
4007
|
-
updateStreamingLine(
|
|
4008
|
-
currentStreamingLineId.current,
|
|
4009
|
-
fullResponse || "",
|
|
4010
|
-
void 0,
|
|
4011
|
-
void 0,
|
|
4012
|
-
snap
|
|
4013
|
-
);
|
|
4014
|
-
}
|
|
4015
|
-
addTerminalLine("error", `STREAMING EXCEPTION: ${error.message}`);
|
|
4016
|
-
setProgressState(null);
|
|
4017
|
-
resetStreamState();
|
|
4283
|
+
fail(error?.message || "The answer could not be completed.");
|
|
4018
4284
|
}
|
|
4019
4285
|
},
|
|
4020
4286
|
[
|
|
@@ -4023,10 +4289,12 @@ function useStreamingChat({
|
|
|
4023
4289
|
updateStreamingLine,
|
|
4024
4290
|
setStreamingLineSender,
|
|
4025
4291
|
resetStreamState,
|
|
4026
|
-
addTerminalLine
|
|
4292
|
+
addTerminalLine,
|
|
4293
|
+
settleAgentSteps,
|
|
4294
|
+
currentUser
|
|
4027
4295
|
]
|
|
4028
4296
|
);
|
|
4029
|
-
const clearReasoningSession =
|
|
4297
|
+
const clearReasoningSession = React15.useCallback(() => {
|
|
4030
4298
|
setLiveKgId(null);
|
|
4031
4299
|
setLiveRunId(null);
|
|
4032
4300
|
setLiveThreadId(null);
|
|
@@ -4057,9 +4325,9 @@ function useMessagePolling({
|
|
|
4057
4325
|
pollIntervalMs = 3e3,
|
|
4058
4326
|
enabled
|
|
4059
4327
|
}) {
|
|
4060
|
-
const lastMessageIdRef =
|
|
4061
|
-
const pollingRef =
|
|
4062
|
-
const poll =
|
|
4328
|
+
const lastMessageIdRef = React15.useRef(void 0);
|
|
4329
|
+
const pollingRef = React15.useRef(false);
|
|
4330
|
+
const poll = React15.useCallback(async () => {
|
|
4063
4331
|
if (!onPollMessages || pollingRef.current) return;
|
|
4064
4332
|
pollingRef.current = true;
|
|
4065
4333
|
try {
|
|
@@ -4098,7 +4366,7 @@ function useMessagePolling({
|
|
|
4098
4366
|
pollingRef.current = false;
|
|
4099
4367
|
}
|
|
4100
4368
|
}, [onPollMessages, setTerminalHistory]);
|
|
4101
|
-
|
|
4369
|
+
React15.useEffect(() => {
|
|
4102
4370
|
if (!enabled || !onPollMessages) return;
|
|
4103
4371
|
const timer = setInterval(poll, pollIntervalMs);
|
|
4104
4372
|
return () => clearInterval(timer);
|
|
@@ -4116,6 +4384,7 @@ function useTerminalCore({
|
|
|
4116
4384
|
onReasoningModeChangeProp,
|
|
4117
4385
|
reasoningRef,
|
|
4118
4386
|
workingGroupContextProp = null,
|
|
4387
|
+
autoFocusInput = true,
|
|
4119
4388
|
onResolveWorkingGroup,
|
|
4120
4389
|
onRagFileUpload,
|
|
4121
4390
|
onListRagFiles,
|
|
@@ -4133,14 +4402,15 @@ function useTerminalCore({
|
|
|
4133
4402
|
pollIntervalMs,
|
|
4134
4403
|
authToken
|
|
4135
4404
|
}) {
|
|
4136
|
-
const
|
|
4405
|
+
const agentLabel = config.agentLabel?.trim() || DEFAULT_AGENT_LABEL;
|
|
4406
|
+
const [internalReasoningMode, setInternalReasoningMode] = React15.useState(null);
|
|
4137
4407
|
const reasoningMode = reasoningModeProp !== void 0 ? reasoningModeProp : internalReasoningMode;
|
|
4138
4408
|
const onReasoningModeChange = onReasoningModeChangeProp || setInternalReasoningMode;
|
|
4139
|
-
const [terminalHistory, setTerminalHistory] =
|
|
4409
|
+
const [terminalHistory, setTerminalHistory] = React15.useState(() => {
|
|
4140
4410
|
if (initialHistory && initialHistory.length > 0) return initialHistory;
|
|
4141
|
-
return [{ type: "system", content:
|
|
4411
|
+
return [{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() }];
|
|
4142
4412
|
});
|
|
4143
|
-
|
|
4413
|
+
React15.useEffect(() => {
|
|
4144
4414
|
if (historyRef) {
|
|
4145
4415
|
historyRef.current = { setHistory: setTerminalHistory, setIsExecuting };
|
|
4146
4416
|
}
|
|
@@ -4148,10 +4418,10 @@ function useTerminalCore({
|
|
|
4148
4418
|
if (historyRef) historyRef.current = null;
|
|
4149
4419
|
};
|
|
4150
4420
|
}, [historyRef]);
|
|
4151
|
-
const enrichedHistory =
|
|
4421
|
+
const enrichedHistory = React15.useMemo(() => {
|
|
4152
4422
|
if (!sourceKGNodes?.length) return terminalHistory;
|
|
4153
4423
|
let changed = false;
|
|
4154
|
-
const
|
|
4424
|
+
const result2 = terminalHistory.map((entry) => {
|
|
4155
4425
|
if ((entry.type === "response" || entry.type === "success") && entry.content && entry.content.length > 20 && !entry.sources?.length) {
|
|
4156
4426
|
const sources = extractKGSources(entry.content, sourceKGNodes);
|
|
4157
4427
|
if (sources.length > 0) {
|
|
@@ -4161,9 +4431,9 @@ function useTerminalCore({
|
|
|
4161
4431
|
}
|
|
4162
4432
|
return entry;
|
|
4163
4433
|
});
|
|
4164
|
-
return changed ?
|
|
4434
|
+
return changed ? result2 : terminalHistory;
|
|
4165
4435
|
}, [terminalHistory, sourceKGNodes]);
|
|
4166
|
-
|
|
4436
|
+
React15.useEffect(() => {
|
|
4167
4437
|
if (initialHistory && initialHistory.length > 0) {
|
|
4168
4438
|
setTerminalHistory((prev) => {
|
|
4169
4439
|
const isDefault = prev.length <= 1 && prev[0]?.type === "system";
|
|
@@ -4171,35 +4441,39 @@ function useTerminalCore({
|
|
|
4171
4441
|
});
|
|
4172
4442
|
}
|
|
4173
4443
|
}, [initialHistory]);
|
|
4174
|
-
|
|
4444
|
+
React15.useEffect(() => {
|
|
4175
4445
|
onHistoryChange?.(enrichedHistory);
|
|
4176
4446
|
}, [enrichedHistory, onHistoryChange]);
|
|
4177
|
-
const addTerminalLine =
|
|
4447
|
+
const addTerminalLine = React15.useCallback((type, content, pageSuggestions) => {
|
|
4178
4448
|
setTerminalHistory((prev) => [...prev, { id: Date.now().toString(), type, content, timestamp: /* @__PURE__ */ new Date(), suggestions: pageSuggestions }]);
|
|
4179
4449
|
}, []);
|
|
4180
|
-
const addTerminalLineWithActions =
|
|
4450
|
+
const addTerminalLineWithActions = React15.useCallback((content, actions) => {
|
|
4181
4451
|
setTerminalHistory((prev) => [...prev, { id: Date.now().toString(), type: "response", content, timestamp: /* @__PURE__ */ new Date(), suggested_actions: actions }]);
|
|
4182
4452
|
}, []);
|
|
4183
|
-
const [currentCommand, setCurrentCommand] =
|
|
4184
|
-
const [
|
|
4185
|
-
const [
|
|
4186
|
-
const [
|
|
4187
|
-
const [
|
|
4188
|
-
const [
|
|
4189
|
-
const
|
|
4190
|
-
const
|
|
4191
|
-
const
|
|
4192
|
-
|
|
4453
|
+
const [currentCommand, setCurrentCommand] = React15.useState("");
|
|
4454
|
+
const [pendingSubmit, setPendingSubmit] = React15.useState(null);
|
|
4455
|
+
const [workingGroupContext, setWorkingGroupContext] = React15.useState(workingGroupContextProp);
|
|
4456
|
+
const [hasShownWelcome, setHasShownWelcome] = React15.useState(false);
|
|
4457
|
+
const [isInputFocused, setIsInputFocused] = React15.useState(true);
|
|
4458
|
+
const [commandPaletteItems, setCommandPaletteItems] = React15.useState([]);
|
|
4459
|
+
const [selectedPaletteItem, setSelectedPaletteItem] = React15.useState(0);
|
|
4460
|
+
const terminalBodyRef = React15.useRef(null);
|
|
4461
|
+
const fileInputRef = React15.useRef(null);
|
|
4462
|
+
const uploadAbortsRef = React15.useRef([]);
|
|
4463
|
+
React15.useEffect(() => () => {
|
|
4193
4464
|
for (const ctrl of uploadAbortsRef.current) ctrl.abort();
|
|
4194
4465
|
uploadAbortsRef.current = [];
|
|
4195
4466
|
}, []);
|
|
4196
|
-
const { inputRef, focusInput } = useFocusManagement();
|
|
4197
|
-
|
|
4467
|
+
const { inputRef, focusInput } = useFocusManagement(autoFocusInput);
|
|
4468
|
+
React15.useEffect(() => {
|
|
4198
4469
|
function onPrefill(e) {
|
|
4199
4470
|
const detail = e.detail;
|
|
4200
4471
|
if (!detail || typeof detail.value !== "string") return;
|
|
4201
4472
|
const value = detail.value;
|
|
4202
4473
|
setCurrentCommand(value);
|
|
4474
|
+
if (e.detail?.submit) {
|
|
4475
|
+
setPendingSubmit(value);
|
|
4476
|
+
}
|
|
4203
4477
|
requestAnimationFrame(() => {
|
|
4204
4478
|
focusInput();
|
|
4205
4479
|
const el = inputRef.current;
|
|
@@ -4213,6 +4487,9 @@ function useTerminalCore({
|
|
|
4213
4487
|
window.removeEventListener("yieldfabric:terminal:prefill", onPrefill);
|
|
4214
4488
|
};
|
|
4215
4489
|
}, [focusInput, inputRef]);
|
|
4490
|
+
const restoreInputFocus = React15.useCallback(() => {
|
|
4491
|
+
if (autoFocusInput) focusInput();
|
|
4492
|
+
}, [autoFocusInput, focusInput]);
|
|
4216
4493
|
const {
|
|
4217
4494
|
isExecuting,
|
|
4218
4495
|
setIsExecuting,
|
|
@@ -4232,15 +4509,16 @@ function useTerminalCore({
|
|
|
4232
4509
|
activityEvents
|
|
4233
4510
|
} = useStreamingChat({
|
|
4234
4511
|
config,
|
|
4512
|
+
authToken,
|
|
4235
4513
|
onStreamRequest,
|
|
4236
4514
|
reasoningMode,
|
|
4237
4515
|
setTerminalHistory,
|
|
4238
4516
|
addTerminalLine,
|
|
4239
|
-
focusInput,
|
|
4517
|
+
focusInput: restoreInputFocus,
|
|
4240
4518
|
currentUser,
|
|
4241
4519
|
sourceKGNodes
|
|
4242
4520
|
});
|
|
4243
|
-
|
|
4521
|
+
React15.useEffect(() => {
|
|
4244
4522
|
const handler = () => {
|
|
4245
4523
|
setCurrentCommand("");
|
|
4246
4524
|
onReasoningModeChange(null);
|
|
@@ -4256,7 +4534,7 @@ function useTerminalCore({
|
|
|
4256
4534
|
pollIntervalMs: pollIntervalMs ?? 3e3,
|
|
4257
4535
|
enabled: !!onPollMessages
|
|
4258
4536
|
});
|
|
4259
|
-
|
|
4537
|
+
React15.useEffect(() => {
|
|
4260
4538
|
if (reasoningRef) {
|
|
4261
4539
|
reasoningRef.current = { progressState, submitInput: handleHilSubmit, cancelReasoning: handleCancelReasoning };
|
|
4262
4540
|
}
|
|
@@ -4264,25 +4542,25 @@ function useTerminalCore({
|
|
|
4264
4542
|
if (reasoningRef) reasoningRef.current = null;
|
|
4265
4543
|
};
|
|
4266
4544
|
});
|
|
4267
|
-
|
|
4545
|
+
React15.useEffect(() => {
|
|
4268
4546
|
if (liveKgId) {
|
|
4269
4547
|
onKGScopeChange?.({ kgId: liveKgId, label: "Live Analysis" });
|
|
4270
4548
|
onKgIdChange?.(liveKgId);
|
|
4271
4549
|
}
|
|
4272
4550
|
}, [liveKgId]);
|
|
4273
|
-
|
|
4551
|
+
React15.useEffect(() => {
|
|
4274
4552
|
if (liveRunId) onRunIdChange?.(liveRunId);
|
|
4275
4553
|
}, [liveRunId]);
|
|
4276
|
-
|
|
4554
|
+
React15.useEffect(() => {
|
|
4277
4555
|
if (liveThreadId) onThreadIdChange?.(liveThreadId);
|
|
4278
4556
|
}, [liveThreadId]);
|
|
4279
|
-
|
|
4557
|
+
React15.useEffect(() => {
|
|
4280
4558
|
onReasoningPhaseChange?.(progressState?.phase ?? null);
|
|
4281
4559
|
}, [progressState?.phase]);
|
|
4282
|
-
|
|
4560
|
+
React15.useEffect(() => {
|
|
4283
4561
|
setWorkingGroupContext(workingGroupContextProp || null);
|
|
4284
4562
|
}, [workingGroupContextProp]);
|
|
4285
|
-
|
|
4563
|
+
React15.useEffect(() => {
|
|
4286
4564
|
let cancelled = false;
|
|
4287
4565
|
if (!onResolveWorkingGroup) return;
|
|
4288
4566
|
(async () => {
|
|
@@ -4297,26 +4575,26 @@ function useTerminalCore({
|
|
|
4297
4575
|
cancelled = true;
|
|
4298
4576
|
};
|
|
4299
4577
|
}, [onResolveWorkingGroup]);
|
|
4300
|
-
|
|
4578
|
+
React15.useEffect(() => {
|
|
4301
4579
|
const handleActionResult = (event) => {
|
|
4302
|
-
const
|
|
4303
|
-
if (
|
|
4580
|
+
const result2 = event.detail;
|
|
4581
|
+
if (result2.success) {
|
|
4304
4582
|
addTerminalLine("success", "Action executed successfully!");
|
|
4305
|
-
if (
|
|
4583
|
+
if (result2.data) addTerminalLine("response", JSON.stringify(result2.data, null, 2));
|
|
4306
4584
|
} else {
|
|
4307
|
-
addTerminalLine("error", `Action failed: ${
|
|
4585
|
+
addTerminalLine("error", `Action failed: ${result2.error || "Unknown error"}`);
|
|
4308
4586
|
}
|
|
4309
4587
|
};
|
|
4310
4588
|
window.addEventListener("terminal-action-result", handleActionResult);
|
|
4311
4589
|
return () => window.removeEventListener("terminal-action-result", handleActionResult);
|
|
4312
4590
|
}, [addTerminalLine]);
|
|
4313
|
-
|
|
4591
|
+
React15.useEffect(() => {
|
|
4314
4592
|
if (showWelcomeMessage && initialHistory.length === 0 && !hasShownWelcome && config.welcomeMessage) {
|
|
4315
4593
|
setHasShownWelcome(true);
|
|
4316
4594
|
const fullMessage = config.welcomeMessage;
|
|
4317
4595
|
const typingLineId = Date.now().toString();
|
|
4318
4596
|
setTerminalHistory([
|
|
4319
|
-
{ type: "system", content:
|
|
4597
|
+
{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() },
|
|
4320
4598
|
{ id: typingLineId, type: "info", content: "", timestamp: /* @__PURE__ */ new Date() }
|
|
4321
4599
|
]);
|
|
4322
4600
|
let i = 0;
|
|
@@ -4329,10 +4607,10 @@ function useTerminalCore({
|
|
|
4329
4607
|
requestAnimationFrame(step);
|
|
4330
4608
|
}
|
|
4331
4609
|
}, [showWelcomeMessage, hasShownWelcome, initialHistory.length, config.welcomeMessage]);
|
|
4332
|
-
|
|
4610
|
+
React15.useEffect(() => {
|
|
4333
4611
|
if (terminalBodyRef.current) terminalBodyRef.current.scrollTop = terminalBodyRef.current.scrollHeight;
|
|
4334
4612
|
}, [terminalHistory, progressState]);
|
|
4335
|
-
const updateCommandPalette =
|
|
4613
|
+
const updateCommandPalette = React15.useCallback((value) => {
|
|
4336
4614
|
if (value.startsWith("/")) {
|
|
4337
4615
|
const query = value.slice(1);
|
|
4338
4616
|
setCommandPaletteItems(filterCommands(query, getBuiltInCommands(), config.customCommands || []));
|
|
@@ -4342,7 +4620,7 @@ function useTerminalCore({
|
|
|
4342
4620
|
setCommandPaletteItems([]);
|
|
4343
4621
|
return false;
|
|
4344
4622
|
}, [config.customCommands]);
|
|
4345
|
-
const handleCommandPaletteKeyDown =
|
|
4623
|
+
const handleCommandPaletteKeyDown = React15.useCallback((e) => {
|
|
4346
4624
|
if (commandPaletteItems.length === 0) return false;
|
|
4347
4625
|
if (e.key === "ArrowUp") {
|
|
4348
4626
|
e.preventDefault();
|
|
@@ -4370,15 +4648,15 @@ function useTerminalCore({
|
|
|
4370
4648
|
}
|
|
4371
4649
|
return false;
|
|
4372
4650
|
}, [commandPaletteItems, selectedPaletteItem]);
|
|
4373
|
-
const handleClearCommand =
|
|
4651
|
+
const handleClearCommand = React15.useCallback(() => {
|
|
4374
4652
|
setTerminalHistory([
|
|
4375
|
-
{ type: "system", content:
|
|
4653
|
+
{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() },
|
|
4376
4654
|
{ type: "system", content: "Terminal cleared.", timestamp: /* @__PURE__ */ new Date() }
|
|
4377
4655
|
]);
|
|
4378
4656
|
setCurrentCommand("");
|
|
4379
4657
|
setTimeout(() => focusInput(), 50);
|
|
4380
4658
|
}, [focusInput]);
|
|
4381
|
-
const handleUploadCommand =
|
|
4659
|
+
const handleUploadCommand = React15.useCallback(() => {
|
|
4382
4660
|
if (!onRagFileUpload) {
|
|
4383
4661
|
addTerminalLine("error", "Upload not enabled in this terminal.");
|
|
4384
4662
|
} else {
|
|
@@ -4387,7 +4665,7 @@ function useTerminalCore({
|
|
|
4387
4665
|
setCurrentCommand("");
|
|
4388
4666
|
setTimeout(() => focusInput(), 50);
|
|
4389
4667
|
}, [onRagFileUpload, addTerminalLine, focusInput]);
|
|
4390
|
-
const handleUploadFiles =
|
|
4668
|
+
const handleUploadFiles = React15.useCallback(async (files) => {
|
|
4391
4669
|
if (!files?.length || !onRagFileUpload) return;
|
|
4392
4670
|
const names = files.map((f) => f.name).join(", ");
|
|
4393
4671
|
addTerminalLine("info", "");
|
|
@@ -4395,11 +4673,11 @@ function useTerminalCore({
|
|
|
4395
4673
|
addTerminalLine("info", `Uploading ${files.length} file(s)...`);
|
|
4396
4674
|
setIsExecuting(true);
|
|
4397
4675
|
try {
|
|
4398
|
-
const
|
|
4399
|
-
if (
|
|
4400
|
-
addTerminalLine("success", `Started ${
|
|
4401
|
-
if (
|
|
4402
|
-
const runs =
|
|
4676
|
+
const result2 = await onRagFileUpload(files, workingGroupContext);
|
|
4677
|
+
if (result2.success) {
|
|
4678
|
+
addTerminalLine("success", `Started ${result2.pipelineRuns?.length ?? result2.documentsIngested ?? files.length} ingestion pipeline(s)`);
|
|
4679
|
+
if (result2.message) addTerminalLine("response", result2.message);
|
|
4680
|
+
const runs = result2.pipelineRuns ?? [];
|
|
4403
4681
|
if (runs.length > 0) {
|
|
4404
4682
|
const apiUrl = config.agentsApiUrl || "http://localhost:3001";
|
|
4405
4683
|
const remaining = new Set(runs.map((r) => r.run_id));
|
|
@@ -4486,7 +4764,7 @@ function useTerminalCore({
|
|
|
4486
4764
|
await handleListFilesCommand();
|
|
4487
4765
|
}
|
|
4488
4766
|
} else {
|
|
4489
|
-
addTerminalLine("error", `Upload failed${
|
|
4767
|
+
addTerminalLine("error", `Upload failed${result2.message ? `: ${result2.message}` : ""}`);
|
|
4490
4768
|
}
|
|
4491
4769
|
} catch (error) {
|
|
4492
4770
|
addTerminalLine("error", `Upload exception: ${error?.message || "Unknown error"}`);
|
|
@@ -4495,8 +4773,8 @@ function useTerminalCore({
|
|
|
4495
4773
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
4496
4774
|
setTimeout(() => focusInput(), 50);
|
|
4497
4775
|
}
|
|
4498
|
-
}, [onRagFileUpload, onListRagFiles, workingGroupContext, addTerminalLine, setIsExecuting, focusInput, config.agentsApiUrl]);
|
|
4499
|
-
const handleListFilesCommand =
|
|
4776
|
+
}, [onRagFileUpload, onListRagFiles, workingGroupContext, addTerminalLine, setIsExecuting, focusInput, config.agentsApiUrl, authToken]);
|
|
4777
|
+
const handleListFilesCommand = React15.useCallback(async () => {
|
|
4500
4778
|
addTerminalLine("info", "");
|
|
4501
4779
|
addTerminalLine("command", "files");
|
|
4502
4780
|
if (!onListRagFiles) {
|
|
@@ -4505,12 +4783,12 @@ function useTerminalCore({
|
|
|
4505
4783
|
}
|
|
4506
4784
|
setIsExecuting(true);
|
|
4507
4785
|
try {
|
|
4508
|
-
const
|
|
4509
|
-
if (!
|
|
4510
|
-
addTerminalLine("error", `Could not load files${
|
|
4786
|
+
const result2 = await onListRagFiles(workingGroupContext);
|
|
4787
|
+
if (!result2.success) {
|
|
4788
|
+
addTerminalLine("error", `Could not load files${result2.message ? `: ${result2.message}` : ""}`);
|
|
4511
4789
|
return;
|
|
4512
4790
|
}
|
|
4513
|
-
const files =
|
|
4791
|
+
const files = result2.files || [];
|
|
4514
4792
|
if (files.length === 0) {
|
|
4515
4793
|
addTerminalLine("info", "No files uploaded yet for this page working group.");
|
|
4516
4794
|
return;
|
|
@@ -4530,7 +4808,7 @@ function useTerminalCore({
|
|
|
4530
4808
|
setIsExecuting(false);
|
|
4531
4809
|
}
|
|
4532
4810
|
}, [onListRagFiles, workingGroupContext, addTerminalLine, addTerminalLineWithActions, setIsExecuting]);
|
|
4533
|
-
const handleTerminalActionExecute =
|
|
4811
|
+
const handleTerminalActionExecute = React15.useCallback(async (updatedAction) => {
|
|
4534
4812
|
const actionType = updatedAction?.action_type;
|
|
4535
4813
|
const payload = updatedAction?.payload || {};
|
|
4536
4814
|
if (actionType === "delete_file") {
|
|
@@ -4539,12 +4817,12 @@ function useTerminalCore({
|
|
|
4539
4817
|
return;
|
|
4540
4818
|
}
|
|
4541
4819
|
const title = payload.title || payload.document_id;
|
|
4542
|
-
const
|
|
4543
|
-
if (
|
|
4820
|
+
const result2 = await onDeleteRagFile(String(payload.document_id), workingGroupContext);
|
|
4821
|
+
if (result2.success) {
|
|
4544
4822
|
addTerminalLine("success", `Removed ${title}`);
|
|
4545
4823
|
await handleListFilesCommand();
|
|
4546
4824
|
} else {
|
|
4547
|
-
addTerminalLine("error", `Failed to remove ${title}${
|
|
4825
|
+
addTerminalLine("error", `Failed to remove ${title}${result2.message ? `: ${result2.message}` : ""}`);
|
|
4548
4826
|
}
|
|
4549
4827
|
return;
|
|
4550
4828
|
}
|
|
@@ -4554,9 +4832,9 @@ function useTerminalCore({
|
|
|
4554
4832
|
return;
|
|
4555
4833
|
}
|
|
4556
4834
|
const title = payload.title || payload.document_id;
|
|
4557
|
-
const
|
|
4558
|
-
if (
|
|
4559
|
-
else addTerminalLine("error", `Download failed for ${title}${
|
|
4835
|
+
const result2 = await onDownloadRagFile(String(payload.document_id), title, workingGroupContext);
|
|
4836
|
+
if (result2.success) addTerminalLine("success", `Download started: ${title}`);
|
|
4837
|
+
else addTerminalLine("error", `Download failed for ${title}${result2.message ? `: ${result2.message}` : ""}`);
|
|
4560
4838
|
return;
|
|
4561
4839
|
}
|
|
4562
4840
|
if (actionType === "resume_pipeline_run") {
|
|
@@ -4595,6 +4873,8 @@ function useTerminalCore({
|
|
|
4595
4873
|
window.dispatchEvent(new CustomEvent("terminal-action-execute", { detail: updatedAction, bubbles: true }));
|
|
4596
4874
|
}, [onDeleteRagFile, onDownloadRagFile, workingGroupContext, addTerminalLine, handleListFilesCommand, config.agentsApiUrl]);
|
|
4597
4875
|
return {
|
|
4876
|
+
// Identity
|
|
4877
|
+
agentLabel,
|
|
4598
4878
|
// History
|
|
4599
4879
|
terminalHistory,
|
|
4600
4880
|
setTerminalHistory,
|
|
@@ -4623,6 +4903,8 @@ function useTerminalCore({
|
|
|
4623
4903
|
// Command input
|
|
4624
4904
|
currentCommand,
|
|
4625
4905
|
setCurrentCommand,
|
|
4906
|
+
pendingSubmit,
|
|
4907
|
+
setPendingSubmit,
|
|
4626
4908
|
commandPaletteItems,
|
|
4627
4909
|
setCommandPaletteItems,
|
|
4628
4910
|
selectedPaletteItem,
|
|
@@ -4653,10 +4935,10 @@ function useSlashMentionPicker({
|
|
|
4653
4935
|
enabledCommands = ["note", "personal"],
|
|
4654
4936
|
requireSlashCommand = true
|
|
4655
4937
|
}) {
|
|
4656
|
-
const [candidates, setCandidates] =
|
|
4657
|
-
const [selectedIndex, setSelectedIndex] =
|
|
4658
|
-
const debounceRef =
|
|
4659
|
-
const reqIdRef =
|
|
4938
|
+
const [candidates, setCandidates] = React15.useState([]);
|
|
4939
|
+
const [selectedIndex, setSelectedIndex] = React15.useState(0);
|
|
4940
|
+
const debounceRef = React15.useRef(null);
|
|
4941
|
+
const reqIdRef = React15.useRef(0);
|
|
4660
4942
|
const extracted = extractQuery(
|
|
4661
4943
|
currentCommand,
|
|
4662
4944
|
caretIndex,
|
|
@@ -4666,7 +4948,7 @@ function useSlashMentionPicker({
|
|
|
4666
4948
|
const query = extracted?.query ?? null;
|
|
4667
4949
|
const command = extracted?.command;
|
|
4668
4950
|
const queryActive = query !== null && !!onMentionResolve;
|
|
4669
|
-
|
|
4951
|
+
React15.useEffect(() => {
|
|
4670
4952
|
if (!queryActive) {
|
|
4671
4953
|
setCandidates([]);
|
|
4672
4954
|
setSelectedIndex(0);
|
|
@@ -4689,17 +4971,17 @@ function useSlashMentionPicker({
|
|
|
4689
4971
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
4690
4972
|
};
|
|
4691
4973
|
}, [queryActive, query, command, onMentionResolve]);
|
|
4692
|
-
const navigateUp =
|
|
4974
|
+
const navigateUp = React15.useCallback(() => {
|
|
4693
4975
|
setSelectedIndex((i) => Math.max(0, i - 1));
|
|
4694
4976
|
}, []);
|
|
4695
|
-
const navigateDown =
|
|
4977
|
+
const navigateDown = React15.useCallback(() => {
|
|
4696
4978
|
setSelectedIndex((i) => Math.min((candidates.length || 1) - 1, i + 1));
|
|
4697
4979
|
}, [candidates.length]);
|
|
4698
|
-
const cancel =
|
|
4980
|
+
const cancel = React15.useCallback(() => {
|
|
4699
4981
|
setCandidates([]);
|
|
4700
4982
|
setSelectedIndex(0);
|
|
4701
4983
|
}, []);
|
|
4702
|
-
const complete =
|
|
4984
|
+
const complete = React15.useCallback(
|
|
4703
4985
|
(candidate) => {
|
|
4704
4986
|
if (query === null) return null;
|
|
4705
4987
|
const head = currentCommand.slice(0, caretIndex);
|
|
@@ -4745,6 +5027,7 @@ function extractQuery(input, caret, enabledCommands, requireSlashCommand) {
|
|
|
4745
5027
|
return { query: tail, command: cmd };
|
|
4746
5028
|
}
|
|
4747
5029
|
function StandardTerminal({
|
|
5030
|
+
showBusyIndicator,
|
|
4748
5031
|
theme: themeOverrides,
|
|
4749
5032
|
config,
|
|
4750
5033
|
onCommandExecute,
|
|
@@ -4764,9 +5047,15 @@ function StandardTerminal({
|
|
|
4764
5047
|
onDeleteRagFile,
|
|
4765
5048
|
onDownloadRagFile,
|
|
4766
5049
|
workingGroupContext: workingGroupContextProp = null,
|
|
5050
|
+
showWorkingGroupBanner = true,
|
|
5051
|
+
autoFocusInput = true,
|
|
5052
|
+
inputPlaceholder,
|
|
5053
|
+
submitRequest,
|
|
5054
|
+
onSubmitRequest,
|
|
4767
5055
|
onPipelineDraftEdit,
|
|
4768
5056
|
onPipelineDraftReject,
|
|
4769
5057
|
onSubmitNote,
|
|
5058
|
+
onSubmitLog,
|
|
4770
5059
|
onMentionResolve,
|
|
4771
5060
|
onMentionPicked,
|
|
4772
5061
|
availableKGs,
|
|
@@ -4787,6 +5076,7 @@ function StandardTerminal({
|
|
|
4787
5076
|
widgets,
|
|
4788
5077
|
slots,
|
|
4789
5078
|
onSourcesActivate,
|
|
5079
|
+
onSourceActivate,
|
|
4790
5080
|
onPollMessages,
|
|
4791
5081
|
pollIntervalMs,
|
|
4792
5082
|
historyRef
|
|
@@ -4802,6 +5092,7 @@ function StandardTerminal({
|
|
|
4802
5092
|
reasoningRef,
|
|
4803
5093
|
workingGroupContextProp,
|
|
4804
5094
|
onResolveWorkingGroup,
|
|
5095
|
+
autoFocusInput,
|
|
4805
5096
|
onRagFileUpload,
|
|
4806
5097
|
onListRagFiles,
|
|
4807
5098
|
onDeleteRagFile,
|
|
@@ -4817,17 +5108,32 @@ function StandardTerminal({
|
|
|
4817
5108
|
showWelcomeMessage
|
|
4818
5109
|
});
|
|
4819
5110
|
const { pushCommand, navigateUp, navigateDown, resetIndex } = useCommandHistory();
|
|
4820
|
-
const
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
5111
|
+
const consumedRequest = React15.useRef(null);
|
|
5112
|
+
React15__default.default.useEffect(() => {
|
|
5113
|
+
if (!submitRequest || consumedRequest.current === submitRequest.id || !submitRequest.value.trim() || !onStreamRequest || core.isExecuting || core.isStreaming || core.currentStreamingLineId.current) return;
|
|
5114
|
+
consumedRequest.current = submitRequest.id;
|
|
5115
|
+
onSubmitRequest?.(submitRequest.id);
|
|
5116
|
+
void core.handleStreamingChat(submitRequest.value.trim());
|
|
5117
|
+
}, [
|
|
5118
|
+
submitRequest,
|
|
5119
|
+
onSubmitRequest,
|
|
5120
|
+
onStreamRequest,
|
|
5121
|
+
core.isExecuting,
|
|
5122
|
+
core.isStreaming,
|
|
5123
|
+
core.currentStreamingLineId,
|
|
5124
|
+
core.handleStreamingChat
|
|
5125
|
+
]);
|
|
5126
|
+
const [suggestions, setSuggestions] = React15.useState([]);
|
|
5127
|
+
const [selectedSuggestion, setSelectedSuggestion] = React15.useState(0);
|
|
5128
|
+
const [internalAuthToken, setInternalAuthToken] = React15.useState(authToken);
|
|
5129
|
+
const authTokenRef = React15.useRef(internalAuthToken);
|
|
4824
5130
|
authTokenRef.current = internalAuthToken;
|
|
4825
|
-
|
|
5131
|
+
React15__default.default.useEffect(() => {
|
|
4826
5132
|
if (authToken !== internalAuthToken) setInternalAuthToken(authToken);
|
|
4827
5133
|
}, [authToken]);
|
|
4828
|
-
const [caretIndex, setCaretIndex] =
|
|
4829
|
-
const [slashPickedNames, setSlashPickedNames] =
|
|
4830
|
-
const liveSlashPickedNames =
|
|
5134
|
+
const [caretIndex, setCaretIndex] = React15.useState(0);
|
|
5135
|
+
const [slashPickedNames, setSlashPickedNames] = React15.useState([]);
|
|
5136
|
+
const liveSlashPickedNames = React15__default.default.useMemo(
|
|
4831
5137
|
() => slashPickedNames.filter(
|
|
4832
5138
|
(n) => core.currentCommand.toLowerCase().includes(`@${n.toLowerCase()}`)
|
|
4833
5139
|
),
|
|
@@ -4914,6 +5220,11 @@ function StandardTerminal({
|
|
|
4914
5220
|
setSuggestions([]);
|
|
4915
5221
|
}
|
|
4916
5222
|
};
|
|
5223
|
+
React15__default.default.useEffect(() => {
|
|
5224
|
+
if (!core.pendingSubmit) return;
|
|
5225
|
+
core.setPendingSubmit(null);
|
|
5226
|
+
void handleSubmit();
|
|
5227
|
+
}, [core.pendingSubmit]);
|
|
4917
5228
|
const handleSubmit = async () => {
|
|
4918
5229
|
if (!core.currentCommand.trim() || core.isExecuting || core.isStreaming || core.currentStreamingLineId.current) return;
|
|
4919
5230
|
const rawCmd = core.currentCommand.trim();
|
|
@@ -4961,6 +5272,21 @@ function StandardTerminal({
|
|
|
4961
5272
|
setTimeout(() => core.focusInput(), 50);
|
|
4962
5273
|
return;
|
|
4963
5274
|
}
|
|
5275
|
+
if (command === "log") {
|
|
5276
|
+
const prose = args.join(" ");
|
|
5277
|
+
core.addTerminalLine("command", prose.trim() ? `log ${prose}` : "log");
|
|
5278
|
+
if (!onSubmitLog) {
|
|
5279
|
+
core.addTerminalLine("error", "Work capture is not available in this context.");
|
|
5280
|
+
} else if (!prose.trim()) {
|
|
5281
|
+
core.addTerminalLine("info", "Usage: /log <what you did or decided>");
|
|
5282
|
+
} else {
|
|
5283
|
+
const result2 = await onSubmitLog(prose);
|
|
5284
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
5285
|
+
}
|
|
5286
|
+
core.setCurrentCommand("");
|
|
5287
|
+
setTimeout(() => core.focusInput(), 50);
|
|
5288
|
+
return;
|
|
5289
|
+
}
|
|
4964
5290
|
if (isNaturalLanguage(cmd, config.endpoints) && onStreamRequest) {
|
|
4965
5291
|
await core.handleStreamingChat(cmd);
|
|
4966
5292
|
core.setCurrentCommand("");
|
|
@@ -5016,8 +5342,8 @@ function StandardTerminal({
|
|
|
5016
5342
|
);
|
|
5017
5343
|
return;
|
|
5018
5344
|
}
|
|
5019
|
-
const
|
|
5020
|
-
core.addTerminalLine(
|
|
5345
|
+
const result2 = await onSubmitNote(prose, scope);
|
|
5346
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
5021
5347
|
};
|
|
5022
5348
|
const handleTokenCommand = (args) => {
|
|
5023
5349
|
core.addTerminalLine("command", `token ${args.join(" ")}`);
|
|
@@ -5045,18 +5371,18 @@ Method: ${parsed.endpoint.method}
|
|
|
5045
5371
|
Path: ${parsed.endpoint.path}`);
|
|
5046
5372
|
core.addTerminalLine("info", "");
|
|
5047
5373
|
try {
|
|
5048
|
-
const
|
|
5049
|
-
if (
|
|
5050
|
-
core.addTerminalLine("success",
|
|
5051
|
-
if (
|
|
5052
|
-
if (parsed.endpoint.id.includes("login") &&
|
|
5053
|
-
setInternalAuthToken(
|
|
5054
|
-
onAuthTokenChange?.(
|
|
5374
|
+
const result2 = await onCommandExecute(cmd, parsed.endpoint, parsed.args);
|
|
5375
|
+
if (result2.success) {
|
|
5376
|
+
core.addTerminalLine("success", result2.message || "RESPONSE: SUCCESS");
|
|
5377
|
+
if (result2.data) core.addTerminalLine("response", JSON.stringify(result2.data, null, 2));
|
|
5378
|
+
if (parsed.endpoint.id.includes("login") && result2.data?.token) {
|
|
5379
|
+
setInternalAuthToken(result2.data.token);
|
|
5380
|
+
onAuthTokenChange?.(result2.data.token);
|
|
5055
5381
|
core.addTerminalLine("success", "AUTH TOKEN AUTO-SAVED");
|
|
5056
5382
|
}
|
|
5057
5383
|
} else {
|
|
5058
|
-
core.addTerminalLine("error", `ERROR: ${
|
|
5059
|
-
if (
|
|
5384
|
+
core.addTerminalLine("error", `ERROR: ${result2.error || "Request failed"}`);
|
|
5385
|
+
if (result2.data) core.addTerminalLine("response", JSON.stringify(result2.data, null, 2));
|
|
5060
5386
|
}
|
|
5061
5387
|
} catch (error) {
|
|
5062
5388
|
core.addTerminalLine("error", `SYSTEM ERROR: ${error.message}`);
|
|
@@ -5079,14 +5405,17 @@ Path: ${parsed.endpoint.path}`);
|
|
|
5079
5405
|
className,
|
|
5080
5406
|
style,
|
|
5081
5407
|
showHeader,
|
|
5408
|
+
agentLabel: core.agentLabel,
|
|
5082
5409
|
focusInput: core.focusInput,
|
|
5083
5410
|
setTerminalHistory: core.setTerminalHistory,
|
|
5084
5411
|
terminalBodyRef: core.terminalBodyRef,
|
|
5085
5412
|
workingGroupContext: core.workingGroupContext,
|
|
5413
|
+
showWorkingGroupBanner,
|
|
5086
5414
|
progressState: core.progressState,
|
|
5087
5415
|
streamTransparency: core.streamTransparency,
|
|
5088
5416
|
streamNowMs: core.streamNowMs,
|
|
5089
5417
|
isExecuting: core.isExecuting,
|
|
5418
|
+
showBusyIndicator,
|
|
5090
5419
|
handleCancelReasoning: core.handleCancelReasoning,
|
|
5091
5420
|
onViewKnowledgeGraph,
|
|
5092
5421
|
onLiveKGUpdate,
|
|
@@ -5161,11 +5490,12 @@ Path: ${parsed.endpoint.path}`);
|
|
|
5161
5490
|
inputBar: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5162
5491
|
TerminalInputBar,
|
|
5163
5492
|
{
|
|
5493
|
+
autoFocus: autoFocusInput,
|
|
5164
5494
|
inputRef: core.inputRef,
|
|
5165
5495
|
fileInputRef: core.fileInputRef,
|
|
5166
5496
|
currentCommand: core.currentCommand,
|
|
5167
5497
|
isExecuting: core.isExecuting,
|
|
5168
|
-
placeholder: activeKGScope ? `Ask about ${activeKGScope.label}...` : "Ask anything...",
|
|
5498
|
+
placeholder: activeKGScope ? `Ask about ${activeKGScope.label}...` : inputPlaceholder ?? "Ask anything...",
|
|
5169
5499
|
onInputChange: handleInputChange,
|
|
5170
5500
|
onKeyDown: handleKeyDown,
|
|
5171
5501
|
onSubmit: handleSubmit,
|
|
@@ -5202,6 +5532,7 @@ Path: ${parsed.endpoint.path}`);
|
|
|
5202
5532
|
authToken: authTokenRef.current,
|
|
5203
5533
|
onPageNavigation,
|
|
5204
5534
|
onSourcesActivate,
|
|
5535
|
+
onSourceActivate,
|
|
5205
5536
|
renderEntryExtra,
|
|
5206
5537
|
renderEntry,
|
|
5207
5538
|
widgets,
|
|
@@ -5315,8 +5646,8 @@ function MentionDropdown({
|
|
|
5315
5646
|
const name = (p.display_name || p.entity_id).toLowerCase();
|
|
5316
5647
|
return name.includes(query.toLowerCase());
|
|
5317
5648
|
});
|
|
5318
|
-
const selectedRef =
|
|
5319
|
-
|
|
5649
|
+
const selectedRef = React15.useRef(null);
|
|
5650
|
+
React15.useEffect(() => {
|
|
5320
5651
|
selectedRef.current?.scrollIntoView({ block: "nearest" });
|
|
5321
5652
|
}, [selectedIndex]);
|
|
5322
5653
|
if (filtered.length === 0) return null;
|
|
@@ -5377,8 +5708,8 @@ var ALL_TARGET = {
|
|
|
5377
5708
|
type: "special"
|
|
5378
5709
|
};
|
|
5379
5710
|
function useMentions(currentCommand, participants, mentionTargets) {
|
|
5380
|
-
const [selectedMentionIndex, setSelectedMentionIndex] =
|
|
5381
|
-
const allCandidates =
|
|
5711
|
+
const [selectedMentionIndex, setSelectedMentionIndex] = React15.useState(0);
|
|
5712
|
+
const allCandidates = React15.useMemo(() => {
|
|
5382
5713
|
const map = /* @__PURE__ */ new Map();
|
|
5383
5714
|
if (participants) {
|
|
5384
5715
|
for (const p of participants) {
|
|
@@ -5409,7 +5740,7 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5409
5740
|
return list;
|
|
5410
5741
|
}, [participants, mentionTargets]);
|
|
5411
5742
|
const hasCandidates = allCandidates.length > 0;
|
|
5412
|
-
const mentionQuery =
|
|
5743
|
+
const mentionQuery = React15.useMemo(() => {
|
|
5413
5744
|
if (!hasCandidates) return null;
|
|
5414
5745
|
const atIdx = currentCommand.lastIndexOf("@");
|
|
5415
5746
|
if (atIdx === -1) return null;
|
|
@@ -5418,7 +5749,7 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5418
5749
|
if (query.includes(" ") && query.trim().length > 0) return null;
|
|
5419
5750
|
return query;
|
|
5420
5751
|
}, [currentCommand, hasCandidates]);
|
|
5421
|
-
const mentionCandidates =
|
|
5752
|
+
const mentionCandidates = React15.useMemo(() => {
|
|
5422
5753
|
if (mentionQuery === null) return [];
|
|
5423
5754
|
const q = mentionQuery.toLowerCase();
|
|
5424
5755
|
return allCandidates.filter(
|
|
@@ -5426,18 +5757,18 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5426
5757
|
);
|
|
5427
5758
|
}, [mentionQuery, allCandidates]);
|
|
5428
5759
|
const safeIndex = mentionCandidates.length > 0 ? Math.min(selectedMentionIndex, mentionCandidates.length - 1) : 0;
|
|
5429
|
-
const navigateMentionUp =
|
|
5760
|
+
const navigateMentionUp = React15.useCallback(() => {
|
|
5430
5761
|
setSelectedMentionIndex((prev) => Math.max(0, prev - 1));
|
|
5431
5762
|
}, []);
|
|
5432
|
-
const navigateMentionDown =
|
|
5763
|
+
const navigateMentionDown = React15.useCallback(() => {
|
|
5433
5764
|
setSelectedMentionIndex(
|
|
5434
5765
|
(prev) => Math.min((mentionCandidates.length || 1) - 1, prev + 1)
|
|
5435
5766
|
);
|
|
5436
5767
|
}, [mentionCandidates.length]);
|
|
5437
|
-
const resetMentionIndex =
|
|
5768
|
+
const resetMentionIndex = React15.useCallback(() => {
|
|
5438
5769
|
setSelectedMentionIndex(0);
|
|
5439
5770
|
}, []);
|
|
5440
|
-
const completeMention =
|
|
5771
|
+
const completeMention = React15.useCallback(
|
|
5441
5772
|
(candidate) => {
|
|
5442
5773
|
const atIdx = currentCommand.lastIndexOf("@");
|
|
5443
5774
|
if (atIdx === -1) return currentCommand;
|
|
@@ -5446,7 +5777,7 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5446
5777
|
},
|
|
5447
5778
|
[currentCommand]
|
|
5448
5779
|
);
|
|
5449
|
-
const parseMentions =
|
|
5780
|
+
const parseMentions = React15.useCallback(
|
|
5450
5781
|
(cmd) => {
|
|
5451
5782
|
if (allCandidates.length === 0) return [];
|
|
5452
5783
|
const sortedCandidates = [...allCandidates].sort(
|
|
@@ -5492,6 +5823,7 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5492
5823
|
};
|
|
5493
5824
|
}
|
|
5494
5825
|
function ChatTerminal({
|
|
5826
|
+
showBusyIndicator,
|
|
5495
5827
|
theme: themeOverrides,
|
|
5496
5828
|
config,
|
|
5497
5829
|
className = "",
|
|
@@ -5507,6 +5839,8 @@ function ChatTerminal({
|
|
|
5507
5839
|
onDeleteRagFile,
|
|
5508
5840
|
onDownloadRagFile,
|
|
5509
5841
|
workingGroupContext: workingGroupContextProp = null,
|
|
5842
|
+
showWorkingGroupBanner = true,
|
|
5843
|
+
autoFocusInput = true,
|
|
5510
5844
|
onPipelineDraftEdit,
|
|
5511
5845
|
onPipelineDraftReject,
|
|
5512
5846
|
onPageNavigation,
|
|
@@ -5529,6 +5863,7 @@ function ChatTerminal({
|
|
|
5529
5863
|
widgets,
|
|
5530
5864
|
slots,
|
|
5531
5865
|
onSourcesActivate,
|
|
5866
|
+
onSourceActivate,
|
|
5532
5867
|
historyRef,
|
|
5533
5868
|
currentUser,
|
|
5534
5869
|
onSendMessage,
|
|
@@ -5538,8 +5873,10 @@ function ChatTerminal({
|
|
|
5538
5873
|
typingUsers,
|
|
5539
5874
|
onTyping,
|
|
5540
5875
|
onSubmitNote,
|
|
5876
|
+
onSubmitLog,
|
|
5541
5877
|
onMentionResolve,
|
|
5542
|
-
onMentionPicked
|
|
5878
|
+
onMentionPicked,
|
|
5879
|
+
authToken
|
|
5543
5880
|
}) {
|
|
5544
5881
|
const core = useTerminalCore({
|
|
5545
5882
|
config,
|
|
@@ -5552,6 +5889,7 @@ function ChatTerminal({
|
|
|
5552
5889
|
reasoningRef,
|
|
5553
5890
|
workingGroupContextProp,
|
|
5554
5891
|
onResolveWorkingGroup,
|
|
5892
|
+
autoFocusInput,
|
|
5555
5893
|
onRagFileUpload,
|
|
5556
5894
|
onListRagFiles,
|
|
5557
5895
|
onDeleteRagFile,
|
|
@@ -5565,9 +5903,10 @@ function ChatTerminal({
|
|
|
5565
5903
|
showWelcomeMessage,
|
|
5566
5904
|
currentUser,
|
|
5567
5905
|
onPollMessages,
|
|
5568
|
-
pollIntervalMs
|
|
5906
|
+
pollIntervalMs,
|
|
5907
|
+
authToken
|
|
5569
5908
|
});
|
|
5570
|
-
|
|
5909
|
+
React15.useEffect(() => {
|
|
5571
5910
|
onActivityEventsChange?.(core.activityEvents);
|
|
5572
5911
|
}, [core.activityEvents]);
|
|
5573
5912
|
const isCollaborative = !!core.collaborationState?.session_id || !!onSendMessage || !!currentUser;
|
|
@@ -5582,8 +5921,8 @@ function ChatTerminal({
|
|
|
5582
5921
|
completeMention,
|
|
5583
5922
|
parseMentions
|
|
5584
5923
|
} = useMentions(mentionsInput, core.collaborationState?.participants, mentionTargets);
|
|
5585
|
-
const [caretIndex, setCaretIndex] =
|
|
5586
|
-
const [slashPickedNames, setSlashPickedNames] =
|
|
5924
|
+
const [caretIndex, setCaretIndex] = React15.useState(0);
|
|
5925
|
+
const [slashPickedNames, setSlashPickedNames] = React15.useState([]);
|
|
5587
5926
|
const slashMentions = useSlashMentionPicker({
|
|
5588
5927
|
currentCommand: core.currentCommand,
|
|
5589
5928
|
caretIndex,
|
|
@@ -5605,13 +5944,13 @@ function ChatTerminal({
|
|
|
5605
5944
|
setCaretIndex(replaced.caret);
|
|
5606
5945
|
});
|
|
5607
5946
|
};
|
|
5608
|
-
const liveSlashPickedNames =
|
|
5947
|
+
const liveSlashPickedNames = React15.useMemo(
|
|
5609
5948
|
() => slashPickedNames.filter(
|
|
5610
5949
|
(n) => core.currentCommand.toLowerCase().includes(`@${n.toLowerCase()}`)
|
|
5611
5950
|
),
|
|
5612
5951
|
[slashPickedNames, core.currentCommand]
|
|
5613
5952
|
);
|
|
5614
|
-
const knownMentionNames =
|
|
5953
|
+
const knownMentionNames = React15.useMemo(() => {
|
|
5615
5954
|
const names = [...liveSlashPickedNames];
|
|
5616
5955
|
if (mentionTargets) for (const t of mentionTargets) names.push(t.display_name);
|
|
5617
5956
|
if (core.collaborationState?.participants) {
|
|
@@ -5709,11 +6048,26 @@ function ChatTerminal({
|
|
|
5709
6048
|
`Usage: /${command} <prose>. Use @name to link an entity.`
|
|
5710
6049
|
);
|
|
5711
6050
|
} else {
|
|
5712
|
-
const
|
|
6051
|
+
const result2 = await onSubmitNote(
|
|
5713
6052
|
prose,
|
|
5714
6053
|
command === "personal" ? "personal" : "workspace"
|
|
5715
6054
|
);
|
|
5716
|
-
core.addTerminalLine(
|
|
6055
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
6056
|
+
}
|
|
6057
|
+
core.setCurrentCommand("");
|
|
6058
|
+
setTimeout(() => core.focusInput(), 50);
|
|
6059
|
+
return;
|
|
6060
|
+
}
|
|
6061
|
+
if (command === "log") {
|
|
6062
|
+
const prose = args.join(" ");
|
|
6063
|
+
core.addTerminalLine("command", prose.trim() ? `log ${prose}` : "log");
|
|
6064
|
+
if (!onSubmitLog) {
|
|
6065
|
+
core.addTerminalLine("error", "Work capture is not available in this context.");
|
|
6066
|
+
} else if (!prose.trim()) {
|
|
6067
|
+
core.addTerminalLine("info", "Usage: /log <what you did or decided>");
|
|
6068
|
+
} else {
|
|
6069
|
+
const result2 = await onSubmitLog(prose);
|
|
6070
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
5717
6071
|
}
|
|
5718
6072
|
core.setCurrentCommand("");
|
|
5719
6073
|
setTimeout(() => core.focusInput(), 50);
|
|
@@ -5760,14 +6114,17 @@ function ChatTerminal({
|
|
|
5760
6114
|
className,
|
|
5761
6115
|
style,
|
|
5762
6116
|
showHeader,
|
|
6117
|
+
agentLabel: core.agentLabel,
|
|
5763
6118
|
focusInput: core.focusInput,
|
|
5764
6119
|
setTerminalHistory: core.setTerminalHistory,
|
|
5765
6120
|
terminalBodyRef: core.terminalBodyRef,
|
|
5766
6121
|
workingGroupContext: core.workingGroupContext,
|
|
6122
|
+
showWorkingGroupBanner,
|
|
5767
6123
|
progressState: core.progressState,
|
|
5768
6124
|
streamTransparency: core.streamTransparency,
|
|
5769
6125
|
streamNowMs: core.streamNowMs,
|
|
5770
6126
|
isExecuting: core.isExecuting,
|
|
6127
|
+
showBusyIndicator,
|
|
5771
6128
|
handleCancelReasoning: core.handleCancelReasoning,
|
|
5772
6129
|
onViewKnowledgeGraph,
|
|
5773
6130
|
onLiveKGUpdate,
|
|
@@ -5804,6 +6161,7 @@ function ChatTerminal({
|
|
|
5804
6161
|
inputBar: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5805
6162
|
TerminalInputBar,
|
|
5806
6163
|
{
|
|
6164
|
+
autoFocus: autoFocusInput,
|
|
5807
6165
|
inputRef: core.inputRef,
|
|
5808
6166
|
fileInputRef: core.fileInputRef,
|
|
5809
6167
|
currentCommand: core.currentCommand,
|
|
@@ -5856,6 +6214,7 @@ function ChatTerminal({
|
|
|
5856
6214
|
config,
|
|
5857
6215
|
onPageNavigation,
|
|
5858
6216
|
onSourcesActivate,
|
|
6217
|
+
onSourceActivate,
|
|
5859
6218
|
renderEntryExtra,
|
|
5860
6219
|
renderEntry,
|
|
5861
6220
|
widgets,
|
|
@@ -5877,17 +6236,17 @@ function CoreTerminal(props) {
|
|
|
5877
6236
|
return /* @__PURE__ */ jsxRuntime.jsx(StandardTerminal, { ...props });
|
|
5878
6237
|
}
|
|
5879
6238
|
function TypingAnimation({ text, className = "", shouldStart = false }) {
|
|
5880
|
-
const [displayedText, setDisplayedText] =
|
|
5881
|
-
const [currentIndex, setCurrentIndex] =
|
|
5882
|
-
const [isTyping, setIsTyping] =
|
|
5883
|
-
|
|
6239
|
+
const [displayedText, setDisplayedText] = React15.useState("");
|
|
6240
|
+
const [currentIndex, setCurrentIndex] = React15.useState(0);
|
|
6241
|
+
const [isTyping, setIsTyping] = React15.useState(false);
|
|
6242
|
+
React15.useEffect(() => {
|
|
5884
6243
|
if (shouldStart && !isTyping) {
|
|
5885
6244
|
setIsTyping(true);
|
|
5886
6245
|
setDisplayedText("");
|
|
5887
6246
|
setCurrentIndex(0);
|
|
5888
6247
|
}
|
|
5889
6248
|
}, [shouldStart, isTyping]);
|
|
5890
|
-
|
|
6249
|
+
React15.useEffect(() => {
|
|
5891
6250
|
if (isTyping && currentIndex < text.length) {
|
|
5892
6251
|
const timeout = setTimeout(() => {
|
|
5893
6252
|
setDisplayedText((prev) => prev + text[currentIndex]);
|
|
@@ -5908,19 +6267,19 @@ function ExpandableTerminal({
|
|
|
5908
6267
|
...terminalProps
|
|
5909
6268
|
}) {
|
|
5910
6269
|
const t = mergeTheme(themeOverrides);
|
|
5911
|
-
const [isExpanded, setIsExpanded] =
|
|
5912
|
-
const [isFullscreen, setIsFullscreen] =
|
|
5913
|
-
const initialHistoryRef =
|
|
5914
|
-
|
|
6270
|
+
const [isExpanded, setIsExpanded] = React15.useState(false);
|
|
6271
|
+
const [isFullscreen, setIsFullscreen] = React15.useState(false);
|
|
6272
|
+
const initialHistoryRef = React15.useRef(initialHistory);
|
|
6273
|
+
React15.useEffect(() => {
|
|
5915
6274
|
initialHistoryRef.current = initialHistory;
|
|
5916
6275
|
}, [initialHistory]);
|
|
5917
|
-
const [currentGuidance, setCurrentGuidance] =
|
|
5918
|
-
const [isLoadingGuidance, setIsLoadingGuidance] =
|
|
5919
|
-
const [hasTriggeredTyping, setHasTriggeredTyping] =
|
|
5920
|
-
const [internalWindowWidth, setInternalWindowWidth] =
|
|
5921
|
-
const terminalRef =
|
|
5922
|
-
const justOpenedRef =
|
|
5923
|
-
|
|
6276
|
+
const [currentGuidance, setCurrentGuidance] = React15.useState(guidanceMessage || "");
|
|
6277
|
+
const [isLoadingGuidance, setIsLoadingGuidance] = React15.useState(false);
|
|
6278
|
+
const [hasTriggeredTyping, setHasTriggeredTyping] = React15.useState(false);
|
|
6279
|
+
const [internalWindowWidth, setInternalWindowWidth] = React15.useState(windowWidth);
|
|
6280
|
+
const terminalRef = React15.useRef(null);
|
|
6281
|
+
const justOpenedRef = React15.useRef(false);
|
|
6282
|
+
React15.useEffect(() => {
|
|
5924
6283
|
if (typeof window !== "undefined") {
|
|
5925
6284
|
const updateWindowWidth = () => setInternalWindowWidth(window.innerWidth);
|
|
5926
6285
|
updateWindowWidth();
|
|
@@ -5928,7 +6287,7 @@ function ExpandableTerminal({
|
|
|
5928
6287
|
return () => window.removeEventListener("resize", updateWindowWidth);
|
|
5929
6288
|
}
|
|
5930
6289
|
}, []);
|
|
5931
|
-
|
|
6290
|
+
React15.useEffect(() => {
|
|
5932
6291
|
const handleClickOutside = (event) => {
|
|
5933
6292
|
if (justOpenedRef.current) return;
|
|
5934
6293
|
if ((isExpanded || isFullscreen) && terminalRef.current && !terminalRef.current.contains(event.target)) {
|
|
@@ -5947,13 +6306,13 @@ function ExpandableTerminal({
|
|
|
5947
6306
|
};
|
|
5948
6307
|
}
|
|
5949
6308
|
}, [isExpanded, isFullscreen]);
|
|
5950
|
-
|
|
6309
|
+
React15.useEffect(() => {
|
|
5951
6310
|
if (onGuidanceRequest && !currentGuidance && !isLoadingGuidance) {
|
|
5952
6311
|
setIsLoadingGuidance(true);
|
|
5953
6312
|
onGuidanceRequest().then((message) => setCurrentGuidance(message)).catch(() => setCurrentGuidance("\u{1F4AC} Intelligence Online - Ask anything!")).finally(() => setIsLoadingGuidance(false));
|
|
5954
6313
|
}
|
|
5955
6314
|
}, [onGuidanceRequest, currentGuidance, isLoadingGuidance]);
|
|
5956
|
-
|
|
6315
|
+
React15.useEffect(() => {
|
|
5957
6316
|
const timer = setTimeout(() => setHasTriggeredTyping(true), 1e3);
|
|
5958
6317
|
return () => clearTimeout(timer);
|
|
5959
6318
|
}, []);
|
|
@@ -6139,12 +6498,12 @@ function InlineTerminal({
|
|
|
6139
6498
|
autoFocus = false
|
|
6140
6499
|
}) {
|
|
6141
6500
|
const t = useTheme();
|
|
6142
|
-
const [command, setCommand] =
|
|
6143
|
-
const [isProcessing, setIsProcessing] =
|
|
6144
|
-
const [response, setResponse] =
|
|
6145
|
-
const [showResponse, setShowResponse] =
|
|
6146
|
-
const inputRef =
|
|
6147
|
-
|
|
6501
|
+
const [command, setCommand] = React15.useState("");
|
|
6502
|
+
const [isProcessing, setIsProcessing] = React15.useState(false);
|
|
6503
|
+
const [response, setResponse] = React15.useState("");
|
|
6504
|
+
const [showResponse, setShowResponse] = React15.useState(false);
|
|
6505
|
+
const inputRef = React15.useRef(null);
|
|
6506
|
+
React15.useEffect(() => {
|
|
6148
6507
|
if (autoFocus && inputRef.current) inputRef.current.focus();
|
|
6149
6508
|
}, [autoFocus]);
|
|
6150
6509
|
const handleSubmit = async (e) => {
|
|
@@ -6298,18 +6657,18 @@ function buildNarrativeSummary(snapshot, columnConfig) {
|
|
|
6298
6657
|
}
|
|
6299
6658
|
function KnowledgeGraphPanel({ snapshot, genericKG, onClose }) {
|
|
6300
6659
|
const t = useTheme();
|
|
6301
|
-
const [selected, setSelected] =
|
|
6302
|
-
const [fullscreen, setFullscreen] =
|
|
6303
|
-
const [searchTerm, setSearchTerm] =
|
|
6304
|
-
const COLUMN_CONFIG =
|
|
6305
|
-
const SEVERITY_COLORS =
|
|
6306
|
-
const FALLBACK_COLORS =
|
|
6307
|
-
const genericNodeMap =
|
|
6660
|
+
const [selected, setSelected] = React15.useState(null);
|
|
6661
|
+
const [fullscreen, setFullscreen] = React15.useState(false);
|
|
6662
|
+
const [searchTerm, setSearchTerm] = React15.useState("");
|
|
6663
|
+
const COLUMN_CONFIG = React15.useMemo(() => getColumnConfig(t), [t]);
|
|
6664
|
+
const SEVERITY_COLORS = React15.useMemo(() => getSeverityColors(t), [t]);
|
|
6665
|
+
const FALLBACK_COLORS = React15.useMemo(() => getFallbackColors(t), [t]);
|
|
6666
|
+
const genericNodeMap = React15.useMemo(() => {
|
|
6308
6667
|
if (!genericKG) return /* @__PURE__ */ new Map();
|
|
6309
6668
|
return new Map(genericKG.nodes.map((n) => [n.id, n]));
|
|
6310
6669
|
}, [genericKG]);
|
|
6311
|
-
const narrativeSummary =
|
|
6312
|
-
|
|
6670
|
+
const narrativeSummary = React15.useMemo(() => buildNarrativeSummary(snapshot, COLUMN_CONFIG), [snapshot, COLUMN_CONFIG]);
|
|
6671
|
+
React15.useEffect(() => {
|
|
6313
6672
|
if (!fullscreen) return;
|
|
6314
6673
|
const handleEsc = (e) => {
|
|
6315
6674
|
if (e.key === "Escape") setFullscreen(false);
|
|
@@ -6317,11 +6676,11 @@ function KnowledgeGraphPanel({ snapshot, genericKG, onClose }) {
|
|
|
6317
6676
|
window.addEventListener("keydown", handleEsc);
|
|
6318
6677
|
return () => window.removeEventListener("keydown", handleEsc);
|
|
6319
6678
|
}, [fullscreen]);
|
|
6320
|
-
const isStructured =
|
|
6679
|
+
const isStructured = React15.useMemo(() => {
|
|
6321
6680
|
const types = new Set(snapshot.nodes.map((n) => n.node_type));
|
|
6322
6681
|
return types.has("document_element") || types.has("finding") || types.has("recommendation");
|
|
6323
6682
|
}, [snapshot]);
|
|
6324
|
-
const { columns, otherNodes } =
|
|
6683
|
+
const { columns, otherNodes } = React15.useMemo(() => {
|
|
6325
6684
|
const cols = {
|
|
6326
6685
|
document_element: [],
|
|
6327
6686
|
finding: [],
|
|
@@ -6343,7 +6702,7 @@ function KnowledgeGraphPanel({ snapshot, genericKG, onClose }) {
|
|
|
6343
6702
|
});
|
|
6344
6703
|
return { columns: cols, otherNodes: other };
|
|
6345
6704
|
}, [snapshot, searchTerm]);
|
|
6346
|
-
const edgeMap =
|
|
6705
|
+
const edgeMap = React15.useMemo(() => {
|
|
6347
6706
|
const map = {};
|
|
6348
6707
|
snapshot.edges.forEach((e) => {
|
|
6349
6708
|
if (!map[e.from]) map[e.from] = [];
|
|
@@ -6709,7 +7068,7 @@ function HistoryAgentCard({
|
|
|
6709
7068
|
thinking
|
|
6710
7069
|
}) {
|
|
6711
7070
|
const t = useTheme();
|
|
6712
|
-
const [agentExpanded, setAgentExpanded] =
|
|
7071
|
+
const [agentExpanded, setAgentExpanded] = React15.useState(false);
|
|
6713
7072
|
const name = agent.display_name || agent.id.replace(/_/g, " ");
|
|
6714
7073
|
const statusColor = agent.status === "complete" ? t.success : agent.status === "failed" ? t.error : t.warning;
|
|
6715
7074
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -6772,8 +7131,8 @@ function ReasoningHistoryCard({
|
|
|
6772
7131
|
defaultExpanded = false
|
|
6773
7132
|
}) {
|
|
6774
7133
|
const t = useTheme();
|
|
6775
|
-
const [expanded, setExpanded] =
|
|
6776
|
-
const [showKG, setShowKG] =
|
|
7134
|
+
const [expanded, setExpanded] = React15.useState(defaultExpanded);
|
|
7135
|
+
const [showKG, setShowKG] = React15.useState(false);
|
|
6777
7136
|
const agentCount = snapshot.agents?.length || 0;
|
|
6778
7137
|
const completedCount = snapshot.agents?.filter((a) => a.status === "complete").length || 0;
|
|
6779
7138
|
const elapsedSec = snapshot.elapsedMs ? Math.round(snapshot.elapsedMs / 1e3) : null;
|
|
@@ -7012,6 +7371,227 @@ function ReasoningHistoryCard({
|
|
|
7012
7371
|
}
|
|
7013
7372
|
);
|
|
7014
7373
|
}
|
|
7374
|
+
function subject(step) {
|
|
7375
|
+
const idx = step.detail.indexOf(": ");
|
|
7376
|
+
const s = idx > -1 ? step.detail.slice(idx + 2).trim() : "";
|
|
7377
|
+
return s.length ? s : null;
|
|
7378
|
+
}
|
|
7379
|
+
function bare(tool) {
|
|
7380
|
+
return tool.replace(/^yf_kg_/, "").replace(/^yf_/, "");
|
|
7381
|
+
}
|
|
7382
|
+
function action(step) {
|
|
7383
|
+
const subj = subject(step);
|
|
7384
|
+
const quoted = subj ? `\u201C${subj}\u201D` : null;
|
|
7385
|
+
switch (bare(step.tool)) {
|
|
7386
|
+
case "graphs":
|
|
7387
|
+
return "Listed knowledge collections";
|
|
7388
|
+
case "search":
|
|
7389
|
+
return quoted ? `Searched for ${quoted}` : "Searched the documents";
|
|
7390
|
+
case "count":
|
|
7391
|
+
return quoted ? `Counted mentions of ${quoted}` : "Counted mentions";
|
|
7392
|
+
case "enumerate":
|
|
7393
|
+
return quoted ? `Listed every match for ${quoted}` : "Listed every match";
|
|
7394
|
+
case "fetch":
|
|
7395
|
+
return "Read a document";
|
|
7396
|
+
case "entities":
|
|
7397
|
+
return "Listed the people and things found";
|
|
7398
|
+
case "explore":
|
|
7399
|
+
return quoted ? `Followed connections from ${quoted}` : "Followed connections";
|
|
7400
|
+
case "sets":
|
|
7401
|
+
return "Listed frozen document sets";
|
|
7402
|
+
case "get_set":
|
|
7403
|
+
return "Read a frozen document set";
|
|
7404
|
+
case "count_in_set":
|
|
7405
|
+
return quoted ? `Counted ${quoted} inside a set` : "Counted inside a set";
|
|
7406
|
+
case "think":
|
|
7407
|
+
return "Thought it through";
|
|
7408
|
+
default:
|
|
7409
|
+
return subj ? `${bare(step.tool).replace(/_/g, " ")} ${subj}` : bare(step.tool).replace(/_/g, " ");
|
|
7410
|
+
}
|
|
7411
|
+
}
|
|
7412
|
+
function took(step) {
|
|
7413
|
+
if (step.status === "running") return null;
|
|
7414
|
+
const ms = Number(step.ms);
|
|
7415
|
+
if (!Number.isFinite(ms) || ms < 1e3) return null;
|
|
7416
|
+
return ms < 1e4 ? `${(ms / 1e3).toFixed(1)}s` : `${Math.round(ms / 1e3)}s`;
|
|
7417
|
+
}
|
|
7418
|
+
function groupTook(g) {
|
|
7419
|
+
const slowest = g.steps.reduce(
|
|
7420
|
+
(worst, s) => Number(s.ms) > Number(worst.ms) ? s : worst,
|
|
7421
|
+
g.steps[0]
|
|
7422
|
+
);
|
|
7423
|
+
return took(slowest);
|
|
7424
|
+
}
|
|
7425
|
+
function result(step) {
|
|
7426
|
+
if (step.status === "running") return null;
|
|
7427
|
+
if (step.status === "error") return "unavailable";
|
|
7428
|
+
const n = Number(step.outcome);
|
|
7429
|
+
if (!Number.isFinite(n)) return null;
|
|
7430
|
+
const [one, many] = {
|
|
7431
|
+
graphs: ["collection", "collections"],
|
|
7432
|
+
search: ["result", "results"],
|
|
7433
|
+
count: ["document", "documents"],
|
|
7434
|
+
enumerate: ["match", "matches"],
|
|
7435
|
+
entities: ["entity", "entities"],
|
|
7436
|
+
explore: ["connection", "connections"],
|
|
7437
|
+
sets: ["set", "sets"]
|
|
7438
|
+
}[bare(step.tool)] ?? ["result", "results"];
|
|
7439
|
+
if (n === 0) return "nothing found";
|
|
7440
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
7441
|
+
}
|
|
7442
|
+
function group(steps) {
|
|
7443
|
+
const out = [];
|
|
7444
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
7445
|
+
for (const step of steps) {
|
|
7446
|
+
const label = action(step);
|
|
7447
|
+
const key = `${step.round ?? ""}\0${label}`;
|
|
7448
|
+
const existing = byKey.get(key);
|
|
7449
|
+
if (existing) {
|
|
7450
|
+
existing.steps.push(step);
|
|
7451
|
+
continue;
|
|
7452
|
+
}
|
|
7453
|
+
const g = { key: step.seq, label, round: step.round, steps: [step] };
|
|
7454
|
+
byKey.set(key, g);
|
|
7455
|
+
out.push(g);
|
|
7456
|
+
}
|
|
7457
|
+
return out;
|
|
7458
|
+
}
|
|
7459
|
+
function groupResult(g) {
|
|
7460
|
+
if (g.steps.length === 1) return result(g.steps[0]);
|
|
7461
|
+
const done = g.steps.filter((s) => s.status !== "running");
|
|
7462
|
+
if (!done.length) return null;
|
|
7463
|
+
const hits = done.filter((s) => Number(s.outcome) > 0).length;
|
|
7464
|
+
if (hits === 0) return "nothing found";
|
|
7465
|
+
return `found in ${hits} of ${done.length}`;
|
|
7466
|
+
}
|
|
7467
|
+
function roundCount(steps) {
|
|
7468
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7469
|
+
for (const s of steps) if (typeof s.round === "number") seen.add(s.round);
|
|
7470
|
+
return seen.size ? seen.size : null;
|
|
7471
|
+
}
|
|
7472
|
+
function AgentStepTrace({ steps, working }) {
|
|
7473
|
+
const t = useTheme();
|
|
7474
|
+
const failed = steps.some((s) => s.status === "error");
|
|
7475
|
+
const prominent = working || failed;
|
|
7476
|
+
const [open, setOpen] = React15.useState(prominent);
|
|
7477
|
+
const [touched, setTouched] = React15.useState(false);
|
|
7478
|
+
const [hover, setHover] = React15.useState(false);
|
|
7479
|
+
React15.useEffect(() => {
|
|
7480
|
+
if (!touched) setOpen(prominent);
|
|
7481
|
+
}, [prominent, touched]);
|
|
7482
|
+
if (!steps.length) return null;
|
|
7483
|
+
const groups = group(steps);
|
|
7484
|
+
const rounds = roundCount(steps);
|
|
7485
|
+
const n = rounds ?? groups.length;
|
|
7486
|
+
const count = `${n} ${rounds ? "round" : "step"}${n === 1 ? "" : "s"}`;
|
|
7487
|
+
const only = groups.length === 1 ? groups[0] : null;
|
|
7488
|
+
const summary = working ? `${action(steps[steps.length - 1])}\u2026` : failed ? `${count}, some unavailable` : only ? [
|
|
7489
|
+
only.label + (only.steps.length > 1 ? ` \xD7${only.steps.length}` : ""),
|
|
7490
|
+
groupResult(only)
|
|
7491
|
+
].filter(Boolean).join(" \u2014 ") : count;
|
|
7492
|
+
const toggle = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7493
|
+
"button",
|
|
7494
|
+
{
|
|
7495
|
+
type: "button",
|
|
7496
|
+
onClick: () => {
|
|
7497
|
+
setTouched(true);
|
|
7498
|
+
setOpen((o) => !o);
|
|
7499
|
+
},
|
|
7500
|
+
onMouseEnter: () => setHover(true),
|
|
7501
|
+
onMouseLeave: () => setHover(false),
|
|
7502
|
+
"aria-expanded": open,
|
|
7503
|
+
className: "flex w-full items-center gap-2 text-left text-xs",
|
|
7504
|
+
style: { color: failed ? t.error : hover ? t.text : t.textMuted },
|
|
7505
|
+
children: [
|
|
7506
|
+
working && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7507
|
+
"span",
|
|
7508
|
+
{
|
|
7509
|
+
"aria-hidden": true,
|
|
7510
|
+
className: "inline-block h-1.5 w-1.5 shrink-0 rounded-full motion-safe:animate-pulse",
|
|
7511
|
+
style: { backgroundColor: t.primary }
|
|
7512
|
+
}
|
|
7513
|
+
),
|
|
7514
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: summary }),
|
|
7515
|
+
!(only && !working && !failed) && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "shrink-0", children: open ? "\u2212" : "+" })
|
|
7516
|
+
]
|
|
7517
|
+
}
|
|
7518
|
+
);
|
|
7519
|
+
const rows = /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "mt-2 space-y-1", children: groups.map((g, i) => {
|
|
7520
|
+
const res = groupResult(g);
|
|
7521
|
+
const slow = groupTook(g);
|
|
7522
|
+
const anyError = g.steps.some((s) => s.status === "error");
|
|
7523
|
+
const running = g.steps.some((s) => s.status === "running");
|
|
7524
|
+
const startsRound = g.round !== void 0 && g.round !== groups[i - 1]?.round;
|
|
7525
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-baseline gap-2 text-xs", children: [
|
|
7526
|
+
rounds !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7527
|
+
"span",
|
|
7528
|
+
{
|
|
7529
|
+
className: "w-3 shrink-0 text-right tabular-nums",
|
|
7530
|
+
style: { color: t.textMuted },
|
|
7531
|
+
"aria-hidden": !startsRound,
|
|
7532
|
+
children: startsRound ? g.round : ""
|
|
7533
|
+
}
|
|
7534
|
+
),
|
|
7535
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7536
|
+
"span",
|
|
7537
|
+
{
|
|
7538
|
+
"aria-hidden": true,
|
|
7539
|
+
className: "w-3 shrink-0 text-[10px]",
|
|
7540
|
+
style: { color: anyError ? t.error : t.textMuted },
|
|
7541
|
+
children: running ? "\xB7" : anyError ? "!" : "\u2713"
|
|
7542
|
+
}
|
|
7543
|
+
),
|
|
7544
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7545
|
+
"span",
|
|
7546
|
+
{
|
|
7547
|
+
className: "min-w-0 flex-1 truncate",
|
|
7548
|
+
style: { color: t.textSecondary },
|
|
7549
|
+
title: g.label,
|
|
7550
|
+
children: [
|
|
7551
|
+
g.label,
|
|
7552
|
+
g.steps.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: t.textMuted }, children: [
|
|
7553
|
+
" \xD7",
|
|
7554
|
+
g.steps.length
|
|
7555
|
+
] })
|
|
7556
|
+
]
|
|
7557
|
+
}
|
|
7558
|
+
),
|
|
7559
|
+
slow && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7560
|
+
"span",
|
|
7561
|
+
{
|
|
7562
|
+
className: "shrink-0 tabular-nums",
|
|
7563
|
+
style: { color: t.textMuted },
|
|
7564
|
+
children: slow
|
|
7565
|
+
}
|
|
7566
|
+
),
|
|
7567
|
+
res && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", style: { color: anyError ? t.error : t.textMuted }, children: res })
|
|
7568
|
+
] }, g.key);
|
|
7569
|
+
}) });
|
|
7570
|
+
if (!prominent) {
|
|
7571
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2", children: [
|
|
7572
|
+
toggle,
|
|
7573
|
+
open && !only && rows
|
|
7574
|
+
] });
|
|
7575
|
+
}
|
|
7576
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7577
|
+
"div",
|
|
7578
|
+
{
|
|
7579
|
+
className: "mt-2 rounded-lg p-3",
|
|
7580
|
+
style: { backgroundColor: t.bgRaisedAlt, border: `1px solid ${t.border}` },
|
|
7581
|
+
children: [
|
|
7582
|
+
toggle,
|
|
7583
|
+
open && rows
|
|
7584
|
+
]
|
|
7585
|
+
}
|
|
7586
|
+
);
|
|
7587
|
+
}
|
|
7588
|
+
function agentStepTraceExtra(entry) {
|
|
7589
|
+
const meta = entry.metadata;
|
|
7590
|
+
const steps = meta?.agentSteps;
|
|
7591
|
+
if (!steps?.length) return null;
|
|
7592
|
+
const working = meta?.agentStepsLive ?? entry.content.endsWith("\u258B");
|
|
7593
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AgentStepTrace, { steps, working });
|
|
7594
|
+
}
|
|
7015
7595
|
|
|
7016
7596
|
// src/knowledge/graphTheme.ts
|
|
7017
7597
|
var NODE_TYPE_COLORS = {
|
|
@@ -7277,7 +7857,7 @@ function GraphNodeComponent({ data, selected }) {
|
|
|
7277
7857
|
` })
|
|
7278
7858
|
] });
|
|
7279
7859
|
}
|
|
7280
|
-
var GraphNode =
|
|
7860
|
+
var GraphNode = React15.memo(GraphNodeComponent);
|
|
7281
7861
|
function GraphEdgeComponent({
|
|
7282
7862
|
id,
|
|
7283
7863
|
sourceX,
|
|
@@ -7346,7 +7926,7 @@ function GraphEdgeComponent({
|
|
|
7346
7926
|
) })
|
|
7347
7927
|
] });
|
|
7348
7928
|
}
|
|
7349
|
-
var GraphEdge =
|
|
7929
|
+
var GraphEdge = React15.memo(GraphEdgeComponent);
|
|
7350
7930
|
function EdgeMarkerDefs() {
|
|
7351
7931
|
const types = [
|
|
7352
7932
|
"supports",
|
|
@@ -7476,18 +8056,18 @@ function AnnotationCard({ annotation: a }) {
|
|
|
7476
8056
|
}
|
|
7477
8057
|
);
|
|
7478
8058
|
}
|
|
7479
|
-
var MarkdownContent =
|
|
8059
|
+
var MarkdownContent = React15.memo(function MarkdownContent2({
|
|
7480
8060
|
children,
|
|
7481
8061
|
className = "",
|
|
7482
8062
|
entities,
|
|
7483
8063
|
onEntityClick
|
|
7484
8064
|
}) {
|
|
7485
8065
|
if (!children) return null;
|
|
7486
|
-
const components =
|
|
8066
|
+
const components = React15.useMemo(() => {
|
|
7487
8067
|
if (!entities || entities.length === 0) return MARKDOWN_COMPONENTS;
|
|
7488
8068
|
return { ...MARKDOWN_COMPONENTS, ...buildHighlightOverrides(entities, onEntityClick) };
|
|
7489
8069
|
}, [entities, onEntityClick]);
|
|
7490
|
-
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `text-xs leading-relaxed text-gray-300 break-words ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown__default.default, { components, children }) });
|
|
8070
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: `text-xs leading-relaxed text-gray-300 break-words ${className}`, children: /* @__PURE__ */ jsxRuntime.jsx(ReactMarkdown__default.default, { remarkPlugins: [remarkGfm__default.default], components, children }) });
|
|
7491
8071
|
});
|
|
7492
8072
|
function escapeRegex(s) {
|
|
7493
8073
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -7553,13 +8133,13 @@ function highlightText(text, regex, entityMap, onEntityClick) {
|
|
|
7553
8133
|
return parts;
|
|
7554
8134
|
}
|
|
7555
8135
|
function highlightChildren(children, regex, entityMap, onEntityClick) {
|
|
7556
|
-
return
|
|
8136
|
+
return React15__default.default.Children.map(children, (child) => {
|
|
7557
8137
|
if (typeof child === "string") {
|
|
7558
8138
|
const highlighted = highlightText(child, regex, entityMap, onEntityClick);
|
|
7559
8139
|
return highlighted.length === 1 && typeof highlighted[0] === "string" ? child : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: highlighted });
|
|
7560
8140
|
}
|
|
7561
|
-
if (
|
|
7562
|
-
return
|
|
8141
|
+
if (React15__default.default.isValidElement(child) && child.props.children) {
|
|
8142
|
+
return React15__default.default.cloneElement(child, {
|
|
7563
8143
|
...child.props,
|
|
7564
8144
|
children: highlightChildren(child.props.children, regex, entityMap, onEntityClick)
|
|
7565
8145
|
});
|
|
@@ -7727,7 +8307,7 @@ var MARKDOWN_COMPONENTS = {
|
|
|
7727
8307
|
}
|
|
7728
8308
|
)
|
|
7729
8309
|
};
|
|
7730
|
-
var MarkdownEditor =
|
|
8310
|
+
var MarkdownEditor = React15.memo(function MarkdownEditor2({
|
|
7731
8311
|
value,
|
|
7732
8312
|
onChange,
|
|
7733
8313
|
onSave,
|
|
@@ -7736,14 +8316,14 @@ var MarkdownEditor = React12.memo(function MarkdownEditor2({
|
|
|
7736
8316
|
autoFocus = true,
|
|
7737
8317
|
disabled = false
|
|
7738
8318
|
}) {
|
|
7739
|
-
const editorRef =
|
|
7740
|
-
|
|
8319
|
+
const editorRef = React15.useRef(null);
|
|
8320
|
+
React15.useEffect(() => {
|
|
7741
8321
|
if (autoFocus && editorRef.current) {
|
|
7742
8322
|
const id = requestAnimationFrame(() => editorRef.current?.focus());
|
|
7743
8323
|
return () => cancelAnimationFrame(id);
|
|
7744
8324
|
}
|
|
7745
8325
|
}, [autoFocus]);
|
|
7746
|
-
const handleKeyDown =
|
|
8326
|
+
const handleKeyDown = React15.useCallback(
|
|
7747
8327
|
(e) => {
|
|
7748
8328
|
if (disabled) return;
|
|
7749
8329
|
if (e.key === "Escape") {
|
|
@@ -7760,7 +8340,7 @@ var MarkdownEditor = React12.memo(function MarkdownEditor2({
|
|
|
7760
8340
|
},
|
|
7761
8341
|
[disabled, onCancel, onSave, onChange]
|
|
7762
8342
|
);
|
|
7763
|
-
const handleChange =
|
|
8343
|
+
const handleChange = React15.useCallback(
|
|
7764
8344
|
(markdown, initialNormalize) => {
|
|
7765
8345
|
if (initialNormalize) return;
|
|
7766
8346
|
onChange(markdown);
|
|
@@ -8014,7 +8594,7 @@ var MarkdownEditor = React12.memo(function MarkdownEditor2({
|
|
|
8014
8594
|
}
|
|
8015
8595
|
);
|
|
8016
8596
|
});
|
|
8017
|
-
var KbdKey =
|
|
8597
|
+
var KbdKey = React15.memo(function KbdKey2({ children }) {
|
|
8018
8598
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8019
8599
|
"kbd",
|
|
8020
8600
|
{
|
|
@@ -8030,10 +8610,10 @@ var SAVE_STAGE_MESSAGES = {
|
|
|
8030
8610
|
extracting: "re-analyzing entities with AI\u2026",
|
|
8031
8611
|
finishing: "almost done \xB7 finalizing graph\u2026"
|
|
8032
8612
|
};
|
|
8033
|
-
function summarizeSaveResult(
|
|
8034
|
-
if (!
|
|
8035
|
-
const added =
|
|
8036
|
-
const removed =
|
|
8613
|
+
function summarizeSaveResult(result2) {
|
|
8614
|
+
if (!result2?.diff) return "Saved";
|
|
8615
|
+
const added = result2.diff.added_node_keys?.length ?? 0;
|
|
8616
|
+
const removed = result2.diff.removed_node_keys?.length ?? 0;
|
|
8037
8617
|
if (added === 0 && removed === 0) return "Saved \xB7 graph unchanged";
|
|
8038
8618
|
const parts = [];
|
|
8039
8619
|
if (added > 0) parts.push(`+${added}`);
|
|
@@ -8044,21 +8624,21 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8044
8624
|
const vocabType = node.properties?.vocabulary_type;
|
|
8045
8625
|
const colors = vocabType ? getVocabTypeColors(vocabType) : getNodeColors(node.nodeType);
|
|
8046
8626
|
const typeLabel = vocabType ? getVocabTypeLabel(vocabType) : getNodeTypeLabel(node.nodeType);
|
|
8047
|
-
const [showProperties, setShowProperties] =
|
|
8048
|
-
const [expandedChunks, setExpandedChunks] =
|
|
8049
|
-
const [isEditing, setIsEditing] =
|
|
8050
|
-
const [draftText, setDraftText] =
|
|
8051
|
-
const [localDescription, setLocalDescription] =
|
|
8052
|
-
const [isSaving, setIsSaving] =
|
|
8053
|
-
const [saveError, setSaveError] =
|
|
8054
|
-
const [lastSaveResult, setLastSaveResult] =
|
|
8055
|
-
const [saveProgressStage, setSaveProgressStage] =
|
|
8056
|
-
const currentNodeIdRef =
|
|
8057
|
-
const savedPillTimerRef =
|
|
8627
|
+
const [showProperties, setShowProperties] = React15.useState(false);
|
|
8628
|
+
const [expandedChunks, setExpandedChunks] = React15.useState(/* @__PURE__ */ new Set());
|
|
8629
|
+
const [isEditing, setIsEditing] = React15.useState(false);
|
|
8630
|
+
const [draftText, setDraftText] = React15.useState("");
|
|
8631
|
+
const [localDescription, setLocalDescription] = React15.useState(null);
|
|
8632
|
+
const [isSaving, setIsSaving] = React15.useState(false);
|
|
8633
|
+
const [saveError, setSaveError] = React15.useState(null);
|
|
8634
|
+
const [lastSaveResult, setLastSaveResult] = React15.useState(null);
|
|
8635
|
+
const [saveProgressStage, setSaveProgressStage] = React15.useState("starting");
|
|
8636
|
+
const currentNodeIdRef = React15.useRef(node.id);
|
|
8637
|
+
const savedPillTimerRef = React15.useRef(null);
|
|
8058
8638
|
const displayedDescription = localDescription ?? node.description ?? "";
|
|
8059
8639
|
const isLocallyEdited = localDescription !== null && localDescription !== (node.description ?? "");
|
|
8060
8640
|
const isDirty = isEditing && draftText !== displayedDescription;
|
|
8061
|
-
|
|
8641
|
+
React15.useEffect(() => {
|
|
8062
8642
|
currentNodeIdRef.current = node.id;
|
|
8063
8643
|
setIsEditing(false);
|
|
8064
8644
|
setLocalDescription(null);
|
|
@@ -8071,7 +8651,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8071
8651
|
savedPillTimerRef.current = null;
|
|
8072
8652
|
}
|
|
8073
8653
|
}, [node.id]);
|
|
8074
|
-
|
|
8654
|
+
React15.useEffect(() => {
|
|
8075
8655
|
if (!isSaving) return;
|
|
8076
8656
|
if (saveMode !== "reextract") {
|
|
8077
8657
|
setSaveProgressStage("embedding");
|
|
@@ -8087,7 +8667,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8087
8667
|
clearTimeout(t3);
|
|
8088
8668
|
};
|
|
8089
8669
|
}, [isSaving, saveMode]);
|
|
8090
|
-
|
|
8670
|
+
React15.useEffect(() => () => {
|
|
8091
8671
|
if (savedPillTimerRef.current) clearTimeout(savedPillTimerRef.current);
|
|
8092
8672
|
}, []);
|
|
8093
8673
|
const handleStartEdit = () => {
|
|
@@ -8112,11 +8692,11 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8112
8692
|
setIsSaving(true);
|
|
8113
8693
|
try {
|
|
8114
8694
|
const rawResult = await onSaveDescription(draftAtSaveTime);
|
|
8115
|
-
const
|
|
8695
|
+
const result2 = rawResult ?? null;
|
|
8116
8696
|
if (currentNodeIdRef.current === savingForNodeId) {
|
|
8117
8697
|
setLocalDescription(draftAtSaveTime);
|
|
8118
8698
|
setIsEditing(false);
|
|
8119
|
-
setLastSaveResult(
|
|
8699
|
+
setLastSaveResult(result2);
|
|
8120
8700
|
if (savedPillTimerRef.current) clearTimeout(savedPillTimerRef.current);
|
|
8121
8701
|
savedPillTimerRef.current = setTimeout(() => {
|
|
8122
8702
|
setLastSaveResult(null);
|
|
@@ -8148,7 +8728,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8148
8728
|
onClose();
|
|
8149
8729
|
};
|
|
8150
8730
|
const PLATFORM_SLOT_RE = /<[^>]*(chunk|timestamp|source|when|date|where|location)[^>]*>/i;
|
|
8151
|
-
const renderedClaims =
|
|
8731
|
+
const renderedClaims = React15.useMemo(() => {
|
|
8152
8732
|
const seen = /* @__PURE__ */ new Set();
|
|
8153
8733
|
const out = [];
|
|
8154
8734
|
for (const cn of connectedNodes) {
|
|
@@ -8223,7 +8803,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8223
8803
|
}
|
|
8224
8804
|
return out;
|
|
8225
8805
|
}, [connectedNodes, node.label]);
|
|
8226
|
-
const claimGroups =
|
|
8806
|
+
const claimGroups = React15.useMemo(() => {
|
|
8227
8807
|
const byPredicate = /* @__PURE__ */ new Map();
|
|
8228
8808
|
for (const c of renderedClaims) {
|
|
8229
8809
|
const key = c.predicateClean || "(related)";
|
|
@@ -8238,11 +8818,11 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8238
8818
|
}).map(([predicate, items]) => ({ predicate, items }));
|
|
8239
8819
|
}, [renderedClaims]);
|
|
8240
8820
|
const sourceDocs = node.properties?.source_documents ?? [];
|
|
8241
|
-
const aliases =
|
|
8821
|
+
const aliases = React15.useMemo(() => {
|
|
8242
8822
|
const a = node.aliases ?? [];
|
|
8243
8823
|
return a.filter((v) => v && v.toLowerCase() !== node.label.toLowerCase());
|
|
8244
8824
|
}, [node.aliases, node.label]);
|
|
8245
|
-
const speakerMeta =
|
|
8825
|
+
const speakerMeta = React15.useMemo(() => {
|
|
8246
8826
|
const raw = node.source?.trim();
|
|
8247
8827
|
if (!raw) return null;
|
|
8248
8828
|
if (raw === "system_extractor") return { label: "System extractor", klass: "extractor" };
|
|
@@ -8253,7 +8833,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8253
8833
|
return { label: raw.replace(/_/g, " "), klass: "other" };
|
|
8254
8834
|
}, [node.source]);
|
|
8255
8835
|
const graphLayer = node.graphLayer || node.properties?.graph_layer;
|
|
8256
|
-
const HIDDEN_PROPERTY_KEYS =
|
|
8836
|
+
const HIDDEN_PROPERTY_KEYS = React15.useMemo(() => /* @__PURE__ */ new Set([
|
|
8257
8837
|
"vocabulary_type",
|
|
8258
8838
|
"claim_status",
|
|
8259
8839
|
"settled",
|
|
@@ -8269,7 +8849,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8269
8849
|
"sample_labels",
|
|
8270
8850
|
"view"
|
|
8271
8851
|
]), []);
|
|
8272
|
-
const visibleProperties =
|
|
8852
|
+
const visibleProperties = React15.useMemo(() => {
|
|
8273
8853
|
const src = node.properties ?? {};
|
|
8274
8854
|
const out = {};
|
|
8275
8855
|
for (const [k, v] of Object.entries(src)) {
|
|
@@ -8278,23 +8858,23 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8278
8858
|
}
|
|
8279
8859
|
return out;
|
|
8280
8860
|
}, [node.properties, HIDDEN_PROPERTY_KEYS]);
|
|
8281
|
-
const reviewIndex =
|
|
8861
|
+
const reviewIndex = React15.useMemo(() => {
|
|
8282
8862
|
if (!reviewNodeIds || reviewNodeIds.length === 0) return -1;
|
|
8283
8863
|
return reviewNodeIds.indexOf(node.id);
|
|
8284
8864
|
}, [reviewNodeIds, node.id]);
|
|
8285
8865
|
const hasPrev = reviewIndex > 0;
|
|
8286
8866
|
const hasNext = reviewNodeIds ? reviewIndex < reviewNodeIds.length - 1 : false;
|
|
8287
8867
|
const isChunk = node.nodeType === "chunk";
|
|
8288
|
-
const noteTitle =
|
|
8868
|
+
const noteTitle = React15.useMemo(() => {
|
|
8289
8869
|
if (!isChunk || !displayedDescription) return null;
|
|
8290
8870
|
const match = displayedDescription.match(/^#{1,4}\s+(.+)/m);
|
|
8291
8871
|
return match ? match[1].trim() : null;
|
|
8292
8872
|
}, [isChunk, displayedDescription]);
|
|
8293
|
-
const chunkEntities =
|
|
8873
|
+
const chunkEntities = React15.useMemo(() => {
|
|
8294
8874
|
if (!isChunk) return [];
|
|
8295
8875
|
return connectedNodes.map((cn) => ({ id: cn.id, label: cn.label, nodeType: cn.nodeType }));
|
|
8296
8876
|
}, [isChunk, connectedNodes]);
|
|
8297
|
-
const [showMeta, setShowMeta] =
|
|
8877
|
+
const [showMeta, setShowMeta] = React15.useState(false);
|
|
8298
8878
|
const entityCount = node.properties?.entity_count;
|
|
8299
8879
|
const relationshipCount = node.properties?.relationship_count;
|
|
8300
8880
|
const reviewNav = reviewNodeIds && reviewNodeIds.length > 1 && reviewIndex >= 0 && onReviewNavigate ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -8652,11 +9232,11 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8652
9232
|
renderedClaims.length,
|
|
8653
9233
|
")"
|
|
8654
9234
|
] }),
|
|
8655
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: claimGroups.map((
|
|
8656
|
-
const isRelated =
|
|
9235
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: claimGroups.map((group2) => {
|
|
9236
|
+
const isRelated = group2.predicate === "(related)";
|
|
8657
9237
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
8658
|
-
|
|
8659
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0.5", children:
|
|
9238
|
+
group2.items.length > 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-gray-500 italic mb-0.5 px-2", children: group2.predicate }),
|
|
9239
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0.5", children: group2.items.map((claim) => {
|
|
8660
9240
|
const cnColors = getNodeColors(claim.targetType);
|
|
8661
9241
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8662
9242
|
"button",
|
|
@@ -8694,7 +9274,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8694
9274
|
claim.key
|
|
8695
9275
|
);
|
|
8696
9276
|
}) })
|
|
8697
|
-
] },
|
|
9277
|
+
] }, group2.predicate);
|
|
8698
9278
|
}) })
|
|
8699
9279
|
] }),
|
|
8700
9280
|
Object.keys(visibleProperties).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
@@ -8839,8 +9419,8 @@ function EdgeDetailDrawer({ edge, annotations, onClose, onNavigate }) {
|
|
|
8839
9419
|
] });
|
|
8840
9420
|
}
|
|
8841
9421
|
function EditableField({ label, value, placeholder, onSave, color }) {
|
|
8842
|
-
const [editing, setEditing] =
|
|
8843
|
-
const [editVal, setEditVal] =
|
|
9422
|
+
const [editing, setEditing] = React15.useState(false);
|
|
9423
|
+
const [editVal, setEditVal] = React15.useState(value);
|
|
8844
9424
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: 20 }, children: [
|
|
8845
9425
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 10, textTransform: "uppercase", letterSpacing: 1, marginBottom: 6 }, children: label }),
|
|
8846
9426
|
editing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -8884,15 +9464,15 @@ function EditableField({ label, value, placeholder, onSave, color }) {
|
|
|
8884
9464
|
] });
|
|
8885
9465
|
}
|
|
8886
9466
|
function TeamStage({ agents, onSendAction, onUpdateAgent, onRemoveAgent, onAddAgent }) {
|
|
8887
|
-
const [editingId, setEditingId] =
|
|
8888
|
-
const [editField, setEditField] =
|
|
8889
|
-
const [editValue, setEditValue] =
|
|
8890
|
-
const [addingAgent, setAddingAgent] =
|
|
8891
|
-
const [newName, setNewName] =
|
|
8892
|
-
const [newRole, setNewRole] =
|
|
8893
|
-
const [confirmDeleteId, setConfirmDeleteId] =
|
|
8894
|
-
const [selectedAgent, setSelectedAgent] =
|
|
8895
|
-
const [hoveredId, setHoveredId] =
|
|
9467
|
+
const [editingId, setEditingId] = React15.useState(null);
|
|
9468
|
+
const [editField, setEditField] = React15.useState(null);
|
|
9469
|
+
const [editValue, setEditValue] = React15.useState("");
|
|
9470
|
+
const [addingAgent, setAddingAgent] = React15.useState(false);
|
|
9471
|
+
const [newName, setNewName] = React15.useState("");
|
|
9472
|
+
const [newRole, setNewRole] = React15.useState("");
|
|
9473
|
+
const [confirmDeleteId, setConfirmDeleteId] = React15.useState(null);
|
|
9474
|
+
const [selectedAgent, setSelectedAgent] = React15.useState(null);
|
|
9475
|
+
const [hoveredId, setHoveredId] = React15.useState(null);
|
|
8896
9476
|
const startEdit = (agent, field) => {
|
|
8897
9477
|
setEditingId(agent.id);
|
|
8898
9478
|
setEditField(field);
|
|
@@ -9308,8 +9888,8 @@ var RECRUITING_LINES = [
|
|
|
9308
9888
|
"Briefing the team on the working group context\u2026"
|
|
9309
9889
|
];
|
|
9310
9890
|
function RecruitingHint() {
|
|
9311
|
-
const [idx, setIdx] =
|
|
9312
|
-
|
|
9891
|
+
const [idx, setIdx] = React15.useState(0);
|
|
9892
|
+
React15__default.default.useEffect(() => {
|
|
9313
9893
|
const t = setInterval(() => setIdx((i) => (i + 1) % RECRUITING_LINES.length), 2500);
|
|
9314
9894
|
return () => clearInterval(t);
|
|
9315
9895
|
}, []);
|
|
@@ -9412,7 +9992,7 @@ function RelationshipSentence({ rel }) {
|
|
|
9412
9992
|
const hasRange = rel.range.length > 0;
|
|
9413
9993
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { lineHeight: 2, color: "#888", fontSize: 13, wordBreak: "break-word" }, children: [
|
|
9414
9994
|
hasDomain && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9415
|
-
rel.domain.map((d, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
9995
|
+
rel.domain.map((d, i) => /* @__PURE__ */ jsxRuntime.jsxs(React15__default.default.Fragment, { children: [
|
|
9416
9996
|
i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#666" }, children: " or " }),
|
|
9417
9997
|
/* @__PURE__ */ jsxRuntime.jsx(TypeChip, { name: d })
|
|
9418
9998
|
] }, d)),
|
|
@@ -9421,7 +10001,7 @@ function RelationshipSentence({ rel }) {
|
|
|
9421
10001
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#ddd", fontStyle: "italic", fontWeight: 500 }, children: verb }),
|
|
9422
10002
|
hasRange && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9423
10003
|
" ",
|
|
9424
|
-
rel.range.map((r, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10004
|
+
rel.range.map((r, i) => /* @__PURE__ */ jsxRuntime.jsxs(React15__default.default.Fragment, { children: [
|
|
9425
10005
|
i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#666" }, children: " and " }),
|
|
9426
10006
|
/* @__PURE__ */ jsxRuntime.jsx(TypeChip, { name: r })
|
|
9427
10007
|
] }, r))
|
|
@@ -9437,14 +10017,14 @@ function SchemaStage({
|
|
|
9437
10017
|
edgeTypeCount,
|
|
9438
10018
|
onSendAction
|
|
9439
10019
|
}) {
|
|
9440
|
-
const [renamingType, setRenamingType] =
|
|
9441
|
-
const [renameValue, setRenameValue] =
|
|
9442
|
-
const [addingType, setAddingType] =
|
|
9443
|
-
const [newTypeName, setNewTypeName] =
|
|
9444
|
-
const [addingRel, setAddingRel] =
|
|
9445
|
-
const [newRelName, setNewRelName] =
|
|
9446
|
-
const [newRelDomain, setNewRelDomain] =
|
|
9447
|
-
const [newRelRange, setNewRelRange] =
|
|
10020
|
+
const [renamingType, setRenamingType] = React15.useState(null);
|
|
10021
|
+
const [renameValue, setRenameValue] = React15.useState("");
|
|
10022
|
+
const [addingType, setAddingType] = React15.useState(false);
|
|
10023
|
+
const [newTypeName, setNewTypeName] = React15.useState("");
|
|
10024
|
+
const [addingRel, setAddingRel] = React15.useState(false);
|
|
10025
|
+
const [newRelName, setNewRelName] = React15.useState("");
|
|
10026
|
+
const [newRelDomain, setNewRelDomain] = React15.useState("");
|
|
10027
|
+
const [newRelRange, setNewRelRange] = React15.useState("");
|
|
9448
10028
|
const removeType = (name) => {
|
|
9449
10029
|
onSendAction(`remove the "${name}" type from the schema`);
|
|
9450
10030
|
};
|
|
@@ -9900,8 +10480,8 @@ var DOCUMENT_PIPELINE_STEPS = [
|
|
|
9900
10480
|
{ key: "complete", label: "Done" }
|
|
9901
10481
|
];
|
|
9902
10482
|
function DocumentProcessingProgress() {
|
|
9903
|
-
const [state, setState] =
|
|
9904
|
-
|
|
10483
|
+
const [state, setState] = React15.useState(null);
|
|
10484
|
+
React15.useEffect(() => {
|
|
9905
10485
|
const handler = (e) => {
|
|
9906
10486
|
const event = e.detail;
|
|
9907
10487
|
if (!event?.step) return;
|
|
@@ -9941,7 +10521,7 @@ function DocumentProcessingProgress() {
|
|
|
9941
10521
|
if (!state) return null;
|
|
9942
10522
|
const currentIdx = DOCUMENT_PIPELINE_STEPS.findIndex((s) => s.key === state.step);
|
|
9943
10523
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "px-3 py-1.5 flex flex-col gap-1", style: { borderBottom: "1px solid #282828", backgroundColor: "#1a1a1a" }, children: [
|
|
9944
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0", children: DOCUMENT_PIPELINE_STEPS.map((step, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10524
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "flex items-center gap-0", children: DOCUMENT_PIPELINE_STEPS.map((step, i) => /* @__PURE__ */ jsxRuntime.jsxs(React15__default.default.Fragment, { children: [
|
|
9945
10525
|
i > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-px mx-0.5", style: { backgroundColor: i <= currentIdx ? "#10b981" : "#333" } }),
|
|
9946
10526
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9947
10527
|
"span",
|
|
@@ -10139,7 +10719,7 @@ function useStageActionBridge({
|
|
|
10139
10719
|
kgId,
|
|
10140
10720
|
agentsApiUrl
|
|
10141
10721
|
}) {
|
|
10142
|
-
|
|
10722
|
+
React15.useEffect(() => {
|
|
10143
10723
|
const threadMode = !!threadId && !!onPostMessage;
|
|
10144
10724
|
const pipelineMode = !!runId && !!agentsApiUrl;
|
|
10145
10725
|
if (!threadMode && !pipelineMode) return;
|
|
@@ -10225,10 +10805,10 @@ function hydrateAgentIds(ids) {
|
|
|
10225
10805
|
};
|
|
10226
10806
|
});
|
|
10227
10807
|
}
|
|
10228
|
-
function stageReducer(state,
|
|
10229
|
-
switch (
|
|
10808
|
+
function stageReducer(state, action2) {
|
|
10809
|
+
switch (action2.type) {
|
|
10230
10810
|
case "TEAM_SETUP": {
|
|
10231
|
-
const incomingIds = new Set(
|
|
10811
|
+
const incomingIds = new Set(action2.agents.map((a) => a.id));
|
|
10232
10812
|
let isWholesaleReplace = state.lastBackendTeamIds.size > 0;
|
|
10233
10813
|
if (isWholesaleReplace) {
|
|
10234
10814
|
state.lastBackendTeamIds.forEach((id) => {
|
|
@@ -10246,48 +10826,48 @@ function stageReducer(state, action) {
|
|
|
10246
10826
|
return {
|
|
10247
10827
|
...state,
|
|
10248
10828
|
stage: "team_formation",
|
|
10249
|
-
team: [...
|
|
10829
|
+
team: [...action2.agents, ...surviving],
|
|
10250
10830
|
localOnlyAgentIds: nextLocalOnly,
|
|
10251
10831
|
lastBackendTeamIds: incomingIds
|
|
10252
10832
|
};
|
|
10253
10833
|
}
|
|
10254
10834
|
case "PHASE_ADVANCED": {
|
|
10255
|
-
const to =
|
|
10835
|
+
const to = action2.to;
|
|
10256
10836
|
if (to === "team_formation") return { ...state, stage: "team_formation" };
|
|
10257
10837
|
if (to === "schema_seeding") return { ...state, stage: "schema_seeding" };
|
|
10258
10838
|
if (to === "construction" || to === "synthesis" || to === "done") return { ...state, stage: "graph" };
|
|
10259
10839
|
return state;
|
|
10260
10840
|
}
|
|
10261
10841
|
case "UPDATE_AGENT":
|
|
10262
|
-
return { ...state, team: state.team.map((a) => a.id ===
|
|
10842
|
+
return { ...state, team: state.team.map((a) => a.id === action2.id ? { ...a, ...action2.updates } : a) };
|
|
10263
10843
|
case "REMOVE_AGENT": {
|
|
10264
10844
|
const nextLocalOnly = new Set(state.localOnlyAgentIds);
|
|
10265
|
-
nextLocalOnly.delete(
|
|
10845
|
+
nextLocalOnly.delete(action2.id);
|
|
10266
10846
|
return {
|
|
10267
10847
|
...state,
|
|
10268
|
-
team: state.team.filter((a) => a.id !==
|
|
10848
|
+
team: state.team.filter((a) => a.id !== action2.id),
|
|
10269
10849
|
localOnlyAgentIds: nextLocalOnly
|
|
10270
10850
|
};
|
|
10271
10851
|
}
|
|
10272
10852
|
case "ADD_AGENT": {
|
|
10273
10853
|
const nextLocalOnly = new Set(state.localOnlyAgentIds);
|
|
10274
|
-
nextLocalOnly.add(
|
|
10854
|
+
nextLocalOnly.add(action2.agent.id);
|
|
10275
10855
|
return {
|
|
10276
10856
|
...state,
|
|
10277
|
-
team: [...state.team,
|
|
10857
|
+
team: [...state.team, action2.agent],
|
|
10278
10858
|
localOnlyAgentIds: nextLocalOnly
|
|
10279
10859
|
};
|
|
10280
10860
|
}
|
|
10281
10861
|
case "SCHEMA_SEEDED":
|
|
10282
|
-
return { ...state, schemaNodeTypeCount:
|
|
10862
|
+
return { ...state, schemaNodeTypeCount: action2.nodeTypeCount, schemaEdgeTypeCount: action2.edgeTypeCount };
|
|
10283
10863
|
case "SCHEMA_TYPE_ADDED":
|
|
10284
|
-
return { ...state, schemaNodeTypes: state.schemaNodeTypes.includes(
|
|
10864
|
+
return { ...state, schemaNodeTypes: state.schemaNodeTypes.includes(action2.typeName) ? state.schemaNodeTypes : [...state.schemaNodeTypes, action2.typeName] };
|
|
10285
10865
|
case "SCHEMA_TEXT": {
|
|
10286
10866
|
const rels = [];
|
|
10287
10867
|
const nodeTypes2 = new Set(state.schemaNodeTypes);
|
|
10288
10868
|
const relPattern = /(\w+)\s*:\s*\[([^\]]*)\]\s*→\s*\[([^\]]*)\]/g;
|
|
10289
10869
|
let m;
|
|
10290
|
-
while ((m = relPattern.exec(
|
|
10870
|
+
while ((m = relPattern.exec(action2.text)) !== null) {
|
|
10291
10871
|
const name = m[1];
|
|
10292
10872
|
const domain = m[2].split(",").map((s) => s.replace(/"/g, "").trim()).filter(Boolean);
|
|
10293
10873
|
const range = m[3].split(",").map((s) => s.replace(/"/g, "").trim()).filter(Boolean);
|
|
@@ -10302,7 +10882,7 @@ function stageReducer(state, action) {
|
|
|
10302
10882
|
};
|
|
10303
10883
|
}
|
|
10304
10884
|
case "DOC_STEP": {
|
|
10305
|
-
const step =
|
|
10885
|
+
const step = action2.step;
|
|
10306
10886
|
if (step === "complete") return { ...state, stage: "graph" };
|
|
10307
10887
|
if (step === "processing" || step === "vocabulary") return { ...state, stage: "doc_preparing" };
|
|
10308
10888
|
if (step === "extracting") return { ...state, stage: "doc_extracting" };
|
|
@@ -10311,7 +10891,7 @@ function stageReducer(state, action) {
|
|
|
10311
10891
|
return state;
|
|
10312
10892
|
}
|
|
10313
10893
|
case "DOC_ACTIVITY":
|
|
10314
|
-
return { ...state, docActivity: [...state.docActivity,
|
|
10894
|
+
return { ...state, docActivity: [...state.docActivity, action2.item] };
|
|
10315
10895
|
case "FORCE_GRAPH":
|
|
10316
10896
|
return { ...state, stage: "graph" };
|
|
10317
10897
|
default:
|
|
@@ -10332,7 +10912,7 @@ var initialState = {
|
|
|
10332
10912
|
docActivity: []
|
|
10333
10913
|
};
|
|
10334
10914
|
function StageCanvas({ nodeCount, onForceGraph, initialPhase, initialTeam, kgId }) {
|
|
10335
|
-
const [state, dispatch] =
|
|
10915
|
+
const [state, dispatch] = React15.useReducer(stageReducer, initialState, (base) => {
|
|
10336
10916
|
if (!initialPhase) return base;
|
|
10337
10917
|
let stage = "idle";
|
|
10338
10918
|
if (initialPhase === "team_formation") stage = "team_formation";
|
|
@@ -10341,13 +10921,13 @@ function StageCanvas({ nodeCount, onForceGraph, initialPhase, initialTeam, kgId
|
|
|
10341
10921
|
const team = initialTeam && initialTeam.length > 0 ? initialTeam : stage === "team_formation" ? hydrateAgentIds(["proposer", "critic", "synthesizer"]) : base.team;
|
|
10342
10922
|
return { ...base, stage, team };
|
|
10343
10923
|
});
|
|
10344
|
-
|
|
10924
|
+
React15.useEffect(() => {
|
|
10345
10925
|
if (initialPhase) dispatch({ type: "PHASE_ADVANCED", to: initialPhase });
|
|
10346
10926
|
}, [initialPhase]);
|
|
10347
|
-
|
|
10927
|
+
React15.useEffect(() => {
|
|
10348
10928
|
if (initialTeam && initialTeam.length > 0) dispatch({ type: "TEAM_SETUP", agents: initialTeam });
|
|
10349
10929
|
}, [initialTeam]);
|
|
10350
|
-
const handleProgressEvent =
|
|
10930
|
+
const handleProgressEvent = React15.useCallback((event) => {
|
|
10351
10931
|
if (!event?.type) return;
|
|
10352
10932
|
switch (event.type) {
|
|
10353
10933
|
case "TeamSetup":
|
|
@@ -10436,7 +11016,7 @@ function StageCanvas({ nodeCount, onForceGraph, initialPhase, initialTeam, kgId
|
|
|
10436
11016
|
}
|
|
10437
11017
|
}, []);
|
|
10438
11018
|
useScopedProgressEvent(kgId, handleProgressEvent);
|
|
10439
|
-
|
|
11019
|
+
React15.useEffect(() => {
|
|
10440
11020
|
const handler = (e) => {
|
|
10441
11021
|
const event = e.detail;
|
|
10442
11022
|
if (!event?.step) return;
|
|
@@ -10542,8 +11122,8 @@ var STATUS_COLORS = {
|
|
|
10542
11122
|
idle: "#6b7280"
|
|
10543
11123
|
};
|
|
10544
11124
|
function AgentPresenceBar({ listenForEvents = true, agents: agentsProp, kgId }) {
|
|
10545
|
-
const [agents, setAgents] =
|
|
10546
|
-
const handleAgentEvent =
|
|
11125
|
+
const [agents, setAgents] = React15.useState(/* @__PURE__ */ new Map());
|
|
11126
|
+
const handleAgentEvent = React15.useCallback((event) => {
|
|
10547
11127
|
if (!event?.type) return;
|
|
10548
11128
|
switch (event.type) {
|
|
10549
11129
|
case "TeamSetup": {
|
|
@@ -10958,7 +11538,7 @@ function ClaimNodeComponent({ data, selected }) {
|
|
|
10958
11538
|
/* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Bottom, style: { background: borderColor, border: "none", width: 6, height: 6 } })
|
|
10959
11539
|
] });
|
|
10960
11540
|
}
|
|
10961
|
-
var ClaimNode =
|
|
11541
|
+
var ClaimNode = React15.memo(ClaimNodeComponent);
|
|
10962
11542
|
function extractTitle(text) {
|
|
10963
11543
|
const headingMatch = text.match(/^#{1,4}\s+(.+)/m);
|
|
10964
11544
|
if (headingMatch) {
|
|
@@ -11057,7 +11637,7 @@ function NoteCardComponent({ data, selected }) {
|
|
|
11057
11637
|
/* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Bottom, style: { opacity: 0, width: 1, height: 1 } })
|
|
11058
11638
|
] });
|
|
11059
11639
|
}
|
|
11060
|
-
var NoteCard =
|
|
11640
|
+
var NoteCard = React15.memo(NoteCardComponent);
|
|
11061
11641
|
|
|
11062
11642
|
// src/knowledge/claimsProjection.ts
|
|
11063
11643
|
function buildClaimsGraph(nodes, edges) {
|
|
@@ -11128,13 +11708,13 @@ var PIPELINE_STEPS = [
|
|
|
11128
11708
|
{ key: "construction", label: "Building", short: "B" }
|
|
11129
11709
|
];
|
|
11130
11710
|
function PipelineProgressBar({ listenForEvents = true, currentPhase: currentPhaseProp, completedPhases: completedProp, kgId }) {
|
|
11131
|
-
const [currentPhase, setCurrentPhase] =
|
|
11132
|
-
const [completed, setCompleted] =
|
|
11133
|
-
const [backtracking, setBacktracking] =
|
|
11134
|
-
|
|
11711
|
+
const [currentPhase, setCurrentPhase] = React15.useState(currentPhaseProp || "");
|
|
11712
|
+
const [completed, setCompleted] = React15.useState(new Set(completedProp || []));
|
|
11713
|
+
const [backtracking, setBacktracking] = React15.useState(false);
|
|
11714
|
+
React15.useEffect(() => {
|
|
11135
11715
|
if (currentPhaseProp) setCurrentPhase(currentPhaseProp);
|
|
11136
11716
|
}, [currentPhaseProp]);
|
|
11137
|
-
const handlePipelineEvent =
|
|
11717
|
+
const handlePipelineEvent = React15.useCallback((event) => {
|
|
11138
11718
|
if (!event?.type) return;
|
|
11139
11719
|
const isAdvance = event.type === "PhaseAdvanced" || event.type === "transform_extension" && event.kind === "phase_advanced";
|
|
11140
11720
|
const isBacktrack = event.type === "PhaseBacktracked" || event.type === "transform_extension" && event.kind === "phase_backtracked";
|
|
@@ -11177,7 +11757,7 @@ function PipelineProgressBar({ listenForEvents = true, currentPhase: currentPhas
|
|
|
11177
11757
|
PIPELINE_STEPS.map((step, i) => {
|
|
11178
11758
|
const isCompleted = completed.has(step.key) || i < currentIdx;
|
|
11179
11759
|
const isCurrent = step.key === currentPhase;
|
|
11180
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11760
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React15__default.default.Fragment, { children: [
|
|
11181
11761
|
i > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11182
11762
|
"div",
|
|
11183
11763
|
{
|
|
@@ -11250,9 +11830,9 @@ var EMPTY_STATE = {
|
|
|
11250
11830
|
edgeCount: 0
|
|
11251
11831
|
};
|
|
11252
11832
|
function ConstructionProgress({ kgId } = {}) {
|
|
11253
|
-
const [state, setState] =
|
|
11254
|
-
const [isBuilding, setIsBuilding] =
|
|
11255
|
-
const handleConstructionEvent =
|
|
11833
|
+
const [state, setState] = React15.useState(null);
|
|
11834
|
+
const [isBuilding, setIsBuilding] = React15.useState(false);
|
|
11835
|
+
const handleConstructionEvent = React15.useCallback((event) => {
|
|
11256
11836
|
if (!event?.type) return;
|
|
11257
11837
|
const isAdvance = event.type === "PhaseAdvanced" || event.type === "transform_extension" && event.kind === "phase_advanced";
|
|
11258
11838
|
if (isAdvance && event.to === "construction") {
|
|
@@ -11361,12 +11941,12 @@ function ConstructionProgress({ kgId } = {}) {
|
|
|
11361
11941
|
}
|
|
11362
11942
|
var MAX_ADOPTED_KG_IDS = 16;
|
|
11363
11943
|
function useAdoptedKgIds(kgId) {
|
|
11364
|
-
const adoptedKgIdsRef =
|
|
11365
|
-
const kgIdRef =
|
|
11366
|
-
|
|
11944
|
+
const adoptedKgIdsRef = React15.useRef(/* @__PURE__ */ new Set());
|
|
11945
|
+
const kgIdRef = React15.useRef(kgId);
|
|
11946
|
+
React15.useEffect(() => {
|
|
11367
11947
|
kgIdRef.current = kgId;
|
|
11368
11948
|
}, [kgId]);
|
|
11369
|
-
const adoptKgIdFromChunk =
|
|
11949
|
+
const adoptKgIdFromChunk = React15.useCallback(
|
|
11370
11950
|
(chunk, progress) => {
|
|
11371
11951
|
if (isFixedKgId(kgIdRef.current)) return;
|
|
11372
11952
|
const fromChunk = extractKgId(chunk, progress);
|
|
@@ -11379,7 +11959,7 @@ function useAdoptedKgIds(kgId) {
|
|
|
11379
11959
|
},
|
|
11380
11960
|
[]
|
|
11381
11961
|
);
|
|
11382
|
-
const hasOwnedKgId =
|
|
11962
|
+
const hasOwnedKgId = React15.useCallback((id) => {
|
|
11383
11963
|
if (id === kgIdRef.current) return true;
|
|
11384
11964
|
return adoptedKgIdsRef.current.has(id);
|
|
11385
11965
|
}, []);
|
|
@@ -11394,7 +11974,7 @@ function useReasoningKeepalive({
|
|
|
11394
11974
|
authToken
|
|
11395
11975
|
}) {
|
|
11396
11976
|
const isRealKg = isFixedKgId(kgId);
|
|
11397
|
-
|
|
11977
|
+
React15.useEffect(() => {
|
|
11398
11978
|
if (!isRealKg || !runId || isLiveReasoning || !agentsApiUrl) return;
|
|
11399
11979
|
const abort = new AbortController();
|
|
11400
11980
|
const broadcastProgress = (event) => {
|
|
@@ -11425,12 +12005,12 @@ function useCheckpointCard({
|
|
|
11425
12005
|
isLoadedSession,
|
|
11426
12006
|
initialPhase
|
|
11427
12007
|
}) {
|
|
11428
|
-
const [checkpoint, setCheckpoint] =
|
|
11429
|
-
const currentPhaseRef =
|
|
11430
|
-
|
|
12008
|
+
const [checkpoint, setCheckpoint] = React15.useState(null);
|
|
12009
|
+
const currentPhaseRef = React15.useRef(initialPhase || "");
|
|
12010
|
+
React15.useEffect(() => {
|
|
11431
12011
|
if (initialPhase) currentPhaseRef.current = initialPhase;
|
|
11432
12012
|
}, [initialPhase]);
|
|
11433
|
-
const handler =
|
|
12013
|
+
const handler = React15.useCallback(
|
|
11434
12014
|
(event) => {
|
|
11435
12015
|
if (!event?.type) return;
|
|
11436
12016
|
if (event.type === "PhaseAdvanced" || event.type === "PhaseBacktracked" || event.type === "transform_extension") {
|
|
@@ -11475,7 +12055,7 @@ function useCheckpointCard({
|
|
|
11475
12055
|
handler,
|
|
11476
12056
|
(!!threadId || !!runId) && !isLoadedSession
|
|
11477
12057
|
);
|
|
11478
|
-
const setCheckpointResponded =
|
|
12058
|
+
const setCheckpointResponded = React15.useCallback(() => {
|
|
11479
12059
|
setCheckpoint((prev) => prev ? { ...prev, responded: true } : null);
|
|
11480
12060
|
}, []);
|
|
11481
12061
|
return { checkpoint, setCheckpointResponded };
|
|
@@ -11511,10 +12091,10 @@ function GraphChatPanel({
|
|
|
11511
12091
|
reasoningPhase,
|
|
11512
12092
|
authToken
|
|
11513
12093
|
}) {
|
|
11514
|
-
const accumulatedTextRef =
|
|
11515
|
-
const conversationRef =
|
|
11516
|
-
const historyRef =
|
|
11517
|
-
const [loadedHistory, setLoadedHistory] =
|
|
12094
|
+
const accumulatedTextRef = React15.useRef("");
|
|
12095
|
+
const conversationRef = React15.useRef([]);
|
|
12096
|
+
const historyRef = React15.useRef(null);
|
|
12097
|
+
const [loadedHistory, setLoadedHistory] = React15.useState(null);
|
|
11518
12098
|
const { adoptKgIdFromChunk, hasOwnedKgId } = useAdoptedKgIds(kgId);
|
|
11519
12099
|
useReasoningKeepalive({
|
|
11520
12100
|
kgId,
|
|
@@ -11523,7 +12103,7 @@ function GraphChatPanel({
|
|
|
11523
12103
|
agentsApiUrl: config.agentsApiUrl,
|
|
11524
12104
|
authToken
|
|
11525
12105
|
});
|
|
11526
|
-
const narrativeHandler =
|
|
12106
|
+
const narrativeHandler = React15.useCallback((event) => {
|
|
11527
12107
|
if (event?.type !== "transform_extension" || event?.kind !== "narrative_text") return;
|
|
11528
12108
|
const text = event?.payload?.text;
|
|
11529
12109
|
if (typeof text !== "string" || !text.trim()) return;
|
|
@@ -11559,7 +12139,7 @@ function GraphChatPanel({
|
|
|
11559
12139
|
kgId,
|
|
11560
12140
|
agentsApiUrl: config.agentsApiUrl
|
|
11561
12141
|
});
|
|
11562
|
-
const deduplicateMessages =
|
|
12142
|
+
const deduplicateMessages = React15.useCallback((sorted) => {
|
|
11563
12143
|
return sorted.filter((msg, i) => {
|
|
11564
12144
|
if (i === 0) return true;
|
|
11565
12145
|
const prev = sorted[i - 1];
|
|
@@ -11567,7 +12147,7 @@ function GraphChatPanel({
|
|
|
11567
12147
|
return true;
|
|
11568
12148
|
});
|
|
11569
12149
|
}, []);
|
|
11570
|
-
const mapMessages =
|
|
12150
|
+
const mapMessages = React15.useCallback((msgs) => {
|
|
11571
12151
|
const nonEmpty = msgs.filter((m) => typeof m.content === "string" && m.content.trim().length > 0);
|
|
11572
12152
|
const sorted = nonEmpty.sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
|
|
11573
12153
|
const deduped = deduplicateMessages(sorted);
|
|
@@ -11590,7 +12170,7 @@ function GraphChatPanel({
|
|
|
11590
12170
|
};
|
|
11591
12171
|
});
|
|
11592
12172
|
}, [deduplicateMessages, currentUser]);
|
|
11593
|
-
|
|
12173
|
+
React15.useEffect(() => {
|
|
11594
12174
|
if (!threadId) {
|
|
11595
12175
|
console.warn("[GraphChatPanel] no threadId \u2014 skipping history load", { groupId, kgId });
|
|
11596
12176
|
return;
|
|
@@ -11629,7 +12209,7 @@ function GraphChatPanel({
|
|
|
11629
12209
|
cancelled = true;
|
|
11630
12210
|
};
|
|
11631
12211
|
}, [groupId, threadId, mapMessages]);
|
|
11632
|
-
const onPollMessages =
|
|
12212
|
+
const onPollMessages = React15.useCallback(async () => {
|
|
11633
12213
|
if (!threadId) return [];
|
|
11634
12214
|
try {
|
|
11635
12215
|
const msgs = await onLoadMessages(groupId, threadId);
|
|
@@ -11642,14 +12222,14 @@ function GraphChatPanel({
|
|
|
11642
12222
|
return [];
|
|
11643
12223
|
}
|
|
11644
12224
|
}, [groupId, threadId, mapMessages]);
|
|
11645
|
-
const defaultHistory =
|
|
12225
|
+
const defaultHistory = React15.useMemo(() => [
|
|
11646
12226
|
{
|
|
11647
12227
|
type: "system",
|
|
11648
12228
|
content: threadId ? "Reasoning session \u2014 agent progress and your questions appear here." : "Ask questions about this document. Answers are grounded in the knowledge graph.",
|
|
11649
12229
|
timestamp: /* @__PURE__ */ new Date()
|
|
11650
12230
|
}
|
|
11651
12231
|
], [threadId]);
|
|
11652
|
-
const resumeOrInputPipeline =
|
|
12232
|
+
const resumeOrInputPipeline = React15.useCallback(async (message) => {
|
|
11653
12233
|
if (!runId || !config.agentsApiUrl) return;
|
|
11654
12234
|
if (checkpoint) setCheckpointResponded();
|
|
11655
12235
|
const trimmed = message.trim();
|
|
@@ -11662,7 +12242,7 @@ function GraphChatPanel({
|
|
|
11662
12242
|
});
|
|
11663
12243
|
historyRef.current?.setIsExecuting?.(false);
|
|
11664
12244
|
}, [runId, checkpoint, config.agentsApiUrl, setCheckpointResponded]);
|
|
11665
|
-
const onSendMessage =
|
|
12245
|
+
const onSendMessage = React15.useCallback(async (content) => {
|
|
11666
12246
|
if (runId && !threadId && checkpoint) {
|
|
11667
12247
|
historyRef.current?.setIsExecuting?.(true);
|
|
11668
12248
|
resumeOrInputPipeline(content).catch(() => {
|
|
@@ -11695,7 +12275,7 @@ function GraphChatPanel({
|
|
|
11695
12275
|
sender: currentUser
|
|
11696
12276
|
};
|
|
11697
12277
|
}, [groupId, threadId, runId, currentUser, resumeOrInputPipeline]);
|
|
11698
|
-
const extractSources =
|
|
12278
|
+
const extractSources = React15.useCallback((text) => {
|
|
11699
12279
|
const lower = text.toLowerCase();
|
|
11700
12280
|
const matched = [];
|
|
11701
12281
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -11740,7 +12320,7 @@ function GraphChatPanel({
|
|
|
11740
12320
|
}
|
|
11741
12321
|
return matched;
|
|
11742
12322
|
}, [rawNodes]);
|
|
11743
|
-
const onStreamRequest =
|
|
12323
|
+
const onStreamRequest = React15.useCallback(async (command, handlers) => {
|
|
11744
12324
|
accumulatedTextRef.current = "";
|
|
11745
12325
|
let senderOverridden = false;
|
|
11746
12326
|
let mentionedAgent;
|
|
@@ -11852,7 +12432,7 @@ ${kgContext}` : ""}`,
|
|
|
11852
12432
|
handlers.onError
|
|
11853
12433
|
);
|
|
11854
12434
|
}, [groupId, kgId, threadId, onHighlightNodes, extractSources, config.agentsApiUrl, onStreamChat, adoptKgIdFromChunk]);
|
|
11855
|
-
const sourceKGNodes =
|
|
12435
|
+
const sourceKGNodes = React15.useMemo(
|
|
11856
12436
|
() => rawNodes.map((n) => ({
|
|
11857
12437
|
id: n.node_key,
|
|
11858
12438
|
label: n.label,
|
|
@@ -11868,7 +12448,7 @@ ${kgContext}` : ""}`,
|
|
|
11868
12448
|
})),
|
|
11869
12449
|
[rawNodes]
|
|
11870
12450
|
);
|
|
11871
|
-
const mentionTargets =
|
|
12451
|
+
const mentionTargets = React15.useMemo(() => {
|
|
11872
12452
|
const agentKeys = /* @__PURE__ */ new Set();
|
|
11873
12453
|
for (const n of rawNodes) {
|
|
11874
12454
|
const key = n.source_agent_key || n.created_by || n.properties?.created_by || n.properties?.source_agent_key;
|
|
@@ -11978,8 +12558,8 @@ function extractTitle2(text) {
|
|
|
11978
12558
|
function stripMarkdown2(text) {
|
|
11979
12559
|
return text.replace(/#{1,6}\s+/g, "").replace(/\*\*(.+?)\*\*/g, "$1").replace(/\*(.+?)\*/g, "$1").replace(/`(.+?)`/g, "$1").replace(/\[(.+?)\]\(.+?\)/g, "$1").replace(/^[-*+]\s+/gm, "").replace(/^\d+\.\s+/gm, "").replace(/\n{2,}/g, " ").trim();
|
|
11980
12560
|
}
|
|
11981
|
-
var NotesList =
|
|
11982
|
-
const allNotes =
|
|
12561
|
+
var NotesList = React15.memo(function NotesList2({ chunks, selectedId, onSelect, onCreateNote, filter }) {
|
|
12562
|
+
const allNotes = React15.useMemo(() => {
|
|
11983
12563
|
const byChunk = /* @__PURE__ */ new Map();
|
|
11984
12564
|
for (const link of chunks) {
|
|
11985
12565
|
const list = byChunk.get(link.chunk_id) ?? [];
|
|
@@ -12000,7 +12580,7 @@ var NotesList = React12.memo(function NotesList2({ chunks, selectedId, onSelect,
|
|
|
12000
12580
|
groups.sort((a, b) => (a.chunkIndex ?? Infinity) - (b.chunkIndex ?? Infinity));
|
|
12001
12581
|
return groups;
|
|
12002
12582
|
}, [chunks]);
|
|
12003
|
-
const notes =
|
|
12583
|
+
const notes = React15.useMemo(() => {
|
|
12004
12584
|
if (!filter || !filter.trim()) return allNotes;
|
|
12005
12585
|
const q = filter.toLowerCase().trim();
|
|
12006
12586
|
return allNotes.filter((n) => n.excerpt.toLowerCase().includes(q));
|
|
@@ -12200,19 +12780,19 @@ function NoteExtractionToast({
|
|
|
12200
12780
|
onRunFailed,
|
|
12201
12781
|
authToken
|
|
12202
12782
|
}) {
|
|
12203
|
-
const [phase, setPhase] =
|
|
12204
|
-
const [successFlash, setSuccessFlash] =
|
|
12205
|
-
const [error, setError] =
|
|
12206
|
-
const abortsRef =
|
|
12207
|
-
const onRunCompleteRef =
|
|
12208
|
-
const onRunFailedRef =
|
|
12209
|
-
|
|
12783
|
+
const [phase, setPhase] = React15.useState("Saving note\u2026");
|
|
12784
|
+
const [successFlash, setSuccessFlash] = React15.useState(false);
|
|
12785
|
+
const [error, setError] = React15.useState(null);
|
|
12786
|
+
const abortsRef = React15.useRef(/* @__PURE__ */ new Map());
|
|
12787
|
+
const onRunCompleteRef = React15.useRef(onRunComplete);
|
|
12788
|
+
const onRunFailedRef = React15.useRef(onRunFailed);
|
|
12789
|
+
React15.useEffect(() => {
|
|
12210
12790
|
onRunCompleteRef.current = onRunComplete;
|
|
12211
12791
|
}, [onRunComplete]);
|
|
12212
|
-
|
|
12792
|
+
React15.useEffect(() => {
|
|
12213
12793
|
onRunFailedRef.current = onRunFailed;
|
|
12214
12794
|
}, [onRunFailed]);
|
|
12215
|
-
|
|
12795
|
+
React15.useEffect(() => {
|
|
12216
12796
|
const controllers = abortsRef.current;
|
|
12217
12797
|
for (const run of runs) {
|
|
12218
12798
|
if (controllers.has(run.run_id)) continue;
|
|
@@ -12263,7 +12843,7 @@ function NoteExtractionToast({
|
|
|
12263
12843
|
}
|
|
12264
12844
|
}
|
|
12265
12845
|
}, [runs, agentsApiUrl, authToken]);
|
|
12266
|
-
|
|
12846
|
+
React15.useEffect(() => {
|
|
12267
12847
|
if (runs.length === 0 && !error) {
|
|
12268
12848
|
setSuccessFlash(true);
|
|
12269
12849
|
const t = setTimeout(() => setSuccessFlash(false), 1800);
|
|
@@ -12271,7 +12851,7 @@ function NoteExtractionToast({
|
|
|
12271
12851
|
}
|
|
12272
12852
|
if (runs.length > 0) setSuccessFlash(false);
|
|
12273
12853
|
}, [runs.length, error]);
|
|
12274
|
-
|
|
12854
|
+
React15.useEffect(() => {
|
|
12275
12855
|
return () => {
|
|
12276
12856
|
abortsRef.current.forEach((abort) => abort.abort());
|
|
12277
12857
|
abortsRef.current.clear();
|
|
@@ -12383,10 +12963,10 @@ function KnowledgeGraphView({
|
|
|
12383
12963
|
}) {
|
|
12384
12964
|
const [nodes, setNodes, onNodesChangeBase] = react.useNodesState([]);
|
|
12385
12965
|
const [edges, setEdges, onEdgesChange] = react.useEdgesState([]);
|
|
12386
|
-
const liveNodePositionsRef =
|
|
12387
|
-
const [activityItems, setActivityItems] =
|
|
12388
|
-
const prevActivityLenRef =
|
|
12389
|
-
|
|
12966
|
+
const liveNodePositionsRef = React15.useRef(/* @__PURE__ */ new Map());
|
|
12967
|
+
const [activityItems, setActivityItems] = React15.useState([]);
|
|
12968
|
+
const prevActivityLenRef = React15.useRef(0);
|
|
12969
|
+
React15.useEffect(() => {
|
|
12390
12970
|
if (!activityEvents || activityEvents.length <= prevActivityLenRef.current) {
|
|
12391
12971
|
prevActivityLenRef.current = activityEvents?.length || 0;
|
|
12392
12972
|
return;
|
|
@@ -12399,23 +12979,23 @@ function KnowledgeGraphView({
|
|
|
12399
12979
|
}
|
|
12400
12980
|
}, [activityEvents?.length]);
|
|
12401
12981
|
const useWindowEvents = !activityEvents;
|
|
12402
|
-
const [liveRefreshTrigger, setLiveRefreshTrigger] =
|
|
12403
|
-
const lastPersistRef =
|
|
12404
|
-
const pipelineDoneRef =
|
|
12405
|
-
const pendingActivityRef =
|
|
12406
|
-
const activityFlushRef =
|
|
12407
|
-
const flushActivity =
|
|
12982
|
+
const [liveRefreshTrigger, setLiveRefreshTrigger] = React15.useState(0);
|
|
12983
|
+
const lastPersistRef = React15.useRef(0);
|
|
12984
|
+
const pipelineDoneRef = React15.useRef(false);
|
|
12985
|
+
const pendingActivityRef = React15.useRef([]);
|
|
12986
|
+
const activityFlushRef = React15.useRef(null);
|
|
12987
|
+
const flushActivity = React15.useCallback(() => {
|
|
12408
12988
|
activityFlushRef.current = null;
|
|
12409
12989
|
if (pendingActivityRef.current.length === 0) return;
|
|
12410
12990
|
const batch = pendingActivityRef.current;
|
|
12411
12991
|
pendingActivityRef.current = [];
|
|
12412
12992
|
setActivityItems((prev) => [...prev, ...batch]);
|
|
12413
12993
|
}, []);
|
|
12414
|
-
|
|
12994
|
+
React15.useEffect(() => () => {
|
|
12415
12995
|
if (activityFlushRef.current) clearTimeout(activityFlushRef.current);
|
|
12416
12996
|
flushActivity();
|
|
12417
12997
|
}, [flushActivity]);
|
|
12418
|
-
const handleActivityEvent =
|
|
12998
|
+
const handleActivityEvent = React15.useCallback((event) => {
|
|
12419
12999
|
if (pipelineDoneRef.current) return;
|
|
12420
13000
|
const item = eventToActivity(event);
|
|
12421
13001
|
if (item) {
|
|
@@ -12438,8 +13018,8 @@ function KnowledgeGraphView({
|
|
|
12438
13018
|
}
|
|
12439
13019
|
}, [flushActivity]);
|
|
12440
13020
|
useScopedProgressEvent(kgId, handleActivityEvent, useWindowEvents);
|
|
12441
|
-
const [forceGraph, setForceGraph] =
|
|
12442
|
-
const onNodesChange =
|
|
13021
|
+
const [forceGraph, setForceGraph] = React15.useState(false);
|
|
13022
|
+
const onNodesChange = React15.useCallback((changes) => {
|
|
12443
13023
|
onNodesChangeBase(changes);
|
|
12444
13024
|
for (const change of changes) {
|
|
12445
13025
|
if (change.type === "position" && "position" in change && change.position) {
|
|
@@ -12447,29 +13027,29 @@ function KnowledgeGraphView({
|
|
|
12447
13027
|
}
|
|
12448
13028
|
}
|
|
12449
13029
|
}, [onNodesChangeBase]);
|
|
12450
|
-
const [loading, setLoading] =
|
|
12451
|
-
const [error, setError] =
|
|
12452
|
-
const [searchTerm, setSearchTerm] =
|
|
12453
|
-
const [phaseFilter, setPhaseFilter] =
|
|
12454
|
-
const [isFullscreen, setIsFullscreen] =
|
|
12455
|
-
const [selectedNodeId, setSelectedNodeId] =
|
|
12456
|
-
const [selectedEdgeId, setSelectedEdgeId] =
|
|
12457
|
-
const [hoveredNodeId, setHoveredNodeId] =
|
|
13030
|
+
const [loading, setLoading] = React15.useState(true);
|
|
13031
|
+
const [error, setError] = React15.useState(null);
|
|
13032
|
+
const [searchTerm, setSearchTerm] = React15.useState("");
|
|
13033
|
+
const [phaseFilter, setPhaseFilter] = React15.useState("all");
|
|
13034
|
+
const [isFullscreen, setIsFullscreen] = React15.useState(false);
|
|
13035
|
+
const [selectedNodeId, setSelectedNodeId] = React15.useState(null);
|
|
13036
|
+
const [selectedEdgeId, setSelectedEdgeId] = React15.useState(null);
|
|
13037
|
+
const [hoveredNodeId, setHoveredNodeId] = React15.useState(null);
|
|
12458
13038
|
const hasChat = !!(renderChat || config);
|
|
12459
|
-
const [chatOpen, setChatOpen] =
|
|
12460
|
-
const [chatMounted, setChatMounted] =
|
|
12461
|
-
|
|
13039
|
+
const [chatOpen, setChatOpen] = React15.useState(hasChat);
|
|
13040
|
+
const [chatMounted, setChatMounted] = React15.useState(hasChat);
|
|
13041
|
+
React15.useEffect(() => {
|
|
12462
13042
|
if (chatOpen && !chatMounted) setChatMounted(true);
|
|
12463
13043
|
}, [chatOpen]);
|
|
12464
|
-
|
|
13044
|
+
React15.useEffect(() => {
|
|
12465
13045
|
if ((runId || genericKGProp) && hasChat && !chatOpen) {
|
|
12466
13046
|
setChatOpen(true);
|
|
12467
13047
|
setChatMounted(true);
|
|
12468
13048
|
}
|
|
12469
13049
|
}, [runId, genericKGProp, hasChat]);
|
|
12470
|
-
const [chatQuery, setChatQuery] =
|
|
12471
|
-
const [ontologyOpen, setOntologyOpen] =
|
|
12472
|
-
|
|
13050
|
+
const [chatQuery, setChatQuery] = React15.useState(void 0);
|
|
13051
|
+
const [ontologyOpen, setOntologyOpen] = React15.useState(false);
|
|
13052
|
+
React15.useEffect(() => {
|
|
12473
13053
|
if (chatToggleRef) {
|
|
12474
13054
|
chatToggleRef.current = () => {
|
|
12475
13055
|
setChatOpen((v) => !v);
|
|
@@ -12480,43 +13060,43 @@ function KnowledgeGraphView({
|
|
|
12480
13060
|
};
|
|
12481
13061
|
}
|
|
12482
13062
|
}, [chatToggleRef]);
|
|
12483
|
-
const [searching, setSearching] =
|
|
12484
|
-
const [searchResult, setSearchResult] =
|
|
12485
|
-
const [searchActive, setSearchActive] =
|
|
12486
|
-
const searchTimerRef =
|
|
12487
|
-
const fitViewTimerRef =
|
|
12488
|
-
const rfInstanceRef =
|
|
12489
|
-
const didInitialFitRef =
|
|
12490
|
-
const [rfReady, setRfReady] =
|
|
12491
|
-
|
|
13063
|
+
const [searching, setSearching] = React15.useState(false);
|
|
13064
|
+
const [searchResult, setSearchResult] = React15.useState({ hits: [], traversal: [] });
|
|
13065
|
+
const [searchActive, setSearchActive] = React15.useState(false);
|
|
13066
|
+
const searchTimerRef = React15.useRef(null);
|
|
13067
|
+
const fitViewTimerRef = React15.useRef(null);
|
|
13068
|
+
const rfInstanceRef = React15.useRef(null);
|
|
13069
|
+
const didInitialFitRef = React15.useRef(false);
|
|
13070
|
+
const [rfReady, setRfReady] = React15.useState(false);
|
|
13071
|
+
React15.useEffect(() => {
|
|
12492
13072
|
didInitialFitRef.current = false;
|
|
12493
13073
|
setRfReady(false);
|
|
12494
13074
|
}, [kgId]);
|
|
12495
|
-
const gkgNodeMap =
|
|
13075
|
+
const gkgNodeMap = React15.useMemo(() => {
|
|
12496
13076
|
if (!genericKGProp) return /* @__PURE__ */ new Map();
|
|
12497
13077
|
return new Map(genericKGProp.nodes.map((n) => [n.id, n]));
|
|
12498
13078
|
}, [genericKGProp]);
|
|
12499
|
-
const gkgEdgeMap =
|
|
13079
|
+
const gkgEdgeMap = React15.useMemo(() => {
|
|
12500
13080
|
if (!genericKGProp) return /* @__PURE__ */ new Map();
|
|
12501
13081
|
return new Map(genericKGProp.edges.map((e) => [e.id, e]));
|
|
12502
13082
|
}, [genericKGProp]);
|
|
12503
|
-
const fullNodesRef =
|
|
12504
|
-
const fullEdgesRef =
|
|
12505
|
-
const [rawNodes, setRawNodes] =
|
|
12506
|
-
const [rawEdges, setRawEdges] =
|
|
12507
|
-
const [nodeChunks, setNodeChunks] =
|
|
13083
|
+
const fullNodesRef = React15.useRef([]);
|
|
13084
|
+
const fullEdgesRef = React15.useRef([]);
|
|
13085
|
+
const [rawNodes, setRawNodes] = React15.useState([]);
|
|
13086
|
+
const [rawEdges, setRawEdges] = React15.useState([]);
|
|
13087
|
+
const [nodeChunks, setNodeChunks] = React15.useState([]);
|
|
12508
13088
|
const hasLiveReasoning = !!runId || !!genericKGProp;
|
|
12509
|
-
const [viewMode, setViewMode] =
|
|
13089
|
+
const [viewMode, setViewMode] = React15.useState(
|
|
12510
13090
|
hasLiveReasoning ? "entity" : data.onLoadAllChunks ? "chunk" : "entity"
|
|
12511
13091
|
);
|
|
12512
|
-
const viewModeRef =
|
|
13092
|
+
const viewModeRef = React15.useRef(viewMode);
|
|
12513
13093
|
viewModeRef.current = viewMode;
|
|
12514
|
-
const [allChunks, setAllChunks] =
|
|
12515
|
-
const [chunksLoading, setChunksLoading] =
|
|
12516
|
-
const [draftNote, setDraftNote] =
|
|
12517
|
-
const [savingDraft, setSavingDraft] =
|
|
12518
|
-
const [noteRuns, setNoteRuns] =
|
|
12519
|
-
const handleNoteRunFinished =
|
|
13094
|
+
const [allChunks, setAllChunks] = React15.useState(null);
|
|
13095
|
+
const [chunksLoading, setChunksLoading] = React15.useState(false);
|
|
13096
|
+
const [draftNote, setDraftNote] = React15.useState(null);
|
|
13097
|
+
const [savingDraft, setSavingDraft] = React15.useState(false);
|
|
13098
|
+
const [noteRuns, setNoteRuns] = React15.useState([]);
|
|
13099
|
+
const handleNoteRunFinished = React15.useCallback((runId2) => {
|
|
12520
13100
|
setNoteRuns((prev) => {
|
|
12521
13101
|
const next = prev.filter((r) => r.run_id !== runId2);
|
|
12522
13102
|
if (next.length === 0 && data.onLoadAllChunks) {
|
|
@@ -12525,9 +13105,9 @@ function KnowledgeGraphView({
|
|
|
12525
13105
|
return next;
|
|
12526
13106
|
});
|
|
12527
13107
|
}, [data, groupId, kgId]);
|
|
12528
|
-
|
|
12529
|
-
|
|
12530
|
-
|
|
13108
|
+
React15.useRef(null);
|
|
13109
|
+
React15.useRef(null);
|
|
13110
|
+
React15.useEffect(() => {
|
|
12531
13111
|
if (!selectedNodeId) {
|
|
12532
13112
|
setNodeChunks([]);
|
|
12533
13113
|
return;
|
|
@@ -12553,7 +13133,7 @@ function KnowledgeGraphView({
|
|
|
12553
13133
|
cancelled = true;
|
|
12554
13134
|
};
|
|
12555
13135
|
}, [selectedNodeId, groupId, kgId, allChunks]);
|
|
12556
|
-
|
|
13136
|
+
React15.useEffect(() => {
|
|
12557
13137
|
if (allChunks !== null || !data.onLoadAllChunks) return;
|
|
12558
13138
|
let cancelled = false;
|
|
12559
13139
|
setChunksLoading(true);
|
|
@@ -12569,8 +13149,8 @@ function KnowledgeGraphView({
|
|
|
12569
13149
|
cancelled = true;
|
|
12570
13150
|
};
|
|
12571
13151
|
}, [viewMode, allChunks, groupId, kgId, data.onLoadAllChunks]);
|
|
12572
|
-
const prevViewModeRef =
|
|
12573
|
-
|
|
13152
|
+
const prevViewModeRef = React15.useRef(viewMode);
|
|
13153
|
+
React15.useEffect(() => {
|
|
12574
13154
|
const modeChanged = prevViewModeRef.current !== viewMode;
|
|
12575
13155
|
prevViewModeRef.current = viewMode;
|
|
12576
13156
|
if (viewMode === "entity") {
|
|
@@ -12632,7 +13212,7 @@ function KnowledgeGraphView({
|
|
|
12632
13212
|
fitViewTimerRef.current = setTimeout(() => rfInstanceRef.current?.fitView({ padding: 0.2, duration: 300 }), 60);
|
|
12633
13213
|
}
|
|
12634
13214
|
}, [viewMode, allChunks, rawNodes, rawEdges]);
|
|
12635
|
-
const buildRfGraph =
|
|
13215
|
+
const buildRfGraph = React15.useCallback((subgraph, existingPositions) => {
|
|
12636
13216
|
const rfNodes = subgraph.nodes.map((n) => {
|
|
12637
13217
|
const gkg = gkgNodeMap.get(n.node_key);
|
|
12638
13218
|
const filterValue = gkg?.claim_status ?? n.properties?.claim_status ?? gkg?.phase ?? n.properties?.phase;
|
|
@@ -12683,8 +13263,8 @@ function KnowledgeGraphView({
|
|
|
12683
13263
|
}));
|
|
12684
13264
|
return { rfNodes, rfEdges };
|
|
12685
13265
|
}, [phaseFilter, gkgNodeMap]);
|
|
12686
|
-
const prevNodeIdsRef =
|
|
12687
|
-
const applyRfGraph =
|
|
13266
|
+
const prevNodeIdsRef = React15.useRef("");
|
|
13267
|
+
const applyRfGraph = React15.useCallback((rfNodes, rfEdges, existingPositions) => {
|
|
12688
13268
|
const nodeIds = rfNodes.map((n) => n.id).join(",");
|
|
12689
13269
|
const structureChanged = nodeIds !== prevNodeIdsRef.current || existingPositions.size === 0;
|
|
12690
13270
|
prevNodeIdsRef.current = nodeIds;
|
|
@@ -12721,7 +13301,7 @@ function KnowledgeGraphView({
|
|
|
12721
13301
|
setNodes(finalNodes);
|
|
12722
13302
|
setEdges(rfEdges);
|
|
12723
13303
|
}, [setNodes, setEdges]);
|
|
12724
|
-
|
|
13304
|
+
React15.useEffect(() => {
|
|
12725
13305
|
let cancelled = false;
|
|
12726
13306
|
const isLiveUpdate = !!genericKGProp;
|
|
12727
13307
|
(async () => {
|
|
@@ -12792,7 +13372,7 @@ function KnowledgeGraphView({
|
|
|
12792
13372
|
cancelled = true;
|
|
12793
13373
|
};
|
|
12794
13374
|
}, [groupId, kgId, genericKGProp, data.onLoadKg, liveRefreshTrigger]);
|
|
12795
|
-
|
|
13375
|
+
React15.useEffect(() => {
|
|
12796
13376
|
if (!rfReady) return;
|
|
12797
13377
|
if (nodes.length === 0) return;
|
|
12798
13378
|
if (didInitialFitRef.current) return;
|
|
@@ -12802,8 +13382,8 @@ function KnowledgeGraphView({
|
|
|
12802
13382
|
});
|
|
12803
13383
|
return () => cancelAnimationFrame(raf);
|
|
12804
13384
|
}, [rfReady, nodes.length, kgId]);
|
|
12805
|
-
const prevSnapshotFingerprintRef =
|
|
12806
|
-
|
|
13385
|
+
const prevSnapshotFingerprintRef = React15.useRef("");
|
|
13386
|
+
React15.useEffect(() => {
|
|
12807
13387
|
if (!processingDetail && !runId) return;
|
|
12808
13388
|
if (!isFixedKgId(kgId)) return;
|
|
12809
13389
|
const interval = setInterval(async () => {
|
|
@@ -12829,7 +13409,7 @@ function KnowledgeGraphView({
|
|
|
12829
13409
|
}, 5e3);
|
|
12830
13410
|
return () => clearInterval(interval);
|
|
12831
13411
|
}, [!!processingDetail, !!runId, groupId, kgId, buildRfGraph, applyRfGraph]);
|
|
12832
|
-
const applyFocusedSubgraph =
|
|
13412
|
+
const applyFocusedSubgraph = React15.useCallback((matchIds, scoreMap, neighborIds, traversalIds) => {
|
|
12833
13413
|
const visibleIds = new Set(matchIds);
|
|
12834
13414
|
neighborIds?.forEach((id) => visibleIds.add(id));
|
|
12835
13415
|
traversalIds?.forEach((id) => visibleIds.add(id));
|
|
@@ -12868,7 +13448,7 @@ function KnowledgeGraphView({
|
|
|
12868
13448
|
if (fitViewTimerRef.current) clearTimeout(fitViewTimerRef.current);
|
|
12869
13449
|
fitViewTimerRef.current = setTimeout(() => rfInstanceRef.current?.fitView({ padding: 0.3, duration: 300 }), 60);
|
|
12870
13450
|
}, [rawEdges, setNodes, setEdges]);
|
|
12871
|
-
const restoreFullGraph =
|
|
13451
|
+
const restoreFullGraph = React15.useCallback(() => {
|
|
12872
13452
|
setNodes(fullNodesRef.current.map((n) => ({
|
|
12873
13453
|
...n,
|
|
12874
13454
|
data: { ...n.data, isHighlighted: false, isDimmed: false, searchScore: null }
|
|
@@ -12881,17 +13461,17 @@ function KnowledgeGraphView({
|
|
|
12881
13461
|
if (fitViewTimerRef.current) clearTimeout(fitViewTimerRef.current);
|
|
12882
13462
|
fitViewTimerRef.current = setTimeout(() => rfInstanceRef.current?.fitView({ padding: 0.2, duration: 300 }), 60);
|
|
12883
13463
|
}, [setNodes, setEdges]);
|
|
12884
|
-
const hasClaimStatuses =
|
|
13464
|
+
const hasClaimStatuses = React15.useMemo(() => {
|
|
12885
13465
|
if (genericKGProp) return genericKGProp.nodes.some((n) => n.claim_status);
|
|
12886
13466
|
return rawNodes.some((n) => n.properties?.claim_status);
|
|
12887
13467
|
}, [genericKGProp, rawNodes]);
|
|
12888
|
-
const hasPhases =
|
|
13468
|
+
const hasPhases = React15.useMemo(() => {
|
|
12889
13469
|
if (hasClaimStatuses) return false;
|
|
12890
13470
|
if (genericKGProp) return genericKGProp.nodes.some((n) => n.phase && n.phase !== "simple");
|
|
12891
13471
|
return rawNodes.some((n) => n.properties?.phase && n.properties.phase !== "simple");
|
|
12892
13472
|
}, [genericKGProp, hasClaimStatuses, rawNodes]);
|
|
12893
13473
|
const hasFilters = hasClaimStatuses || hasPhases;
|
|
12894
|
-
|
|
13474
|
+
React15.useEffect(() => {
|
|
12895
13475
|
if (!hasFilters || searchActive) return;
|
|
12896
13476
|
if (phaseFilter === "all") {
|
|
12897
13477
|
setNodes((nds) => nds.map((n) => ({ ...n, data: { ...n.data, isDimmed: false } })));
|
|
@@ -12915,7 +13495,7 @@ function KnowledgeGraphView({
|
|
|
12915
13495
|
return { ...n, data: { ...n.data, isDimmed: !matches } };
|
|
12916
13496
|
}));
|
|
12917
13497
|
}, [phaseFilter, hasFilters, searchActive, setNodes, setEdges]);
|
|
12918
|
-
|
|
13498
|
+
React15.useEffect(() => {
|
|
12919
13499
|
if (searchActive) return;
|
|
12920
13500
|
if (!hoveredNodeId) {
|
|
12921
13501
|
setNodes((nds) => nds.map((n) => ({ ...n, data: { ...n.data, isHighlighted: false, isDimmed: false } })));
|
|
@@ -12944,7 +13524,7 @@ function KnowledgeGraphView({
|
|
|
12944
13524
|
}
|
|
12945
13525
|
})));
|
|
12946
13526
|
}, [hoveredNodeId, searchActive, setNodes, setEdges]);
|
|
12947
|
-
|
|
13527
|
+
React15.useEffect(() => {
|
|
12948
13528
|
if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
|
|
12949
13529
|
if (!searchTerm.trim()) {
|
|
12950
13530
|
setSearchResult({ hits: [], traversal: [] });
|
|
@@ -12965,19 +13545,19 @@ function KnowledgeGraphView({
|
|
|
12965
13545
|
setSearching(true);
|
|
12966
13546
|
searchTimerRef.current = setTimeout(async () => {
|
|
12967
13547
|
try {
|
|
12968
|
-
const
|
|
12969
|
-
setSearchResult(
|
|
12970
|
-
if (
|
|
13548
|
+
const result2 = data.onSearchNodes ? await data.onSearchNodes(groupId, kgId, q, 10, 2) : { hits: [], traversal: [] };
|
|
13549
|
+
setSearchResult(result2);
|
|
13550
|
+
if (result2.hits.length === 0 && localMatchIds.size === 0) {
|
|
12971
13551
|
restoreFullGraph();
|
|
12972
13552
|
setSearching(false);
|
|
12973
13553
|
return;
|
|
12974
13554
|
}
|
|
12975
|
-
if (
|
|
13555
|
+
if (result2.hits.length === 0) {
|
|
12976
13556
|
setSearching(false);
|
|
12977
13557
|
return;
|
|
12978
13558
|
}
|
|
12979
13559
|
const scoreMap = /* @__PURE__ */ new Map();
|
|
12980
|
-
|
|
13560
|
+
result2.hits.forEach((h) => {
|
|
12981
13561
|
const existing = scoreMap.get(h.node_key) ?? 0;
|
|
12982
13562
|
if ((h.score ?? 0) > existing) scoreMap.set(h.node_key, h.score ?? 0);
|
|
12983
13563
|
});
|
|
@@ -12985,9 +13565,9 @@ function KnowledgeGraphView({
|
|
|
12985
13565
|
if (!scoreMap.has(id)) scoreMap.set(id, 0.5);
|
|
12986
13566
|
});
|
|
12987
13567
|
const traversalIds = /* @__PURE__ */ new Set();
|
|
12988
|
-
|
|
13568
|
+
result2.traversal.forEach((t) => traversalIds.add(t.node_key));
|
|
12989
13569
|
const neighborIds = /* @__PURE__ */ new Set();
|
|
12990
|
-
|
|
13570
|
+
result2.hits.forEach((h) => {
|
|
12991
13571
|
h.neighbors?.forEach((nk) => {
|
|
12992
13572
|
if (!scoreMap.has(nk)) neighborIds.add(nk);
|
|
12993
13573
|
});
|
|
@@ -13002,7 +13582,7 @@ function KnowledgeGraphView({
|
|
|
13002
13582
|
if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
|
|
13003
13583
|
};
|
|
13004
13584
|
}, [searchTerm, rawNodes, rawEdges, groupId, kgId, applyFocusedSubgraph, restoreFullGraph]);
|
|
13005
|
-
const onNodeClick =
|
|
13585
|
+
const onNodeClick = React15.useCallback((_, node) => {
|
|
13006
13586
|
if (node.id === "__add_note__" && data.onCreateNote) {
|
|
13007
13587
|
setSelectedNodeId(null);
|
|
13008
13588
|
setSelectedEdgeId(null);
|
|
@@ -13012,21 +13592,21 @@ function KnowledgeGraphView({
|
|
|
13012
13592
|
setSelectedNodeId(node.id);
|
|
13013
13593
|
setSelectedEdgeId(null);
|
|
13014
13594
|
}, [data.onCreateNote]);
|
|
13015
|
-
const onEdgeClick =
|
|
13595
|
+
const onEdgeClick = React15.useCallback((_, edge) => {
|
|
13016
13596
|
setSelectedEdgeId(edge.id);
|
|
13017
13597
|
setSelectedNodeId(null);
|
|
13018
13598
|
}, []);
|
|
13019
|
-
const onNodeMouseEnter =
|
|
13599
|
+
const onNodeMouseEnter = React15.useCallback((_, node) => {
|
|
13020
13600
|
setHoveredNodeId(node.id);
|
|
13021
13601
|
}, []);
|
|
13022
|
-
const onNodeMouseLeave =
|
|
13602
|
+
const onNodeMouseLeave = React15.useCallback(() => {
|
|
13023
13603
|
setHoveredNodeId(null);
|
|
13024
13604
|
}, []);
|
|
13025
|
-
const onPaneClick =
|
|
13605
|
+
const onPaneClick = React15.useCallback(() => {
|
|
13026
13606
|
setSelectedNodeId(null);
|
|
13027
13607
|
setSelectedEdgeId(null);
|
|
13028
13608
|
}, []);
|
|
13029
|
-
const selectedNodeConnections =
|
|
13609
|
+
const selectedNodeConnections = React15.useMemo(() => {
|
|
13030
13610
|
if (!selectedNodeId) return [];
|
|
13031
13611
|
if (viewMode === "chunk" && selectedNodeId.startsWith("chunk:") && allChunks) {
|
|
13032
13612
|
const chunkId = selectedNodeId.slice("chunk:".length);
|
|
@@ -13076,7 +13656,7 @@ function KnowledgeGraphView({
|
|
|
13076
13656
|
};
|
|
13077
13657
|
});
|
|
13078
13658
|
}, [selectedNodeId, rawNodes, rawEdges, viewMode, allChunks]);
|
|
13079
|
-
const selectedEdgeData =
|
|
13659
|
+
const selectedEdgeData = React15.useMemo(() => {
|
|
13080
13660
|
if (!selectedEdgeId) return null;
|
|
13081
13661
|
const raw = rawEdges.find((e) => e.edge_key === selectedEdgeId);
|
|
13082
13662
|
if (!raw) return null;
|
|
@@ -13096,7 +13676,7 @@ function KnowledgeGraphView({
|
|
|
13096
13676
|
targetNode: { id: raw.to_node_key, label: targetNode?.label || raw.to_node_key, nodeType: targetNode?.node_type || "unknown" }
|
|
13097
13677
|
};
|
|
13098
13678
|
}, [selectedEdgeId, rawNodes, rawEdges, gkgEdgeMap]);
|
|
13099
|
-
const selectedNodeData =
|
|
13679
|
+
const selectedNodeData = React15.useMemo(() => {
|
|
13100
13680
|
if (!selectedNodeId) return null;
|
|
13101
13681
|
if (viewMode === "chunk" && selectedNodeId.startsWith("chunk:") && allChunks) {
|
|
13102
13682
|
const chunkId = selectedNodeId.slice("chunk:".length);
|
|
@@ -13142,12 +13722,12 @@ function KnowledgeGraphView({
|
|
|
13142
13722
|
hasRagChunks: !!(raw.properties?.rag_chunks?.length || raw.properties?.source_chunks?.length || raw.properties?.references?.length)
|
|
13143
13723
|
};
|
|
13144
13724
|
}, [selectedNodeId, rawNodes, viewMode, allChunks]);
|
|
13145
|
-
const navigateToNode =
|
|
13725
|
+
const navigateToNode = React15.useCallback((nodeId) => {
|
|
13146
13726
|
setSelectedNodeId(nodeId);
|
|
13147
13727
|
setSelectedEdgeId(null);
|
|
13148
13728
|
}, []);
|
|
13149
|
-
const reviewNodeIds =
|
|
13150
|
-
const onReviewNavigate =
|
|
13729
|
+
const reviewNodeIds = React15.useMemo(() => rawNodes.map((n) => n.node_key), [rawNodes]);
|
|
13730
|
+
const onReviewNavigate = React15.useCallback((nodeId) => {
|
|
13151
13731
|
setSelectedNodeId(nodeId);
|
|
13152
13732
|
setSelectedEdgeId(null);
|
|
13153
13733
|
const rfNode = nodes.find((n) => n.id === nodeId);
|
|
@@ -13160,8 +13740,8 @@ function KnowledgeGraphView({
|
|
|
13160
13740
|
);
|
|
13161
13741
|
}
|
|
13162
13742
|
}, [nodes]);
|
|
13163
|
-
const lastChatHighlightRef =
|
|
13164
|
-
const handleChatHighlight =
|
|
13743
|
+
const lastChatHighlightRef = React15.useRef("");
|
|
13744
|
+
const handleChatHighlight = React15.useCallback((nodeIds) => {
|
|
13165
13745
|
if (nodeIds.length === 0) return;
|
|
13166
13746
|
const key = nodeIds.sort().join(",");
|
|
13167
13747
|
if (key === lastChatHighlightRef.current) return;
|
|
@@ -13177,7 +13757,7 @@ function KnowledgeGraphView({
|
|
|
13177
13757
|
})));
|
|
13178
13758
|
setSearchActive(true);
|
|
13179
13759
|
}, [setNodes, setEdges]);
|
|
13180
|
-
const minimapNodeColor =
|
|
13760
|
+
const minimapNodeColor = React15.useCallback((node) => {
|
|
13181
13761
|
return getNodeColors(node.data?.nodeType || "").badge;
|
|
13182
13762
|
}, []);
|
|
13183
13763
|
const hasLiveRun = !!runId;
|
|
@@ -13476,9 +14056,9 @@ function KnowledgeGraphView({
|
|
|
13476
14056
|
if (!data.onCreateNote || !draftNote || !draftNote.trim()) return;
|
|
13477
14057
|
setSavingDraft(true);
|
|
13478
14058
|
try {
|
|
13479
|
-
const
|
|
14059
|
+
const result2 = await data.onCreateNote(groupId, kgId, draftNote);
|
|
13480
14060
|
setDraftNote(null);
|
|
13481
|
-
setSelectedNodeId(`chunk:${
|
|
14061
|
+
setSelectedNodeId(`chunk:${result2.chunk_id}`);
|
|
13482
14062
|
if (data.onLoadAllChunks) {
|
|
13483
14063
|
try {
|
|
13484
14064
|
const fresh = await data.onLoadAllChunks(groupId, kgId);
|
|
@@ -13487,10 +14067,10 @@ function KnowledgeGraphView({
|
|
|
13487
14067
|
console.warn("[KGV] post-create chunk refetch failed", err);
|
|
13488
14068
|
}
|
|
13489
14069
|
}
|
|
13490
|
-
if (
|
|
14070
|
+
if (result2.run_id && config?.agentsApiUrl) {
|
|
13491
14071
|
setNoteRuns((prev) => [
|
|
13492
14072
|
...prev,
|
|
13493
|
-
{ run_id:
|
|
14073
|
+
{ run_id: result2.run_id, kg_id: kgId }
|
|
13494
14074
|
]);
|
|
13495
14075
|
}
|
|
13496
14076
|
} catch (err) {
|
|
@@ -13586,9 +14166,9 @@ function ReasoningView({
|
|
|
13586
14166
|
activityEvents,
|
|
13587
14167
|
className = ""
|
|
13588
14168
|
}) {
|
|
13589
|
-
const [chainOpen, setChainOpen] =
|
|
13590
|
-
const [chainGoal, setChainGoal] =
|
|
13591
|
-
const chainInputRef =
|
|
14169
|
+
const [chainOpen, setChainOpen] = React15.useState(false);
|
|
14170
|
+
const [chainGoal, setChainGoal] = React15.useState("");
|
|
14171
|
+
const chainInputRef = React15.useRef(null);
|
|
13592
14172
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col h-full overflow-hidden ${className}`, style: { backgroundColor: "#181818" }, children: [
|
|
13593
14173
|
(title || onClose) && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 px-4 py-2 flex-shrink-0", style: { borderBottom: "1px solid #282828" }, children: [
|
|
13594
14174
|
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -13740,15 +14320,15 @@ function SettlementBar({ settledCount, totalCount }) {
|
|
|
13740
14320
|
] });
|
|
13741
14321
|
}
|
|
13742
14322
|
function ReasoningOverlay({ config, currentUser, data, onLookupKg, authToken }) {
|
|
13743
|
-
const [open, setOpen] =
|
|
13744
|
-
const [kgId, setKgId] =
|
|
13745
|
-
const [runId, setRunId] =
|
|
13746
|
-
const [workingGroupId, setWorkingGroupId] =
|
|
13747
|
-
const [threadId, setThreadId] =
|
|
13748
|
-
const [reasoningPhase, setReasoningPhase] =
|
|
13749
|
-
const [reasoningAgents, setReasoningAgents] =
|
|
13750
|
-
const [genericKG, setGenericKG] =
|
|
13751
|
-
const loadKg =
|
|
14323
|
+
const [open, setOpen] = React15.useState(false);
|
|
14324
|
+
const [kgId, setKgId] = React15.useState(null);
|
|
14325
|
+
const [runId, setRunId] = React15.useState();
|
|
14326
|
+
const [workingGroupId, setWorkingGroupId] = React15.useState(null);
|
|
14327
|
+
const [threadId, setThreadId] = React15.useState();
|
|
14328
|
+
const [reasoningPhase, setReasoningPhase] = React15.useState(null);
|
|
14329
|
+
const [reasoningAgents, setReasoningAgents] = React15.useState();
|
|
14330
|
+
const [genericKG, setGenericKG] = React15.useState(null);
|
|
14331
|
+
const loadKg = React15.useCallback(async (id) => {
|
|
13752
14332
|
try {
|
|
13753
14333
|
let wgId = null;
|
|
13754
14334
|
let resolvedThread;
|
|
@@ -13824,7 +14404,7 @@ function ReasoningOverlay({ config, currentUser, data, onLookupKg, authToken })
|
|
|
13824
14404
|
console.error("[ReasoningOverlay] Failed to load:", e);
|
|
13825
14405
|
}
|
|
13826
14406
|
}, [data, onLookupKg]);
|
|
13827
|
-
const close =
|
|
14407
|
+
const close = React15.useCallback(() => {
|
|
13828
14408
|
setOpen(false);
|
|
13829
14409
|
setGenericKG(null);
|
|
13830
14410
|
setKgId(null);
|
|
@@ -13833,7 +14413,7 @@ function ReasoningOverlay({ config, currentUser, data, onLookupKg, authToken })
|
|
|
13833
14413
|
setRunId(void 0);
|
|
13834
14414
|
window.dispatchEvent(new CustomEvent("reasoning-overlay-closed", { bubbles: true }));
|
|
13835
14415
|
}, []);
|
|
13836
|
-
|
|
14416
|
+
React15.useEffect(() => {
|
|
13837
14417
|
const handler = (e) => {
|
|
13838
14418
|
const detail = e.detail || {};
|
|
13839
14419
|
const id = detail.kgId || detail.reasoningSetId;
|
|
@@ -13846,7 +14426,7 @@ function ReasoningOverlay({ config, currentUser, data, onLookupKg, authToken })
|
|
|
13846
14426
|
window.removeEventListener("view-reasoning-set", handler);
|
|
13847
14427
|
};
|
|
13848
14428
|
}, [loadKg]);
|
|
13849
|
-
|
|
14429
|
+
React15.useEffect(() => {
|
|
13850
14430
|
if (!open) return;
|
|
13851
14431
|
const handler = (e) => {
|
|
13852
14432
|
if (e.key === "Escape") close();
|
|
@@ -13907,9 +14487,9 @@ function CheckpointCard({
|
|
|
13907
14487
|
onAction,
|
|
13908
14488
|
responded = false
|
|
13909
14489
|
}) {
|
|
13910
|
-
const [inputValue, setInputValue] =
|
|
13911
|
-
const [showInput, setShowInput] =
|
|
13912
|
-
const inputRef =
|
|
14490
|
+
const [inputValue, setInputValue] = React15.useState("");
|
|
14491
|
+
const [showInput, setShowInput] = React15.useState(false);
|
|
14492
|
+
const inputRef = React15.useRef(null);
|
|
13913
14493
|
const config = TYPE_CONFIG2[type] || TYPE_CONFIG2.generic;
|
|
13914
14494
|
const handleSend = () => {
|
|
13915
14495
|
if (!inputValue.trim()) return;
|
|
@@ -13917,7 +14497,7 @@ function CheckpointCard({
|
|
|
13917
14497
|
setInputValue("");
|
|
13918
14498
|
setShowInput(false);
|
|
13919
14499
|
};
|
|
13920
|
-
|
|
14500
|
+
React15.useEffect(() => {
|
|
13921
14501
|
if (showInput) inputRef.current?.focus();
|
|
13922
14502
|
}, [showInput]);
|
|
13923
14503
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -14049,6 +14629,7 @@ exports.ADVANCE_PHASE_SIGNAL = ADVANCE_PHASE_SIGNAL;
|
|
|
14049
14629
|
exports.AGENT_PALETTE = AGENT_PALETTE;
|
|
14050
14630
|
exports.AgentAvatar = AgentAvatar;
|
|
14051
14631
|
exports.AgentPresenceBar = AgentPresenceBar;
|
|
14632
|
+
exports.AgentStepTrace = AgentStepTrace;
|
|
14052
14633
|
exports.AnnotationThread = AnnotationThread;
|
|
14053
14634
|
exports.CLAIM_STATUS_COLORS = CLAIM_STATUS_COLORS;
|
|
14054
14635
|
exports.ChatTerminal = ChatTerminal;
|
|
@@ -14056,6 +14637,7 @@ exports.CheckpointCard = CheckpointCard;
|
|
|
14056
14637
|
exports.ClaimNode = ClaimNode;
|
|
14057
14638
|
exports.ConstructionProgress = ConstructionProgress;
|
|
14058
14639
|
exports.CoreTerminal = CoreTerminal;
|
|
14640
|
+
exports.DEFAULT_AGENT_LABEL = DEFAULT_AGENT_LABEL;
|
|
14059
14641
|
exports.DOCUMENT_PIPELINE_STEPS = DOCUMENT_PIPELINE_STEPS;
|
|
14060
14642
|
exports.DocumentProcessingProgress = DocumentProcessingProgress;
|
|
14061
14643
|
exports.EDGE_TYPE_COLORS = EDGE_TYPE_COLORS;
|
|
@@ -14080,6 +14662,8 @@ exports.PipelineProgressBar = PipelineProgressBar;
|
|
|
14080
14662
|
exports.ReasoningHistoryCard = ReasoningHistoryCard;
|
|
14081
14663
|
exports.ReasoningOverlay = ReasoningOverlay;
|
|
14082
14664
|
exports.ReasoningView = ReasoningView;
|
|
14665
|
+
exports.SSE_KEEPALIVE_MS = SSE_KEEPALIVE_MS;
|
|
14666
|
+
exports.SSE_STALL_MS = SSE_STALL_MS;
|
|
14083
14667
|
exports.SYNTHESIS_DONE_SIGNAL = SYNTHESIS_DONE_SIGNAL;
|
|
14084
14668
|
exports.ScopedReasoningProvider = ScopedReasoningProvider;
|
|
14085
14669
|
exports.SettlementBar = SettlementBar;
|
|
@@ -14089,6 +14673,7 @@ exports.StandardTerminal = StandardTerminal;
|
|
|
14089
14673
|
exports.TerminalInputBar = TerminalInputBar;
|
|
14090
14674
|
exports.TerminalThemeProvider = TerminalThemeProvider;
|
|
14091
14675
|
exports.agentSeed = agentSeed;
|
|
14676
|
+
exports.agentStepTraceExtra = agentStepTraceExtra;
|
|
14092
14677
|
exports.avatarColor = avatarColor;
|
|
14093
14678
|
exports.blueScope = blueScope;
|
|
14094
14679
|
exports.buildClaimsGraph = buildClaimsGraph;
|
|
@@ -14141,3 +14726,4 @@ exports.useScopedProgressEvent = useScopedProgressEvent;
|
|
|
14141
14726
|
exports.useSlashMentionPicker = useSlashMentionPicker;
|
|
14142
14727
|
exports.useTheme = useTheme;
|
|
14143
14728
|
exports.warmBg = warmBg;
|
|
14729
|
+
exports.withStallTimeout = withStallTimeout;
|