@yieldfabric/terminal 1.0.0 → 1.1.1
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 +1391 -775
- package/dist/index.d.cts +244 -4
- package/dist/index.d.ts +244 -4
- package/dist/index.js +959 -350
- 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",
|
|
@@ -162,12 +201,12 @@ var handleSSEStream = async (url, body, onChunk, onComplete, onError, options) =
|
|
|
162
201
|
...method !== "GET" && method !== "HEAD" ? { "Content-Type": "application/json" } : {},
|
|
163
202
|
...options?.headers
|
|
164
203
|
};
|
|
165
|
-
const response = await fetch(url, {
|
|
204
|
+
const response = await (options?.fetcher ?? fetch)(url, {
|
|
166
205
|
method,
|
|
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);
|
|
@@ -3098,7 +3296,7 @@ function KGScopeDropdown({ items, onSelect, compact = false }) {
|
|
|
3098
3296
|
}
|
|
3099
3297
|
function ReasoningModeSelector({ current, onChange, compact = false }) {
|
|
3100
3298
|
const t = useTheme();
|
|
3101
|
-
const isLight = t.bgRaised === "#ffffff";
|
|
3299
|
+
const isLight = t.mode ? t.mode === "light" : t.bgRaised === "#ffffff";
|
|
3102
3300
|
const isReason = current === "reason";
|
|
3103
3301
|
const label = isReason ? "Reason" : "Auto";
|
|
3104
3302
|
const title = isReason ? "Force deep reasoning \u2014 click to let the AI decide" : "AI decides \u2014 click to force deep reasoning";
|
|
@@ -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,50 +3391,58 @@ 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();
|
|
3186
|
-
|
|
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;
|
|
3404
|
+
const isTouch = typeof window !== "undefined" && "ontouchstart" in window;
|
|
3405
|
+
const isLight = t.mode ? t.mode === "light" : t.bgRaised === "#ffffff";
|
|
3187
3406
|
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 ?
|
|
3407
|
+
const placeholderColor = isLight ? t.textMuted : "rgba(255,255,255,0.52)";
|
|
3408
|
+
const panelBorder = isLight ? t.border : "rgba(255,255,255,0.10)";
|
|
3409
|
+
const panelBg = t.bgInput;
|
|
3410
|
+
const toolbarButtonBg = isLight ? "rgba(255,255,255,0.72)" : "rgba(255,255,255,0.05)";
|
|
3411
|
+
const toolbarButtonHover = isLight ? t.bgRaised : "rgba(255,255,255,0.14)";
|
|
3412
|
+
const toolbarButtonText = isLight ? t.textSecondary : "rgba(255,255,255,0.52)";
|
|
3194
3413
|
const toolbarButtonStyle = {
|
|
3195
3414
|
backgroundColor: toolbarButtonBg,
|
|
3196
|
-
border: `1px solid ${isLight ?
|
|
3415
|
+
border: `1px solid ${isLight ? t.border : "rgba(255,255,255,0.08)"}`,
|
|
3197
3416
|
boxShadow: "none",
|
|
3198
3417
|
color: toolbarButtonText
|
|
3199
3418
|
};
|
|
3200
|
-
const toolbarRef =
|
|
3201
|
-
const [compact, setCompact] =
|
|
3202
|
-
|
|
3419
|
+
const toolbarRef = React15.useRef(null);
|
|
3420
|
+
const [compact, setCompact] = React15.useState(false);
|
|
3421
|
+
React15.useEffect(() => {
|
|
3203
3422
|
if (compactToolbar) {
|
|
3204
3423
|
setCompact(true);
|
|
3205
3424
|
return;
|
|
3206
3425
|
}
|
|
3207
3426
|
const el = toolbarRef.current;
|
|
3208
3427
|
if (!el || typeof ResizeObserver === "undefined") return;
|
|
3428
|
+
let lastWidth = -1;
|
|
3209
3429
|
const ro = new ResizeObserver((entries) => {
|
|
3210
|
-
const w = entries[0]?.contentRect.width ?? 0;
|
|
3430
|
+
const w = Math.round(entries[0]?.contentRect.width ?? 0);
|
|
3431
|
+
if (w === lastWidth) return;
|
|
3432
|
+
lastWidth = w;
|
|
3211
3433
|
setCompact((prev) => prev ? w < 520 : w < 480);
|
|
3212
3434
|
});
|
|
3213
3435
|
ro.observe(el);
|
|
3214
3436
|
return () => ro.disconnect();
|
|
3215
3437
|
}, [compactToolbar]);
|
|
3216
3438
|
const toolbarIsCompact = compactToolbar || compact;
|
|
3217
|
-
|
|
3439
|
+
React15.useEffect(() => {
|
|
3218
3440
|
const input = inputRef.current;
|
|
3219
3441
|
if (!input) return;
|
|
3220
|
-
input
|
|
3221
|
-
if (currentCommand.trim()) {
|
|
3222
|
-
input.style.height = Math.min(input.scrollHeight, 120) + "px";
|
|
3223
|
-
}
|
|
3442
|
+
fitToContent(input);
|
|
3224
3443
|
}, [currentCommand, inputRef]);
|
|
3225
3444
|
return /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3226
|
-
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `.yf-input-bar::placeholder { color: ${placeholderColor}; }` }),
|
|
3445
|
+
/* @__PURE__ */ jsxRuntime.jsx("style", { children: `.yf-input-bar::placeholder { color: ${placeholderColor}; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }` }),
|
|
3227
3446
|
commandPaletteItems.length > 0 && /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3228
3447
|
"div",
|
|
3229
3448
|
{
|
|
@@ -3262,17 +3481,24 @@ function TerminalInputBar({
|
|
|
3262
3481
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3263
3482
|
"div",
|
|
3264
3483
|
{
|
|
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" : ""}`,
|
|
3484
|
+
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
3485
|
children: /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3267
3486
|
"div",
|
|
3268
3487
|
{
|
|
3269
|
-
className:
|
|
3488
|
+
className: `rounded-xl border px-3 transition-[box-shadow,border-color] sm:px-4 ${focused ? "yf-input-focused" : ""}`,
|
|
3270
3489
|
style: {
|
|
3271
3490
|
backgroundColor: panelBg,
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3491
|
+
// No backdrop blur on a touch screen. It is the one compositing
|
|
3492
|
+
// layer between the textarea and the page, and on iPhone the
|
|
3493
|
+
// caret was drawn a line below and a character right of where
|
|
3494
|
+
// typing lands — the caret rect resolved against the wrong
|
|
3495
|
+
// layer — while WebKit's own layout (checked in WebKit 26) puts
|
|
3496
|
+
// it on the line. The box keeps its colour; only the frosted
|
|
3497
|
+
// fabric behind it goes, which at this size is barely a change.
|
|
3498
|
+
backdropFilter: isTouch ? void 0 : "blur(18px)",
|
|
3499
|
+
borderColor: focused ? t.primary : panelBorder,
|
|
3500
|
+
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)",
|
|
3501
|
+
WebkitBackdropFilter: isTouch ? void 0 : "blur(18px)"
|
|
3276
3502
|
},
|
|
3277
3503
|
children: [
|
|
3278
3504
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -3341,8 +3567,7 @@ function TerminalInputBar({
|
|
|
3341
3567
|
onInputChange(`${prefixRaw}${e.target.value}`);
|
|
3342
3568
|
onCaretChange?.(prefixRaw.length + (e.target.selectionStart ?? e.target.value.length));
|
|
3343
3569
|
onTyping?.();
|
|
3344
|
-
e.target
|
|
3345
|
-
e.target.style.height = Math.min(e.target.scrollHeight, 120) + "px";
|
|
3570
|
+
fitToContent(e.target);
|
|
3346
3571
|
},
|
|
3347
3572
|
onSelect: (e) => {
|
|
3348
3573
|
const ta = e.currentTarget;
|
|
@@ -3369,17 +3594,34 @@ function TerminalInputBar({
|
|
|
3369
3594
|
if (e.key === "Enter" && !e.shiftKey && !e.defaultPrevented) {
|
|
3370
3595
|
e.preventDefault();
|
|
3371
3596
|
onSubmit();
|
|
3372
|
-
if (inputRef.current) inputRef.current
|
|
3597
|
+
if (inputRef.current) resetHeight(inputRef.current);
|
|
3373
3598
|
}
|
|
3374
3599
|
},
|
|
3375
|
-
disabled: isExecuting,
|
|
3600
|
+
disabled: isExecuting || disabled,
|
|
3601
|
+
"aria-label": placeholder ?? "Message",
|
|
3376
3602
|
placeholder: isExecuting ? "Processing..." : placeholder,
|
|
3377
3603
|
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-
|
|
3604
|
+
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",
|
|
3605
|
+
onFocus: () => {
|
|
3606
|
+
setFocused(true);
|
|
3607
|
+
if (!("ontouchstart" in window)) return;
|
|
3608
|
+
window.setTimeout(() => {
|
|
3609
|
+
const ta = inputRef.current;
|
|
3610
|
+
if (!ta || document.activeElement !== ta) return;
|
|
3611
|
+
let scroller = ta.parentElement;
|
|
3612
|
+
while (scroller && !/(auto|scroll)/.test(getComputedStyle(scroller).overflowY)) scroller = scroller.parentElement;
|
|
3613
|
+
window.scrollBy(0, 1);
|
|
3614
|
+
if (scroller) scroller.scrollTop += 1;
|
|
3615
|
+
window.requestAnimationFrame(() => {
|
|
3616
|
+
window.scrollBy(0, -1);
|
|
3617
|
+
if (scroller) scroller.scrollTop -= 1;
|
|
3618
|
+
});
|
|
3619
|
+
}, 400);
|
|
3620
|
+
},
|
|
3621
|
+
onBlur: () => setFocused(false),
|
|
3379
3622
|
style: { color: t.text, caretColor: t.cursor },
|
|
3380
3623
|
spellCheck: false,
|
|
3381
3624
|
autoComplete: "off",
|
|
3382
|
-
autoFocus: true,
|
|
3383
3625
|
tabIndex: 0
|
|
3384
3626
|
}
|
|
3385
3627
|
)
|
|
@@ -3388,67 +3630,85 @@ function TerminalInputBar({
|
|
|
3388
3630
|
"button",
|
|
3389
3631
|
{
|
|
3390
3632
|
type: "submit",
|
|
3391
|
-
disabled: !hasCommand || isExecuting,
|
|
3392
|
-
className: "h-10 w-10 rounded-xl disabled:opacity-
|
|
3633
|
+
disabled: !hasCommand || isExecuting || disabled,
|
|
3634
|
+
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
3635
|
style: {
|
|
3394
|
-
backgroundColor:
|
|
3395
|
-
|
|
3636
|
+
backgroundColor: isLight ? t.primary : hasCommand ? t.primary : "rgba(255,255,255,0.08)",
|
|
3637
|
+
// `textInverse` is the theme's "text on a filled button".
|
|
3638
|
+
// `bgBase` was used here before and is `transparent` in
|
|
3639
|
+
// every app theme — so the chevron vanished the moment
|
|
3640
|
+
// there was something to send.
|
|
3641
|
+
// In LIGHT mode this is always a solid accent fill with white
|
|
3642
|
+
// on it (6.1:1). It is the app's primary verb and the single
|
|
3643
|
+
// most-pressed control; a pale disc — grey, or a 10% tint —
|
|
3644
|
+
// read as disabled even when it was not. The empty state is
|
|
3645
|
+
// already expressed by `disabled:opacity-60`, so the fill does
|
|
3646
|
+
// not also have to whisper. Dark keeps its white-alpha rest,
|
|
3647
|
+
// where a solid orange disc would shout on near-black.
|
|
3648
|
+
color: isLight ? t.textInverse : hasCommand ? t.textInverse : "rgba(255,255,255,0.72)"
|
|
3396
3649
|
},
|
|
3397
3650
|
onMouseEnter: (e) => {
|
|
3398
|
-
|
|
3651
|
+
if (hasCommand) {
|
|
3652
|
+
e.currentTarget.style.filter = "brightness(1.15)";
|
|
3653
|
+
} else {
|
|
3654
|
+
e.currentTarget.style.backgroundColor = toolbarButtonHover;
|
|
3655
|
+
}
|
|
3399
3656
|
},
|
|
3400
3657
|
onMouseLeave: (e) => {
|
|
3401
|
-
e.currentTarget.style.
|
|
3658
|
+
e.currentTarget.style.filter = "";
|
|
3659
|
+
e.currentTarget.style.backgroundColor = isLight ? t.primary : hasCommand ? t.primary : "rgba(255,255,255,0.08)";
|
|
3402
3660
|
},
|
|
3403
3661
|
title: submitTitle,
|
|
3404
3662
|
"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 ?
|
|
3663
|
+
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
3664
|
}
|
|
3407
3665
|
)
|
|
3408
3666
|
] });
|
|
3409
3667
|
})(),
|
|
3410
3668
|
/* @__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
|
-
|
|
3669
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 text-[11px] min-w-0 flex-wrap", children: [
|
|
3670
|
+
chipsVisible && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
3671
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3672
|
+
"button",
|
|
3673
|
+
{
|
|
3674
|
+
type: "button",
|
|
3675
|
+
onClick: () => {
|
|
3676
|
+
onInputChange("@");
|
|
3677
|
+
inputRef.current?.focus();
|
|
3678
|
+
},
|
|
3679
|
+
title: "Insert @ mention",
|
|
3680
|
+
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`,
|
|
3681
|
+
style: toolbarButtonStyle,
|
|
3682
|
+
onMouseEnter: (e) => {
|
|
3683
|
+
e.currentTarget.style.backgroundColor = toolbarButtonHover;
|
|
3684
|
+
},
|
|
3685
|
+
onMouseLeave: (e) => {
|
|
3686
|
+
e.currentTarget.style.backgroundColor = toolbarButtonBg;
|
|
3687
|
+
},
|
|
3688
|
+
children: toolbarIsCompact ? "@" : "@ mention"
|
|
3689
|
+
}
|
|
3690
|
+
),
|
|
3691
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
3692
|
+
"button",
|
|
3693
|
+
{
|
|
3694
|
+
type: "button",
|
|
3695
|
+
onClick: () => {
|
|
3696
|
+
onInputChange("/");
|
|
3697
|
+
inputRef.current?.focus();
|
|
3698
|
+
},
|
|
3699
|
+
title: "Insert / command",
|
|
3700
|
+
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`,
|
|
3701
|
+
style: toolbarButtonStyle,
|
|
3702
|
+
onMouseEnter: (e) => {
|
|
3703
|
+
e.currentTarget.style.backgroundColor = toolbarButtonHover;
|
|
3704
|
+
},
|
|
3705
|
+
onMouseLeave: (e) => {
|
|
3706
|
+
e.currentTarget.style.backgroundColor = toolbarButtonBg;
|
|
3707
|
+
},
|
|
3708
|
+
children: toolbarIsCompact ? "/" : "/ commands"
|
|
3709
|
+
}
|
|
3710
|
+
)
|
|
3711
|
+
] }),
|
|
3452
3712
|
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
3713
|
/* @__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
3714
|
/* @__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 +3722,7 @@ function TerminalInputBar({
|
|
|
3462
3722
|
] }),
|
|
3463
3723
|
/* @__PURE__ */ jsxRuntime.jsx("button", { type: "button", onClick: () => onKGScopeChange?.(null), className: "ml-0.5 opacity-40 hover:opacity-100 transition-opacity", children: "\u2715" })
|
|
3464
3724
|
] }) : /* @__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 }))
|
|
3725
|
+
chipsVisible && (modeSelector ?? (onReasoningModeChange && /* @__PURE__ */ jsxRuntime.jsx(ReasoningModeSelector, { current: reasoningMode || null, onChange: onReasoningModeChange, compact: toolbarIsCompact })))
|
|
3466
3726
|
] }),
|
|
3467
3727
|
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-1.5 flex-shrink-0", children: [
|
|
3468
3728
|
inputBarExtra,
|
|
@@ -3470,8 +3730,8 @@ function TerminalInputBar({
|
|
|
3470
3730
|
"button",
|
|
3471
3731
|
{
|
|
3472
3732
|
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",
|
|
3733
|
+
disabled: isExecuting || disabled,
|
|
3734
|
+
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
3735
|
style: toolbarButtonStyle,
|
|
3476
3736
|
title: "Upload files",
|
|
3477
3737
|
onClick: () => fileInputRef.current?.click(),
|
|
@@ -3488,8 +3748,8 @@ function TerminalInputBar({
|
|
|
3488
3748
|
"button",
|
|
3489
3749
|
{
|
|
3490
3750
|
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",
|
|
3751
|
+
disabled: isExecuting || disabled,
|
|
3752
|
+
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
3753
|
style: toolbarButtonStyle,
|
|
3494
3754
|
title: "List files",
|
|
3495
3755
|
onClick: () => onListFilesCommand(),
|
|
@@ -3520,7 +3780,7 @@ var KIND_DOT = {
|
|
|
3520
3780
|
};
|
|
3521
3781
|
function SlashMentionPicker({ candidates, selectedIndex, onPick }) {
|
|
3522
3782
|
const t = useTheme();
|
|
3523
|
-
const isLight = t.bgRaised === "#ffffff";
|
|
3783
|
+
const isLight = t.mode ? t.mode === "light" : t.bgRaised === "#ffffff";
|
|
3524
3784
|
if (candidates.length === 0) return null;
|
|
3525
3785
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
3526
3786
|
"div",
|
|
@@ -3575,13 +3835,13 @@ function SlashMentionPicker({ candidates, selectedIndex, onPick }) {
|
|
|
3575
3835
|
);
|
|
3576
3836
|
}
|
|
3577
3837
|
function useCommandHistory() {
|
|
3578
|
-
const [commandHistory, setCommandHistory] =
|
|
3579
|
-
const [historyIndex, setHistoryIndex] =
|
|
3580
|
-
const pushCommand =
|
|
3838
|
+
const [commandHistory, setCommandHistory] = React15.useState([]);
|
|
3839
|
+
const [historyIndex, setHistoryIndex] = React15.useState(-1);
|
|
3840
|
+
const pushCommand = React15.useCallback((cmd) => {
|
|
3581
3841
|
setCommandHistory((prev) => [...prev, cmd]);
|
|
3582
3842
|
setHistoryIndex(-1);
|
|
3583
3843
|
}, []);
|
|
3584
|
-
const navigateUp =
|
|
3844
|
+
const navigateUp = React15.useCallback(
|
|
3585
3845
|
(setCurrentCommand) => {
|
|
3586
3846
|
if (commandHistory.length === 0) return;
|
|
3587
3847
|
const newIndex = historyIndex === -1 ? commandHistory.length - 1 : Math.max(0, historyIndex - 1);
|
|
@@ -3590,7 +3850,7 @@ function useCommandHistory() {
|
|
|
3590
3850
|
},
|
|
3591
3851
|
[commandHistory, historyIndex]
|
|
3592
3852
|
);
|
|
3593
|
-
const navigateDown =
|
|
3853
|
+
const navigateDown = React15.useCallback(
|
|
3594
3854
|
(setCurrentCommand) => {
|
|
3595
3855
|
if (historyIndex === -1) return;
|
|
3596
3856
|
const newIndex = historyIndex + 1;
|
|
@@ -3604,21 +3864,20 @@ function useCommandHistory() {
|
|
|
3604
3864
|
},
|
|
3605
3865
|
[commandHistory, historyIndex]
|
|
3606
3866
|
);
|
|
3607
|
-
const resetIndex =
|
|
3867
|
+
const resetIndex = React15.useCallback(() => {
|
|
3608
3868
|
setHistoryIndex(-1);
|
|
3609
3869
|
}, []);
|
|
3610
3870
|
return { commandHistory, historyIndex, pushCommand, navigateUp, navigateDown, resetIndex };
|
|
3611
3871
|
}
|
|
3612
|
-
function useFocusManagement() {
|
|
3613
|
-
const inputRef =
|
|
3614
|
-
const focusInput =
|
|
3872
|
+
function useFocusManagement(autoFocus = true) {
|
|
3873
|
+
const inputRef = React15.useRef(null);
|
|
3874
|
+
const focusInput = React15.useCallback(() => {
|
|
3615
3875
|
const selection = window.getSelection();
|
|
3616
3876
|
if (selection && selection.toString().length > 0) return;
|
|
3617
|
-
|
|
3618
|
-
inputRef.current.focus();
|
|
3619
|
-
}
|
|
3877
|
+
inputRef.current?.focus({ preventScroll: true });
|
|
3620
3878
|
}, []);
|
|
3621
|
-
|
|
3879
|
+
React15.useEffect(() => {
|
|
3880
|
+
if (!autoFocus) return;
|
|
3622
3881
|
const timer = setTimeout(focusInput, 100);
|
|
3623
3882
|
const handleVisibilityChange = () => {
|
|
3624
3883
|
if (!document.hidden) {
|
|
@@ -3630,11 +3889,12 @@ function useFocusManagement() {
|
|
|
3630
3889
|
clearTimeout(timer);
|
|
3631
3890
|
document.removeEventListener("visibilitychange", handleVisibilityChange);
|
|
3632
3891
|
};
|
|
3633
|
-
}, [focusInput]);
|
|
3892
|
+
}, [focusInput, autoFocus]);
|
|
3634
3893
|
return { inputRef, focusInput };
|
|
3635
3894
|
}
|
|
3636
3895
|
function useStreamingChat({
|
|
3637
3896
|
config,
|
|
3897
|
+
authToken,
|
|
3638
3898
|
onStreamRequest,
|
|
3639
3899
|
reasoningMode,
|
|
3640
3900
|
setTerminalHistory,
|
|
@@ -3643,35 +3903,47 @@ function useStreamingChat({
|
|
|
3643
3903
|
currentUser,
|
|
3644
3904
|
sourceKGNodes
|
|
3645
3905
|
}) {
|
|
3646
|
-
const
|
|
3906
|
+
const authTokenRef = React15.useRef(authToken);
|
|
3907
|
+
authTokenRef.current = authToken;
|
|
3908
|
+
const sourceKGNodesRef = React15.useRef(sourceKGNodes);
|
|
3647
3909
|
sourceKGNodesRef.current = sourceKGNodes;
|
|
3648
|
-
const reasoningModeRef =
|
|
3910
|
+
const reasoningModeRef = React15.useRef(reasoningMode);
|
|
3649
3911
|
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
|
|
3912
|
+
const [isExecuting, setIsExecuting] = React15.useState(false);
|
|
3913
|
+
const turnSequence = React15.useRef(0);
|
|
3914
|
+
const [isStreaming, setIsStreaming] = React15.useState(false);
|
|
3915
|
+
const [progressState, setProgressState] = React15.useState(null);
|
|
3916
|
+
const [activityEvents, setActivityEvents] = React15.useState([]);
|
|
3917
|
+
const [streamTransparency, setStreamTransparency] = React15.useState(null);
|
|
3918
|
+
const [streamNowMs, setStreamNowMs] = React15.useState(Date.now());
|
|
3919
|
+
const [collaborationState, setCollaborationState] = React15.useState(null);
|
|
3920
|
+
const [liveKgId, setLiveKgId] = React15.useState(null);
|
|
3921
|
+
const [liveRunId, setLiveRunId] = React15.useState(null);
|
|
3922
|
+
const [liveThreadId, setLiveThreadId] = React15.useState(null);
|
|
3923
|
+
const progressStateRef = React15.useRef(null);
|
|
3924
|
+
const lastExecutedCommand = React15.useRef(null);
|
|
3925
|
+
const isProcessingRef = React15.useRef(false);
|
|
3926
|
+
const currentStreamingLineId = React15.useRef(null);
|
|
3927
|
+
const liveRunIdRef = React15.useRef(null);
|
|
3665
3928
|
liveRunIdRef.current = liveRunId;
|
|
3666
|
-
|
|
3929
|
+
const mountEpoch = React15.useRef(0);
|
|
3930
|
+
React15.useEffect(() => {
|
|
3931
|
+
const epoch = ++mountEpoch.current;
|
|
3932
|
+
return () => {
|
|
3933
|
+
void Promise.resolve().then(() => {
|
|
3934
|
+
if (mountEpoch.current === epoch) currentStreamingLineId.current = null;
|
|
3935
|
+
});
|
|
3936
|
+
};
|
|
3937
|
+
}, []);
|
|
3938
|
+
React15.useEffect(() => {
|
|
3667
3939
|
progressStateRef.current = progressState;
|
|
3668
3940
|
}, [progressState]);
|
|
3669
|
-
|
|
3941
|
+
React15.useEffect(() => {
|
|
3670
3942
|
if (!isExecuting && !isStreaming) return;
|
|
3671
3943
|
const t = setInterval(() => setStreamNowMs(Date.now()), 1e3);
|
|
3672
3944
|
return () => clearInterval(t);
|
|
3673
3945
|
}, [isExecuting, isStreaming]);
|
|
3674
|
-
const setStreamingLineSender =
|
|
3946
|
+
const setStreamingLineSender = React15.useCallback(
|
|
3675
3947
|
(lineId, sender) => {
|
|
3676
3948
|
setTerminalHistory((prev) => {
|
|
3677
3949
|
const idx = prev.findIndex((line) => line.id === lineId);
|
|
@@ -3684,7 +3956,7 @@ function useStreamingChat({
|
|
|
3684
3956
|
},
|
|
3685
3957
|
[setTerminalHistory]
|
|
3686
3958
|
);
|
|
3687
|
-
const updateStreamingLine =
|
|
3959
|
+
const updateStreamingLine = React15.useCallback(
|
|
3688
3960
|
(lineId, newContent, suggestions, suggestedActions, reasoningSnapshot, pipelineDraft, sources, kgId, runId) => {
|
|
3689
3961
|
setTerminalHistory((prev) => {
|
|
3690
3962
|
const idx = prev.findIndex((line) => line.id === lineId);
|
|
@@ -3706,7 +3978,7 @@ function useStreamingChat({
|
|
|
3706
3978
|
},
|
|
3707
3979
|
[setTerminalHistory]
|
|
3708
3980
|
);
|
|
3709
|
-
const resetStreamState =
|
|
3981
|
+
const resetStreamState = React15.useCallback(() => {
|
|
3710
3982
|
setIsStreaming(false);
|
|
3711
3983
|
setStreamTransparency(null);
|
|
3712
3984
|
setIsExecuting(false);
|
|
@@ -3715,46 +3987,55 @@ function useStreamingChat({
|
|
|
3715
3987
|
currentStreamingLineId.current = null;
|
|
3716
3988
|
setTimeout(() => focusInput(), 50);
|
|
3717
3989
|
}, [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 () => {
|
|
3990
|
+
const postPipelineAction = React15.useCallback(async (runId, action2, body) => {
|
|
3991
|
+
const headers = config.getAuthHeaders?.() ?? (authTokenRef.current ? { Authorization: `Bearer ${authTokenRef.current}` } : {});
|
|
3992
|
+
const response = await fetch(`${config.agentsApiUrl || "http://localhost:3001"}/pipelines/${runId}/${action2}`, {
|
|
3993
|
+
method: "POST",
|
|
3994
|
+
headers: { "Content-Type": "application/json", ...headers },
|
|
3995
|
+
body: body === void 0 ? void 0 : JSON.stringify(body)
|
|
3996
|
+
});
|
|
3997
|
+
if (!response.ok) throw new Error(`The request was not accepted (${response.status}). Please try again.`);
|
|
3998
|
+
}, [config]);
|
|
3999
|
+
const handleHilSubmit = React15.useCallback(async (message) => {
|
|
3743
4000
|
const runId = liveRunIdRef.current;
|
|
3744
4001
|
if (!runId) return;
|
|
3745
|
-
const apiUrl = config.agentsApiUrl || "http://localhost:3001";
|
|
3746
|
-
setProgressState(null);
|
|
3747
|
-
resetStreamState();
|
|
3748
4002
|
try {
|
|
3749
|
-
await
|
|
3750
|
-
|
|
3751
|
-
|
|
3752
|
-
});
|
|
3753
|
-
} catch (e) {
|
|
3754
|
-
console.error("Failed to cancel pipeline:", e);
|
|
4003
|
+
if (message.trim()) await postPipelineAction(runId, "input", { kind: "guidance", content: message });
|
|
4004
|
+
await postPipelineAction(runId, "input", { kind: "proceed" });
|
|
4005
|
+
} catch (error) {
|
|
4006
|
+
addTerminalLine("error", `Your input was not sent. ${error.message}`);
|
|
3755
4007
|
}
|
|
3756
|
-
}, [
|
|
3757
|
-
const
|
|
4008
|
+
}, [postPipelineAction, addTerminalLine]);
|
|
4009
|
+
const handleCancelReasoning = React15.useCallback(async () => {
|
|
4010
|
+
const runId = liveRunIdRef.current;
|
|
4011
|
+
if (!runId) return;
|
|
4012
|
+
try {
|
|
4013
|
+
await postPipelineAction(runId, "cancel");
|
|
4014
|
+
setProgressState(null);
|
|
4015
|
+
resetStreamState();
|
|
4016
|
+
addTerminalLine("info", "Stopped the analysis.");
|
|
4017
|
+
} catch (error) {
|
|
4018
|
+
addTerminalLine("error", `The analysis is still running. ${error.message}`);
|
|
4019
|
+
}
|
|
4020
|
+
}, [postPipelineAction, resetStreamState, addTerminalLine]);
|
|
4021
|
+
const settleAgentSteps = React15.useCallback(
|
|
4022
|
+
(lineId) => {
|
|
4023
|
+
setTerminalHistory((prev) => {
|
|
4024
|
+
const idx = prev.findIndex((line) => line.id === lineId);
|
|
4025
|
+
if (idx === -1) return prev;
|
|
4026
|
+
const meta = prev[idx].metadata;
|
|
4027
|
+
if (!meta?.agentStepsLive) return prev;
|
|
4028
|
+
const updated = [...prev];
|
|
4029
|
+
updated[idx] = {
|
|
4030
|
+
...updated[idx],
|
|
4031
|
+
metadata: { ...updated[idx].metadata || {}, agentStepsLive: false }
|
|
4032
|
+
};
|
|
4033
|
+
return updated;
|
|
4034
|
+
});
|
|
4035
|
+
},
|
|
4036
|
+
[setTerminalHistory]
|
|
4037
|
+
);
|
|
4038
|
+
const handleStreamingChat = React15.useCallback(
|
|
3758
4039
|
async (cmd) => {
|
|
3759
4040
|
if (isProcessingRef.current || !onStreamRequest) return;
|
|
3760
4041
|
if (lastExecutedCommand.current === cmd) return;
|
|
@@ -3765,8 +4046,9 @@ function useStreamingChat({
|
|
|
3765
4046
|
const startMs = Date.now();
|
|
3766
4047
|
setStreamTransparency({ startedAtMs: startMs, lastEventAtMs: startMs });
|
|
3767
4048
|
setActivityEvents([]);
|
|
3768
|
-
const
|
|
3769
|
-
const
|
|
4049
|
+
const turnKey = `${Date.now()}-${++turnSequence.current}`;
|
|
4050
|
+
const userCommandId = `${turnKey}:question`;
|
|
4051
|
+
const streamingLineId = `${turnKey}:answer`;
|
|
3770
4052
|
currentStreamingLineId.current = streamingLineId;
|
|
3771
4053
|
const userCommandEntry = {
|
|
3772
4054
|
id: userCommandId,
|
|
@@ -3792,14 +4074,14 @@ function useStreamingChat({
|
|
|
3792
4074
|
setTerminalHistory((prev) => [
|
|
3793
4075
|
...prev,
|
|
3794
4076
|
{
|
|
3795
|
-
id:
|
|
4077
|
+
id: `${turnKey}:before-question`,
|
|
3796
4078
|
type: "info",
|
|
3797
4079
|
content: "",
|
|
3798
4080
|
timestamp: /* @__PURE__ */ new Date()
|
|
3799
4081
|
},
|
|
3800
4082
|
userCommandEntry,
|
|
3801
4083
|
{
|
|
3802
|
-
id:
|
|
4084
|
+
id: `${turnKey}:before-answer`,
|
|
3803
4085
|
type: "info",
|
|
3804
4086
|
content: "",
|
|
3805
4087
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -3813,10 +4095,37 @@ function useStreamingChat({
|
|
|
3813
4095
|
let sources;
|
|
3814
4096
|
let kgId;
|
|
3815
4097
|
let runId;
|
|
4098
|
+
const steps = /* @__PURE__ */ new Map();
|
|
4099
|
+
const fail = (error) => {
|
|
4100
|
+
if (currentStreamingLineId.current !== streamingLineId) return;
|
|
4101
|
+
settleAgentSteps(streamingLineId);
|
|
4102
|
+
updateStreamingLine(
|
|
4103
|
+
streamingLineId,
|
|
4104
|
+
fullResponse,
|
|
4105
|
+
pageSuggestions,
|
|
4106
|
+
suggestedActions,
|
|
4107
|
+
progressStateRef.current ? captureReasoningSnapshot(progressStateRef.current, true) : void 0,
|
|
4108
|
+
pipelineDraft,
|
|
4109
|
+
sources,
|
|
4110
|
+
kgId,
|
|
4111
|
+
runId
|
|
4112
|
+
);
|
|
4113
|
+
setTerminalHistory((prev) => prev.map((entry) => entry.id === streamingLineId ? { ...entry, metadata: { ...entry.metadata, completion: { stop_reason: /connection|interrupt/i.test(error) ? "interrupted" : "failed" } } } : entry));
|
|
4114
|
+
addTerminalLine("error", error);
|
|
4115
|
+
setProgressState(null);
|
|
4116
|
+
resetStreamState();
|
|
4117
|
+
};
|
|
3816
4118
|
try {
|
|
3817
4119
|
await onStreamRequest(cmd, {
|
|
3818
4120
|
onChunk: (chunk) => {
|
|
4121
|
+
if (currentStreamingLineId.current !== streamingLineId) return;
|
|
4122
|
+
if (chunk.entryMetadata) {
|
|
4123
|
+
setTerminalHistory((prev) => prev.map((entry) => entry.id === streamingLineId ? { ...entry, metadata: { ...entry.metadata, ...chunk.entryMetadata } } : entry));
|
|
4124
|
+
}
|
|
3819
4125
|
const eventMs = Date.now();
|
|
4126
|
+
if (chunk.completion) {
|
|
4127
|
+
setTerminalHistory((prev) => prev.map((entry) => entry.id === streamingLineId ? { ...entry, metadata: { ...entry.metadata, completion: chunk.completion } } : entry));
|
|
4128
|
+
}
|
|
3820
4129
|
if (chunk.sender) {
|
|
3821
4130
|
setStreamingLineSender(streamingLineId, chunk.sender);
|
|
3822
4131
|
if (currentUser) {
|
|
@@ -3829,6 +4138,28 @@ function useStreamingChat({
|
|
|
3829
4138
|
if (chunk.collaboration) {
|
|
3830
4139
|
setCollaborationState(chunk.collaboration);
|
|
3831
4140
|
}
|
|
4141
|
+
if (chunk.step) {
|
|
4142
|
+
steps.set(chunk.step.seq, chunk.step);
|
|
4143
|
+
const ordered = Array.from(steps.values()).sort((a, b) => a.seq - b.seq);
|
|
4144
|
+
setTerminalHistory((prev) => {
|
|
4145
|
+
const idx = prev.findIndex((line) => line.id === streamingLineId);
|
|
4146
|
+
if (idx === -1) return prev;
|
|
4147
|
+
const updated = [...prev];
|
|
4148
|
+
updated[idx] = {
|
|
4149
|
+
...updated[idx],
|
|
4150
|
+
metadata: {
|
|
4151
|
+
...updated[idx].metadata || {},
|
|
4152
|
+
agentSteps: ordered,
|
|
4153
|
+
// Explicit rather than inferred from the streaming cursor:
|
|
4154
|
+
// a tool loop runs to completion BEFORE the first answer
|
|
4155
|
+
// token, so during the whole loop the entry's content is
|
|
4156
|
+
// empty and carries no cursor to read.
|
|
4157
|
+
agentStepsLive: true
|
|
4158
|
+
}
|
|
4159
|
+
};
|
|
4160
|
+
return updated;
|
|
4161
|
+
});
|
|
4162
|
+
}
|
|
3832
4163
|
const ckgId = extractKgId(chunk, chunk.progress);
|
|
3833
4164
|
const cRunId = chunk.run_id || chunk.progress?.run_id;
|
|
3834
4165
|
const ctId = chunk.thread_id || chunk.progress?.thread_id || chunk.reasoning_thread_id || chunk.progress?.reasoning_thread_id;
|
|
@@ -3972,49 +4303,14 @@ function useStreamingChat({
|
|
|
3972
4303
|
kgId,
|
|
3973
4304
|
runId
|
|
3974
4305
|
);
|
|
4306
|
+
settleAgentSteps(streamingLineId);
|
|
3975
4307
|
resetStreamState();
|
|
3976
4308
|
}
|
|
3977
4309
|
},
|
|
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
|
-
}
|
|
4310
|
+
onError: fail
|
|
4000
4311
|
}, reasoningModeRef.current ? { reasoningMode: reasoningModeRef.current } : void 0);
|
|
4001
4312
|
} 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();
|
|
4313
|
+
fail(error?.message || "The answer could not be completed.");
|
|
4018
4314
|
}
|
|
4019
4315
|
},
|
|
4020
4316
|
[
|
|
@@ -4023,10 +4319,12 @@ function useStreamingChat({
|
|
|
4023
4319
|
updateStreamingLine,
|
|
4024
4320
|
setStreamingLineSender,
|
|
4025
4321
|
resetStreamState,
|
|
4026
|
-
addTerminalLine
|
|
4322
|
+
addTerminalLine,
|
|
4323
|
+
settleAgentSteps,
|
|
4324
|
+
currentUser
|
|
4027
4325
|
]
|
|
4028
4326
|
);
|
|
4029
|
-
const clearReasoningSession =
|
|
4327
|
+
const clearReasoningSession = React15.useCallback(() => {
|
|
4030
4328
|
setLiveKgId(null);
|
|
4031
4329
|
setLiveRunId(null);
|
|
4032
4330
|
setLiveThreadId(null);
|
|
@@ -4057,9 +4355,9 @@ function useMessagePolling({
|
|
|
4057
4355
|
pollIntervalMs = 3e3,
|
|
4058
4356
|
enabled
|
|
4059
4357
|
}) {
|
|
4060
|
-
const lastMessageIdRef =
|
|
4061
|
-
const pollingRef =
|
|
4062
|
-
const poll =
|
|
4358
|
+
const lastMessageIdRef = React15.useRef(void 0);
|
|
4359
|
+
const pollingRef = React15.useRef(false);
|
|
4360
|
+
const poll = React15.useCallback(async () => {
|
|
4063
4361
|
if (!onPollMessages || pollingRef.current) return;
|
|
4064
4362
|
pollingRef.current = true;
|
|
4065
4363
|
try {
|
|
@@ -4098,7 +4396,7 @@ function useMessagePolling({
|
|
|
4098
4396
|
pollingRef.current = false;
|
|
4099
4397
|
}
|
|
4100
4398
|
}, [onPollMessages, setTerminalHistory]);
|
|
4101
|
-
|
|
4399
|
+
React15.useEffect(() => {
|
|
4102
4400
|
if (!enabled || !onPollMessages) return;
|
|
4103
4401
|
const timer = setInterval(poll, pollIntervalMs);
|
|
4104
4402
|
return () => clearInterval(timer);
|
|
@@ -4116,6 +4414,7 @@ function useTerminalCore({
|
|
|
4116
4414
|
onReasoningModeChangeProp,
|
|
4117
4415
|
reasoningRef,
|
|
4118
4416
|
workingGroupContextProp = null,
|
|
4417
|
+
autoFocusInput = true,
|
|
4119
4418
|
onResolveWorkingGroup,
|
|
4120
4419
|
onRagFileUpload,
|
|
4121
4420
|
onListRagFiles,
|
|
@@ -4133,14 +4432,15 @@ function useTerminalCore({
|
|
|
4133
4432
|
pollIntervalMs,
|
|
4134
4433
|
authToken
|
|
4135
4434
|
}) {
|
|
4136
|
-
const
|
|
4435
|
+
const agentLabel = config.agentLabel?.trim() || DEFAULT_AGENT_LABEL;
|
|
4436
|
+
const [internalReasoningMode, setInternalReasoningMode] = React15.useState(null);
|
|
4137
4437
|
const reasoningMode = reasoningModeProp !== void 0 ? reasoningModeProp : internalReasoningMode;
|
|
4138
4438
|
const onReasoningModeChange = onReasoningModeChangeProp || setInternalReasoningMode;
|
|
4139
|
-
const [terminalHistory, setTerminalHistory] =
|
|
4439
|
+
const [terminalHistory, setTerminalHistory] = React15.useState(() => {
|
|
4140
4440
|
if (initialHistory && initialHistory.length > 0) return initialHistory;
|
|
4141
|
-
return [{ type: "system", content:
|
|
4441
|
+
return [{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() }];
|
|
4142
4442
|
});
|
|
4143
|
-
|
|
4443
|
+
React15.useEffect(() => {
|
|
4144
4444
|
if (historyRef) {
|
|
4145
4445
|
historyRef.current = { setHistory: setTerminalHistory, setIsExecuting };
|
|
4146
4446
|
}
|
|
@@ -4148,10 +4448,10 @@ function useTerminalCore({
|
|
|
4148
4448
|
if (historyRef) historyRef.current = null;
|
|
4149
4449
|
};
|
|
4150
4450
|
}, [historyRef]);
|
|
4151
|
-
const enrichedHistory =
|
|
4451
|
+
const enrichedHistory = React15.useMemo(() => {
|
|
4152
4452
|
if (!sourceKGNodes?.length) return terminalHistory;
|
|
4153
4453
|
let changed = false;
|
|
4154
|
-
const
|
|
4454
|
+
const result2 = terminalHistory.map((entry) => {
|
|
4155
4455
|
if ((entry.type === "response" || entry.type === "success") && entry.content && entry.content.length > 20 && !entry.sources?.length) {
|
|
4156
4456
|
const sources = extractKGSources(entry.content, sourceKGNodes);
|
|
4157
4457
|
if (sources.length > 0) {
|
|
@@ -4161,9 +4461,9 @@ function useTerminalCore({
|
|
|
4161
4461
|
}
|
|
4162
4462
|
return entry;
|
|
4163
4463
|
});
|
|
4164
|
-
return changed ?
|
|
4464
|
+
return changed ? result2 : terminalHistory;
|
|
4165
4465
|
}, [terminalHistory, sourceKGNodes]);
|
|
4166
|
-
|
|
4466
|
+
React15.useEffect(() => {
|
|
4167
4467
|
if (initialHistory && initialHistory.length > 0) {
|
|
4168
4468
|
setTerminalHistory((prev) => {
|
|
4169
4469
|
const isDefault = prev.length <= 1 && prev[0]?.type === "system";
|
|
@@ -4171,35 +4471,39 @@ function useTerminalCore({
|
|
|
4171
4471
|
});
|
|
4172
4472
|
}
|
|
4173
4473
|
}, [initialHistory]);
|
|
4174
|
-
|
|
4474
|
+
React15.useEffect(() => {
|
|
4175
4475
|
onHistoryChange?.(enrichedHistory);
|
|
4176
4476
|
}, [enrichedHistory, onHistoryChange]);
|
|
4177
|
-
const addTerminalLine =
|
|
4477
|
+
const addTerminalLine = React15.useCallback((type, content, pageSuggestions) => {
|
|
4178
4478
|
setTerminalHistory((prev) => [...prev, { id: Date.now().toString(), type, content, timestamp: /* @__PURE__ */ new Date(), suggestions: pageSuggestions }]);
|
|
4179
4479
|
}, []);
|
|
4180
|
-
const addTerminalLineWithActions =
|
|
4480
|
+
const addTerminalLineWithActions = React15.useCallback((content, actions) => {
|
|
4181
4481
|
setTerminalHistory((prev) => [...prev, { id: Date.now().toString(), type: "response", content, timestamp: /* @__PURE__ */ new Date(), suggested_actions: actions }]);
|
|
4182
4482
|
}, []);
|
|
4183
|
-
const [currentCommand, setCurrentCommand] =
|
|
4184
|
-
const [
|
|
4185
|
-
const [
|
|
4186
|
-
const [
|
|
4187
|
-
const [
|
|
4188
|
-
const [
|
|
4189
|
-
const
|
|
4190
|
-
const
|
|
4191
|
-
const
|
|
4192
|
-
|
|
4483
|
+
const [currentCommand, setCurrentCommand] = React15.useState("");
|
|
4484
|
+
const [pendingSubmit, setPendingSubmit] = React15.useState(null);
|
|
4485
|
+
const [workingGroupContext, setWorkingGroupContext] = React15.useState(workingGroupContextProp);
|
|
4486
|
+
const [hasShownWelcome, setHasShownWelcome] = React15.useState(false);
|
|
4487
|
+
const [isInputFocused, setIsInputFocused] = React15.useState(true);
|
|
4488
|
+
const [commandPaletteItems, setCommandPaletteItems] = React15.useState([]);
|
|
4489
|
+
const [selectedPaletteItem, setSelectedPaletteItem] = React15.useState(0);
|
|
4490
|
+
const terminalBodyRef = React15.useRef(null);
|
|
4491
|
+
const fileInputRef = React15.useRef(null);
|
|
4492
|
+
const uploadAbortsRef = React15.useRef([]);
|
|
4493
|
+
React15.useEffect(() => () => {
|
|
4193
4494
|
for (const ctrl of uploadAbortsRef.current) ctrl.abort();
|
|
4194
4495
|
uploadAbortsRef.current = [];
|
|
4195
4496
|
}, []);
|
|
4196
|
-
const { inputRef, focusInput } = useFocusManagement();
|
|
4197
|
-
|
|
4497
|
+
const { inputRef, focusInput } = useFocusManagement(autoFocusInput);
|
|
4498
|
+
React15.useEffect(() => {
|
|
4198
4499
|
function onPrefill(e) {
|
|
4199
4500
|
const detail = e.detail;
|
|
4200
4501
|
if (!detail || typeof detail.value !== "string") return;
|
|
4201
4502
|
const value = detail.value;
|
|
4202
4503
|
setCurrentCommand(value);
|
|
4504
|
+
if (e.detail?.submit) {
|
|
4505
|
+
setPendingSubmit(value);
|
|
4506
|
+
}
|
|
4203
4507
|
requestAnimationFrame(() => {
|
|
4204
4508
|
focusInput();
|
|
4205
4509
|
const el = inputRef.current;
|
|
@@ -4213,6 +4517,9 @@ function useTerminalCore({
|
|
|
4213
4517
|
window.removeEventListener("yieldfabric:terminal:prefill", onPrefill);
|
|
4214
4518
|
};
|
|
4215
4519
|
}, [focusInput, inputRef]);
|
|
4520
|
+
const restoreInputFocus = React15.useCallback(() => {
|
|
4521
|
+
if (autoFocusInput) focusInput();
|
|
4522
|
+
}, [autoFocusInput, focusInput]);
|
|
4216
4523
|
const {
|
|
4217
4524
|
isExecuting,
|
|
4218
4525
|
setIsExecuting,
|
|
@@ -4232,15 +4539,16 @@ function useTerminalCore({
|
|
|
4232
4539
|
activityEvents
|
|
4233
4540
|
} = useStreamingChat({
|
|
4234
4541
|
config,
|
|
4542
|
+
authToken,
|
|
4235
4543
|
onStreamRequest,
|
|
4236
4544
|
reasoningMode,
|
|
4237
4545
|
setTerminalHistory,
|
|
4238
4546
|
addTerminalLine,
|
|
4239
|
-
focusInput,
|
|
4547
|
+
focusInput: restoreInputFocus,
|
|
4240
4548
|
currentUser,
|
|
4241
4549
|
sourceKGNodes
|
|
4242
4550
|
});
|
|
4243
|
-
|
|
4551
|
+
React15.useEffect(() => {
|
|
4244
4552
|
const handler = () => {
|
|
4245
4553
|
setCurrentCommand("");
|
|
4246
4554
|
onReasoningModeChange(null);
|
|
@@ -4256,7 +4564,7 @@ function useTerminalCore({
|
|
|
4256
4564
|
pollIntervalMs: pollIntervalMs ?? 3e3,
|
|
4257
4565
|
enabled: !!onPollMessages
|
|
4258
4566
|
});
|
|
4259
|
-
|
|
4567
|
+
React15.useEffect(() => {
|
|
4260
4568
|
if (reasoningRef) {
|
|
4261
4569
|
reasoningRef.current = { progressState, submitInput: handleHilSubmit, cancelReasoning: handleCancelReasoning };
|
|
4262
4570
|
}
|
|
@@ -4264,25 +4572,25 @@ function useTerminalCore({
|
|
|
4264
4572
|
if (reasoningRef) reasoningRef.current = null;
|
|
4265
4573
|
};
|
|
4266
4574
|
});
|
|
4267
|
-
|
|
4575
|
+
React15.useEffect(() => {
|
|
4268
4576
|
if (liveKgId) {
|
|
4269
4577
|
onKGScopeChange?.({ kgId: liveKgId, label: "Live Analysis" });
|
|
4270
4578
|
onKgIdChange?.(liveKgId);
|
|
4271
4579
|
}
|
|
4272
4580
|
}, [liveKgId]);
|
|
4273
|
-
|
|
4581
|
+
React15.useEffect(() => {
|
|
4274
4582
|
if (liveRunId) onRunIdChange?.(liveRunId);
|
|
4275
4583
|
}, [liveRunId]);
|
|
4276
|
-
|
|
4584
|
+
React15.useEffect(() => {
|
|
4277
4585
|
if (liveThreadId) onThreadIdChange?.(liveThreadId);
|
|
4278
4586
|
}, [liveThreadId]);
|
|
4279
|
-
|
|
4587
|
+
React15.useEffect(() => {
|
|
4280
4588
|
onReasoningPhaseChange?.(progressState?.phase ?? null);
|
|
4281
4589
|
}, [progressState?.phase]);
|
|
4282
|
-
|
|
4590
|
+
React15.useEffect(() => {
|
|
4283
4591
|
setWorkingGroupContext(workingGroupContextProp || null);
|
|
4284
4592
|
}, [workingGroupContextProp]);
|
|
4285
|
-
|
|
4593
|
+
React15.useEffect(() => {
|
|
4286
4594
|
let cancelled = false;
|
|
4287
4595
|
if (!onResolveWorkingGroup) return;
|
|
4288
4596
|
(async () => {
|
|
@@ -4297,26 +4605,26 @@ function useTerminalCore({
|
|
|
4297
4605
|
cancelled = true;
|
|
4298
4606
|
};
|
|
4299
4607
|
}, [onResolveWorkingGroup]);
|
|
4300
|
-
|
|
4608
|
+
React15.useEffect(() => {
|
|
4301
4609
|
const handleActionResult = (event) => {
|
|
4302
|
-
const
|
|
4303
|
-
if (
|
|
4610
|
+
const result2 = event.detail;
|
|
4611
|
+
if (result2.success) {
|
|
4304
4612
|
addTerminalLine("success", "Action executed successfully!");
|
|
4305
|
-
if (
|
|
4613
|
+
if (result2.data) addTerminalLine("response", JSON.stringify(result2.data, null, 2));
|
|
4306
4614
|
} else {
|
|
4307
|
-
addTerminalLine("error", `Action failed: ${
|
|
4615
|
+
addTerminalLine("error", `Action failed: ${result2.error || "Unknown error"}`);
|
|
4308
4616
|
}
|
|
4309
4617
|
};
|
|
4310
4618
|
window.addEventListener("terminal-action-result", handleActionResult);
|
|
4311
4619
|
return () => window.removeEventListener("terminal-action-result", handleActionResult);
|
|
4312
4620
|
}, [addTerminalLine]);
|
|
4313
|
-
|
|
4621
|
+
React15.useEffect(() => {
|
|
4314
4622
|
if (showWelcomeMessage && initialHistory.length === 0 && !hasShownWelcome && config.welcomeMessage) {
|
|
4315
4623
|
setHasShownWelcome(true);
|
|
4316
4624
|
const fullMessage = config.welcomeMessage;
|
|
4317
4625
|
const typingLineId = Date.now().toString();
|
|
4318
4626
|
setTerminalHistory([
|
|
4319
|
-
{ type: "system", content:
|
|
4627
|
+
{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() },
|
|
4320
4628
|
{ id: typingLineId, type: "info", content: "", timestamp: /* @__PURE__ */ new Date() }
|
|
4321
4629
|
]);
|
|
4322
4630
|
let i = 0;
|
|
@@ -4329,10 +4637,10 @@ function useTerminalCore({
|
|
|
4329
4637
|
requestAnimationFrame(step);
|
|
4330
4638
|
}
|
|
4331
4639
|
}, [showWelcomeMessage, hasShownWelcome, initialHistory.length, config.welcomeMessage]);
|
|
4332
|
-
|
|
4640
|
+
React15.useEffect(() => {
|
|
4333
4641
|
if (terminalBodyRef.current) terminalBodyRef.current.scrollTop = terminalBodyRef.current.scrollHeight;
|
|
4334
4642
|
}, [terminalHistory, progressState]);
|
|
4335
|
-
const updateCommandPalette =
|
|
4643
|
+
const updateCommandPalette = React15.useCallback((value) => {
|
|
4336
4644
|
if (value.startsWith("/")) {
|
|
4337
4645
|
const query = value.slice(1);
|
|
4338
4646
|
setCommandPaletteItems(filterCommands(query, getBuiltInCommands(), config.customCommands || []));
|
|
@@ -4342,7 +4650,7 @@ function useTerminalCore({
|
|
|
4342
4650
|
setCommandPaletteItems([]);
|
|
4343
4651
|
return false;
|
|
4344
4652
|
}, [config.customCommands]);
|
|
4345
|
-
const handleCommandPaletteKeyDown =
|
|
4653
|
+
const handleCommandPaletteKeyDown = React15.useCallback((e) => {
|
|
4346
4654
|
if (commandPaletteItems.length === 0) return false;
|
|
4347
4655
|
if (e.key === "ArrowUp") {
|
|
4348
4656
|
e.preventDefault();
|
|
@@ -4370,15 +4678,15 @@ function useTerminalCore({
|
|
|
4370
4678
|
}
|
|
4371
4679
|
return false;
|
|
4372
4680
|
}, [commandPaletteItems, selectedPaletteItem]);
|
|
4373
|
-
const handleClearCommand =
|
|
4681
|
+
const handleClearCommand = React15.useCallback(() => {
|
|
4374
4682
|
setTerminalHistory([
|
|
4375
|
-
{ type: "system", content:
|
|
4683
|
+
{ type: "system", content: agentLabel, timestamp: /* @__PURE__ */ new Date() },
|
|
4376
4684
|
{ type: "system", content: "Terminal cleared.", timestamp: /* @__PURE__ */ new Date() }
|
|
4377
4685
|
]);
|
|
4378
4686
|
setCurrentCommand("");
|
|
4379
4687
|
setTimeout(() => focusInput(), 50);
|
|
4380
4688
|
}, [focusInput]);
|
|
4381
|
-
const handleUploadCommand =
|
|
4689
|
+
const handleUploadCommand = React15.useCallback(() => {
|
|
4382
4690
|
if (!onRagFileUpload) {
|
|
4383
4691
|
addTerminalLine("error", "Upload not enabled in this terminal.");
|
|
4384
4692
|
} else {
|
|
@@ -4387,7 +4695,7 @@ function useTerminalCore({
|
|
|
4387
4695
|
setCurrentCommand("");
|
|
4388
4696
|
setTimeout(() => focusInput(), 50);
|
|
4389
4697
|
}, [onRagFileUpload, addTerminalLine, focusInput]);
|
|
4390
|
-
const handleUploadFiles =
|
|
4698
|
+
const handleUploadFiles = React15.useCallback(async (files) => {
|
|
4391
4699
|
if (!files?.length || !onRagFileUpload) return;
|
|
4392
4700
|
const names = files.map((f) => f.name).join(", ");
|
|
4393
4701
|
addTerminalLine("info", "");
|
|
@@ -4395,11 +4703,11 @@ function useTerminalCore({
|
|
|
4395
4703
|
addTerminalLine("info", `Uploading ${files.length} file(s)...`);
|
|
4396
4704
|
setIsExecuting(true);
|
|
4397
4705
|
try {
|
|
4398
|
-
const
|
|
4399
|
-
if (
|
|
4400
|
-
addTerminalLine("success", `Started ${
|
|
4401
|
-
if (
|
|
4402
|
-
const runs =
|
|
4706
|
+
const result2 = await onRagFileUpload(files, workingGroupContext);
|
|
4707
|
+
if (result2.success) {
|
|
4708
|
+
addTerminalLine("success", `Started ${result2.pipelineRuns?.length ?? result2.documentsIngested ?? files.length} ingestion pipeline(s)`);
|
|
4709
|
+
if (result2.message) addTerminalLine("response", result2.message);
|
|
4710
|
+
const runs = result2.pipelineRuns ?? [];
|
|
4403
4711
|
if (runs.length > 0) {
|
|
4404
4712
|
const apiUrl = config.agentsApiUrl || "http://localhost:3001";
|
|
4405
4713
|
const remaining = new Set(runs.map((r) => r.run_id));
|
|
@@ -4486,7 +4794,7 @@ function useTerminalCore({
|
|
|
4486
4794
|
await handleListFilesCommand();
|
|
4487
4795
|
}
|
|
4488
4796
|
} else {
|
|
4489
|
-
addTerminalLine("error", `Upload failed${
|
|
4797
|
+
addTerminalLine("error", `Upload failed${result2.message ? `: ${result2.message}` : ""}`);
|
|
4490
4798
|
}
|
|
4491
4799
|
} catch (error) {
|
|
4492
4800
|
addTerminalLine("error", `Upload exception: ${error?.message || "Unknown error"}`);
|
|
@@ -4495,8 +4803,8 @@ function useTerminalCore({
|
|
|
4495
4803
|
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
4496
4804
|
setTimeout(() => focusInput(), 50);
|
|
4497
4805
|
}
|
|
4498
|
-
}, [onRagFileUpload, onListRagFiles, workingGroupContext, addTerminalLine, setIsExecuting, focusInput, config.agentsApiUrl]);
|
|
4499
|
-
const handleListFilesCommand =
|
|
4806
|
+
}, [onRagFileUpload, onListRagFiles, workingGroupContext, addTerminalLine, setIsExecuting, focusInput, config.agentsApiUrl, authToken]);
|
|
4807
|
+
const handleListFilesCommand = React15.useCallback(async () => {
|
|
4500
4808
|
addTerminalLine("info", "");
|
|
4501
4809
|
addTerminalLine("command", "files");
|
|
4502
4810
|
if (!onListRagFiles) {
|
|
@@ -4505,12 +4813,12 @@ function useTerminalCore({
|
|
|
4505
4813
|
}
|
|
4506
4814
|
setIsExecuting(true);
|
|
4507
4815
|
try {
|
|
4508
|
-
const
|
|
4509
|
-
if (!
|
|
4510
|
-
addTerminalLine("error", `Could not load files${
|
|
4816
|
+
const result2 = await onListRagFiles(workingGroupContext);
|
|
4817
|
+
if (!result2.success) {
|
|
4818
|
+
addTerminalLine("error", `Could not load files${result2.message ? `: ${result2.message}` : ""}`);
|
|
4511
4819
|
return;
|
|
4512
4820
|
}
|
|
4513
|
-
const files =
|
|
4821
|
+
const files = result2.files || [];
|
|
4514
4822
|
if (files.length === 0) {
|
|
4515
4823
|
addTerminalLine("info", "No files uploaded yet for this page working group.");
|
|
4516
4824
|
return;
|
|
@@ -4530,7 +4838,7 @@ function useTerminalCore({
|
|
|
4530
4838
|
setIsExecuting(false);
|
|
4531
4839
|
}
|
|
4532
4840
|
}, [onListRagFiles, workingGroupContext, addTerminalLine, addTerminalLineWithActions, setIsExecuting]);
|
|
4533
|
-
const handleTerminalActionExecute =
|
|
4841
|
+
const handleTerminalActionExecute = React15.useCallback(async (updatedAction) => {
|
|
4534
4842
|
const actionType = updatedAction?.action_type;
|
|
4535
4843
|
const payload = updatedAction?.payload || {};
|
|
4536
4844
|
if (actionType === "delete_file") {
|
|
@@ -4539,12 +4847,12 @@ function useTerminalCore({
|
|
|
4539
4847
|
return;
|
|
4540
4848
|
}
|
|
4541
4849
|
const title = payload.title || payload.document_id;
|
|
4542
|
-
const
|
|
4543
|
-
if (
|
|
4850
|
+
const result2 = await onDeleteRagFile(String(payload.document_id), workingGroupContext);
|
|
4851
|
+
if (result2.success) {
|
|
4544
4852
|
addTerminalLine("success", `Removed ${title}`);
|
|
4545
4853
|
await handleListFilesCommand();
|
|
4546
4854
|
} else {
|
|
4547
|
-
addTerminalLine("error", `Failed to remove ${title}${
|
|
4855
|
+
addTerminalLine("error", `Failed to remove ${title}${result2.message ? `: ${result2.message}` : ""}`);
|
|
4548
4856
|
}
|
|
4549
4857
|
return;
|
|
4550
4858
|
}
|
|
@@ -4554,9 +4862,9 @@ function useTerminalCore({
|
|
|
4554
4862
|
return;
|
|
4555
4863
|
}
|
|
4556
4864
|
const title = payload.title || payload.document_id;
|
|
4557
|
-
const
|
|
4558
|
-
if (
|
|
4559
|
-
else addTerminalLine("error", `Download failed for ${title}${
|
|
4865
|
+
const result2 = await onDownloadRagFile(String(payload.document_id), title, workingGroupContext);
|
|
4866
|
+
if (result2.success) addTerminalLine("success", `Download started: ${title}`);
|
|
4867
|
+
else addTerminalLine("error", `Download failed for ${title}${result2.message ? `: ${result2.message}` : ""}`);
|
|
4560
4868
|
return;
|
|
4561
4869
|
}
|
|
4562
4870
|
if (actionType === "resume_pipeline_run") {
|
|
@@ -4595,6 +4903,8 @@ function useTerminalCore({
|
|
|
4595
4903
|
window.dispatchEvent(new CustomEvent("terminal-action-execute", { detail: updatedAction, bubbles: true }));
|
|
4596
4904
|
}, [onDeleteRagFile, onDownloadRagFile, workingGroupContext, addTerminalLine, handleListFilesCommand, config.agentsApiUrl]);
|
|
4597
4905
|
return {
|
|
4906
|
+
// Identity
|
|
4907
|
+
agentLabel,
|
|
4598
4908
|
// History
|
|
4599
4909
|
terminalHistory,
|
|
4600
4910
|
setTerminalHistory,
|
|
@@ -4623,6 +4933,8 @@ function useTerminalCore({
|
|
|
4623
4933
|
// Command input
|
|
4624
4934
|
currentCommand,
|
|
4625
4935
|
setCurrentCommand,
|
|
4936
|
+
pendingSubmit,
|
|
4937
|
+
setPendingSubmit,
|
|
4626
4938
|
commandPaletteItems,
|
|
4627
4939
|
setCommandPaletteItems,
|
|
4628
4940
|
selectedPaletteItem,
|
|
@@ -4653,10 +4965,10 @@ function useSlashMentionPicker({
|
|
|
4653
4965
|
enabledCommands = ["note", "personal"],
|
|
4654
4966
|
requireSlashCommand = true
|
|
4655
4967
|
}) {
|
|
4656
|
-
const [candidates, setCandidates] =
|
|
4657
|
-
const [selectedIndex, setSelectedIndex] =
|
|
4658
|
-
const debounceRef =
|
|
4659
|
-
const reqIdRef =
|
|
4968
|
+
const [candidates, setCandidates] = React15.useState([]);
|
|
4969
|
+
const [selectedIndex, setSelectedIndex] = React15.useState(0);
|
|
4970
|
+
const debounceRef = React15.useRef(null);
|
|
4971
|
+
const reqIdRef = React15.useRef(0);
|
|
4660
4972
|
const extracted = extractQuery(
|
|
4661
4973
|
currentCommand,
|
|
4662
4974
|
caretIndex,
|
|
@@ -4666,7 +4978,7 @@ function useSlashMentionPicker({
|
|
|
4666
4978
|
const query = extracted?.query ?? null;
|
|
4667
4979
|
const command = extracted?.command;
|
|
4668
4980
|
const queryActive = query !== null && !!onMentionResolve;
|
|
4669
|
-
|
|
4981
|
+
React15.useEffect(() => {
|
|
4670
4982
|
if (!queryActive) {
|
|
4671
4983
|
setCandidates([]);
|
|
4672
4984
|
setSelectedIndex(0);
|
|
@@ -4689,17 +5001,17 @@ function useSlashMentionPicker({
|
|
|
4689
5001
|
if (debounceRef.current) clearTimeout(debounceRef.current);
|
|
4690
5002
|
};
|
|
4691
5003
|
}, [queryActive, query, command, onMentionResolve]);
|
|
4692
|
-
const navigateUp =
|
|
5004
|
+
const navigateUp = React15.useCallback(() => {
|
|
4693
5005
|
setSelectedIndex((i) => Math.max(0, i - 1));
|
|
4694
5006
|
}, []);
|
|
4695
|
-
const navigateDown =
|
|
5007
|
+
const navigateDown = React15.useCallback(() => {
|
|
4696
5008
|
setSelectedIndex((i) => Math.min((candidates.length || 1) - 1, i + 1));
|
|
4697
5009
|
}, [candidates.length]);
|
|
4698
|
-
const cancel =
|
|
5010
|
+
const cancel = React15.useCallback(() => {
|
|
4699
5011
|
setCandidates([]);
|
|
4700
5012
|
setSelectedIndex(0);
|
|
4701
5013
|
}, []);
|
|
4702
|
-
const complete =
|
|
5014
|
+
const complete = React15.useCallback(
|
|
4703
5015
|
(candidate) => {
|
|
4704
5016
|
if (query === null) return null;
|
|
4705
5017
|
const head = currentCommand.slice(0, caretIndex);
|
|
@@ -4745,6 +5057,7 @@ function extractQuery(input, caret, enabledCommands, requireSlashCommand) {
|
|
|
4745
5057
|
return { query: tail, command: cmd };
|
|
4746
5058
|
}
|
|
4747
5059
|
function StandardTerminal({
|
|
5060
|
+
showBusyIndicator,
|
|
4748
5061
|
theme: themeOverrides,
|
|
4749
5062
|
config,
|
|
4750
5063
|
onCommandExecute,
|
|
@@ -4764,9 +5077,15 @@ function StandardTerminal({
|
|
|
4764
5077
|
onDeleteRagFile,
|
|
4765
5078
|
onDownloadRagFile,
|
|
4766
5079
|
workingGroupContext: workingGroupContextProp = null,
|
|
5080
|
+
showWorkingGroupBanner = true,
|
|
5081
|
+
autoFocusInput = true,
|
|
5082
|
+
inputPlaceholder,
|
|
5083
|
+
submitRequest,
|
|
5084
|
+
onSubmitRequest,
|
|
4767
5085
|
onPipelineDraftEdit,
|
|
4768
5086
|
onPipelineDraftReject,
|
|
4769
5087
|
onSubmitNote,
|
|
5088
|
+
onSubmitLog,
|
|
4770
5089
|
onMentionResolve,
|
|
4771
5090
|
onMentionPicked,
|
|
4772
5091
|
availableKGs,
|
|
@@ -4787,6 +5106,7 @@ function StandardTerminal({
|
|
|
4787
5106
|
widgets,
|
|
4788
5107
|
slots,
|
|
4789
5108
|
onSourcesActivate,
|
|
5109
|
+
onSourceActivate,
|
|
4790
5110
|
onPollMessages,
|
|
4791
5111
|
pollIntervalMs,
|
|
4792
5112
|
historyRef
|
|
@@ -4802,6 +5122,7 @@ function StandardTerminal({
|
|
|
4802
5122
|
reasoningRef,
|
|
4803
5123
|
workingGroupContextProp,
|
|
4804
5124
|
onResolveWorkingGroup,
|
|
5125
|
+
autoFocusInput,
|
|
4805
5126
|
onRagFileUpload,
|
|
4806
5127
|
onListRagFiles,
|
|
4807
5128
|
onDeleteRagFile,
|
|
@@ -4817,17 +5138,32 @@ function StandardTerminal({
|
|
|
4817
5138
|
showWelcomeMessage
|
|
4818
5139
|
});
|
|
4819
5140
|
const { pushCommand, navigateUp, navigateDown, resetIndex } = useCommandHistory();
|
|
4820
|
-
const
|
|
4821
|
-
|
|
4822
|
-
|
|
4823
|
-
|
|
5141
|
+
const consumedRequest = React15.useRef(null);
|
|
5142
|
+
React15__default.default.useEffect(() => {
|
|
5143
|
+
if (!submitRequest || consumedRequest.current === submitRequest.id || !submitRequest.value.trim() || !onStreamRequest || core.isExecuting || core.isStreaming || core.currentStreamingLineId.current) return;
|
|
5144
|
+
consumedRequest.current = submitRequest.id;
|
|
5145
|
+
onSubmitRequest?.(submitRequest.id);
|
|
5146
|
+
void core.handleStreamingChat(submitRequest.value.trim());
|
|
5147
|
+
}, [
|
|
5148
|
+
submitRequest,
|
|
5149
|
+
onSubmitRequest,
|
|
5150
|
+
onStreamRequest,
|
|
5151
|
+
core.isExecuting,
|
|
5152
|
+
core.isStreaming,
|
|
5153
|
+
core.currentStreamingLineId,
|
|
5154
|
+
core.handleStreamingChat
|
|
5155
|
+
]);
|
|
5156
|
+
const [suggestions, setSuggestions] = React15.useState([]);
|
|
5157
|
+
const [selectedSuggestion, setSelectedSuggestion] = React15.useState(0);
|
|
5158
|
+
const [internalAuthToken, setInternalAuthToken] = React15.useState(authToken);
|
|
5159
|
+
const authTokenRef = React15.useRef(internalAuthToken);
|
|
4824
5160
|
authTokenRef.current = internalAuthToken;
|
|
4825
|
-
|
|
5161
|
+
React15__default.default.useEffect(() => {
|
|
4826
5162
|
if (authToken !== internalAuthToken) setInternalAuthToken(authToken);
|
|
4827
5163
|
}, [authToken]);
|
|
4828
|
-
const [caretIndex, setCaretIndex] =
|
|
4829
|
-
const [slashPickedNames, setSlashPickedNames] =
|
|
4830
|
-
const liveSlashPickedNames =
|
|
5164
|
+
const [caretIndex, setCaretIndex] = React15.useState(0);
|
|
5165
|
+
const [slashPickedNames, setSlashPickedNames] = React15.useState([]);
|
|
5166
|
+
const liveSlashPickedNames = React15__default.default.useMemo(
|
|
4831
5167
|
() => slashPickedNames.filter(
|
|
4832
5168
|
(n) => core.currentCommand.toLowerCase().includes(`@${n.toLowerCase()}`)
|
|
4833
5169
|
),
|
|
@@ -4914,6 +5250,11 @@ function StandardTerminal({
|
|
|
4914
5250
|
setSuggestions([]);
|
|
4915
5251
|
}
|
|
4916
5252
|
};
|
|
5253
|
+
React15__default.default.useEffect(() => {
|
|
5254
|
+
if (!core.pendingSubmit) return;
|
|
5255
|
+
core.setPendingSubmit(null);
|
|
5256
|
+
void handleSubmit();
|
|
5257
|
+
}, [core.pendingSubmit]);
|
|
4917
5258
|
const handleSubmit = async () => {
|
|
4918
5259
|
if (!core.currentCommand.trim() || core.isExecuting || core.isStreaming || core.currentStreamingLineId.current) return;
|
|
4919
5260
|
const rawCmd = core.currentCommand.trim();
|
|
@@ -4961,6 +5302,21 @@ function StandardTerminal({
|
|
|
4961
5302
|
setTimeout(() => core.focusInput(), 50);
|
|
4962
5303
|
return;
|
|
4963
5304
|
}
|
|
5305
|
+
if (command === "log") {
|
|
5306
|
+
const prose = args.join(" ");
|
|
5307
|
+
core.addTerminalLine("command", prose.trim() ? `log ${prose}` : "log");
|
|
5308
|
+
if (!onSubmitLog) {
|
|
5309
|
+
core.addTerminalLine("error", "Work capture is not available in this context.");
|
|
5310
|
+
} else if (!prose.trim()) {
|
|
5311
|
+
core.addTerminalLine("info", "Usage: /log <what you did or decided>");
|
|
5312
|
+
} else {
|
|
5313
|
+
const result2 = await onSubmitLog(prose);
|
|
5314
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
5315
|
+
}
|
|
5316
|
+
core.setCurrentCommand("");
|
|
5317
|
+
setTimeout(() => core.focusInput(), 50);
|
|
5318
|
+
return;
|
|
5319
|
+
}
|
|
4964
5320
|
if (isNaturalLanguage(cmd, config.endpoints) && onStreamRequest) {
|
|
4965
5321
|
await core.handleStreamingChat(cmd);
|
|
4966
5322
|
core.setCurrentCommand("");
|
|
@@ -5016,8 +5372,8 @@ function StandardTerminal({
|
|
|
5016
5372
|
);
|
|
5017
5373
|
return;
|
|
5018
5374
|
}
|
|
5019
|
-
const
|
|
5020
|
-
core.addTerminalLine(
|
|
5375
|
+
const result2 = await onSubmitNote(prose, scope);
|
|
5376
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
5021
5377
|
};
|
|
5022
5378
|
const handleTokenCommand = (args) => {
|
|
5023
5379
|
core.addTerminalLine("command", `token ${args.join(" ")}`);
|
|
@@ -5045,18 +5401,18 @@ Method: ${parsed.endpoint.method}
|
|
|
5045
5401
|
Path: ${parsed.endpoint.path}`);
|
|
5046
5402
|
core.addTerminalLine("info", "");
|
|
5047
5403
|
try {
|
|
5048
|
-
const
|
|
5049
|
-
if (
|
|
5050
|
-
core.addTerminalLine("success",
|
|
5051
|
-
if (
|
|
5052
|
-
if (parsed.endpoint.id.includes("login") &&
|
|
5053
|
-
setInternalAuthToken(
|
|
5054
|
-
onAuthTokenChange?.(
|
|
5404
|
+
const result2 = await onCommandExecute(cmd, parsed.endpoint, parsed.args);
|
|
5405
|
+
if (result2.success) {
|
|
5406
|
+
core.addTerminalLine("success", result2.message || "RESPONSE: SUCCESS");
|
|
5407
|
+
if (result2.data) core.addTerminalLine("response", JSON.stringify(result2.data, null, 2));
|
|
5408
|
+
if (parsed.endpoint.id.includes("login") && result2.data?.token) {
|
|
5409
|
+
setInternalAuthToken(result2.data.token);
|
|
5410
|
+
onAuthTokenChange?.(result2.data.token);
|
|
5055
5411
|
core.addTerminalLine("success", "AUTH TOKEN AUTO-SAVED");
|
|
5056
5412
|
}
|
|
5057
5413
|
} else {
|
|
5058
|
-
core.addTerminalLine("error", `ERROR: ${
|
|
5059
|
-
if (
|
|
5414
|
+
core.addTerminalLine("error", `ERROR: ${result2.error || "Request failed"}`);
|
|
5415
|
+
if (result2.data) core.addTerminalLine("response", JSON.stringify(result2.data, null, 2));
|
|
5060
5416
|
}
|
|
5061
5417
|
} catch (error) {
|
|
5062
5418
|
core.addTerminalLine("error", `SYSTEM ERROR: ${error.message}`);
|
|
@@ -5079,14 +5435,17 @@ Path: ${parsed.endpoint.path}`);
|
|
|
5079
5435
|
className,
|
|
5080
5436
|
style,
|
|
5081
5437
|
showHeader,
|
|
5438
|
+
agentLabel: core.agentLabel,
|
|
5082
5439
|
focusInput: core.focusInput,
|
|
5083
5440
|
setTerminalHistory: core.setTerminalHistory,
|
|
5084
5441
|
terminalBodyRef: core.terminalBodyRef,
|
|
5085
5442
|
workingGroupContext: core.workingGroupContext,
|
|
5443
|
+
showWorkingGroupBanner,
|
|
5086
5444
|
progressState: core.progressState,
|
|
5087
5445
|
streamTransparency: core.streamTransparency,
|
|
5088
5446
|
streamNowMs: core.streamNowMs,
|
|
5089
5447
|
isExecuting: core.isExecuting,
|
|
5448
|
+
showBusyIndicator,
|
|
5090
5449
|
handleCancelReasoning: core.handleCancelReasoning,
|
|
5091
5450
|
onViewKnowledgeGraph,
|
|
5092
5451
|
onLiveKGUpdate,
|
|
@@ -5161,11 +5520,12 @@ Path: ${parsed.endpoint.path}`);
|
|
|
5161
5520
|
inputBar: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5162
5521
|
TerminalInputBar,
|
|
5163
5522
|
{
|
|
5523
|
+
autoFocus: autoFocusInput,
|
|
5164
5524
|
inputRef: core.inputRef,
|
|
5165
5525
|
fileInputRef: core.fileInputRef,
|
|
5166
5526
|
currentCommand: core.currentCommand,
|
|
5167
5527
|
isExecuting: core.isExecuting,
|
|
5168
|
-
placeholder: activeKGScope ? `Ask about ${activeKGScope.label}...` : "Ask anything...",
|
|
5528
|
+
placeholder: activeKGScope ? `Ask about ${activeKGScope.label}...` : inputPlaceholder ?? "Ask anything...",
|
|
5169
5529
|
onInputChange: handleInputChange,
|
|
5170
5530
|
onKeyDown: handleKeyDown,
|
|
5171
5531
|
onSubmit: handleSubmit,
|
|
@@ -5202,6 +5562,7 @@ Path: ${parsed.endpoint.path}`);
|
|
|
5202
5562
|
authToken: authTokenRef.current,
|
|
5203
5563
|
onPageNavigation,
|
|
5204
5564
|
onSourcesActivate,
|
|
5565
|
+
onSourceActivate,
|
|
5205
5566
|
renderEntryExtra,
|
|
5206
5567
|
renderEntry,
|
|
5207
5568
|
widgets,
|
|
@@ -5315,8 +5676,8 @@ function MentionDropdown({
|
|
|
5315
5676
|
const name = (p.display_name || p.entity_id).toLowerCase();
|
|
5316
5677
|
return name.includes(query.toLowerCase());
|
|
5317
5678
|
});
|
|
5318
|
-
const selectedRef =
|
|
5319
|
-
|
|
5679
|
+
const selectedRef = React15.useRef(null);
|
|
5680
|
+
React15.useEffect(() => {
|
|
5320
5681
|
selectedRef.current?.scrollIntoView({ block: "nearest" });
|
|
5321
5682
|
}, [selectedIndex]);
|
|
5322
5683
|
if (filtered.length === 0) return null;
|
|
@@ -5377,8 +5738,8 @@ var ALL_TARGET = {
|
|
|
5377
5738
|
type: "special"
|
|
5378
5739
|
};
|
|
5379
5740
|
function useMentions(currentCommand, participants, mentionTargets) {
|
|
5380
|
-
const [selectedMentionIndex, setSelectedMentionIndex] =
|
|
5381
|
-
const allCandidates =
|
|
5741
|
+
const [selectedMentionIndex, setSelectedMentionIndex] = React15.useState(0);
|
|
5742
|
+
const allCandidates = React15.useMemo(() => {
|
|
5382
5743
|
const map = /* @__PURE__ */ new Map();
|
|
5383
5744
|
if (participants) {
|
|
5384
5745
|
for (const p of participants) {
|
|
@@ -5409,7 +5770,7 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5409
5770
|
return list;
|
|
5410
5771
|
}, [participants, mentionTargets]);
|
|
5411
5772
|
const hasCandidates = allCandidates.length > 0;
|
|
5412
|
-
const mentionQuery =
|
|
5773
|
+
const mentionQuery = React15.useMemo(() => {
|
|
5413
5774
|
if (!hasCandidates) return null;
|
|
5414
5775
|
const atIdx = currentCommand.lastIndexOf("@");
|
|
5415
5776
|
if (atIdx === -1) return null;
|
|
@@ -5418,7 +5779,7 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5418
5779
|
if (query.includes(" ") && query.trim().length > 0) return null;
|
|
5419
5780
|
return query;
|
|
5420
5781
|
}, [currentCommand, hasCandidates]);
|
|
5421
|
-
const mentionCandidates =
|
|
5782
|
+
const mentionCandidates = React15.useMemo(() => {
|
|
5422
5783
|
if (mentionQuery === null) return [];
|
|
5423
5784
|
const q = mentionQuery.toLowerCase();
|
|
5424
5785
|
return allCandidates.filter(
|
|
@@ -5426,18 +5787,18 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5426
5787
|
);
|
|
5427
5788
|
}, [mentionQuery, allCandidates]);
|
|
5428
5789
|
const safeIndex = mentionCandidates.length > 0 ? Math.min(selectedMentionIndex, mentionCandidates.length - 1) : 0;
|
|
5429
|
-
const navigateMentionUp =
|
|
5790
|
+
const navigateMentionUp = React15.useCallback(() => {
|
|
5430
5791
|
setSelectedMentionIndex((prev) => Math.max(0, prev - 1));
|
|
5431
5792
|
}, []);
|
|
5432
|
-
const navigateMentionDown =
|
|
5793
|
+
const navigateMentionDown = React15.useCallback(() => {
|
|
5433
5794
|
setSelectedMentionIndex(
|
|
5434
5795
|
(prev) => Math.min((mentionCandidates.length || 1) - 1, prev + 1)
|
|
5435
5796
|
);
|
|
5436
5797
|
}, [mentionCandidates.length]);
|
|
5437
|
-
const resetMentionIndex =
|
|
5798
|
+
const resetMentionIndex = React15.useCallback(() => {
|
|
5438
5799
|
setSelectedMentionIndex(0);
|
|
5439
5800
|
}, []);
|
|
5440
|
-
const completeMention =
|
|
5801
|
+
const completeMention = React15.useCallback(
|
|
5441
5802
|
(candidate) => {
|
|
5442
5803
|
const atIdx = currentCommand.lastIndexOf("@");
|
|
5443
5804
|
if (atIdx === -1) return currentCommand;
|
|
@@ -5446,7 +5807,7 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5446
5807
|
},
|
|
5447
5808
|
[currentCommand]
|
|
5448
5809
|
);
|
|
5449
|
-
const parseMentions =
|
|
5810
|
+
const parseMentions = React15.useCallback(
|
|
5450
5811
|
(cmd) => {
|
|
5451
5812
|
if (allCandidates.length === 0) return [];
|
|
5452
5813
|
const sortedCandidates = [...allCandidates].sort(
|
|
@@ -5492,6 +5853,7 @@ function useMentions(currentCommand, participants, mentionTargets) {
|
|
|
5492
5853
|
};
|
|
5493
5854
|
}
|
|
5494
5855
|
function ChatTerminal({
|
|
5856
|
+
showBusyIndicator,
|
|
5495
5857
|
theme: themeOverrides,
|
|
5496
5858
|
config,
|
|
5497
5859
|
className = "",
|
|
@@ -5507,6 +5869,8 @@ function ChatTerminal({
|
|
|
5507
5869
|
onDeleteRagFile,
|
|
5508
5870
|
onDownloadRagFile,
|
|
5509
5871
|
workingGroupContext: workingGroupContextProp = null,
|
|
5872
|
+
showWorkingGroupBanner = true,
|
|
5873
|
+
autoFocusInput = true,
|
|
5510
5874
|
onPipelineDraftEdit,
|
|
5511
5875
|
onPipelineDraftReject,
|
|
5512
5876
|
onPageNavigation,
|
|
@@ -5529,6 +5893,7 @@ function ChatTerminal({
|
|
|
5529
5893
|
widgets,
|
|
5530
5894
|
slots,
|
|
5531
5895
|
onSourcesActivate,
|
|
5896
|
+
onSourceActivate,
|
|
5532
5897
|
historyRef,
|
|
5533
5898
|
currentUser,
|
|
5534
5899
|
onSendMessage,
|
|
@@ -5538,8 +5903,10 @@ function ChatTerminal({
|
|
|
5538
5903
|
typingUsers,
|
|
5539
5904
|
onTyping,
|
|
5540
5905
|
onSubmitNote,
|
|
5906
|
+
onSubmitLog,
|
|
5541
5907
|
onMentionResolve,
|
|
5542
|
-
onMentionPicked
|
|
5908
|
+
onMentionPicked,
|
|
5909
|
+
authToken
|
|
5543
5910
|
}) {
|
|
5544
5911
|
const core = useTerminalCore({
|
|
5545
5912
|
config,
|
|
@@ -5552,6 +5919,7 @@ function ChatTerminal({
|
|
|
5552
5919
|
reasoningRef,
|
|
5553
5920
|
workingGroupContextProp,
|
|
5554
5921
|
onResolveWorkingGroup,
|
|
5922
|
+
autoFocusInput,
|
|
5555
5923
|
onRagFileUpload,
|
|
5556
5924
|
onListRagFiles,
|
|
5557
5925
|
onDeleteRagFile,
|
|
@@ -5565,9 +5933,10 @@ function ChatTerminal({
|
|
|
5565
5933
|
showWelcomeMessage,
|
|
5566
5934
|
currentUser,
|
|
5567
5935
|
onPollMessages,
|
|
5568
|
-
pollIntervalMs
|
|
5936
|
+
pollIntervalMs,
|
|
5937
|
+
authToken
|
|
5569
5938
|
});
|
|
5570
|
-
|
|
5939
|
+
React15.useEffect(() => {
|
|
5571
5940
|
onActivityEventsChange?.(core.activityEvents);
|
|
5572
5941
|
}, [core.activityEvents]);
|
|
5573
5942
|
const isCollaborative = !!core.collaborationState?.session_id || !!onSendMessage || !!currentUser;
|
|
@@ -5582,8 +5951,8 @@ function ChatTerminal({
|
|
|
5582
5951
|
completeMention,
|
|
5583
5952
|
parseMentions
|
|
5584
5953
|
} = useMentions(mentionsInput, core.collaborationState?.participants, mentionTargets);
|
|
5585
|
-
const [caretIndex, setCaretIndex] =
|
|
5586
|
-
const [slashPickedNames, setSlashPickedNames] =
|
|
5954
|
+
const [caretIndex, setCaretIndex] = React15.useState(0);
|
|
5955
|
+
const [slashPickedNames, setSlashPickedNames] = React15.useState([]);
|
|
5587
5956
|
const slashMentions = useSlashMentionPicker({
|
|
5588
5957
|
currentCommand: core.currentCommand,
|
|
5589
5958
|
caretIndex,
|
|
@@ -5605,13 +5974,13 @@ function ChatTerminal({
|
|
|
5605
5974
|
setCaretIndex(replaced.caret);
|
|
5606
5975
|
});
|
|
5607
5976
|
};
|
|
5608
|
-
const liveSlashPickedNames =
|
|
5977
|
+
const liveSlashPickedNames = React15.useMemo(
|
|
5609
5978
|
() => slashPickedNames.filter(
|
|
5610
5979
|
(n) => core.currentCommand.toLowerCase().includes(`@${n.toLowerCase()}`)
|
|
5611
5980
|
),
|
|
5612
5981
|
[slashPickedNames, core.currentCommand]
|
|
5613
5982
|
);
|
|
5614
|
-
const knownMentionNames =
|
|
5983
|
+
const knownMentionNames = React15.useMemo(() => {
|
|
5615
5984
|
const names = [...liveSlashPickedNames];
|
|
5616
5985
|
if (mentionTargets) for (const t of mentionTargets) names.push(t.display_name);
|
|
5617
5986
|
if (core.collaborationState?.participants) {
|
|
@@ -5709,11 +6078,26 @@ function ChatTerminal({
|
|
|
5709
6078
|
`Usage: /${command} <prose>. Use @name to link an entity.`
|
|
5710
6079
|
);
|
|
5711
6080
|
} else {
|
|
5712
|
-
const
|
|
6081
|
+
const result2 = await onSubmitNote(
|
|
5713
6082
|
prose,
|
|
5714
6083
|
command === "personal" ? "personal" : "workspace"
|
|
5715
6084
|
);
|
|
5716
|
-
core.addTerminalLine(
|
|
6085
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
6086
|
+
}
|
|
6087
|
+
core.setCurrentCommand("");
|
|
6088
|
+
setTimeout(() => core.focusInput(), 50);
|
|
6089
|
+
return;
|
|
6090
|
+
}
|
|
6091
|
+
if (command === "log") {
|
|
6092
|
+
const prose = args.join(" ");
|
|
6093
|
+
core.addTerminalLine("command", prose.trim() ? `log ${prose}` : "log");
|
|
6094
|
+
if (!onSubmitLog) {
|
|
6095
|
+
core.addTerminalLine("error", "Work capture is not available in this context.");
|
|
6096
|
+
} else if (!prose.trim()) {
|
|
6097
|
+
core.addTerminalLine("info", "Usage: /log <what you did or decided>");
|
|
6098
|
+
} else {
|
|
6099
|
+
const result2 = await onSubmitLog(prose);
|
|
6100
|
+
core.addTerminalLine(result2.ok ? "success" : "error", result2.message);
|
|
5717
6101
|
}
|
|
5718
6102
|
core.setCurrentCommand("");
|
|
5719
6103
|
setTimeout(() => core.focusInput(), 50);
|
|
@@ -5760,14 +6144,17 @@ function ChatTerminal({
|
|
|
5760
6144
|
className,
|
|
5761
6145
|
style,
|
|
5762
6146
|
showHeader,
|
|
6147
|
+
agentLabel: core.agentLabel,
|
|
5763
6148
|
focusInput: core.focusInput,
|
|
5764
6149
|
setTerminalHistory: core.setTerminalHistory,
|
|
5765
6150
|
terminalBodyRef: core.terminalBodyRef,
|
|
5766
6151
|
workingGroupContext: core.workingGroupContext,
|
|
6152
|
+
showWorkingGroupBanner,
|
|
5767
6153
|
progressState: core.progressState,
|
|
5768
6154
|
streamTransparency: core.streamTransparency,
|
|
5769
6155
|
streamNowMs: core.streamNowMs,
|
|
5770
6156
|
isExecuting: core.isExecuting,
|
|
6157
|
+
showBusyIndicator,
|
|
5771
6158
|
handleCancelReasoning: core.handleCancelReasoning,
|
|
5772
6159
|
onViewKnowledgeGraph,
|
|
5773
6160
|
onLiveKGUpdate,
|
|
@@ -5804,6 +6191,7 @@ function ChatTerminal({
|
|
|
5804
6191
|
inputBar: /* @__PURE__ */ jsxRuntime.jsx(
|
|
5805
6192
|
TerminalInputBar,
|
|
5806
6193
|
{
|
|
6194
|
+
autoFocus: autoFocusInput,
|
|
5807
6195
|
inputRef: core.inputRef,
|
|
5808
6196
|
fileInputRef: core.fileInputRef,
|
|
5809
6197
|
currentCommand: core.currentCommand,
|
|
@@ -5856,6 +6244,7 @@ function ChatTerminal({
|
|
|
5856
6244
|
config,
|
|
5857
6245
|
onPageNavigation,
|
|
5858
6246
|
onSourcesActivate,
|
|
6247
|
+
onSourceActivate,
|
|
5859
6248
|
renderEntryExtra,
|
|
5860
6249
|
renderEntry,
|
|
5861
6250
|
widgets,
|
|
@@ -5877,17 +6266,17 @@ function CoreTerminal(props) {
|
|
|
5877
6266
|
return /* @__PURE__ */ jsxRuntime.jsx(StandardTerminal, { ...props });
|
|
5878
6267
|
}
|
|
5879
6268
|
function TypingAnimation({ text, className = "", shouldStart = false }) {
|
|
5880
|
-
const [displayedText, setDisplayedText] =
|
|
5881
|
-
const [currentIndex, setCurrentIndex] =
|
|
5882
|
-
const [isTyping, setIsTyping] =
|
|
5883
|
-
|
|
6269
|
+
const [displayedText, setDisplayedText] = React15.useState("");
|
|
6270
|
+
const [currentIndex, setCurrentIndex] = React15.useState(0);
|
|
6271
|
+
const [isTyping, setIsTyping] = React15.useState(false);
|
|
6272
|
+
React15.useEffect(() => {
|
|
5884
6273
|
if (shouldStart && !isTyping) {
|
|
5885
6274
|
setIsTyping(true);
|
|
5886
6275
|
setDisplayedText("");
|
|
5887
6276
|
setCurrentIndex(0);
|
|
5888
6277
|
}
|
|
5889
6278
|
}, [shouldStart, isTyping]);
|
|
5890
|
-
|
|
6279
|
+
React15.useEffect(() => {
|
|
5891
6280
|
if (isTyping && currentIndex < text.length) {
|
|
5892
6281
|
const timeout = setTimeout(() => {
|
|
5893
6282
|
setDisplayedText((prev) => prev + text[currentIndex]);
|
|
@@ -5908,19 +6297,19 @@ function ExpandableTerminal({
|
|
|
5908
6297
|
...terminalProps
|
|
5909
6298
|
}) {
|
|
5910
6299
|
const t = mergeTheme(themeOverrides);
|
|
5911
|
-
const [isExpanded, setIsExpanded] =
|
|
5912
|
-
const [isFullscreen, setIsFullscreen] =
|
|
5913
|
-
const initialHistoryRef =
|
|
5914
|
-
|
|
6300
|
+
const [isExpanded, setIsExpanded] = React15.useState(false);
|
|
6301
|
+
const [isFullscreen, setIsFullscreen] = React15.useState(false);
|
|
6302
|
+
const initialHistoryRef = React15.useRef(initialHistory);
|
|
6303
|
+
React15.useEffect(() => {
|
|
5915
6304
|
initialHistoryRef.current = initialHistory;
|
|
5916
6305
|
}, [initialHistory]);
|
|
5917
|
-
const [currentGuidance, setCurrentGuidance] =
|
|
5918
|
-
const [isLoadingGuidance, setIsLoadingGuidance] =
|
|
5919
|
-
const [hasTriggeredTyping, setHasTriggeredTyping] =
|
|
5920
|
-
const [internalWindowWidth, setInternalWindowWidth] =
|
|
5921
|
-
const terminalRef =
|
|
5922
|
-
const justOpenedRef =
|
|
5923
|
-
|
|
6306
|
+
const [currentGuidance, setCurrentGuidance] = React15.useState(guidanceMessage || "");
|
|
6307
|
+
const [isLoadingGuidance, setIsLoadingGuidance] = React15.useState(false);
|
|
6308
|
+
const [hasTriggeredTyping, setHasTriggeredTyping] = React15.useState(false);
|
|
6309
|
+
const [internalWindowWidth, setInternalWindowWidth] = React15.useState(windowWidth);
|
|
6310
|
+
const terminalRef = React15.useRef(null);
|
|
6311
|
+
const justOpenedRef = React15.useRef(false);
|
|
6312
|
+
React15.useEffect(() => {
|
|
5924
6313
|
if (typeof window !== "undefined") {
|
|
5925
6314
|
const updateWindowWidth = () => setInternalWindowWidth(window.innerWidth);
|
|
5926
6315
|
updateWindowWidth();
|
|
@@ -5928,7 +6317,7 @@ function ExpandableTerminal({
|
|
|
5928
6317
|
return () => window.removeEventListener("resize", updateWindowWidth);
|
|
5929
6318
|
}
|
|
5930
6319
|
}, []);
|
|
5931
|
-
|
|
6320
|
+
React15.useEffect(() => {
|
|
5932
6321
|
const handleClickOutside = (event) => {
|
|
5933
6322
|
if (justOpenedRef.current) return;
|
|
5934
6323
|
if ((isExpanded || isFullscreen) && terminalRef.current && !terminalRef.current.contains(event.target)) {
|
|
@@ -5947,13 +6336,13 @@ function ExpandableTerminal({
|
|
|
5947
6336
|
};
|
|
5948
6337
|
}
|
|
5949
6338
|
}, [isExpanded, isFullscreen]);
|
|
5950
|
-
|
|
6339
|
+
React15.useEffect(() => {
|
|
5951
6340
|
if (onGuidanceRequest && !currentGuidance && !isLoadingGuidance) {
|
|
5952
6341
|
setIsLoadingGuidance(true);
|
|
5953
6342
|
onGuidanceRequest().then((message) => setCurrentGuidance(message)).catch(() => setCurrentGuidance("\u{1F4AC} Intelligence Online - Ask anything!")).finally(() => setIsLoadingGuidance(false));
|
|
5954
6343
|
}
|
|
5955
6344
|
}, [onGuidanceRequest, currentGuidance, isLoadingGuidance]);
|
|
5956
|
-
|
|
6345
|
+
React15.useEffect(() => {
|
|
5957
6346
|
const timer = setTimeout(() => setHasTriggeredTyping(true), 1e3);
|
|
5958
6347
|
return () => clearTimeout(timer);
|
|
5959
6348
|
}, []);
|
|
@@ -6139,12 +6528,12 @@ function InlineTerminal({
|
|
|
6139
6528
|
autoFocus = false
|
|
6140
6529
|
}) {
|
|
6141
6530
|
const t = useTheme();
|
|
6142
|
-
const [command, setCommand] =
|
|
6143
|
-
const [isProcessing, setIsProcessing] =
|
|
6144
|
-
const [response, setResponse] =
|
|
6145
|
-
const [showResponse, setShowResponse] =
|
|
6146
|
-
const inputRef =
|
|
6147
|
-
|
|
6531
|
+
const [command, setCommand] = React15.useState("");
|
|
6532
|
+
const [isProcessing, setIsProcessing] = React15.useState(false);
|
|
6533
|
+
const [response, setResponse] = React15.useState("");
|
|
6534
|
+
const [showResponse, setShowResponse] = React15.useState(false);
|
|
6535
|
+
const inputRef = React15.useRef(null);
|
|
6536
|
+
React15.useEffect(() => {
|
|
6148
6537
|
if (autoFocus && inputRef.current) inputRef.current.focus();
|
|
6149
6538
|
}, [autoFocus]);
|
|
6150
6539
|
const handleSubmit = async (e) => {
|
|
@@ -6298,18 +6687,18 @@ function buildNarrativeSummary(snapshot, columnConfig) {
|
|
|
6298
6687
|
}
|
|
6299
6688
|
function KnowledgeGraphPanel({ snapshot, genericKG, onClose }) {
|
|
6300
6689
|
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 =
|
|
6690
|
+
const [selected, setSelected] = React15.useState(null);
|
|
6691
|
+
const [fullscreen, setFullscreen] = React15.useState(false);
|
|
6692
|
+
const [searchTerm, setSearchTerm] = React15.useState("");
|
|
6693
|
+
const COLUMN_CONFIG = React15.useMemo(() => getColumnConfig(t), [t]);
|
|
6694
|
+
const SEVERITY_COLORS = React15.useMemo(() => getSeverityColors(t), [t]);
|
|
6695
|
+
const FALLBACK_COLORS = React15.useMemo(() => getFallbackColors(t), [t]);
|
|
6696
|
+
const genericNodeMap = React15.useMemo(() => {
|
|
6308
6697
|
if (!genericKG) return /* @__PURE__ */ new Map();
|
|
6309
6698
|
return new Map(genericKG.nodes.map((n) => [n.id, n]));
|
|
6310
6699
|
}, [genericKG]);
|
|
6311
|
-
const narrativeSummary =
|
|
6312
|
-
|
|
6700
|
+
const narrativeSummary = React15.useMemo(() => buildNarrativeSummary(snapshot, COLUMN_CONFIG), [snapshot, COLUMN_CONFIG]);
|
|
6701
|
+
React15.useEffect(() => {
|
|
6313
6702
|
if (!fullscreen) return;
|
|
6314
6703
|
const handleEsc = (e) => {
|
|
6315
6704
|
if (e.key === "Escape") setFullscreen(false);
|
|
@@ -6317,11 +6706,11 @@ function KnowledgeGraphPanel({ snapshot, genericKG, onClose }) {
|
|
|
6317
6706
|
window.addEventListener("keydown", handleEsc);
|
|
6318
6707
|
return () => window.removeEventListener("keydown", handleEsc);
|
|
6319
6708
|
}, [fullscreen]);
|
|
6320
|
-
const isStructured =
|
|
6709
|
+
const isStructured = React15.useMemo(() => {
|
|
6321
6710
|
const types = new Set(snapshot.nodes.map((n) => n.node_type));
|
|
6322
6711
|
return types.has("document_element") || types.has("finding") || types.has("recommendation");
|
|
6323
6712
|
}, [snapshot]);
|
|
6324
|
-
const { columns, otherNodes } =
|
|
6713
|
+
const { columns, otherNodes } = React15.useMemo(() => {
|
|
6325
6714
|
const cols = {
|
|
6326
6715
|
document_element: [],
|
|
6327
6716
|
finding: [],
|
|
@@ -6343,7 +6732,7 @@ function KnowledgeGraphPanel({ snapshot, genericKG, onClose }) {
|
|
|
6343
6732
|
});
|
|
6344
6733
|
return { columns: cols, otherNodes: other };
|
|
6345
6734
|
}, [snapshot, searchTerm]);
|
|
6346
|
-
const edgeMap =
|
|
6735
|
+
const edgeMap = React15.useMemo(() => {
|
|
6347
6736
|
const map = {};
|
|
6348
6737
|
snapshot.edges.forEach((e) => {
|
|
6349
6738
|
if (!map[e.from]) map[e.from] = [];
|
|
@@ -6709,7 +7098,7 @@ function HistoryAgentCard({
|
|
|
6709
7098
|
thinking
|
|
6710
7099
|
}) {
|
|
6711
7100
|
const t = useTheme();
|
|
6712
|
-
const [agentExpanded, setAgentExpanded] =
|
|
7101
|
+
const [agentExpanded, setAgentExpanded] = React15.useState(false);
|
|
6713
7102
|
const name = agent.display_name || agent.id.replace(/_/g, " ");
|
|
6714
7103
|
const statusColor = agent.status === "complete" ? t.success : agent.status === "failed" ? t.error : t.warning;
|
|
6715
7104
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -6772,8 +7161,8 @@ function ReasoningHistoryCard({
|
|
|
6772
7161
|
defaultExpanded = false
|
|
6773
7162
|
}) {
|
|
6774
7163
|
const t = useTheme();
|
|
6775
|
-
const [expanded, setExpanded] =
|
|
6776
|
-
const [showKG, setShowKG] =
|
|
7164
|
+
const [expanded, setExpanded] = React15.useState(defaultExpanded);
|
|
7165
|
+
const [showKG, setShowKG] = React15.useState(false);
|
|
6777
7166
|
const agentCount = snapshot.agents?.length || 0;
|
|
6778
7167
|
const completedCount = snapshot.agents?.filter((a) => a.status === "complete").length || 0;
|
|
6779
7168
|
const elapsedSec = snapshot.elapsedMs ? Math.round(snapshot.elapsedMs / 1e3) : null;
|
|
@@ -7012,6 +7401,227 @@ function ReasoningHistoryCard({
|
|
|
7012
7401
|
}
|
|
7013
7402
|
);
|
|
7014
7403
|
}
|
|
7404
|
+
function subject(step) {
|
|
7405
|
+
const idx = step.detail.indexOf(": ");
|
|
7406
|
+
const s = idx > -1 ? step.detail.slice(idx + 2).trim() : "";
|
|
7407
|
+
return s.length ? s : null;
|
|
7408
|
+
}
|
|
7409
|
+
function bare(tool) {
|
|
7410
|
+
return tool.replace(/^yf_kg_/, "").replace(/^yf_/, "");
|
|
7411
|
+
}
|
|
7412
|
+
function action(step) {
|
|
7413
|
+
const subj = subject(step);
|
|
7414
|
+
const quoted = subj ? `\u201C${subj}\u201D` : null;
|
|
7415
|
+
switch (bare(step.tool)) {
|
|
7416
|
+
case "graphs":
|
|
7417
|
+
return "Listed knowledge collections";
|
|
7418
|
+
case "search":
|
|
7419
|
+
return quoted ? `Searched for ${quoted}` : "Searched the documents";
|
|
7420
|
+
case "count":
|
|
7421
|
+
return quoted ? `Counted mentions of ${quoted}` : "Counted mentions";
|
|
7422
|
+
case "enumerate":
|
|
7423
|
+
return quoted ? `Listed every match for ${quoted}` : "Listed every match";
|
|
7424
|
+
case "fetch":
|
|
7425
|
+
return "Read a document";
|
|
7426
|
+
case "entities":
|
|
7427
|
+
return "Listed the people and things found";
|
|
7428
|
+
case "explore":
|
|
7429
|
+
return quoted ? `Followed connections from ${quoted}` : "Followed connections";
|
|
7430
|
+
case "sets":
|
|
7431
|
+
return "Listed frozen document sets";
|
|
7432
|
+
case "get_set":
|
|
7433
|
+
return "Read a frozen document set";
|
|
7434
|
+
case "count_in_set":
|
|
7435
|
+
return quoted ? `Counted ${quoted} inside a set` : "Counted inside a set";
|
|
7436
|
+
case "think":
|
|
7437
|
+
return "Thought it through";
|
|
7438
|
+
default:
|
|
7439
|
+
return subj ? `${bare(step.tool).replace(/_/g, " ")} ${subj}` : bare(step.tool).replace(/_/g, " ");
|
|
7440
|
+
}
|
|
7441
|
+
}
|
|
7442
|
+
function took(step) {
|
|
7443
|
+
if (step.status === "running") return null;
|
|
7444
|
+
const ms = Number(step.ms);
|
|
7445
|
+
if (!Number.isFinite(ms) || ms < 1e3) return null;
|
|
7446
|
+
return ms < 1e4 ? `${(ms / 1e3).toFixed(1)}s` : `${Math.round(ms / 1e3)}s`;
|
|
7447
|
+
}
|
|
7448
|
+
function groupTook(g) {
|
|
7449
|
+
const slowest = g.steps.reduce(
|
|
7450
|
+
(worst, s) => Number(s.ms) > Number(worst.ms) ? s : worst,
|
|
7451
|
+
g.steps[0]
|
|
7452
|
+
);
|
|
7453
|
+
return took(slowest);
|
|
7454
|
+
}
|
|
7455
|
+
function result(step) {
|
|
7456
|
+
if (step.status === "running") return null;
|
|
7457
|
+
if (step.status === "error") return "unavailable";
|
|
7458
|
+
const n = Number(step.outcome);
|
|
7459
|
+
if (!Number.isFinite(n)) return null;
|
|
7460
|
+
const [one, many] = {
|
|
7461
|
+
graphs: ["collection", "collections"],
|
|
7462
|
+
search: ["result", "results"],
|
|
7463
|
+
count: ["document", "documents"],
|
|
7464
|
+
enumerate: ["match", "matches"],
|
|
7465
|
+
entities: ["entity", "entities"],
|
|
7466
|
+
explore: ["connection", "connections"],
|
|
7467
|
+
sets: ["set", "sets"]
|
|
7468
|
+
}[bare(step.tool)] ?? ["result", "results"];
|
|
7469
|
+
if (n === 0) return "nothing found";
|
|
7470
|
+
return `${n} ${n === 1 ? one : many}`;
|
|
7471
|
+
}
|
|
7472
|
+
function group(steps) {
|
|
7473
|
+
const out = [];
|
|
7474
|
+
const byKey = /* @__PURE__ */ new Map();
|
|
7475
|
+
for (const step of steps) {
|
|
7476
|
+
const label = action(step);
|
|
7477
|
+
const key = `${step.round ?? ""}\0${label}`;
|
|
7478
|
+
const existing = byKey.get(key);
|
|
7479
|
+
if (existing) {
|
|
7480
|
+
existing.steps.push(step);
|
|
7481
|
+
continue;
|
|
7482
|
+
}
|
|
7483
|
+
const g = { key: step.seq, label, round: step.round, steps: [step] };
|
|
7484
|
+
byKey.set(key, g);
|
|
7485
|
+
out.push(g);
|
|
7486
|
+
}
|
|
7487
|
+
return out;
|
|
7488
|
+
}
|
|
7489
|
+
function groupResult(g) {
|
|
7490
|
+
if (g.steps.length === 1) return result(g.steps[0]);
|
|
7491
|
+
const done = g.steps.filter((s) => s.status !== "running");
|
|
7492
|
+
if (!done.length) return null;
|
|
7493
|
+
const hits = done.filter((s) => Number(s.outcome) > 0).length;
|
|
7494
|
+
if (hits === 0) return "nothing found";
|
|
7495
|
+
return `found in ${hits} of ${done.length}`;
|
|
7496
|
+
}
|
|
7497
|
+
function roundCount(steps) {
|
|
7498
|
+
const seen = /* @__PURE__ */ new Set();
|
|
7499
|
+
for (const s of steps) if (typeof s.round === "number") seen.add(s.round);
|
|
7500
|
+
return seen.size ? seen.size : null;
|
|
7501
|
+
}
|
|
7502
|
+
function AgentStepTrace({ steps, working }) {
|
|
7503
|
+
const t = useTheme();
|
|
7504
|
+
const failed = steps.some((s) => s.status === "error");
|
|
7505
|
+
const prominent = working || failed;
|
|
7506
|
+
const [open, setOpen] = React15.useState(prominent);
|
|
7507
|
+
const [touched, setTouched] = React15.useState(false);
|
|
7508
|
+
const [hover, setHover] = React15.useState(false);
|
|
7509
|
+
React15.useEffect(() => {
|
|
7510
|
+
if (!touched) setOpen(prominent);
|
|
7511
|
+
}, [prominent, touched]);
|
|
7512
|
+
if (!steps.length) return null;
|
|
7513
|
+
const groups = group(steps);
|
|
7514
|
+
const rounds = roundCount(steps);
|
|
7515
|
+
const n = rounds ?? groups.length;
|
|
7516
|
+
const count = `${n} ${rounds ? "round" : "step"}${n === 1 ? "" : "s"}`;
|
|
7517
|
+
const only = groups.length === 1 ? groups[0] : null;
|
|
7518
|
+
const summary = working ? `${action(steps[steps.length - 1])}\u2026` : failed ? `${count}, some unavailable` : only ? [
|
|
7519
|
+
only.label + (only.steps.length > 1 ? ` \xD7${only.steps.length}` : ""),
|
|
7520
|
+
groupResult(only)
|
|
7521
|
+
].filter(Boolean).join(" \u2014 ") : count;
|
|
7522
|
+
const toggle = /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7523
|
+
"button",
|
|
7524
|
+
{
|
|
7525
|
+
type: "button",
|
|
7526
|
+
onClick: () => {
|
|
7527
|
+
setTouched(true);
|
|
7528
|
+
setOpen((o) => !o);
|
|
7529
|
+
},
|
|
7530
|
+
onMouseEnter: () => setHover(true),
|
|
7531
|
+
onMouseLeave: () => setHover(false),
|
|
7532
|
+
"aria-expanded": open,
|
|
7533
|
+
className: "flex w-full items-center gap-2 text-left text-xs",
|
|
7534
|
+
style: { color: failed ? t.error : hover ? t.text : t.textMuted },
|
|
7535
|
+
children: [
|
|
7536
|
+
working && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7537
|
+
"span",
|
|
7538
|
+
{
|
|
7539
|
+
"aria-hidden": true,
|
|
7540
|
+
className: "inline-block h-1.5 w-1.5 shrink-0 rounded-full motion-safe:animate-pulse",
|
|
7541
|
+
style: { backgroundColor: t.primary }
|
|
7542
|
+
}
|
|
7543
|
+
),
|
|
7544
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "min-w-0 flex-1 truncate", children: summary }),
|
|
7545
|
+
!(only && !working && !failed) && /* @__PURE__ */ jsxRuntime.jsx("span", { "aria-hidden": true, className: "shrink-0", children: open ? "\u2212" : "+" })
|
|
7546
|
+
]
|
|
7547
|
+
}
|
|
7548
|
+
);
|
|
7549
|
+
const rows = /* @__PURE__ */ jsxRuntime.jsx("ol", { className: "mt-2 space-y-1", children: groups.map((g, i) => {
|
|
7550
|
+
const res = groupResult(g);
|
|
7551
|
+
const slow = groupTook(g);
|
|
7552
|
+
const anyError = g.steps.some((s) => s.status === "error");
|
|
7553
|
+
const running = g.steps.some((s) => s.status === "running");
|
|
7554
|
+
const startsRound = g.round !== void 0 && g.round !== groups[i - 1]?.round;
|
|
7555
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("li", { className: "flex items-baseline gap-2 text-xs", children: [
|
|
7556
|
+
rounds !== null && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7557
|
+
"span",
|
|
7558
|
+
{
|
|
7559
|
+
className: "w-3 shrink-0 text-right tabular-nums",
|
|
7560
|
+
style: { color: t.textMuted },
|
|
7561
|
+
"aria-hidden": !startsRound,
|
|
7562
|
+
children: startsRound ? g.round : ""
|
|
7563
|
+
}
|
|
7564
|
+
),
|
|
7565
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
7566
|
+
"span",
|
|
7567
|
+
{
|
|
7568
|
+
"aria-hidden": true,
|
|
7569
|
+
className: "w-3 shrink-0 text-[10px]",
|
|
7570
|
+
style: { color: anyError ? t.error : t.textMuted },
|
|
7571
|
+
children: running ? "\xB7" : anyError ? "!" : "\u2713"
|
|
7572
|
+
}
|
|
7573
|
+
),
|
|
7574
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
7575
|
+
"span",
|
|
7576
|
+
{
|
|
7577
|
+
className: "min-w-0 flex-1 truncate",
|
|
7578
|
+
style: { color: t.textSecondary },
|
|
7579
|
+
title: g.label,
|
|
7580
|
+
children: [
|
|
7581
|
+
g.label,
|
|
7582
|
+
g.steps.length > 1 && /* @__PURE__ */ jsxRuntime.jsxs("span", { style: { color: t.textMuted }, children: [
|
|
7583
|
+
" \xD7",
|
|
7584
|
+
g.steps.length
|
|
7585
|
+
] })
|
|
7586
|
+
]
|
|
7587
|
+
}
|
|
7588
|
+
),
|
|
7589
|
+
slow && /* @__PURE__ */ jsxRuntime.jsx(
|
|
7590
|
+
"span",
|
|
7591
|
+
{
|
|
7592
|
+
className: "shrink-0 tabular-nums",
|
|
7593
|
+
style: { color: t.textMuted },
|
|
7594
|
+
children: slow
|
|
7595
|
+
}
|
|
7596
|
+
),
|
|
7597
|
+
res && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "shrink-0", style: { color: anyError ? t.error : t.textMuted }, children: res })
|
|
7598
|
+
] }, g.key);
|
|
7599
|
+
}) });
|
|
7600
|
+
if (!prominent) {
|
|
7601
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-2", children: [
|
|
7602
|
+
toggle,
|
|
7603
|
+
open && !only && rows
|
|
7604
|
+
] });
|
|
7605
|
+
}
|
|
7606
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
7607
|
+
"div",
|
|
7608
|
+
{
|
|
7609
|
+
className: "mt-2 rounded-lg p-3",
|
|
7610
|
+
style: { backgroundColor: t.bgRaisedAlt, border: `1px solid ${t.border}` },
|
|
7611
|
+
children: [
|
|
7612
|
+
toggle,
|
|
7613
|
+
open && rows
|
|
7614
|
+
]
|
|
7615
|
+
}
|
|
7616
|
+
);
|
|
7617
|
+
}
|
|
7618
|
+
function agentStepTraceExtra(entry) {
|
|
7619
|
+
const meta = entry.metadata;
|
|
7620
|
+
const steps = meta?.agentSteps;
|
|
7621
|
+
if (!steps?.length) return null;
|
|
7622
|
+
const working = meta?.agentStepsLive ?? entry.content.endsWith("\u258B");
|
|
7623
|
+
return /* @__PURE__ */ jsxRuntime.jsx(AgentStepTrace, { steps, working });
|
|
7624
|
+
}
|
|
7015
7625
|
|
|
7016
7626
|
// src/knowledge/graphTheme.ts
|
|
7017
7627
|
var NODE_TYPE_COLORS = {
|
|
@@ -7277,7 +7887,7 @@ function GraphNodeComponent({ data, selected }) {
|
|
|
7277
7887
|
` })
|
|
7278
7888
|
] });
|
|
7279
7889
|
}
|
|
7280
|
-
var GraphNode =
|
|
7890
|
+
var GraphNode = React15.memo(GraphNodeComponent);
|
|
7281
7891
|
function GraphEdgeComponent({
|
|
7282
7892
|
id,
|
|
7283
7893
|
sourceX,
|
|
@@ -7346,7 +7956,7 @@ function GraphEdgeComponent({
|
|
|
7346
7956
|
) })
|
|
7347
7957
|
] });
|
|
7348
7958
|
}
|
|
7349
|
-
var GraphEdge =
|
|
7959
|
+
var GraphEdge = React15.memo(GraphEdgeComponent);
|
|
7350
7960
|
function EdgeMarkerDefs() {
|
|
7351
7961
|
const types = [
|
|
7352
7962
|
"supports",
|
|
@@ -7476,18 +8086,18 @@ function AnnotationCard({ annotation: a }) {
|
|
|
7476
8086
|
}
|
|
7477
8087
|
);
|
|
7478
8088
|
}
|
|
7479
|
-
var MarkdownContent =
|
|
8089
|
+
var MarkdownContent = React15.memo(function MarkdownContent2({
|
|
7480
8090
|
children,
|
|
7481
8091
|
className = "",
|
|
7482
8092
|
entities,
|
|
7483
8093
|
onEntityClick
|
|
7484
8094
|
}) {
|
|
7485
8095
|
if (!children) return null;
|
|
7486
|
-
const components =
|
|
8096
|
+
const components = React15.useMemo(() => {
|
|
7487
8097
|
if (!entities || entities.length === 0) return MARKDOWN_COMPONENTS;
|
|
7488
8098
|
return { ...MARKDOWN_COMPONENTS, ...buildHighlightOverrides(entities, onEntityClick) };
|
|
7489
8099
|
}, [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 }) });
|
|
8100
|
+
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
8101
|
});
|
|
7492
8102
|
function escapeRegex(s) {
|
|
7493
8103
|
return s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
@@ -7553,13 +8163,13 @@ function highlightText(text, regex, entityMap, onEntityClick) {
|
|
|
7553
8163
|
return parts;
|
|
7554
8164
|
}
|
|
7555
8165
|
function highlightChildren(children, regex, entityMap, onEntityClick) {
|
|
7556
|
-
return
|
|
8166
|
+
return React15__default.default.Children.map(children, (child) => {
|
|
7557
8167
|
if (typeof child === "string") {
|
|
7558
8168
|
const highlighted = highlightText(child, regex, entityMap, onEntityClick);
|
|
7559
8169
|
return highlighted.length === 1 && typeof highlighted[0] === "string" ? child : /* @__PURE__ */ jsxRuntime.jsx(jsxRuntime.Fragment, { children: highlighted });
|
|
7560
8170
|
}
|
|
7561
|
-
if (
|
|
7562
|
-
return
|
|
8171
|
+
if (React15__default.default.isValidElement(child) && child.props.children) {
|
|
8172
|
+
return React15__default.default.cloneElement(child, {
|
|
7563
8173
|
...child.props,
|
|
7564
8174
|
children: highlightChildren(child.props.children, regex, entityMap, onEntityClick)
|
|
7565
8175
|
});
|
|
@@ -7727,7 +8337,7 @@ var MARKDOWN_COMPONENTS = {
|
|
|
7727
8337
|
}
|
|
7728
8338
|
)
|
|
7729
8339
|
};
|
|
7730
|
-
var MarkdownEditor =
|
|
8340
|
+
var MarkdownEditor = React15.memo(function MarkdownEditor2({
|
|
7731
8341
|
value,
|
|
7732
8342
|
onChange,
|
|
7733
8343
|
onSave,
|
|
@@ -7736,14 +8346,14 @@ var MarkdownEditor = React12.memo(function MarkdownEditor2({
|
|
|
7736
8346
|
autoFocus = true,
|
|
7737
8347
|
disabled = false
|
|
7738
8348
|
}) {
|
|
7739
|
-
const editorRef =
|
|
7740
|
-
|
|
8349
|
+
const editorRef = React15.useRef(null);
|
|
8350
|
+
React15.useEffect(() => {
|
|
7741
8351
|
if (autoFocus && editorRef.current) {
|
|
7742
8352
|
const id = requestAnimationFrame(() => editorRef.current?.focus());
|
|
7743
8353
|
return () => cancelAnimationFrame(id);
|
|
7744
8354
|
}
|
|
7745
8355
|
}, [autoFocus]);
|
|
7746
|
-
const handleKeyDown =
|
|
8356
|
+
const handleKeyDown = React15.useCallback(
|
|
7747
8357
|
(e) => {
|
|
7748
8358
|
if (disabled) return;
|
|
7749
8359
|
if (e.key === "Escape") {
|
|
@@ -7760,7 +8370,7 @@ var MarkdownEditor = React12.memo(function MarkdownEditor2({
|
|
|
7760
8370
|
},
|
|
7761
8371
|
[disabled, onCancel, onSave, onChange]
|
|
7762
8372
|
);
|
|
7763
|
-
const handleChange =
|
|
8373
|
+
const handleChange = React15.useCallback(
|
|
7764
8374
|
(markdown, initialNormalize) => {
|
|
7765
8375
|
if (initialNormalize) return;
|
|
7766
8376
|
onChange(markdown);
|
|
@@ -8014,7 +8624,7 @@ var MarkdownEditor = React12.memo(function MarkdownEditor2({
|
|
|
8014
8624
|
}
|
|
8015
8625
|
);
|
|
8016
8626
|
});
|
|
8017
|
-
var KbdKey =
|
|
8627
|
+
var KbdKey = React15.memo(function KbdKey2({ children }) {
|
|
8018
8628
|
return /* @__PURE__ */ jsxRuntime.jsx(
|
|
8019
8629
|
"kbd",
|
|
8020
8630
|
{
|
|
@@ -8030,10 +8640,10 @@ var SAVE_STAGE_MESSAGES = {
|
|
|
8030
8640
|
extracting: "re-analyzing entities with AI\u2026",
|
|
8031
8641
|
finishing: "almost done \xB7 finalizing graph\u2026"
|
|
8032
8642
|
};
|
|
8033
|
-
function summarizeSaveResult(
|
|
8034
|
-
if (!
|
|
8035
|
-
const added =
|
|
8036
|
-
const removed =
|
|
8643
|
+
function summarizeSaveResult(result2) {
|
|
8644
|
+
if (!result2?.diff) return "Saved";
|
|
8645
|
+
const added = result2.diff.added_node_keys?.length ?? 0;
|
|
8646
|
+
const removed = result2.diff.removed_node_keys?.length ?? 0;
|
|
8037
8647
|
if (added === 0 && removed === 0) return "Saved \xB7 graph unchanged";
|
|
8038
8648
|
const parts = [];
|
|
8039
8649
|
if (added > 0) parts.push(`+${added}`);
|
|
@@ -8044,21 +8654,21 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8044
8654
|
const vocabType = node.properties?.vocabulary_type;
|
|
8045
8655
|
const colors = vocabType ? getVocabTypeColors(vocabType) : getNodeColors(node.nodeType);
|
|
8046
8656
|
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 =
|
|
8657
|
+
const [showProperties, setShowProperties] = React15.useState(false);
|
|
8658
|
+
const [expandedChunks, setExpandedChunks] = React15.useState(/* @__PURE__ */ new Set());
|
|
8659
|
+
const [isEditing, setIsEditing] = React15.useState(false);
|
|
8660
|
+
const [draftText, setDraftText] = React15.useState("");
|
|
8661
|
+
const [localDescription, setLocalDescription] = React15.useState(null);
|
|
8662
|
+
const [isSaving, setIsSaving] = React15.useState(false);
|
|
8663
|
+
const [saveError, setSaveError] = React15.useState(null);
|
|
8664
|
+
const [lastSaveResult, setLastSaveResult] = React15.useState(null);
|
|
8665
|
+
const [saveProgressStage, setSaveProgressStage] = React15.useState("starting");
|
|
8666
|
+
const currentNodeIdRef = React15.useRef(node.id);
|
|
8667
|
+
const savedPillTimerRef = React15.useRef(null);
|
|
8058
8668
|
const displayedDescription = localDescription ?? node.description ?? "";
|
|
8059
8669
|
const isLocallyEdited = localDescription !== null && localDescription !== (node.description ?? "");
|
|
8060
8670
|
const isDirty = isEditing && draftText !== displayedDescription;
|
|
8061
|
-
|
|
8671
|
+
React15.useEffect(() => {
|
|
8062
8672
|
currentNodeIdRef.current = node.id;
|
|
8063
8673
|
setIsEditing(false);
|
|
8064
8674
|
setLocalDescription(null);
|
|
@@ -8071,7 +8681,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8071
8681
|
savedPillTimerRef.current = null;
|
|
8072
8682
|
}
|
|
8073
8683
|
}, [node.id]);
|
|
8074
|
-
|
|
8684
|
+
React15.useEffect(() => {
|
|
8075
8685
|
if (!isSaving) return;
|
|
8076
8686
|
if (saveMode !== "reextract") {
|
|
8077
8687
|
setSaveProgressStage("embedding");
|
|
@@ -8087,7 +8697,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8087
8697
|
clearTimeout(t3);
|
|
8088
8698
|
};
|
|
8089
8699
|
}, [isSaving, saveMode]);
|
|
8090
|
-
|
|
8700
|
+
React15.useEffect(() => () => {
|
|
8091
8701
|
if (savedPillTimerRef.current) clearTimeout(savedPillTimerRef.current);
|
|
8092
8702
|
}, []);
|
|
8093
8703
|
const handleStartEdit = () => {
|
|
@@ -8112,11 +8722,11 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8112
8722
|
setIsSaving(true);
|
|
8113
8723
|
try {
|
|
8114
8724
|
const rawResult = await onSaveDescription(draftAtSaveTime);
|
|
8115
|
-
const
|
|
8725
|
+
const result2 = rawResult ?? null;
|
|
8116
8726
|
if (currentNodeIdRef.current === savingForNodeId) {
|
|
8117
8727
|
setLocalDescription(draftAtSaveTime);
|
|
8118
8728
|
setIsEditing(false);
|
|
8119
|
-
setLastSaveResult(
|
|
8729
|
+
setLastSaveResult(result2);
|
|
8120
8730
|
if (savedPillTimerRef.current) clearTimeout(savedPillTimerRef.current);
|
|
8121
8731
|
savedPillTimerRef.current = setTimeout(() => {
|
|
8122
8732
|
setLastSaveResult(null);
|
|
@@ -8148,7 +8758,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8148
8758
|
onClose();
|
|
8149
8759
|
};
|
|
8150
8760
|
const PLATFORM_SLOT_RE = /<[^>]*(chunk|timestamp|source|when|date|where|location)[^>]*>/i;
|
|
8151
|
-
const renderedClaims =
|
|
8761
|
+
const renderedClaims = React15.useMemo(() => {
|
|
8152
8762
|
const seen = /* @__PURE__ */ new Set();
|
|
8153
8763
|
const out = [];
|
|
8154
8764
|
for (const cn of connectedNodes) {
|
|
@@ -8223,7 +8833,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8223
8833
|
}
|
|
8224
8834
|
return out;
|
|
8225
8835
|
}, [connectedNodes, node.label]);
|
|
8226
|
-
const claimGroups =
|
|
8836
|
+
const claimGroups = React15.useMemo(() => {
|
|
8227
8837
|
const byPredicate = /* @__PURE__ */ new Map();
|
|
8228
8838
|
for (const c of renderedClaims) {
|
|
8229
8839
|
const key = c.predicateClean || "(related)";
|
|
@@ -8238,11 +8848,11 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8238
8848
|
}).map(([predicate, items]) => ({ predicate, items }));
|
|
8239
8849
|
}, [renderedClaims]);
|
|
8240
8850
|
const sourceDocs = node.properties?.source_documents ?? [];
|
|
8241
|
-
const aliases =
|
|
8851
|
+
const aliases = React15.useMemo(() => {
|
|
8242
8852
|
const a = node.aliases ?? [];
|
|
8243
8853
|
return a.filter((v) => v && v.toLowerCase() !== node.label.toLowerCase());
|
|
8244
8854
|
}, [node.aliases, node.label]);
|
|
8245
|
-
const speakerMeta =
|
|
8855
|
+
const speakerMeta = React15.useMemo(() => {
|
|
8246
8856
|
const raw = node.source?.trim();
|
|
8247
8857
|
if (!raw) return null;
|
|
8248
8858
|
if (raw === "system_extractor") return { label: "System extractor", klass: "extractor" };
|
|
@@ -8253,7 +8863,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8253
8863
|
return { label: raw.replace(/_/g, " "), klass: "other" };
|
|
8254
8864
|
}, [node.source]);
|
|
8255
8865
|
const graphLayer = node.graphLayer || node.properties?.graph_layer;
|
|
8256
|
-
const HIDDEN_PROPERTY_KEYS =
|
|
8866
|
+
const HIDDEN_PROPERTY_KEYS = React15.useMemo(() => /* @__PURE__ */ new Set([
|
|
8257
8867
|
"vocabulary_type",
|
|
8258
8868
|
"claim_status",
|
|
8259
8869
|
"settled",
|
|
@@ -8269,7 +8879,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8269
8879
|
"sample_labels",
|
|
8270
8880
|
"view"
|
|
8271
8881
|
]), []);
|
|
8272
|
-
const visibleProperties =
|
|
8882
|
+
const visibleProperties = React15.useMemo(() => {
|
|
8273
8883
|
const src = node.properties ?? {};
|
|
8274
8884
|
const out = {};
|
|
8275
8885
|
for (const [k, v] of Object.entries(src)) {
|
|
@@ -8278,23 +8888,23 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8278
8888
|
}
|
|
8279
8889
|
return out;
|
|
8280
8890
|
}, [node.properties, HIDDEN_PROPERTY_KEYS]);
|
|
8281
|
-
const reviewIndex =
|
|
8891
|
+
const reviewIndex = React15.useMemo(() => {
|
|
8282
8892
|
if (!reviewNodeIds || reviewNodeIds.length === 0) return -1;
|
|
8283
8893
|
return reviewNodeIds.indexOf(node.id);
|
|
8284
8894
|
}, [reviewNodeIds, node.id]);
|
|
8285
8895
|
const hasPrev = reviewIndex > 0;
|
|
8286
8896
|
const hasNext = reviewNodeIds ? reviewIndex < reviewNodeIds.length - 1 : false;
|
|
8287
8897
|
const isChunk = node.nodeType === "chunk";
|
|
8288
|
-
const noteTitle =
|
|
8898
|
+
const noteTitle = React15.useMemo(() => {
|
|
8289
8899
|
if (!isChunk || !displayedDescription) return null;
|
|
8290
8900
|
const match = displayedDescription.match(/^#{1,4}\s+(.+)/m);
|
|
8291
8901
|
return match ? match[1].trim() : null;
|
|
8292
8902
|
}, [isChunk, displayedDescription]);
|
|
8293
|
-
const chunkEntities =
|
|
8903
|
+
const chunkEntities = React15.useMemo(() => {
|
|
8294
8904
|
if (!isChunk) return [];
|
|
8295
8905
|
return connectedNodes.map((cn) => ({ id: cn.id, label: cn.label, nodeType: cn.nodeType }));
|
|
8296
8906
|
}, [isChunk, connectedNodes]);
|
|
8297
|
-
const [showMeta, setShowMeta] =
|
|
8907
|
+
const [showMeta, setShowMeta] = React15.useState(false);
|
|
8298
8908
|
const entityCount = node.properties?.entity_count;
|
|
8299
8909
|
const relationshipCount = node.properties?.relationship_count;
|
|
8300
8910
|
const reviewNav = reviewNodeIds && reviewNodeIds.length > 1 && reviewIndex >= 0 && onReviewNavigate ? /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -8652,11 +9262,11 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8652
9262
|
renderedClaims.length,
|
|
8653
9263
|
")"
|
|
8654
9264
|
] }),
|
|
8655
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: claimGroups.map((
|
|
8656
|
-
const isRelated =
|
|
9265
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-2", children: claimGroups.map((group2) => {
|
|
9266
|
+
const isRelated = group2.predicate === "(related)";
|
|
8657
9267
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
8658
|
-
|
|
8659
|
-
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0.5", children:
|
|
9268
|
+
group2.items.length > 1 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-[10px] text-gray-500 italic mb-0.5 px-2", children: group2.predicate }),
|
|
9269
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-0.5", children: group2.items.map((claim) => {
|
|
8660
9270
|
const cnColors = getNodeColors(claim.targetType);
|
|
8661
9271
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
8662
9272
|
"button",
|
|
@@ -8694,7 +9304,7 @@ function NodeDetailDrawer({ node, connectedNodes, chunks = [], annotations, onCl
|
|
|
8694
9304
|
claim.key
|
|
8695
9305
|
);
|
|
8696
9306
|
}) })
|
|
8697
|
-
] },
|
|
9307
|
+
] }, group2.predicate);
|
|
8698
9308
|
}) })
|
|
8699
9309
|
] }),
|
|
8700
9310
|
Object.keys(visibleProperties).length > 0 && /* @__PURE__ */ jsxRuntime.jsxs("div", { children: [
|
|
@@ -8839,8 +9449,8 @@ function EdgeDetailDrawer({ edge, annotations, onClose, onNavigate }) {
|
|
|
8839
9449
|
] });
|
|
8840
9450
|
}
|
|
8841
9451
|
function EditableField({ label, value, placeholder, onSave, color }) {
|
|
8842
|
-
const [editing, setEditing] =
|
|
8843
|
-
const [editVal, setEditVal] =
|
|
9452
|
+
const [editing, setEditing] = React15.useState(false);
|
|
9453
|
+
const [editVal, setEditVal] = React15.useState(value);
|
|
8844
9454
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { marginBottom: 20 }, children: [
|
|
8845
9455
|
/* @__PURE__ */ jsxRuntime.jsx("div", { style: { color: "#888", fontSize: 10, textTransform: "uppercase", letterSpacing: 1, marginBottom: 6 }, children: label }),
|
|
8846
9456
|
editing ? /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -8884,15 +9494,15 @@ function EditableField({ label, value, placeholder, onSave, color }) {
|
|
|
8884
9494
|
] });
|
|
8885
9495
|
}
|
|
8886
9496
|
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] =
|
|
9497
|
+
const [editingId, setEditingId] = React15.useState(null);
|
|
9498
|
+
const [editField, setEditField] = React15.useState(null);
|
|
9499
|
+
const [editValue, setEditValue] = React15.useState("");
|
|
9500
|
+
const [addingAgent, setAddingAgent] = React15.useState(false);
|
|
9501
|
+
const [newName, setNewName] = React15.useState("");
|
|
9502
|
+
const [newRole, setNewRole] = React15.useState("");
|
|
9503
|
+
const [confirmDeleteId, setConfirmDeleteId] = React15.useState(null);
|
|
9504
|
+
const [selectedAgent, setSelectedAgent] = React15.useState(null);
|
|
9505
|
+
const [hoveredId, setHoveredId] = React15.useState(null);
|
|
8896
9506
|
const startEdit = (agent, field) => {
|
|
8897
9507
|
setEditingId(agent.id);
|
|
8898
9508
|
setEditField(field);
|
|
@@ -9308,8 +9918,8 @@ var RECRUITING_LINES = [
|
|
|
9308
9918
|
"Briefing the team on the working group context\u2026"
|
|
9309
9919
|
];
|
|
9310
9920
|
function RecruitingHint() {
|
|
9311
|
-
const [idx, setIdx] =
|
|
9312
|
-
|
|
9921
|
+
const [idx, setIdx] = React15.useState(0);
|
|
9922
|
+
React15__default.default.useEffect(() => {
|
|
9313
9923
|
const t = setInterval(() => setIdx((i) => (i + 1) % RECRUITING_LINES.length), 2500);
|
|
9314
9924
|
return () => clearInterval(t);
|
|
9315
9925
|
}, []);
|
|
@@ -9412,7 +10022,7 @@ function RelationshipSentence({ rel }) {
|
|
|
9412
10022
|
const hasRange = rel.range.length > 0;
|
|
9413
10023
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { style: { lineHeight: 2, color: "#888", fontSize: 13, wordBreak: "break-word" }, children: [
|
|
9414
10024
|
hasDomain && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9415
|
-
rel.domain.map((d, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10025
|
+
rel.domain.map((d, i) => /* @__PURE__ */ jsxRuntime.jsxs(React15__default.default.Fragment, { children: [
|
|
9416
10026
|
i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#666" }, children: " or " }),
|
|
9417
10027
|
/* @__PURE__ */ jsxRuntime.jsx(TypeChip, { name: d })
|
|
9418
10028
|
] }, d)),
|
|
@@ -9421,7 +10031,7 @@ function RelationshipSentence({ rel }) {
|
|
|
9421
10031
|
/* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#ddd", fontStyle: "italic", fontWeight: 500 }, children: verb }),
|
|
9422
10032
|
hasRange && /* @__PURE__ */ jsxRuntime.jsxs(jsxRuntime.Fragment, { children: [
|
|
9423
10033
|
" ",
|
|
9424
|
-
rel.range.map((r, i) => /* @__PURE__ */ jsxRuntime.jsxs(
|
|
10034
|
+
rel.range.map((r, i) => /* @__PURE__ */ jsxRuntime.jsxs(React15__default.default.Fragment, { children: [
|
|
9425
10035
|
i > 0 && /* @__PURE__ */ jsxRuntime.jsx("span", { style: { color: "#666" }, children: " and " }),
|
|
9426
10036
|
/* @__PURE__ */ jsxRuntime.jsx(TypeChip, { name: r })
|
|
9427
10037
|
] }, r))
|
|
@@ -9437,14 +10047,14 @@ function SchemaStage({
|
|
|
9437
10047
|
edgeTypeCount,
|
|
9438
10048
|
onSendAction
|
|
9439
10049
|
}) {
|
|
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] =
|
|
10050
|
+
const [renamingType, setRenamingType] = React15.useState(null);
|
|
10051
|
+
const [renameValue, setRenameValue] = React15.useState("");
|
|
10052
|
+
const [addingType, setAddingType] = React15.useState(false);
|
|
10053
|
+
const [newTypeName, setNewTypeName] = React15.useState("");
|
|
10054
|
+
const [addingRel, setAddingRel] = React15.useState(false);
|
|
10055
|
+
const [newRelName, setNewRelName] = React15.useState("");
|
|
10056
|
+
const [newRelDomain, setNewRelDomain] = React15.useState("");
|
|
10057
|
+
const [newRelRange, setNewRelRange] = React15.useState("");
|
|
9448
10058
|
const removeType = (name) => {
|
|
9449
10059
|
onSendAction(`remove the "${name}" type from the schema`);
|
|
9450
10060
|
};
|
|
@@ -9900,8 +10510,8 @@ var DOCUMENT_PIPELINE_STEPS = [
|
|
|
9900
10510
|
{ key: "complete", label: "Done" }
|
|
9901
10511
|
];
|
|
9902
10512
|
function DocumentProcessingProgress() {
|
|
9903
|
-
const [state, setState] =
|
|
9904
|
-
|
|
10513
|
+
const [state, setState] = React15.useState(null);
|
|
10514
|
+
React15.useEffect(() => {
|
|
9905
10515
|
const handler = (e) => {
|
|
9906
10516
|
const event = e.detail;
|
|
9907
10517
|
if (!event?.step) return;
|
|
@@ -9941,7 +10551,7 @@ function DocumentProcessingProgress() {
|
|
|
9941
10551
|
if (!state) return null;
|
|
9942
10552
|
const currentIdx = DOCUMENT_PIPELINE_STEPS.findIndex((s) => s.key === state.step);
|
|
9943
10553
|
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(
|
|
10554
|
+
/* @__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
10555
|
i > 0 && /* @__PURE__ */ jsxRuntime.jsx("div", { className: "w-2 h-px mx-0.5", style: { backgroundColor: i <= currentIdx ? "#10b981" : "#333" } }),
|
|
9946
10556
|
/* @__PURE__ */ jsxRuntime.jsx(
|
|
9947
10557
|
"span",
|
|
@@ -10139,7 +10749,7 @@ function useStageActionBridge({
|
|
|
10139
10749
|
kgId,
|
|
10140
10750
|
agentsApiUrl
|
|
10141
10751
|
}) {
|
|
10142
|
-
|
|
10752
|
+
React15.useEffect(() => {
|
|
10143
10753
|
const threadMode = !!threadId && !!onPostMessage;
|
|
10144
10754
|
const pipelineMode = !!runId && !!agentsApiUrl;
|
|
10145
10755
|
if (!threadMode && !pipelineMode) return;
|
|
@@ -10225,10 +10835,10 @@ function hydrateAgentIds(ids) {
|
|
|
10225
10835
|
};
|
|
10226
10836
|
});
|
|
10227
10837
|
}
|
|
10228
|
-
function stageReducer(state,
|
|
10229
|
-
switch (
|
|
10838
|
+
function stageReducer(state, action2) {
|
|
10839
|
+
switch (action2.type) {
|
|
10230
10840
|
case "TEAM_SETUP": {
|
|
10231
|
-
const incomingIds = new Set(
|
|
10841
|
+
const incomingIds = new Set(action2.agents.map((a) => a.id));
|
|
10232
10842
|
let isWholesaleReplace = state.lastBackendTeamIds.size > 0;
|
|
10233
10843
|
if (isWholesaleReplace) {
|
|
10234
10844
|
state.lastBackendTeamIds.forEach((id) => {
|
|
@@ -10246,48 +10856,48 @@ function stageReducer(state, action) {
|
|
|
10246
10856
|
return {
|
|
10247
10857
|
...state,
|
|
10248
10858
|
stage: "team_formation",
|
|
10249
|
-
team: [...
|
|
10859
|
+
team: [...action2.agents, ...surviving],
|
|
10250
10860
|
localOnlyAgentIds: nextLocalOnly,
|
|
10251
10861
|
lastBackendTeamIds: incomingIds
|
|
10252
10862
|
};
|
|
10253
10863
|
}
|
|
10254
10864
|
case "PHASE_ADVANCED": {
|
|
10255
|
-
const to =
|
|
10865
|
+
const to = action2.to;
|
|
10256
10866
|
if (to === "team_formation") return { ...state, stage: "team_formation" };
|
|
10257
10867
|
if (to === "schema_seeding") return { ...state, stage: "schema_seeding" };
|
|
10258
10868
|
if (to === "construction" || to === "synthesis" || to === "done") return { ...state, stage: "graph" };
|
|
10259
10869
|
return state;
|
|
10260
10870
|
}
|
|
10261
10871
|
case "UPDATE_AGENT":
|
|
10262
|
-
return { ...state, team: state.team.map((a) => a.id ===
|
|
10872
|
+
return { ...state, team: state.team.map((a) => a.id === action2.id ? { ...a, ...action2.updates } : a) };
|
|
10263
10873
|
case "REMOVE_AGENT": {
|
|
10264
10874
|
const nextLocalOnly = new Set(state.localOnlyAgentIds);
|
|
10265
|
-
nextLocalOnly.delete(
|
|
10875
|
+
nextLocalOnly.delete(action2.id);
|
|
10266
10876
|
return {
|
|
10267
10877
|
...state,
|
|
10268
|
-
team: state.team.filter((a) => a.id !==
|
|
10878
|
+
team: state.team.filter((a) => a.id !== action2.id),
|
|
10269
10879
|
localOnlyAgentIds: nextLocalOnly
|
|
10270
10880
|
};
|
|
10271
10881
|
}
|
|
10272
10882
|
case "ADD_AGENT": {
|
|
10273
10883
|
const nextLocalOnly = new Set(state.localOnlyAgentIds);
|
|
10274
|
-
nextLocalOnly.add(
|
|
10884
|
+
nextLocalOnly.add(action2.agent.id);
|
|
10275
10885
|
return {
|
|
10276
10886
|
...state,
|
|
10277
|
-
team: [...state.team,
|
|
10887
|
+
team: [...state.team, action2.agent],
|
|
10278
10888
|
localOnlyAgentIds: nextLocalOnly
|
|
10279
10889
|
};
|
|
10280
10890
|
}
|
|
10281
10891
|
case "SCHEMA_SEEDED":
|
|
10282
|
-
return { ...state, schemaNodeTypeCount:
|
|
10892
|
+
return { ...state, schemaNodeTypeCount: action2.nodeTypeCount, schemaEdgeTypeCount: action2.edgeTypeCount };
|
|
10283
10893
|
case "SCHEMA_TYPE_ADDED":
|
|
10284
|
-
return { ...state, schemaNodeTypes: state.schemaNodeTypes.includes(
|
|
10894
|
+
return { ...state, schemaNodeTypes: state.schemaNodeTypes.includes(action2.typeName) ? state.schemaNodeTypes : [...state.schemaNodeTypes, action2.typeName] };
|
|
10285
10895
|
case "SCHEMA_TEXT": {
|
|
10286
10896
|
const rels = [];
|
|
10287
10897
|
const nodeTypes2 = new Set(state.schemaNodeTypes);
|
|
10288
10898
|
const relPattern = /(\w+)\s*:\s*\[([^\]]*)\]\s*→\s*\[([^\]]*)\]/g;
|
|
10289
10899
|
let m;
|
|
10290
|
-
while ((m = relPattern.exec(
|
|
10900
|
+
while ((m = relPattern.exec(action2.text)) !== null) {
|
|
10291
10901
|
const name = m[1];
|
|
10292
10902
|
const domain = m[2].split(",").map((s) => s.replace(/"/g, "").trim()).filter(Boolean);
|
|
10293
10903
|
const range = m[3].split(",").map((s) => s.replace(/"/g, "").trim()).filter(Boolean);
|
|
@@ -10302,7 +10912,7 @@ function stageReducer(state, action) {
|
|
|
10302
10912
|
};
|
|
10303
10913
|
}
|
|
10304
10914
|
case "DOC_STEP": {
|
|
10305
|
-
const step =
|
|
10915
|
+
const step = action2.step;
|
|
10306
10916
|
if (step === "complete") return { ...state, stage: "graph" };
|
|
10307
10917
|
if (step === "processing" || step === "vocabulary") return { ...state, stage: "doc_preparing" };
|
|
10308
10918
|
if (step === "extracting") return { ...state, stage: "doc_extracting" };
|
|
@@ -10311,7 +10921,7 @@ function stageReducer(state, action) {
|
|
|
10311
10921
|
return state;
|
|
10312
10922
|
}
|
|
10313
10923
|
case "DOC_ACTIVITY":
|
|
10314
|
-
return { ...state, docActivity: [...state.docActivity,
|
|
10924
|
+
return { ...state, docActivity: [...state.docActivity, action2.item] };
|
|
10315
10925
|
case "FORCE_GRAPH":
|
|
10316
10926
|
return { ...state, stage: "graph" };
|
|
10317
10927
|
default:
|
|
@@ -10332,7 +10942,7 @@ var initialState = {
|
|
|
10332
10942
|
docActivity: []
|
|
10333
10943
|
};
|
|
10334
10944
|
function StageCanvas({ nodeCount, onForceGraph, initialPhase, initialTeam, kgId }) {
|
|
10335
|
-
const [state, dispatch] =
|
|
10945
|
+
const [state, dispatch] = React15.useReducer(stageReducer, initialState, (base) => {
|
|
10336
10946
|
if (!initialPhase) return base;
|
|
10337
10947
|
let stage = "idle";
|
|
10338
10948
|
if (initialPhase === "team_formation") stage = "team_formation";
|
|
@@ -10341,13 +10951,13 @@ function StageCanvas({ nodeCount, onForceGraph, initialPhase, initialTeam, kgId
|
|
|
10341
10951
|
const team = initialTeam && initialTeam.length > 0 ? initialTeam : stage === "team_formation" ? hydrateAgentIds(["proposer", "critic", "synthesizer"]) : base.team;
|
|
10342
10952
|
return { ...base, stage, team };
|
|
10343
10953
|
});
|
|
10344
|
-
|
|
10954
|
+
React15.useEffect(() => {
|
|
10345
10955
|
if (initialPhase) dispatch({ type: "PHASE_ADVANCED", to: initialPhase });
|
|
10346
10956
|
}, [initialPhase]);
|
|
10347
|
-
|
|
10957
|
+
React15.useEffect(() => {
|
|
10348
10958
|
if (initialTeam && initialTeam.length > 0) dispatch({ type: "TEAM_SETUP", agents: initialTeam });
|
|
10349
10959
|
}, [initialTeam]);
|
|
10350
|
-
const handleProgressEvent =
|
|
10960
|
+
const handleProgressEvent = React15.useCallback((event) => {
|
|
10351
10961
|
if (!event?.type) return;
|
|
10352
10962
|
switch (event.type) {
|
|
10353
10963
|
case "TeamSetup":
|
|
@@ -10436,7 +11046,7 @@ function StageCanvas({ nodeCount, onForceGraph, initialPhase, initialTeam, kgId
|
|
|
10436
11046
|
}
|
|
10437
11047
|
}, []);
|
|
10438
11048
|
useScopedProgressEvent(kgId, handleProgressEvent);
|
|
10439
|
-
|
|
11049
|
+
React15.useEffect(() => {
|
|
10440
11050
|
const handler = (e) => {
|
|
10441
11051
|
const event = e.detail;
|
|
10442
11052
|
if (!event?.step) return;
|
|
@@ -10542,8 +11152,8 @@ var STATUS_COLORS = {
|
|
|
10542
11152
|
idle: "#6b7280"
|
|
10543
11153
|
};
|
|
10544
11154
|
function AgentPresenceBar({ listenForEvents = true, agents: agentsProp, kgId }) {
|
|
10545
|
-
const [agents, setAgents] =
|
|
10546
|
-
const handleAgentEvent =
|
|
11155
|
+
const [agents, setAgents] = React15.useState(/* @__PURE__ */ new Map());
|
|
11156
|
+
const handleAgentEvent = React15.useCallback((event) => {
|
|
10547
11157
|
if (!event?.type) return;
|
|
10548
11158
|
switch (event.type) {
|
|
10549
11159
|
case "TeamSetup": {
|
|
@@ -10958,7 +11568,7 @@ function ClaimNodeComponent({ data, selected }) {
|
|
|
10958
11568
|
/* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Bottom, style: { background: borderColor, border: "none", width: 6, height: 6 } })
|
|
10959
11569
|
] });
|
|
10960
11570
|
}
|
|
10961
|
-
var ClaimNode =
|
|
11571
|
+
var ClaimNode = React15.memo(ClaimNodeComponent);
|
|
10962
11572
|
function extractTitle(text) {
|
|
10963
11573
|
const headingMatch = text.match(/^#{1,4}\s+(.+)/m);
|
|
10964
11574
|
if (headingMatch) {
|
|
@@ -11057,7 +11667,7 @@ function NoteCardComponent({ data, selected }) {
|
|
|
11057
11667
|
/* @__PURE__ */ jsxRuntime.jsx(react.Handle, { type: "source", position: react.Position.Bottom, style: { opacity: 0, width: 1, height: 1 } })
|
|
11058
11668
|
] });
|
|
11059
11669
|
}
|
|
11060
|
-
var NoteCard =
|
|
11670
|
+
var NoteCard = React15.memo(NoteCardComponent);
|
|
11061
11671
|
|
|
11062
11672
|
// src/knowledge/claimsProjection.ts
|
|
11063
11673
|
function buildClaimsGraph(nodes, edges) {
|
|
@@ -11128,13 +11738,13 @@ var PIPELINE_STEPS = [
|
|
|
11128
11738
|
{ key: "construction", label: "Building", short: "B" }
|
|
11129
11739
|
];
|
|
11130
11740
|
function PipelineProgressBar({ listenForEvents = true, currentPhase: currentPhaseProp, completedPhases: completedProp, kgId }) {
|
|
11131
|
-
const [currentPhase, setCurrentPhase] =
|
|
11132
|
-
const [completed, setCompleted] =
|
|
11133
|
-
const [backtracking, setBacktracking] =
|
|
11134
|
-
|
|
11741
|
+
const [currentPhase, setCurrentPhase] = React15.useState(currentPhaseProp || "");
|
|
11742
|
+
const [completed, setCompleted] = React15.useState(new Set(completedProp || []));
|
|
11743
|
+
const [backtracking, setBacktracking] = React15.useState(false);
|
|
11744
|
+
React15.useEffect(() => {
|
|
11135
11745
|
if (currentPhaseProp) setCurrentPhase(currentPhaseProp);
|
|
11136
11746
|
}, [currentPhaseProp]);
|
|
11137
|
-
const handlePipelineEvent =
|
|
11747
|
+
const handlePipelineEvent = React15.useCallback((event) => {
|
|
11138
11748
|
if (!event?.type) return;
|
|
11139
11749
|
const isAdvance = event.type === "PhaseAdvanced" || event.type === "transform_extension" && event.kind === "phase_advanced";
|
|
11140
11750
|
const isBacktrack = event.type === "PhaseBacktracked" || event.type === "transform_extension" && event.kind === "phase_backtracked";
|
|
@@ -11177,7 +11787,7 @@ function PipelineProgressBar({ listenForEvents = true, currentPhase: currentPhas
|
|
|
11177
11787
|
PIPELINE_STEPS.map((step, i) => {
|
|
11178
11788
|
const isCompleted = completed.has(step.key) || i < currentIdx;
|
|
11179
11789
|
const isCurrent = step.key === currentPhase;
|
|
11180
|
-
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
11790
|
+
return /* @__PURE__ */ jsxRuntime.jsxs(React15__default.default.Fragment, { children: [
|
|
11181
11791
|
i > 0 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
11182
11792
|
"div",
|
|
11183
11793
|
{
|
|
@@ -11250,9 +11860,9 @@ var EMPTY_STATE = {
|
|
|
11250
11860
|
edgeCount: 0
|
|
11251
11861
|
};
|
|
11252
11862
|
function ConstructionProgress({ kgId } = {}) {
|
|
11253
|
-
const [state, setState] =
|
|
11254
|
-
const [isBuilding, setIsBuilding] =
|
|
11255
|
-
const handleConstructionEvent =
|
|
11863
|
+
const [state, setState] = React15.useState(null);
|
|
11864
|
+
const [isBuilding, setIsBuilding] = React15.useState(false);
|
|
11865
|
+
const handleConstructionEvent = React15.useCallback((event) => {
|
|
11256
11866
|
if (!event?.type) return;
|
|
11257
11867
|
const isAdvance = event.type === "PhaseAdvanced" || event.type === "transform_extension" && event.kind === "phase_advanced";
|
|
11258
11868
|
if (isAdvance && event.to === "construction") {
|
|
@@ -11361,12 +11971,12 @@ function ConstructionProgress({ kgId } = {}) {
|
|
|
11361
11971
|
}
|
|
11362
11972
|
var MAX_ADOPTED_KG_IDS = 16;
|
|
11363
11973
|
function useAdoptedKgIds(kgId) {
|
|
11364
|
-
const adoptedKgIdsRef =
|
|
11365
|
-
const kgIdRef =
|
|
11366
|
-
|
|
11974
|
+
const adoptedKgIdsRef = React15.useRef(/* @__PURE__ */ new Set());
|
|
11975
|
+
const kgIdRef = React15.useRef(kgId);
|
|
11976
|
+
React15.useEffect(() => {
|
|
11367
11977
|
kgIdRef.current = kgId;
|
|
11368
11978
|
}, [kgId]);
|
|
11369
|
-
const adoptKgIdFromChunk =
|
|
11979
|
+
const adoptKgIdFromChunk = React15.useCallback(
|
|
11370
11980
|
(chunk, progress) => {
|
|
11371
11981
|
if (isFixedKgId(kgIdRef.current)) return;
|
|
11372
11982
|
const fromChunk = extractKgId(chunk, progress);
|
|
@@ -11379,7 +11989,7 @@ function useAdoptedKgIds(kgId) {
|
|
|
11379
11989
|
},
|
|
11380
11990
|
[]
|
|
11381
11991
|
);
|
|
11382
|
-
const hasOwnedKgId =
|
|
11992
|
+
const hasOwnedKgId = React15.useCallback((id) => {
|
|
11383
11993
|
if (id === kgIdRef.current) return true;
|
|
11384
11994
|
return adoptedKgIdsRef.current.has(id);
|
|
11385
11995
|
}, []);
|
|
@@ -11394,7 +12004,7 @@ function useReasoningKeepalive({
|
|
|
11394
12004
|
authToken
|
|
11395
12005
|
}) {
|
|
11396
12006
|
const isRealKg = isFixedKgId(kgId);
|
|
11397
|
-
|
|
12007
|
+
React15.useEffect(() => {
|
|
11398
12008
|
if (!isRealKg || !runId || isLiveReasoning || !agentsApiUrl) return;
|
|
11399
12009
|
const abort = new AbortController();
|
|
11400
12010
|
const broadcastProgress = (event) => {
|
|
@@ -11425,12 +12035,12 @@ function useCheckpointCard({
|
|
|
11425
12035
|
isLoadedSession,
|
|
11426
12036
|
initialPhase
|
|
11427
12037
|
}) {
|
|
11428
|
-
const [checkpoint, setCheckpoint] =
|
|
11429
|
-
const currentPhaseRef =
|
|
11430
|
-
|
|
12038
|
+
const [checkpoint, setCheckpoint] = React15.useState(null);
|
|
12039
|
+
const currentPhaseRef = React15.useRef(initialPhase || "");
|
|
12040
|
+
React15.useEffect(() => {
|
|
11431
12041
|
if (initialPhase) currentPhaseRef.current = initialPhase;
|
|
11432
12042
|
}, [initialPhase]);
|
|
11433
|
-
const handler =
|
|
12043
|
+
const handler = React15.useCallback(
|
|
11434
12044
|
(event) => {
|
|
11435
12045
|
if (!event?.type) return;
|
|
11436
12046
|
if (event.type === "PhaseAdvanced" || event.type === "PhaseBacktracked" || event.type === "transform_extension") {
|
|
@@ -11475,7 +12085,7 @@ function useCheckpointCard({
|
|
|
11475
12085
|
handler,
|
|
11476
12086
|
(!!threadId || !!runId) && !isLoadedSession
|
|
11477
12087
|
);
|
|
11478
|
-
const setCheckpointResponded =
|
|
12088
|
+
const setCheckpointResponded = React15.useCallback(() => {
|
|
11479
12089
|
setCheckpoint((prev) => prev ? { ...prev, responded: true } : null);
|
|
11480
12090
|
}, []);
|
|
11481
12091
|
return { checkpoint, setCheckpointResponded };
|
|
@@ -11511,10 +12121,10 @@ function GraphChatPanel({
|
|
|
11511
12121
|
reasoningPhase,
|
|
11512
12122
|
authToken
|
|
11513
12123
|
}) {
|
|
11514
|
-
const accumulatedTextRef =
|
|
11515
|
-
const conversationRef =
|
|
11516
|
-
const historyRef =
|
|
11517
|
-
const [loadedHistory, setLoadedHistory] =
|
|
12124
|
+
const accumulatedTextRef = React15.useRef("");
|
|
12125
|
+
const conversationRef = React15.useRef([]);
|
|
12126
|
+
const historyRef = React15.useRef(null);
|
|
12127
|
+
const [loadedHistory, setLoadedHistory] = React15.useState(null);
|
|
11518
12128
|
const { adoptKgIdFromChunk, hasOwnedKgId } = useAdoptedKgIds(kgId);
|
|
11519
12129
|
useReasoningKeepalive({
|
|
11520
12130
|
kgId,
|
|
@@ -11523,7 +12133,7 @@ function GraphChatPanel({
|
|
|
11523
12133
|
agentsApiUrl: config.agentsApiUrl,
|
|
11524
12134
|
authToken
|
|
11525
12135
|
});
|
|
11526
|
-
const narrativeHandler =
|
|
12136
|
+
const narrativeHandler = React15.useCallback((event) => {
|
|
11527
12137
|
if (event?.type !== "transform_extension" || event?.kind !== "narrative_text") return;
|
|
11528
12138
|
const text = event?.payload?.text;
|
|
11529
12139
|
if (typeof text !== "string" || !text.trim()) return;
|
|
@@ -11559,7 +12169,7 @@ function GraphChatPanel({
|
|
|
11559
12169
|
kgId,
|
|
11560
12170
|
agentsApiUrl: config.agentsApiUrl
|
|
11561
12171
|
});
|
|
11562
|
-
const deduplicateMessages =
|
|
12172
|
+
const deduplicateMessages = React15.useCallback((sorted) => {
|
|
11563
12173
|
return sorted.filter((msg, i) => {
|
|
11564
12174
|
if (i === 0) return true;
|
|
11565
12175
|
const prev = sorted[i - 1];
|
|
@@ -11567,7 +12177,7 @@ function GraphChatPanel({
|
|
|
11567
12177
|
return true;
|
|
11568
12178
|
});
|
|
11569
12179
|
}, []);
|
|
11570
|
-
const mapMessages =
|
|
12180
|
+
const mapMessages = React15.useCallback((msgs) => {
|
|
11571
12181
|
const nonEmpty = msgs.filter((m) => typeof m.content === "string" && m.content.trim().length > 0);
|
|
11572
12182
|
const sorted = nonEmpty.sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
|
|
11573
12183
|
const deduped = deduplicateMessages(sorted);
|
|
@@ -11590,7 +12200,7 @@ function GraphChatPanel({
|
|
|
11590
12200
|
};
|
|
11591
12201
|
});
|
|
11592
12202
|
}, [deduplicateMessages, currentUser]);
|
|
11593
|
-
|
|
12203
|
+
React15.useEffect(() => {
|
|
11594
12204
|
if (!threadId) {
|
|
11595
12205
|
console.warn("[GraphChatPanel] no threadId \u2014 skipping history load", { groupId, kgId });
|
|
11596
12206
|
return;
|
|
@@ -11629,7 +12239,7 @@ function GraphChatPanel({
|
|
|
11629
12239
|
cancelled = true;
|
|
11630
12240
|
};
|
|
11631
12241
|
}, [groupId, threadId, mapMessages]);
|
|
11632
|
-
const onPollMessages =
|
|
12242
|
+
const onPollMessages = React15.useCallback(async () => {
|
|
11633
12243
|
if (!threadId) return [];
|
|
11634
12244
|
try {
|
|
11635
12245
|
const msgs = await onLoadMessages(groupId, threadId);
|
|
@@ -11642,14 +12252,14 @@ function GraphChatPanel({
|
|
|
11642
12252
|
return [];
|
|
11643
12253
|
}
|
|
11644
12254
|
}, [groupId, threadId, mapMessages]);
|
|
11645
|
-
const defaultHistory =
|
|
12255
|
+
const defaultHistory = React15.useMemo(() => [
|
|
11646
12256
|
{
|
|
11647
12257
|
type: "system",
|
|
11648
12258
|
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
12259
|
timestamp: /* @__PURE__ */ new Date()
|
|
11650
12260
|
}
|
|
11651
12261
|
], [threadId]);
|
|
11652
|
-
const resumeOrInputPipeline =
|
|
12262
|
+
const resumeOrInputPipeline = React15.useCallback(async (message) => {
|
|
11653
12263
|
if (!runId || !config.agentsApiUrl) return;
|
|
11654
12264
|
if (checkpoint) setCheckpointResponded();
|
|
11655
12265
|
const trimmed = message.trim();
|
|
@@ -11662,7 +12272,7 @@ function GraphChatPanel({
|
|
|
11662
12272
|
});
|
|
11663
12273
|
historyRef.current?.setIsExecuting?.(false);
|
|
11664
12274
|
}, [runId, checkpoint, config.agentsApiUrl, setCheckpointResponded]);
|
|
11665
|
-
const onSendMessage =
|
|
12275
|
+
const onSendMessage = React15.useCallback(async (content) => {
|
|
11666
12276
|
if (runId && !threadId && checkpoint) {
|
|
11667
12277
|
historyRef.current?.setIsExecuting?.(true);
|
|
11668
12278
|
resumeOrInputPipeline(content).catch(() => {
|
|
@@ -11695,7 +12305,7 @@ function GraphChatPanel({
|
|
|
11695
12305
|
sender: currentUser
|
|
11696
12306
|
};
|
|
11697
12307
|
}, [groupId, threadId, runId, currentUser, resumeOrInputPipeline]);
|
|
11698
|
-
const extractSources =
|
|
12308
|
+
const extractSources = React15.useCallback((text) => {
|
|
11699
12309
|
const lower = text.toLowerCase();
|
|
11700
12310
|
const matched = [];
|
|
11701
12311
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -11740,7 +12350,7 @@ function GraphChatPanel({
|
|
|
11740
12350
|
}
|
|
11741
12351
|
return matched;
|
|
11742
12352
|
}, [rawNodes]);
|
|
11743
|
-
const onStreamRequest =
|
|
12353
|
+
const onStreamRequest = React15.useCallback(async (command, handlers) => {
|
|
11744
12354
|
accumulatedTextRef.current = "";
|
|
11745
12355
|
let senderOverridden = false;
|
|
11746
12356
|
let mentionedAgent;
|
|
@@ -11852,7 +12462,7 @@ ${kgContext}` : ""}`,
|
|
|
11852
12462
|
handlers.onError
|
|
11853
12463
|
);
|
|
11854
12464
|
}, [groupId, kgId, threadId, onHighlightNodes, extractSources, config.agentsApiUrl, onStreamChat, adoptKgIdFromChunk]);
|
|
11855
|
-
const sourceKGNodes =
|
|
12465
|
+
const sourceKGNodes = React15.useMemo(
|
|
11856
12466
|
() => rawNodes.map((n) => ({
|
|
11857
12467
|
id: n.node_key,
|
|
11858
12468
|
label: n.label,
|
|
@@ -11868,7 +12478,7 @@ ${kgContext}` : ""}`,
|
|
|
11868
12478
|
})),
|
|
11869
12479
|
[rawNodes]
|
|
11870
12480
|
);
|
|
11871
|
-
const mentionTargets =
|
|
12481
|
+
const mentionTargets = React15.useMemo(() => {
|
|
11872
12482
|
const agentKeys = /* @__PURE__ */ new Set();
|
|
11873
12483
|
for (const n of rawNodes) {
|
|
11874
12484
|
const key = n.source_agent_key || n.created_by || n.properties?.created_by || n.properties?.source_agent_key;
|
|
@@ -11978,8 +12588,8 @@ function extractTitle2(text) {
|
|
|
11978
12588
|
function stripMarkdown2(text) {
|
|
11979
12589
|
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
12590
|
}
|
|
11981
|
-
var NotesList =
|
|
11982
|
-
const allNotes =
|
|
12591
|
+
var NotesList = React15.memo(function NotesList2({ chunks, selectedId, onSelect, onCreateNote, filter }) {
|
|
12592
|
+
const allNotes = React15.useMemo(() => {
|
|
11983
12593
|
const byChunk = /* @__PURE__ */ new Map();
|
|
11984
12594
|
for (const link of chunks) {
|
|
11985
12595
|
const list = byChunk.get(link.chunk_id) ?? [];
|
|
@@ -12000,7 +12610,7 @@ var NotesList = React12.memo(function NotesList2({ chunks, selectedId, onSelect,
|
|
|
12000
12610
|
groups.sort((a, b) => (a.chunkIndex ?? Infinity) - (b.chunkIndex ?? Infinity));
|
|
12001
12611
|
return groups;
|
|
12002
12612
|
}, [chunks]);
|
|
12003
|
-
const notes =
|
|
12613
|
+
const notes = React15.useMemo(() => {
|
|
12004
12614
|
if (!filter || !filter.trim()) return allNotes;
|
|
12005
12615
|
const q = filter.toLowerCase().trim();
|
|
12006
12616
|
return allNotes.filter((n) => n.excerpt.toLowerCase().includes(q));
|
|
@@ -12200,19 +12810,19 @@ function NoteExtractionToast({
|
|
|
12200
12810
|
onRunFailed,
|
|
12201
12811
|
authToken
|
|
12202
12812
|
}) {
|
|
12203
|
-
const [phase, setPhase] =
|
|
12204
|
-
const [successFlash, setSuccessFlash] =
|
|
12205
|
-
const [error, setError] =
|
|
12206
|
-
const abortsRef =
|
|
12207
|
-
const onRunCompleteRef =
|
|
12208
|
-
const onRunFailedRef =
|
|
12209
|
-
|
|
12813
|
+
const [phase, setPhase] = React15.useState("Saving note\u2026");
|
|
12814
|
+
const [successFlash, setSuccessFlash] = React15.useState(false);
|
|
12815
|
+
const [error, setError] = React15.useState(null);
|
|
12816
|
+
const abortsRef = React15.useRef(/* @__PURE__ */ new Map());
|
|
12817
|
+
const onRunCompleteRef = React15.useRef(onRunComplete);
|
|
12818
|
+
const onRunFailedRef = React15.useRef(onRunFailed);
|
|
12819
|
+
React15.useEffect(() => {
|
|
12210
12820
|
onRunCompleteRef.current = onRunComplete;
|
|
12211
12821
|
}, [onRunComplete]);
|
|
12212
|
-
|
|
12822
|
+
React15.useEffect(() => {
|
|
12213
12823
|
onRunFailedRef.current = onRunFailed;
|
|
12214
12824
|
}, [onRunFailed]);
|
|
12215
|
-
|
|
12825
|
+
React15.useEffect(() => {
|
|
12216
12826
|
const controllers = abortsRef.current;
|
|
12217
12827
|
for (const run of runs) {
|
|
12218
12828
|
if (controllers.has(run.run_id)) continue;
|
|
@@ -12263,7 +12873,7 @@ function NoteExtractionToast({
|
|
|
12263
12873
|
}
|
|
12264
12874
|
}
|
|
12265
12875
|
}, [runs, agentsApiUrl, authToken]);
|
|
12266
|
-
|
|
12876
|
+
React15.useEffect(() => {
|
|
12267
12877
|
if (runs.length === 0 && !error) {
|
|
12268
12878
|
setSuccessFlash(true);
|
|
12269
12879
|
const t = setTimeout(() => setSuccessFlash(false), 1800);
|
|
@@ -12271,7 +12881,7 @@ function NoteExtractionToast({
|
|
|
12271
12881
|
}
|
|
12272
12882
|
if (runs.length > 0) setSuccessFlash(false);
|
|
12273
12883
|
}, [runs.length, error]);
|
|
12274
|
-
|
|
12884
|
+
React15.useEffect(() => {
|
|
12275
12885
|
return () => {
|
|
12276
12886
|
abortsRef.current.forEach((abort) => abort.abort());
|
|
12277
12887
|
abortsRef.current.clear();
|
|
@@ -12383,10 +12993,10 @@ function KnowledgeGraphView({
|
|
|
12383
12993
|
}) {
|
|
12384
12994
|
const [nodes, setNodes, onNodesChangeBase] = react.useNodesState([]);
|
|
12385
12995
|
const [edges, setEdges, onEdgesChange] = react.useEdgesState([]);
|
|
12386
|
-
const liveNodePositionsRef =
|
|
12387
|
-
const [activityItems, setActivityItems] =
|
|
12388
|
-
const prevActivityLenRef =
|
|
12389
|
-
|
|
12996
|
+
const liveNodePositionsRef = React15.useRef(/* @__PURE__ */ new Map());
|
|
12997
|
+
const [activityItems, setActivityItems] = React15.useState([]);
|
|
12998
|
+
const prevActivityLenRef = React15.useRef(0);
|
|
12999
|
+
React15.useEffect(() => {
|
|
12390
13000
|
if (!activityEvents || activityEvents.length <= prevActivityLenRef.current) {
|
|
12391
13001
|
prevActivityLenRef.current = activityEvents?.length || 0;
|
|
12392
13002
|
return;
|
|
@@ -12399,23 +13009,23 @@ function KnowledgeGraphView({
|
|
|
12399
13009
|
}
|
|
12400
13010
|
}, [activityEvents?.length]);
|
|
12401
13011
|
const useWindowEvents = !activityEvents;
|
|
12402
|
-
const [liveRefreshTrigger, setLiveRefreshTrigger] =
|
|
12403
|
-
const lastPersistRef =
|
|
12404
|
-
const pipelineDoneRef =
|
|
12405
|
-
const pendingActivityRef =
|
|
12406
|
-
const activityFlushRef =
|
|
12407
|
-
const flushActivity =
|
|
13012
|
+
const [liveRefreshTrigger, setLiveRefreshTrigger] = React15.useState(0);
|
|
13013
|
+
const lastPersistRef = React15.useRef(0);
|
|
13014
|
+
const pipelineDoneRef = React15.useRef(false);
|
|
13015
|
+
const pendingActivityRef = React15.useRef([]);
|
|
13016
|
+
const activityFlushRef = React15.useRef(null);
|
|
13017
|
+
const flushActivity = React15.useCallback(() => {
|
|
12408
13018
|
activityFlushRef.current = null;
|
|
12409
13019
|
if (pendingActivityRef.current.length === 0) return;
|
|
12410
13020
|
const batch = pendingActivityRef.current;
|
|
12411
13021
|
pendingActivityRef.current = [];
|
|
12412
13022
|
setActivityItems((prev) => [...prev, ...batch]);
|
|
12413
13023
|
}, []);
|
|
12414
|
-
|
|
13024
|
+
React15.useEffect(() => () => {
|
|
12415
13025
|
if (activityFlushRef.current) clearTimeout(activityFlushRef.current);
|
|
12416
13026
|
flushActivity();
|
|
12417
13027
|
}, [flushActivity]);
|
|
12418
|
-
const handleActivityEvent =
|
|
13028
|
+
const handleActivityEvent = React15.useCallback((event) => {
|
|
12419
13029
|
if (pipelineDoneRef.current) return;
|
|
12420
13030
|
const item = eventToActivity(event);
|
|
12421
13031
|
if (item) {
|
|
@@ -12438,8 +13048,8 @@ function KnowledgeGraphView({
|
|
|
12438
13048
|
}
|
|
12439
13049
|
}, [flushActivity]);
|
|
12440
13050
|
useScopedProgressEvent(kgId, handleActivityEvent, useWindowEvents);
|
|
12441
|
-
const [forceGraph, setForceGraph] =
|
|
12442
|
-
const onNodesChange =
|
|
13051
|
+
const [forceGraph, setForceGraph] = React15.useState(false);
|
|
13052
|
+
const onNodesChange = React15.useCallback((changes) => {
|
|
12443
13053
|
onNodesChangeBase(changes);
|
|
12444
13054
|
for (const change of changes) {
|
|
12445
13055
|
if (change.type === "position" && "position" in change && change.position) {
|
|
@@ -12447,29 +13057,29 @@ function KnowledgeGraphView({
|
|
|
12447
13057
|
}
|
|
12448
13058
|
}
|
|
12449
13059
|
}, [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] =
|
|
13060
|
+
const [loading, setLoading] = React15.useState(true);
|
|
13061
|
+
const [error, setError] = React15.useState(null);
|
|
13062
|
+
const [searchTerm, setSearchTerm] = React15.useState("");
|
|
13063
|
+
const [phaseFilter, setPhaseFilter] = React15.useState("all");
|
|
13064
|
+
const [isFullscreen, setIsFullscreen] = React15.useState(false);
|
|
13065
|
+
const [selectedNodeId, setSelectedNodeId] = React15.useState(null);
|
|
13066
|
+
const [selectedEdgeId, setSelectedEdgeId] = React15.useState(null);
|
|
13067
|
+
const [hoveredNodeId, setHoveredNodeId] = React15.useState(null);
|
|
12458
13068
|
const hasChat = !!(renderChat || config);
|
|
12459
|
-
const [chatOpen, setChatOpen] =
|
|
12460
|
-
const [chatMounted, setChatMounted] =
|
|
12461
|
-
|
|
13069
|
+
const [chatOpen, setChatOpen] = React15.useState(hasChat);
|
|
13070
|
+
const [chatMounted, setChatMounted] = React15.useState(hasChat);
|
|
13071
|
+
React15.useEffect(() => {
|
|
12462
13072
|
if (chatOpen && !chatMounted) setChatMounted(true);
|
|
12463
13073
|
}, [chatOpen]);
|
|
12464
|
-
|
|
13074
|
+
React15.useEffect(() => {
|
|
12465
13075
|
if ((runId || genericKGProp) && hasChat && !chatOpen) {
|
|
12466
13076
|
setChatOpen(true);
|
|
12467
13077
|
setChatMounted(true);
|
|
12468
13078
|
}
|
|
12469
13079
|
}, [runId, genericKGProp, hasChat]);
|
|
12470
|
-
const [chatQuery, setChatQuery] =
|
|
12471
|
-
const [ontologyOpen, setOntologyOpen] =
|
|
12472
|
-
|
|
13080
|
+
const [chatQuery, setChatQuery] = React15.useState(void 0);
|
|
13081
|
+
const [ontologyOpen, setOntologyOpen] = React15.useState(false);
|
|
13082
|
+
React15.useEffect(() => {
|
|
12473
13083
|
if (chatToggleRef) {
|
|
12474
13084
|
chatToggleRef.current = () => {
|
|
12475
13085
|
setChatOpen((v) => !v);
|
|
@@ -12480,43 +13090,43 @@ function KnowledgeGraphView({
|
|
|
12480
13090
|
};
|
|
12481
13091
|
}
|
|
12482
13092
|
}, [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
|
-
|
|
13093
|
+
const [searching, setSearching] = React15.useState(false);
|
|
13094
|
+
const [searchResult, setSearchResult] = React15.useState({ hits: [], traversal: [] });
|
|
13095
|
+
const [searchActive, setSearchActive] = React15.useState(false);
|
|
13096
|
+
const searchTimerRef = React15.useRef(null);
|
|
13097
|
+
const fitViewTimerRef = React15.useRef(null);
|
|
13098
|
+
const rfInstanceRef = React15.useRef(null);
|
|
13099
|
+
const didInitialFitRef = React15.useRef(false);
|
|
13100
|
+
const [rfReady, setRfReady] = React15.useState(false);
|
|
13101
|
+
React15.useEffect(() => {
|
|
12492
13102
|
didInitialFitRef.current = false;
|
|
12493
13103
|
setRfReady(false);
|
|
12494
13104
|
}, [kgId]);
|
|
12495
|
-
const gkgNodeMap =
|
|
13105
|
+
const gkgNodeMap = React15.useMemo(() => {
|
|
12496
13106
|
if (!genericKGProp) return /* @__PURE__ */ new Map();
|
|
12497
13107
|
return new Map(genericKGProp.nodes.map((n) => [n.id, n]));
|
|
12498
13108
|
}, [genericKGProp]);
|
|
12499
|
-
const gkgEdgeMap =
|
|
13109
|
+
const gkgEdgeMap = React15.useMemo(() => {
|
|
12500
13110
|
if (!genericKGProp) return /* @__PURE__ */ new Map();
|
|
12501
13111
|
return new Map(genericKGProp.edges.map((e) => [e.id, e]));
|
|
12502
13112
|
}, [genericKGProp]);
|
|
12503
|
-
const fullNodesRef =
|
|
12504
|
-
const fullEdgesRef =
|
|
12505
|
-
const [rawNodes, setRawNodes] =
|
|
12506
|
-
const [rawEdges, setRawEdges] =
|
|
12507
|
-
const [nodeChunks, setNodeChunks] =
|
|
13113
|
+
const fullNodesRef = React15.useRef([]);
|
|
13114
|
+
const fullEdgesRef = React15.useRef([]);
|
|
13115
|
+
const [rawNodes, setRawNodes] = React15.useState([]);
|
|
13116
|
+
const [rawEdges, setRawEdges] = React15.useState([]);
|
|
13117
|
+
const [nodeChunks, setNodeChunks] = React15.useState([]);
|
|
12508
13118
|
const hasLiveReasoning = !!runId || !!genericKGProp;
|
|
12509
|
-
const [viewMode, setViewMode] =
|
|
13119
|
+
const [viewMode, setViewMode] = React15.useState(
|
|
12510
13120
|
hasLiveReasoning ? "entity" : data.onLoadAllChunks ? "chunk" : "entity"
|
|
12511
13121
|
);
|
|
12512
|
-
const viewModeRef =
|
|
13122
|
+
const viewModeRef = React15.useRef(viewMode);
|
|
12513
13123
|
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 =
|
|
13124
|
+
const [allChunks, setAllChunks] = React15.useState(null);
|
|
13125
|
+
const [chunksLoading, setChunksLoading] = React15.useState(false);
|
|
13126
|
+
const [draftNote, setDraftNote] = React15.useState(null);
|
|
13127
|
+
const [savingDraft, setSavingDraft] = React15.useState(false);
|
|
13128
|
+
const [noteRuns, setNoteRuns] = React15.useState([]);
|
|
13129
|
+
const handleNoteRunFinished = React15.useCallback((runId2) => {
|
|
12520
13130
|
setNoteRuns((prev) => {
|
|
12521
13131
|
const next = prev.filter((r) => r.run_id !== runId2);
|
|
12522
13132
|
if (next.length === 0 && data.onLoadAllChunks) {
|
|
@@ -12525,9 +13135,9 @@ function KnowledgeGraphView({
|
|
|
12525
13135
|
return next;
|
|
12526
13136
|
});
|
|
12527
13137
|
}, [data, groupId, kgId]);
|
|
12528
|
-
|
|
12529
|
-
|
|
12530
|
-
|
|
13138
|
+
React15.useRef(null);
|
|
13139
|
+
React15.useRef(null);
|
|
13140
|
+
React15.useEffect(() => {
|
|
12531
13141
|
if (!selectedNodeId) {
|
|
12532
13142
|
setNodeChunks([]);
|
|
12533
13143
|
return;
|
|
@@ -12553,7 +13163,7 @@ function KnowledgeGraphView({
|
|
|
12553
13163
|
cancelled = true;
|
|
12554
13164
|
};
|
|
12555
13165
|
}, [selectedNodeId, groupId, kgId, allChunks]);
|
|
12556
|
-
|
|
13166
|
+
React15.useEffect(() => {
|
|
12557
13167
|
if (allChunks !== null || !data.onLoadAllChunks) return;
|
|
12558
13168
|
let cancelled = false;
|
|
12559
13169
|
setChunksLoading(true);
|
|
@@ -12569,8 +13179,8 @@ function KnowledgeGraphView({
|
|
|
12569
13179
|
cancelled = true;
|
|
12570
13180
|
};
|
|
12571
13181
|
}, [viewMode, allChunks, groupId, kgId, data.onLoadAllChunks]);
|
|
12572
|
-
const prevViewModeRef =
|
|
12573
|
-
|
|
13182
|
+
const prevViewModeRef = React15.useRef(viewMode);
|
|
13183
|
+
React15.useEffect(() => {
|
|
12574
13184
|
const modeChanged = prevViewModeRef.current !== viewMode;
|
|
12575
13185
|
prevViewModeRef.current = viewMode;
|
|
12576
13186
|
if (viewMode === "entity") {
|
|
@@ -12632,7 +13242,7 @@ function KnowledgeGraphView({
|
|
|
12632
13242
|
fitViewTimerRef.current = setTimeout(() => rfInstanceRef.current?.fitView({ padding: 0.2, duration: 300 }), 60);
|
|
12633
13243
|
}
|
|
12634
13244
|
}, [viewMode, allChunks, rawNodes, rawEdges]);
|
|
12635
|
-
const buildRfGraph =
|
|
13245
|
+
const buildRfGraph = React15.useCallback((subgraph, existingPositions) => {
|
|
12636
13246
|
const rfNodes = subgraph.nodes.map((n) => {
|
|
12637
13247
|
const gkg = gkgNodeMap.get(n.node_key);
|
|
12638
13248
|
const filterValue = gkg?.claim_status ?? n.properties?.claim_status ?? gkg?.phase ?? n.properties?.phase;
|
|
@@ -12683,8 +13293,8 @@ function KnowledgeGraphView({
|
|
|
12683
13293
|
}));
|
|
12684
13294
|
return { rfNodes, rfEdges };
|
|
12685
13295
|
}, [phaseFilter, gkgNodeMap]);
|
|
12686
|
-
const prevNodeIdsRef =
|
|
12687
|
-
const applyRfGraph =
|
|
13296
|
+
const prevNodeIdsRef = React15.useRef("");
|
|
13297
|
+
const applyRfGraph = React15.useCallback((rfNodes, rfEdges, existingPositions) => {
|
|
12688
13298
|
const nodeIds = rfNodes.map((n) => n.id).join(",");
|
|
12689
13299
|
const structureChanged = nodeIds !== prevNodeIdsRef.current || existingPositions.size === 0;
|
|
12690
13300
|
prevNodeIdsRef.current = nodeIds;
|
|
@@ -12721,7 +13331,7 @@ function KnowledgeGraphView({
|
|
|
12721
13331
|
setNodes(finalNodes);
|
|
12722
13332
|
setEdges(rfEdges);
|
|
12723
13333
|
}, [setNodes, setEdges]);
|
|
12724
|
-
|
|
13334
|
+
React15.useEffect(() => {
|
|
12725
13335
|
let cancelled = false;
|
|
12726
13336
|
const isLiveUpdate = !!genericKGProp;
|
|
12727
13337
|
(async () => {
|
|
@@ -12792,7 +13402,7 @@ function KnowledgeGraphView({
|
|
|
12792
13402
|
cancelled = true;
|
|
12793
13403
|
};
|
|
12794
13404
|
}, [groupId, kgId, genericKGProp, data.onLoadKg, liveRefreshTrigger]);
|
|
12795
|
-
|
|
13405
|
+
React15.useEffect(() => {
|
|
12796
13406
|
if (!rfReady) return;
|
|
12797
13407
|
if (nodes.length === 0) return;
|
|
12798
13408
|
if (didInitialFitRef.current) return;
|
|
@@ -12802,8 +13412,8 @@ function KnowledgeGraphView({
|
|
|
12802
13412
|
});
|
|
12803
13413
|
return () => cancelAnimationFrame(raf);
|
|
12804
13414
|
}, [rfReady, nodes.length, kgId]);
|
|
12805
|
-
const prevSnapshotFingerprintRef =
|
|
12806
|
-
|
|
13415
|
+
const prevSnapshotFingerprintRef = React15.useRef("");
|
|
13416
|
+
React15.useEffect(() => {
|
|
12807
13417
|
if (!processingDetail && !runId) return;
|
|
12808
13418
|
if (!isFixedKgId(kgId)) return;
|
|
12809
13419
|
const interval = setInterval(async () => {
|
|
@@ -12829,7 +13439,7 @@ function KnowledgeGraphView({
|
|
|
12829
13439
|
}, 5e3);
|
|
12830
13440
|
return () => clearInterval(interval);
|
|
12831
13441
|
}, [!!processingDetail, !!runId, groupId, kgId, buildRfGraph, applyRfGraph]);
|
|
12832
|
-
const applyFocusedSubgraph =
|
|
13442
|
+
const applyFocusedSubgraph = React15.useCallback((matchIds, scoreMap, neighborIds, traversalIds) => {
|
|
12833
13443
|
const visibleIds = new Set(matchIds);
|
|
12834
13444
|
neighborIds?.forEach((id) => visibleIds.add(id));
|
|
12835
13445
|
traversalIds?.forEach((id) => visibleIds.add(id));
|
|
@@ -12868,7 +13478,7 @@ function KnowledgeGraphView({
|
|
|
12868
13478
|
if (fitViewTimerRef.current) clearTimeout(fitViewTimerRef.current);
|
|
12869
13479
|
fitViewTimerRef.current = setTimeout(() => rfInstanceRef.current?.fitView({ padding: 0.3, duration: 300 }), 60);
|
|
12870
13480
|
}, [rawEdges, setNodes, setEdges]);
|
|
12871
|
-
const restoreFullGraph =
|
|
13481
|
+
const restoreFullGraph = React15.useCallback(() => {
|
|
12872
13482
|
setNodes(fullNodesRef.current.map((n) => ({
|
|
12873
13483
|
...n,
|
|
12874
13484
|
data: { ...n.data, isHighlighted: false, isDimmed: false, searchScore: null }
|
|
@@ -12881,17 +13491,17 @@ function KnowledgeGraphView({
|
|
|
12881
13491
|
if (fitViewTimerRef.current) clearTimeout(fitViewTimerRef.current);
|
|
12882
13492
|
fitViewTimerRef.current = setTimeout(() => rfInstanceRef.current?.fitView({ padding: 0.2, duration: 300 }), 60);
|
|
12883
13493
|
}, [setNodes, setEdges]);
|
|
12884
|
-
const hasClaimStatuses =
|
|
13494
|
+
const hasClaimStatuses = React15.useMemo(() => {
|
|
12885
13495
|
if (genericKGProp) return genericKGProp.nodes.some((n) => n.claim_status);
|
|
12886
13496
|
return rawNodes.some((n) => n.properties?.claim_status);
|
|
12887
13497
|
}, [genericKGProp, rawNodes]);
|
|
12888
|
-
const hasPhases =
|
|
13498
|
+
const hasPhases = React15.useMemo(() => {
|
|
12889
13499
|
if (hasClaimStatuses) return false;
|
|
12890
13500
|
if (genericKGProp) return genericKGProp.nodes.some((n) => n.phase && n.phase !== "simple");
|
|
12891
13501
|
return rawNodes.some((n) => n.properties?.phase && n.properties.phase !== "simple");
|
|
12892
13502
|
}, [genericKGProp, hasClaimStatuses, rawNodes]);
|
|
12893
13503
|
const hasFilters = hasClaimStatuses || hasPhases;
|
|
12894
|
-
|
|
13504
|
+
React15.useEffect(() => {
|
|
12895
13505
|
if (!hasFilters || searchActive) return;
|
|
12896
13506
|
if (phaseFilter === "all") {
|
|
12897
13507
|
setNodes((nds) => nds.map((n) => ({ ...n, data: { ...n.data, isDimmed: false } })));
|
|
@@ -12915,7 +13525,7 @@ function KnowledgeGraphView({
|
|
|
12915
13525
|
return { ...n, data: { ...n.data, isDimmed: !matches } };
|
|
12916
13526
|
}));
|
|
12917
13527
|
}, [phaseFilter, hasFilters, searchActive, setNodes, setEdges]);
|
|
12918
|
-
|
|
13528
|
+
React15.useEffect(() => {
|
|
12919
13529
|
if (searchActive) return;
|
|
12920
13530
|
if (!hoveredNodeId) {
|
|
12921
13531
|
setNodes((nds) => nds.map((n) => ({ ...n, data: { ...n.data, isHighlighted: false, isDimmed: false } })));
|
|
@@ -12944,7 +13554,7 @@ function KnowledgeGraphView({
|
|
|
12944
13554
|
}
|
|
12945
13555
|
})));
|
|
12946
13556
|
}, [hoveredNodeId, searchActive, setNodes, setEdges]);
|
|
12947
|
-
|
|
13557
|
+
React15.useEffect(() => {
|
|
12948
13558
|
if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
|
|
12949
13559
|
if (!searchTerm.trim()) {
|
|
12950
13560
|
setSearchResult({ hits: [], traversal: [] });
|
|
@@ -12965,19 +13575,19 @@ function KnowledgeGraphView({
|
|
|
12965
13575
|
setSearching(true);
|
|
12966
13576
|
searchTimerRef.current = setTimeout(async () => {
|
|
12967
13577
|
try {
|
|
12968
|
-
const
|
|
12969
|
-
setSearchResult(
|
|
12970
|
-
if (
|
|
13578
|
+
const result2 = data.onSearchNodes ? await data.onSearchNodes(groupId, kgId, q, 10, 2) : { hits: [], traversal: [] };
|
|
13579
|
+
setSearchResult(result2);
|
|
13580
|
+
if (result2.hits.length === 0 && localMatchIds.size === 0) {
|
|
12971
13581
|
restoreFullGraph();
|
|
12972
13582
|
setSearching(false);
|
|
12973
13583
|
return;
|
|
12974
13584
|
}
|
|
12975
|
-
if (
|
|
13585
|
+
if (result2.hits.length === 0) {
|
|
12976
13586
|
setSearching(false);
|
|
12977
13587
|
return;
|
|
12978
13588
|
}
|
|
12979
13589
|
const scoreMap = /* @__PURE__ */ new Map();
|
|
12980
|
-
|
|
13590
|
+
result2.hits.forEach((h) => {
|
|
12981
13591
|
const existing = scoreMap.get(h.node_key) ?? 0;
|
|
12982
13592
|
if ((h.score ?? 0) > existing) scoreMap.set(h.node_key, h.score ?? 0);
|
|
12983
13593
|
});
|
|
@@ -12985,9 +13595,9 @@ function KnowledgeGraphView({
|
|
|
12985
13595
|
if (!scoreMap.has(id)) scoreMap.set(id, 0.5);
|
|
12986
13596
|
});
|
|
12987
13597
|
const traversalIds = /* @__PURE__ */ new Set();
|
|
12988
|
-
|
|
13598
|
+
result2.traversal.forEach((t) => traversalIds.add(t.node_key));
|
|
12989
13599
|
const neighborIds = /* @__PURE__ */ new Set();
|
|
12990
|
-
|
|
13600
|
+
result2.hits.forEach((h) => {
|
|
12991
13601
|
h.neighbors?.forEach((nk) => {
|
|
12992
13602
|
if (!scoreMap.has(nk)) neighborIds.add(nk);
|
|
12993
13603
|
});
|
|
@@ -13002,7 +13612,7 @@ function KnowledgeGraphView({
|
|
|
13002
13612
|
if (searchTimerRef.current) clearTimeout(searchTimerRef.current);
|
|
13003
13613
|
};
|
|
13004
13614
|
}, [searchTerm, rawNodes, rawEdges, groupId, kgId, applyFocusedSubgraph, restoreFullGraph]);
|
|
13005
|
-
const onNodeClick =
|
|
13615
|
+
const onNodeClick = React15.useCallback((_, node) => {
|
|
13006
13616
|
if (node.id === "__add_note__" && data.onCreateNote) {
|
|
13007
13617
|
setSelectedNodeId(null);
|
|
13008
13618
|
setSelectedEdgeId(null);
|
|
@@ -13012,21 +13622,21 @@ function KnowledgeGraphView({
|
|
|
13012
13622
|
setSelectedNodeId(node.id);
|
|
13013
13623
|
setSelectedEdgeId(null);
|
|
13014
13624
|
}, [data.onCreateNote]);
|
|
13015
|
-
const onEdgeClick =
|
|
13625
|
+
const onEdgeClick = React15.useCallback((_, edge) => {
|
|
13016
13626
|
setSelectedEdgeId(edge.id);
|
|
13017
13627
|
setSelectedNodeId(null);
|
|
13018
13628
|
}, []);
|
|
13019
|
-
const onNodeMouseEnter =
|
|
13629
|
+
const onNodeMouseEnter = React15.useCallback((_, node) => {
|
|
13020
13630
|
setHoveredNodeId(node.id);
|
|
13021
13631
|
}, []);
|
|
13022
|
-
const onNodeMouseLeave =
|
|
13632
|
+
const onNodeMouseLeave = React15.useCallback(() => {
|
|
13023
13633
|
setHoveredNodeId(null);
|
|
13024
13634
|
}, []);
|
|
13025
|
-
const onPaneClick =
|
|
13635
|
+
const onPaneClick = React15.useCallback(() => {
|
|
13026
13636
|
setSelectedNodeId(null);
|
|
13027
13637
|
setSelectedEdgeId(null);
|
|
13028
13638
|
}, []);
|
|
13029
|
-
const selectedNodeConnections =
|
|
13639
|
+
const selectedNodeConnections = React15.useMemo(() => {
|
|
13030
13640
|
if (!selectedNodeId) return [];
|
|
13031
13641
|
if (viewMode === "chunk" && selectedNodeId.startsWith("chunk:") && allChunks) {
|
|
13032
13642
|
const chunkId = selectedNodeId.slice("chunk:".length);
|
|
@@ -13076,7 +13686,7 @@ function KnowledgeGraphView({
|
|
|
13076
13686
|
};
|
|
13077
13687
|
});
|
|
13078
13688
|
}, [selectedNodeId, rawNodes, rawEdges, viewMode, allChunks]);
|
|
13079
|
-
const selectedEdgeData =
|
|
13689
|
+
const selectedEdgeData = React15.useMemo(() => {
|
|
13080
13690
|
if (!selectedEdgeId) return null;
|
|
13081
13691
|
const raw = rawEdges.find((e) => e.edge_key === selectedEdgeId);
|
|
13082
13692
|
if (!raw) return null;
|
|
@@ -13096,7 +13706,7 @@ function KnowledgeGraphView({
|
|
|
13096
13706
|
targetNode: { id: raw.to_node_key, label: targetNode?.label || raw.to_node_key, nodeType: targetNode?.node_type || "unknown" }
|
|
13097
13707
|
};
|
|
13098
13708
|
}, [selectedEdgeId, rawNodes, rawEdges, gkgEdgeMap]);
|
|
13099
|
-
const selectedNodeData =
|
|
13709
|
+
const selectedNodeData = React15.useMemo(() => {
|
|
13100
13710
|
if (!selectedNodeId) return null;
|
|
13101
13711
|
if (viewMode === "chunk" && selectedNodeId.startsWith("chunk:") && allChunks) {
|
|
13102
13712
|
const chunkId = selectedNodeId.slice("chunk:".length);
|
|
@@ -13142,12 +13752,12 @@ function KnowledgeGraphView({
|
|
|
13142
13752
|
hasRagChunks: !!(raw.properties?.rag_chunks?.length || raw.properties?.source_chunks?.length || raw.properties?.references?.length)
|
|
13143
13753
|
};
|
|
13144
13754
|
}, [selectedNodeId, rawNodes, viewMode, allChunks]);
|
|
13145
|
-
const navigateToNode =
|
|
13755
|
+
const navigateToNode = React15.useCallback((nodeId) => {
|
|
13146
13756
|
setSelectedNodeId(nodeId);
|
|
13147
13757
|
setSelectedEdgeId(null);
|
|
13148
13758
|
}, []);
|
|
13149
|
-
const reviewNodeIds =
|
|
13150
|
-
const onReviewNavigate =
|
|
13759
|
+
const reviewNodeIds = React15.useMemo(() => rawNodes.map((n) => n.node_key), [rawNodes]);
|
|
13760
|
+
const onReviewNavigate = React15.useCallback((nodeId) => {
|
|
13151
13761
|
setSelectedNodeId(nodeId);
|
|
13152
13762
|
setSelectedEdgeId(null);
|
|
13153
13763
|
const rfNode = nodes.find((n) => n.id === nodeId);
|
|
@@ -13160,8 +13770,8 @@ function KnowledgeGraphView({
|
|
|
13160
13770
|
);
|
|
13161
13771
|
}
|
|
13162
13772
|
}, [nodes]);
|
|
13163
|
-
const lastChatHighlightRef =
|
|
13164
|
-
const handleChatHighlight =
|
|
13773
|
+
const lastChatHighlightRef = React15.useRef("");
|
|
13774
|
+
const handleChatHighlight = React15.useCallback((nodeIds) => {
|
|
13165
13775
|
if (nodeIds.length === 0) return;
|
|
13166
13776
|
const key = nodeIds.sort().join(",");
|
|
13167
13777
|
if (key === lastChatHighlightRef.current) return;
|
|
@@ -13177,7 +13787,7 @@ function KnowledgeGraphView({
|
|
|
13177
13787
|
})));
|
|
13178
13788
|
setSearchActive(true);
|
|
13179
13789
|
}, [setNodes, setEdges]);
|
|
13180
|
-
const minimapNodeColor =
|
|
13790
|
+
const minimapNodeColor = React15.useCallback((node) => {
|
|
13181
13791
|
return getNodeColors(node.data?.nodeType || "").badge;
|
|
13182
13792
|
}, []);
|
|
13183
13793
|
const hasLiveRun = !!runId;
|
|
@@ -13476,9 +14086,9 @@ function KnowledgeGraphView({
|
|
|
13476
14086
|
if (!data.onCreateNote || !draftNote || !draftNote.trim()) return;
|
|
13477
14087
|
setSavingDraft(true);
|
|
13478
14088
|
try {
|
|
13479
|
-
const
|
|
14089
|
+
const result2 = await data.onCreateNote(groupId, kgId, draftNote);
|
|
13480
14090
|
setDraftNote(null);
|
|
13481
|
-
setSelectedNodeId(`chunk:${
|
|
14091
|
+
setSelectedNodeId(`chunk:${result2.chunk_id}`);
|
|
13482
14092
|
if (data.onLoadAllChunks) {
|
|
13483
14093
|
try {
|
|
13484
14094
|
const fresh = await data.onLoadAllChunks(groupId, kgId);
|
|
@@ -13487,10 +14097,10 @@ function KnowledgeGraphView({
|
|
|
13487
14097
|
console.warn("[KGV] post-create chunk refetch failed", err);
|
|
13488
14098
|
}
|
|
13489
14099
|
}
|
|
13490
|
-
if (
|
|
14100
|
+
if (result2.run_id && config?.agentsApiUrl) {
|
|
13491
14101
|
setNoteRuns((prev) => [
|
|
13492
14102
|
...prev,
|
|
13493
|
-
{ run_id:
|
|
14103
|
+
{ run_id: result2.run_id, kg_id: kgId }
|
|
13494
14104
|
]);
|
|
13495
14105
|
}
|
|
13496
14106
|
} catch (err) {
|
|
@@ -13586,9 +14196,9 @@ function ReasoningView({
|
|
|
13586
14196
|
activityEvents,
|
|
13587
14197
|
className = ""
|
|
13588
14198
|
}) {
|
|
13589
|
-
const [chainOpen, setChainOpen] =
|
|
13590
|
-
const [chainGoal, setChainGoal] =
|
|
13591
|
-
const chainInputRef =
|
|
14199
|
+
const [chainOpen, setChainOpen] = React15.useState(false);
|
|
14200
|
+
const [chainGoal, setChainGoal] = React15.useState("");
|
|
14201
|
+
const chainInputRef = React15.useRef(null);
|
|
13592
14202
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `flex flex-col h-full overflow-hidden ${className}`, style: { backgroundColor: "#181818" }, children: [
|
|
13593
14203
|
(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
14204
|
onClose && /* @__PURE__ */ jsxRuntime.jsx(
|
|
@@ -13740,15 +14350,15 @@ function SettlementBar({ settledCount, totalCount }) {
|
|
|
13740
14350
|
] });
|
|
13741
14351
|
}
|
|
13742
14352
|
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 =
|
|
14353
|
+
const [open, setOpen] = React15.useState(false);
|
|
14354
|
+
const [kgId, setKgId] = React15.useState(null);
|
|
14355
|
+
const [runId, setRunId] = React15.useState();
|
|
14356
|
+
const [workingGroupId, setWorkingGroupId] = React15.useState(null);
|
|
14357
|
+
const [threadId, setThreadId] = React15.useState();
|
|
14358
|
+
const [reasoningPhase, setReasoningPhase] = React15.useState(null);
|
|
14359
|
+
const [reasoningAgents, setReasoningAgents] = React15.useState();
|
|
14360
|
+
const [genericKG, setGenericKG] = React15.useState(null);
|
|
14361
|
+
const loadKg = React15.useCallback(async (id) => {
|
|
13752
14362
|
try {
|
|
13753
14363
|
let wgId = null;
|
|
13754
14364
|
let resolvedThread;
|
|
@@ -13824,7 +14434,7 @@ function ReasoningOverlay({ config, currentUser, data, onLookupKg, authToken })
|
|
|
13824
14434
|
console.error("[ReasoningOverlay] Failed to load:", e);
|
|
13825
14435
|
}
|
|
13826
14436
|
}, [data, onLookupKg]);
|
|
13827
|
-
const close =
|
|
14437
|
+
const close = React15.useCallback(() => {
|
|
13828
14438
|
setOpen(false);
|
|
13829
14439
|
setGenericKG(null);
|
|
13830
14440
|
setKgId(null);
|
|
@@ -13833,7 +14443,7 @@ function ReasoningOverlay({ config, currentUser, data, onLookupKg, authToken })
|
|
|
13833
14443
|
setRunId(void 0);
|
|
13834
14444
|
window.dispatchEvent(new CustomEvent("reasoning-overlay-closed", { bubbles: true }));
|
|
13835
14445
|
}, []);
|
|
13836
|
-
|
|
14446
|
+
React15.useEffect(() => {
|
|
13837
14447
|
const handler = (e) => {
|
|
13838
14448
|
const detail = e.detail || {};
|
|
13839
14449
|
const id = detail.kgId || detail.reasoningSetId;
|
|
@@ -13846,7 +14456,7 @@ function ReasoningOverlay({ config, currentUser, data, onLookupKg, authToken })
|
|
|
13846
14456
|
window.removeEventListener("view-reasoning-set", handler);
|
|
13847
14457
|
};
|
|
13848
14458
|
}, [loadKg]);
|
|
13849
|
-
|
|
14459
|
+
React15.useEffect(() => {
|
|
13850
14460
|
if (!open) return;
|
|
13851
14461
|
const handler = (e) => {
|
|
13852
14462
|
if (e.key === "Escape") close();
|
|
@@ -13907,9 +14517,9 @@ function CheckpointCard({
|
|
|
13907
14517
|
onAction,
|
|
13908
14518
|
responded = false
|
|
13909
14519
|
}) {
|
|
13910
|
-
const [inputValue, setInputValue] =
|
|
13911
|
-
const [showInput, setShowInput] =
|
|
13912
|
-
const inputRef =
|
|
14520
|
+
const [inputValue, setInputValue] = React15.useState("");
|
|
14521
|
+
const [showInput, setShowInput] = React15.useState(false);
|
|
14522
|
+
const inputRef = React15.useRef(null);
|
|
13913
14523
|
const config = TYPE_CONFIG2[type] || TYPE_CONFIG2.generic;
|
|
13914
14524
|
const handleSend = () => {
|
|
13915
14525
|
if (!inputValue.trim()) return;
|
|
@@ -13917,7 +14527,7 @@ function CheckpointCard({
|
|
|
13917
14527
|
setInputValue("");
|
|
13918
14528
|
setShowInput(false);
|
|
13919
14529
|
};
|
|
13920
|
-
|
|
14530
|
+
React15.useEffect(() => {
|
|
13921
14531
|
if (showInput) inputRef.current?.focus();
|
|
13922
14532
|
}, [showInput]);
|
|
13923
14533
|
return /* @__PURE__ */ jsxRuntime.jsxs(
|
|
@@ -14049,6 +14659,7 @@ exports.ADVANCE_PHASE_SIGNAL = ADVANCE_PHASE_SIGNAL;
|
|
|
14049
14659
|
exports.AGENT_PALETTE = AGENT_PALETTE;
|
|
14050
14660
|
exports.AgentAvatar = AgentAvatar;
|
|
14051
14661
|
exports.AgentPresenceBar = AgentPresenceBar;
|
|
14662
|
+
exports.AgentStepTrace = AgentStepTrace;
|
|
14052
14663
|
exports.AnnotationThread = AnnotationThread;
|
|
14053
14664
|
exports.CLAIM_STATUS_COLORS = CLAIM_STATUS_COLORS;
|
|
14054
14665
|
exports.ChatTerminal = ChatTerminal;
|
|
@@ -14056,6 +14667,7 @@ exports.CheckpointCard = CheckpointCard;
|
|
|
14056
14667
|
exports.ClaimNode = ClaimNode;
|
|
14057
14668
|
exports.ConstructionProgress = ConstructionProgress;
|
|
14058
14669
|
exports.CoreTerminal = CoreTerminal;
|
|
14670
|
+
exports.DEFAULT_AGENT_LABEL = DEFAULT_AGENT_LABEL;
|
|
14059
14671
|
exports.DOCUMENT_PIPELINE_STEPS = DOCUMENT_PIPELINE_STEPS;
|
|
14060
14672
|
exports.DocumentProcessingProgress = DocumentProcessingProgress;
|
|
14061
14673
|
exports.EDGE_TYPE_COLORS = EDGE_TYPE_COLORS;
|
|
@@ -14080,6 +14692,8 @@ exports.PipelineProgressBar = PipelineProgressBar;
|
|
|
14080
14692
|
exports.ReasoningHistoryCard = ReasoningHistoryCard;
|
|
14081
14693
|
exports.ReasoningOverlay = ReasoningOverlay;
|
|
14082
14694
|
exports.ReasoningView = ReasoningView;
|
|
14695
|
+
exports.SSE_KEEPALIVE_MS = SSE_KEEPALIVE_MS;
|
|
14696
|
+
exports.SSE_STALL_MS = SSE_STALL_MS;
|
|
14083
14697
|
exports.SYNTHESIS_DONE_SIGNAL = SYNTHESIS_DONE_SIGNAL;
|
|
14084
14698
|
exports.ScopedReasoningProvider = ScopedReasoningProvider;
|
|
14085
14699
|
exports.SettlementBar = SettlementBar;
|
|
@@ -14089,6 +14703,7 @@ exports.StandardTerminal = StandardTerminal;
|
|
|
14089
14703
|
exports.TerminalInputBar = TerminalInputBar;
|
|
14090
14704
|
exports.TerminalThemeProvider = TerminalThemeProvider;
|
|
14091
14705
|
exports.agentSeed = agentSeed;
|
|
14706
|
+
exports.agentStepTraceExtra = agentStepTraceExtra;
|
|
14092
14707
|
exports.avatarColor = avatarColor;
|
|
14093
14708
|
exports.blueScope = blueScope;
|
|
14094
14709
|
exports.buildClaimsGraph = buildClaimsGraph;
|
|
@@ -14141,3 +14756,4 @@ exports.useScopedProgressEvent = useScopedProgressEvent;
|
|
|
14141
14756
|
exports.useSlashMentionPicker = useSlashMentionPicker;
|
|
14142
14757
|
exports.useTheme = useTheme;
|
|
14143
14758
|
exports.warmBg = warmBg;
|
|
14759
|
+
exports.withStallTimeout = withStallTimeout;
|