@tangle-network/agent-app 0.60.177 → 0.60.178
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/agent-profiles/d1.js +1 -1
- package/dist/agent-profiles/index.js +9 -1
- package/dist/agent-profiles/self-management.d.ts +82 -0
- package/dist/{chunk-6VXBUIM5.js → chunk-ARBBJWZA.js} +63 -6
- package/dist/{chunk-6VXBUIM5.js.map → chunk-ARBBJWZA.js.map} +1 -1
- package/dist/{chunk-MCAIZKQ5.js → chunk-CPNJRLPN.js} +15 -4
- package/dist/chunk-CPNJRLPN.js.map +1 -0
- package/dist/hub-approvals/index.js +1 -1
- package/dist/hub-approvals/present.d.ts +1 -1
- package/dist/hub-approvals/types.d.ts +35 -0
- package/dist/hub-approvals-react/dock.d.ts +3 -2
- package/dist/hub-approvals-react/email.d.ts +13 -0
- package/dist/hub-approvals-react/feedback.d.ts +20 -0
- package/dist/hub-approvals-react/index.d.ts +1 -0
- package/dist/hub-approvals-react/index.js +535 -286
- package/dist/hub-approvals-react/index.js.map +1 -1
- package/dist/hub-approvals-react/parts.d.ts +1 -1
- package/dist/hub-approvals-react/row.d.ts +3 -2
- package/package.json +1 -1
- package/dist/chunk-MCAIZKQ5.js.map +0 -1
|
@@ -7,17 +7,16 @@ import {
|
|
|
7
7
|
formatWhen,
|
|
8
8
|
hubActionReceipt,
|
|
9
9
|
presentHubAction
|
|
10
|
-
} from "../chunk-
|
|
10
|
+
} from "../chunk-CPNJRLPN.js";
|
|
11
11
|
|
|
12
12
|
// src/hub-approvals-react/dock.tsx
|
|
13
|
-
import { useEffect, useMemo, useRef, useState as
|
|
13
|
+
import { useEffect as useEffect3, useMemo, useRef, useState as useState4 } from "react";
|
|
14
14
|
import { Check, ChevronDown, ExternalLink, Loader2, X } from "lucide-react";
|
|
15
|
-
import { Button as
|
|
15
|
+
import { Button as Button3, Label as Label2, RadioGroup, RadioGroupItem } from "@tangle-network/ui/primitives";
|
|
16
16
|
|
|
17
17
|
// src/hub-approvals-react/parts.tsx
|
|
18
18
|
import { useState } from "react";
|
|
19
19
|
import { ChevronRight, Clock, Zap } from "lucide-react";
|
|
20
|
-
import { ProviderIcon } from "@tangle-network/sandbox-ui/integrations";
|
|
21
20
|
import { Button, StatusPill } from "@tangle-network/ui/primitives";
|
|
22
21
|
import { jsx, jsxs } from "react/jsx-runtime";
|
|
23
22
|
var PHASE_TONES = {
|
|
@@ -47,13 +46,15 @@ function HubApprovalWaitNote({ wait, className = "" }) {
|
|
|
47
46
|
] });
|
|
48
47
|
}
|
|
49
48
|
function HubProviderMark({ providerId, name, size = 28 }) {
|
|
50
|
-
const inner = Math.round(size * 0.64);
|
|
51
49
|
return /* @__PURE__ */ jsx(
|
|
52
50
|
"span",
|
|
53
51
|
{
|
|
54
52
|
className: "flex shrink-0 items-center justify-center rounded-lg border border-border bg-background",
|
|
55
53
|
style: { width: size, height: size },
|
|
56
|
-
|
|
54
|
+
title: name,
|
|
55
|
+
"data-provider": providerId,
|
|
56
|
+
"aria-hidden": true,
|
|
57
|
+
children: /* @__PURE__ */ jsx("span", { className: "text-sm font-semibold text-muted-foreground", children: name.charAt(0).toUpperCase() })
|
|
57
58
|
}
|
|
58
59
|
);
|
|
59
60
|
}
|
|
@@ -115,121 +116,196 @@ function relativeTime(at, now = Date.now()) {
|
|
|
115
116
|
// src/hub-approvals-react/preview.tsx
|
|
116
117
|
import { ArrowRight, CalendarDays, GitBranch, GitCommitHorizontal, GitPullRequest, MapPin, Phone, Users } from "lucide-react";
|
|
117
118
|
import { ApprovalDiffSummary } from "@tangle-network/ui/run";
|
|
119
|
+
|
|
120
|
+
// src/hub-approvals-react/email.tsx
|
|
121
|
+
import { useEffect, useState as useState2 } from "react";
|
|
118
122
|
import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
123
|
+
var EMAIL_TAGS = new Set("a abbr b blockquote br caption center code col colgroup dd del div dl dt em font h1 h2 h3 h4 h5 h6 hr i img li ol p pre s small span strong sub sup table tbody td tfoot th thead tr u ul".split(" "));
|
|
124
|
+
var EMAIL_ATTRIBUTES = new Set("align alt bgcolor border cellpadding cellspacing class color colspan dir face height lang rowspan size style title valign width".split(" "));
|
|
125
|
+
function embeddedPreviewImage(value) {
|
|
126
|
+
return value && /^data:image\/(?:png|jpeg|jpg|gif|webp);base64,[a-z0-9+/=\s]+$/i.test(value) ? value : void 0;
|
|
127
|
+
}
|
|
128
|
+
function emailDocument(body) {
|
|
129
|
+
const template = document.createElement("template");
|
|
130
|
+
template.innerHTML = body;
|
|
131
|
+
const target = document.createElement("div");
|
|
132
|
+
function copy(source, parent) {
|
|
133
|
+
if (source.nodeType === Node.TEXT_NODE) {
|
|
134
|
+
parent.appendChild(document.createTextNode(source.textContent ?? ""));
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
if (!(source instanceof HTMLElement) || !EMAIL_TAGS.has(source.localName)) return;
|
|
138
|
+
const element = document.createElement(source.localName);
|
|
139
|
+
for (const attribute of source.attributes) {
|
|
140
|
+
if (EMAIL_ATTRIBUTES.has(attribute.name)) element.setAttribute(attribute.name, attribute.value);
|
|
141
|
+
}
|
|
142
|
+
if (source.localName === "a") {
|
|
143
|
+
const href = source.getAttribute("href") ?? "";
|
|
144
|
+
if (/^(https?:|mailto:)/i.test(href.trim())) element.setAttribute("href", href);
|
|
145
|
+
element.setAttribute("target", "_blank");
|
|
146
|
+
element.setAttribute("rel", "noopener noreferrer");
|
|
147
|
+
}
|
|
148
|
+
if (source.localName === "img") {
|
|
149
|
+
const image = embeddedPreviewImage(source.getAttribute("src") ?? void 0);
|
|
150
|
+
if (image) element.setAttribute("src", image);
|
|
151
|
+
}
|
|
152
|
+
for (const child of source.childNodes) copy(child, element);
|
|
153
|
+
parent.appendChild(element);
|
|
154
|
+
}
|
|
155
|
+
for (const child of template.content.childNodes) copy(child, target);
|
|
156
|
+
return {
|
|
157
|
+
document: `<!doctype html><html><head><meta charset="utf-8"><meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; form-action 'none'; base-uri 'none'"><meta name="referrer" content="no-referrer"><style>body{margin:0;padding:16px 20px;color:#202124;background:#fff;font:14px/1.6 Arial,sans-serif;overflow-wrap:anywhere}a{color:#1155cc}img{max-width:100%;height:auto}table{max-width:100%}pre{white-space:pre-wrap}</style></head><body>${target.innerHTML}</body></html>`,
|
|
158
|
+
text: target.textContent ?? ""
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
function EmailPreview({ preview, account }) {
|
|
162
|
+
const [html, setHtml] = useState2(null);
|
|
163
|
+
useEffect(() => {
|
|
164
|
+
if (preview.html && preview.body) setHtml({ source: preview.body, ...emailDocument(preview.body) });
|
|
165
|
+
else setHtml(null);
|
|
166
|
+
}, [preview.body, preview.html]);
|
|
167
|
+
const sender = preview.from ?? account ?? "Sender unavailable";
|
|
168
|
+
const mailbox = /^(.*?)\s*<([^>]+)>$/.exec(sender);
|
|
169
|
+
const name = preview.fromName ?? mailbox?.[1]?.replace(/^"|"$/g, "") ?? sender;
|
|
170
|
+
const address = mailbox?.[2] ?? sender;
|
|
171
|
+
const currentHtml = html?.source === preview.body ? html : null;
|
|
172
|
+
const snippet = preview.previewText ?? (preview.html ? currentHtml?.text : preview.body)?.replace(/\s+/g, " ").trim();
|
|
173
|
+
return /* @__PURE__ */ jsxs2("div", { "data-hub-email-preview": true, className: "overflow-hidden rounded-lg border border-border bg-white font-[Arial,sans-serif] text-[#202124] [color-scheme:light]", children: [
|
|
174
|
+
/* @__PURE__ */ jsxs2("div", { className: "flex min-w-0 items-baseline gap-3 border-b border-[#e8eaed] bg-[#f2f6fc] px-4 py-3 text-sm", "aria-label": "Inbox preview", children: [
|
|
175
|
+
/* @__PURE__ */ jsx2("span", { className: "max-w-[30%] shrink-0 truncate font-semibold", children: name }),
|
|
176
|
+
/* @__PURE__ */ jsxs2("span", { className: "min-w-0 truncate", children: [
|
|
177
|
+
/* @__PURE__ */ jsx2("strong", { children: preview.subject ?? "(no subject)" }),
|
|
178
|
+
snippet && /* @__PURE__ */ jsxs2("span", { className: "text-[#5f6368]", children: [
|
|
179
|
+
" \u2014 ",
|
|
180
|
+
snippet
|
|
181
|
+
] })
|
|
182
|
+
] })
|
|
183
|
+
] }),
|
|
184
|
+
/* @__PURE__ */ jsxs2("div", { className: "px-4 pt-5 sm:px-5", children: [
|
|
185
|
+
/* @__PURE__ */ jsx2("h4", { className: "break-words text-[22px] font-normal leading-7", children: preview.subject ?? (preview.reply ? "Reply" : "(no subject)") }),
|
|
186
|
+
/* @__PURE__ */ jsxs2("div", { className: "mb-4 mt-5 flex items-start gap-3", children: [
|
|
187
|
+
/* @__PURE__ */ jsx2("span", { "aria-hidden": true, className: "flex size-9 shrink-0 items-center justify-center rounded-full bg-[#e8eaed] text-base text-[#5f6368]", children: name.charAt(0).toUpperCase() }),
|
|
188
|
+
/* @__PURE__ */ jsxs2("dl", { className: "min-w-0 space-y-1 text-[13px]", children: [
|
|
189
|
+
/* @__PURE__ */ jsxs2("div", { className: "break-words", children: [
|
|
190
|
+
/* @__PURE__ */ jsx2("dt", { className: "sr-only", children: "From" }),
|
|
191
|
+
/* @__PURE__ */ jsxs2("dd", { children: [
|
|
192
|
+
/* @__PURE__ */ jsx2("strong", { children: name }),
|
|
193
|
+
name !== address && /* @__PURE__ */ jsxs2("span", { className: "text-[#5f6368]", children: [
|
|
194
|
+
" <",
|
|
195
|
+
address,
|
|
196
|
+
">"
|
|
197
|
+
] })
|
|
198
|
+
] })
|
|
199
|
+
] }),
|
|
200
|
+
/* @__PURE__ */ jsxs2("div", { className: "break-words text-[#5f6368]", children: [
|
|
201
|
+
/* @__PURE__ */ jsx2("dt", { className: "inline", children: "To " }),
|
|
202
|
+
/* @__PURE__ */ jsx2("dd", { className: "inline", children: preview.to.join(", ") || "Recipient unavailable" })
|
|
203
|
+
] }),
|
|
204
|
+
preview.cc.length > 0 && /* @__PURE__ */ jsxs2("div", { className: "break-words text-[#5f6368]", children: [
|
|
205
|
+
/* @__PURE__ */ jsx2("dt", { className: "inline", children: "Cc " }),
|
|
206
|
+
/* @__PURE__ */ jsx2("dd", { className: "inline", children: preview.cc.join(", ") })
|
|
207
|
+
] })
|
|
208
|
+
] })
|
|
209
|
+
] })
|
|
210
|
+
] }),
|
|
211
|
+
preview.html ? currentHtml ? /* @__PURE__ */ jsx2("iframe", { title: "Email body", sandbox: "", referrerPolicy: "no-referrer", srcDoc: currentHtml.document, className: "h-[360px] w-full border-0 sm:h-[440px]" }) : /* @__PURE__ */ jsx2("p", { role: "status", className: "px-5 pb-5 text-sm", children: "Rendering email\u2026" }) : /* @__PURE__ */ jsx2("div", { className: "whitespace-pre-wrap break-words px-4 pb-6 text-[14px] leading-[1.6] sm:px-5", children: linkedText(preview.body ?? "") }),
|
|
212
|
+
preview.bcc.length > 0 && /* @__PURE__ */ jsxs2("p", { className: "border-t border-[#e8eaed] px-4 py-2 text-[13px] text-[#5f6368]", children: [
|
|
213
|
+
"Bcc (sender only): ",
|
|
214
|
+
preview.bcc.join(", ")
|
|
215
|
+
] })
|
|
216
|
+
] });
|
|
122
217
|
}
|
|
218
|
+
function linkedText(value) {
|
|
219
|
+
return value.split(/(https?:\/\/[^\s<>"']+)/g).map((part, index) => /^https?:\/\//i.test(part) ? /* @__PURE__ */ jsx2("a", { href: part, onClick: (event) => event.preventDefault(), title: "Link shown for review", className: "text-[#1155cc] underline", children: part }, index) : part);
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
// src/hub-approvals-react/preview.tsx
|
|
223
|
+
import { jsx as jsx3, jsxs as jsxs3 } from "react/jsx-runtime";
|
|
123
224
|
function initial(name) {
|
|
124
225
|
return (name?.trim().replace(/^@/, "").charAt(0) || "?").toUpperCase();
|
|
125
226
|
}
|
|
126
227
|
function Panel({ children, className = "" }) {
|
|
127
|
-
return /* @__PURE__ */
|
|
228
|
+
return /* @__PURE__ */ jsx3("div", { className: `rounded-lg border border-border bg-background ${className}`, children });
|
|
128
229
|
}
|
|
129
230
|
function PullRequestPreview({ preview }) {
|
|
130
|
-
return /* @__PURE__ */
|
|
131
|
-
/* @__PURE__ */
|
|
132
|
-
/* @__PURE__ */
|
|
133
|
-
/* @__PURE__ */
|
|
134
|
-
preview.repository && /* @__PURE__ */
|
|
135
|
-
preview.head && preview.base && /* @__PURE__ */
|
|
136
|
-
/* @__PURE__ */
|
|
137
|
-
/* @__PURE__ */
|
|
138
|
-
/* @__PURE__ */
|
|
231
|
+
return /* @__PURE__ */ jsxs3("div", { className: "space-y-3", children: [
|
|
232
|
+
/* @__PURE__ */ jsxs3(Panel, { className: "px-3 py-3", children: [
|
|
233
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center gap-2 text-sm text-muted-foreground", children: [
|
|
234
|
+
/* @__PURE__ */ jsx3(GitPullRequest, { "aria-hidden": true, className: "size-4 shrink-0" }),
|
|
235
|
+
preview.repository && /* @__PURE__ */ jsx3("span", { className: "font-medium text-foreground", children: preview.repository }),
|
|
236
|
+
preview.head && preview.base && /* @__PURE__ */ jsxs3("span", { className: "flex min-w-0 flex-wrap items-center gap-1.5", children: [
|
|
237
|
+
/* @__PURE__ */ jsx3(Chip, { mono: true, children: preview.head }),
|
|
238
|
+
/* @__PURE__ */ jsx3(ArrowRight, { "aria-label": "into", className: "size-4 shrink-0" }),
|
|
239
|
+
/* @__PURE__ */ jsx3(Chip, { mono: true, children: preview.base })
|
|
139
240
|
] }),
|
|
140
|
-
preview.draft && /* @__PURE__ */
|
|
141
|
-
] }),
|
|
142
|
-
preview.title && /* @__PURE__ */ jsx2("p", { className: "mt-2 text-base font-semibold leading-6 text-foreground", children: preview.title }),
|
|
143
|
-
preview.body && /* @__PURE__ */ jsx2("p", { className: "mt-1 line-clamp-3 whitespace-pre-line text-sm leading-6 text-muted-foreground sm:line-clamp-4", children: preview.body })
|
|
144
|
-
] }),
|
|
145
|
-
preview.files.length > 0 && /* @__PURE__ */ jsx2(ApprovalDiffSummary, { files: preview.files })
|
|
146
|
-
] });
|
|
147
|
-
}
|
|
148
|
-
function EmailPreview({ preview, account }) {
|
|
149
|
-
const rows = [
|
|
150
|
-
...account ? [["From", account]] : [],
|
|
151
|
-
...preview.to.length ? [["To", preview.to.join(", ")]] : [],
|
|
152
|
-
...preview.cc.length ? [["Cc", preview.cc.join(", ")]] : [],
|
|
153
|
-
...preview.bcc.length ? [["Bcc", preview.bcc.join(", ")]] : []
|
|
154
|
-
];
|
|
155
|
-
const body = preview.body ? plainText(preview.body, preview.html) : "";
|
|
156
|
-
return /* @__PURE__ */ jsxs2(Panel, { className: "overflow-hidden", children: [
|
|
157
|
-
/* @__PURE__ */ jsxs2("dl", { className: "grid grid-cols-[auto_minmax(0,1fr)] gap-x-3 gap-y-1 border-b border-border px-3 py-2.5 text-sm", children: [
|
|
158
|
-
rows.map(([label, value]) => /* @__PURE__ */ jsxs2("div", { className: "contents", children: [
|
|
159
|
-
/* @__PURE__ */ jsx2("dt", { className: "text-muted-foreground", children: label }),
|
|
160
|
-
/* @__PURE__ */ jsx2("dd", { className: "break-words text-foreground", children: value })
|
|
161
|
-
] }, label)),
|
|
162
|
-
preview.subject && /* @__PURE__ */ jsxs2("div", { className: "contents", children: [
|
|
163
|
-
/* @__PURE__ */ jsx2("dt", { className: "text-muted-foreground", children: "Subject" }),
|
|
164
|
-
/* @__PURE__ */ jsx2("dd", { className: "break-words font-semibold text-foreground", children: preview.subject })
|
|
241
|
+
preview.draft && /* @__PURE__ */ jsx3("span", { className: "rounded-md border border-border px-1.5 py-0.5 text-sm text-muted-foreground", children: "Draft" })
|
|
165
242
|
] }),
|
|
166
|
-
preview.
|
|
167
|
-
|
|
168
|
-
/* @__PURE__ */ jsx2("dd", { className: "text-foreground", children: "In the existing conversation" })
|
|
169
|
-
] })
|
|
243
|
+
preview.title && /* @__PURE__ */ jsx3("p", { className: "mt-2 text-base font-semibold leading-6 text-foreground", children: preview.title }),
|
|
244
|
+
preview.body && /* @__PURE__ */ jsx3("p", { className: "mt-1 line-clamp-3 whitespace-pre-line text-sm leading-6 text-muted-foreground sm:line-clamp-4", children: preview.body })
|
|
170
245
|
] }),
|
|
171
|
-
|
|
246
|
+
preview.files.length > 0 && /* @__PURE__ */ jsx3(ApprovalDiffSummary, { files: preview.files })
|
|
172
247
|
] });
|
|
173
248
|
}
|
|
174
249
|
function PostPreview({ preview, account }) {
|
|
175
250
|
if (preview.channel === "slack") {
|
|
176
|
-
return /* @__PURE__ */
|
|
177
|
-
/* @__PURE__ */
|
|
178
|
-
/* @__PURE__ */
|
|
179
|
-
/* @__PURE__ */
|
|
180
|
-
/* @__PURE__ */
|
|
181
|
-
/* @__PURE__ */
|
|
182
|
-
/* @__PURE__ */
|
|
251
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "px-3 py-3", children: [
|
|
252
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-semibold text-foreground", children: preview.where ?? "Slack" }),
|
|
253
|
+
/* @__PURE__ */ jsxs3("div", { className: "mt-2 flex gap-3", children: [
|
|
254
|
+
/* @__PURE__ */ jsx3("span", { className: "flex size-9 shrink-0 items-center justify-center rounded-md bg-muted text-sm font-semibold text-foreground", children: initial(account) }),
|
|
255
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0", children: [
|
|
256
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-semibold text-foreground", children: account ?? "Your account" }),
|
|
257
|
+
/* @__PURE__ */ jsx3("p", { className: "whitespace-pre-wrap break-words text-sm leading-6 text-foreground", children: linkedText(preview.text) })
|
|
183
258
|
] })
|
|
184
259
|
] })
|
|
185
260
|
] });
|
|
186
261
|
}
|
|
187
262
|
const x = preview.channel === "x";
|
|
188
263
|
const length = [...preview.text].length;
|
|
189
|
-
return /* @__PURE__ */
|
|
190
|
-
/* @__PURE__ */
|
|
191
|
-
/* @__PURE__ */
|
|
192
|
-
/* @__PURE__ */
|
|
193
|
-
/* @__PURE__ */
|
|
194
|
-
/* @__PURE__ */
|
|
195
|
-
/* @__PURE__ */
|
|
264
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "px-4 py-3", children: [
|
|
265
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex gap-3", children: [
|
|
266
|
+
/* @__PURE__ */ jsx3("span", { className: `flex size-10 shrink-0 items-center justify-center rounded-full text-base font-semibold ${x ? "bg-foreground text-background" : "bg-[#0a66c2] text-white"}`, children: initial(account) }),
|
|
267
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
|
|
268
|
+
/* @__PURE__ */ jsxs3("p", { className: "flex flex-wrap items-baseline gap-x-1.5 text-sm", children: [
|
|
269
|
+
/* @__PURE__ */ jsx3("span", { className: "font-semibold text-foreground", children: account ?? "Your account" }),
|
|
270
|
+
/* @__PURE__ */ jsx3("span", { className: "text-muted-foreground", children: x ? "\xB7 now" : "\xB7 Post \xB7 Anyone" })
|
|
196
271
|
] }),
|
|
197
|
-
/* @__PURE__ */
|
|
198
|
-
preview.
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
preview.link.
|
|
272
|
+
/* @__PURE__ */ jsx3("p", { className: `mt-1 whitespace-pre-wrap break-words text-foreground ${x ? "text-base leading-6" : "text-sm leading-6"}`, children: linkedText(preview.text) }),
|
|
273
|
+
preview.images && preview.images.length > 0 && /* @__PURE__ */ jsx3("div", { className: "mt-3 grid grid-cols-2 gap-0.5 overflow-hidden rounded-xl border border-border", children: preview.images.map((image, index) => /* @__PURE__ */ jsx3("div", { className: `${preview.images.length === 1 ? "col-span-2 aspect-[16/9]" : "aspect-square"} overflow-hidden bg-muted`, children: embeddedPreviewImage(image.url) ? /* @__PURE__ */ jsx3("img", { src: image.url, alt: image.alt ?? `Post image ${index + 1}`, className: "size-full object-cover" }) : /* @__PURE__ */ jsx3("p", { className: "p-3 text-sm text-muted-foreground", children: "Image not embedded in this preview" }) }, index)) }),
|
|
274
|
+
preview.link && /* @__PURE__ */ jsx3("div", { className: "mt-3 overflow-hidden rounded-lg border border-border", children: /* @__PURE__ */ jsxs3("div", { className: "px-3 py-2", children: [
|
|
275
|
+
/* @__PURE__ */ jsx3("p", { className: "truncate text-sm text-muted-foreground", children: preview.link.url.replace(/^https?:\/\//, "") }),
|
|
276
|
+
preview.link.title && /* @__PURE__ */ jsx3("p", { className: "truncate text-sm font-semibold text-foreground", children: preview.link.title }),
|
|
277
|
+
preview.link.description && /* @__PURE__ */ jsx3("p", { className: "line-clamp-2 text-sm text-muted-foreground", children: preview.link.description })
|
|
202
278
|
] }) })
|
|
203
279
|
] })
|
|
204
280
|
] }),
|
|
205
|
-
|
|
281
|
+
/* @__PURE__ */ jsxs3("p", { className: "mt-2 text-right text-sm tabular-nums text-muted-foreground", children: [
|
|
206
282
|
length,
|
|
207
|
-
"
|
|
283
|
+
" characters"
|
|
208
284
|
] })
|
|
209
285
|
] });
|
|
210
286
|
}
|
|
211
287
|
function PaymentPreview({ preview }) {
|
|
212
|
-
return /* @__PURE__ */
|
|
213
|
-
/* @__PURE__ */
|
|
214
|
-
preview.amount !== void 0 && /* @__PURE__ */
|
|
215
|
-
/* @__PURE__ */
|
|
216
|
-
preview.customer && /* @__PURE__ */
|
|
288
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "px-4 py-3", children: [
|
|
289
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm text-muted-foreground", children: preview.label.charAt(0).toUpperCase() + preview.label.slice(1) }),
|
|
290
|
+
preview.amount !== void 0 && /* @__PURE__ */ jsx3("p", { className: "mt-0.5 text-2xl font-semibold tabular-nums text-foreground", children: formatMinorAmount(preview.amount, preview.currency) }),
|
|
291
|
+
/* @__PURE__ */ jsxs3("div", { className: "mt-2 space-y-1 text-sm", children: [
|
|
292
|
+
preview.customer && /* @__PURE__ */ jsxs3("p", { className: "text-muted-foreground", children: [
|
|
217
293
|
"Customer ",
|
|
218
|
-
/* @__PURE__ */
|
|
294
|
+
/* @__PURE__ */ jsx3("span", { className: `text-foreground ${preview.customer.startsWith("cus_") ? "font-mono" : ""}`, children: preview.customer })
|
|
219
295
|
] }),
|
|
220
|
-
preview.description && /* @__PURE__ */
|
|
296
|
+
preview.description && /* @__PURE__ */ jsx3("p", { className: "text-foreground", children: preview.description })
|
|
221
297
|
] })
|
|
222
298
|
] });
|
|
223
299
|
}
|
|
224
300
|
function SpeechPreview({ preview }) {
|
|
225
|
-
return /* @__PURE__ */
|
|
226
|
-
/* @__PURE__ */
|
|
227
|
-
(preview.voice || preview.seconds) && /* @__PURE__ */
|
|
228
|
-
preview.voice && /* @__PURE__ */
|
|
301
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "px-4 py-3", children: [
|
|
302
|
+
/* @__PURE__ */ jsx3("blockquote", { className: "border-l-2 border-[var(--accent-text)] pl-3 text-base leading-7 text-foreground", children: preview.text }),
|
|
303
|
+
(preview.voice || preview.seconds) && /* @__PURE__ */ jsxs3("div", { className: "mt-3 flex flex-wrap gap-2", children: [
|
|
304
|
+
preview.voice && /* @__PURE__ */ jsxs3(Chip, { children: [
|
|
229
305
|
"Voice: ",
|
|
230
306
|
preview.voice
|
|
231
307
|
] }),
|
|
232
|
-
preview.seconds && /* @__PURE__ */
|
|
308
|
+
preview.seconds && /* @__PURE__ */ jsxs3(Chip, { children: [
|
|
233
309
|
"About ",
|
|
234
310
|
preview.seconds,
|
|
235
311
|
" s"
|
|
@@ -238,97 +314,245 @@ function SpeechPreview({ preview }) {
|
|
|
238
314
|
] });
|
|
239
315
|
}
|
|
240
316
|
function CallPreview({ preview }) {
|
|
241
|
-
return /* @__PURE__ */
|
|
242
|
-
/* @__PURE__ */
|
|
243
|
-
/* @__PURE__ */
|
|
244
|
-
/* @__PURE__ */
|
|
245
|
-
preview.from && /* @__PURE__ */
|
|
317
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "flex gap-3 px-4 py-3", children: [
|
|
318
|
+
/* @__PURE__ */ jsx3("span", { className: "flex size-10 shrink-0 items-center justify-center rounded-full bg-muted", children: /* @__PURE__ */ jsx3(Phone, { "aria-hidden": true, className: "size-5 text-foreground" }) }),
|
|
319
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0 space-y-1 text-sm", children: [
|
|
320
|
+
/* @__PURE__ */ jsx3("p", { className: "text-base font-semibold tabular-nums text-foreground", children: preview.to ?? "Unknown number" }),
|
|
321
|
+
preview.from && /* @__PURE__ */ jsxs3("p", { className: "text-muted-foreground", children: [
|
|
246
322
|
"From ",
|
|
247
|
-
/* @__PURE__ */
|
|
323
|
+
/* @__PURE__ */ jsx3("span", { className: "tabular-nums text-foreground", children: preview.from })
|
|
248
324
|
] }),
|
|
249
|
-
preview.purpose && /* @__PURE__ */
|
|
325
|
+
preview.purpose && /* @__PURE__ */ jsx3("p", { className: "leading-6 text-foreground", children: preview.purpose })
|
|
250
326
|
] })
|
|
251
327
|
] });
|
|
252
328
|
}
|
|
253
329
|
function EventPreview({ preview }) {
|
|
254
330
|
const start = preview.start ? new Date(preview.start) : null;
|
|
255
331
|
const valid = start && !Number.isNaN(start.getTime());
|
|
256
|
-
return /* @__PURE__ */
|
|
257
|
-
/* @__PURE__ */
|
|
258
|
-
/* @__PURE__ */
|
|
259
|
-
/* @__PURE__ */
|
|
332
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "flex gap-4 px-4 py-3", children: [
|
|
333
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex w-14 shrink-0 flex-col items-center overflow-hidden rounded-lg border border-border text-center", children: [
|
|
334
|
+
/* @__PURE__ */ jsx3("span", { className: "w-full bg-[var(--surface-danger-bg)] py-0.5 text-sm font-semibold uppercase text-[var(--surface-danger-text)]", children: valid ? start.toLocaleDateString(void 0, { month: "short" }) : /* @__PURE__ */ jsx3(CalendarDays, { "aria-hidden": true, className: "mx-auto size-4" }) }),
|
|
335
|
+
/* @__PURE__ */ jsx3("span", { className: "py-1 text-xl font-semibold tabular-nums text-foreground", children: valid ? start.getDate() : "\u2013" })
|
|
260
336
|
] }),
|
|
261
|
-
/* @__PURE__ */
|
|
262
|
-
/* @__PURE__ */
|
|
263
|
-
preview.start && /* @__PURE__ */
|
|
264
|
-
preview.location && /* @__PURE__ */
|
|
265
|
-
/* @__PURE__ */
|
|
337
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0 space-y-1 text-sm", children: [
|
|
338
|
+
/* @__PURE__ */ jsx3("p", { className: "text-base font-semibold text-foreground", children: preview.title ?? "Untitled event" }),
|
|
339
|
+
preview.start && /* @__PURE__ */ jsx3("p", { className: "text-foreground", children: formatWhen(preview.start, preview.end) }),
|
|
340
|
+
preview.location && /* @__PURE__ */ jsxs3("p", { className: "flex items-center gap-1.5 text-muted-foreground", children: [
|
|
341
|
+
/* @__PURE__ */ jsx3(MapPin, { "aria-hidden": true, className: "size-4 shrink-0" }),
|
|
266
342
|
preview.location
|
|
267
343
|
] }),
|
|
268
|
-
preview.attendees.length > 0 && /* @__PURE__ */
|
|
269
|
-
/* @__PURE__ */
|
|
270
|
-
/* @__PURE__ */
|
|
344
|
+
preview.attendees.length > 0 && /* @__PURE__ */ jsxs3("p", { className: "flex items-start gap-1.5 text-muted-foreground", children: [
|
|
345
|
+
/* @__PURE__ */ jsx3(Users, { "aria-hidden": true, className: "mt-0.5 size-4 shrink-0" }),
|
|
346
|
+
/* @__PURE__ */ jsx3("span", { className: "break-words", children: preview.attendees.join(", ") })
|
|
271
347
|
] }),
|
|
272
|
-
preview.description && /* @__PURE__ */
|
|
348
|
+
preview.description && /* @__PURE__ */ jsx3("p", { className: "line-clamp-3 leading-6 text-foreground", children: preview.description })
|
|
273
349
|
] })
|
|
274
350
|
] });
|
|
275
351
|
}
|
|
276
352
|
function HubActionPreviewView({ preview, account }) {
|
|
277
353
|
switch (preview.kind) {
|
|
278
354
|
case "pull-request":
|
|
279
|
-
return /* @__PURE__ */
|
|
355
|
+
return /* @__PURE__ */ jsx3(PullRequestPreview, { preview });
|
|
280
356
|
case "files":
|
|
281
|
-
return preview.files.length > 0 ? /* @__PURE__ */
|
|
357
|
+
return preview.files.length > 0 ? /* @__PURE__ */ jsx3(ApprovalDiffSummary, { files: preview.files }) : null;
|
|
282
358
|
case "commit":
|
|
283
|
-
return /* @__PURE__ */
|
|
284
|
-
/* @__PURE__ */
|
|
285
|
-
/* @__PURE__ */
|
|
359
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "px-3 py-3", children: [
|
|
360
|
+
/* @__PURE__ */ jsxs3("p", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
361
|
+
/* @__PURE__ */ jsx3(GitCommitHorizontal, { "aria-hidden": true, className: "size-4 shrink-0" }),
|
|
286
362
|
preview.repository ?? "Commit"
|
|
287
363
|
] }),
|
|
288
|
-
preview.message && /* @__PURE__ */
|
|
289
|
-
/* @__PURE__ */
|
|
364
|
+
preview.message && /* @__PURE__ */ jsx3("p", { className: "mt-2 whitespace-pre-line text-sm leading-6 text-foreground", children: preview.message }),
|
|
365
|
+
/* @__PURE__ */ jsx3("div", { className: "mt-2", children: /* @__PURE__ */ jsx3(HubFieldList, { fields: [
|
|
290
366
|
...preview.tree ? [{ label: "Tree", value: preview.tree.slice(0, 7), mono: true }] : [],
|
|
291
367
|
...preview.parents.map((parent) => ({ label: "Parent", value: parent.slice(0, 7), mono: true }))
|
|
292
368
|
] }) })
|
|
293
369
|
] });
|
|
294
370
|
case "branch":
|
|
295
|
-
return /* @__PURE__ */
|
|
296
|
-
/* @__PURE__ */
|
|
297
|
-
preview.branch && /* @__PURE__ */
|
|
298
|
-
preview.sha && /* @__PURE__ */
|
|
371
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "flex flex-wrap items-center gap-2 px-3 py-3 text-sm", children: [
|
|
372
|
+
/* @__PURE__ */ jsx3(GitBranch, { "aria-hidden": true, className: "size-4 shrink-0 text-muted-foreground" }),
|
|
373
|
+
preview.branch && /* @__PURE__ */ jsx3(Chip, { mono: true, children: preview.branch }),
|
|
374
|
+
preview.sha && /* @__PURE__ */ jsxs3("span", { className: "text-muted-foreground", children: [
|
|
299
375
|
"at ",
|
|
300
|
-
/* @__PURE__ */
|
|
376
|
+
/* @__PURE__ */ jsx3("span", { className: "font-mono text-foreground", children: preview.sha.slice(0, 7) })
|
|
301
377
|
] })
|
|
302
378
|
] });
|
|
303
379
|
case "issue":
|
|
304
|
-
return /* @__PURE__ */
|
|
305
|
-
preview.verdict && /* @__PURE__ */
|
|
306
|
-
preview.title && /* @__PURE__ */
|
|
307
|
-
preview.body && /* @__PURE__ */
|
|
380
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "px-3 py-3", children: [
|
|
381
|
+
preview.verdict && /* @__PURE__ */ jsx3("p", { className: "text-sm font-medium capitalize text-foreground", children: preview.verdict }),
|
|
382
|
+
preview.title && /* @__PURE__ */ jsx3("p", { className: "text-base font-semibold leading-6 text-foreground", children: preview.title }),
|
|
383
|
+
preview.body && /* @__PURE__ */ jsx3("p", { className: "mt-1 line-clamp-6 whitespace-pre-line text-sm leading-6 text-foreground", children: preview.body })
|
|
308
384
|
] });
|
|
309
385
|
case "email":
|
|
310
|
-
return /* @__PURE__ */
|
|
386
|
+
return /* @__PURE__ */ jsx3(EmailPreview, { preview, account });
|
|
311
387
|
case "post":
|
|
312
|
-
return /* @__PURE__ */
|
|
388
|
+
return /* @__PURE__ */ jsx3(PostPreview, { preview, account });
|
|
389
|
+
case "ad":
|
|
390
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "overflow-hidden", children: [
|
|
391
|
+
/* @__PURE__ */ jsxs3("div", { className: "space-y-1 px-4 py-3", children: [
|
|
392
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-semibold text-foreground", children: preview.advertiser ?? account ?? "Advertiser unavailable" }),
|
|
393
|
+
/* @__PURE__ */ jsxs3("p", { className: "text-sm text-muted-foreground", children: [
|
|
394
|
+
"Sponsored \xB7 ",
|
|
395
|
+
preview.placement
|
|
396
|
+
] }),
|
|
397
|
+
preview.text && /* @__PURE__ */ jsx3("p", { className: "whitespace-pre-wrap break-words text-sm leading-6 text-foreground", children: preview.text })
|
|
398
|
+
] }),
|
|
399
|
+
preview.image && (embeddedPreviewImage(preview.image) ? /* @__PURE__ */ jsx3("img", { src: preview.image, alt: preview.headline ?? "Ad creative", className: "aspect-[1.91/1] w-full object-cover" }) : /* @__PURE__ */ jsx3("p", { className: "bg-muted p-4 text-sm text-muted-foreground", children: "Creative image not embedded in this preview" })),
|
|
400
|
+
/* @__PURE__ */ jsxs3("div", { className: "flex flex-wrap items-center gap-3 bg-muted/40 px-4 py-3", children: [
|
|
401
|
+
/* @__PURE__ */ jsxs3("div", { className: "min-w-0 flex-1", children: [
|
|
402
|
+
preview.destination && /* @__PURE__ */ jsx3("p", { className: "truncate text-sm text-muted-foreground", children: preview.destination }),
|
|
403
|
+
preview.headline && /* @__PURE__ */ jsx3("p", { className: "break-words font-semibold text-foreground", children: preview.headline })
|
|
404
|
+
] }),
|
|
405
|
+
preview.callToAction && /* @__PURE__ */ jsx3("span", { className: "rounded-md border border-border px-3 py-2 text-sm font-medium text-foreground", children: preview.callToAction })
|
|
406
|
+
] })
|
|
407
|
+
] });
|
|
408
|
+
case "page":
|
|
409
|
+
return /* @__PURE__ */ jsxs3(Panel, { className: "overflow-hidden", children: [
|
|
410
|
+
/* @__PURE__ */ jsxs3("div", { className: "border-b border-border px-4 py-2", children: [
|
|
411
|
+
/* @__PURE__ */ jsx3("p", { className: "text-sm font-medium text-foreground", children: preview.title ?? "Page preview" }),
|
|
412
|
+
preview.url && /* @__PURE__ */ jsx3("p", { className: "truncate text-sm text-muted-foreground", children: preview.url })
|
|
413
|
+
] }),
|
|
414
|
+
embeddedPreviewImage(preview.screenshot) ? /* @__PURE__ */ jsx3("img", { src: preview.screenshot, alt: preview.title ?? "Page screenshot", className: "h-auto w-full" }) : /* @__PURE__ */ jsx3("p", { className: "p-4 text-sm text-muted-foreground", children: "A captured screenshot is needed to preview this page." })
|
|
415
|
+
] });
|
|
313
416
|
case "payment":
|
|
314
|
-
return /* @__PURE__ */
|
|
417
|
+
return /* @__PURE__ */ jsx3(PaymentPreview, { preview });
|
|
315
418
|
case "speech":
|
|
316
|
-
return /* @__PURE__ */
|
|
419
|
+
return /* @__PURE__ */ jsx3(SpeechPreview, { preview });
|
|
317
420
|
case "call":
|
|
318
|
-
return /* @__PURE__ */
|
|
421
|
+
return /* @__PURE__ */ jsx3(CallPreview, { preview });
|
|
319
422
|
case "event":
|
|
320
|
-
return /* @__PURE__ */
|
|
423
|
+
return /* @__PURE__ */ jsx3(EventPreview, { preview });
|
|
321
424
|
case "fields":
|
|
322
|
-
return preview.fields.length > 0 ? /* @__PURE__ */
|
|
425
|
+
return preview.fields.length > 0 ? /* @__PURE__ */ jsx3(Panel, { className: "px-3 py-3", children: /* @__PURE__ */ jsx3(HubFieldList, { fields: preview.fields }) }) : null;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
// src/hub-approvals-react/feedback.tsx
|
|
430
|
+
import { useEffect as useEffect2, useId, useState as useState3 } from "react";
|
|
431
|
+
import { Button as Button2, Input, Label, Textarea } from "@tangle-network/ui/primitives";
|
|
432
|
+
import { jsx as jsx4, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
433
|
+
function HubPreviewFeedback({ item, onFeedback, drafts }) {
|
|
434
|
+
const id = useId();
|
|
435
|
+
const saved = item.feedback;
|
|
436
|
+
const original = item.input && typeof item.input === "object" && !Array.isArray(item.input) ? item.input : {};
|
|
437
|
+
const prior = saved?.editedInput && typeof saved.editedInput === "object" && !Array.isArray(saved.editedInput) ? saved.editedInput : original;
|
|
438
|
+
const kind = presentHubAction(item).preview.kind;
|
|
439
|
+
const field = kind === "email" ? typeof original.html === "string" ? "html" : typeof original.body === "string" ? "body" : "text" : typeof original.commentary === "string" ? "commentary" : "text";
|
|
440
|
+
const draft = drafts?.get(item.id);
|
|
441
|
+
const [score, setScore] = useState3(draft?.score ?? (saved ? String(saved.score) : ""));
|
|
442
|
+
const [comment, setComment] = useState3(draft?.comment ?? saved?.comment ?? "");
|
|
443
|
+
const [editing, setEditing] = useState3(draft?.editing ?? false);
|
|
444
|
+
const [edited, setEdited] = useState3(draft?.edited ?? saved?.editedInput !== void 0);
|
|
445
|
+
const [subject, setSubject] = useState3(draft?.subject ?? String(prior.subject ?? ""));
|
|
446
|
+
const [body, setBody] = useState3(draft?.body ?? String(prior[field] ?? ""));
|
|
447
|
+
const [payload, setPayload] = useState3(draft?.payload ?? JSON.stringify(prior, null, 2));
|
|
448
|
+
const [busy, setBusy] = useState3(false);
|
|
449
|
+
const [status, setStatus] = useState3((draft ? draft.saved : saved) ? "Feedback saved" : "");
|
|
450
|
+
const [error, setError] = useState3("");
|
|
451
|
+
useEffect2(() => {
|
|
452
|
+
drafts?.set(item.id, { score, comment, editing, edited, subject, body, payload, saved: status === "Feedback saved" });
|
|
453
|
+
}, [drafts, item.id, score, comment, editing, edited, subject, body, payload, status]);
|
|
454
|
+
async function save() {
|
|
455
|
+
if (busy) return;
|
|
456
|
+
if (score.trim() === "" || !Number.isInteger(Number(score)) || Number(score) < 0 || Number(score) > 100) {
|
|
457
|
+
setError("Enter a score from 0 to 100.");
|
|
458
|
+
return;
|
|
459
|
+
}
|
|
460
|
+
setBusy(true);
|
|
461
|
+
setError("");
|
|
462
|
+
setStatus("");
|
|
463
|
+
try {
|
|
464
|
+
const editedInput = edited ? kind === "email" ? { ...original, subject, [field]: body } : kind === "post" ? { ...original, [field]: body } : JSON.parse(payload) : saved?.editedInput;
|
|
465
|
+
await onFeedback(item, {
|
|
466
|
+
score: Number(score),
|
|
467
|
+
comment,
|
|
468
|
+
...editedInput !== void 0 && JSON.stringify(editedInput) !== JSON.stringify(item.input) ? { editedInput } : {}
|
|
469
|
+
});
|
|
470
|
+
setStatus("Feedback saved");
|
|
471
|
+
} catch (cause) {
|
|
472
|
+
setError(cause instanceof Error ? cause.message : "Feedback could not be saved. Your edits are kept here.");
|
|
473
|
+
} finally {
|
|
474
|
+
setBusy(false);
|
|
475
|
+
}
|
|
323
476
|
}
|
|
477
|
+
return /* @__PURE__ */ jsxs4("form", { "aria-label": "Preview feedback", className: "space-y-3 border-t border-border pt-3", onSubmit: (event) => {
|
|
478
|
+
event.preventDefault();
|
|
479
|
+
void save();
|
|
480
|
+
}, children: [
|
|
481
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-end gap-3", children: [
|
|
482
|
+
/* @__PURE__ */ jsxs4("div", { className: "w-36 space-y-1", children: [
|
|
483
|
+
/* @__PURE__ */ jsx4(Label, { htmlFor: `${id}-score`, children: "Score (0\u2013100)" }),
|
|
484
|
+
/* @__PURE__ */ jsx4(
|
|
485
|
+
Input,
|
|
486
|
+
{
|
|
487
|
+
id: `${id}-score`,
|
|
488
|
+
type: "number",
|
|
489
|
+
inputMode: "numeric",
|
|
490
|
+
min: 0,
|
|
491
|
+
max: 100,
|
|
492
|
+
step: 1,
|
|
493
|
+
required: true,
|
|
494
|
+
value: score,
|
|
495
|
+
placeholder: "Unscored",
|
|
496
|
+
disabled: busy,
|
|
497
|
+
onChange: (event) => {
|
|
498
|
+
setScore(event.target.value);
|
|
499
|
+
setStatus("");
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
)
|
|
503
|
+
] }),
|
|
504
|
+
/* @__PURE__ */ jsx4(Button2, { type: "button", variant: "outline", "aria-expanded": editing, disabled: busy, onClick: () => {
|
|
505
|
+
setEditing((value) => !value);
|
|
506
|
+
setStatus("");
|
|
507
|
+
}, children: "Edit to teach" })
|
|
508
|
+
] }),
|
|
509
|
+
/* @__PURE__ */ jsxs4("div", { className: "space-y-1", children: [
|
|
510
|
+
/* @__PURE__ */ jsx4(Label, { htmlFor: `${id}-comment`, children: "Comment" }),
|
|
511
|
+
/* @__PURE__ */ jsx4(Textarea, { id: `${id}-comment`, value: comment, rows: 2, disabled: busy, onChange: (event) => {
|
|
512
|
+
setComment(event.target.value);
|
|
513
|
+
setStatus("");
|
|
514
|
+
} })
|
|
515
|
+
] }),
|
|
516
|
+
editing && /* @__PURE__ */ jsxs4("div", { className: "space-y-3", children: [
|
|
517
|
+
/* @__PURE__ */ jsx4("p", { className: "text-sm text-muted-foreground", children: "Your edit is saved as a teaching example. Live approval applies to the original held payload." }),
|
|
518
|
+
kind === "email" && /* @__PURE__ */ jsxs4("div", { className: "space-y-1", children: [
|
|
519
|
+
/* @__PURE__ */ jsx4(Label, { htmlFor: `${id}-subject`, children: "Subject" }),
|
|
520
|
+
/* @__PURE__ */ jsx4(Input, { id: `${id}-subject`, value: subject, disabled: busy, onChange: (event) => {
|
|
521
|
+
setSubject(event.target.value);
|
|
522
|
+
setEdited(true);
|
|
523
|
+
setStatus("");
|
|
524
|
+
} })
|
|
525
|
+
] }),
|
|
526
|
+
kind === "email" || kind === "post" ? /* @__PURE__ */ jsxs4("div", { className: "space-y-1", children: [
|
|
527
|
+
/* @__PURE__ */ jsx4(Label, { htmlFor: `${id}-body`, children: kind === "email" ? "Body" : "Post text" }),
|
|
528
|
+
/* @__PURE__ */ jsx4(Textarea, { id: `${id}-body`, value: body, rows: 6, disabled: busy, onChange: (event) => {
|
|
529
|
+
setBody(event.target.value);
|
|
530
|
+
setEdited(true);
|
|
531
|
+
setStatus("");
|
|
532
|
+
} })
|
|
533
|
+
] }) : /* @__PURE__ */ jsxs4("div", { className: "space-y-1", children: [
|
|
534
|
+
/* @__PURE__ */ jsx4(Label, { htmlFor: `${id}-payload`, children: "Payload" }),
|
|
535
|
+
/* @__PURE__ */ jsx4(Textarea, { id: `${id}-payload`, value: payload, rows: 6, disabled: busy, onChange: (event) => {
|
|
536
|
+
setPayload(event.target.value);
|
|
537
|
+
setEdited(true);
|
|
538
|
+
setStatus("");
|
|
539
|
+
} })
|
|
540
|
+
] })
|
|
541
|
+
] }),
|
|
542
|
+
error && /* @__PURE__ */ jsx4("p", { role: "alert", className: "text-sm text-[var(--surface-danger-text)]", children: error }),
|
|
543
|
+
/* @__PURE__ */ jsxs4("div", { className: "flex flex-wrap items-center gap-3", children: [
|
|
544
|
+
/* @__PURE__ */ jsx4(Button2, { type: "submit", variant: "outline", disabled: busy, children: busy ? "Saving feedback\u2026" : "Save feedback" }),
|
|
545
|
+
/* @__PURE__ */ jsx4("p", { role: "status", className: "text-sm text-muted-foreground", children: status })
|
|
546
|
+
] })
|
|
547
|
+
] });
|
|
324
548
|
}
|
|
325
549
|
|
|
326
550
|
// src/hub-approvals-react/dock.tsx
|
|
327
|
-
import { Fragment, jsx as
|
|
551
|
+
import { Fragment, jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
328
552
|
var DONE_VISIBLE_MS = 6e3;
|
|
329
553
|
function useNow(intervalMs) {
|
|
330
|
-
const [now, setNow] =
|
|
331
|
-
|
|
554
|
+
const [now, setNow] = useState4(() => Date.now());
|
|
555
|
+
useEffect3(() => {
|
|
332
556
|
const timer = setInterval(() => setNow(Date.now()), intervalMs);
|
|
333
557
|
return () => clearInterval(timer);
|
|
334
558
|
}, [intervalMs]);
|
|
@@ -337,48 +561,50 @@ function useNow(intervalMs) {
|
|
|
337
561
|
function Progress({ item }) {
|
|
338
562
|
const provider = presentHubAction(item).provider.name;
|
|
339
563
|
if (item.phase === "queued" || item.phase === "running") {
|
|
340
|
-
return /* @__PURE__ */
|
|
341
|
-
/* @__PURE__ */
|
|
564
|
+
return /* @__PURE__ */ jsxs5("p", { role: "status", className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
565
|
+
/* @__PURE__ */ jsx5(Loader2, { "aria-hidden": true, className: "size-4 animate-spin text-[var(--surface-info-text)]" }),
|
|
342
566
|
item.phase === "queued" ? "Approved. It runs when the agent\u2019s turn finishes\u2026" : `Running on ${provider}\u2026`
|
|
343
567
|
] });
|
|
344
568
|
}
|
|
345
569
|
if (item.phase === "done") {
|
|
346
570
|
const receipt = hubActionReceipt(item);
|
|
347
|
-
return /* @__PURE__ */
|
|
348
|
-
/* @__PURE__ */
|
|
349
|
-
receipt.href ? /* @__PURE__ */
|
|
350
|
-
/* @__PURE__ */
|
|
351
|
-
/* @__PURE__ */
|
|
352
|
-
] }) : /* @__PURE__ */
|
|
571
|
+
return /* @__PURE__ */ jsxs5("p", { role: "status", className: "flex min-w-0 items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
572
|
+
/* @__PURE__ */ jsx5(Check, { "aria-hidden": true, className: "size-4 shrink-0 text-[var(--surface-success-text)]" }),
|
|
573
|
+
receipt.href ? /* @__PURE__ */ jsxs5("a", { href: receipt.href, target: "_blank", rel: "noreferrer", className: "inline-flex min-w-0 items-center gap-1 hover:underline", children: [
|
|
574
|
+
/* @__PURE__ */ jsx5("span", { className: "truncate", children: receipt.title }),
|
|
575
|
+
/* @__PURE__ */ jsx5(ExternalLink, { "aria-hidden": true, className: "size-4 shrink-0 text-muted-foreground" })
|
|
576
|
+
] }) : /* @__PURE__ */ jsx5("span", { className: "truncate", children: receipt.title })
|
|
353
577
|
] });
|
|
354
578
|
}
|
|
355
579
|
if (item.phase === "unknown") {
|
|
356
|
-
return /* @__PURE__ */
|
|
357
|
-
/* @__PURE__ */
|
|
580
|
+
return /* @__PURE__ */ jsxs5("p", { role: "alert", className: "break-words text-sm text-[var(--surface-warning-text)]", children: [
|
|
581
|
+
/* @__PURE__ */ jsx5("span", { className: "font-medium", children: "May have run." }),
|
|
358
582
|
" ",
|
|
359
583
|
HUB_APPROVAL_UNKNOWN_WARNING
|
|
360
584
|
] });
|
|
361
585
|
}
|
|
362
586
|
if (item.phase === "failed") {
|
|
363
|
-
return /* @__PURE__ */
|
|
587
|
+
return /* @__PURE__ */ jsxs5("p", { role: "alert", className: "break-words text-sm text-[var(--surface-danger-text)]", children: [
|
|
364
588
|
hubActionReceipt(item).title,
|
|
365
589
|
item.error ? `: ${item.error}` : "."
|
|
366
590
|
] });
|
|
367
591
|
}
|
|
368
592
|
return null;
|
|
369
593
|
}
|
|
370
|
-
function HubApprovalDock({ items, onDecide, permissions, onOpen, focusId, className = "" }) {
|
|
594
|
+
function HubApprovalDock({ items, onDecide, permissions, onOpen, focusId, onFeedback, className = "" }) {
|
|
371
595
|
const now = useNow(3e4);
|
|
372
596
|
const watched = useRef(/* @__PURE__ */ new Map());
|
|
373
|
-
const [settled, setSettled] =
|
|
374
|
-
const [dismissed, setDismissed] =
|
|
375
|
-
const [submitting, setSubmitting] =
|
|
376
|
-
const [error, setError] =
|
|
377
|
-
const [activeId, setActiveId] =
|
|
378
|
-
const [collapsed, setCollapsed] =
|
|
379
|
-
const [permissionsOpen, setPermissionsOpen] =
|
|
380
|
-
const [scope, setScope] =
|
|
381
|
-
|
|
597
|
+
const [settled, setSettled] = useState4({});
|
|
598
|
+
const [dismissed, setDismissed] = useState4(/* @__PURE__ */ new Set());
|
|
599
|
+
const [submitting, setSubmitting] = useState4(null);
|
|
600
|
+
const [error, setError] = useState4(null);
|
|
601
|
+
const [activeId, setActiveId] = useState4(null);
|
|
602
|
+
const [collapsed, setCollapsed] = useState4(false);
|
|
603
|
+
const [permissionsOpen, setPermissionsOpen] = useState4(false);
|
|
604
|
+
const [scope, setScope] = useState4(null);
|
|
605
|
+
const feedbackDrafts = useRef(/* @__PURE__ */ new Map());
|
|
606
|
+
const [feedbackSaving, setFeedbackSaving] = useState4(false);
|
|
607
|
+
useEffect3(() => {
|
|
382
608
|
const finishedNow = {};
|
|
383
609
|
for (const item of items) {
|
|
384
610
|
const before = watched.current.get(item.id);
|
|
@@ -388,7 +614,7 @@ function HubApprovalDock({ items, onDecide, permissions, onOpen, focusId, classN
|
|
|
388
614
|
}
|
|
389
615
|
if (Object.keys(finishedNow).length > 0) setSettled((current) => ({ ...current, ...finishedNow }));
|
|
390
616
|
}, [items]);
|
|
391
|
-
|
|
617
|
+
useEffect3(() => {
|
|
392
618
|
const doneIds = Object.entries(settled).filter(([id]) => items.find((item) => item.id === id)?.phase === "done");
|
|
393
619
|
if (doneIds.length === 0) return;
|
|
394
620
|
const oldest = Math.min(...doneIds.map(([, at]) => at));
|
|
@@ -399,26 +625,26 @@ function HubApprovalDock({ items, onDecide, permissions, onOpen, focusId, classN
|
|
|
399
625
|
return () => clearTimeout(timer);
|
|
400
626
|
}, [settled, items]);
|
|
401
627
|
const queue = useMemo(() => items.filter((item) => !dismissed.has(item.id) && (HUB_APPROVAL_OPEN_PHASES.has(item.phase) || HUB_APPROVAL_ACTIVE_PHASES.has(item.phase) || item.phase === "unknown" || item.id in settled || submitting?.id === item.id)), [items, dismissed, settled, submitting]);
|
|
402
|
-
|
|
403
|
-
if (focusId && queue.some((item) => item.id === focusId)) {
|
|
628
|
+
useEffect3(() => {
|
|
629
|
+
if (!feedbackSaving && focusId && queue.some((item) => item.id === focusId)) {
|
|
404
630
|
setActiveId(focusId);
|
|
405
631
|
setCollapsed(false);
|
|
406
632
|
}
|
|
407
|
-
}, [focusId, queue]);
|
|
633
|
+
}, [focusId, queue, feedbackSaving]);
|
|
408
634
|
const activeIndex = Math.max(0, queue.findIndex((item) => item.id === activeId));
|
|
409
635
|
const active = queue[activeIndex];
|
|
410
|
-
|
|
636
|
+
useEffect3(() => {
|
|
411
637
|
if (!active || activeId === active.id) return;
|
|
412
638
|
setActiveId(active.id);
|
|
413
639
|
}, [active, activeId]);
|
|
414
|
-
|
|
640
|
+
useEffect3(() => {
|
|
415
641
|
setPermissionsOpen(false);
|
|
416
642
|
setScope(null);
|
|
417
643
|
}, [active?.id]);
|
|
418
644
|
if (!active) return null;
|
|
419
645
|
const presentation = presentHubAction(active);
|
|
420
646
|
const waitingCount = queue.filter((item) => HUB_APPROVAL_OPEN_PHASES.has(item.phase)).length;
|
|
421
|
-
const choices = permissions?.(active) ?? null;
|
|
647
|
+
const choices = active.executionMode === "dry-run" ? null : permissions?.(active) ?? null;
|
|
422
648
|
const scopes = choices && "scopes" in choices ? choices.scopes : [];
|
|
423
649
|
const chosenScope = scope ?? scopes[0]?.id ?? null;
|
|
424
650
|
const busy = submitting?.id === active.id;
|
|
@@ -438,104 +664,115 @@ function HubApprovalDock({ items, onDecide, permissions, onOpen, focusId, classN
|
|
|
438
664
|
setSubmitting(null);
|
|
439
665
|
}
|
|
440
666
|
}
|
|
441
|
-
const card = /* @__PURE__ */
|
|
442
|
-
/* @__PURE__ */
|
|
443
|
-
/* @__PURE__ */
|
|
444
|
-
/* @__PURE__ */
|
|
445
|
-
/* @__PURE__ */
|
|
446
|
-
/* @__PURE__ */
|
|
667
|
+
const card = /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
668
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex items-start gap-3 px-4 pt-3", children: [
|
|
669
|
+
/* @__PURE__ */ jsx5(HubProviderMark, { providerId: presentation.provider.id, name: presentation.provider.name, size: 28 }),
|
|
670
|
+
/* @__PURE__ */ jsxs5("div", { className: "min-w-0 flex-1", children: [
|
|
671
|
+
/* @__PURE__ */ jsx5("h3", { className: "line-clamp-2 break-words text-base font-semibold leading-6 text-foreground", title: presentation.title, children: presentation.title }),
|
|
672
|
+
/* @__PURE__ */ jsx5("p", { className: "truncate text-sm text-muted-foreground", children: subtitle })
|
|
447
673
|
] }),
|
|
448
|
-
/* @__PURE__ */
|
|
449
|
-
|
|
674
|
+
/* @__PURE__ */ jsx5(
|
|
675
|
+
Button3,
|
|
450
676
|
{
|
|
451
677
|
variant: "ghost",
|
|
452
678
|
size: "icon-sm",
|
|
453
679
|
"aria-label": collapsed ? "Show the request" : "Hide the preview",
|
|
454
680
|
"aria-expanded": !collapsed,
|
|
681
|
+
disabled: feedbackSaving,
|
|
455
682
|
onClick: () => setCollapsed((value) => !value),
|
|
456
|
-
children: /* @__PURE__ */
|
|
683
|
+
children: /* @__PURE__ */ jsx5(ChevronDown, { className: `transition-transform ${collapsed ? "-rotate-90" : ""}` })
|
|
457
684
|
}
|
|
458
685
|
)
|
|
459
686
|
] }),
|
|
460
|
-
!collapsed && /* @__PURE__ */
|
|
461
|
-
active.bundle?.steps && active.bundle.steps.length > 0 && /* @__PURE__ */
|
|
462
|
-
/* @__PURE__ */
|
|
687
|
+
!collapsed && /* @__PURE__ */ jsxs5("div", { className: "max-h-[55vh] space-y-3 overflow-y-auto px-4 pt-3 sm:max-h-[60vh]", children: [
|
|
688
|
+
active.bundle?.steps && active.bundle.steps.length > 0 && /* @__PURE__ */ jsx5("ol", { className: "space-y-1 text-sm", "aria-label": "Steps this approval covers", children: active.bundle.steps.map((stepItem, index) => /* @__PURE__ */ jsxs5("li", { className: `flex items-center gap-2 ${stepItem.state === "current" ? "font-medium text-foreground" : "text-muted-foreground"}`, children: [
|
|
689
|
+
/* @__PURE__ */ jsx5("span", { className: `flex size-5 shrink-0 items-center justify-center rounded-full border text-sm tabular-nums ${stepItem.state === "done" ? "border-transparent bg-[var(--surface-success-bg)] text-[var(--surface-success-text)]" : "border-border"}`, children: stepItem.state === "done" ? /* @__PURE__ */ jsx5(Check, { "aria-hidden": true, className: "size-3.5" }) : index + 1 }),
|
|
463
690
|
stepItem.label
|
|
464
691
|
] }, index)) }),
|
|
465
|
-
/* @__PURE__ */
|
|
466
|
-
/* @__PURE__ */
|
|
692
|
+
/* @__PURE__ */ jsx5(HubActionPreviewView, { preview: presentation.preview, account: active.account }),
|
|
693
|
+
/* @__PURE__ */ jsx5(HubRawDetails, { sections: [{ label: "Call", value: { action: active.actionPath, input: active.input } }] }),
|
|
694
|
+
onFeedback && /* @__PURE__ */ jsx5(HubPreviewFeedback, { item: active, drafts: feedbackDrafts.current, onFeedback: async (item, feedback) => {
|
|
695
|
+
setFeedbackSaving(true);
|
|
696
|
+
try {
|
|
697
|
+
await onFeedback(item, feedback);
|
|
698
|
+
} finally {
|
|
699
|
+
setFeedbackSaving(false);
|
|
700
|
+
}
|
|
701
|
+
} }, active.id)
|
|
467
702
|
] }),
|
|
468
|
-
/* @__PURE__ */
|
|
469
|
-
busy && submitting && !HUB_APPROVAL_ACTIVE_PHASES.has(active.phase) && active.phase === "waiting" && /* @__PURE__ */
|
|
470
|
-
/* @__PURE__ */
|
|
703
|
+
/* @__PURE__ */ jsxs5("div", { className: "space-y-3 px-4 pb-4 pt-3", children: [
|
|
704
|
+
busy && submitting && !HUB_APPROVAL_ACTIVE_PHASES.has(active.phase) && active.phase === "waiting" && /* @__PURE__ */ jsxs5("p", { role: "status", className: "flex items-center gap-2 text-sm font-medium text-foreground", children: [
|
|
705
|
+
/* @__PURE__ */ jsx5(Loader2, { "aria-hidden": true, className: "size-4 animate-spin text-[var(--surface-info-text)]" }),
|
|
471
706
|
submitting.label
|
|
472
707
|
] }),
|
|
473
|
-
/* @__PURE__ */
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
active.phase
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
708
|
+
/* @__PURE__ */ jsx5(Progress, { item: active }),
|
|
709
|
+
HUB_APPROVAL_OPEN_PHASES.has(active.phase) && active.executionMode === "dry-run" && /* @__PURE__ */ jsx5("p", { className: "text-sm text-muted-foreground", children: "Dry run. This exact payload stays held until you approve this action live." }),
|
|
710
|
+
error?.id === active.id && active.phase === "waiting" && /* @__PURE__ */ jsx5("p", { role: "alert", className: "text-sm text-[var(--surface-danger-text)]", children: error.message }),
|
|
711
|
+
HUB_APPROVAL_OPEN_PHASES.has(active.phase) && active.wait && /* @__PURE__ */ jsx5(HubApprovalWaitNote, { wait: active.wait }),
|
|
712
|
+
active.phase === "blocked" && !active.wait && /* @__PURE__ */ jsx5("p", { className: "text-sm text-muted-foreground", children: "The workspace owner approves this request." }),
|
|
713
|
+
decidable && permissionsOpen && scopes.length > 0 && /* @__PURE__ */ jsxs5("fieldset", { className: "space-y-2 rounded-xl border border-border bg-muted/30 px-3 py-3", children: [
|
|
714
|
+
/* @__PURE__ */ jsx5("legend", { className: "sr-only", children: "Standing permission" }),
|
|
715
|
+
scopes.length > 1 && /* @__PURE__ */ jsx5(
|
|
480
716
|
RadioGroup,
|
|
481
717
|
{
|
|
482
718
|
"aria-label": "What the permission covers",
|
|
483
719
|
value: chosenScope ?? void 0,
|
|
484
720
|
onValueChange: setScope,
|
|
485
721
|
className: "gap-1.5",
|
|
486
|
-
children: scopes.map((option) => /* @__PURE__ */
|
|
487
|
-
/* @__PURE__ */
|
|
488
|
-
/* @__PURE__ */
|
|
722
|
+
children: scopes.map((option) => /* @__PURE__ */ jsxs5("div", { className: "flex min-h-8 items-center gap-2", children: [
|
|
723
|
+
/* @__PURE__ */ jsx5(RadioGroupItem, { id: `hub-scope-${active.id}-${option.id}`, value: option.id }),
|
|
724
|
+
/* @__PURE__ */ jsx5(Label2, { htmlFor: `hub-scope-${active.id}-${option.id}`, className: "cursor-pointer text-sm font-normal text-foreground", children: option.label })
|
|
489
725
|
] }, option.id))
|
|
490
726
|
}
|
|
491
727
|
),
|
|
492
|
-
scopes.length === 1 && /* @__PURE__ */
|
|
493
|
-
/* @__PURE__ */
|
|
494
|
-
/* @__PURE__ */
|
|
495
|
-
/* @__PURE__ */
|
|
728
|
+
scopes.length === 1 && /* @__PURE__ */ jsx5("p", { className: "text-sm text-foreground", children: scopes[0]?.label }),
|
|
729
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap gap-2", children: [
|
|
730
|
+
/* @__PURE__ */ jsx5(Button3, { variant: "outline", onClick: () => chosenScope && void decide({ kind: "allow", duration: "24h", scope: chosenScope }, "Approving and allowing for 24 hours\u2026"), children: "Approve and allow for 24 hours" }),
|
|
731
|
+
/* @__PURE__ */ jsx5(Button3, { variant: "outline", onClick: () => chosenScope && void decide({ kind: "allow", duration: "always", scope: chosenScope }, "Approving and allowing from now on\u2026"), children: "Approve and always allow" })
|
|
496
732
|
] })
|
|
497
733
|
] }),
|
|
498
|
-
/* @__PURE__ */
|
|
499
|
-
decidable && /* @__PURE__ */
|
|
500
|
-
/* @__PURE__ */
|
|
501
|
-
/* @__PURE__ */
|
|
502
|
-
scopes.length > 0 && /* @__PURE__ */
|
|
734
|
+
/* @__PURE__ */ jsxs5("div", { className: "flex flex-wrap items-center gap-2", children: [
|
|
735
|
+
decidable && /* @__PURE__ */ jsxs5(Fragment, { children: [
|
|
736
|
+
/* @__PURE__ */ jsx5(Button3, { disabled: feedbackSaving, onClick: () => void decide({ kind: "approve" }, "Approving\u2026"), children: active.executionMode === "dry-run" ? "Approve live" : "Approve" }),
|
|
737
|
+
/* @__PURE__ */ jsx5(Button3, { disabled: feedbackSaving, variant: "outline", onClick: () => void decide({ kind: "deny" }, "Denying\u2026"), children: "Deny" }),
|
|
738
|
+
scopes.length > 0 && /* @__PURE__ */ jsx5(Button3, { variant: "ghost", "aria-expanded": permissionsOpen, onClick: () => setPermissionsOpen((value) => !value), children: permissionsOpen ? "Fewer options" : "Allow future calls\u2026" })
|
|
503
739
|
] }),
|
|
504
|
-
(active.phase === "failed" || active.phase === "unknown") && /* @__PURE__ */
|
|
505
|
-
/* @__PURE__ */
|
|
740
|
+
(active.phase === "failed" || active.phase === "unknown") && /* @__PURE__ */ jsxs5(Button3, { variant: "outline", onClick: () => setDismissed((current) => /* @__PURE__ */ new Set([...current, active.id])), children: [
|
|
741
|
+
/* @__PURE__ */ jsx5(X, { "aria-hidden": true }),
|
|
506
742
|
" Dismiss"
|
|
507
743
|
] }),
|
|
508
|
-
/* @__PURE__ */
|
|
509
|
-
decidable && choices && "never" in choices && !active.wait && /* @__PURE__ */
|
|
510
|
-
onOpen && /* @__PURE__ */
|
|
744
|
+
/* @__PURE__ */ jsx5("span", { className: "flex-1" }),
|
|
745
|
+
decidable && choices && "never" in choices && !active.wait && /* @__PURE__ */ jsx5("span", { className: "text-sm text-muted-foreground", children: choices.never }),
|
|
746
|
+
onOpen && /* @__PURE__ */ jsx5(Button3, { variant: "ghost", onClick: () => onOpen(active), children: "View in chat" })
|
|
511
747
|
] })
|
|
512
748
|
] })
|
|
513
749
|
] });
|
|
514
|
-
return /* @__PURE__ */
|
|
750
|
+
return /* @__PURE__ */ jsx5(
|
|
515
751
|
"section",
|
|
516
752
|
{
|
|
517
753
|
"aria-label": active.phase === "unknown" ? "Action may have run" : "Waiting for your approval",
|
|
518
754
|
"data-hub-approval-dock": active.id,
|
|
519
755
|
className: `overflow-hidden rounded-2xl border border-[var(--surface-warning-border)] bg-card shadow-md ${className}`,
|
|
520
|
-
children: queue.length > 1 ? /* @__PURE__ */
|
|
521
|
-
/* @__PURE__ */
|
|
522
|
-
/* @__PURE__ */
|
|
523
|
-
if (item.id === active.id) return /* @__PURE__ */
|
|
756
|
+
children: queue.length > 1 ? /* @__PURE__ */ jsxs5("div", { className: "max-h-[70vh] overflow-y-auto pt-2.5", children: [
|
|
757
|
+
/* @__PURE__ */ jsx5("p", { className: "px-4 pb-1.5 text-sm font-medium text-muted-foreground", "aria-live": "polite", children: waitingCount === 0 ? `${queue.length} requests` : waitingCount === 1 ? "1 request waiting" : `${waitingCount} requests waiting` }),
|
|
758
|
+
/* @__PURE__ */ jsx5("ul", { "aria-label": "Requests in this conversation", className: "divide-y divide-border border-t border-border", children: queue.map((item) => {
|
|
759
|
+
if (item.id === active.id) return /* @__PURE__ */ jsx5("li", { "aria-current": "true", children: card }, item.id);
|
|
524
760
|
const shown = presentHubAction(item);
|
|
525
|
-
return /* @__PURE__ */
|
|
526
|
-
|
|
761
|
+
return /* @__PURE__ */ jsx5("li", { children: /* @__PURE__ */ jsxs5(
|
|
762
|
+
Button3,
|
|
527
763
|
{
|
|
528
764
|
variant: "bare",
|
|
529
765
|
"data-hub-approval-dock-row": item.id,
|
|
766
|
+
disabled: feedbackSaving,
|
|
530
767
|
onClick: () => {
|
|
531
768
|
setActiveId(item.id);
|
|
532
769
|
setCollapsed(false);
|
|
533
770
|
},
|
|
534
771
|
className: "flex min-h-11 w-full items-center gap-2.5 px-4 text-left transition-colors hover:bg-muted/60",
|
|
535
772
|
children: [
|
|
536
|
-
/* @__PURE__ */
|
|
537
|
-
/* @__PURE__ */
|
|
538
|
-
/* @__PURE__ */
|
|
773
|
+
/* @__PURE__ */ jsx5(HubProviderMark, { providerId: shown.provider.id, name: shown.provider.name, size: 24 }),
|
|
774
|
+
/* @__PURE__ */ jsx5("span", { className: "min-w-0 flex-1 truncate text-sm font-medium text-foreground", children: item.phase === "done" ? hubActionReceipt(item).title : shown.title }),
|
|
775
|
+
/* @__PURE__ */ jsx5("span", { className: item.phase === "waiting" ? "hidden sm:inline-flex" : "inline-flex", children: /* @__PURE__ */ jsx5(HubApprovalPhasePill, { phase: item.phase, label: openPhaseLabel(item) }) })
|
|
539
776
|
]
|
|
540
777
|
}
|
|
541
778
|
) }, item.id);
|
|
@@ -546,10 +783,10 @@ function HubApprovalDock({ items, onDecide, permissions, onOpen, focusId, classN
|
|
|
546
783
|
}
|
|
547
784
|
|
|
548
785
|
// src/hub-approvals-react/list.tsx
|
|
549
|
-
import { useEffect as
|
|
786
|
+
import { useEffect as useEffect4, useState as useState5 } from "react";
|
|
550
787
|
import { ChevronRight as ChevronRight2, ShieldCheck } from "lucide-react";
|
|
551
|
-
import { Button as
|
|
552
|
-
import { jsx as
|
|
788
|
+
import { Button as Button4 } from "@tangle-network/ui/primitives";
|
|
789
|
+
import { jsx as jsx6, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
553
790
|
var GROUPS = [
|
|
554
791
|
{ id: "waiting", label: "Waiting", phases: ["waiting", "blocked"] },
|
|
555
792
|
{ id: "running", label: "Running", phases: ["queued", "running"] },
|
|
@@ -560,55 +797,55 @@ var GROUPS = [
|
|
|
560
797
|
{ id: "closed", label: "Denied or expired", phases: ["denied", "expired"] }
|
|
561
798
|
];
|
|
562
799
|
function HubApprovalsList({ items, onSelect, selectedId, className = "" }) {
|
|
563
|
-
const [now, setNow] =
|
|
564
|
-
|
|
800
|
+
const [now, setNow] = useState5(() => Date.now());
|
|
801
|
+
useEffect4(() => {
|
|
565
802
|
const timer = setInterval(() => setNow(Date.now()), 3e4);
|
|
566
803
|
return () => clearInterval(timer);
|
|
567
804
|
}, []);
|
|
568
805
|
const waiting = items.filter((item) => item.phase === "waiting" || item.phase === "blocked").length;
|
|
569
806
|
const groups = GROUPS.map((group) => ({ ...group, items: items.filter((item) => group.phases.includes(item.phase)).slice().reverse() })).filter((group) => group.items.length > 0);
|
|
570
|
-
return /* @__PURE__ */
|
|
571
|
-
/* @__PURE__ */
|
|
572
|
-
/* @__PURE__ */
|
|
573
|
-
/* @__PURE__ */
|
|
807
|
+
return /* @__PURE__ */ jsxs6("div", { className: `flex h-full min-h-0 flex-col ${className}`, children: [
|
|
808
|
+
/* @__PURE__ */ jsxs6("div", { className: "shrink-0 border-b border-border px-4 py-3", children: [
|
|
809
|
+
/* @__PURE__ */ jsx6("h2", { className: "text-base font-semibold text-foreground", children: "Approvals" }),
|
|
810
|
+
/* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", "aria-live": "polite", children: waiting === 0 ? "Nothing is waiting for you" : waiting === 1 ? "1 request is waiting" : `${waiting} requests are waiting` })
|
|
574
811
|
] }),
|
|
575
|
-
groups.length === 0 ? /* @__PURE__ */
|
|
576
|
-
/* @__PURE__ */
|
|
577
|
-
/* @__PURE__ */
|
|
578
|
-
/* @__PURE__ */
|
|
579
|
-
] }) : /* @__PURE__ */
|
|
580
|
-
/* @__PURE__ */
|
|
812
|
+
groups.length === 0 ? /* @__PURE__ */ jsxs6("div", { className: "flex flex-1 flex-col items-center justify-center gap-2 px-6 py-10 text-center", children: [
|
|
813
|
+
/* @__PURE__ */ jsx6("span", { className: "flex size-10 items-center justify-center rounded-xl bg-muted", children: /* @__PURE__ */ jsx6(ShieldCheck, { "aria-hidden": true, className: "size-5 text-muted-foreground" }) }),
|
|
814
|
+
/* @__PURE__ */ jsx6("p", { className: "text-sm font-medium text-foreground", children: "No approvals in this conversation" }),
|
|
815
|
+
/* @__PURE__ */ jsx6("p", { className: "text-sm text-muted-foreground", children: "Requests to act on your connected accounts appear here." })
|
|
816
|
+
] }) : /* @__PURE__ */ jsx6("div", { className: "min-h-0 flex-1 space-y-5 overflow-y-auto px-2 py-3", children: groups.map((group) => /* @__PURE__ */ jsxs6("section", { "aria-label": group.label, children: [
|
|
817
|
+
/* @__PURE__ */ jsxs6("h3", { className: "px-2 pb-1 text-sm font-medium text-muted-foreground", children: [
|
|
581
818
|
group.label,
|
|
582
819
|
" ",
|
|
583
|
-
/* @__PURE__ */
|
|
820
|
+
/* @__PURE__ */ jsxs6("span", { className: "tabular-nums", children: [
|
|
584
821
|
"\xB7 ",
|
|
585
822
|
group.items.length
|
|
586
823
|
] })
|
|
587
824
|
] }),
|
|
588
|
-
/* @__PURE__ */
|
|
825
|
+
/* @__PURE__ */ jsx6("ul", { className: "space-y-1", children: group.items.map((item) => {
|
|
589
826
|
const presentation = presentHubAction(item);
|
|
590
827
|
const title = item.phase === "done" ? hubActionReceipt(item).title : presentation.title;
|
|
591
828
|
const when = item.phase === "waiting" ? closesIn(item.expiresAt, now) ?? relativeTime(item.requestedAt, now) : relativeTime(item.requestedAt, now);
|
|
592
829
|
const detail = [presentation.provider.name, distinctAccount(item.account, presentation.provider.name), when].filter(Boolean).join(" \xB7 ");
|
|
593
830
|
const selected = selectedId === item.id;
|
|
594
|
-
return /* @__PURE__ */
|
|
595
|
-
|
|
831
|
+
return /* @__PURE__ */ jsx6("li", { children: /* @__PURE__ */ jsxs6(
|
|
832
|
+
Button4,
|
|
596
833
|
{
|
|
597
834
|
variant: "bare",
|
|
598
835
|
onClick: () => onSelect?.(item),
|
|
599
836
|
"aria-current": selected ? "true" : void 0,
|
|
600
837
|
className: `flex w-full items-start gap-3 rounded-lg px-2 py-2.5 text-left transition-colors hover:bg-muted ${selected ? "bg-muted" : ""}`,
|
|
601
838
|
children: [
|
|
602
|
-
/* @__PURE__ */
|
|
603
|
-
/* @__PURE__ */
|
|
604
|
-
/* @__PURE__ */
|
|
605
|
-
/* @__PURE__ */
|
|
606
|
-
item.phase === "unknown" && /* @__PURE__ */
|
|
607
|
-
(item.phase === "waiting" || item.phase === "blocked") && item.wait && /* @__PURE__ */
|
|
839
|
+
/* @__PURE__ */ jsx6(HubProviderMark, { providerId: presentation.provider.id, name: presentation.provider.name, size: 28 }),
|
|
840
|
+
/* @__PURE__ */ jsxs6("span", { className: "min-w-0 flex-1", children: [
|
|
841
|
+
/* @__PURE__ */ jsx6("span", { className: "line-clamp-2 text-sm font-medium leading-5 text-foreground", children: title }),
|
|
842
|
+
/* @__PURE__ */ jsx6("span", { className: "mt-0.5 block truncate text-sm text-muted-foreground", children: detail }),
|
|
843
|
+
item.phase === "unknown" && /* @__PURE__ */ jsx6("span", { className: "mt-1 block text-sm text-[var(--surface-warning-text)]", children: HUB_APPROVAL_UNKNOWN_WARNING }),
|
|
844
|
+
(item.phase === "waiting" || item.phase === "blocked") && item.wait && /* @__PURE__ */ jsx6("span", { className: "mt-1 line-clamp-2 block text-sm text-muted-foreground", children: item.wait.reason })
|
|
608
845
|
] }),
|
|
609
|
-
/* @__PURE__ */
|
|
610
|
-
/* @__PURE__ */
|
|
611
|
-
/* @__PURE__ */
|
|
846
|
+
/* @__PURE__ */ jsxs6("span", { className: "flex shrink-0 items-center gap-1", children: [
|
|
847
|
+
/* @__PURE__ */ jsx6(HubApprovalPhasePill, { phase: item.phase, label: openPhaseLabel(item, "Owner") }),
|
|
848
|
+
/* @__PURE__ */ jsx6(ChevronRight2, { "aria-hidden": true, className: "size-4 text-muted-foreground" })
|
|
612
849
|
] })
|
|
613
850
|
]
|
|
614
851
|
}
|
|
@@ -619,19 +856,19 @@ function HubApprovalsList({ items, onSelect, selectedId, className = "" }) {
|
|
|
619
856
|
}
|
|
620
857
|
|
|
621
858
|
// src/hub-approvals-react/row.tsx
|
|
622
|
-
import { useEffect as
|
|
859
|
+
import { useEffect as useEffect5, useRef as useRef2, useState as useState7 } from "react";
|
|
623
860
|
import { ChevronDown as ChevronDown2 } from "lucide-react";
|
|
624
|
-
import { Button as
|
|
861
|
+
import { Button as Button5 } from "@tangle-network/ui/primitives";
|
|
625
862
|
|
|
626
863
|
// src/hub-approvals-react/receipt.tsx
|
|
627
|
-
import { useState as
|
|
864
|
+
import { useState as useState6 } from "react";
|
|
628
865
|
import { ExternalLink as ExternalLink2 } from "lucide-react";
|
|
629
866
|
import { ApprovalDiffSummary as ApprovalDiffSummary2 } from "@tangle-network/ui/run";
|
|
630
|
-
import { jsx as
|
|
867
|
+
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
631
868
|
function AudioPlayer({ src }) {
|
|
632
|
-
const [failed, setFailed] =
|
|
633
|
-
if (failed) return /* @__PURE__ */
|
|
634
|
-
return /* @__PURE__ */
|
|
869
|
+
const [failed, setFailed] = useState6(false);
|
|
870
|
+
if (failed) return /* @__PURE__ */ jsx7("p", { className: "text-sm text-muted-foreground", children: "The audio link has expired. Ask the agent for a new one." });
|
|
871
|
+
return /* @__PURE__ */ jsx7("audio", { controls: true, preload: "metadata", src, onError: () => setFailed(true), className: "h-10 w-full" });
|
|
635
872
|
}
|
|
636
873
|
function HubActionReceiptCard({ item, className = "" }) {
|
|
637
874
|
const receipt = hubActionReceipt(item);
|
|
@@ -639,27 +876,27 @@ function HubActionReceiptCard({ item, className = "" }) {
|
|
|
639
876
|
const account = distinctAccount(item.account, receipt.provider.name);
|
|
640
877
|
const subtitle = [receipt.provider.name, account ? `as ${account}` : null, presentation.target && !receipt.title.includes(presentation.target) ? presentation.target : null].filter(Boolean).join(" \xB7 ");
|
|
641
878
|
const phase = item.phase;
|
|
642
|
-
return /* @__PURE__ */
|
|
643
|
-
/* @__PURE__ */
|
|
644
|
-
/* @__PURE__ */
|
|
645
|
-
/* @__PURE__ */
|
|
646
|
-
/* @__PURE__ */
|
|
647
|
-
/* @__PURE__ */
|
|
648
|
-
/* @__PURE__ */
|
|
649
|
-
] }) : /* @__PURE__ */
|
|
650
|
-
subtitle && /* @__PURE__ */
|
|
879
|
+
return /* @__PURE__ */ jsxs7("article", { "aria-label": receipt.title, className: `rounded-xl border border-border bg-card px-4 py-3 shadow-sm ${className}`, children: [
|
|
880
|
+
/* @__PURE__ */ jsxs7("div", { className: "flex items-start gap-3", children: [
|
|
881
|
+
/* @__PURE__ */ jsx7(HubProviderMark, { providerId: receipt.provider.id, name: receipt.provider.name }),
|
|
882
|
+
/* @__PURE__ */ jsxs7("div", { className: "min-w-0 flex-1", children: [
|
|
883
|
+
/* @__PURE__ */ jsx7("p", { className: "text-base font-semibold leading-6 text-foreground", children: receipt.href ? /* @__PURE__ */ jsxs7("a", { href: receipt.href, target: "_blank", rel: "noreferrer", className: "inline-flex max-w-full items-center gap-1.5 hover:underline", children: [
|
|
884
|
+
/* @__PURE__ */ jsx7("span", { className: "truncate", children: receipt.title }),
|
|
885
|
+
/* @__PURE__ */ jsx7(ExternalLink2, { "aria-hidden": true, className: "size-4 shrink-0 text-muted-foreground" })
|
|
886
|
+
] }) : /* @__PURE__ */ jsx7("span", { className: "break-words", children: receipt.title }) }),
|
|
887
|
+
subtitle && /* @__PURE__ */ jsx7("p", { className: "truncate text-sm text-muted-foreground", children: subtitle })
|
|
651
888
|
] }),
|
|
652
|
-
/* @__PURE__ */
|
|
889
|
+
/* @__PURE__ */ jsx7(HubApprovalPhasePill, { phase })
|
|
653
890
|
] }),
|
|
654
|
-
(receipt.fields.length > 0 || receipt.media || receipt.files || receipt.error || receipt.warning) && /* @__PURE__ */
|
|
655
|
-
/* @__PURE__ */
|
|
656
|
-
receipt.media && /* @__PURE__ */
|
|
657
|
-
receipt.files && /* @__PURE__ */
|
|
658
|
-
receipt.warning && /* @__PURE__ */
|
|
659
|
-
receipt.error && /* @__PURE__ */
|
|
891
|
+
(receipt.fields.length > 0 || receipt.media || receipt.files || receipt.error || receipt.warning) && /* @__PURE__ */ jsxs7("div", { className: "mt-3 space-y-3", children: [
|
|
892
|
+
/* @__PURE__ */ jsx7(HubFieldList, { fields: receipt.fields }),
|
|
893
|
+
receipt.media && /* @__PURE__ */ jsx7(AudioPlayer, { src: receipt.media.src }),
|
|
894
|
+
receipt.files && /* @__PURE__ */ jsx7(ApprovalDiffSummary2, { files: receipt.files }),
|
|
895
|
+
receipt.warning && /* @__PURE__ */ jsx7("p", { className: "break-words rounded-lg border border-[var(--surface-warning-border)] bg-[var(--surface-warning-bg)] px-3 py-2 text-sm text-[var(--surface-warning-text)]", children: receipt.warning }),
|
|
896
|
+
receipt.error && /* @__PURE__ */ jsx7("p", { className: "break-words rounded-lg border border-[var(--surface-danger-border)] bg-[var(--surface-danger-bg)] px-3 py-2 text-sm text-[var(--surface-danger-text)]", children: receipt.error })
|
|
660
897
|
] }),
|
|
661
|
-
(item.grant || item.autoApproved) && /* @__PURE__ */
|
|
662
|
-
/* @__PURE__ */
|
|
898
|
+
(item.grant || item.autoApproved) && /* @__PURE__ */ jsx7("p", { className: "mt-3 text-sm text-muted-foreground", children: item.autoApproved ?? `Allowed ${item.grant?.expiresAt ? "for 24 hours" : "from now on"}: ${item.grant?.scope}` }),
|
|
899
|
+
/* @__PURE__ */ jsx7("div", { className: "mt-2", children: /* @__PURE__ */ jsx7(HubRawDetails, { sections: [
|
|
663
900
|
{ label: "Call", value: { action: item.actionPath, input: item.input } },
|
|
664
901
|
{ label: "Result", value: item.result }
|
|
665
902
|
] }) })
|
|
@@ -675,63 +912,74 @@ function HubApprovalReceipts({ items, message, at }) {
|
|
|
675
912
|
const verbs = [approved ? `approved ${actions(approved)}` : null, denied ? `denied ${actions(denied)}` : null].filter(Boolean);
|
|
676
913
|
const summary = verbs.length ? `You ${verbs.join(" and ")}${expired ? `; ${actions(expired)} expired` : ""}` : expired ? `${actions(expired)} expired` : "Your decisions";
|
|
677
914
|
const when = at ? new Date(at) : null;
|
|
678
|
-
return /* @__PURE__ */
|
|
679
|
-
/* @__PURE__ */
|
|
680
|
-
/* @__PURE__ */
|
|
681
|
-
when && !Number.isNaN(when.getTime()) && /* @__PURE__ */
|
|
915
|
+
return /* @__PURE__ */ jsxs7("section", { "aria-label": "Approval results", className: "space-y-2", children: [
|
|
916
|
+
/* @__PURE__ */ jsxs7("p", { className: "flex items-center gap-2 text-sm text-muted-foreground", children: [
|
|
917
|
+
/* @__PURE__ */ jsx7("span", { children: summary }),
|
|
918
|
+
when && !Number.isNaN(when.getTime()) && /* @__PURE__ */ jsxs7("time", { dateTime: when.toISOString(), children: [
|
|
682
919
|
"\xB7 ",
|
|
683
920
|
when.toLocaleTimeString(void 0, { hour: "numeric", minute: "2-digit" })
|
|
684
921
|
] })
|
|
685
922
|
] }),
|
|
686
|
-
decided.map((item) => /* @__PURE__ */
|
|
687
|
-
message && /* @__PURE__ */
|
|
923
|
+
decided.map((item) => /* @__PURE__ */ jsx7(HubActionReceiptCard, { item }, item.id)),
|
|
924
|
+
message && /* @__PURE__ */ jsx7(HubRawDetails, { label: "Message sent to the agent", sections: [{ label: "The agent received", value: message }] })
|
|
688
925
|
] });
|
|
689
926
|
}
|
|
690
927
|
|
|
691
928
|
// src/hub-approvals-react/row.tsx
|
|
692
|
-
import { Fragment as Fragment2, jsx as
|
|
693
|
-
function HubApprovalRow({ item, expanded: controlled, onExpandedChange, onReview, actions }) {
|
|
694
|
-
const [own, setOwn] =
|
|
929
|
+
import { Fragment as Fragment2, jsx as jsx8, jsxs as jsxs8 } from "react/jsx-runtime";
|
|
930
|
+
function HubApprovalRow({ item, expanded: controlled, onExpandedChange, onReview, actions, onFeedback }) {
|
|
931
|
+
const [own, setOwn] = useState7(false);
|
|
695
932
|
const expanded = controlled ?? own;
|
|
696
933
|
const ref = useRef2(null);
|
|
934
|
+
const feedbackDrafts = useRef2(/* @__PURE__ */ new Map());
|
|
935
|
+
const [feedbackSaving, setFeedbackSaving] = useState7(false);
|
|
697
936
|
const presentation = presentHubAction(item);
|
|
698
937
|
const title = item.phase === "done" ? hubActionReceipt(item).title : presentation.title;
|
|
699
|
-
|
|
938
|
+
useEffect5(() => {
|
|
700
939
|
if (controlled) ref.current?.scrollIntoView({ block: "center", behavior: "smooth" });
|
|
701
940
|
}, [controlled]);
|
|
702
941
|
const toggle = () => {
|
|
703
942
|
setOwn(!expanded);
|
|
704
943
|
onExpandedChange?.(!expanded);
|
|
705
944
|
};
|
|
706
|
-
return /* @__PURE__ */
|
|
707
|
-
/* @__PURE__ */
|
|
708
|
-
/* @__PURE__ */
|
|
709
|
-
|
|
945
|
+
return /* @__PURE__ */ jsxs8("div", { ref, "data-hub-approval-row": item.id, className: `rounded-xl border bg-card ${expanded ? "border-border shadow-sm" : "border-border/80"}`, children: [
|
|
946
|
+
/* @__PURE__ */ jsxs8("div", { className: "flex items-center gap-3 px-3 py-2", children: [
|
|
947
|
+
/* @__PURE__ */ jsxs8(
|
|
948
|
+
Button5,
|
|
710
949
|
{
|
|
711
950
|
variant: "bare",
|
|
712
951
|
"aria-expanded": expanded,
|
|
952
|
+
disabled: feedbackSaving,
|
|
713
953
|
onClick: toggle,
|
|
714
954
|
className: "flex min-h-9 min-w-0 flex-1 items-center gap-3 rounded-md text-left",
|
|
715
955
|
children: [
|
|
716
|
-
/* @__PURE__ */
|
|
717
|
-
/* @__PURE__ */
|
|
718
|
-
/* @__PURE__ */
|
|
719
|
-
/* @__PURE__ */
|
|
956
|
+
/* @__PURE__ */ jsx8(HubProviderMark, { providerId: presentation.provider.id, name: presentation.provider.name, size: 24 }),
|
|
957
|
+
/* @__PURE__ */ jsx8("span", { className: "min-w-0 flex-1 truncate text-sm font-medium text-foreground", children: title }),
|
|
958
|
+
/* @__PURE__ */ jsx8(HubApprovalPhasePill, { phase: item.phase, label: openPhaseLabel(item) }),
|
|
959
|
+
/* @__PURE__ */ jsx8(ChevronDown2, { "aria-hidden": true, className: `size-4 shrink-0 text-muted-foreground transition-transform ${expanded ? "rotate-180" : ""}` })
|
|
720
960
|
]
|
|
721
961
|
}
|
|
722
962
|
),
|
|
723
963
|
item.phase === "waiting" && onReview && // On a phone the dock sits just below; the row keeps its width for the title.
|
|
724
|
-
/* @__PURE__ */
|
|
964
|
+
/* @__PURE__ */ jsx8(Button5, { variant: "outline", className: "hidden sm:inline-flex", onClick: () => onReview(item), children: "Review" })
|
|
725
965
|
] }),
|
|
726
|
-
!expanded && item.phase === "unknown" && /* @__PURE__ */
|
|
727
|
-
expanded && /* @__PURE__ */
|
|
728
|
-
item.phase === "done" || item.phase === "failed" || item.phase === "unknown" ? /* @__PURE__ */
|
|
729
|
-
/* @__PURE__ */
|
|
730
|
-
/* @__PURE__ */
|
|
966
|
+
!expanded && item.phase === "unknown" && /* @__PURE__ */ jsx8("p", { className: "px-3 pb-3 text-sm text-[var(--surface-warning-text)]", children: HUB_APPROVAL_UNKNOWN_WARNING }),
|
|
967
|
+
expanded && /* @__PURE__ */ jsxs8("div", { className: "space-y-3 border-t border-border px-3 pb-3 pt-3", children: [
|
|
968
|
+
item.phase === "done" || item.phase === "failed" || item.phase === "unknown" ? /* @__PURE__ */ jsx8(HubActionReceiptCard, { item, className: "border-0 px-0 py-0 shadow-none" }) : /* @__PURE__ */ jsxs8(Fragment2, { children: [
|
|
969
|
+
/* @__PURE__ */ jsx8(HubActionPreviewView, { preview: presentation.preview, account: item.account }),
|
|
970
|
+
/* @__PURE__ */ jsx8(HubRawDetails, { sections: [{ label: "Call", value: { action: item.actionPath, input: item.input } }] })
|
|
731
971
|
] }),
|
|
732
|
-
item.phase !== "unknown" && actions
|
|
972
|
+
item.phase !== "unknown" && actions,
|
|
973
|
+
onFeedback && /* @__PURE__ */ jsx8(HubPreviewFeedback, { item, drafts: feedbackDrafts.current, onFeedback: async (source, feedback) => {
|
|
974
|
+
setFeedbackSaving(true);
|
|
975
|
+
try {
|
|
976
|
+
await onFeedback(source, feedback);
|
|
977
|
+
} finally {
|
|
978
|
+
setFeedbackSaving(false);
|
|
979
|
+
}
|
|
980
|
+
} }, item.id)
|
|
733
981
|
] }),
|
|
734
|
-
!expanded && actions && (item.phase === "expired" || item.phase === "failed") && /* @__PURE__ */
|
|
982
|
+
!expanded && actions && (item.phase === "expired" || item.phase === "failed") && /* @__PURE__ */ jsx8("div", { className: "border-t border-border px-3 py-2", children: actions })
|
|
735
983
|
] });
|
|
736
984
|
}
|
|
737
985
|
export {
|
|
@@ -743,6 +991,7 @@ export {
|
|
|
743
991
|
HubApprovalRow,
|
|
744
992
|
HubApprovalWaitNote,
|
|
745
993
|
HubApprovalsList,
|
|
994
|
+
HubPreviewFeedback,
|
|
746
995
|
HubProviderMark,
|
|
747
996
|
openPhaseLabel
|
|
748
997
|
};
|