@pgege/kaboo-react 0.1.0 → 0.2.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/AGENTS.md +3 -3
- package/CHANGELOG.md +36 -3
- package/README.md +58 -0
- package/dist/{chunk-RXZWOBSI.js → chunk-4TDUEMK5.js} +175 -2
- package/dist/chunk-4TDUEMK5.js.map +1 -0
- package/dist/copilotkit.cjs +158 -26
- package/dist/copilotkit.cjs.map +1 -1
- package/dist/copilotkit.d.cts +17 -2
- package/dist/copilotkit.d.ts +17 -2
- package/dist/copilotkit.js +118 -7
- package/dist/copilotkit.js.map +1 -1
- package/dist/index.cjs +1110 -35
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +324 -4
- package/dist/index.d.ts +324 -4
- package/dist/index.js +951 -30
- package/dist/index.js.map +1 -1
- package/dist/styles.css +319 -0
- package/llms-full.txt +93 -5
- package/package.json +1 -1
- package/dist/chunk-RXZWOBSI.js.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -30,20 +30,38 @@ __export(src_exports, {
|
|
|
30
30
|
InterruptRenderer: () => InterruptRenderer,
|
|
31
31
|
KabooActivityProvider: () => KabooActivityProvider,
|
|
32
32
|
KabooProvider: () => KabooProvider,
|
|
33
|
+
KabooReferenceInput: () => KabooReferenceInput,
|
|
33
34
|
MarkdownContent: () => MarkdownContent,
|
|
34
35
|
MiniTable: () => MiniTable,
|
|
36
|
+
REFERENCES_STATE_KEY: () => REFERENCES_STATE_KEY,
|
|
37
|
+
REFERENCE_METADATA_KEYS: () => REFERENCE_METADATA_KEYS,
|
|
38
|
+
ReferenceStateSync: () => ReferenceStateSync,
|
|
39
|
+
ReferencesProvider: () => ReferencesProvider,
|
|
35
40
|
StructuredRenderersContext: () => StructuredRenderersContext,
|
|
36
41
|
Timeline: () => Timeline,
|
|
37
42
|
ToolRow: () => ToolRow,
|
|
43
|
+
UPLOAD_MARKER: () => UPLOAD_MARKER,
|
|
44
|
+
attachmentToInputContent: () => attachmentToInputContent,
|
|
45
|
+
buildAttachmentsConfig: () => buildAttachmentsConfig,
|
|
46
|
+
buildUserContent: () => buildUserContent,
|
|
38
47
|
directChildren: () => directChildren,
|
|
39
48
|
formatToolInput: () => formatToolInput,
|
|
40
49
|
formatToolResult: () => formatToolResult,
|
|
50
|
+
isUploadProvider: () => isUploadProvider,
|
|
51
|
+
mintReferenceId: () => mintReferenceId,
|
|
41
52
|
normalizeResult: () => normalizeResult,
|
|
53
|
+
objectToStateEntry: () => objectToStateEntry,
|
|
54
|
+
referenceMarker: () => referenceMarker,
|
|
55
|
+
serializeReferences: () => serializeReferences,
|
|
42
56
|
topLevelGroups: () => topLevelGroups,
|
|
57
|
+
uploadFileToReference: () => uploadFileToReference,
|
|
58
|
+
uploadProvider: () => uploadProvider,
|
|
43
59
|
useActivity: () => useActivity,
|
|
44
60
|
useDrill: () => useDrill,
|
|
45
61
|
useInterruptBridge: () => useInterruptBridge,
|
|
46
|
-
useInterruptFor: () => useInterruptFor
|
|
62
|
+
useInterruptFor: () => useInterruptFor,
|
|
63
|
+
useReferences: () => useReferences,
|
|
64
|
+
withReferenceState: () => withReferenceState
|
|
47
65
|
});
|
|
48
66
|
module.exports = __toCommonJS(src_exports);
|
|
49
67
|
|
|
@@ -101,7 +119,7 @@ function DrillProvider({ children }) {
|
|
|
101
119
|
}
|
|
102
120
|
|
|
103
121
|
// src/context/KabooProvider.tsx
|
|
104
|
-
var
|
|
122
|
+
var import_v27 = require("@copilotkit/react-core/v2");
|
|
105
123
|
|
|
106
124
|
// src/context/InterruptBridge.tsx
|
|
107
125
|
var import_react3 = require("react");
|
|
@@ -1191,8 +1209,164 @@ function InlineCardRenderer({
|
|
|
1191
1209
|
);
|
|
1192
1210
|
}
|
|
1193
1211
|
|
|
1194
|
-
// src/
|
|
1212
|
+
// src/references/ReferencesProvider.tsx
|
|
1213
|
+
var import_react10 = require("react");
|
|
1214
|
+
var import_v26 = require("@copilotkit/react-core/v2");
|
|
1215
|
+
|
|
1216
|
+
// src/references/types.ts
|
|
1217
|
+
var REFERENCE_METADATA_KEYS = {
|
|
1218
|
+
/** Metadata key carrying the reference id. */
|
|
1219
|
+
id: "kaboo_id",
|
|
1220
|
+
/** Metadata key carrying the reference kind. */
|
|
1221
|
+
kind: "kaboo_kind",
|
|
1222
|
+
/** Metadata key carrying the reference display name. */
|
|
1223
|
+
name: "kaboo_name"
|
|
1224
|
+
};
|
|
1225
|
+
var REFERENCES_STATE_KEY = "kaboo_references";
|
|
1226
|
+
|
|
1227
|
+
// src/references/serialize.ts
|
|
1228
|
+
function mintReferenceId(kind) {
|
|
1229
|
+
const rand = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : Math.random().toString(36).slice(2);
|
|
1230
|
+
return `${kind}_${rand}`;
|
|
1231
|
+
}
|
|
1232
|
+
function referenceMarker(ref) {
|
|
1233
|
+
return `[${ref.kind}:${ref.id}]`;
|
|
1234
|
+
}
|
|
1235
|
+
function modalityFor(mimeType) {
|
|
1236
|
+
if (mimeType.startsWith("image/")) return "image";
|
|
1237
|
+
if (mimeType.startsWith("audio/")) return "audio";
|
|
1238
|
+
if (mimeType.startsWith("video/")) return "video";
|
|
1239
|
+
return "document";
|
|
1240
|
+
}
|
|
1241
|
+
function attachmentToInputContent(ref) {
|
|
1242
|
+
const source = "url" in ref.source ? { type: "url", value: ref.source.url, mimeType: ref.mimeType } : { type: "data", value: ref.source.data, mimeType: ref.mimeType };
|
|
1243
|
+
return {
|
|
1244
|
+
type: modalityFor(ref.mimeType),
|
|
1245
|
+
source,
|
|
1246
|
+
metadata: {
|
|
1247
|
+
[REFERENCE_METADATA_KEYS.id]: ref.id,
|
|
1248
|
+
[REFERENCE_METADATA_KEYS.kind]: ref.kind,
|
|
1249
|
+
[REFERENCE_METADATA_KEYS.name]: ref.name,
|
|
1250
|
+
filename: ref.name
|
|
1251
|
+
}
|
|
1252
|
+
};
|
|
1253
|
+
}
|
|
1254
|
+
function objectToStateEntry(ref) {
|
|
1255
|
+
return { kind: ref.kind, id: ref.id, name: ref.name, meta: ref.meta };
|
|
1256
|
+
}
|
|
1257
|
+
function serializeReferences(refs) {
|
|
1258
|
+
const attachmentParts = [];
|
|
1259
|
+
const objectReferences = [];
|
|
1260
|
+
for (const ref of refs) {
|
|
1261
|
+
if (ref.transport === "attachment") {
|
|
1262
|
+
attachmentParts.push(attachmentToInputContent(ref));
|
|
1263
|
+
} else {
|
|
1264
|
+
objectReferences.push(objectToStateEntry(ref));
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
return { attachmentParts, objectReferences };
|
|
1268
|
+
}
|
|
1269
|
+
function withReferenceState(state, objectReferences) {
|
|
1270
|
+
const next = { ...state ?? {} };
|
|
1271
|
+
if (objectReferences.length > 0) {
|
|
1272
|
+
next[REFERENCES_STATE_KEY] = objectReferences;
|
|
1273
|
+
} else {
|
|
1274
|
+
delete next[REFERENCES_STATE_KEY];
|
|
1275
|
+
}
|
|
1276
|
+
return next;
|
|
1277
|
+
}
|
|
1278
|
+
function buildUserContent(text, attachmentParts) {
|
|
1279
|
+
const parts = [];
|
|
1280
|
+
if (text.length > 0) parts.push({ type: "text", text });
|
|
1281
|
+
parts.push(...attachmentParts);
|
|
1282
|
+
return parts;
|
|
1283
|
+
}
|
|
1284
|
+
|
|
1285
|
+
// src/references/ReferencesProvider.tsx
|
|
1195
1286
|
var import_jsx_runtime15 = require("react/jsx-runtime");
|
|
1287
|
+
var ReferencesContext = (0, import_react10.createContext)({
|
|
1288
|
+
providers: [],
|
|
1289
|
+
pending: [],
|
|
1290
|
+
addReference: () => {
|
|
1291
|
+
},
|
|
1292
|
+
removeReference: () => {
|
|
1293
|
+
},
|
|
1294
|
+
clearReferences: () => {
|
|
1295
|
+
},
|
|
1296
|
+
messageReferences: {},
|
|
1297
|
+
recordMessageReferences: () => {
|
|
1298
|
+
}
|
|
1299
|
+
});
|
|
1300
|
+
function ReferencesProvider({
|
|
1301
|
+
providers = [],
|
|
1302
|
+
syncObjectStateTo = false,
|
|
1303
|
+
children
|
|
1304
|
+
}) {
|
|
1305
|
+
const [pending, setPending] = (0, import_react10.useState)([]);
|
|
1306
|
+
const [messageReferences, setMessageReferences] = (0, import_react10.useState)({});
|
|
1307
|
+
const addReference = (0, import_react10.useCallback)((ref) => {
|
|
1308
|
+
setPending(
|
|
1309
|
+
(prev) => prev.some((r) => r.id === ref.id) ? prev : [...prev, ref]
|
|
1310
|
+
);
|
|
1311
|
+
}, []);
|
|
1312
|
+
const removeReference = (0, import_react10.useCallback)((id) => {
|
|
1313
|
+
setPending((prev) => prev.filter((r) => r.id !== id));
|
|
1314
|
+
}, []);
|
|
1315
|
+
const clearReferences = (0, import_react10.useCallback)(() => setPending([]), []);
|
|
1316
|
+
const recordMessageReferences = (0, import_react10.useCallback)(
|
|
1317
|
+
(messageId, refs) => {
|
|
1318
|
+
if (refs.length === 0) return;
|
|
1319
|
+
setMessageReferences((prev) => ({ ...prev, [messageId]: refs }));
|
|
1320
|
+
},
|
|
1321
|
+
[]
|
|
1322
|
+
);
|
|
1323
|
+
const value = (0, import_react10.useMemo)(
|
|
1324
|
+
() => ({
|
|
1325
|
+
providers,
|
|
1326
|
+
pending,
|
|
1327
|
+
addReference,
|
|
1328
|
+
removeReference,
|
|
1329
|
+
clearReferences,
|
|
1330
|
+
messageReferences,
|
|
1331
|
+
recordMessageReferences
|
|
1332
|
+
}),
|
|
1333
|
+
[
|
|
1334
|
+
providers,
|
|
1335
|
+
pending,
|
|
1336
|
+
addReference,
|
|
1337
|
+
removeReference,
|
|
1338
|
+
clearReferences,
|
|
1339
|
+
messageReferences,
|
|
1340
|
+
recordMessageReferences
|
|
1341
|
+
]
|
|
1342
|
+
);
|
|
1343
|
+
return /* @__PURE__ */ (0, import_jsx_runtime15.jsxs)(ReferencesContext.Provider, { value, children: [
|
|
1344
|
+
syncObjectStateTo !== false && /* @__PURE__ */ (0, import_jsx_runtime15.jsx)(ReferenceStateSync, { agentId: syncObjectStateTo, pending }),
|
|
1345
|
+
children
|
|
1346
|
+
] });
|
|
1347
|
+
}
|
|
1348
|
+
function ReferenceStateSync({
|
|
1349
|
+
agentId,
|
|
1350
|
+
pending
|
|
1351
|
+
}) {
|
|
1352
|
+
const { agent } = (0, import_v26.useAgent)(agentId ? { agentId } : void 0);
|
|
1353
|
+
const objectRefs = (0, import_react10.useMemo)(
|
|
1354
|
+
() => pending.filter((r) => r.transport === "object").map(objectToStateEntry),
|
|
1355
|
+
[pending]
|
|
1356
|
+
);
|
|
1357
|
+
const key = JSON.stringify(objectRefs);
|
|
1358
|
+
(0, import_react10.useEffect)(() => {
|
|
1359
|
+
if (!agent || typeof agent.setState !== "function") return;
|
|
1360
|
+
agent.setState(withReferenceState(agent.state, objectRefs));
|
|
1361
|
+
}, [agent, key]);
|
|
1362
|
+
return null;
|
|
1363
|
+
}
|
|
1364
|
+
function useReferences() {
|
|
1365
|
+
return (0, import_react10.useContext)(ReferencesContext);
|
|
1366
|
+
}
|
|
1367
|
+
|
|
1368
|
+
// src/context/KabooProvider.tsx
|
|
1369
|
+
var import_jsx_runtime16 = require("react/jsx-runtime");
|
|
1196
1370
|
function KabooProvider({
|
|
1197
1371
|
runtimeUrl,
|
|
1198
1372
|
agent,
|
|
@@ -1201,28 +1375,911 @@ function KabooProvider({
|
|
|
1201
1375
|
interruptRenderers,
|
|
1202
1376
|
disableInterruptHandler = false,
|
|
1203
1377
|
disableInlineCards = false,
|
|
1378
|
+
references,
|
|
1204
1379
|
copilotKitProps,
|
|
1205
1380
|
children
|
|
1206
1381
|
}) {
|
|
1207
|
-
return /* @__PURE__ */ (0,
|
|
1208
|
-
|
|
1382
|
+
return /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(
|
|
1383
|
+
import_v27.CopilotKit,
|
|
1209
1384
|
{
|
|
1210
1385
|
runtimeUrl,
|
|
1211
1386
|
agent,
|
|
1212
1387
|
threadId,
|
|
1213
1388
|
useSingleEndpoint: false,
|
|
1214
1389
|
...copilotKitProps,
|
|
1215
|
-
children: /* @__PURE__ */ (0,
|
|
1216
|
-
!disableInterruptHandler && /* @__PURE__ */ (0,
|
|
1217
|
-
!disableInlineCards && /* @__PURE__ */ (0,
|
|
1390
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KabooActivityProvider, { agentId: agent, structuredRenderers, children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(DrillProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(InterruptBridgeProvider, { children: /* @__PURE__ */ (0, import_jsx_runtime16.jsxs)(ReferencesProvider, { providers: references, syncObjectStateTo: agent, children: [
|
|
1391
|
+
!disableInterruptHandler && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KabooInterruptHandler, { agentId: agent, renderers: interruptRenderers }),
|
|
1392
|
+
!disableInlineCards && /* @__PURE__ */ (0, import_jsx_runtime16.jsx)(KabooInlineCards, {}),
|
|
1218
1393
|
children
|
|
1219
|
-
] }) }) })
|
|
1394
|
+
] }) }) }) })
|
|
1395
|
+
}
|
|
1396
|
+
);
|
|
1397
|
+
}
|
|
1398
|
+
|
|
1399
|
+
// src/references/ReferenceInput.tsx
|
|
1400
|
+
var import_react11 = require("react");
|
|
1401
|
+
var import_react_dom = require("react-dom");
|
|
1402
|
+
var import_v28 = require("@copilotkit/react-core/v2");
|
|
1403
|
+
|
|
1404
|
+
// src/references/uploadProvider.tsx
|
|
1405
|
+
var UPLOAD_MARKER = "__kabooUpload";
|
|
1406
|
+
var DEFAULT_MAX_SIZE = 20 * 1024 * 1024;
|
|
1407
|
+
function readAsBase64(file) {
|
|
1408
|
+
return new Promise((resolve, reject) => {
|
|
1409
|
+
const reader = new FileReader();
|
|
1410
|
+
reader.onload = () => {
|
|
1411
|
+
const result = String(reader.result);
|
|
1412
|
+
const comma = result.indexOf(",");
|
|
1413
|
+
resolve(comma >= 0 ? result.slice(comma + 1) : result);
|
|
1414
|
+
};
|
|
1415
|
+
reader.onerror = () => reject(reader.error);
|
|
1416
|
+
reader.readAsDataURL(file);
|
|
1417
|
+
});
|
|
1418
|
+
}
|
|
1419
|
+
async function uploadFileToReference(file, config) {
|
|
1420
|
+
const kind = config.kind ?? "file";
|
|
1421
|
+
const id = mintReferenceId(kind);
|
|
1422
|
+
const maxSize = config.maxSize ?? DEFAULT_MAX_SIZE;
|
|
1423
|
+
if (file.size > maxSize) {
|
|
1424
|
+
throw new Error(`File "${file.name}" exceeds the ${maxSize}-byte limit.`);
|
|
1425
|
+
}
|
|
1426
|
+
if (config.onUpload) {
|
|
1427
|
+
const result = await config.onUpload(file);
|
|
1428
|
+
const mimeType = result.mimeType ?? file.type ?? "application/octet-stream";
|
|
1429
|
+
const source = result.type === "url" ? { url: result.value } : { data: result.value };
|
|
1430
|
+
return { transport: "attachment", kind, id, name: file.name, mimeType, source };
|
|
1431
|
+
}
|
|
1432
|
+
const data = await readAsBase64(file);
|
|
1433
|
+
return {
|
|
1434
|
+
transport: "attachment",
|
|
1435
|
+
kind,
|
|
1436
|
+
id,
|
|
1437
|
+
name: file.name,
|
|
1438
|
+
mimeType: file.type || "application/octet-stream",
|
|
1439
|
+
source: { data }
|
|
1440
|
+
};
|
|
1441
|
+
}
|
|
1442
|
+
function uploadProvider(config = {}) {
|
|
1443
|
+
return {
|
|
1444
|
+
id: config.id ?? "upload",
|
|
1445
|
+
label: config.label ?? "Upload",
|
|
1446
|
+
[UPLOAD_MARKER]: {
|
|
1447
|
+
kind: config.kind ?? "file",
|
|
1448
|
+
maxSize: config.maxSize ?? DEFAULT_MAX_SIZE,
|
|
1449
|
+
accept: config.accept,
|
|
1450
|
+
onUpload: config.onUpload
|
|
1451
|
+
}
|
|
1452
|
+
};
|
|
1453
|
+
}
|
|
1454
|
+
function isUploadProvider(provider) {
|
|
1455
|
+
return UPLOAD_MARKER in provider;
|
|
1456
|
+
}
|
|
1457
|
+
function buildAttachmentsConfig(config = {}) {
|
|
1458
|
+
const kind = config.kind ?? "file";
|
|
1459
|
+
return {
|
|
1460
|
+
enabled: true,
|
|
1461
|
+
accept: config.accept,
|
|
1462
|
+
maxSize: config.maxSize,
|
|
1463
|
+
onUpload: async (file) => {
|
|
1464
|
+
const id = mintReferenceId(kind);
|
|
1465
|
+
const kabooMeta = {
|
|
1466
|
+
[REFERENCE_METADATA_KEYS.id]: id,
|
|
1467
|
+
[REFERENCE_METADATA_KEYS.kind]: kind,
|
|
1468
|
+
[REFERENCE_METADATA_KEYS.name]: file.name
|
|
1469
|
+
};
|
|
1470
|
+
if (config.onUpload) {
|
|
1471
|
+
const result = await config.onUpload(file);
|
|
1472
|
+
return { ...result, metadata: { ...result.metadata ?? {}, ...kabooMeta } };
|
|
1473
|
+
}
|
|
1474
|
+
const value = await readAsBase64(file);
|
|
1475
|
+
return {
|
|
1476
|
+
type: "data",
|
|
1477
|
+
value,
|
|
1478
|
+
mimeType: file.type || "application/octet-stream",
|
|
1479
|
+
metadata: kabooMeta
|
|
1480
|
+
};
|
|
1481
|
+
}
|
|
1482
|
+
};
|
|
1483
|
+
}
|
|
1484
|
+
|
|
1485
|
+
// src/references/ReferenceInput.tsx
|
|
1486
|
+
var import_jsx_runtime17 = require("react/jsx-runtime");
|
|
1487
|
+
var CHIP_CLASS = "kaboo-chip";
|
|
1488
|
+
var NBSP = "\xA0";
|
|
1489
|
+
var AT_SVG = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="4"/><path d="M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94"/></svg>';
|
|
1490
|
+
var FILE_SVG = '<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8z"/><path d="M14 2v6h6"/></svg>';
|
|
1491
|
+
var X_SVG = '<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path d="M18 6 6 18M6 6l12 12"/></svg>';
|
|
1492
|
+
var AttachIcon = /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48" }) });
|
|
1493
|
+
var AtIcon = /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
1494
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "12", cy: "12", r: "4" }),
|
|
1495
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M16 8v5a3 3 0 0 0 6 0v-1a10 10 0 1 0-3.92 7.94" })
|
|
1496
|
+
] });
|
|
1497
|
+
var PlusIcon = /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { width: "18", height: "18", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M5 12h14M12 5v14" }) });
|
|
1498
|
+
var SearchIcon = /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("svg", { width: "15", height: "15", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: [
|
|
1499
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("circle", { cx: "11", cy: "11", r: "7" }),
|
|
1500
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "m21 21-4.3-4.3" })
|
|
1501
|
+
] });
|
|
1502
|
+
var POPOVER_WIDTH = 320;
|
|
1503
|
+
var VIEWPORT_MARGIN = 8;
|
|
1504
|
+
var ANCHOR_GAP = 6;
|
|
1505
|
+
function computePosition(rect) {
|
|
1506
|
+
if (!rect) return null;
|
|
1507
|
+
const width = Math.min(POPOVER_WIDTH, window.innerWidth - VIEWPORT_MARGIN * 2);
|
|
1508
|
+
const left = Math.max(
|
|
1509
|
+
VIEWPORT_MARGIN,
|
|
1510
|
+
Math.min(rect.left, window.innerWidth - width - VIEWPORT_MARGIN)
|
|
1511
|
+
);
|
|
1512
|
+
return { left, bottom: window.innerHeight - rect.top + ANCHOR_GAP, width };
|
|
1513
|
+
}
|
|
1514
|
+
function isImageMime(mime) {
|
|
1515
|
+
return mime.startsWith("image/");
|
|
1516
|
+
}
|
|
1517
|
+
function previewSrc(ref) {
|
|
1518
|
+
return "url" in ref.source ? ref.source.url : `data:${ref.mimeType};base64,${ref.source.data}`;
|
|
1519
|
+
}
|
|
1520
|
+
function serializeEditor(root) {
|
|
1521
|
+
let out = "";
|
|
1522
|
+
const walk = (node) => {
|
|
1523
|
+
if (node.nodeType === Node.TEXT_NODE) {
|
|
1524
|
+
out += node.textContent ?? "";
|
|
1525
|
+
return;
|
|
1526
|
+
}
|
|
1527
|
+
if (node instanceof HTMLElement) {
|
|
1528
|
+
if (node.classList.contains(CHIP_CLASS)) {
|
|
1529
|
+
const name = node.dataset.name ?? "";
|
|
1530
|
+
out += node.dataset.transport === "object" ? `@${name}` : name;
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
if (node.tagName === "BR") {
|
|
1534
|
+
out += "\n";
|
|
1535
|
+
return;
|
|
1536
|
+
}
|
|
1537
|
+
if (node.tagName === "DIV" && out.length > 0 && !out.endsWith("\n")) out += "\n";
|
|
1538
|
+
node.childNodes.forEach(walk);
|
|
1539
|
+
}
|
|
1540
|
+
};
|
|
1541
|
+
root.childNodes.forEach(walk);
|
|
1542
|
+
return out.replace(new RegExp(NBSP, "g"), " ");
|
|
1543
|
+
}
|
|
1544
|
+
function KabooReferenceInput({ trigger = "@", ...inputProps }) {
|
|
1545
|
+
const {
|
|
1546
|
+
providers,
|
|
1547
|
+
pending,
|
|
1548
|
+
addReference,
|
|
1549
|
+
removeReference,
|
|
1550
|
+
clearReferences,
|
|
1551
|
+
recordMessageReferences
|
|
1552
|
+
} = useReferences();
|
|
1553
|
+
const config = (0, import_v28.useCopilotChatConfiguration)();
|
|
1554
|
+
const configAgentId = config?.agentId;
|
|
1555
|
+
const { agent } = (0, import_v28.useAgent)(configAgentId ? { agentId: configAgentId } : void 0);
|
|
1556
|
+
const placeholder = config?.labels?.chatInputPlaceholder ?? "Type a message...";
|
|
1557
|
+
const wrapRef = (0, import_react11.useRef)(null);
|
|
1558
|
+
const trayRef = (0, import_react11.useRef)(null);
|
|
1559
|
+
const menuRef = (0, import_react11.useRef)(null);
|
|
1560
|
+
const editorRef = (0, import_react11.useRef)(null);
|
|
1561
|
+
const fileInputRef = (0, import_react11.useRef)(null);
|
|
1562
|
+
const addBtnRef = (0, import_react11.useRef)(null);
|
|
1563
|
+
const searchRef = (0, import_react11.useRef)(null);
|
|
1564
|
+
const nativeChangeRef = (0, import_react11.useRef)(void 0);
|
|
1565
|
+
const anchorRef = (0, import_react11.useRef)(() => null);
|
|
1566
|
+
const tokenRef = (0, import_react11.useRef)(null);
|
|
1567
|
+
const replacingRef = (0, import_react11.useRef)(null);
|
|
1568
|
+
const replacingTrayIdRef = (0, import_react11.useRef)(null);
|
|
1569
|
+
const inlineIdsRef = (0, import_react11.useRef)(/* @__PURE__ */ new Set());
|
|
1570
|
+
const commitTargetRef = (0, import_react11.useRef)("inline");
|
|
1571
|
+
const [open, setOpen] = (0, import_react11.useState)(false);
|
|
1572
|
+
const [rows, setRows] = (0, import_react11.useState)([]);
|
|
1573
|
+
const [active, setActive] = (0, import_react11.useState)(0);
|
|
1574
|
+
const [query, setQuery] = (0, import_react11.useState)("");
|
|
1575
|
+
const [mode, setMode] = (0, import_react11.useState)("token");
|
|
1576
|
+
const [pos, setPos] = (0, import_react11.useState)(null);
|
|
1577
|
+
const placeholderRef = (0, import_react11.useRef)(placeholder);
|
|
1578
|
+
placeholderRef.current = placeholder;
|
|
1579
|
+
const markEmpty = (0, import_react11.useCallback)(() => {
|
|
1580
|
+
const root = editorRef.current;
|
|
1581
|
+
if (!root) return;
|
|
1582
|
+
const isEmpty = root.querySelector(`.${CHIP_CLASS}`) === null && (root.textContent ?? "").trim().length === 0;
|
|
1583
|
+
root.dataset.empty = isEmpty ? "true" : "false";
|
|
1584
|
+
}, []);
|
|
1585
|
+
const uploadProviderDef = (0, import_react11.useMemo)(() => providers.find(isUploadProvider), [providers]);
|
|
1586
|
+
const searchable = (0, import_react11.useMemo)(() => providers.filter((p) => typeof p.search === "function"), [providers]);
|
|
1587
|
+
const actionProviders = (0, import_react11.useMemo)(
|
|
1588
|
+
() => providers.filter((p) => typeof p.search !== "function"),
|
|
1589
|
+
[providers]
|
|
1590
|
+
);
|
|
1591
|
+
const buildRows = (0, import_react11.useCallback)(
|
|
1592
|
+
async (q) => {
|
|
1593
|
+
const next = [];
|
|
1594
|
+
for (const provider of actionProviders) {
|
|
1595
|
+
const label = isUploadProvider(provider) ? "Attach" : provider.label;
|
|
1596
|
+
if (!q || label.toLowerCase().includes(q.toLowerCase())) {
|
|
1597
|
+
next.push({ kind: "action", group: label, provider });
|
|
1598
|
+
}
|
|
1599
|
+
}
|
|
1600
|
+
for (const provider of searchable) {
|
|
1601
|
+
try {
|
|
1602
|
+
const items = await provider.search(q);
|
|
1603
|
+
for (const item of items) next.push({ kind: "item", group: provider.label, provider, item });
|
|
1604
|
+
} catch {
|
|
1605
|
+
}
|
|
1606
|
+
}
|
|
1607
|
+
return next;
|
|
1608
|
+
},
|
|
1609
|
+
[actionProviders, searchable]
|
|
1610
|
+
);
|
|
1611
|
+
const refresh = (0, import_react11.useCallback)(
|
|
1612
|
+
async (q) => {
|
|
1613
|
+
const next = await buildRows(q);
|
|
1614
|
+
setRows(next);
|
|
1615
|
+
setActive(0);
|
|
1616
|
+
},
|
|
1617
|
+
[buildRows]
|
|
1618
|
+
);
|
|
1619
|
+
const close = (0, import_react11.useCallback)(() => {
|
|
1620
|
+
setOpen(false);
|
|
1621
|
+
setRows([]);
|
|
1622
|
+
setQuery("");
|
|
1623
|
+
tokenRef.current = null;
|
|
1624
|
+
replacingRef.current = null;
|
|
1625
|
+
replacingTrayIdRef.current = null;
|
|
1626
|
+
}, []);
|
|
1627
|
+
const emit = (0, import_react11.useCallback)(() => {
|
|
1628
|
+
const root = editorRef.current;
|
|
1629
|
+
if (!root) return;
|
|
1630
|
+
const text = serializeEditor(root);
|
|
1631
|
+
markEmpty();
|
|
1632
|
+
nativeChangeRef.current?.({ target: { value: text } });
|
|
1633
|
+
}, [markEmpty]);
|
|
1634
|
+
const reconcile = (0, import_react11.useCallback)(() => {
|
|
1635
|
+
const root = editorRef.current;
|
|
1636
|
+
if (!root) return;
|
|
1637
|
+
const live = new Set(
|
|
1638
|
+
Array.from(root.querySelectorAll(`.${CHIP_CLASS}`)).map((c) => c.dataset.refId)
|
|
1639
|
+
);
|
|
1640
|
+
for (const id of Array.from(inlineIdsRef.current)) {
|
|
1641
|
+
if (!live.has(id)) {
|
|
1642
|
+
inlineIdsRef.current.delete(id);
|
|
1643
|
+
removeReference(id);
|
|
1644
|
+
}
|
|
1645
|
+
}
|
|
1646
|
+
}, [removeReference]);
|
|
1647
|
+
const focusEditor = (0, import_react11.useCallback)(() => editorRef.current?.focus(), []);
|
|
1648
|
+
const createChip = (0, import_react11.useCallback)((ref) => {
|
|
1649
|
+
const chip = document.createElement("span");
|
|
1650
|
+
chip.className = `${CHIP_CLASS} ${CHIP_CLASS}-${ref.transport}`;
|
|
1651
|
+
chip.contentEditable = "false";
|
|
1652
|
+
chip.dataset.refId = ref.id;
|
|
1653
|
+
chip.dataset.kind = ref.kind;
|
|
1654
|
+
chip.dataset.name = ref.name;
|
|
1655
|
+
chip.dataset.transport = ref.transport;
|
|
1656
|
+
chip.title = ref.name;
|
|
1657
|
+
if (ref.transport === "attachment" && isImageMime(ref.mimeType)) {
|
|
1658
|
+
const img = document.createElement("img");
|
|
1659
|
+
img.className = "kaboo-chip-thumb";
|
|
1660
|
+
img.src = previewSrc(ref);
|
|
1661
|
+
img.alt = ref.name;
|
|
1662
|
+
chip.appendChild(img);
|
|
1663
|
+
} else {
|
|
1664
|
+
const ic = document.createElement("span");
|
|
1665
|
+
ic.className = "kaboo-chip-ic";
|
|
1666
|
+
ic.innerHTML = ref.transport === "object" ? AT_SVG : FILE_SVG;
|
|
1667
|
+
chip.appendChild(ic);
|
|
1668
|
+
}
|
|
1669
|
+
const label = document.createElement("span");
|
|
1670
|
+
label.className = "kaboo-chip-label";
|
|
1671
|
+
label.textContent = ref.name;
|
|
1672
|
+
chip.appendChild(label);
|
|
1673
|
+
const x = document.createElement("button");
|
|
1674
|
+
x.type = "button";
|
|
1675
|
+
x.className = "kaboo-chip-x";
|
|
1676
|
+
x.setAttribute("aria-label", `Remove ${ref.name}`);
|
|
1677
|
+
x.innerHTML = X_SVG;
|
|
1678
|
+
x.addEventListener("mousedown", (e) => {
|
|
1679
|
+
e.preventDefault();
|
|
1680
|
+
e.stopPropagation();
|
|
1681
|
+
handlersRef.current.removeChip(chip);
|
|
1682
|
+
});
|
|
1683
|
+
chip.appendChild(x);
|
|
1684
|
+
chip.addEventListener("mousedown", (e) => {
|
|
1685
|
+
if (e.target === x || x.contains(e.target)) return;
|
|
1686
|
+
e.preventDefault();
|
|
1687
|
+
handlersRef.current.replaceChip(chip);
|
|
1688
|
+
});
|
|
1689
|
+
return chip;
|
|
1690
|
+
}, []);
|
|
1691
|
+
const insertAtCaret = (0, import_react11.useCallback)((node) => {
|
|
1692
|
+
const root = editorRef.current;
|
|
1693
|
+
if (!root) return;
|
|
1694
|
+
const sel = window.getSelection();
|
|
1695
|
+
let range;
|
|
1696
|
+
if (sel && sel.rangeCount > 0 && root.contains(sel.focusNode)) {
|
|
1697
|
+
range = sel.getRangeAt(0);
|
|
1698
|
+
} else {
|
|
1699
|
+
range = document.createRange();
|
|
1700
|
+
range.selectNodeContents(root);
|
|
1701
|
+
range.collapse(false);
|
|
1702
|
+
}
|
|
1703
|
+
range.collapse(false);
|
|
1704
|
+
const space = document.createTextNode(NBSP);
|
|
1705
|
+
range.insertNode(space);
|
|
1706
|
+
range.insertNode(node);
|
|
1707
|
+
const after = document.createRange();
|
|
1708
|
+
after.setStartAfter(space);
|
|
1709
|
+
after.collapse(true);
|
|
1710
|
+
sel?.removeAllRanges();
|
|
1711
|
+
sel?.addRange(after);
|
|
1712
|
+
}, []);
|
|
1713
|
+
const placeChip = (0, import_react11.useCallback)(
|
|
1714
|
+
(ref) => {
|
|
1715
|
+
const chip = createChip(ref);
|
|
1716
|
+
const replacing = replacingRef.current;
|
|
1717
|
+
if (replacing) {
|
|
1718
|
+
const oldId = replacing.dataset.refId;
|
|
1719
|
+
if (oldId && oldId !== ref.id) removeReference(oldId);
|
|
1720
|
+
replacing.replaceWith(chip);
|
|
1721
|
+
replacingRef.current = null;
|
|
1722
|
+
} else if (tokenRef.current) {
|
|
1723
|
+
const { node, start } = tokenRef.current;
|
|
1724
|
+
const sel = window.getSelection();
|
|
1725
|
+
const range = document.createRange();
|
|
1726
|
+
range.setStart(node, Math.min(start, node.textContent?.length ?? 0));
|
|
1727
|
+
if (sel && sel.focusNode && editorRef.current?.contains(sel.focusNode)) {
|
|
1728
|
+
range.setEnd(sel.focusNode, sel.focusOffset);
|
|
1729
|
+
} else {
|
|
1730
|
+
range.setEnd(node, node.textContent?.length ?? 0);
|
|
1731
|
+
}
|
|
1732
|
+
range.deleteContents();
|
|
1733
|
+
const space = document.createTextNode(NBSP);
|
|
1734
|
+
range.insertNode(space);
|
|
1735
|
+
range.insertNode(chip);
|
|
1736
|
+
const after = document.createRange();
|
|
1737
|
+
after.setStartAfter(space);
|
|
1738
|
+
after.collapse(true);
|
|
1739
|
+
sel?.removeAllRanges();
|
|
1740
|
+
sel?.addRange(after);
|
|
1741
|
+
tokenRef.current = null;
|
|
1742
|
+
} else {
|
|
1743
|
+
insertAtCaret(chip);
|
|
1744
|
+
}
|
|
1745
|
+
emit();
|
|
1746
|
+
},
|
|
1747
|
+
[createChip, insertAtCaret, removeReference, emit]
|
|
1748
|
+
);
|
|
1749
|
+
const commit = (0, import_react11.useCallback)(
|
|
1750
|
+
(ref, target) => {
|
|
1751
|
+
addReference(ref);
|
|
1752
|
+
if (target === "inline") {
|
|
1753
|
+
inlineIdsRef.current.add(ref.id);
|
|
1754
|
+
placeChip(ref);
|
|
1755
|
+
} else {
|
|
1756
|
+
const oldId = replacingTrayIdRef.current;
|
|
1757
|
+
if (oldId && oldId !== ref.id) removeReference(oldId);
|
|
1758
|
+
replacingTrayIdRef.current = null;
|
|
1759
|
+
inlineIdsRef.current.delete(ref.id);
|
|
1760
|
+
}
|
|
1761
|
+
},
|
|
1762
|
+
[addReference, placeChip, removeReference]
|
|
1763
|
+
);
|
|
1764
|
+
const openFilePicker = (0, import_react11.useCallback)(
|
|
1765
|
+
(provider, target) => {
|
|
1766
|
+
const input = fileInputRef.current;
|
|
1767
|
+
if (!input) return;
|
|
1768
|
+
const cfg = isUploadProvider(provider) ? provider[UPLOAD_MARKER] : {};
|
|
1769
|
+
input.accept = cfg.accept ?? "";
|
|
1770
|
+
input.onchange = async () => {
|
|
1771
|
+
const file = input.files?.[0];
|
|
1772
|
+
input.value = "";
|
|
1773
|
+
if (!file) return;
|
|
1774
|
+
try {
|
|
1775
|
+
const ref = await uploadFileToReference(file, cfg);
|
|
1776
|
+
commit(ref, target);
|
|
1777
|
+
} catch (err) {
|
|
1778
|
+
console.error("[kaboo] upload failed", err);
|
|
1779
|
+
}
|
|
1780
|
+
};
|
|
1781
|
+
input.click();
|
|
1782
|
+
},
|
|
1783
|
+
[commit]
|
|
1784
|
+
);
|
|
1785
|
+
const stripToken = (0, import_react11.useCallback)(() => {
|
|
1786
|
+
const t = tokenRef.current;
|
|
1787
|
+
if (!t) return;
|
|
1788
|
+
const sel = window.getSelection();
|
|
1789
|
+
const range = document.createRange();
|
|
1790
|
+
range.setStart(t.node, Math.min(t.start, t.node.textContent?.length ?? 0));
|
|
1791
|
+
if (sel?.focusNode && editorRef.current?.contains(sel.focusNode)) {
|
|
1792
|
+
range.setEnd(sel.focusNode, sel.focusOffset);
|
|
1793
|
+
} else {
|
|
1794
|
+
range.setEnd(t.node, t.node.textContent?.length ?? 0);
|
|
1220
1795
|
}
|
|
1796
|
+
range.deleteContents();
|
|
1797
|
+
emit();
|
|
1798
|
+
}, [emit]);
|
|
1799
|
+
const select = (0, import_react11.useCallback)(
|
|
1800
|
+
async (row) => {
|
|
1801
|
+
const target = commitTargetRef.current;
|
|
1802
|
+
if (row.kind === "action") {
|
|
1803
|
+
const provider = row.provider;
|
|
1804
|
+
if (target === "inline") stripToken();
|
|
1805
|
+
close();
|
|
1806
|
+
if (isUploadProvider(provider)) openFilePicker(provider, target);
|
|
1807
|
+
else await provider.onSelect?.({ id: provider.id, label: provider.label });
|
|
1808
|
+
focusEditor();
|
|
1809
|
+
return;
|
|
1810
|
+
}
|
|
1811
|
+
await row.provider.onSelect?.(row.item);
|
|
1812
|
+
const ref = row.provider.toReference?.(row.item);
|
|
1813
|
+
if (ref) commit(ref, target);
|
|
1814
|
+
close();
|
|
1815
|
+
focusEditor();
|
|
1816
|
+
},
|
|
1817
|
+
[stripToken, close, openFilePicker, focusEditor, commit]
|
|
1818
|
+
);
|
|
1819
|
+
const openFromToken = (0, import_react11.useCallback)(
|
|
1820
|
+
(q) => {
|
|
1821
|
+
commitTargetRef.current = "inline";
|
|
1822
|
+
replacingRef.current = null;
|
|
1823
|
+
replacingTrayIdRef.current = null;
|
|
1824
|
+
anchorRef.current = () => {
|
|
1825
|
+
const t = tokenRef.current;
|
|
1826
|
+
return t ? caretRectFor(t.node, t.start) : null;
|
|
1827
|
+
};
|
|
1828
|
+
setMode("token");
|
|
1829
|
+
setQuery(q);
|
|
1830
|
+
setPos(computePosition(anchorRef.current()));
|
|
1831
|
+
setOpen(true);
|
|
1832
|
+
void refresh(q);
|
|
1833
|
+
},
|
|
1834
|
+
[refresh]
|
|
1835
|
+
);
|
|
1836
|
+
const toggleFromButton = (0, import_react11.useCallback)(() => {
|
|
1837
|
+
setOpen((prev) => {
|
|
1838
|
+
if (prev) {
|
|
1839
|
+
close();
|
|
1840
|
+
return false;
|
|
1841
|
+
}
|
|
1842
|
+
commitTargetRef.current = "tray";
|
|
1843
|
+
tokenRef.current = null;
|
|
1844
|
+
replacingRef.current = null;
|
|
1845
|
+
replacingTrayIdRef.current = null;
|
|
1846
|
+
anchorRef.current = () => addBtnRef.current?.getBoundingClientRect() ?? null;
|
|
1847
|
+
setMode("menu");
|
|
1848
|
+
setQuery("");
|
|
1849
|
+
setPos(computePosition(anchorRef.current()));
|
|
1850
|
+
void refresh("");
|
|
1851
|
+
return true;
|
|
1852
|
+
});
|
|
1853
|
+
}, [refresh, close]);
|
|
1854
|
+
const onSearch = (0, import_react11.useCallback)(
|
|
1855
|
+
(value) => {
|
|
1856
|
+
setQuery(value);
|
|
1857
|
+
void refresh(value);
|
|
1858
|
+
},
|
|
1859
|
+
[refresh]
|
|
1221
1860
|
);
|
|
1861
|
+
const handleNavKey = (0, import_react11.useCallback)(
|
|
1862
|
+
(e) => {
|
|
1863
|
+
if (!open || rows.length === 0) return false;
|
|
1864
|
+
if (e.key === "ArrowDown") {
|
|
1865
|
+
e.preventDefault();
|
|
1866
|
+
setActive((a) => (a + 1) % rows.length);
|
|
1867
|
+
return true;
|
|
1868
|
+
}
|
|
1869
|
+
if (e.key === "ArrowUp") {
|
|
1870
|
+
e.preventDefault();
|
|
1871
|
+
setActive((a) => (a - 1 + rows.length) % rows.length);
|
|
1872
|
+
return true;
|
|
1873
|
+
}
|
|
1874
|
+
if (e.key === "Enter" || e.key === "Tab") {
|
|
1875
|
+
e.preventDefault();
|
|
1876
|
+
void select(rows[active]);
|
|
1877
|
+
return true;
|
|
1878
|
+
}
|
|
1879
|
+
if (e.key === "Escape") {
|
|
1880
|
+
e.preventDefault();
|
|
1881
|
+
close();
|
|
1882
|
+
focusEditor();
|
|
1883
|
+
return true;
|
|
1884
|
+
}
|
|
1885
|
+
return false;
|
|
1886
|
+
},
|
|
1887
|
+
[open, rows, active, select, close, focusEditor]
|
|
1888
|
+
);
|
|
1889
|
+
const replaceChip = (0, import_react11.useCallback)(
|
|
1890
|
+
(chip) => {
|
|
1891
|
+
commitTargetRef.current = "inline";
|
|
1892
|
+
replacingRef.current = chip;
|
|
1893
|
+
replacingTrayIdRef.current = null;
|
|
1894
|
+
tokenRef.current = null;
|
|
1895
|
+
anchorRef.current = () => chip.getBoundingClientRect();
|
|
1896
|
+
setMode("menu");
|
|
1897
|
+
setQuery("");
|
|
1898
|
+
setPos(computePosition(chip.getBoundingClientRect()));
|
|
1899
|
+
setOpen(true);
|
|
1900
|
+
void refresh("");
|
|
1901
|
+
},
|
|
1902
|
+
[refresh]
|
|
1903
|
+
);
|
|
1904
|
+
const replaceTrayChip = (0, import_react11.useCallback)(
|
|
1905
|
+
(id, anchorEl) => {
|
|
1906
|
+
commitTargetRef.current = "tray";
|
|
1907
|
+
replacingTrayIdRef.current = id;
|
|
1908
|
+
replacingRef.current = null;
|
|
1909
|
+
tokenRef.current = null;
|
|
1910
|
+
anchorRef.current = () => anchorEl.getBoundingClientRect();
|
|
1911
|
+
setMode("menu");
|
|
1912
|
+
setQuery("");
|
|
1913
|
+
setPos(computePosition(anchorEl.getBoundingClientRect()));
|
|
1914
|
+
setOpen(true);
|
|
1915
|
+
void refresh("");
|
|
1916
|
+
},
|
|
1917
|
+
[refresh]
|
|
1918
|
+
);
|
|
1919
|
+
const removeChip = (0, import_react11.useCallback)(
|
|
1920
|
+
(chip) => {
|
|
1921
|
+
const id = chip.dataset.refId;
|
|
1922
|
+
const next = chip.nextSibling;
|
|
1923
|
+
chip.remove();
|
|
1924
|
+
if (next && next.nodeType === Node.TEXT_NODE && next.textContent === NBSP) next.remove();
|
|
1925
|
+
if (id) {
|
|
1926
|
+
inlineIdsRef.current.delete(id);
|
|
1927
|
+
removeReference(id);
|
|
1928
|
+
}
|
|
1929
|
+
emit();
|
|
1930
|
+
focusEditor();
|
|
1931
|
+
},
|
|
1932
|
+
[removeReference, emit, focusEditor]
|
|
1933
|
+
);
|
|
1934
|
+
const handlersRef = (0, import_react11.useRef)({ removeChip, replaceChip });
|
|
1935
|
+
handlersRef.current = { removeChip, replaceChip };
|
|
1936
|
+
const ctl = { open, rows, active, trigger, openFromToken, toggleFromButton, close, handleNavKey };
|
|
1937
|
+
const ctlRef = (0, import_react11.useRef)(ctl);
|
|
1938
|
+
ctlRef.current = ctl;
|
|
1939
|
+
const readToken = (0, import_react11.useCallback)(() => {
|
|
1940
|
+
const sel = window.getSelection();
|
|
1941
|
+
if (!sel || sel.rangeCount === 0 || !sel.isCollapsed) return null;
|
|
1942
|
+
const node = sel.focusNode;
|
|
1943
|
+
if (!node || node.nodeType !== Node.TEXT_NODE) return null;
|
|
1944
|
+
const text = node.textContent ?? "";
|
|
1945
|
+
const before = text.slice(0, sel.focusOffset);
|
|
1946
|
+
const at = before.lastIndexOf(ctlRef.current.trigger);
|
|
1947
|
+
if (at < 0) return null;
|
|
1948
|
+
const prev = at > 0 ? before[at - 1] : "";
|
|
1949
|
+
if (prev && !/\s/.test(prev)) return null;
|
|
1950
|
+
const q = before.slice(at + 1);
|
|
1951
|
+
if (/\s/.test(q)) return null;
|
|
1952
|
+
return { node, start: at, query: q };
|
|
1953
|
+
}, []);
|
|
1954
|
+
const onEditorInput = (0, import_react11.useCallback)(() => {
|
|
1955
|
+
reconcile();
|
|
1956
|
+
emit();
|
|
1957
|
+
const token = readToken();
|
|
1958
|
+
if (token) {
|
|
1959
|
+
tokenRef.current = { node: token.node, start: token.start };
|
|
1960
|
+
const c = ctlRef.current;
|
|
1961
|
+
if (!c.open || mode === "token") openFromToken(token.query);
|
|
1962
|
+
else {
|
|
1963
|
+
setQuery(token.query);
|
|
1964
|
+
void refresh(token.query);
|
|
1965
|
+
}
|
|
1966
|
+
} else if (ctlRef.current.open && mode === "token") {
|
|
1967
|
+
close();
|
|
1968
|
+
}
|
|
1969
|
+
}, [reconcile, emit, readToken, openFromToken, refresh, mode, close]);
|
|
1970
|
+
const TextAreaSlot = (0, import_react11.useMemo)(
|
|
1971
|
+
() => (0, import_react11.forwardRef)(function KabooRefEditor(props, ref) {
|
|
1972
|
+
const { onChange, onKeyDown, className, autoFocus } = props;
|
|
1973
|
+
nativeChangeRef.current = onChange;
|
|
1974
|
+
const setRefs = (node) => {
|
|
1975
|
+
editorRef.current = node;
|
|
1976
|
+
if (typeof ref === "function") ref(node);
|
|
1977
|
+
else if (ref) ref.current = node;
|
|
1978
|
+
};
|
|
1979
|
+
const handleKeyDown = (e) => {
|
|
1980
|
+
if (ctlRef.current.handleNavKey(e)) return;
|
|
1981
|
+
onKeyDown?.(e);
|
|
1982
|
+
};
|
|
1983
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
1984
|
+
"div",
|
|
1985
|
+
{
|
|
1986
|
+
ref: setRefs,
|
|
1987
|
+
role: "textbox",
|
|
1988
|
+
"aria-multiline": "true",
|
|
1989
|
+
tabIndex: 0,
|
|
1990
|
+
contentEditable: true,
|
|
1991
|
+
suppressContentEditableWarning: true,
|
|
1992
|
+
"data-placeholder": placeholderRef.current,
|
|
1993
|
+
className: `kaboo-ref-editor cpk:bg-transparent cpk:outline-none cpk:antialiased cpk:leading-relaxed cpk:text-[16px] ${className ?? ""}`,
|
|
1994
|
+
"data-empty": "true",
|
|
1995
|
+
autoFocus,
|
|
1996
|
+
onInput: onEditorInput,
|
|
1997
|
+
onKeyDown: handleKeyDown
|
|
1998
|
+
}
|
|
1999
|
+
);
|
|
2000
|
+
}),
|
|
2001
|
+
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
2002
|
+
[]
|
|
2003
|
+
);
|
|
2004
|
+
const AddMenuButtonSlot = (0, import_react11.useMemo)(
|
|
2005
|
+
() => function KabooRefAddButton(props) {
|
|
2006
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2007
|
+
"button",
|
|
2008
|
+
{
|
|
2009
|
+
ref: addBtnRef,
|
|
2010
|
+
type: "button",
|
|
2011
|
+
className: "kaboo-ref-add",
|
|
2012
|
+
"aria-label": "Add attachment or reference",
|
|
2013
|
+
"aria-haspopup": "listbox",
|
|
2014
|
+
"aria-expanded": ctlRef.current.open,
|
|
2015
|
+
disabled: props.disabled,
|
|
2016
|
+
onMouseDown: (e) => e.preventDefault(),
|
|
2017
|
+
onClick: () => ctlRef.current.toggleFromButton(),
|
|
2018
|
+
children: PlusIcon
|
|
2019
|
+
}
|
|
2020
|
+
);
|
|
2021
|
+
},
|
|
2022
|
+
[]
|
|
2023
|
+
);
|
|
2024
|
+
(0, import_react11.useEffect)(() => {
|
|
2025
|
+
if (!open) return;
|
|
2026
|
+
const onDocMouseDown = (e) => {
|
|
2027
|
+
const target = e.target;
|
|
2028
|
+
if (wrapRef.current?.contains(target) || menuRef.current?.contains(target)) return;
|
|
2029
|
+
close();
|
|
2030
|
+
};
|
|
2031
|
+
const onDocKey = (e) => {
|
|
2032
|
+
if (e.key === "Escape") close();
|
|
2033
|
+
};
|
|
2034
|
+
document.addEventListener("mousedown", onDocMouseDown);
|
|
2035
|
+
document.addEventListener("keydown", onDocKey);
|
|
2036
|
+
return () => {
|
|
2037
|
+
document.removeEventListener("mousedown", onDocMouseDown);
|
|
2038
|
+
document.removeEventListener("keydown", onDocKey);
|
|
2039
|
+
};
|
|
2040
|
+
}, [open, close]);
|
|
2041
|
+
(0, import_react11.useEffect)(() => {
|
|
2042
|
+
if (!open) return;
|
|
2043
|
+
const reposition = () => setPos(computePosition(anchorRef.current()));
|
|
2044
|
+
window.addEventListener("resize", reposition);
|
|
2045
|
+
window.addEventListener("scroll", reposition, true);
|
|
2046
|
+
return () => {
|
|
2047
|
+
window.removeEventListener("resize", reposition);
|
|
2048
|
+
window.removeEventListener("scroll", reposition, true);
|
|
2049
|
+
};
|
|
2050
|
+
}, [open]);
|
|
2051
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
2052
|
+
if (!open) return;
|
|
2053
|
+
setPos(computePosition(anchorRef.current()));
|
|
2054
|
+
if (mode === "menu") searchRef.current?.focus();
|
|
2055
|
+
}, [open, mode, rows.length]);
|
|
2056
|
+
(0, import_react11.useEffect)(() => {
|
|
2057
|
+
const target = agent;
|
|
2058
|
+
if (!target || typeof target.subscribe !== "function") return;
|
|
2059
|
+
const sub = target.subscribe({ onRunStartedEvent: () => clearReferences() });
|
|
2060
|
+
return () => sub?.unsubscribe?.();
|
|
2061
|
+
}, [agent, clearReferences]);
|
|
2062
|
+
(0, import_react11.useEffect)(() => {
|
|
2063
|
+
const root = editorRef.current;
|
|
2064
|
+
if (!root) return;
|
|
2065
|
+
if ((inputProps.value ?? "") === "" && root.childNodes.length > 0) {
|
|
2066
|
+
root.textContent = "";
|
|
2067
|
+
markEmpty();
|
|
2068
|
+
}
|
|
2069
|
+
}, [inputProps.value, markEmpty]);
|
|
2070
|
+
const handleSubmit = (0, import_react11.useCallback)(
|
|
2071
|
+
(message) => {
|
|
2072
|
+
const text = message.trim();
|
|
2073
|
+
const { attachmentParts } = serializeReferences(pending);
|
|
2074
|
+
const target = agent;
|
|
2075
|
+
if (text.length === 0 && attachmentParts.length === 0) return;
|
|
2076
|
+
if (!target?.addMessage || !target.runAgent) {
|
|
2077
|
+
inputProps.onSubmitMessage?.(message);
|
|
2078
|
+
close();
|
|
2079
|
+
return;
|
|
2080
|
+
}
|
|
2081
|
+
const content = attachmentParts.length > 0 ? buildUserContent(text, attachmentParts) : text;
|
|
2082
|
+
const id = typeof crypto !== "undefined" && "randomUUID" in crypto ? crypto.randomUUID() : Math.random().toString(36).slice(2);
|
|
2083
|
+
recordMessageReferences(
|
|
2084
|
+
id,
|
|
2085
|
+
pending.filter((r) => r.transport === "object")
|
|
2086
|
+
);
|
|
2087
|
+
target.addMessage({ id, role: "user", content });
|
|
2088
|
+
void Promise.resolve(target.runAgent()).catch(
|
|
2089
|
+
(err) => console.error("[kaboo] runAgent failed", err)
|
|
2090
|
+
);
|
|
2091
|
+
const root = editorRef.current;
|
|
2092
|
+
if (root) root.textContent = "";
|
|
2093
|
+
markEmpty();
|
|
2094
|
+
close();
|
|
2095
|
+
},
|
|
2096
|
+
[pending, agent, inputProps, close, markEmpty, recordMessageReferences]
|
|
2097
|
+
);
|
|
2098
|
+
const trayRefs = pending.filter((r) => !inlineIdsRef.current.has(r.id));
|
|
2099
|
+
(0, import_react11.useLayoutEffect)(() => {
|
|
2100
|
+
const tray = trayRef.current;
|
|
2101
|
+
const wrap = wrapRef.current;
|
|
2102
|
+
if (!tray || !wrap) return;
|
|
2103
|
+
const align = () => {
|
|
2104
|
+
const pill = wrap.querySelector(".copilotKitInput");
|
|
2105
|
+
if (!pill) return;
|
|
2106
|
+
const pr = pill.getBoundingClientRect();
|
|
2107
|
+
const wr = wrap.getBoundingClientRect();
|
|
2108
|
+
tray.style.marginLeft = `${Math.max(0, pr.left - wr.left)}px`;
|
|
2109
|
+
tray.style.width = `${pr.width}px`;
|
|
2110
|
+
};
|
|
2111
|
+
align();
|
|
2112
|
+
window.addEventListener("resize", align);
|
|
2113
|
+
return () => window.removeEventListener("resize", align);
|
|
2114
|
+
}, [trayRefs.length]);
|
|
2115
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { ref: wrapRef, className: "kaboo-ref-input", children: [
|
|
2116
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("input", { ref: fileInputRef, type: "file", className: "kaboo-ref-file", tabIndex: -1, "aria-hidden": "true" }),
|
|
2117
|
+
trayRefs.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { ref: trayRef, className: "kaboo-ref-tray", children: trayRefs.map((r) => /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2118
|
+
TrayChip,
|
|
2119
|
+
{
|
|
2120
|
+
reference: r,
|
|
2121
|
+
onRemove: () => removeReference(r.id),
|
|
2122
|
+
onReplace: (el) => replaceTrayChip(r.id, el)
|
|
2123
|
+
},
|
|
2124
|
+
r.id
|
|
2125
|
+
)) }),
|
|
2126
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2127
|
+
import_v28.CopilotChatInput,
|
|
2128
|
+
{
|
|
2129
|
+
...inputProps,
|
|
2130
|
+
onSubmitMessage: handleSubmit,
|
|
2131
|
+
textArea: TextAreaSlot,
|
|
2132
|
+
addMenuButton: AddMenuButtonSlot
|
|
2133
|
+
}
|
|
2134
|
+
),
|
|
2135
|
+
open && pos && (0, import_react_dom.createPortal)(
|
|
2136
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2137
|
+
ReferencePopover,
|
|
2138
|
+
{
|
|
2139
|
+
ref: menuRef,
|
|
2140
|
+
pos,
|
|
2141
|
+
rows,
|
|
2142
|
+
active,
|
|
2143
|
+
query,
|
|
2144
|
+
mode,
|
|
2145
|
+
searchRef,
|
|
2146
|
+
hasUpload: !!uploadProviderDef,
|
|
2147
|
+
onSearch,
|
|
2148
|
+
onSearchKeyDown: handleNavKey,
|
|
2149
|
+
onHover: setActive,
|
|
2150
|
+
onPick: select
|
|
2151
|
+
}
|
|
2152
|
+
),
|
|
2153
|
+
document.body
|
|
2154
|
+
)
|
|
2155
|
+
] });
|
|
2156
|
+
}
|
|
2157
|
+
function TrayChip({
|
|
2158
|
+
reference,
|
|
2159
|
+
onRemove,
|
|
2160
|
+
onReplace
|
|
2161
|
+
}) {
|
|
2162
|
+
const ref = (0, import_react11.useRef)(null);
|
|
2163
|
+
const isImage = reference.transport === "attachment" && isImageMime(reference.mimeType);
|
|
2164
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2165
|
+
"span",
|
|
2166
|
+
{
|
|
2167
|
+
ref,
|
|
2168
|
+
className: `kaboo-chip ${CHIP_CLASS}-${reference.transport} kaboo-chip-tray`,
|
|
2169
|
+
title: reference.name,
|
|
2170
|
+
role: "button",
|
|
2171
|
+
tabIndex: 0,
|
|
2172
|
+
onMouseDown: (e) => {
|
|
2173
|
+
e.preventDefault();
|
|
2174
|
+
if (ref.current) onReplace(ref.current);
|
|
2175
|
+
},
|
|
2176
|
+
children: [
|
|
2177
|
+
isImage ? /* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2178
|
+
"img",
|
|
2179
|
+
{
|
|
2180
|
+
className: "kaboo-chip-thumb",
|
|
2181
|
+
src: previewSrc(reference),
|
|
2182
|
+
alt: reference.name
|
|
2183
|
+
}
|
|
2184
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "kaboo-chip-ic", children: reference.transport === "object" ? AtIcon : AttachIcon }),
|
|
2185
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "kaboo-chip-label", children: reference.name }),
|
|
2186
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2187
|
+
"button",
|
|
2188
|
+
{
|
|
2189
|
+
type: "button",
|
|
2190
|
+
className: "kaboo-chip-x",
|
|
2191
|
+
"aria-label": `Remove ${reference.name}`,
|
|
2192
|
+
onMouseDown: (e) => {
|
|
2193
|
+
e.preventDefault();
|
|
2194
|
+
e.stopPropagation();
|
|
2195
|
+
onRemove();
|
|
2196
|
+
},
|
|
2197
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("svg", { width: "12", height: "12", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", "aria-hidden": "true", children: /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("path", { d: "M18 6 6 18M6 6l12 12" }) })
|
|
2198
|
+
}
|
|
2199
|
+
)
|
|
2200
|
+
]
|
|
2201
|
+
}
|
|
2202
|
+
);
|
|
2203
|
+
}
|
|
2204
|
+
function caretRectFor(node, offset) {
|
|
2205
|
+
try {
|
|
2206
|
+
const range = document.createRange();
|
|
2207
|
+
range.setStart(node, Math.min(offset, node.textContent?.length ?? 0));
|
|
2208
|
+
range.collapse(true);
|
|
2209
|
+
const rect = range.getBoundingClientRect();
|
|
2210
|
+
if (rect.top === 0 && rect.left === 0) {
|
|
2211
|
+
const parent = node.parentElement;
|
|
2212
|
+
return parent ? parent.getBoundingClientRect() : null;
|
|
2213
|
+
}
|
|
2214
|
+
return rect;
|
|
2215
|
+
} catch {
|
|
2216
|
+
return null;
|
|
2217
|
+
}
|
|
1222
2218
|
}
|
|
2219
|
+
var ReferencePopover = (0, import_react11.forwardRef)(function ReferencePopover2({ pos, rows, active, query, mode, searchRef, onSearch, onSearchKeyDown, onHover, onPick }, ref) {
|
|
2220
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2221
|
+
"div",
|
|
2222
|
+
{
|
|
2223
|
+
ref,
|
|
2224
|
+
className: "kaboo-refmenu",
|
|
2225
|
+
role: "listbox",
|
|
2226
|
+
style: { left: pos.left, bottom: pos.bottom, width: pos.width },
|
|
2227
|
+
children: [
|
|
2228
|
+
mode === "menu" && /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { className: "kaboo-refmenu-search", children: [
|
|
2229
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "kaboo-refmenu-search-icon", children: SearchIcon }),
|
|
2230
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)(
|
|
2231
|
+
"input",
|
|
2232
|
+
{
|
|
2233
|
+
ref: searchRef,
|
|
2234
|
+
type: "text",
|
|
2235
|
+
className: "kaboo-refmenu-search-input",
|
|
2236
|
+
placeholder: "Search\u2026",
|
|
2237
|
+
value: query,
|
|
2238
|
+
onChange: (e) => onSearch(e.target.value),
|
|
2239
|
+
onKeyDown: (e) => onSearchKeyDown(e)
|
|
2240
|
+
}
|
|
2241
|
+
)
|
|
2242
|
+
] }),
|
|
2243
|
+
rows.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "kaboo-refmenu-empty", children: "No matches" }),
|
|
2244
|
+
rows.map((row, i) => {
|
|
2245
|
+
const key = row.kind === "action" ? `action:${row.provider.id}` : `${row.provider.id}:${row.item.id}`;
|
|
2246
|
+
const showHeader = i === 0 || rows[i - 1].group !== row.group;
|
|
2247
|
+
const isUpload = row.kind === "action" && isUploadProvider(row.provider);
|
|
2248
|
+
const icon = isUpload ? AttachIcon : row.kind === "item" ? row.provider.icon ?? AtIcon : row.provider.icon ?? AtIcon;
|
|
2249
|
+
const title = row.kind === "action" ? isUpload ? "Attach a file" : row.provider.label : row.item.label;
|
|
2250
|
+
const subtitle = row.kind === "action" ? isUpload ? "Upload from your device" : void 0 : row.item.description;
|
|
2251
|
+
const custom = row.kind === "item" ? row.provider.renderItem?.(row.item) : void 0;
|
|
2252
|
+
return /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("div", { children: [
|
|
2253
|
+
showHeader && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("div", { className: "kaboo-refmenu-group", children: row.group }),
|
|
2254
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsxs)(
|
|
2255
|
+
"div",
|
|
2256
|
+
{
|
|
2257
|
+
role: "option",
|
|
2258
|
+
"aria-selected": i === active,
|
|
2259
|
+
className: `kaboo-refmenu-item${i === active ? " is-active" : ""}`,
|
|
2260
|
+
onMouseEnter: () => onHover(i),
|
|
2261
|
+
onMouseDown: (e) => {
|
|
2262
|
+
e.preventDefault();
|
|
2263
|
+
onPick(row);
|
|
2264
|
+
},
|
|
2265
|
+
children: [
|
|
2266
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "kaboo-refmenu-icon", children: icon }),
|
|
2267
|
+
custom ?? /* @__PURE__ */ (0, import_jsx_runtime17.jsxs)("span", { className: "kaboo-refmenu-text", children: [
|
|
2268
|
+
/* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "kaboo-refmenu-title", children: title }),
|
|
2269
|
+
subtitle && /* @__PURE__ */ (0, import_jsx_runtime17.jsx)("span", { className: "kaboo-refmenu-sub", children: subtitle })
|
|
2270
|
+
] })
|
|
2271
|
+
]
|
|
2272
|
+
}
|
|
2273
|
+
)
|
|
2274
|
+
] }, key);
|
|
2275
|
+
})
|
|
2276
|
+
]
|
|
2277
|
+
}
|
|
2278
|
+
);
|
|
2279
|
+
});
|
|
1223
2280
|
|
|
1224
2281
|
// src/components/ActivityPanel.tsx
|
|
1225
|
-
var
|
|
2282
|
+
var import_jsx_runtime18 = require("react/jsx-runtime");
|
|
1226
2283
|
function ActivityPanel() {
|
|
1227
2284
|
const { groups } = useActivity();
|
|
1228
2285
|
const { activeDrill } = useDrill();
|
|
@@ -1231,14 +2288,14 @@ function ActivityPanel() {
|
|
|
1231
2288
|
if (filtered.length === 0 && activeDrill) {
|
|
1232
2289
|
const exact = groups[activeDrill];
|
|
1233
2290
|
if (exact) {
|
|
1234
|
-
return /* @__PURE__ */ (0,
|
|
2291
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "kaboo-activity-panel", children: /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AgentCard, { groupId: activeDrill, group: exact }) });
|
|
1235
2292
|
}
|
|
1236
2293
|
}
|
|
1237
|
-
return /* @__PURE__ */ (0,
|
|
2294
|
+
return /* @__PURE__ */ (0, import_jsx_runtime18.jsx)("div", { className: "kaboo-activity-panel", children: filtered.map(([id, group]) => /* @__PURE__ */ (0, import_jsx_runtime18.jsx)(AgentCard, { groupId: id, group }, id)) });
|
|
1238
2295
|
}
|
|
1239
2296
|
|
|
1240
2297
|
// src/components/GlassTabs.tsx
|
|
1241
|
-
var
|
|
2298
|
+
var import_jsx_runtime19 = require("react/jsx-runtime");
|
|
1242
2299
|
function GlassTabs() {
|
|
1243
2300
|
const { drillPath, drillToRoot, drillToLevel } = useDrill();
|
|
1244
2301
|
const { groups } = useActivity();
|
|
@@ -1251,11 +2308,11 @@ function GlassTabs() {
|
|
|
1251
2308
|
level: i
|
|
1252
2309
|
}))
|
|
1253
2310
|
];
|
|
1254
|
-
return /* @__PURE__ */ (0,
|
|
2311
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("nav", { className: "kaboo-breadcrumb-bar", children: tabs.map((tab, i) => {
|
|
1255
2312
|
const isLast = i === tabs.length - 1;
|
|
1256
|
-
return /* @__PURE__ */ (0,
|
|
1257
|
-
i > 0 && /* @__PURE__ */ (0,
|
|
1258
|
-
/* @__PURE__ */ (0,
|
|
2313
|
+
return /* @__PURE__ */ (0, import_jsx_runtime19.jsxs)("span", { className: "kaboo-breadcrumb-item", children: [
|
|
2314
|
+
i > 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: 12, height: 12, viewBox: "0 0 16 16", className: "kaboo-breadcrumb-sep", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M6 4l4 4-4 4", fill: "none", stroke: "currentColor", strokeWidth: "1.5", strokeLinecap: "round" }) }),
|
|
2315
|
+
/* @__PURE__ */ (0, import_jsx_runtime19.jsxs)(
|
|
1259
2316
|
"button",
|
|
1260
2317
|
{
|
|
1261
2318
|
className: `kaboo-breadcrumb-link ${isLast ? "kaboo-breadcrumb-current" : ""}`,
|
|
@@ -1266,7 +2323,7 @@ function GlassTabs() {
|
|
|
1266
2323
|
},
|
|
1267
2324
|
disabled: isLast,
|
|
1268
2325
|
children: [
|
|
1269
|
-
i === 0 && /* @__PURE__ */ (0,
|
|
2326
|
+
i === 0 && /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("svg", { width: 14, height: 14, viewBox: "0 0 16 16", className: "kaboo-breadcrumb-icon", children: /* @__PURE__ */ (0, import_jsx_runtime19.jsx)("path", { d: "M3 8.5L8 4l5 4.5M4.5 7.5V12h2.5V9.5h2V12h2.5V7.5", fill: "none", stroke: "currentColor", strokeWidth: "1.2", strokeLinecap: "round", strokeLinejoin: "round" }) }),
|
|
1270
2327
|
tab.label
|
|
1271
2328
|
]
|
|
1272
2329
|
}
|
|
@@ -1276,20 +2333,20 @@ function GlassTabs() {
|
|
|
1276
2333
|
}
|
|
1277
2334
|
|
|
1278
2335
|
// src/components/DrillDetailView.tsx
|
|
1279
|
-
var
|
|
1280
|
-
var
|
|
2336
|
+
var import_react12 = require("react");
|
|
2337
|
+
var import_jsx_runtime20 = require("react/jsx-runtime");
|
|
1281
2338
|
function DrillDetailView() {
|
|
1282
2339
|
const { activeDrill } = useDrill();
|
|
1283
2340
|
const { groups } = useActivity();
|
|
1284
2341
|
const { active: activeInterrupts } = useInterruptBridge();
|
|
1285
|
-
const bodyRef = (0,
|
|
1286
|
-
(0,
|
|
2342
|
+
const bodyRef = (0, import_react12.useRef)(null);
|
|
2343
|
+
(0, import_react12.useEffect)(() => {
|
|
1287
2344
|
if (activeDrill && bodyRef.current) {
|
|
1288
2345
|
bodyRef.current.scrollTop = 0;
|
|
1289
2346
|
}
|
|
1290
2347
|
}, [activeDrill]);
|
|
1291
2348
|
if (!activeDrill) {
|
|
1292
|
-
return /* @__PURE__ */ (0,
|
|
2349
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "kaboo-drill-detail kaboo-hidden" });
|
|
1293
2350
|
}
|
|
1294
2351
|
const group = groups[activeDrill];
|
|
1295
2352
|
const timeline = group?.timeline ?? [];
|
|
@@ -1301,15 +2358,15 @@ function DrillDetailView() {
|
|
|
1301
2358
|
const renderToolCard = (toolUseId) => {
|
|
1302
2359
|
const entry = childByToolCall.get(toolUseId);
|
|
1303
2360
|
if (!entry) return null;
|
|
1304
|
-
return /* @__PURE__ */ (0,
|
|
2361
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AgentCard, { groupId: entry[0], group: entry[1] });
|
|
1305
2362
|
};
|
|
1306
|
-
return /* @__PURE__ */ (0,
|
|
1307
|
-
group?.task && /* @__PURE__ */ (0,
|
|
1308
|
-
/* @__PURE__ */ (0,
|
|
2363
|
+
return /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { ref: bodyRef, className: "kaboo-drill-detail", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "kaboo-drill-detail-inner", children: [
|
|
2364
|
+
group?.task && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "kaboo-agent-card-task kaboo-drill-task", children: [
|
|
2365
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("strong", { children: "Task:" }),
|
|
1309
2366
|
" ",
|
|
1310
2367
|
group.task
|
|
1311
2368
|
] }),
|
|
1312
|
-
group && timeline.length > 0 && /* @__PURE__ */ (0,
|
|
2369
|
+
group && timeline.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "kaboo-drill-timeline", children: /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1313
2370
|
Timeline,
|
|
1314
2371
|
{
|
|
1315
2372
|
timeline,
|
|
@@ -1318,7 +2375,7 @@ function DrillDetailView() {
|
|
|
1318
2375
|
renderToolCard
|
|
1319
2376
|
}
|
|
1320
2377
|
) }),
|
|
1321
|
-
unanchoredInterrupts.length > 0 && /* @__PURE__ */ (0,
|
|
2378
|
+
unanchoredInterrupts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "kaboo-drill-interrupt", children: unanchoredInterrupts.map((it) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(
|
|
1322
2379
|
InterruptRenderer,
|
|
1323
2380
|
{
|
|
1324
2381
|
reason: it.reason,
|
|
@@ -1328,12 +2385,12 @@ function DrillDetailView() {
|
|
|
1328
2385
|
},
|
|
1329
2386
|
it.id
|
|
1330
2387
|
)) }),
|
|
1331
|
-
leftoverChildren.length > 0 && /* @__PURE__ */ (0,
|
|
1332
|
-
/* @__PURE__ */ (0,
|
|
1333
|
-
leftoverChildren.map(([id, childGroup]) => /* @__PURE__ */ (0,
|
|
2388
|
+
leftoverChildren.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsxs)("div", { className: "kaboo-drill-children", children: [
|
|
2389
|
+
/* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "kaboo-drill-section-label", children: "Sub-agents" }),
|
|
2390
|
+
leftoverChildren.map(([id, childGroup]) => /* @__PURE__ */ (0, import_jsx_runtime20.jsx)(AgentCard, { groupId: id, group: childGroup }, id))
|
|
1334
2391
|
] }),
|
|
1335
|
-
group && timeline.length === 0 && childEntries.length === 0 && /* @__PURE__ */ (0,
|
|
1336
|
-
!group && /* @__PURE__ */ (0,
|
|
2392
|
+
group && timeline.length === 0 && childEntries.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "kaboo-agent-card-empty", children: "Working..." }),
|
|
2393
|
+
!group && /* @__PURE__ */ (0, import_jsx_runtime20.jsx)("div", { className: "kaboo-agent-card-empty", children: "No activity data for this group." })
|
|
1337
2394
|
] }) });
|
|
1338
2395
|
}
|
|
1339
2396
|
// Annotate the CommonJS export names for ESM import in node:
|
|
@@ -1348,19 +2405,37 @@ function DrillDetailView() {
|
|
|
1348
2405
|
InterruptRenderer,
|
|
1349
2406
|
KabooActivityProvider,
|
|
1350
2407
|
KabooProvider,
|
|
2408
|
+
KabooReferenceInput,
|
|
1351
2409
|
MarkdownContent,
|
|
1352
2410
|
MiniTable,
|
|
2411
|
+
REFERENCES_STATE_KEY,
|
|
2412
|
+
REFERENCE_METADATA_KEYS,
|
|
2413
|
+
ReferenceStateSync,
|
|
2414
|
+
ReferencesProvider,
|
|
1353
2415
|
StructuredRenderersContext,
|
|
1354
2416
|
Timeline,
|
|
1355
2417
|
ToolRow,
|
|
2418
|
+
UPLOAD_MARKER,
|
|
2419
|
+
attachmentToInputContent,
|
|
2420
|
+
buildAttachmentsConfig,
|
|
2421
|
+
buildUserContent,
|
|
1356
2422
|
directChildren,
|
|
1357
2423
|
formatToolInput,
|
|
1358
2424
|
formatToolResult,
|
|
2425
|
+
isUploadProvider,
|
|
2426
|
+
mintReferenceId,
|
|
1359
2427
|
normalizeResult,
|
|
2428
|
+
objectToStateEntry,
|
|
2429
|
+
referenceMarker,
|
|
2430
|
+
serializeReferences,
|
|
1360
2431
|
topLevelGroups,
|
|
2432
|
+
uploadFileToReference,
|
|
2433
|
+
uploadProvider,
|
|
1361
2434
|
useActivity,
|
|
1362
2435
|
useDrill,
|
|
1363
2436
|
useInterruptBridge,
|
|
1364
|
-
useInterruptFor
|
|
2437
|
+
useInterruptFor,
|
|
2438
|
+
useReferences,
|
|
2439
|
+
withReferenceState
|
|
1365
2440
|
});
|
|
1366
2441
|
//# sourceMappingURL=index.cjs.map
|