@truefoundry/trueforge-ui 0.3.0-rc.1 → 0.3.0-rc.3
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/CHANGELOG.md +70 -0
- package/README.md +22 -7
- package/dist/{AgentCodeSnippets-NZOFJE57.js → AgentCodeSnippets-N546FNNS.js} +38 -23
- package/dist/AgentCodeSnippets-N546FNNS.js.map +1 -0
- package/dist/AgentMetricChart-YWJYVYYA.js +15 -0
- package/dist/{AgentOverview-EEBHJC32.js → AgentOverview-VF74XC7I.js} +7 -7
- package/dist/{AgentSessionEventTimeline-26Z6IB3B.js → AgentSessionEventTimeline-RFR6LQMY.js} +19 -10
- package/dist/AgentSessionEventTimeline-RFR6LQMY.js.map +1 -0
- package/dist/{AgentSessionEventTimelineChart-CGCU7WBK.js → AgentSessionEventTimelineChart-27CQF6FX.js} +144 -57
- package/dist/AgentSessionEventTimelineChart-27CQF6FX.js.map +1 -0
- package/dist/{AgentSessions-3MPDZASK.js → AgentSessions-4IVX2SGD.js} +36 -12
- package/dist/AgentSessions-4IVX2SGD.js.map +1 -0
- package/dist/{ConnectorSettings-MXFRWWR6.js → ConnectorSettings-R5VEP7BO.js} +162 -126
- package/dist/ConnectorSettings-R5VEP7BO.js.map +1 -0
- package/dist/{DockLayout-LM4AFMFY.js → DockLayout-F44RWGEY.js} +10 -10
- package/dist/{DrawerLayout-JR3O6RRB.js → DrawerLayout-SQ323AVM.js} +14 -12
- package/dist/DrawerLayout-SQ323AVM.js.map +1 -0
- package/dist/{ModelSettings-G7IFNC2Y.js → ModelSettings-6QLS63HM.js} +22 -28
- package/dist/ModelSettings-6QLS63HM.js.map +1 -0
- package/dist/OpenUiFenceBlock-4ROX3G4X.js +9 -0
- package/dist/{SandboxSettings-NXAANMAX.js → SandboxSettings-OLKDXIQS.js} +17 -21
- package/dist/SandboxSettings-OLKDXIQS.js.map +1 -0
- package/dist/SchedulesPage-TMOTK6DR.js +15 -0
- package/dist/{SettingsBuilder-L34IQ56S.js → SettingsBuilder-GISAH2WU.js} +8 -8
- package/dist/{ShellRouteSync-CEBETGEJ.js → ShellRouteSync-EN33DUQ7.js} +171 -26
- package/dist/ShellRouteSync-EN33DUQ7.js.map +1 -0
- package/dist/{SidebarLayout-A2HJPPHS.js → SidebarLayout-35K4AKTC.js} +80 -58
- package/dist/SidebarLayout-35K4AKTC.js.map +1 -0
- package/dist/{SkillSettings-FGGMSUNO.js → SkillSettings-JSX2BTII.js} +24 -22
- package/dist/SkillSettings-JSX2BTII.js.map +1 -0
- package/dist/{TrueForgeUIWithRouter-MZVJWJMB.js → TrueForgeUIWithRouter-6VCR7ES3.js} +9 -9
- package/dist/{WidgetLayout-6QM45OQQ.js → WidgetLayout-RKBSN2FZ.js} +10 -10
- package/dist/{chunk-ZTMKFZQ3.js → chunk-2O5EJ6QS.js} +4440 -3042
- package/dist/chunk-2O5EJ6QS.js.map +1 -0
- package/dist/chunk-6WCIL3H2.js +517 -0
- package/dist/chunk-6WCIL3H2.js.map +1 -0
- package/dist/{chunk-WVE3F724.js → chunk-73FQVITT.js} +21 -4
- package/dist/chunk-73FQVITT.js.map +1 -0
- package/dist/{chunk-QC42MLAK.js → chunk-7AAO4UDQ.js} +4 -3
- package/dist/chunk-7AAO4UDQ.js.map +1 -0
- package/dist/{chunk-CYHJDKFB.js → chunk-F5QVQIBH.js} +172 -46
- package/dist/chunk-F5QVQIBH.js.map +1 -0
- package/dist/{chunk-FJW36PD7.js → chunk-GIPFF6FZ.js} +28 -24
- package/dist/chunk-GIPFF6FZ.js.map +1 -0
- package/dist/{chunk-6O6FWUDW.js → chunk-GSJAYYLR.js} +233 -195
- package/dist/chunk-GSJAYYLR.js.map +1 -0
- package/dist/{chunk-MPNSO7E6.js → chunk-J5BPHEDT.js} +2 -2
- package/dist/chunk-KR7WYHVF.js +195 -0
- package/dist/chunk-KR7WYHVF.js.map +1 -0
- package/dist/{chunk-DMMZSZTN.js → chunk-LUG7E6BL.js} +60 -16
- package/dist/chunk-LUG7E6BL.js.map +1 -0
- package/dist/chunk-LXJMINS6.js +587 -0
- package/dist/chunk-LXJMINS6.js.map +1 -0
- package/dist/{chunk-U7KURWW3.js → chunk-PT4EENB3.js} +244 -52
- package/dist/chunk-PT4EENB3.js.map +1 -0
- package/dist/{chunk-XAU7QFG3.js → chunk-Q6TCT7ZJ.js} +68 -256
- package/dist/chunk-Q6TCT7ZJ.js.map +1 -0
- package/dist/{chunk-ZKNUMH2M.js → chunk-XLFOXQKZ.js} +13 -11
- package/dist/chunk-XLFOXQKZ.js.map +1 -0
- package/dist/{chunk-M62XY4NC.js → chunk-XY6LZQES.js} +235 -108
- package/dist/chunk-XY6LZQES.js.map +1 -0
- package/dist/{createTrueFoundryServer-CmZnBh_l.d.ts → createTrueFoundryServer-B_FYhSdn.d.ts} +8 -5
- package/dist/index.d.ts +316 -94
- package/dist/index.js +65 -488
- package/dist/index.js.map +1 -1
- package/dist/plugins/trueforge-agent-server-adapter/index.d.ts +36 -13
- package/dist/plugins/trueforge-agent-server-adapter/index.js +69 -34
- package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +4 -4
- package/dist/AgentCodeSnippets-NZOFJE57.js.map +0 -1
- package/dist/AgentMetricChart-JPU3MFQ2.js +0 -15
- package/dist/AgentSessionEventTimeline-26Z6IB3B.js.map +0 -1
- package/dist/AgentSessionEventTimelineChart-CGCU7WBK.js.map +0 -1
- package/dist/AgentSessions-3MPDZASK.js.map +0 -1
- package/dist/ConnectorSettings-MXFRWWR6.js.map +0 -1
- package/dist/DrawerLayout-JR3O6RRB.js.map +0 -1
- package/dist/ModelSettings-G7IFNC2Y.js.map +0 -1
- package/dist/OpenUiFenceBlock-2TV5TQ6P.js +0 -9
- package/dist/SandboxSettings-NXAANMAX.js.map +0 -1
- package/dist/SchedulesPage-KKLUDO6B.js +0 -15
- package/dist/ShellRouteSync-CEBETGEJ.js.map +0 -1
- package/dist/SidebarLayout-A2HJPPHS.js.map +0 -1
- package/dist/SkillSettings-FGGMSUNO.js.map +0 -1
- package/dist/chunk-2XPPBEYF.js +0 -74
- package/dist/chunk-2XPPBEYF.js.map +0 -1
- package/dist/chunk-6O6FWUDW.js.map +0 -1
- package/dist/chunk-7Z2C2K7F.js +0 -578
- package/dist/chunk-7Z2C2K7F.js.map +0 -1
- package/dist/chunk-CYHJDKFB.js.map +0 -1
- package/dist/chunk-DMMZSZTN.js.map +0 -1
- package/dist/chunk-FJW36PD7.js.map +0 -1
- package/dist/chunk-M62XY4NC.js.map +0 -1
- package/dist/chunk-QC42MLAK.js.map +0 -1
- package/dist/chunk-SFZNIO6U.js +0 -18
- package/dist/chunk-SFZNIO6U.js.map +0 -1
- package/dist/chunk-U7KURWW3.js.map +0 -1
- package/dist/chunk-WVE3F724.js.map +0 -1
- package/dist/chunk-XAU7QFG3.js.map +0 -1
- package/dist/chunk-ZKNUMH2M.js.map +0 -1
- package/dist/chunk-ZTMKFZQ3.js.map +0 -1
- /package/dist/{AgentMetricChart-JPU3MFQ2.js.map → AgentMetricChart-YWJYVYYA.js.map} +0 -0
- /package/dist/{AgentOverview-EEBHJC32.js.map → AgentOverview-VF74XC7I.js.map} +0 -0
- /package/dist/{DockLayout-LM4AFMFY.js.map → DockLayout-F44RWGEY.js.map} +0 -0
- /package/dist/{OpenUiFenceBlock-2TV5TQ6P.js.map → OpenUiFenceBlock-4ROX3G4X.js.map} +0 -0
- /package/dist/{SchedulesPage-KKLUDO6B.js.map → SchedulesPage-TMOTK6DR.js.map} +0 -0
- /package/dist/{SettingsBuilder-L34IQ56S.js.map → SettingsBuilder-GISAH2WU.js.map} +0 -0
- /package/dist/{TrueForgeUIWithRouter-MZVJWJMB.js.map → TrueForgeUIWithRouter-6VCR7ES3.js.map} +0 -0
- /package/dist/{WidgetLayout-6QM45OQQ.js.map → WidgetLayout-RKBSN2FZ.js.map} +0 -0
- /package/dist/{chunk-MPNSO7E6.js.map → chunk-J5BPHEDT.js.map} +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
|
+
getErrorMessage,
|
|
2
3
|
useOptionalServer
|
|
3
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PT4EENB3.js";
|
|
4
5
|
import {
|
|
5
6
|
ThemeContext,
|
|
6
7
|
cn
|
|
7
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-LXJMINS6.js";
|
|
8
9
|
|
|
9
10
|
// src/icons/Icon.tsx
|
|
10
11
|
import { createElement, isValidElement, useContext } from "react";
|
|
@@ -26,6 +27,7 @@ import {
|
|
|
26
27
|
ChevronDown,
|
|
27
28
|
ChevronLeft,
|
|
28
29
|
ChevronRight,
|
|
30
|
+
ChevronsUpDown,
|
|
29
31
|
CircleAlert,
|
|
30
32
|
CircleCheck,
|
|
31
33
|
CircleX,
|
|
@@ -33,6 +35,7 @@ import {
|
|
|
33
35
|
Code2,
|
|
34
36
|
Copy,
|
|
35
37
|
Cpu,
|
|
38
|
+
DollarSign,
|
|
36
39
|
Download,
|
|
37
40
|
Ellipsis,
|
|
38
41
|
EllipsisVertical,
|
|
@@ -142,10 +145,12 @@ var defaults = {
|
|
|
142
145
|
"chevron-down": ChevronDown,
|
|
143
146
|
"chevron-left": ChevronLeft,
|
|
144
147
|
"chevron-right": ChevronRight,
|
|
148
|
+
"chevrons-up-down": ChevronsUpDown,
|
|
145
149
|
loader: Loader2,
|
|
146
150
|
file: File,
|
|
147
151
|
clone: Copy,
|
|
148
152
|
copy: Copy,
|
|
153
|
+
"dollar-sign": DollarSign,
|
|
149
154
|
bars: Menu,
|
|
150
155
|
"panel-left-close": PanelLeftClose,
|
|
151
156
|
"panel-left-open": PanelLeftOpen,
|
|
@@ -269,164 +274,30 @@ function Spinner({ size = 16, className, ...props }) {
|
|
|
269
274
|
|
|
270
275
|
// src/atoms/lib/buttonClasses.ts
|
|
271
276
|
var variantClasses = {
|
|
272
|
-
|
|
273
|
-
secondary: "border border-input-border bg-secondary-button-bg text-secondary-button-text
|
|
277
|
+
primary: "bg-primary-button-bg text-primary-button-text shadow hover:bg-primary-button-hover",
|
|
278
|
+
secondary: "border border-input-border bg-secondary-button-bg text-secondary-button-text hover:bg-secondary-button-hover",
|
|
274
279
|
ghost: "bg-ghost-button-bg text-ghost-button-text hover:bg-ghost-button-hover",
|
|
275
|
-
destructive: "bg-failure-bg text-failure-text shadow-sm hover:bg-failure-bg/90"
|
|
276
|
-
outline: "border border-input-border bg-secondary-button-bg text-secondary-button-text shadow-sm hover:bg-secondary-button-hover"
|
|
280
|
+
destructive: "bg-failure-bg text-failure-text shadow-sm hover:bg-failure-bg/90"
|
|
277
281
|
};
|
|
278
282
|
var sizeClasses = {
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
icon: "h-8 w-8"
|
|
283
|
+
large: "h-8 gap-2 px-2.5 text-sm [&_svg]:size-3.5",
|
|
284
|
+
small: "h-6 gap-1 px-1.5 text-xs [&_svg]:size-3",
|
|
285
|
+
icon: "h-8 w-8 shrink-0 gap-0 p-0 [&_svg]:size-3.5"
|
|
283
286
|
};
|
|
284
|
-
var baseClasses = "inline-flex cursor-pointer items-center justify-center
|
|
287
|
+
var baseClasses = "inline-flex cursor-pointer items-center justify-center whitespace-nowrap rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus-ring disabled:cursor-not-allowed disabled:opacity-50";
|
|
288
|
+
var sidebarButtonRadiusClassName = "rounded-[0.75rem]";
|
|
289
|
+
var sidebarRailButtonClassName = cn(
|
|
290
|
+
sidebarButtonRadiusClassName,
|
|
291
|
+
"h-[3.375rem] w-[4rem] shrink-0 flex-col gap-1 whitespace-normal px-0.5 text-[0.625rem] font-normal leading-tight !justify-center shadow-none hover:bg-secondary-button-hover hover:text-ghost-button-text [&_svg]:size-3.5"
|
|
292
|
+
);
|
|
285
293
|
function auiButtonClass({
|
|
286
|
-
variant = "
|
|
287
|
-
size = "
|
|
294
|
+
variant = "primary",
|
|
295
|
+
size = "large",
|
|
288
296
|
className
|
|
289
297
|
} = {}) {
|
|
290
298
|
return cn(baseClasses, variantClasses[variant], sizeClasses[size], className);
|
|
291
299
|
}
|
|
292
300
|
|
|
293
|
-
// src/utils/getErrorMessage.ts
|
|
294
|
-
function isRecord(value) {
|
|
295
|
-
return value != null && typeof value === "object";
|
|
296
|
-
}
|
|
297
|
-
function readNonEmptyString(value) {
|
|
298
|
-
return typeof value === "string" && value.trim() !== "" ? value : void 0;
|
|
299
|
-
}
|
|
300
|
-
var LITERAL_ESCAPE_PATTERN = /\\(?:[nrtbfv0'"\\]|u[0-9a-fA-F]{4}|x[0-9a-fA-F]{2})/;
|
|
301
|
-
var REAL_CONTROL_PATTERN = /[\n\t\b\f\v]/;
|
|
302
|
-
function decodeLiteralEscapes(text) {
|
|
303
|
-
let out = "";
|
|
304
|
-
for (let i = 0; i < text.length; i += 1) {
|
|
305
|
-
const char = text[i];
|
|
306
|
-
if (char !== "\\" || i + 1 >= text.length) {
|
|
307
|
-
out += char;
|
|
308
|
-
continue;
|
|
309
|
-
}
|
|
310
|
-
const next = text[i + 1];
|
|
311
|
-
switch (next) {
|
|
312
|
-
case "n":
|
|
313
|
-
out += "\n";
|
|
314
|
-
i += 1;
|
|
315
|
-
break;
|
|
316
|
-
case "t":
|
|
317
|
-
out += " ";
|
|
318
|
-
i += 1;
|
|
319
|
-
break;
|
|
320
|
-
case "r":
|
|
321
|
-
out += "\r";
|
|
322
|
-
i += 1;
|
|
323
|
-
break;
|
|
324
|
-
case "b":
|
|
325
|
-
out += "\b";
|
|
326
|
-
i += 1;
|
|
327
|
-
break;
|
|
328
|
-
case "f":
|
|
329
|
-
out += "\f";
|
|
330
|
-
i += 1;
|
|
331
|
-
break;
|
|
332
|
-
case "v":
|
|
333
|
-
out += "\v";
|
|
334
|
-
i += 1;
|
|
335
|
-
break;
|
|
336
|
-
case "0":
|
|
337
|
-
out += "\0";
|
|
338
|
-
i += 1;
|
|
339
|
-
break;
|
|
340
|
-
case "\\":
|
|
341
|
-
out += "\\";
|
|
342
|
-
i += 1;
|
|
343
|
-
break;
|
|
344
|
-
case '"':
|
|
345
|
-
out += '"';
|
|
346
|
-
i += 1;
|
|
347
|
-
break;
|
|
348
|
-
case "'":
|
|
349
|
-
out += "'";
|
|
350
|
-
i += 1;
|
|
351
|
-
break;
|
|
352
|
-
case "u": {
|
|
353
|
-
const hex = text.slice(i + 2, i + 6);
|
|
354
|
-
if (/^[0-9a-fA-F]{4}$/.test(hex)) {
|
|
355
|
-
out += String.fromCharCode(Number.parseInt(hex, 16));
|
|
356
|
-
i += 5;
|
|
357
|
-
} else {
|
|
358
|
-
out += char;
|
|
359
|
-
}
|
|
360
|
-
break;
|
|
361
|
-
}
|
|
362
|
-
case "x": {
|
|
363
|
-
const hex = text.slice(i + 2, i + 4);
|
|
364
|
-
if (/^[0-9a-fA-F]{2}$/.test(hex)) {
|
|
365
|
-
out += String.fromCharCode(Number.parseInt(hex, 16));
|
|
366
|
-
i += 3;
|
|
367
|
-
} else {
|
|
368
|
-
out += char;
|
|
369
|
-
}
|
|
370
|
-
break;
|
|
371
|
-
}
|
|
372
|
-
default:
|
|
373
|
-
out += char;
|
|
374
|
-
break;
|
|
375
|
-
}
|
|
376
|
-
}
|
|
377
|
-
return out;
|
|
378
|
-
}
|
|
379
|
-
function decodeErrorMessageEscapes(text) {
|
|
380
|
-
const normalized = text.replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
381
|
-
if (REAL_CONTROL_PATTERN.test(normalized) || !LITERAL_ESCAPE_PATTERN.test(normalized)) {
|
|
382
|
-
return normalized;
|
|
383
|
-
}
|
|
384
|
-
return decodeLiteralEscapes(normalized).replace(/\r\n/g, "\n").replace(/\r/g, "\n");
|
|
385
|
-
}
|
|
386
|
-
function messageFromErrorShaped(value) {
|
|
387
|
-
if (!isRecord(value)) return void 0;
|
|
388
|
-
const direct = readNonEmptyString(value.message);
|
|
389
|
-
if (direct != null) return direct;
|
|
390
|
-
if (isRecord(value.error)) {
|
|
391
|
-
return readNonEmptyString(value.error.message);
|
|
392
|
-
}
|
|
393
|
-
return void 0;
|
|
394
|
-
}
|
|
395
|
-
function stringifyError(error) {
|
|
396
|
-
if (typeof error === "string") return error;
|
|
397
|
-
if (isRecord(error)) {
|
|
398
|
-
try {
|
|
399
|
-
return JSON.stringify(error);
|
|
400
|
-
} catch {
|
|
401
|
-
return Object.prototype.toString.call(error);
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
return String(error);
|
|
405
|
-
}
|
|
406
|
-
function getErrorMessage(error, fallback) {
|
|
407
|
-
if (typeof error === "string") {
|
|
408
|
-
const trimmed = error.trim();
|
|
409
|
-
if (trimmed !== "") return decodeErrorMessageEscapes(error);
|
|
410
|
-
return fallback != null ? decodeErrorMessageEscapes(fallback) : decodeErrorMessageEscapes(error);
|
|
411
|
-
}
|
|
412
|
-
if (isRecord(error) && "body" in error) {
|
|
413
|
-
const fromBody = messageFromErrorShaped(error.body);
|
|
414
|
-
if (fromBody != null) return decodeErrorMessageEscapes(fromBody);
|
|
415
|
-
if (error.body != null) {
|
|
416
|
-
if (typeof error.body === "string") {
|
|
417
|
-
const trimmed = error.body.trim();
|
|
418
|
-
if (trimmed !== "") return decodeErrorMessageEscapes(error.body);
|
|
419
|
-
} else {
|
|
420
|
-
return stringifyError(error.body);
|
|
421
|
-
}
|
|
422
|
-
}
|
|
423
|
-
}
|
|
424
|
-
const fromShape = messageFromErrorShaped(error);
|
|
425
|
-
if (fromShape != null) return decodeErrorMessageEscapes(fromShape);
|
|
426
|
-
if (fallback != null) return decodeErrorMessageEscapes(fallback);
|
|
427
|
-
return stringifyError(error);
|
|
428
|
-
}
|
|
429
|
-
|
|
430
301
|
// src/atoms/PageHeader.tsx
|
|
431
302
|
import { jsx as jsx4, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
432
303
|
var pageHeaderTitleClassName = "text-text-primary min-w-0 truncate text-md font-semibold";
|
|
@@ -434,10 +305,7 @@ function PageHeader({ title, start, end, children, className }) {
|
|
|
434
305
|
return /* @__PURE__ */ jsxs2(
|
|
435
306
|
"header",
|
|
436
307
|
{
|
|
437
|
-
className: cn(
|
|
438
|
-
"flex min-h-14 shrink-0 flex-wrap items-center gap-2 border-b border-border px-4 md:px-6",
|
|
439
|
-
className
|
|
440
|
-
),
|
|
308
|
+
className: cn("flex min-h-14 shrink-0 flex-wrap items-center gap-2 border-b border-border px-4", className),
|
|
441
309
|
children: [
|
|
442
310
|
start,
|
|
443
311
|
typeof title === "string" ? /* @__PURE__ */ jsx4("h1", { className: pageHeaderTitleClassName, children: title }) : title,
|
|
@@ -460,33 +328,18 @@ function useCompactLayout() {
|
|
|
460
328
|
}
|
|
461
329
|
|
|
462
330
|
// src/atoms/draft/DraftCatalogProvider.tsx
|
|
463
|
-
import { createContext as createContext2, useCallback, useContext as useContext3, useEffect, useMemo,
|
|
331
|
+
import { createContext as createContext2, useCallback, useContext as useContext3, useEffect, useMemo, useState } from "react";
|
|
464
332
|
import { jsx as jsx6 } from "react/jsx-runtime";
|
|
465
|
-
var MCP_CONNECTORS_PAGE_SIZE = 50;
|
|
466
333
|
var DraftCatalogContext = createContext2(null);
|
|
467
334
|
var IDLE_ENSURE = () => void 0;
|
|
468
335
|
var IDLE_REFRESH = async () => void 0;
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
const seen = new Set(previous.map((connector) => connector.id));
|
|
475
|
-
const appended = next.filter((connector) => !seen.has(connector.id));
|
|
476
|
-
return appended.length === 0 ? previous : [...previous, ...appended];
|
|
477
|
-
}
|
|
478
|
-
async function fetchMcpPage({
|
|
479
|
-
server,
|
|
480
|
-
pageToken
|
|
481
|
-
}) {
|
|
482
|
-
if (server.listMcp != null) {
|
|
483
|
-
return server.listMcp({
|
|
484
|
-
limit: MCP_CONNECTORS_PAGE_SIZE,
|
|
485
|
-
...pageToken === void 0 ? {} : { pageToken }
|
|
486
|
-
});
|
|
336
|
+
var EMPTY_LOGOS = {};
|
|
337
|
+
function toConnectorLogos(entries) {
|
|
338
|
+
const logos = {};
|
|
339
|
+
for (const entry of entries) {
|
|
340
|
+
if (entry.logo) logos[entry.name] = entry.logo;
|
|
487
341
|
}
|
|
488
|
-
|
|
489
|
-
return { data };
|
|
342
|
+
return logos;
|
|
490
343
|
}
|
|
491
344
|
function DraftCatalogProvider({ children }) {
|
|
492
345
|
const server = useOptionalServer();
|
|
@@ -501,99 +354,66 @@ function DraftCatalogStore({ server, children }) {
|
|
|
501
354
|
const [models, setModels] = useState([]);
|
|
502
355
|
const [skills, setSkills] = useState([]);
|
|
503
356
|
const [connectors, setConnectors] = useState([]);
|
|
504
|
-
const [
|
|
505
|
-
const [connectorsLoadMoreFailed, setConnectorsLoadMoreFailed] = useState(false);
|
|
506
|
-
const [connectorsLoadingMore, setConnectorsLoadingMore] = useState(false);
|
|
357
|
+
const [connectorLogos, setConnectorLogos] = useState(EMPTY_LOGOS);
|
|
507
358
|
const [completedEpoch, setCompletedEpoch] = useState(null);
|
|
508
359
|
const [loading, setLoading] = useState(false);
|
|
509
360
|
const [error, setError] = useState(null);
|
|
510
|
-
const connectorsNextPageTokenRef = useRef(connectorsNextPageToken);
|
|
511
|
-
const connectorsLoadingMoreRef = useRef(connectorsLoadingMore);
|
|
512
|
-
const loadMoreFailedRef = useRef(false);
|
|
513
|
-
connectorsNextPageTokenRef.current = connectorsNextPageToken;
|
|
514
|
-
connectorsLoadingMoreRef.current = connectorsLoadingMore;
|
|
515
361
|
const ensureLoaded = useCallback(() => {
|
|
516
362
|
setRequestEpoch((current) => current ?? 0);
|
|
517
363
|
}, []);
|
|
518
364
|
const refresh = useCallback(() => {
|
|
519
|
-
loadMoreFailedRef.current = false;
|
|
520
|
-
setConnectorsLoadMoreFailed(false);
|
|
521
365
|
setRequestEpoch((current) => (current ?? -1) + 1);
|
|
522
366
|
}, []);
|
|
523
367
|
const refreshConnectors = useCallback(async () => {
|
|
524
368
|
if (!server) return;
|
|
525
369
|
setLoading(true);
|
|
526
370
|
setError(null);
|
|
527
|
-
loadMoreFailedRef.current = false;
|
|
528
|
-
setConnectorsLoadMoreFailed(false);
|
|
529
371
|
try {
|
|
530
|
-
|
|
531
|
-
setConnectors(page.data);
|
|
532
|
-
setConnectorsNextPageToken(page.nextPageToken);
|
|
372
|
+
setConnectors(await server.getMcp());
|
|
533
373
|
} catch (reason) {
|
|
534
374
|
setError(getErrorMessage(reason, "Failed to load connectors."));
|
|
535
375
|
} finally {
|
|
536
376
|
setLoading(false);
|
|
537
377
|
}
|
|
538
378
|
}, [server]);
|
|
539
|
-
const loadMoreConnectors = useCallback(() => {
|
|
540
|
-
if (!server) return;
|
|
541
|
-
const pageToken = connectorsNextPageTokenRef.current;
|
|
542
|
-
if (pageToken == null || pageToken.length === 0 || connectorsLoadingMoreRef.current) return;
|
|
543
|
-
setConnectorsLoadMoreFailed(false);
|
|
544
|
-
setConnectorsLoadingMore(true);
|
|
545
|
-
void fetchMcpPage({ server, pageToken }).then((page) => {
|
|
546
|
-
setConnectors((previous) => appendConnectors({ previous, next: page.data }));
|
|
547
|
-
setConnectorsNextPageToken(page.nextPageToken);
|
|
548
|
-
if (loadMoreFailedRef.current) {
|
|
549
|
-
loadMoreFailedRef.current = false;
|
|
550
|
-
setError(null);
|
|
551
|
-
}
|
|
552
|
-
}).catch((reason) => {
|
|
553
|
-
loadMoreFailedRef.current = true;
|
|
554
|
-
setConnectorsLoadMoreFailed(true);
|
|
555
|
-
setError(getErrorMessage(reason, "Failed to load more connectors."));
|
|
556
|
-
}).finally(() => {
|
|
557
|
-
setConnectorsLoadingMore(false);
|
|
558
|
-
});
|
|
559
|
-
}, [server]);
|
|
560
379
|
useEffect(() => {
|
|
561
380
|
if (requestEpoch === null || !server) return;
|
|
562
381
|
let cancelled = false;
|
|
563
382
|
setLoading(true);
|
|
564
383
|
setError(null);
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
(
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
} else {
|
|
585
|
-
errors.push(getErrorMessage(mcpResult.reason, "Failed to load connectors."));
|
|
586
|
-
}
|
|
587
|
-
setError(errors[0] ?? null);
|
|
588
|
-
setCompletedEpoch(requestEpoch);
|
|
589
|
-
setLoading(false);
|
|
384
|
+
const connectorCatalog = server.catalog?.connectorCatalog;
|
|
385
|
+
void Promise.allSettled([
|
|
386
|
+
server.getModels(),
|
|
387
|
+
server.getSkills(),
|
|
388
|
+
server.getMcp(),
|
|
389
|
+
connectorCatalog ? connectorCatalog.getConnectorCatalog() : Promise.resolve([])
|
|
390
|
+
]).then(([modelsResult, skillsResult, mcpResult, catalogResult]) => {
|
|
391
|
+
if (cancelled) return;
|
|
392
|
+
setConnectorLogos(catalogResult.status === "fulfilled" ? toConnectorLogos(catalogResult.value) : EMPTY_LOGOS);
|
|
393
|
+
const errors = [];
|
|
394
|
+
if (modelsResult.status === "fulfilled") {
|
|
395
|
+
setModels(modelsResult.value);
|
|
396
|
+
} else {
|
|
397
|
+
errors.push(getErrorMessage(modelsResult.reason, "Failed to load models."));
|
|
398
|
+
}
|
|
399
|
+
if (skillsResult.status === "fulfilled") {
|
|
400
|
+
setSkills(skillsResult.value);
|
|
401
|
+
} else {
|
|
402
|
+
errors.push(getErrorMessage(skillsResult.reason, "Failed to load skills."));
|
|
590
403
|
}
|
|
591
|
-
|
|
404
|
+
if (mcpResult.status === "fulfilled") {
|
|
405
|
+
setConnectors(mcpResult.value);
|
|
406
|
+
} else {
|
|
407
|
+
errors.push(getErrorMessage(mcpResult.reason, "Failed to load connectors."));
|
|
408
|
+
}
|
|
409
|
+
setError(errors[0] ?? null);
|
|
410
|
+
setCompletedEpoch(requestEpoch);
|
|
411
|
+
setLoading(false);
|
|
412
|
+
});
|
|
592
413
|
return () => {
|
|
593
414
|
cancelled = true;
|
|
594
415
|
};
|
|
595
416
|
}, [requestEpoch, server]);
|
|
596
|
-
const connectorsHasMore = connectorsNextPageToken != null && connectorsNextPageToken.length > 0;
|
|
597
417
|
const loaded = requestEpoch !== null && completedEpoch === requestEpoch;
|
|
598
418
|
const value = useMemo(
|
|
599
419
|
() => ({
|
|
@@ -601,32 +421,26 @@ function DraftCatalogStore({ server, children }) {
|
|
|
601
421
|
models,
|
|
602
422
|
skills,
|
|
603
423
|
connectors,
|
|
604
|
-
|
|
605
|
-
connectorsLoadMoreFailed,
|
|
606
|
-
connectorsLoadingMore,
|
|
424
|
+
connectorLogos,
|
|
607
425
|
loaded,
|
|
608
426
|
loading,
|
|
609
427
|
error,
|
|
610
428
|
ensureLoaded,
|
|
611
429
|
refresh,
|
|
612
|
-
refreshConnectors
|
|
613
|
-
loadMoreConnectors
|
|
430
|
+
refreshConnectors
|
|
614
431
|
}),
|
|
615
432
|
[
|
|
616
433
|
server,
|
|
617
434
|
models,
|
|
618
435
|
skills,
|
|
619
436
|
connectors,
|
|
620
|
-
|
|
621
|
-
connectorsLoadMoreFailed,
|
|
622
|
-
connectorsLoadingMore,
|
|
437
|
+
connectorLogos,
|
|
623
438
|
loaded,
|
|
624
439
|
loading,
|
|
625
440
|
error,
|
|
626
441
|
ensureLoaded,
|
|
627
442
|
refresh,
|
|
628
|
-
refreshConnectors
|
|
629
|
-
loadMoreConnectors
|
|
443
|
+
refreshConnectors
|
|
630
444
|
]
|
|
631
445
|
);
|
|
632
446
|
return /* @__PURE__ */ jsx6(DraftCatalogContext.Provider, { value, children });
|
|
@@ -638,16 +452,13 @@ function useDraftCatalog() {
|
|
|
638
452
|
models: [],
|
|
639
453
|
skills: [],
|
|
640
454
|
connectors: [],
|
|
641
|
-
|
|
642
|
-
connectorsLoadMoreFailed: false,
|
|
643
|
-
connectorsLoadingMore: false,
|
|
455
|
+
connectorLogos: EMPTY_LOGOS,
|
|
644
456
|
loaded: false,
|
|
645
457
|
loading: false,
|
|
646
458
|
error: null,
|
|
647
459
|
ensureLoaded: IDLE_ENSURE,
|
|
648
460
|
refresh: IDLE_ENSURE,
|
|
649
|
-
refreshConnectors: IDLE_REFRESH
|
|
650
|
-
loadMoreConnectors: IDLE_ENSURE
|
|
461
|
+
refreshConnectors: IDLE_REFRESH
|
|
651
462
|
};
|
|
652
463
|
}
|
|
653
464
|
return ctx;
|
|
@@ -657,8 +468,9 @@ export {
|
|
|
657
468
|
registerIcons,
|
|
658
469
|
Icon,
|
|
659
470
|
Spinner,
|
|
471
|
+
sidebarButtonRadiusClassName,
|
|
472
|
+
sidebarRailButtonClassName,
|
|
660
473
|
auiButtonClass,
|
|
661
|
-
getErrorMessage,
|
|
662
474
|
pageHeaderTitleClassName,
|
|
663
475
|
PageHeader,
|
|
664
476
|
CompactLayoutProvider,
|
|
@@ -666,4 +478,4 @@ export {
|
|
|
666
478
|
DraftCatalogProvider,
|
|
667
479
|
useDraftCatalog
|
|
668
480
|
};
|
|
669
|
-
//# sourceMappingURL=chunk-
|
|
481
|
+
//# sourceMappingURL=chunk-Q6TCT7ZJ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/icons/Icon.tsx","../src/icons/IconRegistry.tsx","../src/atoms/primitives/Spinner.tsx","../src/atoms/lib/buttonClasses.ts","../src/atoms/PageHeader.tsx","../src/atoms/lib/CompactLayoutContext.tsx","../src/atoms/draft/DraftCatalogProvider.tsx"],"sourcesContent":["import { createElement, isValidElement, useContext, type CSSProperties, type ReactNode } from 'react';\n\nimport { cn } from '../atoms/lib/cn.js';\nimport { ThemeContext } from '../theme/ThemeProvider.js';\nimport type { IconComponent, IconEntry, IconProps as ThemeIconProps } from '../theme/types.js';\nimport { lookupIcon, resolveIconName } from './IconRegistry.js';\n\nexport type IconProps = ThemeIconProps & {\n name: string | readonly string[];\n};\n\ntype IconRenderProps = {\n className?: string;\n style?: CSSProperties;\n size?: string | number;\n width?: string | number;\n height?: string | number;\n role?: string;\n} & Pick<IconProps, 'aria-hidden' | 'aria-label' | 'data-testid'>;\n\nfunction isComponent(entry: IconEntry): entry is IconComponent {\n if (typeof entry === 'function') return true;\n // Lucide (and other) icons are forwardRef objects, not functions\n return (\n typeof entry === 'object' &&\n entry !== null &&\n !isValidElement(entry) &&\n !Array.isArray(entry) &&\n '$$typeof' in entry\n );\n}\n\nfunction renderEntry(entry: IconEntry, props: IconRenderProps): ReactNode {\n if (isComponent(entry)) {\n const { size, className, style, ...aria } = props;\n return createElement(entry, {\n className: cn('inline-block shrink-0', className),\n style,\n size,\n width: size,\n height: size,\n 'aria-hidden': aria['aria-label'] ? undefined : (aria['aria-hidden'] ?? true),\n 'aria-label': aria['aria-label'],\n ...(aria['data-testid'] === undefined ? {} : { 'data-testid': aria['data-testid'] }),\n role: aria['aria-label'] ? 'img' : undefined,\n });\n }\n return entry;\n}\n\nexport function Icon({ name, className, style, size = '1em', ...aria }: IconProps) {\n const themeIcons = useContext(ThemeContext)?.icons;\n const resolved = resolveIconName(name);\n const entry = lookupIcon(resolved, themeIcons);\n if (!entry) return null;\n return <>{renderEntry(entry, { className, style, size, ...aria })}</>;\n}\n\nexport function useIcon(name: string | readonly string[]): IconEntry | undefined {\n const themeIcons = useContext(ThemeContext)?.icons;\n return lookupIcon(resolveIconName(name), themeIcons);\n}\n","import {\n Archive,\n ArrowDown,\n ArrowLeft,\n ArrowUp,\n BookOpen,\n Bot,\n Box,\n Brain,\n Calendar,\n CalendarClock,\n CalendarPlus,\n Check,\n ChevronDown,\n ChevronLeft,\n ChevronRight,\n ChevronsUpDown,\n CircleAlert,\n CircleCheck,\n CircleX,\n Clock,\n Code2,\n Copy,\n Cpu,\n DollarSign,\n Download,\n Ellipsis,\n EllipsisVertical,\n ExternalLink,\n File,\n Github,\n GripVertical,\n History,\n Info,\n LibraryBig,\n Lightbulb,\n LineChart,\n Link2,\n ListChecks,\n ListFilter,\n ListOrdered,\n Loader2,\n Lock,\n LogOut,\n Maximize2,\n Menu,\n MessageSquareText,\n Minimize2,\n Moon,\n PanelLeftClose,\n PanelLeftOpen,\n Paperclip,\n Pause,\n Pencil,\n Play,\n Plug,\n Plus,\n RotateCw,\n Save,\n Search,\n Settings,\n SlidersHorizontal,\n Sparkle,\n SquareArrowOutUpRight,\n SquarePen,\n Sun,\n Terminal,\n Trash2,\n TriangleAlert,\n Wrench,\n X,\n} from 'lucide-react';\nimport type { SVGProps } from 'react';\n\nimport type { IconEntry, IconMap } from '../theme/types.js';\n\n/** Lucide `broom` (https://lucide.dev/icons/broom) — not in lucide-react 0.x. */\nfunction Broom({ size = 24, ...props }: SVGProps<SVGSVGElement> & { size?: string | number }) {\n return (\n <svg\n xmlns=\"http://www.w3.org/2000/svg\"\n width={size}\n height={size}\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n strokeWidth=\"2\"\n strokeLinecap=\"round\"\n strokeLinejoin=\"round\"\n {...props}\n >\n <path d=\"M13.5 10.5 22 2\" />\n <path d=\"M14.734 13.841a2 2 0 00-.314-2.42L12.58 9.58a2 2 0 00-2.421-.314l-7.657 4.461A1 1 0 002.3 15.3l6.403 6.403a1 1 0 001.571-.204z\" />\n <path d=\"m5 18 2-2\" />\n <path d=\"m7.699 10.7 5.602 5.601\" />\n </svg>\n );\n}\n\nconst registry = new Map<string, IconEntry>();\n\nexport function registerIcon(name: string, icon: IconEntry): void {\n registry.set(name, icon);\n}\n\nexport function registerIcons(icons: IconMap): void {\n for (const [name, icon] of Object.entries(icons)) {\n registry.set(name, icon);\n }\n}\n\nexport function getIcon(name: string): IconEntry | undefined {\n return registry.get(name);\n}\n\nexport function resolveIconName(icon: string | readonly string[]): string {\n if (typeof icon === 'string') return icon;\n // e.g. [\"far\", \"clone\"] → \"clone\"\n return icon[icon.length - 1] ?? '';\n}\n\nconst defaults: Record<string, IconEntry> = {\n paperclip: Paperclip,\n 'arrow-up': ArrowUp,\n 'arrow-down': ArrowDown,\n 'arrow-left': ArrowLeft,\n xmark: X,\n check: Check,\n pencil: Pencil,\n play: Play,\n pause: Pause,\n calendar: Calendar,\n 'calendar-clock': CalendarClock,\n 'calendar-plus': CalendarPlus,\n 'grip-vertical': GripVertical,\n 'square-pen': SquarePen,\n 'rotate-right': RotateCw,\n broom: Broom,\n ellipsis: Ellipsis,\n 'ellipsis-vertical': EllipsisVertical,\n trash: Trash2,\n 'box-archive': Archive,\n 'clock-rotate-left': History,\n 'circle-exclamation': CircleAlert,\n info: Info,\n 'triangle-exclamation': TriangleAlert,\n 'chevron-down': ChevronDown,\n 'chevron-left': ChevronLeft,\n 'chevron-right': ChevronRight,\n 'chevrons-up-down': ChevronsUpDown,\n loader: Loader2,\n file: File,\n clone: Copy,\n copy: Copy,\n 'dollar-sign': DollarSign,\n bars: Menu,\n 'panel-left-close': PanelLeftClose,\n 'panel-left-open': PanelLeftOpen,\n plus: Plus,\n sun: Sun,\n moon: Moon,\n settings: Settings,\n sliders: SlidersHorizontal,\n 'log-out': LogOut,\n search: Search,\n clock: Clock,\n 'circle-check': CircleCheck,\n 'circle-xmark': CircleX,\n 'oauth-success': CircleCheck,\n 'oauth-error': CircleX,\n 'oauth-loading': Loader2,\n 'welcome-sparkle': Sparkle,\n robot: Bot,\n bot: Bot,\n 'library-big': LibraryBig,\n 'message-square-text': MessageSquareText,\n 'book-open': BookOpen,\n funnel: ListFilter,\n plug: Plug,\n 'list-check': ListChecks,\n lock: Lock,\n lightbulb: Lightbulb,\n link: Link2,\n wrench: Wrench,\n cpu: Cpu,\n cube: Box,\n 'list-ol': ListOrdered,\n download: Download,\n save: Save,\n brain: Brain,\n terminal: Terminal,\n code: Code2,\n chart: LineChart,\n expand: Maximize2,\n 'expand-alt': Maximize2,\n compress: Minimize2,\n 'external-link': ExternalLink,\n 'square-arrow-out-up-right': SquareArrowOutUpRight,\n github: Github,\n};\n\nfor (const [name, icon] of Object.entries(defaults)) {\n registry.set(name, icon);\n}\n\n/** Merge host `theme.icons` over the registry for a single lookup (does not mutate). */\nexport function lookupIcon(name: string, themeIcons?: IconMap): IconEntry | undefined {\n if (themeIcons && name in themeIcons) {\n return themeIcons[name];\n }\n return registry.get(name);\n}\n","import React from 'react';\n\nimport { cn } from '../lib/cn.js';\n\nexport type SpinnerProps = React.SVGProps<SVGSVGElement> & {\n size?: number;\n};\n\nexport function Spinner({ size = 16, className, ...props }: SpinnerProps) {\n const r = (size / 2) * 0.75;\n const cx = size / 2;\n const circumference = 2 * Math.PI * r;\n\n return (\n <svg\n role=\"status\"\n aria-label=\"Loading\"\n width={size}\n height={size}\n viewBox={`0 0 ${size} ${size}`}\n fill=\"none\"\n className={cn('animate-spin', className)}\n {...props}\n >\n <circle\n cx={cx}\n cy={cx}\n r={r}\n stroke=\"currentColor\"\n strokeWidth={2}\n strokeLinecap=\"round\"\n strokeDasharray={`${circumference * 0.75} ${circumference * 0.25}`}\n opacity={0.8}\n />\n </svg>\n );\n}\n","import { cn } from './cn.js';\n\nexport type AuiButtonVariant = 'primary' | 'secondary' | 'ghost' | 'destructive';\nexport type AuiButtonSize = 'large' | 'small' | 'icon';\n\nconst variantClasses: Record<AuiButtonVariant, string> = {\n primary: 'bg-primary-button-bg text-primary-button-text shadow hover:bg-primary-button-hover',\n secondary:\n 'border border-input-border bg-secondary-button-bg text-secondary-button-text hover:bg-secondary-button-hover',\n ghost: 'bg-ghost-button-bg text-ghost-button-text hover:bg-ghost-button-hover',\n destructive: 'bg-failure-bg text-failure-text shadow-sm hover:bg-failure-bg/90',\n};\n\n/** Glyph sizes match the shared design-system Button (`iconSizeMap`: large 0.875rem, small 0.75rem). */\nconst sizeClasses: Record<AuiButtonSize, string> = {\n large: 'h-8 gap-2 px-2.5 text-sm [&_svg]:size-3.5',\n small: 'h-6 gap-1 px-1.5 text-xs [&_svg]:size-3',\n icon: 'h-8 w-8 shrink-0 gap-0 p-0 [&_svg]:size-3.5',\n};\n\nconst baseClasses =\n 'inline-flex cursor-pointer items-center justify-center whitespace-nowrap rounded-md font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-focus-ring disabled:cursor-not-allowed disabled:opacity-50';\n\n/** Sidebar / rail nav control corner radius: 12px. */\nexport const sidebarButtonRadiusClassName = 'rounded-[0.75rem]';\n\n/** Compact sidebar rail control: 66×54px → 4.125rem × 3.375rem. */\nexport const sidebarRailButtonClassName = cn(\n sidebarButtonRadiusClassName,\n 'h-[3.375rem] w-[4rem] shrink-0 flex-col gap-1 whitespace-normal px-0.5 text-[0.625rem] font-normal leading-tight !justify-center shadow-none hover:bg-secondary-button-hover hover:text-ghost-button-text [&_svg]:size-3.5',\n);\n\n/** Shared Button / native `<button>` className helper (SDK utilities are layered). */\nexport function auiButtonClass({\n variant = 'primary',\n size = 'large',\n className,\n}: {\n variant?: AuiButtonVariant;\n size?: AuiButtonSize;\n className?: string;\n} = {}): string {\n return cn(baseClasses, variantClasses[variant], sizeClasses[size], className);\n}\n","'use client';\n\nimport type { ReactNode } from 'react';\n\nimport { cn } from './lib/cn.js';\n\n/** Shared title styles for page / chat chrome headers. */\nexport const pageHeaderTitleClassName = 'text-text-primary min-w-0 truncate text-md font-semibold';\n\nexport type PageHeaderProps = {\n /** Page name, or a custom title node (e.g. `NamedAgentHeaderLabel`). Strings use the shared h1 styles. */\n title?: ReactNode;\n /** Leading chrome (back / menu). */\n start?: ReactNode;\n /** Trailing actions; pushed to the end. */\n end?: ReactNode;\n /** Extra content between title and end (prefer `start` / `end` when possible). */\n children?: ReactNode;\n className?: string;\n};\n\n/** Shared shell/page header bar used by chat chrome and list pages.\n * `min-h-14` keeps a single-row bar aligned with Agent Config; wrapping end actions can grow the bar.\n */\nexport function PageHeader({ title, start, end, children, className }: PageHeaderProps) {\n return (\n <header\n className={cn('flex min-h-14 shrink-0 flex-wrap items-center gap-2 border-b border-border px-4', className)}\n >\n {start}\n {typeof title === 'string' ? <h1 className={pageHeaderTitleClassName}>{title}</h1> : title}\n {children}\n {end != null ? <div className=\"ml-auto flex min-w-0 flex-wrap items-center gap-2\">{end}</div> : null}\n </header>\n );\n}\n","'use client';\n\nimport { createContext, useContext, type ReactNode } from 'react';\n\nconst CompactLayoutContext = createContext(false);\n\nexport function CompactLayoutProvider({ children }: { children: ReactNode }) {\n return <CompactLayoutContext.Provider value>{children}</CompactLayoutContext.Provider>;\n}\n\nexport function useCompactLayout() {\n return useContext(CompactLayoutContext);\n}\n","'use client';\n\nimport { createContext, useCallback, useContext, useEffect, useMemo, useState, type ReactNode } from 'react';\n\nimport { useOptionalServer } from '../../server/ServerContext.js';\nimport type {\n AgentSkill,\n AgentUIServer,\n ConnectorCatalogEntry,\n ConnectorState,\n ModelSelection,\n} from '../../server/types.js';\nimport { getErrorMessage } from '../../utils/getErrorMessage.js';\n\ntype DraftCatalogValue = {\n models: ModelSelection[];\n skills: AgentSkill[];\n connectors: ConnectorState[];\n /** Connector logo URL keyed by connector name, sourced from the discovery catalog. */\n connectorLogos: Record<string, string>;\n loaded: boolean;\n loading: boolean;\n error: string | null;\n /** Kick off catalog fetch (idempotent). Call when a picker opens. */\n ensureLoaded: () => void;\n /** Reload all collections after settings mutate catalog-backed configuration. */\n refresh: () => void;\n /** Refresh connector auth state without reloading unrelated catalogs. */\n refreshConnectors: () => Promise<void>;\n};\n\ntype DraftCatalogContextValue = DraftCatalogValue & {\n server: AgentUIServer | null;\n};\n\nconst DraftCatalogContext = createContext<DraftCatalogContextValue | null>(null);\n\nconst IDLE_ENSURE = () => undefined;\nconst IDLE_REFRESH = async () => undefined;\nconst EMPTY_LOGOS: Record<string, string> = {};\n\nfunction toConnectorLogos(entries: ConnectorCatalogEntry[]): Record<string, string> {\n const logos: Record<string, string> = {};\n for (const entry of entries) {\n if (entry.logo) logos[entry.name] = entry.logo;\n }\n return logos;\n}\n\nexport function DraftCatalogProvider({ children }: { children: ReactNode }) {\n const server = useOptionalServer();\n const existing = useContext(DraftCatalogContext);\n if (existing?.server === server) {\n return children;\n }\n return <DraftCatalogStore server={server}>{children}</DraftCatalogStore>;\n}\n\nfunction DraftCatalogStore({ server, children }: { server: AgentUIServer | null; children: ReactNode }) {\n const [requestEpoch, setRequestEpoch] = useState<number | null>(null);\n const [models, setModels] = useState<ModelSelection[]>([]);\n const [skills, setSkills] = useState<AgentSkill[]>([]);\n const [connectors, setConnectors] = useState<ConnectorState[]>([]);\n const [connectorLogos, setConnectorLogos] = useState<Record<string, string>>(EMPTY_LOGOS);\n const [completedEpoch, setCompletedEpoch] = useState<number | null>(null);\n const [loading, setLoading] = useState(false);\n const [error, setError] = useState<string | null>(null);\n\n const ensureLoaded = useCallback(() => {\n setRequestEpoch(current => current ?? 0);\n }, []);\n\n const refresh = useCallback(() => {\n setRequestEpoch(current => (current ?? -1) + 1);\n }, []);\n\n const refreshConnectors = useCallback(async () => {\n if (!server) return;\n setLoading(true);\n setError(null);\n try {\n setConnectors(await server.getMcp());\n } catch (reason: unknown) {\n setError(getErrorMessage(reason, 'Failed to load connectors.'));\n } finally {\n setLoading(false);\n }\n }, [server]);\n\n useEffect(() => {\n if (requestEpoch === null || !server) return;\n let cancelled = false;\n setLoading(true);\n setError(null);\n // Settle each list alone so one failing picker does not blank the others.\n // Logos are cosmetic: a missing catalog port or a failed fetch just falls back to icons.\n const connectorCatalog = server.catalog?.connectorCatalog;\n void Promise.allSettled([\n server.getModels(),\n server.getSkills(),\n server.getMcp(),\n connectorCatalog ? connectorCatalog.getConnectorCatalog() : Promise.resolve([]),\n ]).then(([modelsResult, skillsResult, mcpResult, catalogResult]) => {\n if (cancelled) return;\n setConnectorLogos(catalogResult.status === 'fulfilled' ? toConnectorLogos(catalogResult.value) : EMPTY_LOGOS);\n const errors: string[] = [];\n if (modelsResult.status === 'fulfilled') {\n setModels(modelsResult.value);\n } else {\n errors.push(getErrorMessage(modelsResult.reason, 'Failed to load models.'));\n }\n if (skillsResult.status === 'fulfilled') {\n setSkills(skillsResult.value);\n } else {\n errors.push(getErrorMessage(skillsResult.reason, 'Failed to load skills.'));\n }\n if (mcpResult.status === 'fulfilled') {\n setConnectors(mcpResult.value);\n } else {\n errors.push(getErrorMessage(mcpResult.reason, 'Failed to load connectors.'));\n }\n setError(errors[0] ?? null);\n setCompletedEpoch(requestEpoch);\n setLoading(false);\n });\n return () => {\n cancelled = true;\n };\n }, [requestEpoch, server]);\n\n const loaded = requestEpoch !== null && completedEpoch === requestEpoch;\n const value = useMemo(\n () => ({\n server,\n models,\n skills,\n connectors,\n connectorLogos,\n loaded,\n loading,\n error,\n ensureLoaded,\n refresh,\n refreshConnectors,\n }),\n [\n server,\n models,\n skills,\n connectors,\n connectorLogos,\n loaded,\n loading,\n error,\n ensureLoaded,\n refresh,\n refreshConnectors,\n ],\n );\n\n return <DraftCatalogContext.Provider value={value}>{children}</DraftCatalogContext.Provider>;\n}\n\nexport function useDraftCatalog(): DraftCatalogValue {\n const ctx = useContext(DraftCatalogContext);\n if (ctx == null) {\n return {\n models: [],\n skills: [],\n connectors: [],\n connectorLogos: EMPTY_LOGOS,\n loaded: false,\n loading: false,\n error: null,\n ensureLoaded: IDLE_ENSURE,\n refresh: IDLE_ENSURE,\n refreshConnectors: IDLE_REFRESH,\n };\n }\n return ctx;\n}\n"],"mappings":"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","names":["jsx","jsx","jsx","jsxs","useContext","jsx","createContext","useContext","jsx","createContext","useContext"]}
|
|
@@ -2,7 +2,7 @@ import {
|
|
|
2
2
|
formatCostUsd,
|
|
3
3
|
formatDurationMs,
|
|
4
4
|
useThemeMode
|
|
5
|
-
} from "./chunk-
|
|
5
|
+
} from "./chunk-2O5EJ6QS.js";
|
|
6
6
|
|
|
7
7
|
// src/atoms/agent-details/AgentMetricChart.tsx
|
|
8
8
|
import {
|
|
@@ -18,8 +18,8 @@ import { useMemo } from "react";
|
|
|
18
18
|
import { Line } from "react-chartjs-2";
|
|
19
19
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
20
20
|
ChartJS.register(CategoryScale, LinearScale, LineElement, PointElement, Legend, Tooltip);
|
|
21
|
-
var LIGHT_COLORS = ["#
|
|
22
|
-
var DARK_COLORS = ["#
|
|
21
|
+
var LIGHT_COLORS = ["#6366F1", "#2563eb", "#0EA5E9"];
|
|
22
|
+
var DARK_COLORS = ["#6366F1", "#60a5fa", "#38BDF8"];
|
|
23
23
|
var numberFormatter = new Intl.NumberFormat(void 0, { maximumFractionDigits: 4 });
|
|
24
24
|
var timestampFormatter = new Intl.DateTimeFormat(void 0, {
|
|
25
25
|
month: "short",
|
|
@@ -36,10 +36,10 @@ function formatTimestamp(timestamp) {
|
|
|
36
36
|
const date = new Date(timestamp);
|
|
37
37
|
return Number.isNaN(date.getTime()) ? timestamp : timestampFormatter.format(date);
|
|
38
38
|
}
|
|
39
|
-
function AgentMetricChart({ graph, definition, error }) {
|
|
39
|
+
function AgentMetricChart({ graph, definition, error, colorIndex = 0 }) {
|
|
40
40
|
const mode = useThemeMode();
|
|
41
41
|
const colors = mode === "dark" ? DARK_COLORS : LIGHT_COLORS;
|
|
42
|
-
const axisColor = mode === "dark" ? "#
|
|
42
|
+
const axisColor = mode === "dark" ? "#71717a" : "#a1a1aa";
|
|
43
43
|
const gridColor = mode === "dark" ? "#27272a" : "#e4e4e7";
|
|
44
44
|
const labels = useMemo(
|
|
45
45
|
() => graph == null ? [] : [...new Set(graph.graphLines.flatMap((line) => line.values.map((point) => point.timestamp)))].sort(),
|
|
@@ -50,21 +50,23 @@ function AgentMetricChart({ graph, definition, error }) {
|
|
|
50
50
|
labels: labels.map(formatTimestamp),
|
|
51
51
|
datasets: graph?.graphLines.map((line, index) => {
|
|
52
52
|
const valuesByTimestamp = new Map(line.values.map((point) => [point.timestamp, point.value]));
|
|
53
|
-
const color = colors[index % colors.length];
|
|
53
|
+
const color = colors[(colorIndex + index) % colors.length];
|
|
54
54
|
return {
|
|
55
55
|
label: line.name,
|
|
56
56
|
data: labels.map((timestamp) => valuesByTimestamp.get(timestamp) ?? null),
|
|
57
57
|
borderColor: color,
|
|
58
58
|
backgroundColor: color,
|
|
59
|
-
pointRadius:
|
|
60
|
-
pointHoverRadius:
|
|
59
|
+
pointRadius: 0,
|
|
60
|
+
pointHoverRadius: 0,
|
|
61
61
|
borderWidth: 2,
|
|
62
|
-
|
|
62
|
+
borderCapStyle: "butt",
|
|
63
|
+
borderJoinStyle: "miter",
|
|
64
|
+
tension: 0,
|
|
63
65
|
spanGaps: true
|
|
64
66
|
};
|
|
65
67
|
}) ?? []
|
|
66
68
|
}),
|
|
67
|
-
[colors, graph, labels]
|
|
69
|
+
[colorIndex, colors, graph, labels]
|
|
68
70
|
);
|
|
69
71
|
const options = useMemo(
|
|
70
72
|
() => ({
|
|
@@ -116,4 +118,4 @@ function AgentMetricChart({ graph, definition, error }) {
|
|
|
116
118
|
export {
|
|
117
119
|
AgentMetricChart
|
|
118
120
|
};
|
|
119
|
-
//# sourceMappingURL=chunk-
|
|
121
|
+
//# sourceMappingURL=chunk-XLFOXQKZ.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/atoms/agent-details/AgentMetricChart.tsx"],"sourcesContent":["'use client';\n\nimport {\n CategoryScale,\n Chart as ChartJS,\n Legend,\n LinearScale,\n LineElement,\n PointElement,\n Tooltip,\n type ChartData,\n type ChartOptions,\n} from 'chart.js';\nimport { useMemo, type ComponentType } from 'react';\nimport { Line } from 'react-chartjs-2';\n\nimport { useThemeMode } from '../../theme/SlotsProvider.js';\nimport { formatCostUsd, formatDurationMs } from '../../utils/sessionDisplayFormat.js';\nimport type { AgentMetricChartProps } from './types.js';\n\nChartJS.register(CategoryScale, LinearScale, LineElement, PointElement, Legend, Tooltip);\n\nconst LIGHT_COLORS = ['#6366F1', '#2563eb', '#0EA5E9'];\nconst DARK_COLORS = ['#6366F1', '#60a5fa', '#38BDF8'];\nconst numberFormatter = new Intl.NumberFormat(undefined, { maximumFractionDigits: 4 });\nconst timestampFormatter = new Intl.DateTimeFormat(undefined, {\n month: 'short',\n day: 'numeric',\n hour: 'numeric',\n minute: '2-digit',\n});\n\nfunction formatValue(value: number, unit: string): string {\n if (unit === '$') return formatCostUsd(value);\n if (unit === 'ms') return formatDurationMs(value);\n return `${numberFormatter.format(value)}${unit === 'count' || unit.length === 0 ? '' : ` ${unit}`}`;\n}\n\nfunction formatTimestamp(timestamp: string): string {\n const date = new Date(timestamp);\n return Number.isNaN(date.getTime()) ? timestamp : timestampFormatter.format(date);\n}\n\nexport function AgentMetricChart({ graph, definition, error, colorIndex = 0 }: AgentMetricChartProps) {\n const mode = useThemeMode();\n const colors = mode === 'dark' ? DARK_COLORS : LIGHT_COLORS;\n const axisColor = mode === 'dark' ? '#71717a' : '#a1a1aa';\n const gridColor = mode === 'dark' ? '#27272a' : '#e4e4e7';\n const labels = useMemo(\n () =>\n graph == null\n ? []\n : [...new Set(graph.graphLines.flatMap(line => line.values.map(point => point.timestamp)))].sort(),\n [graph],\n );\n const data = useMemo<ChartData<'line', Array<number | null>, string>>(\n () => ({\n labels: labels.map(formatTimestamp),\n datasets:\n graph?.graphLines.map((line, index) => {\n const valuesByTimestamp = new Map(line.values.map(point => [point.timestamp, point.value]));\n const color = colors[(colorIndex + index) % colors.length];\n return {\n label: line.name,\n data: labels.map(timestamp => valuesByTimestamp.get(timestamp) ?? null),\n borderColor: color,\n backgroundColor: color,\n pointRadius: 0,\n pointHoverRadius: 0,\n borderWidth: 2,\n borderCapStyle: 'butt',\n borderJoinStyle: 'miter',\n tension: 0,\n spanGaps: true,\n };\n }) ?? [],\n }),\n [colorIndex, colors, graph, labels],\n );\n const options = useMemo<ChartOptions<'line'>>(\n () => ({\n responsive: true,\n maintainAspectRatio: false,\n animation: false,\n interaction: { intersect: false, mode: 'index' },\n plugins: {\n legend: {\n display: (graph?.graphLines.length ?? 0) > 1,\n labels: { color: axisColor, boxWidth: 10, boxHeight: 2 },\n },\n tooltip: {\n callbacks: {\n label: context => {\n const value = context.parsed.y;\n return `${context.dataset.label ?? ''}: ${value == null ? '—' : formatValue(value, graph?.unit ?? '')}`;\n },\n },\n },\n },\n scales: {\n x: {\n grid: { display: false },\n border: { color: gridColor },\n ticks: { color: axisColor, maxRotation: 0, autoSkip: true, maxTicksLimit: 8 },\n },\n y: {\n beginAtZero: true,\n grid: { color: gridColor },\n border: { display: false },\n ticks: {\n color: axisColor,\n callback: value => formatValue(Number(value), graph?.unit ?? ''),\n },\n },\n },\n }),\n [axisColor, graph, gridColor],\n );\n const hasData = graph?.graphLines.some(line => line.values.length > 0) === true;\n\n return (\n <section className=\"min-w-0 rounded-lg border border-border bg-card-bg p-4\" data-slot=\"agent-metric-chart\">\n <h3 className=\"text-sm font-semibold text-text-primary\">{graph?.displayName ?? definition.displayName}</h3>\n <p className=\"mt-1 text-xs text-text-secondary\">{graph?.description ?? definition.description}</p>\n <div className=\"mt-4 h-64\">\n {error != null ? (\n <div className=\"flex h-full items-center justify-center text-sm text-failure-bg\">{error}</div>\n ) : hasData ? (\n <Line data={data} options={options} />\n ) : (\n <div className=\"flex h-full items-center justify-center text-sm text-text-secondary\">No data</div>\n )}\n </div>\n </section>\n );\n}\n\ndeclare module '../../theme/SlotsProvider.js' {\n interface AtomSlots {\n AgentMetricChart: ComponentType<AgentMetricChartProps>;\n }\n}\n"],"mappings":"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","names":[]}
|