@truefoundry/trueforge-ui 0.3.0-rc.10 → 0.3.0-rc.11

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.
Files changed (75) hide show
  1. package/CHANGELOG.md +13 -0
  2. package/dist/{AgentCodeSnippets-RJBB4DDE.js → AgentCodeSnippets-CHDVZHHK.js} +5 -5
  3. package/dist/AgentMetricChart-6RGWFMJE.js +15 -0
  4. package/dist/AgentOverview-3LJZ6MO7.js +311 -0
  5. package/dist/AgentOverview-3LJZ6MO7.js.map +1 -0
  6. package/dist/{AgentSessionEventTimeline-GRGIQTRE.js → AgentSessionEventTimeline-5GOJKT7D.js} +5 -5
  7. package/dist/{AgentSessionEventTimelineChart-GNF4VOUT.js → AgentSessionEventTimelineChart-UYG3JQMP.js} +5 -5
  8. package/dist/{AgentSessions-5OTF2BUW.js → AgentSessions-KUABCQ4W.js} +78 -13
  9. package/dist/AgentSessions-KUABCQ4W.js.map +1 -0
  10. package/dist/{ConnectorSettings-HDKGLDCY.js → ConnectorSettings-PED5C2P7.js} +5 -5
  11. package/dist/{DockLayout-D2FPQCAL.js → DockLayout-ACM7BVIH.js} +8 -8
  12. package/dist/{DrawerLayout-HUV7RAWL.js → DrawerLayout-SGBYRKHI.js} +9 -9
  13. package/dist/{ModelSettings-VNQ7HPKH.js → ModelSettings-GJTVFXFY.js} +5 -5
  14. package/dist/OpenUiFenceBlock-MJTC2VJ5.js +9 -0
  15. package/dist/{SandboxSettings-ZLXGMFBF.js → SandboxSettings-VETQ7UPE.js} +5 -5
  16. package/dist/SchedulesPage-LHJ3U2VM.js +15 -0
  17. package/dist/{SettingsBuilder-RVVYXOJW.js → SettingsBuilder-5ZCU66FF.js} +7 -7
  18. package/dist/{SidebarLayout-KYA76FQ7.js → SidebarLayout-TR5CAB6Q.js} +10 -10
  19. package/dist/{SkillSettings-7OHT7FPI.js → SkillSettings-TRTY2YH3.js} +5 -5
  20. package/dist/{TrueForgeUIWithRouter-LKG4XLW6.js → TrueForgeUIWithRouter-GZUSRZIR.js} +6 -6
  21. package/dist/{WidgetLayout-W2RGGOQ3.js → WidgetLayout-2TM6I4LJ.js} +8 -8
  22. package/dist/{chunk-PQ7VWBQQ.js → chunk-2MUK3SMR.js} +2 -2
  23. package/dist/{chunk-3ZW74FHC.js → chunk-5N5V7YLO.js} +6 -2
  24. package/dist/chunk-5N5V7YLO.js.map +1 -0
  25. package/dist/{chunk-PCI6VMB5.js → chunk-75YEQUUD.js} +8 -8
  26. package/dist/{chunk-JKEBMGLH.js → chunk-BXG6XN2S.js} +3 -3
  27. package/dist/chunk-GKXDRULM.js +587 -0
  28. package/dist/chunk-GKXDRULM.js.map +1 -0
  29. package/dist/{chunk-GG23N2GW.js → chunk-OH357IHR.js} +1247 -846
  30. package/dist/chunk-OH357IHR.js.map +1 -0
  31. package/dist/{chunk-KSGNKS2D.js → chunk-P6MZDITS.js} +4 -4
  32. package/dist/{chunk-CG75X77Q.js → chunk-SLMFEG7X.js} +2 -2
  33. package/dist/{chunk-EPAL2HD5.js → chunk-UWLL327M.js} +4 -4
  34. package/dist/{chunk-67ZO7Z2W.js → chunk-VAOCM3QQ.js} +8 -8
  35. package/dist/{chunk-DPPOEFBD.js → chunk-Y7O6CMC7.js} +4 -4
  36. package/dist/index.d.ts +10 -2
  37. package/dist/index.js +10 -10
  38. package/dist/plugins/trueforge-agent-server-adapter/index.js +23 -10
  39. package/dist/plugins/trueforge-agent-server-adapter/index.js.map +1 -1
  40. package/dist/styles.css +1 -1
  41. package/package.json +3 -3
  42. package/dist/AgentMetricChart-UPGSJ2WP.js +0 -15
  43. package/dist/AgentOverview-U5WIQXZN.js +0 -169
  44. package/dist/AgentOverview-U5WIQXZN.js.map +0 -1
  45. package/dist/AgentSessions-5OTF2BUW.js.map +0 -1
  46. package/dist/OpenUiFenceBlock-KPZFLUSC.js +0 -9
  47. package/dist/SchedulesPage-QKYI2Z3A.js +0 -15
  48. package/dist/chunk-3ZW74FHC.js.map +0 -1
  49. package/dist/chunk-GG23N2GW.js.map +0 -1
  50. package/dist/chunk-JCL3Q7RW.js +0 -587
  51. package/dist/chunk-JCL3Q7RW.js.map +0 -1
  52. /package/dist/{AgentCodeSnippets-RJBB4DDE.js.map → AgentCodeSnippets-CHDVZHHK.js.map} +0 -0
  53. /package/dist/{AgentMetricChart-UPGSJ2WP.js.map → AgentMetricChart-6RGWFMJE.js.map} +0 -0
  54. /package/dist/{AgentSessionEventTimeline-GRGIQTRE.js.map → AgentSessionEventTimeline-5GOJKT7D.js.map} +0 -0
  55. /package/dist/{AgentSessionEventTimelineChart-GNF4VOUT.js.map → AgentSessionEventTimelineChart-UYG3JQMP.js.map} +0 -0
  56. /package/dist/{ConnectorSettings-HDKGLDCY.js.map → ConnectorSettings-PED5C2P7.js.map} +0 -0
  57. /package/dist/{DockLayout-D2FPQCAL.js.map → DockLayout-ACM7BVIH.js.map} +0 -0
  58. /package/dist/{DrawerLayout-HUV7RAWL.js.map → DrawerLayout-SGBYRKHI.js.map} +0 -0
  59. /package/dist/{ModelSettings-VNQ7HPKH.js.map → ModelSettings-GJTVFXFY.js.map} +0 -0
  60. /package/dist/{OpenUiFenceBlock-KPZFLUSC.js.map → OpenUiFenceBlock-MJTC2VJ5.js.map} +0 -0
  61. /package/dist/{SandboxSettings-ZLXGMFBF.js.map → SandboxSettings-VETQ7UPE.js.map} +0 -0
  62. /package/dist/{SchedulesPage-QKYI2Z3A.js.map → SchedulesPage-LHJ3U2VM.js.map} +0 -0
  63. /package/dist/{SettingsBuilder-RVVYXOJW.js.map → SettingsBuilder-5ZCU66FF.js.map} +0 -0
  64. /package/dist/{SidebarLayout-KYA76FQ7.js.map → SidebarLayout-TR5CAB6Q.js.map} +0 -0
  65. /package/dist/{SkillSettings-7OHT7FPI.js.map → SkillSettings-TRTY2YH3.js.map} +0 -0
  66. /package/dist/{TrueForgeUIWithRouter-LKG4XLW6.js.map → TrueForgeUIWithRouter-GZUSRZIR.js.map} +0 -0
  67. /package/dist/{WidgetLayout-W2RGGOQ3.js.map → WidgetLayout-2TM6I4LJ.js.map} +0 -0
  68. /package/dist/{chunk-PQ7VWBQQ.js.map → chunk-2MUK3SMR.js.map} +0 -0
  69. /package/dist/{chunk-PCI6VMB5.js.map → chunk-75YEQUUD.js.map} +0 -0
  70. /package/dist/{chunk-JKEBMGLH.js.map → chunk-BXG6XN2S.js.map} +0 -0
  71. /package/dist/{chunk-KSGNKS2D.js.map → chunk-P6MZDITS.js.map} +0 -0
  72. /package/dist/{chunk-CG75X77Q.js.map → chunk-SLMFEG7X.js.map} +0 -0
  73. /package/dist/{chunk-EPAL2HD5.js.map → chunk-UWLL327M.js.map} +0 -0
  74. /package/dist/{chunk-67ZO7Z2W.js.map → chunk-VAOCM3QQ.js.map} +0 -0
  75. /package/dist/{chunk-DPPOEFBD.js.map → chunk-Y7O6CMC7.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,18 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.3.0-rc.11
4
+
5
+ ### Patch Changes
6
+
7
+ - 4be60e7: Bump `@truefoundry/assistant-ui-runtime` to `0.1.41` for turn-scoped sandbox artifact downloads and to stop stale session history from merging after a session switch.
8
+ - 551b6a8: Default MCP tool approval to `@destructive` only. Selecting Other/read-only tools clears approval; selecting destructive tools keeps it on. Migrate mounts still carrying the old `@write`+`@destructive` default.
9
+ - 551b6a8: Let Build Agent pick which MCP tools require human approval, saved as `require_approval_for_tools` on the agent spec, and make unchecked tool checkboxes legible in both tool selectors. The agent Overview tab now expands each attached MCP server into its tools, with read/write/destructive labels and approval state.
10
+ - ffbb239: Add a hover ellipsis delete menu with confirmation dialog on Sessions list rows.
11
+ - a655537: Add a `turn.update` event schema with paused/running status and `action_required_on_events`.
12
+ - Updated dependencies [648273b]
13
+ - Updated dependencies [648273b]
14
+ - @truefoundry/trueforge-sdk@0.2.0-rc.9
15
+
3
16
  ## 0.3.0-rc.10
4
17
 
5
18
  ### Patch Changes
@@ -1,17 +1,17 @@
1
1
  "use client";
2
2
  import {
3
3
  useSlot
4
- } from "./chunk-GG23N2GW.js";
4
+ } from "./chunk-OH357IHR.js";
5
5
  import "./chunk-T6QQV5LK.js";
6
6
  import {
7
7
  Icon
8
- } from "./chunk-3ZW74FHC.js";
8
+ } from "./chunk-5N5V7YLO.js";
9
9
  import "./chunk-2GIZY3JJ.js";
10
10
  import "./chunk-M6MHLVSO.js";
11
- import "./chunk-CG75X77Q.js";
11
+ import "./chunk-SLMFEG7X.js";
12
12
  import {
13
13
  cn
14
- } from "./chunk-JCL3Q7RW.js";
14
+ } from "./chunk-GKXDRULM.js";
15
15
 
16
16
  // src/atoms/agent-details/AgentCodeSnippets.tsx
17
17
  import { useEffect, useState } from "react";
@@ -86,4 +86,4 @@ function AgentCodeSnippets({ snippets }) {
86
86
  export {
87
87
  AgentCodeSnippets as default
88
88
  };
89
- //# sourceMappingURL=AgentCodeSnippets-RJBB4DDE.js.map
89
+ //# sourceMappingURL=AgentCodeSnippets-CHDVZHHK.js.map
@@ -0,0 +1,15 @@
1
+ "use client";
2
+ import {
3
+ AgentMetricChart
4
+ } from "./chunk-2MUK3SMR.js";
5
+ import "./chunk-OH357IHR.js";
6
+ import "./chunk-T6QQV5LK.js";
7
+ import "./chunk-5N5V7YLO.js";
8
+ import "./chunk-2GIZY3JJ.js";
9
+ import "./chunk-M6MHLVSO.js";
10
+ import "./chunk-SLMFEG7X.js";
11
+ import "./chunk-GKXDRULM.js";
12
+ export {
13
+ AgentMetricChart
14
+ };
15
+ //# sourceMappingURL=AgentMetricChart-6RGWFMJE.js.map
@@ -0,0 +1,311 @@
1
+ "use client";
2
+ import {
3
+ TOOL_TAG_ALL,
4
+ Tooltip,
5
+ approvalSelectorsFromMount,
6
+ disableSelectorsFromMount,
7
+ editableMountsFromSpec,
8
+ enableSelectorsFromMount,
9
+ mcpToolKind,
10
+ namedToolRequiresApproval,
11
+ selectedToolNames,
12
+ useSlot
13
+ } from "./chunk-OH357IHR.js";
14
+ import "./chunk-T6QQV5LK.js";
15
+ import {
16
+ Icon
17
+ } from "./chunk-5N5V7YLO.js";
18
+ import {
19
+ useOptionalServer
20
+ } from "./chunk-2GIZY3JJ.js";
21
+ import "./chunk-M6MHLVSO.js";
22
+ import "./chunk-SLMFEG7X.js";
23
+ import {
24
+ cn
25
+ } from "./chunk-GKXDRULM.js";
26
+
27
+ // src/atoms/agent-details/AgentOverview.tsx
28
+ import { useState as useState2 } from "react";
29
+
30
+ // src/atoms/agent-details/AgentOverviewMcpServers.tsx
31
+ import { useEffect, useMemo, useState } from "react";
32
+ import { jsx, jsxs } from "react/jsx-runtime";
33
+ var KIND_CLASSES = {
34
+ read: "border-border bg-secondary-bg text-text-secondary",
35
+ write: "border-border bg-secondary-bg text-text-primary",
36
+ destructive: "border-failure-bg/30 bg-failure-bg/10 text-failure-bg"
37
+ };
38
+ var KIND_ORDER = {
39
+ read: 0,
40
+ write: 1,
41
+ unknown: 2,
42
+ destructive: 3
43
+ };
44
+ function toolCountLabel(count) {
45
+ return count === 1 ? "1 tool" : `${count} tools`;
46
+ }
47
+ function toolSelectorLabel(enableSelectors) {
48
+ if (enableSelectors.includes(TOOL_TAG_ALL)) return "All tools";
49
+ return enableSelectors.filter((selector) => selector.startsWith("@")).join(" ");
50
+ }
51
+ function ApprovalCountBadge({ count }) {
52
+ return /* @__PURE__ */ jsxs(
53
+ "span",
54
+ {
55
+ className: "border-warning-bg/40 bg-warning-bg/10 text-warning-bg inline-flex shrink-0 items-center gap-1 rounded-full border px-1.5 py-0.5 text-[0.625rem] font-medium",
56
+ "aria-label": `${count} ${count === 1 ? "tool needs" : "tools need"} approval`,
57
+ children: [
58
+ /* @__PURE__ */ jsx(Icon, { name: "shield-check", className: "size-2.5" }),
59
+ count
60
+ ]
61
+ }
62
+ );
63
+ }
64
+ function ToolKindPill({ kind }) {
65
+ return /* @__PURE__ */ jsx("span", { className: cn("shrink-0 rounded-full border px-1.5 py-0.5 text-[0.625rem] font-medium", KIND_CLASSES[kind]), children: kind });
66
+ }
67
+ function ApprovalIndicator({ approvalRequired, toolName }) {
68
+ return /* @__PURE__ */ jsx(
69
+ Tooltip,
70
+ {
71
+ content: approvalRequired ? "Asks for approval before running" : "Runs without asking for approval",
72
+ triggerClassName: "shrink-0",
73
+ children: /* @__PURE__ */ jsx(
74
+ "span",
75
+ {
76
+ role: "img",
77
+ "aria-label": `${toolName} ${approvalRequired ? "requires approval" : "runs without approval"}`,
78
+ className: cn(
79
+ "flex size-5 items-center justify-center rounded-md border",
80
+ approvalRequired ? "border-warning-bg/50 bg-warning-bg/10 text-warning-bg" : "border-border text-text-secondary"
81
+ ),
82
+ children: /* @__PURE__ */ jsx(Icon, { name: approvalRequired ? "shield-check" : "shield", className: "size-3" })
83
+ }
84
+ )
85
+ }
86
+ );
87
+ }
88
+ function AgentOverviewMcpServers({ mcpServers }) {
89
+ const AgentOverviewCard = useSlot("AgentOverviewCard");
90
+ const server = useOptionalServer();
91
+ const getMcpTools = server?.getMcpTools;
92
+ const mounts = useMemo(() => editableMountsFromSpec(mcpServers), [mcpServers]);
93
+ const [toolsByServer, setToolsByServer] = useState({});
94
+ const [expandedIds, setExpandedIds] = useState(() => /* @__PURE__ */ new Set());
95
+ useEffect(() => {
96
+ if (getMcpTools === void 0) return;
97
+ let cancelled = false;
98
+ for (const mount of mounts) {
99
+ void getMcpTools({ connectorId: mount.name }).then(
100
+ (tools) => {
101
+ if (!cancelled) setToolsByServer((prev) => ({ ...prev, [mount.name]: tools }));
102
+ },
103
+ () => {
104
+ }
105
+ );
106
+ }
107
+ return () => {
108
+ cancelled = true;
109
+ };
110
+ }, [getMcpTools, mounts]);
111
+ if (mounts.length === 0) {
112
+ return /* @__PURE__ */ jsx(AgentOverviewCard, { title: "MCP Servers & Tools", icon: "plug", count: 0, children: /* @__PURE__ */ jsx("p", { className: "text-text-secondary text-xs", children: "No connectors attached." }) });
113
+ }
114
+ return /* @__PURE__ */ jsx(AgentOverviewCard, { title: "MCP Servers & Tools", icon: "plug", count: mounts.length, children: /* @__PURE__ */ jsx("ul", { className: "space-y-1.5", children: mounts.map((mount) => {
115
+ const tools = toolsByServer[mount.name] ?? [];
116
+ const selectors = approvalSelectorsFromMount(mount.value);
117
+ const enableSelectors = enableSelectorsFromMount(mount.value);
118
+ const enabled = selectedToolNames({
119
+ enableSelectors,
120
+ disableSelectors: disableSelectorsFromMount(mount.value),
121
+ tools
122
+ });
123
+ const toolNames = enabled.names.map((toolName) => {
124
+ const tool = tools.find((item) => item.name === toolName);
125
+ const kind = tool === void 0 ? void 0 : mcpToolKind(tool);
126
+ return {
127
+ toolName,
128
+ kind,
129
+ approvalRequired: namedToolRequiresApproval({ toolName, tools, selectors })
130
+ };
131
+ }).sort((left, right) => KIND_ORDER[left.kind ?? "unknown"] - KIND_ORDER[right.kind ?? "unknown"]);
132
+ const approvalCount = toolNames.filter((tool) => tool.approvalRequired).length;
133
+ const expanded = expandedIds.has(mount.id);
134
+ return /* @__PURE__ */ jsxs("li", { className: "overflow-hidden rounded-md border border-border", children: [
135
+ /* @__PURE__ */ jsxs(
136
+ "button",
137
+ {
138
+ type: "button",
139
+ "aria-expanded": expanded,
140
+ disabled: toolNames.length === 0,
141
+ className: "flex w-full cursor-pointer items-center gap-2 bg-secondary-bg px-2.5 py-2 text-left text-xs hover:bg-ghost-button-hover disabled:cursor-default disabled:hover:bg-secondary-bg",
142
+ onClick: () => setExpandedIds((prev) => {
143
+ const next = new Set(prev);
144
+ if (expanded) next.delete(mount.id);
145
+ else next.add(mount.id);
146
+ return next;
147
+ }),
148
+ children: [
149
+ /* @__PURE__ */ jsx(
150
+ Icon,
151
+ {
152
+ name: "chevron-down",
153
+ className: cn(
154
+ "size-3 shrink-0 text-text-secondary transition-transform",
155
+ expanded ? void 0 : "-rotate-90",
156
+ toolNames.length === 0 && "invisible"
157
+ )
158
+ }
159
+ ),
160
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate font-medium", children: mount.name }),
161
+ /* @__PURE__ */ jsx("span", { className: "shrink-0 text-text-secondary", children: enabled.resolved ? toolCountLabel(toolNames.length) : toolSelectorLabel(enableSelectors) }),
162
+ approvalCount > 0 ? /* @__PURE__ */ jsx(ApprovalCountBadge, { count: approvalCount }) : null
163
+ ]
164
+ }
165
+ ),
166
+ expanded ? /* @__PURE__ */ jsx("ul", { className: "divide-y divide-border border-t border-border", children: toolNames.map(({ toolName, kind, approvalRequired }) => /* @__PURE__ */ jsxs("li", { className: "flex items-center gap-2 px-2.5 py-1.5", children: [
167
+ /* @__PURE__ */ jsx("span", { className: "min-w-0 flex-1 truncate font-mono text-[0.6875rem]", title: toolName, children: toolName }),
168
+ kind ? /* @__PURE__ */ jsx(ToolKindPill, { kind }) : null,
169
+ /* @__PURE__ */ jsx(ApprovalIndicator, { approvalRequired, toolName })
170
+ ] }, toolName)) }) : null
171
+ ] }, mount.id);
172
+ }) }) });
173
+ }
174
+
175
+ // src/atoms/agent-details/AgentOverview.tsx
176
+ import { Fragment, jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
177
+ var valueClassName = "text-right font-mono text-primary-button-bg";
178
+ function isRecord(value) {
179
+ return typeof value === "object" && value != null;
180
+ }
181
+ function readName(value) {
182
+ if (!("name" in value) || typeof value.name !== "string") return null;
183
+ return value.name;
184
+ }
185
+ function readRecordValue(record, ...keys) {
186
+ for (const key of keys) {
187
+ const value = record?.[key];
188
+ if (value !== void 0) return value;
189
+ }
190
+ return void 0;
191
+ }
192
+ function displayModelName(name) {
193
+ const slash = name.lastIndexOf("/");
194
+ return slash >= 0 ? name.slice(slash + 1) : name;
195
+ }
196
+ function AgentOverview({ detail }) {
197
+ const Markdown = useSlot("Markdown");
198
+ const AgentOverviewCard = useSlot("AgentOverviewCard");
199
+ const [instructionsView, setInstructionsView] = useState2("markdown");
200
+ const [copied, setCopied] = useState2(false);
201
+ const spec = detail.agentSpec;
202
+ const skills = spec.skills ?? [];
203
+ const modelParams = isRecord(spec.model.params) ? spec.model.params : null;
204
+ const maxTokens = readRecordValue(modelParams, "maxTokens", "max_tokens");
205
+ const temperature = readRecordValue(modelParams, "temperature");
206
+ const config = isRecord(spec.config) ? spec.config : null;
207
+ const sandbox = isRecord(config?.sandbox) ? config.sandbox : null;
208
+ const instructions = spec.instructions?.trim() ? spec.instructions : null;
209
+ const description = detail.description?.trim() ? detail.description : null;
210
+ const execution = [
211
+ ["Sandbox", typeof sandbox?.enabled === "boolean" ? sandbox.enabled ? "Enabled" : "Disabled" : void 0],
212
+ ["Iteration limit", readRecordValue(config, "iterationLimit", "iteration_limit")],
213
+ ["Response format", readRecordValue(config, "responseFormat", "response_format")]
214
+ ].filter((entry) => {
215
+ return typeof entry[1] === "string" || typeof entry[1] === "number";
216
+ });
217
+ const capabilities = [
218
+ ["Generative UI", spec.config?.generativeUi?.enabled],
219
+ ["Dynamic sub-agents", spec.config?.dynamicSubAgents?.enabled],
220
+ ["Ask user questions", spec.config?.askUserQuestions?.enabled]
221
+ ].filter((entry) => typeof entry[1] === "boolean");
222
+ const toggleLabel = instructionsView === "markdown" ? "Raw" : "Markdown";
223
+ return /* @__PURE__ */ jsx2("div", { className: "flex min-h-0 flex-1 flex-col gap-3 overflow-auto p-4 md:overflow-hidden", children: /* @__PURE__ */ jsxs2("div", { className: "grid min-h-0 flex-1 gap-3 md:grid-cols-[minmax(0,1fr)_22rem] md:overflow-hidden", children: [
224
+ /* @__PURE__ */ jsxs2("section", { className: "flex min-h-64 flex-col rounded-lg border border-border bg-card-bg p-4 text-text-primary", children: [
225
+ /* @__PURE__ */ jsxs2("div", { className: "mb-3 flex shrink-0 items-center justify-between gap-2", children: [
226
+ /* @__PURE__ */ jsxs2("h2", { className: "flex items-center gap-1.5 text-sm font-semibold text-text-primary", children: [
227
+ /* @__PURE__ */ jsx2(Icon, { name: "book-open", className: "size-4 text-text-secondary" }),
228
+ "Instructions"
229
+ ] }),
230
+ instructions ? /* @__PURE__ */ jsxs2(
231
+ "div",
232
+ {
233
+ className: "inline-flex h-7 items-stretch overflow-hidden rounded-md border border-border bg-primary-bg text-xs font-medium text-text-secondary",
234
+ role: "group",
235
+ "aria-label": "Instructions actions",
236
+ children: [
237
+ /* @__PURE__ */ jsx2(
238
+ "button",
239
+ {
240
+ type: "button",
241
+ "aria-label": `Show ${toggleLabel}`,
242
+ onClick: () => setInstructionsView((view) => view === "markdown" ? "raw" : "markdown"),
243
+ className: "cursor-pointer px-2.5 transition-colors hover:bg-ghost-button-hover hover:text-text-primary",
244
+ children: toggleLabel
245
+ }
246
+ ),
247
+ /* @__PURE__ */ jsx2("span", { className: "w-px self-stretch bg-border", "aria-hidden": true }),
248
+ /* @__PURE__ */ jsx2(
249
+ "button",
250
+ {
251
+ type: "button",
252
+ title: copied ? "Copied!" : "Copy",
253
+ "aria-label": copied ? "Copied!" : "Copy",
254
+ onClick: () => {
255
+ void navigator.clipboard.writeText(instructions).then(() => {
256
+ setCopied(true);
257
+ setTimeout(() => setCopied(false), 2e3);
258
+ });
259
+ },
260
+ className: "inline-flex cursor-pointer items-center justify-center px-2 transition-colors hover:bg-ghost-button-hover hover:text-text-primary",
261
+ children: /* @__PURE__ */ jsx2(Icon, { name: copied ? "check" : "copy", size: 12 })
262
+ }
263
+ )
264
+ ]
265
+ }
266
+ ) : null
267
+ ] }),
268
+ /* @__PURE__ */ jsx2("div", { className: "min-h-0 flex-1 overflow-auto", children: instructions ? instructionsView === "markdown" ? /* @__PURE__ */ jsx2(Markdown, { content: instructions, readOnly: true, className: "text-sm" }) : /* @__PURE__ */ jsx2("pre", { className: "whitespace-pre-wrap break-words font-mono text-sm text-text-primary", children: instructions }) : /* @__PURE__ */ jsx2("p", { className: "text-sm text-text-secondary", children: "No instructions for this agent." }) })
269
+ ] }),
270
+ /* @__PURE__ */ jsxs2("aside", { className: "flex min-h-0 min-w-0 flex-col gap-3 md:overflow-auto", children: [
271
+ description ? /* @__PURE__ */ jsx2(AgentOverviewCard, { title: "Description", icon: "file", children: /* @__PURE__ */ jsx2("p", { className: "text-xs text-text-secondary", children: description }) }) : null,
272
+ /* @__PURE__ */ jsx2(AgentOverviewCard, { title: "Model Configuration", icon: "cpu", children: /* @__PURE__ */ jsxs2("dl", { className: "grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-1 text-xs", children: [
273
+ /* @__PURE__ */ jsx2("dt", { className: "text-text-secondary", children: "Model" }),
274
+ /* @__PURE__ */ jsx2("dd", { className: cn(valueClassName, "truncate"), title: spec.model.name, children: displayModelName(spec.model.name) }),
275
+ typeof maxTokens === "number" ? /* @__PURE__ */ jsxs2(Fragment, { children: [
276
+ /* @__PURE__ */ jsx2("dt", { className: "text-text-secondary", children: "Max tokens" }),
277
+ /* @__PURE__ */ jsx2("dd", { className: valueClassName, children: maxTokens })
278
+ ] }) : null,
279
+ spec.model.params?.reasoningEffort !== void 0 ? /* @__PURE__ */ jsxs2(Fragment, { children: [
280
+ /* @__PURE__ */ jsx2("dt", { className: "text-text-secondary", children: "Reasoning" }),
281
+ /* @__PURE__ */ jsx2("dd", { className: valueClassName, children: spec.model.params.reasoningEffort })
282
+ ] }) : null,
283
+ typeof temperature === "number" ? /* @__PURE__ */ jsxs2(Fragment, { children: [
284
+ /* @__PURE__ */ jsx2("dt", { className: "text-text-secondary", children: "Temperature" }),
285
+ /* @__PURE__ */ jsx2("dd", { className: valueClassName, children: temperature })
286
+ ] }) : null
287
+ ] }) }),
288
+ /* @__PURE__ */ jsx2(AgentOverviewMcpServers, { mcpServers: spec.mcpServers }),
289
+ /* @__PURE__ */ jsx2(AgentOverviewCard, { title: "Attached Skills", icon: "lightbulb", count: skills.length, children: skills.length === 0 ? /* @__PURE__ */ jsx2("p", { className: "text-xs text-text-secondary", children: "No skills attached." }) : /* @__PURE__ */ jsx2("ul", { className: "space-y-1.5", children: skills.map((skill, index) => /* @__PURE__ */ jsx2(
290
+ "li",
291
+ {
292
+ className: "rounded-md bg-secondary-bg px-2 py-1.5 text-xs",
293
+ children: readName(skill) ?? `Skill ${index + 1}`
294
+ },
295
+ `${readName(skill) ?? "skill"}-${index}`
296
+ )) }) }),
297
+ execution.length > 0 ? /* @__PURE__ */ jsx2(AgentOverviewCard, { title: "Execution", icon: "terminal", children: /* @__PURE__ */ jsx2("dl", { className: "space-y-1 text-xs", children: execution.map(([label, value]) => /* @__PURE__ */ jsxs2("div", { className: "flex justify-between gap-3", children: [
298
+ /* @__PURE__ */ jsx2("dt", { className: "text-text-secondary", children: label }),
299
+ /* @__PURE__ */ jsx2("dd", { className: valueClassName, children: value })
300
+ ] }, label)) }) }) : null,
301
+ capabilities.length > 0 ? /* @__PURE__ */ jsx2(AgentOverviewCard, { title: "Capabilities", icon: "cube", children: /* @__PURE__ */ jsx2("dl", { className: "space-y-1 text-xs", children: capabilities.map(([label, enabled]) => /* @__PURE__ */ jsxs2("div", { className: "flex justify-between gap-3", children: [
302
+ /* @__PURE__ */ jsx2("dt", { className: "text-text-secondary", children: label }),
303
+ /* @__PURE__ */ jsx2("dd", { className: valueClassName, children: enabled ? "Enabled" : "Disabled" })
304
+ ] }, label)) }) }) : null
305
+ ] })
306
+ ] }) });
307
+ }
308
+ export {
309
+ AgentOverview as default
310
+ };
311
+ //# sourceMappingURL=AgentOverview-3LJZ6MO7.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/atoms/agent-details/AgentOverview.tsx","../src/atoms/agent-details/AgentOverviewMcpServers.tsx"],"sourcesContent":["'use client';\n\nimport { useState, type ComponentType } from 'react';\nimport { Icon } from '../../icons/Icon.js';\nimport { useSlot } from '../../theme/SlotsProvider.js';\nimport { cn } from '../lib/cn.js';\nimport { AgentOverviewMcpServers } from './AgentOverviewMcpServers.js';\nimport type { AgentOverviewProps } from './types.js';\n\ntype InstructionsView = 'markdown' | 'raw';\n\nconst valueClassName = 'text-right font-mono text-primary-button-bg';\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value != null;\n}\n\nfunction readName(value: object): string | null {\n if (!('name' in value) || typeof value.name !== 'string') return null;\n return value.name;\n}\n\nfunction readRecordValue(record: Record<string, unknown> | null, ...keys: string[]): unknown {\n for (const key of keys) {\n const value = record?.[key];\n if (value !== undefined) return value;\n }\n return undefined;\n}\n\nfunction displayModelName(name: string): string {\n const slash = name.lastIndexOf('/');\n return slash >= 0 ? name.slice(slash + 1) : name;\n}\n\nexport default function AgentOverview({ detail }: AgentOverviewProps) {\n const Markdown = useSlot('Markdown');\n const AgentOverviewCard = useSlot('AgentOverviewCard');\n const [instructionsView, setInstructionsView] = useState<InstructionsView>('markdown');\n const [copied, setCopied] = useState(false);\n const spec = detail.agentSpec;\n const skills = spec.skills ?? [];\n const modelParams = isRecord(spec.model.params) ? spec.model.params : null;\n const maxTokens = readRecordValue(modelParams, 'maxTokens', 'max_tokens');\n const temperature = readRecordValue(modelParams, 'temperature');\n const config = isRecord(spec.config) ? spec.config : null;\n const sandbox = isRecord(config?.sandbox) ? config.sandbox : null;\n const instructions = spec.instructions?.trim() ? spec.instructions : null;\n const description = detail.description?.trim() ? detail.description : null;\n const execution = [\n ['Sandbox', typeof sandbox?.enabled === 'boolean' ? (sandbox.enabled ? 'Enabled' : 'Disabled') : undefined],\n ['Iteration limit', readRecordValue(config, 'iterationLimit', 'iteration_limit')],\n ['Response format', readRecordValue(config, 'responseFormat', 'response_format')],\n ].filter((entry): entry is [string, string | number] => {\n return typeof entry[1] === 'string' || typeof entry[1] === 'number';\n });\n const capabilities = [\n ['Generative UI', spec.config?.generativeUi?.enabled],\n ['Dynamic sub-agents', spec.config?.dynamicSubAgents?.enabled],\n ['Ask user questions', spec.config?.askUserQuestions?.enabled],\n ].filter((entry): entry is [string, boolean] => typeof entry[1] === 'boolean');\n const toggleLabel = instructionsView === 'markdown' ? 'Raw' : 'Markdown';\n\n return (\n <div className=\"flex min-h-0 flex-1 flex-col gap-3 overflow-auto p-4 md:overflow-hidden\">\n <div className=\"grid min-h-0 flex-1 gap-3 md:grid-cols-[minmax(0,1fr)_22rem] md:overflow-hidden\">\n <section className=\"flex min-h-64 flex-col rounded-lg border border-border bg-card-bg p-4 text-text-primary\">\n <div className=\"mb-3 flex shrink-0 items-center justify-between gap-2\">\n <h2 className=\"flex items-center gap-1.5 text-sm font-semibold text-text-primary\">\n <Icon name=\"book-open\" className=\"size-4 text-text-secondary\" />\n Instructions\n </h2>\n {instructions ? (\n <div\n className=\"inline-flex h-7 items-stretch overflow-hidden rounded-md border border-border bg-primary-bg text-xs font-medium text-text-secondary\"\n role=\"group\"\n aria-label=\"Instructions actions\"\n >\n <button\n type=\"button\"\n aria-label={`Show ${toggleLabel}`}\n onClick={() => setInstructionsView(view => (view === 'markdown' ? 'raw' : 'markdown'))}\n className=\"cursor-pointer px-2.5 transition-colors hover:bg-ghost-button-hover hover:text-text-primary\"\n >\n {toggleLabel}\n </button>\n <span className=\"w-px self-stretch bg-border\" aria-hidden />\n <button\n type=\"button\"\n title={copied ? 'Copied!' : 'Copy'}\n aria-label={copied ? 'Copied!' : 'Copy'}\n onClick={() => {\n void navigator.clipboard.writeText(instructions).then(() => {\n setCopied(true);\n setTimeout(() => setCopied(false), 2000);\n });\n }}\n className=\"inline-flex cursor-pointer items-center justify-center px-2 transition-colors hover:bg-ghost-button-hover hover:text-text-primary\"\n >\n <Icon name={copied ? 'check' : 'copy'} size={12} />\n </button>\n </div>\n ) : null}\n </div>\n <div className=\"min-h-0 flex-1 overflow-auto\">\n {instructions ? (\n instructionsView === 'markdown' ? (\n <Markdown content={instructions} readOnly className=\"text-sm\" />\n ) : (\n <pre className=\"whitespace-pre-wrap break-words font-mono text-sm text-text-primary\">\n {instructions}\n </pre>\n )\n ) : (\n <p className=\"text-sm text-text-secondary\">No instructions for this agent.</p>\n )}\n </div>\n </section>\n\n <aside className=\"flex min-h-0 min-w-0 flex-col gap-3 md:overflow-auto\">\n {description ? (\n <AgentOverviewCard title=\"Description\" icon=\"file\">\n <p className=\"text-xs text-text-secondary\">{description}</p>\n </AgentOverviewCard>\n ) : null}\n <AgentOverviewCard title=\"Model Configuration\" icon=\"cpu\">\n <dl className=\"grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-1 text-xs\">\n <dt className=\"text-text-secondary\">Model</dt>\n <dd className={cn(valueClassName, 'truncate')} title={spec.model.name}>\n {displayModelName(spec.model.name)}\n </dd>\n {typeof maxTokens === 'number' ? (\n <>\n <dt className=\"text-text-secondary\">Max tokens</dt>\n <dd className={valueClassName}>{maxTokens}</dd>\n </>\n ) : null}\n {spec.model.params?.reasoningEffort !== undefined ? (\n <>\n <dt className=\"text-text-secondary\">Reasoning</dt>\n <dd className={valueClassName}>{spec.model.params.reasoningEffort}</dd>\n </>\n ) : null}\n {typeof temperature === 'number' ? (\n <>\n <dt className=\"text-text-secondary\">Temperature</dt>\n <dd className={valueClassName}>{temperature}</dd>\n </>\n ) : null}\n </dl>\n </AgentOverviewCard>\n <AgentOverviewMcpServers mcpServers={spec.mcpServers} />\n\n <AgentOverviewCard title=\"Attached Skills\" icon=\"lightbulb\" count={skills.length}>\n {skills.length === 0 ? (\n <p className=\"text-xs text-text-secondary\">No skills attached.</p>\n ) : (\n <ul className=\"space-y-1.5\">\n {skills.map((skill, index) => (\n <li\n key={`${readName(skill) ?? 'skill'}-${index}`}\n className=\"rounded-md bg-secondary-bg px-2 py-1.5 text-xs\"\n >\n {readName(skill) ?? `Skill ${index + 1}`}\n </li>\n ))}\n </ul>\n )}\n </AgentOverviewCard>\n\n {execution.length > 0 ? (\n <AgentOverviewCard title=\"Execution\" icon=\"terminal\">\n <dl className=\"space-y-1 text-xs\">\n {execution.map(([label, value]) => (\n <div key={label} className=\"flex justify-between gap-3\">\n <dt className=\"text-text-secondary\">{label}</dt>\n <dd className={valueClassName}>{value}</dd>\n </div>\n ))}\n </dl>\n </AgentOverviewCard>\n ) : null}\n\n {capabilities.length > 0 ? (\n <AgentOverviewCard title=\"Capabilities\" icon=\"cube\">\n <dl className=\"space-y-1 text-xs\">\n {capabilities.map(([label, enabled]) => (\n <div key={label} className=\"flex justify-between gap-3\">\n <dt className=\"text-text-secondary\">{label}</dt>\n <dd className={valueClassName}>{enabled ? 'Enabled' : 'Disabled'}</dd>\n </div>\n ))}\n </dl>\n </AgentOverviewCard>\n ) : null}\n </aside>\n </div>\n </div>\n );\n}\n\ndeclare module '../../theme/SlotsProvider.js' {\n interface AtomSlots {\n AgentOverview: ComponentType<AgentOverviewProps>;\n }\n}\n","'use client';\n\nimport { useEffect, useMemo, useState } from 'react';\n\nimport { Icon } from '../../icons/Icon.js';\nimport { useOptionalServer } from '../../server/ServerContext.js';\nimport type { McpToolSelection } from '../../server/types.js';\nimport { useSlot } from '../../theme/SlotsProvider.js';\nimport {\n approvalSelectorsFromMount,\n disableSelectorsFromMount,\n editableMountsFromSpec,\n enableSelectorsFromMount,\n} from '../draft/agentConfigMounts.js';\nimport { namedToolRequiresApproval } from '../draft/mcpToolApprovals.js';\nimport { mcpToolKind, type McpToolKind } from '../draft/mcpToolSections.js';\nimport { selectedToolNames, TOOL_TAG_ALL } from '../draft/mcpToolSelectors.js';\nimport { cn } from '../lib/cn.js';\nimport { Tooltip } from '../primitives/Tooltip.js';\n\nconst KIND_CLASSES: Record<McpToolKind, string> = {\n read: 'border-border bg-secondary-bg text-text-secondary',\n write: 'border-border bg-secondary-bg text-text-primary',\n destructive: 'border-failure-bg/30 bg-failure-bg/10 text-failure-bg',\n};\n\n/** Read-only tools first and destructive last, mirroring the tool picker's sections. */\nconst KIND_ORDER: Record<McpToolKind | 'unknown', number> = {\n read: 0,\n write: 1,\n unknown: 2,\n destructive: 3,\n};\n\nfunction toolCountLabel(count: number): string {\n return count === 1 ? '1 tool' : `${count} tools`;\n}\n\n/** Shown while tags cannot be resolved: the selectors themselves are the best available answer. */\nfunction toolSelectorLabel(enableSelectors: readonly string[]): string {\n if (enableSelectors.includes(TOOL_TAG_ALL)) return 'All tools';\n return enableSelectors.filter(selector => selector.startsWith('@')).join(' ');\n}\n\nfunction ApprovalCountBadge({ count }: { count: number }) {\n return (\n <span\n className=\"border-warning-bg/40 bg-warning-bg/10 text-warning-bg inline-flex shrink-0 items-center gap-1 rounded-full border px-1.5 py-0.5 text-[0.625rem] font-medium\"\n aria-label={`${count} ${count === 1 ? 'tool needs' : 'tools need'} approval`}\n >\n <Icon name=\"shield-check\" className=\"size-2.5\" />\n {count}\n </span>\n );\n}\n\nfunction ToolKindPill({ kind }: { kind: McpToolKind }) {\n return (\n <span className={cn('shrink-0 rounded-full border px-1.5 py-0.5 text-[0.625rem] font-medium', KIND_CLASSES[kind])}>\n {kind}\n </span>\n );\n}\n\nfunction ApprovalIndicator({ approvalRequired, toolName }: { approvalRequired: boolean; toolName: string }) {\n return (\n <Tooltip\n content={approvalRequired ? 'Asks for approval before running' : 'Runs without asking for approval'}\n triggerClassName=\"shrink-0\"\n >\n <span\n role=\"img\"\n aria-label={`${toolName} ${approvalRequired ? 'requires approval' : 'runs without approval'}`}\n className={cn(\n 'flex size-5 items-center justify-center rounded-md border',\n approvalRequired\n ? 'border-warning-bg/50 bg-warning-bg/10 text-warning-bg'\n : 'border-border text-text-secondary',\n )}\n >\n <Icon name={approvalRequired ? 'shield-check' : 'shield'} className=\"size-3\" />\n </span>\n </Tooltip>\n );\n}\n\n/** Attached MCP servers, each expanding into the tools the agent can call. */\nexport function AgentOverviewMcpServers({ mcpServers }: { mcpServers: unknown }) {\n const AgentOverviewCard = useSlot('AgentOverviewCard');\n const server = useOptionalServer();\n const getMcpTools = server?.getMcpTools;\n const mounts = useMemo(() => editableMountsFromSpec(mcpServers), [mcpServers]);\n const [toolsByServer, setToolsByServer] = useState<Record<string, McpToolSelection[]>>({});\n const [expandedIds, setExpandedIds] = useState<ReadonlySet<string>>(() => new Set());\n\n // Tool metadata drives the counts, kinds, and approval state; a failing server just shows less.\n useEffect(() => {\n if (getMcpTools === undefined) return;\n let cancelled = false;\n for (const mount of mounts) {\n void getMcpTools({ connectorId: mount.name }).then(\n tools => {\n if (!cancelled) setToolsByServer(prev => ({ ...prev, [mount.name]: tools }));\n },\n () => {},\n );\n }\n return () => {\n cancelled = true;\n };\n }, [getMcpTools, mounts]);\n\n if (mounts.length === 0) {\n return (\n <AgentOverviewCard title=\"MCP Servers & Tools\" icon=\"plug\" count={0}>\n <p className=\"text-text-secondary text-xs\">No connectors attached.</p>\n </AgentOverviewCard>\n );\n }\n\n return (\n <AgentOverviewCard title=\"MCP Servers & Tools\" icon=\"plug\" count={mounts.length}>\n <ul className=\"space-y-1.5\">\n {mounts.map(mount => {\n const tools = toolsByServer[mount.name] ?? [];\n const selectors = approvalSelectorsFromMount(mount.value);\n const enableSelectors = enableSelectorsFromMount(mount.value);\n const enabled = selectedToolNames({\n enableSelectors,\n disableSelectors: disableSelectorsFromMount(mount.value),\n tools,\n });\n const toolNames = enabled.names\n .map(toolName => {\n const tool = tools.find(item => item.name === toolName);\n const kind = tool === undefined ? undefined : mcpToolKind(tool);\n return {\n toolName,\n kind,\n approvalRequired: namedToolRequiresApproval({ toolName, tools, selectors }),\n };\n })\n .sort((left, right) => KIND_ORDER[left.kind ?? 'unknown'] - KIND_ORDER[right.kind ?? 'unknown']);\n const approvalCount = toolNames.filter(tool => tool.approvalRequired).length;\n const expanded = expandedIds.has(mount.id);\n return (\n <li key={mount.id} className=\"overflow-hidden rounded-md border border-border\">\n <button\n type=\"button\"\n aria-expanded={expanded}\n disabled={toolNames.length === 0}\n className=\"flex w-full cursor-pointer items-center gap-2 bg-secondary-bg px-2.5 py-2 text-left text-xs hover:bg-ghost-button-hover disabled:cursor-default disabled:hover:bg-secondary-bg\"\n onClick={() =>\n setExpandedIds(prev => {\n const next = new Set(prev);\n if (expanded) next.delete(mount.id);\n else next.add(mount.id);\n return next;\n })\n }\n >\n <Icon\n name=\"chevron-down\"\n className={cn(\n 'size-3 shrink-0 text-text-secondary transition-transform',\n expanded ? undefined : '-rotate-90',\n toolNames.length === 0 && 'invisible',\n )}\n />\n <span className=\"min-w-0 flex-1 truncate font-medium\">{mount.name}</span>\n <span className=\"shrink-0 text-text-secondary\">\n {enabled.resolved ? toolCountLabel(toolNames.length) : toolSelectorLabel(enableSelectors)}\n </span>\n {approvalCount > 0 ? <ApprovalCountBadge count={approvalCount} /> : null}\n </button>\n {expanded ? (\n <ul className=\"divide-y divide-border border-t border-border\">\n {toolNames.map(({ toolName, kind, approvalRequired }) => (\n <li key={toolName} className=\"flex items-center gap-2 px-2.5 py-1.5\">\n <span className=\"min-w-0 flex-1 truncate font-mono text-[0.6875rem]\" title={toolName}>\n {toolName}\n </span>\n {kind ? <ToolKindPill kind={kind} /> : null}\n <ApprovalIndicator approvalRequired={approvalRequired} toolName={toolName} />\n </li>\n ))}\n </ul>\n ) : null}\n </li>\n );\n })}\n </ul>\n </AgentOverviewCard>\n );\n}\n"],"mappings":"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","names":["useState","jsx","jsxs","useState"]}
@@ -4,15 +4,15 @@ import {
4
4
  getSessionEventColor,
5
5
  useSlot,
6
6
  useThemeMode
7
- } from "./chunk-GG23N2GW.js";
7
+ } from "./chunk-OH357IHR.js";
8
8
  import "./chunk-T6QQV5LK.js";
9
- import "./chunk-3ZW74FHC.js";
9
+ import "./chunk-5N5V7YLO.js";
10
10
  import "./chunk-2GIZY3JJ.js";
11
11
  import "./chunk-M6MHLVSO.js";
12
- import "./chunk-CG75X77Q.js";
12
+ import "./chunk-SLMFEG7X.js";
13
13
  import {
14
14
  cn
15
- } from "./chunk-JCL3Q7RW.js";
15
+ } from "./chunk-GKXDRULM.js";
16
16
 
17
17
  // src/atoms/agent-details/AgentSessionEventTimeline.tsx
18
18
  import { useCallback, useMemo, useState } from "react";
@@ -85,4 +85,4 @@ function AgentSessionEventTimeline({ turns, segments, onSelectTurn }) {
85
85
  export {
86
86
  AgentSessionEventTimeline
87
87
  };
88
- //# sourceMappingURL=AgentSessionEventTimeline-GRGIQTRE.js.map
88
+ //# sourceMappingURL=AgentSessionEventTimeline-5GOJKT7D.js.map
@@ -25,13 +25,13 @@ import {
25
25
  mergeOverlappingSubAgentSegments,
26
26
  roundDurationMsToSecond,
27
27
  useThemeMode
28
- } from "./chunk-GG23N2GW.js";
28
+ } from "./chunk-OH357IHR.js";
29
29
  import "./chunk-T6QQV5LK.js";
30
- import "./chunk-3ZW74FHC.js";
30
+ import "./chunk-5N5V7YLO.js";
31
31
  import "./chunk-2GIZY3JJ.js";
32
32
  import "./chunk-M6MHLVSO.js";
33
- import "./chunk-CG75X77Q.js";
34
- import "./chunk-JCL3Q7RW.js";
33
+ import "./chunk-SLMFEG7X.js";
34
+ import "./chunk-GKXDRULM.js";
35
35
 
36
36
  // src/atoms/agent-details/AgentSessionEventTimelineChart.tsx
37
37
  import {
@@ -588,4 +588,4 @@ function AgentSessionEventTimelineChart({
588
588
  export {
589
589
  AgentSessionEventTimelineChart
590
590
  };
591
- //# sourceMappingURL=AgentSessionEventTimelineChart-GNF4VOUT.js.map
591
+ //# sourceMappingURL=AgentSessionEventTimelineChart-UYG3JQMP.js.map
@@ -9,16 +9,23 @@ import {
9
9
  sessionIsCreateAgent
10
10
  } from "./chunk-RDXBMTP5.js";
11
11
  import {
12
+ Button,
13
+ Dialog,
14
+ DialogContent,
15
+ DialogFooter,
16
+ DialogHeader,
17
+ DialogTitle,
12
18
  EmptyScreen,
13
19
  Skeleton,
14
20
  useResourcePermissions,
15
21
  useSessionShareSearch,
16
- useSlot
17
- } from "./chunk-GG23N2GW.js";
22
+ useSlot,
23
+ useToasterOptional
24
+ } from "./chunk-OH357IHR.js";
18
25
  import "./chunk-T6QQV5LK.js";
19
26
  import {
20
27
  Icon
21
- } from "./chunk-3ZW74FHC.js";
28
+ } from "./chunk-5N5V7YLO.js";
22
29
  import {
23
30
  sessionTimeRangeFromCreatedAt,
24
31
  useAgentSessionsServer,
@@ -26,10 +33,10 @@ import {
26
33
  useServer
27
34
  } from "./chunk-2GIZY3JJ.js";
28
35
  import "./chunk-M6MHLVSO.js";
29
- import "./chunk-CG75X77Q.js";
36
+ import "./chunk-SLMFEG7X.js";
30
37
  import {
31
38
  cn
32
- } from "./chunk-JCL3Q7RW.js";
39
+ } from "./chunk-GKXDRULM.js";
33
40
 
34
41
  // src/atoms/agent-details/AgentSessions.tsx
35
42
  import { useCallback, useEffect, useMemo, useRef, useState } from "react";
@@ -68,14 +75,10 @@ function entrySourceType(entry) {
68
75
  function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
69
76
  const sessionsServer = useAgentSessionsServer();
70
77
  const chatServer = useServer();
78
+ const toaster = useToasterOptional();
71
79
  const shell = useOptionalShellMode();
72
80
  const routes = useOptionalResolvedRoutes();
73
81
  const { sessionId: selectedSessionId, updateShareSearch } = useSessionShareSearch();
74
- const { allows } = useResourcePermissions({
75
- resourceType: "session",
76
- resourceIds: selectedSessionId == null ? [] : [selectedSessionId]
77
- });
78
- const canResume = allows(selectedSessionId, "MANAGE");
79
82
  const AgentSessionListRow = useSlot("AgentSessionListRow");
80
83
  const AgentSessionDetailHeader = useSlot("AgentSessionDetailHeader");
81
84
  const AgentSessionTimelineContainer = useSlot("AgentSessionTimelineContainer");
@@ -93,6 +96,18 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
93
96
  const [detailSession, setDetailSession] = useState();
94
97
  const [detailLoading, setDetailLoading] = useState(false);
95
98
  const [detailFailed, setDetailFailed] = useState(false);
99
+ const [pendingDelete, setPendingDelete] = useState(null);
100
+ const canDeleteSession = typeof chatServer.deleteSession === "function";
101
+ const permissionResourceIds = useMemo(() => {
102
+ const ids = new Set(entries.map((entry) => entry.id));
103
+ if (selectedSessionId != null && selectedSessionId.length > 0) ids.add(selectedSessionId);
104
+ return [...ids];
105
+ }, [entries, selectedSessionId]);
106
+ const { allows } = useResourcePermissions({
107
+ resourceType: "session",
108
+ resourceIds: permissionResourceIds
109
+ });
110
+ const canResume = allows(selectedSessionId, "MANAGE");
96
111
  const listRequest = useMemo(
97
112
  () => ({
98
113
  order: "desc",
@@ -205,6 +220,19 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
205
220
  if (selectedSessionId == null) return;
206
221
  updateShareSearch({ sessionId: null });
207
222
  };
223
+ const handleDelete = async (entry) => {
224
+ if (!allows(entry.id, "DELETE") || typeof chatServer.deleteSession !== "function") return;
225
+ setPendingDelete(null);
226
+ try {
227
+ await chatServer.deleteSession({ sessionId: entry.id });
228
+ setEntries((current) => current.filter((item) => item.id !== entry.id));
229
+ if (selectedSessionId === entry.id) {
230
+ updateShareSearch({ sessionId: null });
231
+ }
232
+ } catch (caught) {
233
+ toaster?.showError(caught);
234
+ }
235
+ };
208
236
  const selectedEntry = entries.find((entry) => entry.id === selectedSessionId);
209
237
  const selectedTitle = detailSession != null ? sessionTitle(detailSession) : selectedEntry != null ? sessionTitle(selectedEntry) : selectedSessionId ?? "Untitled session";
210
238
  const resumeIsCreateAgent = detailSession != null ? sessionIsCreateAgent(detailSession) : selectedEntry != null ? sessionIsCreateAgent(selectedEntry) : false;
@@ -250,7 +278,11 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
250
278
  lastActivityAt: entry.lastActivityAt,
251
279
  metrics: entry.metrics,
252
280
  active: entry.id === selectedSessionId,
253
- onSelect: () => selectSession(entry)
281
+ onSelect: () => selectSession(entry),
282
+ ...canDeleteSession ? {
283
+ onRequestDelete: () => setPendingDelete(entry),
284
+ canDelete: allows(entry.id, "DELETE")
285
+ } : {}
254
286
  },
255
287
  entry.id
256
288
  )),
@@ -312,7 +344,40 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
312
344
  listMetrics: selectedEntry?.metrics
313
345
  }
314
346
  )
315
- ] }) }) })
347
+ ] }) }) }),
348
+ pendingDelete != null ? /* @__PURE__ */ jsxs(
349
+ Dialog,
350
+ {
351
+ open: true,
352
+ onOpenChange: (open) => {
353
+ if (!open) setPendingDelete(null);
354
+ },
355
+ "aria-label": "Delete session",
356
+ className: "max-w-md",
357
+ children: [
358
+ /* @__PURE__ */ jsx(DialogContent, { children: /* @__PURE__ */ jsxs(DialogHeader, { children: [
359
+ /* @__PURE__ */ jsx(DialogTitle, { children: "Delete session" }),
360
+ /* @__PURE__ */ jsxs("p", { className: "text-text-secondary text-sm", children: [
361
+ "\u201C",
362
+ sessionTitle(pendingDelete),
363
+ "\u201D will be permanently deleted. This cannot be undone."
364
+ ] })
365
+ ] }) }),
366
+ /* @__PURE__ */ jsxs(DialogFooter, { children: [
367
+ /* @__PURE__ */ jsx(Button.Secondary, { type: "button", onClick: () => setPendingDelete(null), children: "Cancel" }),
368
+ /* @__PURE__ */ jsx(
369
+ Button.Destructive,
370
+ {
371
+ type: "button",
372
+ disabled: !allows(pendingDelete.id, "DELETE"),
373
+ onClick: () => void handleDelete(pendingDelete),
374
+ children: "Delete"
375
+ }
376
+ )
377
+ ] })
378
+ ]
379
+ }
380
+ ) : null
316
381
  ]
317
382
  }
318
383
  );
@@ -320,4 +385,4 @@ function AgentSessions({ agentId, startTimestamp, endTimestamp, shareView }) {
320
385
  export {
321
386
  AgentSessions
322
387
  };
323
- //# sourceMappingURL=AgentSessions-5OTF2BUW.js.map
388
+ //# sourceMappingURL=AgentSessions-KUABCQ4W.js.map