@burdenoff/fe-libs 2026.1028.4 → 2026.1028.6
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/shared/assistant/appControls/grammar.d.ts +2 -0
- package/dist/shared/assistant/appControls/grammar.js +101 -93
- package/dist/shared/assistant/appControls/registry.d.ts +2 -0
- package/dist/shared/assistant/appControls/registry.js +20 -12
- package/dist/shared/assistant/commandCompletions.d.ts +9 -0
- package/dist/shared/assistant/commandCompletions.js +161 -0
- package/dist/shared/assistant/index.d.ts +5 -0
- package/dist/shared/assistant/localUiCommands.d.ts +16 -0
- package/dist/shared/assistant/localUiCommands.js +192 -105
- package/dist/shared/assistant/localeCommands/engine.d.ts +6 -0
- package/dist/shared/assistant/localeCommands/engine.js +212 -116
- package/dist/shared/assistant/ui/AiCreditBalance.d.ts +36 -0
- package/dist/shared/assistant/ui/AiCreditBalance.js +32 -0
- package/dist/shared/assistant/ui/AssistantChatArea.js +1594 -1502
- package/dist/shared/assistant/ui/composer/AssistantComposer.d.ts +8 -0
- package/dist/shared/assistant/ui/composer/AssistantComposer.js +142 -131
- package/dist/shared/assistant/ui/draftCommandCheck.d.ts +7 -0
- package/dist/shared/assistant/ui/draftCommandCheck.js +17 -0
- package/dist/shared/assistant/uiActions/backStack.d.ts +1 -0
- package/dist/shared/assistant/uiActions/backStack.js +13 -5
- package/dist/shared/assistant/uiActions/deixis.d.ts +2 -0
- package/dist/shared/assistant/uiActions/deixis.js +12 -1
- package/dist/shared/assistant/uiActions/draftPathname.d.ts +13 -0
- package/dist/shared/assistant/uiActions/draftPathname.js +31 -0
- package/dist/shared/assistant/uiActions/recordNames.js +33 -30
- package/dist/shared/assistant/useAiCreditStatus.d.ts +18 -0
- package/dist/shared/assistant/useAiCreditStatus.js +40 -0
- package/dist/shared/providers/shell/useAssistantShellLabels.d.ts +10 -0
- package/dist/shared/providers/shell/useAssistantShellLabels.js +9 -1
- package/dist/shared-assistant.js +331 -326
- package/package.json +1 -1
|
@@ -55,6 +55,8 @@ interface Props {
|
|
|
55
55
|
* sandbox while the person is still typing (BOFF-7801).
|
|
56
56
|
*/
|
|
57
57
|
onDraftStart?: () => void;
|
|
58
|
+
/** Additive observer: every text/attachment change, including an empty draft. */
|
|
59
|
+
onDraftChange?: (draft: AssistantComposerDraft) => void;
|
|
58
60
|
/**
|
|
59
61
|
* ★ BOFF-9341: something covers the composer (the Avatar tab). Dictation
|
|
60
62
|
* stops, keeping every word it heard in the draft, and stays stopped: a
|
|
@@ -69,6 +71,12 @@ interface Props {
|
|
|
69
71
|
*/
|
|
70
72
|
onVoiceStateChange?: (state: AssistantComposerVoiceState) => void;
|
|
71
73
|
}
|
|
74
|
+
/** A local draft snapshot; no files are uploaded by observing it. */
|
|
75
|
+
export interface AssistantComposerDraft {
|
|
76
|
+
readonly text: string;
|
|
77
|
+
readonly hasAttachments: boolean;
|
|
78
|
+
readonly dictated: boolean;
|
|
79
|
+
}
|
|
72
80
|
/** What in the composer holds a voice conversation back (`onVoiceStateChange`). */
|
|
73
81
|
export interface AssistantComposerVoiceState {
|
|
74
82
|
readonly committing: boolean;
|
|
@@ -17,69 +17,80 @@ import { useCallback as s, useEffect as c, useLayoutEffect as le, useMemo as ue,
|
|
|
17
17
|
import { ArrowUp as de, Loader2 as fe } from "lucide-react";
|
|
18
18
|
import { jsx as d, jsxs as f } from "react/jsx-runtime";
|
|
19
19
|
//#region src/shared/assistant/ui/composer/AssistantComposer.tsx
|
|
20
|
-
var pe = 200, p = ({ writeAccessDenied: p = !1, onSend: m, disabled: h = !1, readOnly: me = !1, placeholder: he, mode: ge, availableModes: g, attachmentCharsPerFile: _e, onModeChange: ve, auto: ye, onStartVoiceSession: be, onDraftStart: _,
|
|
21
|
-
let
|
|
20
|
+
var pe = 200, p = ({ writeAccessDenied: p = !1, onSend: m, disabled: h = !1, readOnly: me = !1, placeholder: he, mode: ge, availableModes: g, attachmentCharsPerFile: _e, onModeChange: ve, auto: ye, onStartVoiceSession: be, onDraftStart: _, onDraftChange: v, suspendDictation: y = !1, onVoiceStateChange: b }) => {
|
|
21
|
+
let x = r(), { locale: S } = e(), C = h || me, w = l(null), [T, E] = u(""), [xe, D] = u(!1), [O, k] = u(!1), A = l(!1), [j, M] = u(null), N = l(0), { attachments: P, isBusy: Se, preparingCount: Ce, sendBlocker: F, rejection: I, addFiles: L, remove: we, retry: Te, clear: R, clearRejection: Ee, canAddMore: De, commit: z, cancelCommit: B } = ce({ perFileChars: _e }), V = T.trim() !== "" || P.length > 0, H = l(!1), U = l(!1);
|
|
22
22
|
c(() => {
|
|
23
|
-
|
|
24
|
-
}, [
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
}
|
|
23
|
+
V && !H.current ? (H.current = !0, _?.()) : V || (H.current = !1);
|
|
24
|
+
}, [V, _]), c(() => {
|
|
25
|
+
V || (U.current = !1), v?.({
|
|
26
|
+
text: T,
|
|
27
|
+
hasAttachments: P.length > 0,
|
|
28
|
+
dictated: U.current
|
|
29
|
+
});
|
|
30
|
+
}, [
|
|
31
|
+
T,
|
|
32
|
+
P.length,
|
|
33
|
+
V,
|
|
34
|
+
v
|
|
35
|
+
]);
|
|
36
|
+
let W = s((e) => {
|
|
37
|
+
U.current = !0, E((t) => t ? `${t.replace(/\s+$/, "")} ${e}` : e);
|
|
38
|
+
}, []), G = i((e) => e.assistantLanguage), K = n({
|
|
39
|
+
onFinalize: W,
|
|
40
|
+
language: ue(() => te(G, S), [G, S]).tag
|
|
41
|
+
}), q = K.isActive, J = K.interim, Oe = K.stop;
|
|
31
42
|
c(() => {
|
|
32
|
-
!
|
|
43
|
+
!y || !q || (J.trim() !== "" && W(J.trim()), Oe());
|
|
33
44
|
}, [
|
|
34
|
-
|
|
35
|
-
G,
|
|
36
|
-
K,
|
|
45
|
+
y,
|
|
37
46
|
q,
|
|
38
|
-
|
|
47
|
+
J,
|
|
48
|
+
Oe,
|
|
49
|
+
W
|
|
39
50
|
]), c(() => {
|
|
40
|
-
|
|
51
|
+
b?.({
|
|
41
52
|
committing: O,
|
|
42
|
-
dictating:
|
|
53
|
+
dictating: q
|
|
43
54
|
});
|
|
44
55
|
}, [
|
|
45
|
-
|
|
56
|
+
b,
|
|
46
57
|
O,
|
|
47
|
-
|
|
58
|
+
q
|
|
48
59
|
]);
|
|
49
|
-
let
|
|
50
|
-
|
|
51
|
-
let
|
|
52
|
-
c(() => (
|
|
53
|
-
|
|
60
|
+
let ke = he ?? x("composer.placeholder", "Ask me anything…"), Ae = T.trim(), Y = a(P), X = P.filter((e) => e.status === "error"), Z = (Ae.length > 0 || Y.length > 0) && !C && !O && F === null, je = Y.some((e) => !e.fileId && !e.inlineOnly), Me = l(C);
|
|
61
|
+
Me.current = C;
|
|
62
|
+
let Q = l(!0);
|
|
63
|
+
c(() => (Q.current = !0, () => {
|
|
64
|
+
Q.current = !1;
|
|
54
65
|
}), []), le(() => {
|
|
55
|
-
let e =
|
|
66
|
+
let e = w.current;
|
|
56
67
|
e && (e.style.height = "auto", e.style.height = `${Math.min(e.scrollHeight, pe)}px`);
|
|
57
|
-
}, [
|
|
58
|
-
let
|
|
59
|
-
if (!
|
|
60
|
-
|
|
61
|
-
let e =
|
|
62
|
-
if (
|
|
63
|
-
m(e,
|
|
68
|
+
}, [T]);
|
|
69
|
+
let $ = s(async () => {
|
|
70
|
+
if (!Z || A.current) return;
|
|
71
|
+
K.isActive && K.stop();
|
|
72
|
+
let e = T.trim();
|
|
73
|
+
if (M(null), !je) {
|
|
74
|
+
m(e, Y), E(""), R();
|
|
64
75
|
return;
|
|
65
76
|
}
|
|
66
77
|
let t = i.getState().activeConversationId;
|
|
67
|
-
|
|
78
|
+
A.current = !0, k(!0);
|
|
68
79
|
try {
|
|
69
|
-
let n = await
|
|
70
|
-
if (!
|
|
80
|
+
let n = await z();
|
|
81
|
+
if (!Q.current) {
|
|
71
82
|
n.ok && await n.rollback();
|
|
72
83
|
return;
|
|
73
84
|
}
|
|
74
85
|
if (!n.ok) {
|
|
75
|
-
n.cancelled ||
|
|
86
|
+
n.cancelled || M({
|
|
76
87
|
kind: "failed",
|
|
77
88
|
failures: n.failures
|
|
78
89
|
});
|
|
79
90
|
return;
|
|
80
91
|
}
|
|
81
|
-
if (
|
|
82
|
-
await n.rollback(),
|
|
92
|
+
if (Me.current) {
|
|
93
|
+
await n.rollback(), Q.current && M({
|
|
83
94
|
kind: "busy",
|
|
84
95
|
failures: []
|
|
85
96
|
});
|
|
@@ -87,67 +98,67 @@ var pe = 200, p = ({ writeAccessDenied: p = !1, onSend: m, disabled: h = !1, rea
|
|
|
87
98
|
}
|
|
88
99
|
let r = i.getState();
|
|
89
100
|
if (!(r.activeConversationId === t && (t === null || r.conversations.some((e) => e.id === t)))) {
|
|
90
|
-
await n.rollback(),
|
|
101
|
+
await n.rollback(), Q.current && M({
|
|
91
102
|
kind: "moved",
|
|
92
103
|
failures: []
|
|
93
104
|
});
|
|
94
105
|
return;
|
|
95
106
|
}
|
|
96
|
-
m(e, a(n.attachments)), n.handedOver(),
|
|
107
|
+
m(e, a(n.attachments)), n.handedOver(), E(""), R();
|
|
97
108
|
} finally {
|
|
98
|
-
|
|
109
|
+
A.current = !1, Q.current && k(!1);
|
|
99
110
|
}
|
|
100
111
|
}, [
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
112
|
+
Z,
|
|
113
|
+
je,
|
|
114
|
+
z,
|
|
104
115
|
m,
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
]),
|
|
110
|
-
|
|
111
|
-
}, [
|
|
116
|
+
T,
|
|
117
|
+
Y,
|
|
118
|
+
R,
|
|
119
|
+
K
|
|
120
|
+
]), Ne = s(() => {
|
|
121
|
+
B(), w.current?.focus();
|
|
122
|
+
}, [B]);
|
|
112
123
|
c(() => {
|
|
113
|
-
|
|
114
|
-
}, [
|
|
115
|
-
let
|
|
116
|
-
if (e.kind === "busy") return
|
|
117
|
-
if (e.kind === "moved") return
|
|
124
|
+
M(null);
|
|
125
|
+
}, [P.length]);
|
|
126
|
+
let Pe = (e) => {
|
|
127
|
+
if (e.kind === "busy") return x("attachments.saveBusy", "The assistant started another reply, so nothing was sent. Your message and files are still here.");
|
|
128
|
+
if (e.kind === "moved") return x("attachments.saveMoved", "You switched conversations while the files were being saved, so nothing was sent. Your message and files are still here.");
|
|
118
129
|
let { failures: t } = e;
|
|
119
|
-
if (t.some((e) => e.code === o.quotaExceeded || e.code === o.quotaNotProvisioned)) return `${
|
|
120
|
-
let n = t[0], r =
|
|
121
|
-
return `${t.length <= 1 ?
|
|
122
|
-
},
|
|
123
|
-
e.key === "Enter" && !e.shiftKey && (e.preventDefault(),
|
|
124
|
-
}, [
|
|
130
|
+
if (t.some((e) => e.code === o.quotaExceeded || e.code === o.quotaNotProvisioned)) return `${x("attachments.quotaFull", "File storage is full or not set up for this workspace, so the attachments couldn't be saved. Nothing was sent.")} ${x("attachments.retrySend", "Press Send to try again, or remove the file.")}`;
|
|
131
|
+
let n = t[0], r = P.find((e) => e.id === n?.id)?.filename ?? "";
|
|
132
|
+
return `${t.length <= 1 ? x("attachments.saveFailedOne", "{{name}} couldn't be saved, so nothing was sent.", { name: r }) : x("attachments.saveFailedMany", "{{count}} attachments couldn't be saved, so nothing was sent.", { count: t.length })} ${x("attachments.retrySend", "Press Send to try again, or remove the file.")}`;
|
|
133
|
+
}, Fe = s((e) => {
|
|
134
|
+
e.key === "Enter" && !e.shiftKey && (e.preventDefault(), $());
|
|
135
|
+
}, [$]), Ie = s((e) => {
|
|
125
136
|
let t = Array.from(e.clipboardData?.files ?? []);
|
|
126
|
-
t.length !== 0 && (e.preventDefault(),
|
|
127
|
-
}, [
|
|
128
|
-
Array.from(e.dataTransfer?.types ?? []).includes("Files") && (
|
|
129
|
-
}, []),
|
|
130
|
-
|
|
131
|
-
}, []), Re = s((e) => {
|
|
132
|
-
Array.from(e.dataTransfer?.types ?? []).includes("Files") && e.preventDefault();
|
|
137
|
+
t.length !== 0 && (e.preventDefault(), L(t));
|
|
138
|
+
}, [L]), Le = s((e) => {
|
|
139
|
+
Array.from(e.dataTransfer?.types ?? []).includes("Files") && (N.current += 1, D(!0));
|
|
140
|
+
}, []), Re = s(() => {
|
|
141
|
+
N.current = Math.max(0, N.current - 1), N.current === 0 && D(!1);
|
|
133
142
|
}, []), ze = s((e) => {
|
|
134
|
-
|
|
135
|
-
}, [
|
|
143
|
+
Array.from(e.dataTransfer?.types ?? []).includes("Files") && e.preventDefault();
|
|
144
|
+
}, []), Be = s((e) => {
|
|
145
|
+
e.preventDefault(), N.current = 0, D(!1), L(e.dataTransfer?.files ?? null);
|
|
146
|
+
}, [L]), Ve = (e) => {
|
|
136
147
|
switch (e) {
|
|
137
|
-
case "too-many": return
|
|
138
|
-
case "too-large": return
|
|
139
|
-
case "empty": return
|
|
140
|
-
case "unreadable": return
|
|
141
|
-
case "unsupported-image": return
|
|
142
|
-
case "too-large-to-save": return
|
|
148
|
+
case "too-many": return x("attachments.tooMany", "You can attach up to {{max}} files per message.", { max: 5 });
|
|
149
|
+
case "too-large": return x("attachments.tooLarge", "That file is larger than 10 MB.");
|
|
150
|
+
case "empty": return x("attachments.empty", "That file is empty.");
|
|
151
|
+
case "unreadable": return x("attachments.unreadable", "That file could not be read.");
|
|
152
|
+
case "unsupported-image": return x("attachments.unsupportedImage", "This device can't read that image format, so it can't be resized to send. Save it as JPEG and try again.");
|
|
153
|
+
case "too-large-to-save": return x("attachments.tooLargeToSave", "That file is over 5 MB, so it can't be saved to Files, and no text could be read from it.");
|
|
143
154
|
}
|
|
144
|
-
},
|
|
145
|
-
switch (
|
|
146
|
-
case "not-allowed": return
|
|
147
|
-
case "audio-capture": return
|
|
148
|
-
case "network": return
|
|
149
|
-
case "language-not-supported": return
|
|
150
|
-
case "unknown": return
|
|
155
|
+
}, He = (() => {
|
|
156
|
+
switch (K.error) {
|
|
157
|
+
case "not-allowed": return x("voice.denied", "Microphone access is blocked. Allow it in your browser settings to dictate.");
|
|
158
|
+
case "audio-capture": return x("voice.noMic", "No microphone was found.");
|
|
159
|
+
case "network": return x("voice.network", "Speech recognition is offline right now.");
|
|
160
|
+
case "language-not-supported": return x("voice.languageNotSupported", "This browser cannot recognise spoken {{language}}. Try a different browser, or type instead.", { language: ee(K.language, S) });
|
|
161
|
+
case "unknown": return x("voice.failed", "Dictation stopped unexpectedly.");
|
|
151
162
|
default: return null;
|
|
152
163
|
}
|
|
153
164
|
})();
|
|
@@ -155,59 +166,59 @@ var pe = 200, p = ({ writeAccessDenied: p = !1, onSend: m, disabled: h = !1, rea
|
|
|
155
166
|
className: "flex-shrink-0 px-3 pb-3 pt-1.5",
|
|
156
167
|
children: [
|
|
157
168
|
/* @__PURE__ */ f("div", {
|
|
158
|
-
onDragEnter:
|
|
159
|
-
onDragLeave:
|
|
160
|
-
onDragOver:
|
|
161
|
-
onDrop:
|
|
162
|
-
className: `rounded-2xl border p-2 shadow-sm transition-colors focus-within:border-action-primary-bg focus-within:ring-2 focus-within:ring-action-primary-bg/15 ${
|
|
169
|
+
onDragEnter: Le,
|
|
170
|
+
onDragLeave: Re,
|
|
171
|
+
onDragOver: ze,
|
|
172
|
+
onDrop: Be,
|
|
173
|
+
className: `rounded-2xl border p-2 shadow-sm transition-colors focus-within:border-action-primary-bg focus-within:ring-2 focus-within:ring-action-primary-bg/15 ${xe ? "border-action-primary-bg border-dashed bg-action-primary-bg/5" : "border-border-default bg-bg-sunken"}`,
|
|
163
174
|
"data-testid": "assistant-composer",
|
|
164
175
|
children: [
|
|
165
176
|
/* @__PURE__ */ d(re, {
|
|
166
|
-
attachments:
|
|
177
|
+
attachments: P,
|
|
167
178
|
onRemove: we,
|
|
168
179
|
onRetry: Te,
|
|
169
|
-
disabled:
|
|
180
|
+
disabled: C || O,
|
|
170
181
|
preparingCount: Ce
|
|
171
182
|
}),
|
|
172
183
|
/* @__PURE__ */ f("div", {
|
|
173
184
|
className: "flex items-end gap-2",
|
|
174
185
|
children: [
|
|
175
186
|
/* @__PURE__ */ d(ne, {
|
|
176
|
-
onFiles:
|
|
187
|
+
onFiles: L,
|
|
177
188
|
canAddMore: De,
|
|
178
|
-
disabled:
|
|
189
|
+
disabled: C || O,
|
|
179
190
|
showLabel: !0
|
|
180
191
|
}),
|
|
181
192
|
/* @__PURE__ */ d("textarea", {
|
|
182
|
-
ref:
|
|
183
|
-
value:
|
|
184
|
-
onChange: (e) =>
|
|
185
|
-
onKeyDown:
|
|
186
|
-
onPaste:
|
|
187
|
-
disabled:
|
|
193
|
+
ref: w,
|
|
194
|
+
value: T,
|
|
195
|
+
onChange: (e) => E(e.target.value),
|
|
196
|
+
onKeyDown: Fe,
|
|
197
|
+
onPaste: Ie,
|
|
198
|
+
disabled: C,
|
|
188
199
|
readOnly: O,
|
|
189
200
|
"aria-busy": O || void 0,
|
|
190
|
-
placeholder:
|
|
201
|
+
placeholder: xe ? x("composer.dropHere", "Drop files to attach") : ke,
|
|
191
202
|
rows: 1,
|
|
192
203
|
className: "min-h-[36px] flex-1 resize-none self-center bg-transparent px-1 py-2 text-[15px] leading-relaxed text-text-primary placeholder:text-text-muted focus:outline-none disabled:opacity-50",
|
|
193
|
-
"aria-label":
|
|
204
|
+
"aria-label": x("chatInput.ariaLabel", "Message input"),
|
|
194
205
|
"data-testid": "assistant-input"
|
|
195
206
|
}),
|
|
196
|
-
|
|
197
|
-
isListening:
|
|
198
|
-
isStarting:
|
|
199
|
-
onToggle:
|
|
200
|
-
disabled:
|
|
207
|
+
K.isSupported && /* @__PURE__ */ d(ae, {
|
|
208
|
+
isListening: K.isListening,
|
|
209
|
+
isStarting: K.isStarting,
|
|
210
|
+
onToggle: K.toggle,
|
|
211
|
+
disabled: C || O
|
|
201
212
|
}),
|
|
202
|
-
be &&
|
|
213
|
+
be && Ae.length === 0 && P.length === 0 && !K.isActive ? /* @__PURE__ */ d(se, {
|
|
203
214
|
onStart: be,
|
|
204
|
-
disabled:
|
|
215
|
+
disabled: C || O
|
|
205
216
|
}) : /* @__PURE__ */ d("button", {
|
|
206
217
|
type: "button",
|
|
207
|
-
onClick: () => void
|
|
208
|
-
disabled: !
|
|
209
|
-
className: `flex size-9 flex-shrink-0 items-center justify-center rounded-full shadow-sm transition-all focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${
|
|
210
|
-
"aria-label":
|
|
218
|
+
onClick: () => void $(),
|
|
219
|
+
disabled: !Z,
|
|
220
|
+
className: `flex size-9 flex-shrink-0 items-center justify-center rounded-full shadow-sm transition-all focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong ${Z ? "bg-action-primary-bg text-action-primary-text hover:scale-105 hover:bg-action-primary-bg-hover" : "bg-bg-elevated text-text-muted"}`,
|
|
221
|
+
"aria-label": x("chatInput.send", "Send message"),
|
|
211
222
|
"data-testid": "assistant-send",
|
|
212
223
|
children: h || Se || O ? /* @__PURE__ */ d(fe, { className: "size-4 motion-safe:animate-spin" }) : /* @__PURE__ */ d(de, { className: "size-4" })
|
|
213
224
|
})
|
|
@@ -219,7 +230,7 @@ var pe = 200, p = ({ writeAccessDenied: p = !1, onSend: m, disabled: h = !1, rea
|
|
|
219
230
|
mode: ge,
|
|
220
231
|
availableModes: g,
|
|
221
232
|
onModeChange: ve,
|
|
222
|
-
disabled:
|
|
233
|
+
disabled: C || O,
|
|
223
234
|
auto: ye
|
|
224
235
|
})
|
|
225
236
|
})
|
|
@@ -228,13 +239,13 @@ var pe = 200, p = ({ writeAccessDenied: p = !1, onSend: m, disabled: h = !1, rea
|
|
|
228
239
|
p ? /* @__PURE__ */ d("p", {
|
|
229
240
|
className: "mt-1.5 px-1 text-center text-[11px] text-status-warning",
|
|
230
241
|
"data-testid": "assistant-write-access-warning",
|
|
231
|
-
children:
|
|
242
|
+
children: x("composer.writeAccessDenied", "Changes may not save — your role in this workspace does not currently allow edits. You can still plan and review an action.")
|
|
232
243
|
}) : null,
|
|
233
244
|
/* @__PURE__ */ d("div", {
|
|
234
245
|
className: "mt-1.5 px-1 text-center text-[11px]",
|
|
235
246
|
"aria-live": "polite",
|
|
236
247
|
children: O ? /* @__PURE__ */ d(t, {
|
|
237
|
-
onDismiss:
|
|
248
|
+
onDismiss: Ne,
|
|
238
249
|
children: /* @__PURE__ */ f("p", {
|
|
239
250
|
className: "flex items-center justify-center gap-2 text-text-muted",
|
|
240
251
|
"data-testid": "assistant-commit-status",
|
|
@@ -243,46 +254,46 @@ var pe = 200, p = ({ writeAccessDenied: p = !1, onSend: m, disabled: h = !1, rea
|
|
|
243
254
|
className: "size-3 motion-safe:animate-spin",
|
|
244
255
|
"aria-hidden": "true"
|
|
245
256
|
}),
|
|
246
|
-
/* @__PURE__ */ d("span", { children:
|
|
257
|
+
/* @__PURE__ */ d("span", { children: x("attachments.saving", "Saving your attachments…") }),
|
|
247
258
|
/* @__PURE__ */ d("button", {
|
|
248
259
|
type: "button",
|
|
249
|
-
onClick:
|
|
260
|
+
onClick: Ne,
|
|
250
261
|
className: "rounded text-text-primary underline underline-offset-2 hover:text-action-primary-bg focus:outline-none focus-visible:ring-2 focus-visible:ring-border-strong",
|
|
251
262
|
"data-testid": "assistant-commit-cancel",
|
|
252
|
-
children:
|
|
263
|
+
children: x("attachments.cancelSaving", "Cancel")
|
|
253
264
|
})
|
|
254
265
|
]
|
|
255
266
|
})
|
|
256
|
-
}) :
|
|
267
|
+
}) : j ? /* @__PURE__ */ d("p", {
|
|
257
268
|
className: "text-status-error-text",
|
|
258
269
|
role: "alert",
|
|
259
270
|
"data-testid": "assistant-commit-failed",
|
|
260
|
-
children:
|
|
261
|
-
}) :
|
|
271
|
+
children: Pe(j)
|
|
272
|
+
}) : K.isStarting && !K.isListening ? /* @__PURE__ */ d("p", {
|
|
262
273
|
className: "text-text-muted",
|
|
263
274
|
"data-testid": "assistant-voice-starting",
|
|
264
|
-
children:
|
|
265
|
-
}) :
|
|
275
|
+
children: x("voice.starting", "Starting the microphone…")
|
|
276
|
+
}) : K.isListening ? /* @__PURE__ */ f("p", {
|
|
266
277
|
className: "text-status-error-text",
|
|
267
278
|
"data-testid": "assistant-voice-status",
|
|
268
|
-
children: [/* @__PURE__ */ d(oe, {}),
|
|
269
|
-
}) :
|
|
279
|
+
children: [/* @__PURE__ */ d(oe, {}), K.interim || x("voice.listening", "Listening… speak now, tap the square to stop")]
|
|
280
|
+
}) : He ? /* @__PURE__ */ d("p", {
|
|
270
281
|
className: "text-status-error-text",
|
|
271
282
|
"data-testid": "assistant-voice-error",
|
|
272
|
-
children:
|
|
273
|
-
}) :
|
|
283
|
+
children: He
|
|
284
|
+
}) : I ? /* @__PURE__ */ d("button", {
|
|
274
285
|
type: "button",
|
|
275
286
|
onClick: Ee,
|
|
276
287
|
className: "text-status-error-text underline-offset-2 hover:underline",
|
|
277
288
|
"data-testid": "assistant-attachment-rejection",
|
|
278
|
-
children:
|
|
279
|
-
}) :
|
|
289
|
+
children: Ve(I)
|
|
290
|
+
}) : F === "failed" ? /* @__PURE__ */ d("p", {
|
|
280
291
|
className: "text-status-error-text",
|
|
281
292
|
"data-testid": "assistant-attachment-blocked",
|
|
282
|
-
children:
|
|
293
|
+
children: X.length === 1 ? x("attachments.blockedOne", "{{name}} didn't upload. Retry or remove it before sending.", { name: X[0].filename }) : x("attachments.blockedMany", "{{count}} attachments didn't upload. Retry or remove them before sending.", { count: X.length })
|
|
283
294
|
}) : /* @__PURE__ */ d("p", {
|
|
284
295
|
className: "text-text-muted",
|
|
285
|
-
children:
|
|
296
|
+
children: x("composer.hint", "Enter to send · Shift+Enter for newline · drag or paste files to attach")
|
|
286
297
|
})
|
|
287
298
|
})
|
|
288
299
|
]
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/** Keep speculative grammar work out of the keystroke's React effect. */
|
|
2
|
+
export declare const DRAFT_COMMAND_CHECK_DELAY_MS = 120;
|
|
3
|
+
/** A trailing check; new edits, cleared drafts and unmounts cancel stale work. */
|
|
4
|
+
export declare function createDraftCommandCheck(): {
|
|
5
|
+
cancel: () => void;
|
|
6
|
+
schedule(check: () => void): void;
|
|
7
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
//#region src/shared/assistant/ui/draftCommandCheck.ts
|
|
2
|
+
var e = 120;
|
|
3
|
+
function t() {
|
|
4
|
+
let e, t = () => {
|
|
5
|
+
e !== void 0 && clearTimeout(e), e = void 0;
|
|
6
|
+
};
|
|
7
|
+
return {
|
|
8
|
+
cancel: t,
|
|
9
|
+
schedule(n) {
|
|
10
|
+
t(), e = setTimeout(() => {
|
|
11
|
+
e = void 0, n();
|
|
12
|
+
}, 120);
|
|
13
|
+
}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
//#endregion
|
|
17
|
+
export { e as DRAFT_COMMAND_CHECK_DELAY_MS, t as createDraftCommandCheck };
|
|
@@ -20,6 +20,7 @@ export interface BackStack {
|
|
|
20
20
|
pop: () => BackEntry | null;
|
|
21
21
|
clear: () => void;
|
|
22
22
|
size: () => number;
|
|
23
|
+
subscribe: (listener: () => void) => () => void;
|
|
23
24
|
}
|
|
24
25
|
export declare function createBackStack(capacity?: number): BackStack;
|
|
25
26
|
/** The panel's stack: one per tab. */
|
|
@@ -2,21 +2,29 @@ import { pathnameOf as e } from "./navigationOutcome.js";
|
|
|
2
2
|
//#region src/shared/assistant/uiActions/backStack.ts
|
|
3
3
|
var t = 10;
|
|
4
4
|
function n(t = 10) {
|
|
5
|
-
let n = []
|
|
5
|
+
let n = [], r = /* @__PURE__ */ new Set(), i = () => {
|
|
6
|
+
for (let e of [...r]) e();
|
|
7
|
+
};
|
|
6
8
|
return {
|
|
7
9
|
push: (r) => {
|
|
8
10
|
n.push({
|
|
9
11
|
...r,
|
|
10
12
|
fromPath: e(r.fromPath),
|
|
11
13
|
toPath: e(r.toPath)
|
|
12
|
-
}), n.length > t && (n = n.slice(n.length - t));
|
|
14
|
+
}), n.length > t && (n = n.slice(n.length - t)), i();
|
|
13
15
|
},
|
|
14
16
|
top: () => n[n.length - 1] ?? null,
|
|
15
|
-
pop: () =>
|
|
17
|
+
pop: () => {
|
|
18
|
+
let e = n.pop() ?? null;
|
|
19
|
+
return e && i(), e;
|
|
20
|
+
},
|
|
16
21
|
clear: () => {
|
|
17
|
-
n = [];
|
|
22
|
+
n.length !== 0 && (n = [], i());
|
|
18
23
|
},
|
|
19
|
-
size: () => n.length
|
|
24
|
+
size: () => n.length,
|
|
25
|
+
subscribe: (e) => (r.add(e), () => {
|
|
26
|
+
r.delete(e);
|
|
27
|
+
})
|
|
20
28
|
};
|
|
21
29
|
}
|
|
22
30
|
var r = n();
|
|
@@ -26,3 +26,5 @@ export type ChoiceRequest =
|
|
|
26
26
|
context: string;
|
|
27
27
|
};
|
|
28
28
|
export declare function parseChoice(utterance: string): ChoiceRequest | null;
|
|
29
|
+
/** Reuse the send grammar when deciding whether a typed prefix may be a follow-up. */
|
|
30
|
+
export declare function navigationPrefixPatterns(back: boolean, navigation: boolean, choice: boolean): readonly RegExp[];
|
|
@@ -50,5 +50,16 @@ function u(e) {
|
|
|
50
50
|
context: (r[1] ?? "").trim()
|
|
51
51
|
} : null;
|
|
52
52
|
}
|
|
53
|
+
function d(n, r, i) {
|
|
54
|
+
return [
|
|
55
|
+
...n ? e : [],
|
|
56
|
+
...r ? t : [],
|
|
57
|
+
...i ? [
|
|
58
|
+
s,
|
|
59
|
+
c,
|
|
60
|
+
l
|
|
61
|
+
] : []
|
|
62
|
+
];
|
|
63
|
+
}
|
|
53
64
|
//#endregion
|
|
54
|
-
export { e as BACK_GRAMMAR, n as isBackRequest, r as isThereRequest, u as parseChoice };
|
|
65
|
+
export { e as BACK_GRAMMAR, n as isBackRequest, r as isThereRequest, d as navigationPrefixPatterns, u as parseChoice };
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/** The panel may live outside a Router; observe paths without polling. */
|
|
2
|
+
type PathSource = Pick<EventTarget, 'addEventListener' | 'removeEventListener'> & {
|
|
3
|
+
location: Pick<Location, 'pathname'>;
|
|
4
|
+
history?: Pick<History, 'pushState' | 'replaceState'>;
|
|
5
|
+
};
|
|
6
|
+
/**
|
|
7
|
+
* Only pathnames are compared. History arguments/state, query strings and
|
|
8
|
+
* hashes are passed through untouched and are never retained or emitted.
|
|
9
|
+
* Multiple panels share one observer; the last cleanup restores our wrappers
|
|
10
|
+
* only if another integration has not replaced them in the meantime.
|
|
11
|
+
*/
|
|
12
|
+
export declare function subscribeDraftPathname(source: PathSource, listener: () => void): () => void;
|
|
13
|
+
export {};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
//#region src/shared/assistant/uiActions/draftPathname.ts
|
|
2
|
+
var e = /* @__PURE__ */ new WeakMap();
|
|
3
|
+
function t(t, n) {
|
|
4
|
+
let r = e.get(t);
|
|
5
|
+
if (!r) {
|
|
6
|
+
let n = /* @__PURE__ */ new Set(), i = t.location.pathname, a = () => {
|
|
7
|
+
let e = t.location.pathname;
|
|
8
|
+
if (e !== i) {
|
|
9
|
+
i = e;
|
|
10
|
+
for (let e of [...n]) e();
|
|
11
|
+
}
|
|
12
|
+
}, o = t.history, s = o?.pushState, c = o?.replaceState, l = (e) => function(...t) {
|
|
13
|
+
let n = e.apply(this, t);
|
|
14
|
+
return queueMicrotask(a), n;
|
|
15
|
+
}, u = typeof s == "function" ? l(s) : void 0, d = typeof c == "function" ? l(c) : void 0;
|
|
16
|
+
o && u && (o.pushState = u), o && d && (o.replaceState = d), t.addEventListener("popstate", a), r = {
|
|
17
|
+
listeners: n,
|
|
18
|
+
dispose: () => {
|
|
19
|
+
t.removeEventListener("popstate", a), o && u && o.pushState === u && s && (o.pushState = s), o && d && o.replaceState === d && c && (o.replaceState = c);
|
|
20
|
+
}
|
|
21
|
+
}, e.set(t, r);
|
|
22
|
+
}
|
|
23
|
+
let i = r, a = () => n();
|
|
24
|
+
i.listeners.add(a);
|
|
25
|
+
let o = !0;
|
|
26
|
+
return () => {
|
|
27
|
+
o && (o = !1, i.listeners.delete(a), i.listeners.size === 0 && (i.dispose(), e.delete(t)));
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
export { t as subscribeDraftPathname };
|