@getcatalystiq/agent-plane-ui 0.1.15 → 0.1.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.cjs +486 -3
- package/dist/index.d.cts +65 -1
- package/dist/index.d.ts +65 -1
- package/dist/index.js +485 -4
- package/package.json +6 -1
package/dist/index.cjs
CHANGED
|
@@ -7,6 +7,7 @@ var swr = require('swr');
|
|
|
7
7
|
var ReactMarkdown = require('react-markdown');
|
|
8
8
|
var cmdk = require('cmdk');
|
|
9
9
|
var Popover = require('@radix-ui/react-popover');
|
|
10
|
+
var remarkGfm = require('remark-gfm');
|
|
10
11
|
|
|
11
12
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
13
|
|
|
@@ -31,6 +32,7 @@ function _interopNamespace(e) {
|
|
|
31
32
|
var React3__namespace = /*#__PURE__*/_interopNamespace(React3);
|
|
32
33
|
var ReactMarkdown__default = /*#__PURE__*/_interopDefault(ReactMarkdown);
|
|
33
34
|
var Popover__namespace = /*#__PURE__*/_interopNamespace(Popover);
|
|
35
|
+
var remarkGfm__default = /*#__PURE__*/_interopDefault(remarkGfm);
|
|
34
36
|
|
|
35
37
|
function Select({ className = "", ...props }) {
|
|
36
38
|
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative w-full", children: [
|
|
@@ -2528,8 +2530,10 @@ function AgentEditForm({ agent, onSaved }) {
|
|
|
2528
2530
|
const [maxTurns, setMaxTurns] = React3.useState(agent.max_turns.toString());
|
|
2529
2531
|
const [maxBudget, setMaxBudget] = React3.useState(agent.max_budget_usd.toString());
|
|
2530
2532
|
const [maxRuntime, setMaxRuntime] = React3.useState(Math.floor(agent.max_runtime_seconds / 60).toString());
|
|
2533
|
+
const [soulMd, setSoulMd] = React3.useState(agent.soul_md ?? "");
|
|
2534
|
+
const [identityMd, setIdentityMd] = React3.useState(agent.identity_md ?? "");
|
|
2531
2535
|
const [saving, setSaving] = React3.useState(false);
|
|
2532
|
-
const isDirty = name !== agent.name || description !== (agent.description ?? "") || model !== agent.model || runner !== (agent.runner ?? "") || permissionMode !== agent.permission_mode || maxTurns !== agent.max_turns.toString() || maxBudget !== agent.max_budget_usd.toString() || maxRuntime !== Math.floor(agent.max_runtime_seconds / 60).toString();
|
|
2536
|
+
const isDirty = name !== agent.name || description !== (agent.description ?? "") || model !== agent.model || runner !== (agent.runner ?? "") || permissionMode !== agent.permission_mode || maxTurns !== agent.max_turns.toString() || maxBudget !== agent.max_budget_usd.toString() || maxRuntime !== Math.floor(agent.max_runtime_seconds / 60).toString() || soulMd !== (agent.soul_md ?? "") || identityMd !== (agent.identity_md ?? "");
|
|
2533
2537
|
const [error, setError] = React3.useState("");
|
|
2534
2538
|
async function handleSave() {
|
|
2535
2539
|
setSaving(true);
|
|
@@ -2543,7 +2547,9 @@ function AgentEditForm({ agent, onSaved }) {
|
|
|
2543
2547
|
permission_mode: permissionMode,
|
|
2544
2548
|
max_turns: parseInt(maxTurns) || agent.max_turns,
|
|
2545
2549
|
max_budget_usd: parseFloat(maxBudget) || agent.max_budget_usd,
|
|
2546
|
-
max_runtime_seconds: (parseInt(maxRuntime) || Math.floor(agent.max_runtime_seconds / 60)) * 60
|
|
2550
|
+
max_runtime_seconds: (parseInt(maxRuntime) || Math.floor(agent.max_runtime_seconds / 60)) * 60,
|
|
2551
|
+
soul_md: soulMd || null,
|
|
2552
|
+
identity_md: identityMd || null
|
|
2547
2553
|
});
|
|
2548
2554
|
onSaved?.();
|
|
2549
2555
|
} catch (err) {
|
|
@@ -2605,7 +2611,46 @@ function AgentEditForm({ agent, onSaved }) {
|
|
|
2605
2611
|
/* @__PURE__ */ jsxRuntime.jsx("option", { value: "plan", children: "plan" })
|
|
2606
2612
|
] }) }) })
|
|
2607
2613
|
] })
|
|
2608
|
-
] }) })
|
|
2614
|
+
] }) }),
|
|
2615
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-lg border border-muted-foreground/25 p-5", children: [
|
|
2616
|
+
/* @__PURE__ */ jsxRuntime.jsx(SectionHeader, { title: "Identity" }),
|
|
2617
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
2618
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(FormField, { label: "SOUL.md", children: [
|
|
2619
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2620
|
+
Textarea,
|
|
2621
|
+
{
|
|
2622
|
+
value: soulMd,
|
|
2623
|
+
onChange: (e) => setSoulMd(e.target.value),
|
|
2624
|
+
placeholder: "## Voice & Tone\nDirect, concise, technical.\n\n## Values\nClarity over completeness.\n\n## Stance\nProactive problem-solver.\n\n## Boundaries\n- Never modify production data directly\n\n## Essence\nA focused engineering assistant.",
|
|
2625
|
+
rows: 10,
|
|
2626
|
+
className: "font-mono text-sm",
|
|
2627
|
+
disabled: saving
|
|
2628
|
+
}
|
|
2629
|
+
),
|
|
2630
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground mt-1 block", children: [
|
|
2631
|
+
soulMd.split(/\s+/).filter(Boolean).length,
|
|
2632
|
+
" words"
|
|
2633
|
+
] })
|
|
2634
|
+
] }) }),
|
|
2635
|
+
/* @__PURE__ */ jsxRuntime.jsx("div", { children: /* @__PURE__ */ jsxRuntime.jsxs(FormField, { label: "IDENTITY.md", children: [
|
|
2636
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
2637
|
+
Textarea,
|
|
2638
|
+
{
|
|
2639
|
+
value: identityMd,
|
|
2640
|
+
onChange: (e) => setIdentityMd(e.target.value),
|
|
2641
|
+
placeholder: "- **Communication Verbosity:** concise\n- **Communication Tone:** direct\n- **Decision Autonomy:** high\n- **Risk Tolerance:** moderate\n- **Collaboration Mode:** autonomous\n\n## Escalation Preferences\n- Budget over $50 -> escalate\n- Breaking changes -> escalate",
|
|
2642
|
+
rows: 10,
|
|
2643
|
+
className: "font-mono text-sm",
|
|
2644
|
+
disabled: saving
|
|
2645
|
+
}
|
|
2646
|
+
),
|
|
2647
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground mt-1 block", children: [
|
|
2648
|
+
identityMd.split(/\s+/).filter(Boolean).length,
|
|
2649
|
+
" words"
|
|
2650
|
+
] })
|
|
2651
|
+
] }) })
|
|
2652
|
+
] }) })
|
|
2653
|
+
] })
|
|
2609
2654
|
] });
|
|
2610
2655
|
}
|
|
2611
2656
|
function ToolkitMultiselect({ value, onChange }) {
|
|
@@ -4386,6 +4431,443 @@ function ScheduleCard({
|
|
|
4386
4431
|
] })
|
|
4387
4432
|
] });
|
|
4388
4433
|
}
|
|
4434
|
+
function MarkdownContent({ children }) {
|
|
4435
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-sm text-foreground [&_p]:my-1 [&_h1]:text-lg [&_h1]:font-bold [&_h1]:my-2 [&_h2]:text-base [&_h2]:font-semibold [&_h2]:my-2 [&_h3]:text-sm [&_h3]:font-semibold [&_h3]:my-1 [&_ul]:list-disc [&_ul]:pl-5 [&_ul]:my-1 [&_ol]:list-decimal [&_ol]:pl-5 [&_ol]:my-1 [&_li]:my-0.5 [&_pre]:bg-muted [&_pre]:rounded-md [&_pre]:p-3 [&_pre]:overflow-x-auto [&_pre]:text-xs [&_pre]:my-2 [&_code:not(pre_code)]:bg-muted [&_code:not(pre_code)]:px-1 [&_code:not(pre_code)]:py-0.5 [&_code:not(pre_code)]:rounded [&_code:not(pre_code)]:text-xs [&_code:not(pre_code)]:font-mono [&_a]:text-blue-400 [&_a]:underline [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground [&_blockquote]:my-2 [&_hr]:border-border [&_hr]:my-3 [&_table]:border-collapse [&_table]:text-xs [&_table]:w-full [&_th]:border [&_th]:border-border [&_th]:px-2 [&_th]:py-1 [&_th]:text-left [&_th]:font-semibold [&_th]:bg-muted [&_td]:border [&_td]:border-border [&_td]:px-2 [&_td]:py-1 [&_strong]:font-semibold [&_em]:italic", children: /* @__PURE__ */ jsxRuntime.jsx(
|
|
4436
|
+
ReactMarkdown__default.default,
|
|
4437
|
+
{
|
|
4438
|
+
remarkPlugins: [remarkGfm__default.default],
|
|
4439
|
+
components: {
|
|
4440
|
+
a: ({ href, children: linkChildren }) => /* @__PURE__ */ jsxRuntime.jsx("a", { href, target: "_blank", rel: "noopener noreferrer", children: linkChildren })
|
|
4441
|
+
},
|
|
4442
|
+
children
|
|
4443
|
+
}
|
|
4444
|
+
) });
|
|
4445
|
+
}
|
|
4446
|
+
function CollapsibleJson({ data, maxHeight = "12rem" }) {
|
|
4447
|
+
const [expanded, setExpanded] = React3.useState(false);
|
|
4448
|
+
const json = typeof data === "string" ? data : JSON.stringify(data, null, 2);
|
|
4449
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "relative", children: [
|
|
4450
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4451
|
+
"pre",
|
|
4452
|
+
{
|
|
4453
|
+
className: `text-xs font-mono text-muted-foreground bg-muted/50 rounded-md p-2 overflow-x-auto whitespace-pre-wrap break-all ${expanded ? "" : "overflow-hidden"}`,
|
|
4454
|
+
style: expanded ? void 0 : { maxHeight },
|
|
4455
|
+
children: json
|
|
4456
|
+
}
|
|
4457
|
+
),
|
|
4458
|
+
json.length > 200 && /* @__PURE__ */ jsxRuntime.jsx(
|
|
4459
|
+
"button",
|
|
4460
|
+
{
|
|
4461
|
+
onClick: () => setExpanded(!expanded),
|
|
4462
|
+
className: "text-xs text-blue-400 hover:text-blue-300 mt-1",
|
|
4463
|
+
children: expanded ? "Collapse" : "Expand"
|
|
4464
|
+
}
|
|
4465
|
+
)
|
|
4466
|
+
] });
|
|
4467
|
+
}
|
|
4468
|
+
function renderEvent(event, idx) {
|
|
4469
|
+
if (event.type === "heartbeat") return null;
|
|
4470
|
+
if (event.type === "text_delta") return null;
|
|
4471
|
+
if (event.type === "session_created") return null;
|
|
4472
|
+
if (event.type === "session_info") return null;
|
|
4473
|
+
if (event.type === "mcp_status") return null;
|
|
4474
|
+
if (event.type === "rate_limit_event") return null;
|
|
4475
|
+
if (event.type === "user_message") {
|
|
4476
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "border-t border-border pt-3 mt-1", children: [
|
|
4477
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-emerald-400 uppercase", children: "You" }),
|
|
4478
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground mt-1 whitespace-pre-wrap", children: String(event.text) })
|
|
4479
|
+
] }, idx);
|
|
4480
|
+
}
|
|
4481
|
+
if (event.type === "assistant") {
|
|
4482
|
+
const content = event.message;
|
|
4483
|
+
const blocks = content?.content ?? [];
|
|
4484
|
+
const textBlocks = blocks.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
4485
|
+
const toolUseBlocks = blocks.filter((c) => c.type === "tool_use");
|
|
4486
|
+
if (!textBlocks && toolUseBlocks.length === 0) return null;
|
|
4487
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2", children: [
|
|
4488
|
+
textBlocks && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
4489
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-blue-400 uppercase", children: "Assistant" }),
|
|
4490
|
+
/* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { children: textBlocks })
|
|
4491
|
+
] }),
|
|
4492
|
+
toolUseBlocks.map((tool, ti) => /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 ml-3 pl-3 border-l-2 border-yellow-800/50", children: [
|
|
4493
|
+
/* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs font-semibold text-yellow-400 uppercase", children: [
|
|
4494
|
+
"Tool Call: ",
|
|
4495
|
+
tool.name ?? "unknown"
|
|
4496
|
+
] }),
|
|
4497
|
+
tool.id && /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground ml-2 font-mono", children: String(tool.id) }),
|
|
4498
|
+
tool.input != null && /* @__PURE__ */ jsxRuntime.jsx(CollapsibleJson, { data: tool.input })
|
|
4499
|
+
] }, ti))
|
|
4500
|
+
] }, idx);
|
|
4501
|
+
}
|
|
4502
|
+
if (event.type === "tool_use") {
|
|
4503
|
+
const toolName = String(event.tool_name ?? event.name ?? "unknown");
|
|
4504
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1 ml-3 pl-3 border-l-2 border-yellow-800/50", children: [
|
|
4505
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4506
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-yellow-400 uppercase", children: "Tool Call" }),
|
|
4507
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-mono text-yellow-400/80", children: toolName }),
|
|
4508
|
+
event.tool_use_id ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground font-mono", children: String(event.tool_use_id) }) : null
|
|
4509
|
+
] }),
|
|
4510
|
+
event.input != null ? /* @__PURE__ */ jsxRuntime.jsx(CollapsibleJson, { data: event.input }) : null
|
|
4511
|
+
] }, idx);
|
|
4512
|
+
}
|
|
4513
|
+
if (event.type === "tool_result") {
|
|
4514
|
+
const isError = event.is_error === true || event.error === true;
|
|
4515
|
+
const content = event.output ?? event.content ?? "";
|
|
4516
|
+
const contentStr = typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
4517
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `space-y-1 ml-3 pl-3 border-l-2 ${isError ? "border-red-800/50" : "border-green-800/50"}`, children: [
|
|
4518
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4519
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xs font-semibold uppercase ${isError ? "text-red-400" : "text-green-400"}`, children: isError ? "Tool Error" : "Tool Result" }),
|
|
4520
|
+
event.tool_name ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-mono text-muted-foreground", children: String(event.tool_name) }) : null,
|
|
4521
|
+
event.tool_use_id ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground font-mono", children: String(event.tool_use_id) }) : null
|
|
4522
|
+
] }),
|
|
4523
|
+
contentStr ? /* @__PURE__ */ jsxRuntime.jsx(CollapsibleJson, { data: contentStr }) : null
|
|
4524
|
+
] }, idx);
|
|
4525
|
+
}
|
|
4526
|
+
if (event.type === "result") {
|
|
4527
|
+
const success = event.subtype === "success";
|
|
4528
|
+
const costUsd = event.cost_usd ?? event.total_cost_usd;
|
|
4529
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: `rounded-md px-3 py-2 flex items-center gap-3 ${success ? "bg-green-950 border border-green-900" : "bg-red-950 border border-red-900"}`, children: [
|
|
4530
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: `text-xs font-semibold ${success ? "text-green-400" : "text-red-400"}`, children: success ? "Completed" : "Failed" }),
|
|
4531
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-wrap gap-3 text-xs text-zinc-400", children: [
|
|
4532
|
+
event.num_turns != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
4533
|
+
String(event.num_turns),
|
|
4534
|
+
" turns"
|
|
4535
|
+
] }),
|
|
4536
|
+
costUsd != null && Number(costUsd) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
4537
|
+
"$",
|
|
4538
|
+
Number(costUsd).toFixed(4)
|
|
4539
|
+
] }),
|
|
4540
|
+
event.duration_ms != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
4541
|
+
(Number(event.duration_ms) / 1e3).toFixed(1),
|
|
4542
|
+
"s"
|
|
4543
|
+
] }),
|
|
4544
|
+
event.duration_api_ms != null && /* @__PURE__ */ jsxRuntime.jsxs("span", { children: [
|
|
4545
|
+
"API: ",
|
|
4546
|
+
(Number(event.duration_api_ms) / 1e3).toFixed(1),
|
|
4547
|
+
"s"
|
|
4548
|
+
] })
|
|
4549
|
+
] })
|
|
4550
|
+
] }, idx);
|
|
4551
|
+
}
|
|
4552
|
+
if (event.type === "error") {
|
|
4553
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "rounded-md p-3 bg-red-950 border border-red-800", children: [
|
|
4554
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4555
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm font-semibold text-red-400", children: "Error" }),
|
|
4556
|
+
event.code ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-mono text-red-400/70", children: String(event.code) }) : null
|
|
4557
|
+
] }),
|
|
4558
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-foreground mt-1", children: String(event.error ?? "Unknown error") })
|
|
4559
|
+
] }, idx);
|
|
4560
|
+
}
|
|
4561
|
+
if (event.type === "stream_detached") {
|
|
4562
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground italic border-t border-border pt-2", children: [
|
|
4563
|
+
"Stream detached at ",
|
|
4564
|
+
event.timestamp ? new Date(String(event.timestamp)).toLocaleTimeString() : "unknown",
|
|
4565
|
+
" \u2014 run continues in background"
|
|
4566
|
+
] }, idx);
|
|
4567
|
+
}
|
|
4568
|
+
if (event.type === "queued") {
|
|
4569
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground", children: "Queued\u2026" }, idx);
|
|
4570
|
+
}
|
|
4571
|
+
if (event.type === "sandbox_starting") {
|
|
4572
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground", children: "Starting sandbox\u2026" }, idx);
|
|
4573
|
+
}
|
|
4574
|
+
if (event.type === "run_started") {
|
|
4575
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "text-xs text-muted-foreground", children: [
|
|
4576
|
+
"Agent started",
|
|
4577
|
+
event.model ? /* @__PURE__ */ jsxRuntime.jsx("span", { className: "ml-2 font-mono text-foreground/60", children: String(event.model) }) : null,
|
|
4578
|
+
event.mcp_server_count != null && Number(event.mcp_server_count) > 0 && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "ml-2", children: [
|
|
4579
|
+
String(event.mcp_server_count),
|
|
4580
|
+
" MCP server",
|
|
4581
|
+
Number(event.mcp_server_count) !== 1 ? "s" : ""
|
|
4582
|
+
] })
|
|
4583
|
+
] }, idx);
|
|
4584
|
+
}
|
|
4585
|
+
if (event.type === "system") {
|
|
4586
|
+
return /* @__PURE__ */ jsxRuntime.jsx("div", { className: "text-xs text-muted-foreground italic", children: String(event.message ?? JSON.stringify(event)) }, idx);
|
|
4587
|
+
}
|
|
4588
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
4589
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-purple-400 uppercase", children: event.type }),
|
|
4590
|
+
/* @__PURE__ */ jsxRuntime.jsx(CollapsibleJson, { data: event, maxHeight: "8rem" })
|
|
4591
|
+
] }, idx);
|
|
4592
|
+
}
|
|
4593
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled", "timed_out"]);
|
|
4594
|
+
function PlaygroundPage({ agentId }) {
|
|
4595
|
+
const client = chunk4XBBDUSZ_cjs.useAgentPlaneClient();
|
|
4596
|
+
const { LinkComponent, basePath } = chunk4XBBDUSZ_cjs.useNavigation();
|
|
4597
|
+
const { data: agent, error: agentError, isLoading } = chunk4XBBDUSZ_cjs.useApi(
|
|
4598
|
+
`agent-${agentId}`,
|
|
4599
|
+
(c) => c.agents.get(agentId)
|
|
4600
|
+
);
|
|
4601
|
+
const [prompt, setPrompt] = React3.useState("");
|
|
4602
|
+
const [events, setEvents] = React3.useState([]);
|
|
4603
|
+
const [streamingText, setStreamingText] = React3.useState("");
|
|
4604
|
+
const [running, setRunning] = React3.useState(false);
|
|
4605
|
+
const [polling, setPolling] = React3.useState(false);
|
|
4606
|
+
const [error, setError] = React3.useState(null);
|
|
4607
|
+
const [sessionId, setSessionId] = React3.useState(null);
|
|
4608
|
+
const sessionIdRef = React3.useRef(null);
|
|
4609
|
+
const abortRef = React3.useRef(null);
|
|
4610
|
+
const runIdRef = React3.useRef(null);
|
|
4611
|
+
const streamRef = React3.useRef(null);
|
|
4612
|
+
const scrollRef = React3.useRef(null);
|
|
4613
|
+
const textareaRef = React3.useRef(null);
|
|
4614
|
+
React3.useEffect(() => {
|
|
4615
|
+
const el = scrollRef.current;
|
|
4616
|
+
if (el) el.scrollTop = el.scrollHeight;
|
|
4617
|
+
}, [events, streamingText]);
|
|
4618
|
+
React3.useEffect(() => {
|
|
4619
|
+
return () => {
|
|
4620
|
+
abortRef.current?.abort();
|
|
4621
|
+
streamRef.current?.abort();
|
|
4622
|
+
};
|
|
4623
|
+
}, []);
|
|
4624
|
+
const pollForFinalResult = React3.useCallback(async (runId) => {
|
|
4625
|
+
setPolling(true);
|
|
4626
|
+
let delay = 3e3;
|
|
4627
|
+
const maxDelay = 1e4;
|
|
4628
|
+
try {
|
|
4629
|
+
while (true) {
|
|
4630
|
+
if (abortRef.current?.signal.aborted) break;
|
|
4631
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
4632
|
+
if (abortRef.current?.signal.aborted) break;
|
|
4633
|
+
try {
|
|
4634
|
+
const run = await client.runs.get(runId);
|
|
4635
|
+
if (TERMINAL_STATUSES.has(run.status)) {
|
|
4636
|
+
try {
|
|
4637
|
+
const transcriptEvents = await client.runs.transcriptArray(runId);
|
|
4638
|
+
if (transcriptEvents.length > 0) {
|
|
4639
|
+
const detachIdx = transcriptEvents.findIndex((ev) => ev.type === "stream_detached");
|
|
4640
|
+
const eventsAfterDetach = detachIdx >= 0 ? transcriptEvents.slice(detachIdx + 1) : [];
|
|
4641
|
+
const newEvents = eventsAfterDetach.filter(
|
|
4642
|
+
(ev) => ev.type !== "heartbeat" && ev.type !== "text_delta" && ev.type !== "run_started" && ev.type !== "queued" && ev.type !== "sandbox_starting"
|
|
4643
|
+
);
|
|
4644
|
+
if (newEvents.length > 0) {
|
|
4645
|
+
setEvents((prev) => [...prev, ...newEvents]);
|
|
4646
|
+
}
|
|
4647
|
+
}
|
|
4648
|
+
} catch {
|
|
4649
|
+
}
|
|
4650
|
+
setEvents((prev) => {
|
|
4651
|
+
if (prev.some((ev) => ev.type === "result")) return prev;
|
|
4652
|
+
const syntheticResult = {
|
|
4653
|
+
type: "result",
|
|
4654
|
+
subtype: run.status === "completed" ? "success" : "failed",
|
|
4655
|
+
cost_usd: run.cost_usd,
|
|
4656
|
+
num_turns: run.num_turns,
|
|
4657
|
+
duration_ms: run.duration_ms
|
|
4658
|
+
};
|
|
4659
|
+
if (run.error_type) {
|
|
4660
|
+
syntheticResult.result = run.error_type;
|
|
4661
|
+
}
|
|
4662
|
+
return [...prev, syntheticResult];
|
|
4663
|
+
});
|
|
4664
|
+
break;
|
|
4665
|
+
}
|
|
4666
|
+
delay = Math.min(delay * 2, maxDelay);
|
|
4667
|
+
} catch (err) {
|
|
4668
|
+
if (err?.name === "AbortError") break;
|
|
4669
|
+
delay = Math.min(delay * 2, maxDelay);
|
|
4670
|
+
}
|
|
4671
|
+
}
|
|
4672
|
+
} finally {
|
|
4673
|
+
setPolling(false);
|
|
4674
|
+
setRunning(false);
|
|
4675
|
+
abortRef.current = null;
|
|
4676
|
+
runIdRef.current = null;
|
|
4677
|
+
streamRef.current = null;
|
|
4678
|
+
}
|
|
4679
|
+
}, [client]);
|
|
4680
|
+
const consumeStream = React3.useCallback(async (stream) => {
|
|
4681
|
+
streamRef.current = stream;
|
|
4682
|
+
let handedOffToPoll = false;
|
|
4683
|
+
try {
|
|
4684
|
+
for await (const event of stream) {
|
|
4685
|
+
const ev = event;
|
|
4686
|
+
if (ev.type === "session_created" && ev.session_id) {
|
|
4687
|
+
const sid = ev.session_id;
|
|
4688
|
+
sessionIdRef.current = sid;
|
|
4689
|
+
setSessionId(sid);
|
|
4690
|
+
}
|
|
4691
|
+
if (ev.type === "run_started" && ev.run_id) {
|
|
4692
|
+
runIdRef.current = ev.run_id;
|
|
4693
|
+
}
|
|
4694
|
+
if (ev.type === "text_delta") {
|
|
4695
|
+
setStreamingText((prev) => prev + (ev.text ?? ""));
|
|
4696
|
+
} else if (ev.type === "stream_detached") {
|
|
4697
|
+
setStreamingText("");
|
|
4698
|
+
setEvents((prev) => [...prev, ev]);
|
|
4699
|
+
if (runIdRef.current) {
|
|
4700
|
+
handedOffToPoll = true;
|
|
4701
|
+
pollForFinalResult(runIdRef.current);
|
|
4702
|
+
return;
|
|
4703
|
+
}
|
|
4704
|
+
} else {
|
|
4705
|
+
if (ev.type === "assistant") setStreamingText("");
|
|
4706
|
+
setEvents((prev) => [...prev, ev]);
|
|
4707
|
+
}
|
|
4708
|
+
}
|
|
4709
|
+
} finally {
|
|
4710
|
+
if (!handedOffToPoll) {
|
|
4711
|
+
setRunning(false);
|
|
4712
|
+
abortRef.current = null;
|
|
4713
|
+
runIdRef.current = null;
|
|
4714
|
+
streamRef.current = null;
|
|
4715
|
+
}
|
|
4716
|
+
}
|
|
4717
|
+
}, [pollForFinalResult]);
|
|
4718
|
+
const handleSend = React3.useCallback(async () => {
|
|
4719
|
+
if (!prompt.trim() || running) return;
|
|
4720
|
+
const messageText = prompt.trim();
|
|
4721
|
+
setPrompt("");
|
|
4722
|
+
setRunning(true);
|
|
4723
|
+
setStreamingText("");
|
|
4724
|
+
setError(null);
|
|
4725
|
+
setPolling(false);
|
|
4726
|
+
setEvents((prev) => [...prev, { type: "user_message", text: messageText }]);
|
|
4727
|
+
const abort = new AbortController();
|
|
4728
|
+
abortRef.current = abort;
|
|
4729
|
+
try {
|
|
4730
|
+
let stream;
|
|
4731
|
+
const currentSessionId = sessionIdRef.current;
|
|
4732
|
+
if (currentSessionId) {
|
|
4733
|
+
stream = await client.sessions.sendMessage(
|
|
4734
|
+
currentSessionId,
|
|
4735
|
+
{ prompt: messageText },
|
|
4736
|
+
{ signal: abort.signal }
|
|
4737
|
+
);
|
|
4738
|
+
} else {
|
|
4739
|
+
stream = await client.sessions.create(
|
|
4740
|
+
{ agent_id: agentId, prompt: messageText },
|
|
4741
|
+
{ signal: abort.signal }
|
|
4742
|
+
);
|
|
4743
|
+
}
|
|
4744
|
+
await consumeStream(stream);
|
|
4745
|
+
} catch (err) {
|
|
4746
|
+
if (err?.name !== "AbortError") {
|
|
4747
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
4748
|
+
setError(msg);
|
|
4749
|
+
}
|
|
4750
|
+
setRunning(false);
|
|
4751
|
+
abortRef.current = null;
|
|
4752
|
+
runIdRef.current = null;
|
|
4753
|
+
streamRef.current = null;
|
|
4754
|
+
}
|
|
4755
|
+
}, [prompt, running, agentId, client, consumeStream]);
|
|
4756
|
+
function handleNewChat() {
|
|
4757
|
+
abortRef.current?.abort();
|
|
4758
|
+
streamRef.current?.abort();
|
|
4759
|
+
if (sessionId) {
|
|
4760
|
+
client.sessions.stop(sessionId).catch(() => {
|
|
4761
|
+
});
|
|
4762
|
+
}
|
|
4763
|
+
sessionIdRef.current = null;
|
|
4764
|
+
setSessionId(null);
|
|
4765
|
+
setEvents([]);
|
|
4766
|
+
setStreamingText("");
|
|
4767
|
+
setRunning(false);
|
|
4768
|
+
setPolling(false);
|
|
4769
|
+
setError(null);
|
|
4770
|
+
setPrompt("");
|
|
4771
|
+
runIdRef.current = null;
|
|
4772
|
+
abortRef.current = null;
|
|
4773
|
+
streamRef.current = null;
|
|
4774
|
+
textareaRef.current?.focus();
|
|
4775
|
+
}
|
|
4776
|
+
function handleStop() {
|
|
4777
|
+
abortRef.current?.abort();
|
|
4778
|
+
streamRef.current?.abort();
|
|
4779
|
+
const id = runIdRef.current;
|
|
4780
|
+
if (id) {
|
|
4781
|
+
runIdRef.current = null;
|
|
4782
|
+
client.runs.cancel(id).catch(() => {
|
|
4783
|
+
});
|
|
4784
|
+
}
|
|
4785
|
+
}
|
|
4786
|
+
if (isLoading) {
|
|
4787
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-[calc(100vh-6rem)]", children: [
|
|
4788
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
4789
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunk4XBBDUSZ_cjs.Skeleton, { className: "h-8 w-24" }),
|
|
4790
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunk4XBBDUSZ_cjs.Skeleton, { className: "h-4 w-40" })
|
|
4791
|
+
] }),
|
|
4792
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunk4XBBDUSZ_cjs.Skeleton, { className: "flex-1 rounded-lg" }),
|
|
4793
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "mt-4 space-y-2", children: [
|
|
4794
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunk4XBBDUSZ_cjs.Skeleton, { className: "h-24 w-full rounded-lg" }),
|
|
4795
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunk4XBBDUSZ_cjs.Skeleton, { className: "h-8 w-20" })
|
|
4796
|
+
] })
|
|
4797
|
+
] });
|
|
4798
|
+
}
|
|
4799
|
+
if (agentError || !agent) {
|
|
4800
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col items-center justify-center h-[calc(100vh-6rem)] gap-3", children: [
|
|
4801
|
+
/* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-destructive text-sm", children: agentError?.status === 404 ? "Agent not found." : `Failed to load agent: ${agentError?.message ?? "Unknown error"}` }),
|
|
4802
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4803
|
+
LinkComponent,
|
|
4804
|
+
{
|
|
4805
|
+
href: `${basePath}/agents`,
|
|
4806
|
+
className: "text-sm text-muted-foreground hover:text-foreground",
|
|
4807
|
+
children: "\u2190 Back to agents"
|
|
4808
|
+
}
|
|
4809
|
+
)
|
|
4810
|
+
] });
|
|
4811
|
+
}
|
|
4812
|
+
const hasContent = events.length > 0 || running;
|
|
4813
|
+
return /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex flex-col h-[calc(100vh-6rem)]", children: [
|
|
4814
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
4815
|
+
/* @__PURE__ */ jsxRuntime.jsxs(
|
|
4816
|
+
LinkComponent,
|
|
4817
|
+
{
|
|
4818
|
+
href: `${basePath}/agents/${agentId}`,
|
|
4819
|
+
className: "text-sm text-muted-foreground hover:text-foreground",
|
|
4820
|
+
children: [
|
|
4821
|
+
"\u2190 ",
|
|
4822
|
+
agent.name
|
|
4823
|
+
]
|
|
4824
|
+
}
|
|
4825
|
+
),
|
|
4826
|
+
(sessionId || events.length > 0) && /* @__PURE__ */ jsxRuntime.jsx(chunk4XBBDUSZ_cjs.Button, { onClick: handleNewChat, variant: "outline", size: "sm", disabled: running, children: "New Chat" }),
|
|
4827
|
+
sessionId && /* @__PURE__ */ jsxRuntime.jsxs("span", { className: "text-xs text-muted-foreground font-mono", children: [
|
|
4828
|
+
"Session: ",
|
|
4829
|
+
sessionId.slice(0, 12),
|
|
4830
|
+
"\u2026"
|
|
4831
|
+
] })
|
|
4832
|
+
] }),
|
|
4833
|
+
hasContent && /* @__PURE__ */ jsxRuntime.jsxs("div", { ref: scrollRef, className: "flex-1 min-h-0 overflow-y-auto rounded-lg border border-border bg-muted/20 p-4 space-y-4 mb-4", children: [
|
|
4834
|
+
events.map((ev, i) => renderEvent(ev, i)),
|
|
4835
|
+
streamingText && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-1", children: [
|
|
4836
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs font-semibold text-blue-400 uppercase", children: "Assistant" }),
|
|
4837
|
+
/* @__PURE__ */ jsxRuntime.jsx(MarkdownContent, { children: streamingText }),
|
|
4838
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "inline-block w-0.5 h-4 bg-foreground animate-pulse align-text-bottom" })
|
|
4839
|
+
] }),
|
|
4840
|
+
running && !streamingText && /* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
4841
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "animate-pulse", children: "\u25CF" }),
|
|
4842
|
+
" ",
|
|
4843
|
+
polling ? "Reconnected, streaming updates\u2026" : "Running\u2026"
|
|
4844
|
+
] })
|
|
4845
|
+
] }),
|
|
4846
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "space-y-2 shrink-0", children: [
|
|
4847
|
+
error && /* @__PURE__ */ jsxRuntime.jsx("p", { className: "text-sm text-destructive", children: error }),
|
|
4848
|
+
/* @__PURE__ */ jsxRuntime.jsx(
|
|
4849
|
+
Textarea,
|
|
4850
|
+
{
|
|
4851
|
+
ref: textareaRef,
|
|
4852
|
+
placeholder: sessionId ? "Send a follow-up message\u2026" : "Enter your prompt\u2026",
|
|
4853
|
+
value: prompt,
|
|
4854
|
+
onChange: (e) => setPrompt(e.target.value),
|
|
4855
|
+
rows: hasContent ? 3 : 12,
|
|
4856
|
+
disabled: running,
|
|
4857
|
+
className: "font-mono text-sm resize-none",
|
|
4858
|
+
onKeyDown: (e) => {
|
|
4859
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) handleSend();
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4862
|
+
),
|
|
4863
|
+
/* @__PURE__ */ jsxRuntime.jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4864
|
+
/* @__PURE__ */ jsxRuntime.jsx(chunk4XBBDUSZ_cjs.Button, { onClick: handleSend, disabled: running || !prompt.trim(), size: "sm", children: running ? "Running\u2026" : sessionId ? "Send" : "Run" }),
|
|
4865
|
+
running && /* @__PURE__ */ jsxRuntime.jsx(chunk4XBBDUSZ_cjs.Button, { onClick: handleStop, variant: "outline", size: "sm", children: "Stop" }),
|
|
4866
|
+
/* @__PURE__ */ jsxRuntime.jsx("span", { className: "text-xs text-muted-foreground ml-1", children: "\u2318+Enter to send" })
|
|
4867
|
+
] })
|
|
4868
|
+
] })
|
|
4869
|
+
] });
|
|
4870
|
+
}
|
|
4389
4871
|
|
|
4390
4872
|
Object.defineProperty(exports, "AgentPlaneProvider", {
|
|
4391
4873
|
enumerable: true,
|
|
@@ -4486,6 +4968,7 @@ exports.McpServerListPage = McpServerListPage;
|
|
|
4486
4968
|
exports.MetricCard = MetricCard;
|
|
4487
4969
|
exports.ModelSelector = ModelSelector;
|
|
4488
4970
|
exports.PaginationBar = PaginationBar;
|
|
4971
|
+
exports.PlaygroundPage = PlaygroundPage;
|
|
4489
4972
|
exports.PluginDetailPage = PluginDetailPage;
|
|
4490
4973
|
exports.PluginMarketplaceDetailPage = PluginMarketplaceDetailPage;
|
|
4491
4974
|
exports.PluginMarketplaceListPage = PluginMarketplaceListPage;
|
package/dist/index.d.cts
CHANGED
|
@@ -7,6 +7,52 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
|
|
|
7
7
|
import { VariantProps } from 'class-variance-authority';
|
|
8
8
|
import { DailyAgentStat } from './charts.cjs';
|
|
9
9
|
|
|
10
|
+
/** Minimal stream event types used by the playground UI. */
|
|
11
|
+
interface PlaygroundTextDeltaEvent {
|
|
12
|
+
type: "text_delta";
|
|
13
|
+
text: string;
|
|
14
|
+
}
|
|
15
|
+
interface PlaygroundRunStartedEvent {
|
|
16
|
+
type: "run_started";
|
|
17
|
+
run_id: string;
|
|
18
|
+
agent_id: string;
|
|
19
|
+
model: string;
|
|
20
|
+
timestamp: string;
|
|
21
|
+
}
|
|
22
|
+
interface PlaygroundToolUseEvent {
|
|
23
|
+
type: "tool_use";
|
|
24
|
+
name?: string;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
interface PlaygroundToolResultEvent {
|
|
28
|
+
type: "tool_result";
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
interface PlaygroundResultEvent {
|
|
32
|
+
type: "result";
|
|
33
|
+
subtype: string;
|
|
34
|
+
total_cost_usd?: number;
|
|
35
|
+
num_turns?: number;
|
|
36
|
+
duration_ms?: number;
|
|
37
|
+
}
|
|
38
|
+
interface PlaygroundErrorEvent {
|
|
39
|
+
type: "error";
|
|
40
|
+
error: string;
|
|
41
|
+
code?: string;
|
|
42
|
+
}
|
|
43
|
+
interface PlaygroundSessionCreatedEvent {
|
|
44
|
+
type: "session_created";
|
|
45
|
+
session_id: string;
|
|
46
|
+
}
|
|
47
|
+
type PlaygroundStreamEvent = PlaygroundTextDeltaEvent | PlaygroundRunStartedEvent | PlaygroundToolUseEvent | PlaygroundToolResultEvent | PlaygroundResultEvent | PlaygroundErrorEvent | PlaygroundSessionCreatedEvent | {
|
|
48
|
+
type: string;
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
};
|
|
51
|
+
/** Async iterable stream of events (compatible with SDK RunStream). */
|
|
52
|
+
interface PlaygroundStream extends AsyncIterable<PlaygroundStreamEvent> {
|
|
53
|
+
run_id: string | null;
|
|
54
|
+
abort(reason?: unknown): void;
|
|
55
|
+
}
|
|
10
56
|
/**
|
|
11
57
|
* Structural interface for the AgentPlane SDK client.
|
|
12
58
|
* Declares all methods the UI actually uses, avoiding a hard compile-time
|
|
@@ -47,6 +93,17 @@ interface AgentPlaneClient {
|
|
|
47
93
|
list(params?: Record<string, unknown>): Promise<unknown>;
|
|
48
94
|
get(sessionId: string): Promise<unknown>;
|
|
49
95
|
stop(sessionId: string): Promise<unknown>;
|
|
96
|
+
create(params: {
|
|
97
|
+
agent_id: string;
|
|
98
|
+
prompt?: string;
|
|
99
|
+
}, options?: {
|
|
100
|
+
signal?: AbortSignal;
|
|
101
|
+
}): Promise<unknown | PlaygroundStream>;
|
|
102
|
+
sendMessage(sessionId: string, params: {
|
|
103
|
+
prompt: string;
|
|
104
|
+
}, options?: {
|
|
105
|
+
signal?: AbortSignal;
|
|
106
|
+
}): Promise<PlaygroundStream>;
|
|
50
107
|
};
|
|
51
108
|
connectors: {
|
|
52
109
|
list(agentId: string): Promise<unknown[]>;
|
|
@@ -555,6 +612,8 @@ interface Agent {
|
|
|
555
612
|
max_turns: number;
|
|
556
613
|
max_budget_usd: number;
|
|
557
614
|
max_runtime_seconds: number;
|
|
615
|
+
soul_md?: string | null;
|
|
616
|
+
identity_md?: string | null;
|
|
558
617
|
}
|
|
559
618
|
interface AgentEditFormProps {
|
|
560
619
|
agent: Agent;
|
|
@@ -632,6 +691,11 @@ interface Props$1 {
|
|
|
632
691
|
}
|
|
633
692
|
declare function AgentA2aInfo({ agentId, tenantSlug, agentSlug, baseUrl, initialEnabled, initialTags, onChanged, }: Props$1): react_jsx_runtime.JSX.Element;
|
|
634
693
|
|
|
694
|
+
interface PlaygroundPageProps {
|
|
695
|
+
agentId: string;
|
|
696
|
+
}
|
|
697
|
+
declare function PlaygroundPage({ agentId }: PlaygroundPageProps): react_jsx_runtime.JSX.Element;
|
|
698
|
+
|
|
635
699
|
interface ModelSelectorProps {
|
|
636
700
|
value: string;
|
|
637
701
|
onChange: (modelId: string) => void;
|
|
@@ -645,4 +709,4 @@ interface Props {
|
|
|
645
709
|
}
|
|
646
710
|
declare function ToolkitMultiselect({ value, onChange }: Props): react_jsx_runtime.JSX.Element;
|
|
647
711
|
|
|
648
|
-
export { AdminTable, AdminTableHead, AdminTableRow, AgentA2aInfo, AgentConnectorsManager, AgentDetailPage, AgentEditForm, AgentListPage, type AgentPlaneClient, AgentPlaneProvider, type AgentPlaneProviderProps, AgentPluginManager, AgentRuns, AgentScheduleForm, AgentSkillManager, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardDescription, CardHeader, CardTitle, ConfirmDialog, CopyButton, DashboardPage, type DashboardPageProps, DetailPageHeader, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, EmptyRow, FormError, FormField, Input, type LinkComponentProps, LocalDate, McpServerListPage, type McpServerListPageProps, MetricCard, ModelSelector, type NavigationProps, PaginationBar, PluginDetailPage, type PluginDetailPageProps, PluginMarketplaceDetailPage, type PluginMarketplaceDetailPageProps, PluginMarketplaceListPage, type PluginMarketplaceListPageProps, RunDetailPage, type RunDetailPageProps, RunListPage, type RunListPageProps, RunSourceBadge, RunStatusBadge, SectionHeader, Select, SettingsPage, type SettingsPageProps, Skeleton, Tabs, Textarea, type TextareaProps, Th, ToolkitMultiselect, TranscriptViewer, badgeVariants, buttonVariants, cn, parsePaginationParams, useAgentPlaneClient, useApi, useAuthError, useNavigation };
|
|
712
|
+
export { AdminTable, AdminTableHead, AdminTableRow, AgentA2aInfo, AgentConnectorsManager, AgentDetailPage, AgentEditForm, AgentListPage, type AgentPlaneClient, AgentPlaneProvider, type AgentPlaneProviderProps, AgentPluginManager, AgentRuns, AgentScheduleForm, AgentSkillManager, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardDescription, CardHeader, CardTitle, ConfirmDialog, CopyButton, DashboardPage, type DashboardPageProps, DetailPageHeader, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, EmptyRow, FormError, FormField, Input, type LinkComponentProps, LocalDate, McpServerListPage, type McpServerListPageProps, MetricCard, ModelSelector, type NavigationProps, PaginationBar, PlaygroundPage, type PlaygroundPageProps, type PlaygroundStream, type PlaygroundStreamEvent, PluginDetailPage, type PluginDetailPageProps, PluginMarketplaceDetailPage, type PluginMarketplaceDetailPageProps, PluginMarketplaceListPage, type PluginMarketplaceListPageProps, RunDetailPage, type RunDetailPageProps, RunListPage, type RunListPageProps, RunSourceBadge, RunStatusBadge, SectionHeader, Select, SettingsPage, type SettingsPageProps, Skeleton, Tabs, Textarea, type TextareaProps, Th, ToolkitMultiselect, TranscriptViewer, badgeVariants, buttonVariants, cn, parsePaginationParams, useAgentPlaneClient, useApi, useAuthError, useNavigation };
|
package/dist/index.d.ts
CHANGED
|
@@ -7,6 +7,52 @@ import * as class_variance_authority_types from 'class-variance-authority/types'
|
|
|
7
7
|
import { VariantProps } from 'class-variance-authority';
|
|
8
8
|
import { DailyAgentStat } from './charts.js';
|
|
9
9
|
|
|
10
|
+
/** Minimal stream event types used by the playground UI. */
|
|
11
|
+
interface PlaygroundTextDeltaEvent {
|
|
12
|
+
type: "text_delta";
|
|
13
|
+
text: string;
|
|
14
|
+
}
|
|
15
|
+
interface PlaygroundRunStartedEvent {
|
|
16
|
+
type: "run_started";
|
|
17
|
+
run_id: string;
|
|
18
|
+
agent_id: string;
|
|
19
|
+
model: string;
|
|
20
|
+
timestamp: string;
|
|
21
|
+
}
|
|
22
|
+
interface PlaygroundToolUseEvent {
|
|
23
|
+
type: "tool_use";
|
|
24
|
+
name?: string;
|
|
25
|
+
[key: string]: unknown;
|
|
26
|
+
}
|
|
27
|
+
interface PlaygroundToolResultEvent {
|
|
28
|
+
type: "tool_result";
|
|
29
|
+
[key: string]: unknown;
|
|
30
|
+
}
|
|
31
|
+
interface PlaygroundResultEvent {
|
|
32
|
+
type: "result";
|
|
33
|
+
subtype: string;
|
|
34
|
+
total_cost_usd?: number;
|
|
35
|
+
num_turns?: number;
|
|
36
|
+
duration_ms?: number;
|
|
37
|
+
}
|
|
38
|
+
interface PlaygroundErrorEvent {
|
|
39
|
+
type: "error";
|
|
40
|
+
error: string;
|
|
41
|
+
code?: string;
|
|
42
|
+
}
|
|
43
|
+
interface PlaygroundSessionCreatedEvent {
|
|
44
|
+
type: "session_created";
|
|
45
|
+
session_id: string;
|
|
46
|
+
}
|
|
47
|
+
type PlaygroundStreamEvent = PlaygroundTextDeltaEvent | PlaygroundRunStartedEvent | PlaygroundToolUseEvent | PlaygroundToolResultEvent | PlaygroundResultEvent | PlaygroundErrorEvent | PlaygroundSessionCreatedEvent | {
|
|
48
|
+
type: string;
|
|
49
|
+
[key: string]: unknown;
|
|
50
|
+
};
|
|
51
|
+
/** Async iterable stream of events (compatible with SDK RunStream). */
|
|
52
|
+
interface PlaygroundStream extends AsyncIterable<PlaygroundStreamEvent> {
|
|
53
|
+
run_id: string | null;
|
|
54
|
+
abort(reason?: unknown): void;
|
|
55
|
+
}
|
|
10
56
|
/**
|
|
11
57
|
* Structural interface for the AgentPlane SDK client.
|
|
12
58
|
* Declares all methods the UI actually uses, avoiding a hard compile-time
|
|
@@ -47,6 +93,17 @@ interface AgentPlaneClient {
|
|
|
47
93
|
list(params?: Record<string, unknown>): Promise<unknown>;
|
|
48
94
|
get(sessionId: string): Promise<unknown>;
|
|
49
95
|
stop(sessionId: string): Promise<unknown>;
|
|
96
|
+
create(params: {
|
|
97
|
+
agent_id: string;
|
|
98
|
+
prompt?: string;
|
|
99
|
+
}, options?: {
|
|
100
|
+
signal?: AbortSignal;
|
|
101
|
+
}): Promise<unknown | PlaygroundStream>;
|
|
102
|
+
sendMessage(sessionId: string, params: {
|
|
103
|
+
prompt: string;
|
|
104
|
+
}, options?: {
|
|
105
|
+
signal?: AbortSignal;
|
|
106
|
+
}): Promise<PlaygroundStream>;
|
|
50
107
|
};
|
|
51
108
|
connectors: {
|
|
52
109
|
list(agentId: string): Promise<unknown[]>;
|
|
@@ -555,6 +612,8 @@ interface Agent {
|
|
|
555
612
|
max_turns: number;
|
|
556
613
|
max_budget_usd: number;
|
|
557
614
|
max_runtime_seconds: number;
|
|
615
|
+
soul_md?: string | null;
|
|
616
|
+
identity_md?: string | null;
|
|
558
617
|
}
|
|
559
618
|
interface AgentEditFormProps {
|
|
560
619
|
agent: Agent;
|
|
@@ -632,6 +691,11 @@ interface Props$1 {
|
|
|
632
691
|
}
|
|
633
692
|
declare function AgentA2aInfo({ agentId, tenantSlug, agentSlug, baseUrl, initialEnabled, initialTags, onChanged, }: Props$1): react_jsx_runtime.JSX.Element;
|
|
634
693
|
|
|
694
|
+
interface PlaygroundPageProps {
|
|
695
|
+
agentId: string;
|
|
696
|
+
}
|
|
697
|
+
declare function PlaygroundPage({ agentId }: PlaygroundPageProps): react_jsx_runtime.JSX.Element;
|
|
698
|
+
|
|
635
699
|
interface ModelSelectorProps {
|
|
636
700
|
value: string;
|
|
637
701
|
onChange: (modelId: string) => void;
|
|
@@ -645,4 +709,4 @@ interface Props {
|
|
|
645
709
|
}
|
|
646
710
|
declare function ToolkitMultiselect({ value, onChange }: Props): react_jsx_runtime.JSX.Element;
|
|
647
711
|
|
|
648
|
-
export { AdminTable, AdminTableHead, AdminTableRow, AgentA2aInfo, AgentConnectorsManager, AgentDetailPage, AgentEditForm, AgentListPage, type AgentPlaneClient, AgentPlaneProvider, type AgentPlaneProviderProps, AgentPluginManager, AgentRuns, AgentScheduleForm, AgentSkillManager, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardDescription, CardHeader, CardTitle, ConfirmDialog, CopyButton, DashboardPage, type DashboardPageProps, DetailPageHeader, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, EmptyRow, FormError, FormField, Input, type LinkComponentProps, LocalDate, McpServerListPage, type McpServerListPageProps, MetricCard, ModelSelector, type NavigationProps, PaginationBar, PluginDetailPage, type PluginDetailPageProps, PluginMarketplaceDetailPage, type PluginMarketplaceDetailPageProps, PluginMarketplaceListPage, type PluginMarketplaceListPageProps, RunDetailPage, type RunDetailPageProps, RunListPage, type RunListPageProps, RunSourceBadge, RunStatusBadge, SectionHeader, Select, SettingsPage, type SettingsPageProps, Skeleton, Tabs, Textarea, type TextareaProps, Th, ToolkitMultiselect, TranscriptViewer, badgeVariants, buttonVariants, cn, parsePaginationParams, useAgentPlaneClient, useApi, useAuthError, useNavigation };
|
|
712
|
+
export { AdminTable, AdminTableHead, AdminTableRow, AgentA2aInfo, AgentConnectorsManager, AgentDetailPage, AgentEditForm, AgentListPage, type AgentPlaneClient, AgentPlaneProvider, type AgentPlaneProviderProps, AgentPluginManager, AgentRuns, AgentScheduleForm, AgentSkillManager, Badge, type BadgeProps, Button, type ButtonProps, Card, CardContent, CardDescription, CardHeader, CardTitle, ConfirmDialog, CopyButton, DashboardPage, type DashboardPageProps, DetailPageHeader, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, EmptyRow, FormError, FormField, Input, type LinkComponentProps, LocalDate, McpServerListPage, type McpServerListPageProps, MetricCard, ModelSelector, type NavigationProps, PaginationBar, PlaygroundPage, type PlaygroundPageProps, type PlaygroundStream, type PlaygroundStreamEvent, PluginDetailPage, type PluginDetailPageProps, PluginMarketplaceDetailPage, type PluginMarketplaceDetailPageProps, PluginMarketplaceListPage, type PluginMarketplaceListPageProps, RunDetailPage, type RunDetailPageProps, RunListPage, type RunListPageProps, RunSourceBadge, RunStatusBadge, SectionHeader, Select, SettingsPage, type SettingsPageProps, Skeleton, Tabs, Textarea, type TextareaProps, Th, ToolkitMultiselect, TranscriptViewer, badgeVariants, buttonVariants, cn, parsePaginationParams, useAgentPlaneClient, useApi, useAuthError, useNavigation };
|
package/dist/index.js
CHANGED
|
@@ -7,6 +7,7 @@ import { useSWRConfig } from 'swr';
|
|
|
7
7
|
import ReactMarkdown from 'react-markdown';
|
|
8
8
|
import { Command } from 'cmdk';
|
|
9
9
|
import * as Popover from '@radix-ui/react-popover';
|
|
10
|
+
import remarkGfm from 'remark-gfm';
|
|
10
11
|
|
|
11
12
|
function Select({ className = "", ...props }) {
|
|
12
13
|
return /* @__PURE__ */ jsxs("div", { className: "relative w-full", children: [
|
|
@@ -2504,8 +2505,10 @@ function AgentEditForm({ agent, onSaved }) {
|
|
|
2504
2505
|
const [maxTurns, setMaxTurns] = useState(agent.max_turns.toString());
|
|
2505
2506
|
const [maxBudget, setMaxBudget] = useState(agent.max_budget_usd.toString());
|
|
2506
2507
|
const [maxRuntime, setMaxRuntime] = useState(Math.floor(agent.max_runtime_seconds / 60).toString());
|
|
2508
|
+
const [soulMd, setSoulMd] = useState(agent.soul_md ?? "");
|
|
2509
|
+
const [identityMd, setIdentityMd] = useState(agent.identity_md ?? "");
|
|
2507
2510
|
const [saving, setSaving] = useState(false);
|
|
2508
|
-
const isDirty = name !== agent.name || description !== (agent.description ?? "") || model !== agent.model || runner !== (agent.runner ?? "") || permissionMode !== agent.permission_mode || maxTurns !== agent.max_turns.toString() || maxBudget !== agent.max_budget_usd.toString() || maxRuntime !== Math.floor(agent.max_runtime_seconds / 60).toString();
|
|
2511
|
+
const isDirty = name !== agent.name || description !== (agent.description ?? "") || model !== agent.model || runner !== (agent.runner ?? "") || permissionMode !== agent.permission_mode || maxTurns !== agent.max_turns.toString() || maxBudget !== agent.max_budget_usd.toString() || maxRuntime !== Math.floor(agent.max_runtime_seconds / 60).toString() || soulMd !== (agent.soul_md ?? "") || identityMd !== (agent.identity_md ?? "");
|
|
2509
2512
|
const [error, setError] = useState("");
|
|
2510
2513
|
async function handleSave() {
|
|
2511
2514
|
setSaving(true);
|
|
@@ -2519,7 +2522,9 @@ function AgentEditForm({ agent, onSaved }) {
|
|
|
2519
2522
|
permission_mode: permissionMode,
|
|
2520
2523
|
max_turns: parseInt(maxTurns) || agent.max_turns,
|
|
2521
2524
|
max_budget_usd: parseFloat(maxBudget) || agent.max_budget_usd,
|
|
2522
|
-
max_runtime_seconds: (parseInt(maxRuntime) || Math.floor(agent.max_runtime_seconds / 60)) * 60
|
|
2525
|
+
max_runtime_seconds: (parseInt(maxRuntime) || Math.floor(agent.max_runtime_seconds / 60)) * 60,
|
|
2526
|
+
soul_md: soulMd || null,
|
|
2527
|
+
identity_md: identityMd || null
|
|
2523
2528
|
});
|
|
2524
2529
|
onSaved?.();
|
|
2525
2530
|
} catch (err) {
|
|
@@ -2581,7 +2586,46 @@ function AgentEditForm({ agent, onSaved }) {
|
|
|
2581
2586
|
/* @__PURE__ */ jsx("option", { value: "plan", children: "plan" })
|
|
2582
2587
|
] }) }) })
|
|
2583
2588
|
] })
|
|
2584
|
-
] }) })
|
|
2589
|
+
] }) }),
|
|
2590
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-lg border border-muted-foreground/25 p-5", children: [
|
|
2591
|
+
/* @__PURE__ */ jsx(SectionHeader, { title: "Identity" }),
|
|
2592
|
+
/* @__PURE__ */ jsx("div", { className: "space-y-4", children: /* @__PURE__ */ jsxs("div", { className: "grid grid-cols-2 gap-4", children: [
|
|
2593
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(FormField, { label: "SOUL.md", children: [
|
|
2594
|
+
/* @__PURE__ */ jsx(
|
|
2595
|
+
Textarea,
|
|
2596
|
+
{
|
|
2597
|
+
value: soulMd,
|
|
2598
|
+
onChange: (e) => setSoulMd(e.target.value),
|
|
2599
|
+
placeholder: "## Voice & Tone\nDirect, concise, technical.\n\n## Values\nClarity over completeness.\n\n## Stance\nProactive problem-solver.\n\n## Boundaries\n- Never modify production data directly\n\n## Essence\nA focused engineering assistant.",
|
|
2600
|
+
rows: 10,
|
|
2601
|
+
className: "font-mono text-sm",
|
|
2602
|
+
disabled: saving
|
|
2603
|
+
}
|
|
2604
|
+
),
|
|
2605
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground mt-1 block", children: [
|
|
2606
|
+
soulMd.split(/\s+/).filter(Boolean).length,
|
|
2607
|
+
" words"
|
|
2608
|
+
] })
|
|
2609
|
+
] }) }),
|
|
2610
|
+
/* @__PURE__ */ jsx("div", { children: /* @__PURE__ */ jsxs(FormField, { label: "IDENTITY.md", children: [
|
|
2611
|
+
/* @__PURE__ */ jsx(
|
|
2612
|
+
Textarea,
|
|
2613
|
+
{
|
|
2614
|
+
value: identityMd,
|
|
2615
|
+
onChange: (e) => setIdentityMd(e.target.value),
|
|
2616
|
+
placeholder: "- **Communication Verbosity:** concise\n- **Communication Tone:** direct\n- **Decision Autonomy:** high\n- **Risk Tolerance:** moderate\n- **Collaboration Mode:** autonomous\n\n## Escalation Preferences\n- Budget over $50 -> escalate\n- Breaking changes -> escalate",
|
|
2617
|
+
rows: 10,
|
|
2618
|
+
className: "font-mono text-sm",
|
|
2619
|
+
disabled: saving
|
|
2620
|
+
}
|
|
2621
|
+
),
|
|
2622
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground mt-1 block", children: [
|
|
2623
|
+
identityMd.split(/\s+/).filter(Boolean).length,
|
|
2624
|
+
" words"
|
|
2625
|
+
] })
|
|
2626
|
+
] }) })
|
|
2627
|
+
] }) })
|
|
2628
|
+
] })
|
|
2585
2629
|
] });
|
|
2586
2630
|
}
|
|
2587
2631
|
function ToolkitMultiselect({ value, onChange }) {
|
|
@@ -4362,5 +4406,442 @@ function ScheduleCard({
|
|
|
4362
4406
|
] })
|
|
4363
4407
|
] });
|
|
4364
4408
|
}
|
|
4409
|
+
function MarkdownContent({ children }) {
|
|
4410
|
+
return /* @__PURE__ */ jsx("div", { className: "text-sm text-foreground [&_p]:my-1 [&_h1]:text-lg [&_h1]:font-bold [&_h1]:my-2 [&_h2]:text-base [&_h2]:font-semibold [&_h2]:my-2 [&_h3]:text-sm [&_h3]:font-semibold [&_h3]:my-1 [&_ul]:list-disc [&_ul]:pl-5 [&_ul]:my-1 [&_ol]:list-decimal [&_ol]:pl-5 [&_ol]:my-1 [&_li]:my-0.5 [&_pre]:bg-muted [&_pre]:rounded-md [&_pre]:p-3 [&_pre]:overflow-x-auto [&_pre]:text-xs [&_pre]:my-2 [&_code:not(pre_code)]:bg-muted [&_code:not(pre_code)]:px-1 [&_code:not(pre_code)]:py-0.5 [&_code:not(pre_code)]:rounded [&_code:not(pre_code)]:text-xs [&_code:not(pre_code)]:font-mono [&_a]:text-blue-400 [&_a]:underline [&_blockquote]:border-l-2 [&_blockquote]:border-border [&_blockquote]:pl-3 [&_blockquote]:text-muted-foreground [&_blockquote]:my-2 [&_hr]:border-border [&_hr]:my-3 [&_table]:border-collapse [&_table]:text-xs [&_table]:w-full [&_th]:border [&_th]:border-border [&_th]:px-2 [&_th]:py-1 [&_th]:text-left [&_th]:font-semibold [&_th]:bg-muted [&_td]:border [&_td]:border-border [&_td]:px-2 [&_td]:py-1 [&_strong]:font-semibold [&_em]:italic", children: /* @__PURE__ */ jsx(
|
|
4411
|
+
ReactMarkdown,
|
|
4412
|
+
{
|
|
4413
|
+
remarkPlugins: [remarkGfm],
|
|
4414
|
+
components: {
|
|
4415
|
+
a: ({ href, children: linkChildren }) => /* @__PURE__ */ jsx("a", { href, target: "_blank", rel: "noopener noreferrer", children: linkChildren })
|
|
4416
|
+
},
|
|
4417
|
+
children
|
|
4418
|
+
}
|
|
4419
|
+
) });
|
|
4420
|
+
}
|
|
4421
|
+
function CollapsibleJson({ data, maxHeight = "12rem" }) {
|
|
4422
|
+
const [expanded, setExpanded] = useState(false);
|
|
4423
|
+
const json = typeof data === "string" ? data : JSON.stringify(data, null, 2);
|
|
4424
|
+
return /* @__PURE__ */ jsxs("div", { className: "relative", children: [
|
|
4425
|
+
/* @__PURE__ */ jsx(
|
|
4426
|
+
"pre",
|
|
4427
|
+
{
|
|
4428
|
+
className: `text-xs font-mono text-muted-foreground bg-muted/50 rounded-md p-2 overflow-x-auto whitespace-pre-wrap break-all ${expanded ? "" : "overflow-hidden"}`,
|
|
4429
|
+
style: expanded ? void 0 : { maxHeight },
|
|
4430
|
+
children: json
|
|
4431
|
+
}
|
|
4432
|
+
),
|
|
4433
|
+
json.length > 200 && /* @__PURE__ */ jsx(
|
|
4434
|
+
"button",
|
|
4435
|
+
{
|
|
4436
|
+
onClick: () => setExpanded(!expanded),
|
|
4437
|
+
className: "text-xs text-blue-400 hover:text-blue-300 mt-1",
|
|
4438
|
+
children: expanded ? "Collapse" : "Expand"
|
|
4439
|
+
}
|
|
4440
|
+
)
|
|
4441
|
+
] });
|
|
4442
|
+
}
|
|
4443
|
+
function renderEvent(event, idx) {
|
|
4444
|
+
if (event.type === "heartbeat") return null;
|
|
4445
|
+
if (event.type === "text_delta") return null;
|
|
4446
|
+
if (event.type === "session_created") return null;
|
|
4447
|
+
if (event.type === "session_info") return null;
|
|
4448
|
+
if (event.type === "mcp_status") return null;
|
|
4449
|
+
if (event.type === "rate_limit_event") return null;
|
|
4450
|
+
if (event.type === "user_message") {
|
|
4451
|
+
return /* @__PURE__ */ jsxs("div", { className: "border-t border-border pt-3 mt-1", children: [
|
|
4452
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-emerald-400 uppercase", children: "You" }),
|
|
4453
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-foreground mt-1 whitespace-pre-wrap", children: String(event.text) })
|
|
4454
|
+
] }, idx);
|
|
4455
|
+
}
|
|
4456
|
+
if (event.type === "assistant") {
|
|
4457
|
+
const content = event.message;
|
|
4458
|
+
const blocks = content?.content ?? [];
|
|
4459
|
+
const textBlocks = blocks.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
4460
|
+
const toolUseBlocks = blocks.filter((c) => c.type === "tool_use");
|
|
4461
|
+
if (!textBlocks && toolUseBlocks.length === 0) return null;
|
|
4462
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
4463
|
+
textBlocks && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
4464
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-blue-400 uppercase", children: "Assistant" }),
|
|
4465
|
+
/* @__PURE__ */ jsx(MarkdownContent, { children: textBlocks })
|
|
4466
|
+
] }),
|
|
4467
|
+
toolUseBlocks.map((tool, ti) => /* @__PURE__ */ jsxs("div", { className: "space-y-1 ml-3 pl-3 border-l-2 border-yellow-800/50", children: [
|
|
4468
|
+
/* @__PURE__ */ jsxs("span", { className: "text-xs font-semibold text-yellow-400 uppercase", children: [
|
|
4469
|
+
"Tool Call: ",
|
|
4470
|
+
tool.name ?? "unknown"
|
|
4471
|
+
] }),
|
|
4472
|
+
tool.id && /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground ml-2 font-mono", children: String(tool.id) }),
|
|
4473
|
+
tool.input != null && /* @__PURE__ */ jsx(CollapsibleJson, { data: tool.input })
|
|
4474
|
+
] }, ti))
|
|
4475
|
+
] }, idx);
|
|
4476
|
+
}
|
|
4477
|
+
if (event.type === "tool_use") {
|
|
4478
|
+
const toolName = String(event.tool_name ?? event.name ?? "unknown");
|
|
4479
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-1 ml-3 pl-3 border-l-2 border-yellow-800/50", children: [
|
|
4480
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4481
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-yellow-400 uppercase", children: "Tool Call" }),
|
|
4482
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-yellow-400/80", children: toolName }),
|
|
4483
|
+
event.tool_use_id ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground font-mono", children: String(event.tool_use_id) }) : null
|
|
4484
|
+
] }),
|
|
4485
|
+
event.input != null ? /* @__PURE__ */ jsx(CollapsibleJson, { data: event.input }) : null
|
|
4486
|
+
] }, idx);
|
|
4487
|
+
}
|
|
4488
|
+
if (event.type === "tool_result") {
|
|
4489
|
+
const isError = event.is_error === true || event.error === true;
|
|
4490
|
+
const content = event.output ?? event.content ?? "";
|
|
4491
|
+
const contentStr = typeof content === "string" ? content : JSON.stringify(content, null, 2);
|
|
4492
|
+
return /* @__PURE__ */ jsxs("div", { className: `space-y-1 ml-3 pl-3 border-l-2 ${isError ? "border-red-800/50" : "border-green-800/50"}`, children: [
|
|
4493
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4494
|
+
/* @__PURE__ */ jsx("span", { className: `text-xs font-semibold uppercase ${isError ? "text-red-400" : "text-green-400"}`, children: isError ? "Tool Error" : "Tool Result" }),
|
|
4495
|
+
event.tool_name ? /* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-muted-foreground", children: String(event.tool_name) }) : null,
|
|
4496
|
+
event.tool_use_id ? /* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground font-mono", children: String(event.tool_use_id) }) : null
|
|
4497
|
+
] }),
|
|
4498
|
+
contentStr ? /* @__PURE__ */ jsx(CollapsibleJson, { data: contentStr }) : null
|
|
4499
|
+
] }, idx);
|
|
4500
|
+
}
|
|
4501
|
+
if (event.type === "result") {
|
|
4502
|
+
const success = event.subtype === "success";
|
|
4503
|
+
const costUsd = event.cost_usd ?? event.total_cost_usd;
|
|
4504
|
+
return /* @__PURE__ */ jsxs("div", { className: `rounded-md px-3 py-2 flex items-center gap-3 ${success ? "bg-green-950 border border-green-900" : "bg-red-950 border border-red-900"}`, children: [
|
|
4505
|
+
/* @__PURE__ */ jsx("span", { className: `text-xs font-semibold ${success ? "text-green-400" : "text-red-400"}`, children: success ? "Completed" : "Failed" }),
|
|
4506
|
+
/* @__PURE__ */ jsxs("div", { className: "flex flex-wrap gap-3 text-xs text-zinc-400", children: [
|
|
4507
|
+
event.num_turns != null && /* @__PURE__ */ jsxs("span", { children: [
|
|
4508
|
+
String(event.num_turns),
|
|
4509
|
+
" turns"
|
|
4510
|
+
] }),
|
|
4511
|
+
costUsd != null && Number(costUsd) > 0 && /* @__PURE__ */ jsxs("span", { children: [
|
|
4512
|
+
"$",
|
|
4513
|
+
Number(costUsd).toFixed(4)
|
|
4514
|
+
] }),
|
|
4515
|
+
event.duration_ms != null && /* @__PURE__ */ jsxs("span", { children: [
|
|
4516
|
+
(Number(event.duration_ms) / 1e3).toFixed(1),
|
|
4517
|
+
"s"
|
|
4518
|
+
] }),
|
|
4519
|
+
event.duration_api_ms != null && /* @__PURE__ */ jsxs("span", { children: [
|
|
4520
|
+
"API: ",
|
|
4521
|
+
(Number(event.duration_api_ms) / 1e3).toFixed(1),
|
|
4522
|
+
"s"
|
|
4523
|
+
] })
|
|
4524
|
+
] })
|
|
4525
|
+
] }, idx);
|
|
4526
|
+
}
|
|
4527
|
+
if (event.type === "error") {
|
|
4528
|
+
return /* @__PURE__ */ jsxs("div", { className: "rounded-md p-3 bg-red-950 border border-red-800", children: [
|
|
4529
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4530
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm font-semibold text-red-400", children: "Error" }),
|
|
4531
|
+
event.code ? /* @__PURE__ */ jsx("span", { className: "text-xs font-mono text-red-400/70", children: String(event.code) }) : null
|
|
4532
|
+
] }),
|
|
4533
|
+
/* @__PURE__ */ jsx("p", { className: "text-sm text-foreground mt-1", children: String(event.error ?? "Unknown error") })
|
|
4534
|
+
] }, idx);
|
|
4535
|
+
}
|
|
4536
|
+
if (event.type === "stream_detached") {
|
|
4537
|
+
return /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground italic border-t border-border pt-2", children: [
|
|
4538
|
+
"Stream detached at ",
|
|
4539
|
+
event.timestamp ? new Date(String(event.timestamp)).toLocaleTimeString() : "unknown",
|
|
4540
|
+
" \u2014 run continues in background"
|
|
4541
|
+
] }, idx);
|
|
4542
|
+
}
|
|
4543
|
+
if (event.type === "queued") {
|
|
4544
|
+
return /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: "Queued\u2026" }, idx);
|
|
4545
|
+
}
|
|
4546
|
+
if (event.type === "sandbox_starting") {
|
|
4547
|
+
return /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground", children: "Starting sandbox\u2026" }, idx);
|
|
4548
|
+
}
|
|
4549
|
+
if (event.type === "run_started") {
|
|
4550
|
+
return /* @__PURE__ */ jsxs("div", { className: "text-xs text-muted-foreground", children: [
|
|
4551
|
+
"Agent started",
|
|
4552
|
+
event.model ? /* @__PURE__ */ jsx("span", { className: "ml-2 font-mono text-foreground/60", children: String(event.model) }) : null,
|
|
4553
|
+
event.mcp_server_count != null && Number(event.mcp_server_count) > 0 && /* @__PURE__ */ jsxs("span", { className: "ml-2", children: [
|
|
4554
|
+
String(event.mcp_server_count),
|
|
4555
|
+
" MCP server",
|
|
4556
|
+
Number(event.mcp_server_count) !== 1 ? "s" : ""
|
|
4557
|
+
] })
|
|
4558
|
+
] }, idx);
|
|
4559
|
+
}
|
|
4560
|
+
if (event.type === "system") {
|
|
4561
|
+
return /* @__PURE__ */ jsx("div", { className: "text-xs text-muted-foreground italic", children: String(event.message ?? JSON.stringify(event)) }, idx);
|
|
4562
|
+
}
|
|
4563
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
4564
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-purple-400 uppercase", children: event.type }),
|
|
4565
|
+
/* @__PURE__ */ jsx(CollapsibleJson, { data: event, maxHeight: "8rem" })
|
|
4566
|
+
] }, idx);
|
|
4567
|
+
}
|
|
4568
|
+
var TERMINAL_STATUSES = /* @__PURE__ */ new Set(["completed", "failed", "cancelled", "timed_out"]);
|
|
4569
|
+
function PlaygroundPage({ agentId }) {
|
|
4570
|
+
const client = useAgentPlaneClient();
|
|
4571
|
+
const { LinkComponent, basePath } = useNavigation();
|
|
4572
|
+
const { data: agent, error: agentError, isLoading } = useApi(
|
|
4573
|
+
`agent-${agentId}`,
|
|
4574
|
+
(c) => c.agents.get(agentId)
|
|
4575
|
+
);
|
|
4576
|
+
const [prompt, setPrompt] = useState("");
|
|
4577
|
+
const [events, setEvents] = useState([]);
|
|
4578
|
+
const [streamingText, setStreamingText] = useState("");
|
|
4579
|
+
const [running, setRunning] = useState(false);
|
|
4580
|
+
const [polling, setPolling] = useState(false);
|
|
4581
|
+
const [error, setError] = useState(null);
|
|
4582
|
+
const [sessionId, setSessionId] = useState(null);
|
|
4583
|
+
const sessionIdRef = useRef(null);
|
|
4584
|
+
const abortRef = useRef(null);
|
|
4585
|
+
const runIdRef = useRef(null);
|
|
4586
|
+
const streamRef = useRef(null);
|
|
4587
|
+
const scrollRef = useRef(null);
|
|
4588
|
+
const textareaRef = useRef(null);
|
|
4589
|
+
useEffect(() => {
|
|
4590
|
+
const el = scrollRef.current;
|
|
4591
|
+
if (el) el.scrollTop = el.scrollHeight;
|
|
4592
|
+
}, [events, streamingText]);
|
|
4593
|
+
useEffect(() => {
|
|
4594
|
+
return () => {
|
|
4595
|
+
abortRef.current?.abort();
|
|
4596
|
+
streamRef.current?.abort();
|
|
4597
|
+
};
|
|
4598
|
+
}, []);
|
|
4599
|
+
const pollForFinalResult = useCallback(async (runId) => {
|
|
4600
|
+
setPolling(true);
|
|
4601
|
+
let delay = 3e3;
|
|
4602
|
+
const maxDelay = 1e4;
|
|
4603
|
+
try {
|
|
4604
|
+
while (true) {
|
|
4605
|
+
if (abortRef.current?.signal.aborted) break;
|
|
4606
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
4607
|
+
if (abortRef.current?.signal.aborted) break;
|
|
4608
|
+
try {
|
|
4609
|
+
const run = await client.runs.get(runId);
|
|
4610
|
+
if (TERMINAL_STATUSES.has(run.status)) {
|
|
4611
|
+
try {
|
|
4612
|
+
const transcriptEvents = await client.runs.transcriptArray(runId);
|
|
4613
|
+
if (transcriptEvents.length > 0) {
|
|
4614
|
+
const detachIdx = transcriptEvents.findIndex((ev) => ev.type === "stream_detached");
|
|
4615
|
+
const eventsAfterDetach = detachIdx >= 0 ? transcriptEvents.slice(detachIdx + 1) : [];
|
|
4616
|
+
const newEvents = eventsAfterDetach.filter(
|
|
4617
|
+
(ev) => ev.type !== "heartbeat" && ev.type !== "text_delta" && ev.type !== "run_started" && ev.type !== "queued" && ev.type !== "sandbox_starting"
|
|
4618
|
+
);
|
|
4619
|
+
if (newEvents.length > 0) {
|
|
4620
|
+
setEvents((prev) => [...prev, ...newEvents]);
|
|
4621
|
+
}
|
|
4622
|
+
}
|
|
4623
|
+
} catch {
|
|
4624
|
+
}
|
|
4625
|
+
setEvents((prev) => {
|
|
4626
|
+
if (prev.some((ev) => ev.type === "result")) return prev;
|
|
4627
|
+
const syntheticResult = {
|
|
4628
|
+
type: "result",
|
|
4629
|
+
subtype: run.status === "completed" ? "success" : "failed",
|
|
4630
|
+
cost_usd: run.cost_usd,
|
|
4631
|
+
num_turns: run.num_turns,
|
|
4632
|
+
duration_ms: run.duration_ms
|
|
4633
|
+
};
|
|
4634
|
+
if (run.error_type) {
|
|
4635
|
+
syntheticResult.result = run.error_type;
|
|
4636
|
+
}
|
|
4637
|
+
return [...prev, syntheticResult];
|
|
4638
|
+
});
|
|
4639
|
+
break;
|
|
4640
|
+
}
|
|
4641
|
+
delay = Math.min(delay * 2, maxDelay);
|
|
4642
|
+
} catch (err) {
|
|
4643
|
+
if (err?.name === "AbortError") break;
|
|
4644
|
+
delay = Math.min(delay * 2, maxDelay);
|
|
4645
|
+
}
|
|
4646
|
+
}
|
|
4647
|
+
} finally {
|
|
4648
|
+
setPolling(false);
|
|
4649
|
+
setRunning(false);
|
|
4650
|
+
abortRef.current = null;
|
|
4651
|
+
runIdRef.current = null;
|
|
4652
|
+
streamRef.current = null;
|
|
4653
|
+
}
|
|
4654
|
+
}, [client]);
|
|
4655
|
+
const consumeStream = useCallback(async (stream) => {
|
|
4656
|
+
streamRef.current = stream;
|
|
4657
|
+
let handedOffToPoll = false;
|
|
4658
|
+
try {
|
|
4659
|
+
for await (const event of stream) {
|
|
4660
|
+
const ev = event;
|
|
4661
|
+
if (ev.type === "session_created" && ev.session_id) {
|
|
4662
|
+
const sid = ev.session_id;
|
|
4663
|
+
sessionIdRef.current = sid;
|
|
4664
|
+
setSessionId(sid);
|
|
4665
|
+
}
|
|
4666
|
+
if (ev.type === "run_started" && ev.run_id) {
|
|
4667
|
+
runIdRef.current = ev.run_id;
|
|
4668
|
+
}
|
|
4669
|
+
if (ev.type === "text_delta") {
|
|
4670
|
+
setStreamingText((prev) => prev + (ev.text ?? ""));
|
|
4671
|
+
} else if (ev.type === "stream_detached") {
|
|
4672
|
+
setStreamingText("");
|
|
4673
|
+
setEvents((prev) => [...prev, ev]);
|
|
4674
|
+
if (runIdRef.current) {
|
|
4675
|
+
handedOffToPoll = true;
|
|
4676
|
+
pollForFinalResult(runIdRef.current);
|
|
4677
|
+
return;
|
|
4678
|
+
}
|
|
4679
|
+
} else {
|
|
4680
|
+
if (ev.type === "assistant") setStreamingText("");
|
|
4681
|
+
setEvents((prev) => [...prev, ev]);
|
|
4682
|
+
}
|
|
4683
|
+
}
|
|
4684
|
+
} finally {
|
|
4685
|
+
if (!handedOffToPoll) {
|
|
4686
|
+
setRunning(false);
|
|
4687
|
+
abortRef.current = null;
|
|
4688
|
+
runIdRef.current = null;
|
|
4689
|
+
streamRef.current = null;
|
|
4690
|
+
}
|
|
4691
|
+
}
|
|
4692
|
+
}, [pollForFinalResult]);
|
|
4693
|
+
const handleSend = useCallback(async () => {
|
|
4694
|
+
if (!prompt.trim() || running) return;
|
|
4695
|
+
const messageText = prompt.trim();
|
|
4696
|
+
setPrompt("");
|
|
4697
|
+
setRunning(true);
|
|
4698
|
+
setStreamingText("");
|
|
4699
|
+
setError(null);
|
|
4700
|
+
setPolling(false);
|
|
4701
|
+
setEvents((prev) => [...prev, { type: "user_message", text: messageText }]);
|
|
4702
|
+
const abort = new AbortController();
|
|
4703
|
+
abortRef.current = abort;
|
|
4704
|
+
try {
|
|
4705
|
+
let stream;
|
|
4706
|
+
const currentSessionId = sessionIdRef.current;
|
|
4707
|
+
if (currentSessionId) {
|
|
4708
|
+
stream = await client.sessions.sendMessage(
|
|
4709
|
+
currentSessionId,
|
|
4710
|
+
{ prompt: messageText },
|
|
4711
|
+
{ signal: abort.signal }
|
|
4712
|
+
);
|
|
4713
|
+
} else {
|
|
4714
|
+
stream = await client.sessions.create(
|
|
4715
|
+
{ agent_id: agentId, prompt: messageText },
|
|
4716
|
+
{ signal: abort.signal }
|
|
4717
|
+
);
|
|
4718
|
+
}
|
|
4719
|
+
await consumeStream(stream);
|
|
4720
|
+
} catch (err) {
|
|
4721
|
+
if (err?.name !== "AbortError") {
|
|
4722
|
+
const msg = err instanceof Error ? err.message : "Unknown error";
|
|
4723
|
+
setError(msg);
|
|
4724
|
+
}
|
|
4725
|
+
setRunning(false);
|
|
4726
|
+
abortRef.current = null;
|
|
4727
|
+
runIdRef.current = null;
|
|
4728
|
+
streamRef.current = null;
|
|
4729
|
+
}
|
|
4730
|
+
}, [prompt, running, agentId, client, consumeStream]);
|
|
4731
|
+
function handleNewChat() {
|
|
4732
|
+
abortRef.current?.abort();
|
|
4733
|
+
streamRef.current?.abort();
|
|
4734
|
+
if (sessionId) {
|
|
4735
|
+
client.sessions.stop(sessionId).catch(() => {
|
|
4736
|
+
});
|
|
4737
|
+
}
|
|
4738
|
+
sessionIdRef.current = null;
|
|
4739
|
+
setSessionId(null);
|
|
4740
|
+
setEvents([]);
|
|
4741
|
+
setStreamingText("");
|
|
4742
|
+
setRunning(false);
|
|
4743
|
+
setPolling(false);
|
|
4744
|
+
setError(null);
|
|
4745
|
+
setPrompt("");
|
|
4746
|
+
runIdRef.current = null;
|
|
4747
|
+
abortRef.current = null;
|
|
4748
|
+
streamRef.current = null;
|
|
4749
|
+
textareaRef.current?.focus();
|
|
4750
|
+
}
|
|
4751
|
+
function handleStop() {
|
|
4752
|
+
abortRef.current?.abort();
|
|
4753
|
+
streamRef.current?.abort();
|
|
4754
|
+
const id = runIdRef.current;
|
|
4755
|
+
if (id) {
|
|
4756
|
+
runIdRef.current = null;
|
|
4757
|
+
client.runs.cancel(id).catch(() => {
|
|
4758
|
+
});
|
|
4759
|
+
}
|
|
4760
|
+
}
|
|
4761
|
+
if (isLoading) {
|
|
4762
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-[calc(100vh-6rem)]", children: [
|
|
4763
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
4764
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-24" }),
|
|
4765
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-4 w-40" })
|
|
4766
|
+
] }),
|
|
4767
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "flex-1 rounded-lg" }),
|
|
4768
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-4 space-y-2", children: [
|
|
4769
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-24 w-full rounded-lg" }),
|
|
4770
|
+
/* @__PURE__ */ jsx(Skeleton, { className: "h-8 w-20" })
|
|
4771
|
+
] })
|
|
4772
|
+
] });
|
|
4773
|
+
}
|
|
4774
|
+
if (agentError || !agent) {
|
|
4775
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col items-center justify-center h-[calc(100vh-6rem)] gap-3", children: [
|
|
4776
|
+
/* @__PURE__ */ jsx("p", { className: "text-destructive text-sm", children: agentError?.status === 404 ? "Agent not found." : `Failed to load agent: ${agentError?.message ?? "Unknown error"}` }),
|
|
4777
|
+
/* @__PURE__ */ jsx(
|
|
4778
|
+
LinkComponent,
|
|
4779
|
+
{
|
|
4780
|
+
href: `${basePath}/agents`,
|
|
4781
|
+
className: "text-sm text-muted-foreground hover:text-foreground",
|
|
4782
|
+
children: "\u2190 Back to agents"
|
|
4783
|
+
}
|
|
4784
|
+
)
|
|
4785
|
+
] });
|
|
4786
|
+
}
|
|
4787
|
+
const hasContent = events.length > 0 || running;
|
|
4788
|
+
return /* @__PURE__ */ jsxs("div", { className: "flex flex-col h-[calc(100vh-6rem)]", children: [
|
|
4789
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-3 mb-4", children: [
|
|
4790
|
+
/* @__PURE__ */ jsxs(
|
|
4791
|
+
LinkComponent,
|
|
4792
|
+
{
|
|
4793
|
+
href: `${basePath}/agents/${agentId}`,
|
|
4794
|
+
className: "text-sm text-muted-foreground hover:text-foreground",
|
|
4795
|
+
children: [
|
|
4796
|
+
"\u2190 ",
|
|
4797
|
+
agent.name
|
|
4798
|
+
]
|
|
4799
|
+
}
|
|
4800
|
+
),
|
|
4801
|
+
(sessionId || events.length > 0) && /* @__PURE__ */ jsx(Button, { onClick: handleNewChat, variant: "outline", size: "sm", disabled: running, children: "New Chat" }),
|
|
4802
|
+
sessionId && /* @__PURE__ */ jsxs("span", { className: "text-xs text-muted-foreground font-mono", children: [
|
|
4803
|
+
"Session: ",
|
|
4804
|
+
sessionId.slice(0, 12),
|
|
4805
|
+
"\u2026"
|
|
4806
|
+
] })
|
|
4807
|
+
] }),
|
|
4808
|
+
hasContent && /* @__PURE__ */ jsxs("div", { ref: scrollRef, className: "flex-1 min-h-0 overflow-y-auto rounded-lg border border-border bg-muted/20 p-4 space-y-4 mb-4", children: [
|
|
4809
|
+
events.map((ev, i) => renderEvent(ev, i)),
|
|
4810
|
+
streamingText && /* @__PURE__ */ jsxs("div", { className: "space-y-1", children: [
|
|
4811
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs font-semibold text-blue-400 uppercase", children: "Assistant" }),
|
|
4812
|
+
/* @__PURE__ */ jsx(MarkdownContent, { children: streamingText }),
|
|
4813
|
+
/* @__PURE__ */ jsx("span", { className: "inline-block w-0.5 h-4 bg-foreground animate-pulse align-text-bottom" })
|
|
4814
|
+
] }),
|
|
4815
|
+
running && !streamingText && /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-xs text-muted-foreground", children: [
|
|
4816
|
+
/* @__PURE__ */ jsx("span", { className: "animate-pulse", children: "\u25CF" }),
|
|
4817
|
+
" ",
|
|
4818
|
+
polling ? "Reconnected, streaming updates\u2026" : "Running\u2026"
|
|
4819
|
+
] })
|
|
4820
|
+
] }),
|
|
4821
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2 shrink-0", children: [
|
|
4822
|
+
error && /* @__PURE__ */ jsx("p", { className: "text-sm text-destructive", children: error }),
|
|
4823
|
+
/* @__PURE__ */ jsx(
|
|
4824
|
+
Textarea,
|
|
4825
|
+
{
|
|
4826
|
+
ref: textareaRef,
|
|
4827
|
+
placeholder: sessionId ? "Send a follow-up message\u2026" : "Enter your prompt\u2026",
|
|
4828
|
+
value: prompt,
|
|
4829
|
+
onChange: (e) => setPrompt(e.target.value),
|
|
4830
|
+
rows: hasContent ? 3 : 12,
|
|
4831
|
+
disabled: running,
|
|
4832
|
+
className: "font-mono text-sm resize-none",
|
|
4833
|
+
onKeyDown: (e) => {
|
|
4834
|
+
if (e.key === "Enter" && (e.metaKey || e.ctrlKey)) handleSend();
|
|
4835
|
+
}
|
|
4836
|
+
}
|
|
4837
|
+
),
|
|
4838
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
4839
|
+
/* @__PURE__ */ jsx(Button, { onClick: handleSend, disabled: running || !prompt.trim(), size: "sm", children: running ? "Running\u2026" : sessionId ? "Send" : "Run" }),
|
|
4840
|
+
running && /* @__PURE__ */ jsx(Button, { onClick: handleStop, variant: "outline", size: "sm", children: "Stop" }),
|
|
4841
|
+
/* @__PURE__ */ jsx("span", { className: "text-xs text-muted-foreground ml-1", children: "\u2318+Enter to send" })
|
|
4842
|
+
] })
|
|
4843
|
+
] })
|
|
4844
|
+
] });
|
|
4845
|
+
}
|
|
4365
4846
|
|
|
4366
|
-
export { AdminTable, AdminTableHead, AdminTableRow, AgentA2aInfo, AgentConnectorsManager, AgentDetailPage, AgentEditForm, AgentListPage, AgentPluginManager, AgentRuns, AgentScheduleForm, AgentSkillManager, ConfirmDialog, CopyButton, DashboardPage, DetailPageHeader, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, EmptyRow, FormError, FormField, LocalDate, McpServerListPage, MetricCard, ModelSelector, PaginationBar, PluginDetailPage, PluginMarketplaceDetailPage, PluginMarketplaceListPage, RunDetailPage, RunListPage, RunSourceBadge, RunStatusBadge, SectionHeader, Select, SettingsPage, Tabs, Textarea, Th, ToolkitMultiselect, TranscriptViewer, parsePaginationParams };
|
|
4847
|
+
export { AdminTable, AdminTableHead, AdminTableRow, AgentA2aInfo, AgentConnectorsManager, AgentDetailPage, AgentEditForm, AgentListPage, AgentPluginManager, AgentRuns, AgentScheduleForm, AgentSkillManager, ConfirmDialog, CopyButton, DashboardPage, DetailPageHeader, Dialog, DialogBody, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, EmptyRow, FormError, FormField, LocalDate, McpServerListPage, MetricCard, ModelSelector, PaginationBar, PlaygroundPage, PluginDetailPage, PluginMarketplaceDetailPage, PluginMarketplaceListPage, RunDetailPage, RunListPage, RunSourceBadge, RunStatusBadge, SectionHeader, Select, SettingsPage, Tabs, Textarea, Th, ToolkitMultiselect, TranscriptViewer, parsePaginationParams };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@getcatalystiq/agent-plane-ui",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.17",
|
|
4
4
|
"description": "Embeddable React component library for AgentPlane",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"exports": {
|
|
@@ -61,12 +61,16 @@
|
|
|
61
61
|
"react-dom": "^18.0.0 || ^19.0.0",
|
|
62
62
|
"react-markdown": "^9.0.0",
|
|
63
63
|
"recharts": "^2.0.0",
|
|
64
|
+
"remark-gfm": "^4.0.0",
|
|
64
65
|
"swr": "^2.0.0"
|
|
65
66
|
},
|
|
66
67
|
"peerDependenciesMeta": {
|
|
67
68
|
"react-markdown": {
|
|
68
69
|
"optional": true
|
|
69
70
|
},
|
|
71
|
+
"remark-gfm": {
|
|
72
|
+
"optional": true
|
|
73
|
+
},
|
|
70
74
|
"recharts": {
|
|
71
75
|
"optional": true
|
|
72
76
|
},
|
|
@@ -96,6 +100,7 @@
|
|
|
96
100
|
"devDependencies": {
|
|
97
101
|
"@types/react": "^19",
|
|
98
102
|
"@types/react-dom": "^19",
|
|
103
|
+
"remark-gfm": "^4.0.1",
|
|
99
104
|
"swr": "^2.0.0",
|
|
100
105
|
"tsup": "^8",
|
|
101
106
|
"typescript": "^5"
|