@yieldfabric/terminal 1.0.0 → 1.1.0

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