@burdenoff/fe-libs 2026.906.6 → 2026.907.2

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.
@@ -1,6 +1,10 @@
1
1
  import { FC } from 'react';
2
2
  import { Message } from '../conversation';
3
3
  interface Props {
4
+ /** Approve a pending write. Absent outside a live conversation. */
5
+ onApprovePendingWrite?: (reference: string) => void;
6
+ /** Reference currently being approved, so only that card shows a spinner. */
7
+ approvingWriteRef?: string | null;
4
8
  message: Message;
5
9
  isStreaming?: boolean;
6
10
  /** This assistant message ended in an error — show the Retry affordance. */
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantMessageItem.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMessageItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAqBnD,OAAO,KAAK,EAGV,OAAO,EACR,MAAM,iBAAiB,CAAC;AAIzB,UAAU,KAAK;IACb,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAyCD,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,KAAK,CA4R1C,CAAC"}
1
+ {"version":3,"file":"AssistantMessageItem.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMessageItem.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAqBnD,OAAO,KAAK,EAGV,OAAO,EACR,MAAM,iBAAiB,CAAC;AAIzB,UAAU,KAAK;IACb,mEAAmE;IACnE,qBAAqB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,6EAA6E;IAC7E,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,4EAA4E;IAC5E,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iEAAiE;IACjE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAyCD,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,KAAK,CAqS1C,CAAC"}
@@ -31,60 +31,60 @@ function T(e, t, n) {
31
31
  let a = new Blob([i], { type: n }), o = URL.createObjectURL(a), s = document.createElement("a");
32
32
  s.href = o, s.download = t, document.body.appendChild(s), s.click(), document.body.removeChild(s), URL.revokeObjectURL(o);
33
33
  }
34
- var E = ({ message: w, isStreaming: E, isFailed: D, isLastAssistant: O, onRetry: k }) => {
35
- let A = r(), j = n(), { getAccessToken: M, getWorkspaceToken: N } = e(), P = o(), [F, I] = m(null), [L, R] = m(!1), z = w.role === "user", B = p(() => S(w), [w]), V = p(() => C(B), [B]), { steps: H, text: U } = p(() => z ? {
34
+ var E = ({ onApprovePendingWrite: w, approvingWriteRef: E = null, message: D, isStreaming: O, isFailed: k, isLastAssistant: A, onRetry: j }) => {
35
+ let M = r(), N = n(), { getAccessToken: P, getWorkspaceToken: F } = e(), I = o(), [L, R] = m(null), [z, B] = m(!1), V = D.role === "user", H = p(() => S(D), [D]), U = p(() => C(H), [H]), { steps: W, text: G } = p(() => V ? {
36
36
  steps: [],
37
- text: w.content
38
- } : a(w.content), [z, w.content]), W = () => {
39
- s(U || w.content).then((e) => {
40
- e && (R(!0), setTimeout(() => R(!1), 2e3));
37
+ text: D.content
38
+ } : a(D.content), [V, D.content]), K = () => {
39
+ s(G || D.content).then((e) => {
40
+ e && (B(!0), setTimeout(() => B(!1), 2e3));
41
41
  });
42
- }, G = async (e) => {
43
- if (!B?.sandboxId || !B.sessionId) return;
42
+ }, q = async (e) => {
43
+ if (!H?.sandboxId || !H.sessionId) return;
44
44
  let n = new URLSearchParams(window.location.search).get("workspace") ?? "";
45
45
  if (n) {
46
- I(e.path);
46
+ R(e.path);
47
47
  try {
48
- let r = await t(B.sandboxId, n, B.sessionId, e.path, {
49
- accessToken: M(),
50
- workspaceToken: N()
48
+ let r = await t(H.sandboxId, n, H.sessionId, e.path, {
49
+ accessToken: P(),
50
+ workspaceToken: F()
51
51
  });
52
52
  T(r.contentBase64, r.filename, r.mimeType);
53
53
  } finally {
54
- I(null);
54
+ R(null);
55
55
  }
56
56
  }
57
- }, K = new Date(w.timestamp).toLocaleTimeString([], {
57
+ }, J = new Date(D.timestamp).toLocaleTimeString([], {
58
58
  hour: "2-digit",
59
59
  minute: "2-digit"
60
60
  });
61
- if (w.role === "system") return /* @__PURE__ */ b("div", {
61
+ if (D.role === "system") return /* @__PURE__ */ b("div", {
62
62
  className: "flex justify-center px-2 py-1",
63
63
  "data-testid": "assistant-message-system",
64
64
  children: /* @__PURE__ */ b("p", {
65
65
  className: "max-w-[90%] whitespace-pre-wrap break-words rounded-lg border border-border-subtle bg-bg-sunken/60 px-3 py-2 text-center text-xs leading-relaxed text-text-muted",
66
- children: w.content
66
+ children: D.content
67
67
  })
68
68
  });
69
- if (z) {
70
- let e = w.metadata?.attachments ?? [];
69
+ if (V) {
70
+ let e = D.metadata?.attachments ?? [];
71
71
  return /* @__PURE__ */ b("div", {
72
72
  className: "flex justify-end",
73
73
  "data-testid": "assistant-message-user",
74
74
  children: /* @__PURE__ */ x("div", {
75
75
  className: "max-w-[85%]",
76
76
  children: [
77
- w.content && /* @__PURE__ */ b("div", {
77
+ D.content && /* @__PURE__ */ b("div", {
78
78
  className: "rounded-2xl rounded-br-md bg-action-primary-bg/12 px-3.5 py-2.5 text-[15px] leading-relaxed text-text-primary",
79
79
  children: /* @__PURE__ */ b("p", {
80
80
  className: "whitespace-pre-wrap",
81
- children: w.content
81
+ children: D.content
82
82
  })
83
83
  }),
84
84
  /* @__PURE__ */ b(l, { attachments: e }),
85
85
  /* @__PURE__ */ b("div", {
86
86
  className: "mt-1 pr-1 text-right text-[10px] text-text-muted",
87
- children: K
87
+ children: J
88
88
  })
89
89
  ]
90
90
  })
@@ -99,61 +99,65 @@ var E = ({ message: w, isStreaming: E, isFailed: D, isLastAssistant: O, onRetry:
99
99
  }), /* @__PURE__ */ x("div", {
100
100
  className: "min-w-0 flex-1",
101
101
  children: [
102
- H.length > 0 && /* @__PURE__ */ b(i, { steps: H }),
103
- B?.pendingWrite ? /* @__PURE__ */ b(u, { pendingWrite: B.pendingWrite }) : null,
104
- U && /* @__PURE__ */ b("div", {
102
+ W.length > 0 && /* @__PURE__ */ b(i, { steps: W }),
103
+ H?.pendingWrite ? /* @__PURE__ */ b(u, {
104
+ pendingWrite: H.pendingWrite,
105
+ onApprove: w,
106
+ approving: E !== null && E === H.pendingWrite.reference
107
+ }) : null,
108
+ G && /* @__PURE__ */ b("div", {
105
109
  className: "text-[15px] leading-relaxed text-text-primary",
106
- children: /* @__PURE__ */ b(c, { content: U })
110
+ children: /* @__PURE__ */ b(c, { content: G })
107
111
  }),
108
- E && /* @__PURE__ */ b("span", {
112
+ O && /* @__PURE__ */ b("span", {
109
113
  "aria-hidden": "true",
110
114
  className: "ml-0.5 inline-block h-4 w-1.5 rounded-sm bg-text-secondary align-middle motion-safe:animate-pulse"
111
115
  }),
112
- V.length > 0 && B?.sandboxId && B.sessionId && /* @__PURE__ */ x("div", {
116
+ U.length > 0 && H?.sandboxId && H.sessionId && /* @__PURE__ */ x("div", {
113
117
  className: "mt-3 space-y-2 border-t border-border-subtle pt-2",
114
118
  children: [/* @__PURE__ */ b("p", {
115
119
  className: "text-[10px] font-medium uppercase tracking-wide text-text-muted",
116
- children: A("message.downloads", "Downloads")
120
+ children: M("message.downloads", "Downloads")
117
121
  }), /* @__PURE__ */ b("div", {
118
122
  className: "flex flex-wrap gap-2",
119
- children: V.map((e) => {
123
+ children: U.map((e) => {
120
124
  let t = `${e.name}${e.type === "directory" ? ".tar.gz" : ""}`;
121
125
  return /* @__PURE__ */ b(f, {
122
126
  label: t,
123
- disabled: F === e.path,
127
+ disabled: L === e.path,
124
128
  testId: `assistant-artifact-${e.name}`,
125
129
  source: {
126
130
  kind: "sandbox-artifact",
127
- sandboxId: B.sandboxId,
128
- sessionId: B.sessionId,
131
+ sandboxId: H.sandboxId,
132
+ sessionId: H.sessionId,
129
133
  path: e.path,
130
134
  filename: t
131
135
  },
132
- defaultFolderPath: j.artifacts,
133
- onDownload: () => G(e)
136
+ defaultFolderPath: N.artifacts,
137
+ onDownload: () => q(e)
134
138
  }, e.path);
135
139
  })
136
140
  })]
137
141
  }),
138
- !E && (U || D || O) && /* @__PURE__ */ x("div", {
142
+ !O && (G || k || A) && /* @__PURE__ */ x("div", {
139
143
  className: "mt-1.5 flex items-center gap-1",
140
144
  children: [
141
- U && /* @__PURE__ */ b("button", {
145
+ G && /* @__PURE__ */ b("button", {
142
146
  type: "button",
143
- onClick: W,
147
+ onClick: K,
144
148
  className: "flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] text-text-muted transition-colors hover:bg-bg-elevated hover:text-text-secondary",
145
- "aria-label": A("message.copy", "Copy message"),
149
+ "aria-label": M("message.copy", "Copy message"),
146
150
  "data-testid": "assistant-message-copy",
147
- children: L ? /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(h, { className: "size-3 text-status-success-text" }), /* @__PURE__ */ b("span", { children: A("message.copied", "Copied") })] }) : /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(g, { className: "size-3" }), /* @__PURE__ */ b("span", { children: A("message.copy", "Copy") })] })
151
+ children: z ? /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(h, { className: "size-3 text-status-success-text" }), /* @__PURE__ */ b("span", { children: M("message.copied", "Copied") })] }) : /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(g, { className: "size-3" }), /* @__PURE__ */ b("span", { children: M("message.copy", "Copy") })] })
148
152
  }),
149
- U && P.isSupported && (() => {
150
- let e = P.blockedFor(w.id) ?? P.disabledReason, t = !!e && !!O, n = t ? `speak-reason-${w.id}` : void 0;
153
+ G && I.isSupported && (() => {
154
+ let e = I.blockedFor(D.id) ?? I.disabledReason, t = !!e && !!A, n = t ? `speak-reason-${D.id}` : void 0;
151
155
  return /* @__PURE__ */ x(y, { children: [/* @__PURE__ */ b(d, {
152
- isSpeaking: P.isSpeaking(w.id),
156
+ isSpeaking: I.isSpeaking(D.id),
153
157
  disabled: e !== null,
154
158
  disabledReason: e,
155
159
  describedById: n,
156
- onClick: () => P.toggle(w.id, U, B?.lang)
160
+ onClick: () => I.toggle(D.id, G, H?.lang)
157
161
  }), t && /* @__PURE__ */ b("span", {
158
162
  id: n,
159
163
  className: "text-[11px] text-text-muted",
@@ -161,21 +165,21 @@ var E = ({ message: w, isStreaming: E, isFailed: D, isLastAssistant: O, onRetry:
161
165
  children: e
162
166
  })] });
163
167
  })(),
164
- (D || O) && k && /* @__PURE__ */ x("button", {
168
+ (k || A) && j && /* @__PURE__ */ x("button", {
165
169
  type: "button",
166
- onClick: k,
167
- className: `flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] transition-colors hover:bg-bg-elevated ${D ? "text-status-error-text" : "text-text-muted hover:text-text-secondary"}`,
168
- "aria-label": A("message.retry", "Retry"),
170
+ onClick: j,
171
+ className: `flex items-center gap-1 rounded-md px-1.5 py-1 text-[11px] transition-colors hover:bg-bg-elevated ${k ? "text-status-error-text" : "text-text-muted hover:text-text-secondary"}`,
172
+ "aria-label": M("message.retry", "Retry"),
169
173
  "data-testid": "assistant-message-retry",
170
- children: [/* @__PURE__ */ b(_, { className: "size-3" }), /* @__PURE__ */ b("span", { children: A("message.retry", "Retry") })]
174
+ children: [/* @__PURE__ */ b(_, { className: "size-3" }), /* @__PURE__ */ b("span", { children: M("message.retry", "Retry") })]
171
175
  })
172
176
  ]
173
177
  }),
174
178
  /* @__PURE__ */ x("div", {
175
179
  className: "mt-1 text-[10px] text-text-muted",
176
- children: [K, w.tokens && /* @__PURE__ */ x("span", {
180
+ children: [J, D.tokens && /* @__PURE__ */ x("span", {
177
181
  className: "ml-2",
178
- children: [w.tokens.input + w.tokens.output, " tokens"]
182
+ children: [D.tokens.input + D.tokens.output, " tokens"]
179
183
  })]
180
184
  })
181
185
  ]
@@ -1,6 +1,9 @@
1
1
  import { FC } from 'react';
2
2
  import { Message } from '../conversation';
3
3
  interface Props {
4
+ /** Forwarded to each pending-write card; see AssistantPendingWriteCard. */
5
+ onApprovePendingWrite?: (reference: string) => void;
6
+ approvingWriteRef?: string | null;
4
7
  messages: Message[];
5
8
  streamingMessageId: string | null;
6
9
  /** The assistant message (if any) whose turn ended in an error. */
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantMessageList.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,UAAU,KAAK;IACb,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,KAAK,CA0E1C,CAAC"}
1
+ {"version":3,"file":"AssistantMessageList.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantMessageList.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAqB,KAAK,EAAE,EAAE,MAAM,OAAO,CAAC;AAEnD,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAG/C,UAAU,KAAK;IACb,2EAA2E;IAC3E,qBAAqB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACpD,iBAAiB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,kBAAkB,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAChC,kEAAkE;IAClE,OAAO,CAAC,EAAE,MAAM,IAAI,CAAC;CACtB;AAED,eAAO,MAAM,oBAAoB,EAAE,EAAE,CAAC,KAAK,CA8E1C,CAAC"}
@@ -3,34 +3,36 @@ import { AssistantMessageItem as t } from "./AssistantMessageItem.js";
3
3
  import { useEffect as n, useRef as r } from "react";
4
4
  import { jsx as i, jsxs as a } from "react/jsx-runtime";
5
5
  //#region src/shared/assistant/ui/AssistantMessageList.tsx
6
- var o = ({ messages: o, streamingMessageId: s, failedMessageId: c, onRetry: l }) => {
7
- let u = e(), d = (() => {
8
- for (let e = o.length - 1; e >= 0; --e) if (o[e].role === "assistant") return o[e].id;
6
+ var o = ({ onApprovePendingWrite: o, approvingWriteRef: s = null, messages: c, streamingMessageId: l, failedMessageId: u, onRetry: d }) => {
7
+ let f = e(), p = (() => {
8
+ for (let e = c.length - 1; e >= 0; --e) if (c[e].role === "assistant") return c[e].id;
9
9
  return null;
10
- })(), f = r(null), p = r(null);
10
+ })(), m = r(null), h = r(null);
11
11
  return n(() => {
12
- let e = p.current;
12
+ let e = h.current;
13
13
  if (e && e.scrollHeight - e.scrollTop - e.clientHeight < 100) {
14
14
  let e = typeof window < "u" && window.matchMedia?.("(prefers-reduced-motion: reduce)").matches;
15
- f.current?.scrollIntoView({ behavior: e ? "auto" : "smooth" });
15
+ m.current?.scrollIntoView({ behavior: e ? "auto" : "smooth" });
16
16
  }
17
- }, [o, s]), n(() => {
18
- f.current?.scrollIntoView({ behavior: "instant" });
17
+ }, [c, l]), n(() => {
18
+ m.current?.scrollIntoView({ behavior: "instant" });
19
19
  }, []), /* @__PURE__ */ a("div", {
20
- ref: p,
20
+ ref: h,
21
21
  className: "flex-1 space-y-4 overflow-y-auto p-3",
22
22
  role: "log",
23
23
  "aria-live": "polite",
24
24
  "aria-relevant": "additions",
25
- "aria-busy": s !== null,
26
- "aria-label": u("messageList.ariaLabel", "Conversation messages"),
27
- children: [o.map((e) => /* @__PURE__ */ i(t, {
25
+ "aria-busy": l !== null,
26
+ "aria-label": f("messageList.ariaLabel", "Conversation messages"),
27
+ children: [c.map((e) => /* @__PURE__ */ i(t, {
28
+ onApprovePendingWrite: o,
29
+ approvingWriteRef: s,
28
30
  message: e,
29
- isStreaming: e.id === s,
30
- isFailed: e.id === c,
31
- isLastAssistant: e.id === d,
32
- onRetry: l
33
- }, e.id)), /* @__PURE__ */ i("div", { ref: f })]
31
+ isStreaming: e.id === l,
32
+ isFailed: e.id === u,
33
+ isLastAssistant: e.id === p,
34
+ onRetry: d
35
+ }, e.id)), /* @__PURE__ */ i("div", { ref: m })]
34
36
  });
35
37
  };
36
38
  //#endregion
@@ -2,6 +2,13 @@ import { FC } from 'react';
2
2
  import { PendingWrite } from '../pendingWrite';
3
3
  interface Props {
4
4
  pendingWrite: PendingWrite;
5
+ /**
6
+ * Approve this exact pending write. Absent when the conversation is not live
7
+ * (history, export) — the card then reads as a record of what was asked.
8
+ */
9
+ onApprove?: (reference: string) => void;
10
+ /** True while the approval is in flight, so the button cannot be double-sent. */
11
+ approving?: boolean;
5
12
  }
6
13
  /**
7
14
  * What the assistant is asking permission to change — taken from the request it
@@ -15,17 +22,25 @@ interface Props {
15
22
  * delete described as an update, and the approval still counts. This card is the
16
23
  * payload.
17
24
  *
18
- * NO APPROVE BUTTON, DELIBERATELY. A button here would have to send "yes" as a
19
- * chat message and let the model decide what that authorises — which is the
20
- * arrangement this card exists to expose, dressed up as a control. The model
21
- * holds the single-use token; until it does not (see `write-confirmation.ts`,
22
- * which names the fix as "the UI holding the approval"), a button would promise
23
- * an authorization boundary the frontend does not have. The user replies in
24
- * their own words, and the card makes sure they know what they are replying to.
25
+ * ★★ IT NOW HAS AN APPROVE BUTTON, AND THAT IS A CHANGE OF FACT, NOT OF TASTE.
25
26
  *
26
- * The confirmation token is never rendered `parseConfirmationRefusal` does
27
- * not even extract it. Echoing it back is what lets the write through, so on
28
- * screen it would be a bypass rather than information.
27
+ * This card deliberately had none. A button would have had to send "yes" as a
28
+ * chat message and let the model decide what that authorised the very
29
+ * arrangement the card existed to expose, dressed up as a control because the
30
+ * model held the single-use token and could paste it back whenever it liked.
31
+ *
32
+ * That is no longer true. The sandbox no longer puts the token in anything the
33
+ * model can read; the refusal carries a reference that NAMES the pending change
34
+ * and authorises nothing. Approval is an out-of-band call to the sandbox
35
+ * (`/write-confirmations/:reference/approve`) that the model is not part of. So
36
+ * the button now promises a boundary that exists.
37
+ *
38
+ * ★ The reference is not a secret and the token is never rendered — the card
39
+ * still never displays anything that could authorise the write on its own.
40
+ *
41
+ * ★ Without a reference (an older sandbox image) the button is not shown at
42
+ * all, and the card falls back to what it always said: reply in your own words.
43
+ * A control that cannot work is worse than no control.
29
44
  */
30
45
  export declare const AssistantPendingWriteCard: FC<Props>;
31
46
  export {};
@@ -1 +1 @@
1
- {"version":3,"file":"AssistantPendingWriteCard.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantPendingWriteCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGpD,UAAU,KAAK;IACb,YAAY,EAAE,YAAY,CAAC;CAC5B;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,eAAO,MAAM,yBAAyB,EAAE,EAAE,CAAC,KAAK,CAgE/C,CAAC"}
1
+ {"version":3,"file":"AssistantPendingWriteCard.d.ts","sourceRoot":"","sources":["../../../../src/shared/assistant/ui/AssistantPendingWriteCard.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC;AAEhC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAGpD,UAAU,KAAK;IACb,YAAY,EAAE,YAAY,CAAC;IAC3B;;;OAGG;IACH,SAAS,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,IAAI,CAAC;IACxC,iFAAiF;IACjF,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AACH,eAAO,MAAM,yBAAyB,EAAE,EAAE,CAAC,KAAK,CA2F/C,CAAC"}
@@ -2,51 +2,65 @@ import { useAssistantTr as e } from "../i18n.js";
2
2
  import { ShieldAlert as t } from "lucide-react";
3
3
  import { jsx as n, jsxs as r } from "react/jsx-runtime";
4
4
  //#region src/shared/assistant/ui/AssistantPendingWriteCard.tsx
5
- var i = ({ pendingWrite: i }) => {
6
- let a = e();
5
+ var i = ({ pendingWrite: i, onApprove: a, approving: o = !1 }) => {
6
+ let s = e(), c = !!i.reference && !!a;
7
7
  return /* @__PURE__ */ r("div", {
8
8
  className: "my-2 overflow-hidden rounded-xl border border-status-warning bg-status-warning/10",
9
9
  "data-testid": "assistant-pending-write",
10
10
  role: "note",
11
- "aria-label": a("pendingWrite.aria", "Change awaiting your approval"),
12
- children: [/* @__PURE__ */ r("div", {
13
- className: "flex items-start gap-2 border-b border-status-warning/40 px-3 py-2",
14
- children: [/* @__PURE__ */ n(t, {
15
- className: "mt-0.5 size-4 flex-shrink-0 text-status-warning",
16
- "aria-hidden": "true"
17
- }), /* @__PURE__ */ r("div", {
18
- className: "min-w-0",
11
+ "aria-label": s("pendingWrite.aria", "Change awaiting your approval"),
12
+ children: [
13
+ /* @__PURE__ */ r("div", {
14
+ className: "flex items-start gap-2 border-b border-status-warning/40 px-3 py-2",
15
+ children: [/* @__PURE__ */ n(t, {
16
+ className: "mt-0.5 size-4 flex-shrink-0 text-status-warning",
17
+ "aria-hidden": "true"
18
+ }), /* @__PURE__ */ r("div", {
19
+ className: "min-w-0",
20
+ children: [/* @__PURE__ */ n("p", {
21
+ className: "text-xs font-semibold text-text-primary",
22
+ children: s("pendingWrite.title", "Nothing has changed yet")
23
+ }), /* @__PURE__ */ n("p", {
24
+ className: "text-[11px] leading-relaxed text-text-secondary",
25
+ children: s("pendingWrite.subtitle", c ? "The assistant asked to make this change and was stopped. Approve it, or say what to change." : "The assistant asked to make this change and was stopped. Reply to approve or decline.")
26
+ })]
27
+ })]
28
+ }),
29
+ /* @__PURE__ */ r("div", {
30
+ className: "px-3 py-2",
19
31
  children: [/* @__PURE__ */ n("p", {
20
- className: "text-xs font-semibold text-text-primary",
21
- children: a("pendingWrite.title", "Nothing has changed yet")
22
- }), /* @__PURE__ */ n("p", {
23
- className: "text-[11px] leading-relaxed text-text-secondary",
24
- children: a("pendingWrite.subtitle", "The assistant asked to make this change and was stopped. Reply to approve or decline.")
32
+ className: "font-mono text-xs text-text-primary",
33
+ "data-testid": "assistant-pending-write-operation",
34
+ children: i.operation
35
+ }), i.values && i.values.length > 0 ? /* @__PURE__ */ n("dl", {
36
+ className: "mt-2 grid grid-cols-[minmax(0,auto)_minmax(0,1fr)] gap-x-3 gap-y-1 text-xs",
37
+ children: i.values.map((e) => /* @__PURE__ */ r("div", {
38
+ className: "contents",
39
+ children: [/* @__PURE__ */ n("dt", {
40
+ className: "truncate text-text-muted",
41
+ children: e.key
42
+ }), /* @__PURE__ */ n("dd", {
43
+ className: "min-w-0 break-words font-medium text-text-primary",
44
+ children: e.value
45
+ })]
46
+ }, e.key))
47
+ }) : /* @__PURE__ */ n("p", {
48
+ className: "mt-1 text-[11px] text-text-muted",
49
+ children: s("pendingWrite.noValues", "No field values were included with this request.")
25
50
  })]
26
- })]
27
- }), /* @__PURE__ */ r("div", {
28
- className: "px-3 py-2",
29
- children: [/* @__PURE__ */ n("p", {
30
- className: "font-mono text-xs text-text-primary",
31
- "data-testid": "assistant-pending-write-operation",
32
- children: i.operation
33
- }), i.values && i.values.length > 0 ? /* @__PURE__ */ n("dl", {
34
- className: "mt-2 grid grid-cols-[minmax(0,auto)_minmax(0,1fr)] gap-x-3 gap-y-1 text-xs",
35
- children: i.values.map((e) => /* @__PURE__ */ r("div", {
36
- className: "contents",
37
- children: [/* @__PURE__ */ n("dt", {
38
- className: "truncate text-text-muted",
39
- children: e.key
40
- }), /* @__PURE__ */ n("dd", {
41
- className: "min-w-0 break-words font-medium text-text-primary",
42
- children: e.value
43
- })]
44
- }, e.key))
45
- }) : /* @__PURE__ */ n("p", {
46
- className: "mt-1 text-[11px] text-text-muted",
47
- children: a("pendingWrite.noValues", "No field values were included with this request.")
48
- })]
49
- })]
51
+ }),
52
+ c ? /* @__PURE__ */ n("div", {
53
+ className: "flex justify-end border-t border-status-warning/40 px-3 py-2",
54
+ children: /* @__PURE__ */ n("button", {
55
+ type: "button",
56
+ onClick: () => a?.(i.reference),
57
+ disabled: o,
58
+ className: "rounded-md bg-action-primary-bg px-3 py-1.5 text-xs font-medium text-action-primary-fg transition-opacity hover:opacity-90 disabled:opacity-60 focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
59
+ "data-testid": "assistant-pending-write-approve",
60
+ children: o ? s("pendingWrite.approving", "Approving…") : s("pendingWrite.approve", "Approve this change")
61
+ })
62
+ }) : null
63
+ ]
50
64
  });
51
65
  };
52
66
  //#endregion