@hachej/boring-agent 0.1.104 → 0.1.107
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/{chunk-K25PK5EC.js → chunk-3JFPS2O6.js} +1 -0
- package/dist/{chunk-JNEKOVMJ.js → chunk-6OANSUEI.js} +1 -1
- package/dist/{chunk-4IQ4HHBG.js → chunk-7XAOVFSN.js} +7 -0
- package/dist/{chunk-I7KFNGB4.js → chunk-GS4ADE34.js} +877 -349
- package/dist/{chunk-BTYOMR7W.js → chunk-KDXIXVF6.js} +5179 -3668
- package/dist/{chunk-6DRHERVK.js → chunk-MVKXLMH3.js} +44 -2
- package/dist/chunk-YTUZFKB3.js +78 -0
- package/dist/core/index.d.ts +5 -5
- package/dist/core/index.js +2 -2
- package/dist/{createHarness-POZ4AXCZ.js → createHarness-AHWSC36D.js} +3 -3
- package/dist/{errors-DH7C01Pm.d.ts → errors-CEU4iujR.d.ts} +59 -4
- package/dist/{file-search-qcD5zItr.d.ts → file-search-BGUHnW9o.d.ts} +3 -3
- package/dist/front/index.d.ts +43 -7
- package/dist/front/index.js +1505 -729
- package/dist/front/styles.css +109 -15
- package/dist/{harness-Dcd08yKr.d.ts → harness-Ct0e4RWc.d.ts} +6 -3
- package/dist/{lease-DffrPrQn.d.ts → lease-nASWv2tU.d.ts} +1 -1
- package/dist/{piChatEvent-iNSXiFQq.d.ts → piChatEvent-BUWIzw5l.d.ts} +67 -36
- package/dist/{piChatSessionService-DQSQ_kWZ.d.ts → piChatSessionService-nvroRAVk.d.ts} +13 -11
- package/dist/server/agent-host/testing/gatewayConformance.d.ts +6 -5
- package/dist/server/agent-host/testing/gatewayConformance.js +57 -8
- package/dist/server/index.d.ts +207 -243
- package/dist/server/index.js +15 -9
- package/dist/server/worker/index.js +7 -7
- package/dist/shared/index.d.ts +34 -28
- package/dist/shared/index.js +8 -8
- package/dist/{types-B1xDlBSo.d.ts → types-B7-PN5jV.d.ts} +75 -23
- package/docs/AGENT_GATEWAY_V0.md +40 -2
- package/docs/ERROR_CODES.md +2 -1
- package/docs/README.md +1 -0
- package/docs/SESSION_IDENTITY.md +91 -0
- package/docs/tools.md +4 -0
- package/package.json +11 -10
- package/dist/chunk-WSQ5QNIY.js +0 -18
package/dist/front/index.js
CHANGED
|
@@ -20,6 +20,7 @@ import {
|
|
|
20
20
|
} from "../chunk-2BGLZZ7T.js";
|
|
21
21
|
import {
|
|
22
22
|
AGENT_GATEWAY_ERROR_CODES,
|
|
23
|
+
AgentGatewayErrorCode,
|
|
23
24
|
CommandReceiptSchema,
|
|
24
25
|
FollowUpReceiptSchema,
|
|
25
26
|
PiChatSnapshotSchema,
|
|
@@ -31,11 +32,13 @@ import {
|
|
|
31
32
|
WORKSPACE_COMMAND_NOTIFY_EVENT,
|
|
32
33
|
extractToolUiMetadata,
|
|
33
34
|
sanitizeToolUiMetadata
|
|
34
|
-
} from "../chunk-
|
|
35
|
-
import
|
|
35
|
+
} from "../chunk-MVKXLMH3.js";
|
|
36
|
+
import {
|
|
37
|
+
safeRandomUUID
|
|
38
|
+
} from "../chunk-YGRQ4Q5P.js";
|
|
36
39
|
import {
|
|
37
40
|
ErrorCode
|
|
38
|
-
} from "../chunk-
|
|
41
|
+
} from "../chunk-3JFPS2O6.js";
|
|
39
42
|
|
|
40
43
|
// src/front/upload/uploadFile.ts
|
|
41
44
|
function readAsDataUrl(file) {
|
|
@@ -47,12 +50,16 @@ function readAsDataUrl(file) {
|
|
|
47
50
|
});
|
|
48
51
|
}
|
|
49
52
|
async function uploadFile(file, opts = {}) {
|
|
50
|
-
const { apiBaseUrl = "", workspaceRequestId, directory, sourcePath, responseUrl = "markdown", fetch: fetchImpl = globalThis.fetch } = opts;
|
|
53
|
+
const { apiBaseUrl = "", workspaceRequestId, requestHeaders, directory, sourcePath, responseUrl = "markdown", fetch: fetchImpl = globalThis.fetch } = opts;
|
|
51
54
|
const dataUrl = await readAsDataUrl(file);
|
|
52
55
|
const comma = dataUrl.indexOf(",");
|
|
53
56
|
const contentBase64 = comma >= 0 ? dataUrl.slice(comma + 1) : "";
|
|
54
|
-
const headers =
|
|
55
|
-
|
|
57
|
+
const headers = new Headers();
|
|
58
|
+
for (const [name, value] of Object.entries(requestHeaders ?? {})) {
|
|
59
|
+
if (value !== void 0) headers.set(name, value);
|
|
60
|
+
}
|
|
61
|
+
headers.set("content-type", "application/json");
|
|
62
|
+
if (workspaceRequestId) headers.set("x-boring-workspace-id", workspaceRequestId);
|
|
56
63
|
const base = apiBaseUrl.replace(/\/$/, "");
|
|
57
64
|
const res = await fetchImpl(`${base}/api/v1/files/upload`, {
|
|
58
65
|
method: "POST",
|
|
@@ -85,7 +92,7 @@ function rawWorkspaceFileUrl(path, opts) {
|
|
|
85
92
|
}
|
|
86
93
|
|
|
87
94
|
// src/front/chat/PiChatPanel.tsx
|
|
88
|
-
import { lazy, Suspense, useCallback as
|
|
95
|
+
import { lazy, Suspense, useCallback as useCallback19, useEffect as useEffect23, useMemo as useMemo17, useRef as useRef18, useState as useState22 } from "react";
|
|
89
96
|
|
|
90
97
|
// src/front/chatPanelSettings.ts
|
|
91
98
|
var DEFAULT_THINKING = "medium";
|
|
@@ -280,6 +287,14 @@ function createCommandRegistry(initial) {
|
|
|
280
287
|
}
|
|
281
288
|
|
|
282
289
|
// src/front/slashCommands/builtins.ts
|
|
290
|
+
var MAX_RELOAD_MODEL_MESSAGE = 2e3;
|
|
291
|
+
function reloadResultForModel(message) {
|
|
292
|
+
const body = message.trim() || "No result reported.";
|
|
293
|
+
const bounded = body.length > MAX_RELOAD_MODEL_MESSAGE ? `${body.slice(0, MAX_RELOAD_MODEL_MESSAGE)}
|
|
294
|
+
\u2026 (truncated)` : body;
|
|
295
|
+
return `/reload result:
|
|
296
|
+
${bounded}`;
|
|
297
|
+
}
|
|
283
298
|
var builtinCommands = [
|
|
284
299
|
{
|
|
285
300
|
name: "reset",
|
|
@@ -301,9 +316,9 @@ var builtinCommands = [
|
|
|
301
316
|
name: "reload",
|
|
302
317
|
description: "Reload agent plugins",
|
|
303
318
|
clickBehavior: "execute",
|
|
304
|
-
handler(_, ctx) {
|
|
305
|
-
|
|
306
|
-
return
|
|
319
|
+
async handler(_, ctx) {
|
|
320
|
+
const message = ctx.pluginUpdate ? await ctx.pluginUpdate.run() : await ctx.reloadAgentPlugins();
|
|
321
|
+
return { message, modelMessage: reloadResultForModel(message) };
|
|
307
322
|
}
|
|
308
323
|
},
|
|
309
324
|
{
|
|
@@ -542,7 +557,7 @@ import { useCallback, useState as useState3 } from "react";
|
|
|
542
557
|
import { Button as Button4 } from "@hachej/boring-ui-kit";
|
|
543
558
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
544
559
|
function CodeBlock({
|
|
545
|
-
code
|
|
560
|
+
code,
|
|
546
561
|
language,
|
|
547
562
|
filename,
|
|
548
563
|
className,
|
|
@@ -551,13 +566,13 @@ function CodeBlock({
|
|
|
551
566
|
}) {
|
|
552
567
|
const [copied, setCopied] = useState3(false);
|
|
553
568
|
const handleCopy = useCallback(() => {
|
|
554
|
-
void copyTextToClipboard(
|
|
569
|
+
void copyTextToClipboard(code).then((ok) => {
|
|
555
570
|
if (!ok) return;
|
|
556
571
|
setCopied(true);
|
|
557
572
|
setTimeout(() => setCopied(false), 2e3);
|
|
558
573
|
});
|
|
559
|
-
}, [
|
|
560
|
-
const lines =
|
|
574
|
+
}, [code]);
|
|
575
|
+
const lines = code.split("\n");
|
|
561
576
|
const lineNumberWidth = `${String(lines.length).length + 1}ch`;
|
|
562
577
|
return /* @__PURE__ */ jsxs5(
|
|
563
578
|
"div",
|
|
@@ -574,7 +589,7 @@ function CodeBlock({
|
|
|
574
589
|
/* @__PURE__ */ jsx5("pre", { className: "m-0 overflow-auto p-3", children: /* @__PURE__ */ jsx5("code", { "data-language": language, children: showLineNumbers ? lines.map((line, i) => /* @__PURE__ */ jsxs5("span", { className: "block", children: [
|
|
575
590
|
/* @__PURE__ */ jsx5("span", { className: "mr-4 inline-block select-none text-right opacity-40", style: { width: lineNumberWidth }, children: i + 1 }),
|
|
576
591
|
line
|
|
577
|
-
] }, i)) :
|
|
592
|
+
] }, i)) : code }) }),
|
|
578
593
|
copyable && !filename && !language && /* @__PURE__ */ jsx5(
|
|
579
594
|
Button4,
|
|
580
595
|
{
|
|
@@ -921,7 +936,6 @@ import {
|
|
|
921
936
|
useRef as useRef2,
|
|
922
937
|
useState as useState4
|
|
923
938
|
} from "react";
|
|
924
|
-
import { createHighlighter } from "shiki";
|
|
925
939
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
926
940
|
var isItalic = (fontStyle) => fontStyle && fontStyle & 1;
|
|
927
941
|
var isBold = (fontStyle) => fontStyle && fontStyle & 2;
|
|
@@ -973,27 +987,27 @@ var CodeBlockContext = createContext({
|
|
|
973
987
|
var highlighterCache = /* @__PURE__ */ new Map();
|
|
974
988
|
var tokensCache = /* @__PURE__ */ new Map();
|
|
975
989
|
var subscribers = /* @__PURE__ */ new Map();
|
|
976
|
-
var getTokensCacheKey = (
|
|
977
|
-
const start =
|
|
978
|
-
const end =
|
|
979
|
-
return `${language}:${
|
|
990
|
+
var getTokensCacheKey = (code, language) => {
|
|
991
|
+
const start = code.slice(0, 100);
|
|
992
|
+
const end = code.length > 100 ? code.slice(-100) : "";
|
|
993
|
+
return `${language}:${code.length}:${start}:${end}`;
|
|
980
994
|
};
|
|
981
995
|
var getHighlighter = (language) => {
|
|
982
996
|
const cached = highlighterCache.get(language);
|
|
983
997
|
if (cached) {
|
|
984
998
|
return cached;
|
|
985
999
|
}
|
|
986
|
-
const highlighterPromise = createHighlighter({
|
|
1000
|
+
const highlighterPromise = import("shiki").then(({ createHighlighter }) => createHighlighter({
|
|
987
1001
|
langs: [language],
|
|
988
1002
|
themes: ["github-light", "github-dark"]
|
|
989
|
-
});
|
|
1003
|
+
}));
|
|
990
1004
|
highlighterCache.set(language, highlighterPromise);
|
|
991
1005
|
return highlighterPromise;
|
|
992
1006
|
};
|
|
993
|
-
var createRawTokens = (
|
|
1007
|
+
var createRawTokens = (code) => ({
|
|
994
1008
|
bg: "transparent",
|
|
995
1009
|
fg: "inherit",
|
|
996
|
-
tokens:
|
|
1010
|
+
tokens: code.split("\n").map(
|
|
997
1011
|
(line) => line === "" ? [] : [
|
|
998
1012
|
{
|
|
999
1013
|
color: "inherit",
|
|
@@ -1002,8 +1016,8 @@ var createRawTokens = (code3) => ({
|
|
|
1002
1016
|
]
|
|
1003
1017
|
)
|
|
1004
1018
|
});
|
|
1005
|
-
var highlightCode = (
|
|
1006
|
-
const tokensCacheKey = getTokensCacheKey(
|
|
1019
|
+
var highlightCode = (code, language, callback) => {
|
|
1020
|
+
const tokensCacheKey = getTokensCacheKey(code, language);
|
|
1007
1021
|
const cached = tokensCache.get(tokensCacheKey);
|
|
1008
1022
|
if (cached) {
|
|
1009
1023
|
return cached;
|
|
@@ -1017,7 +1031,7 @@ var highlightCode = (code3, language, callback) => {
|
|
|
1017
1031
|
getHighlighter(language).then((highlighter) => {
|
|
1018
1032
|
const availableLangs = highlighter.getLoadedLanguages();
|
|
1019
1033
|
const langToUse = availableLangs.includes(language) ? language : "text";
|
|
1020
|
-
const result = highlighter.codeToTokens(
|
|
1034
|
+
const result = highlighter.codeToTokens(code, {
|
|
1021
1035
|
lang: langToUse,
|
|
1022
1036
|
themes: {
|
|
1023
1037
|
dark: "github-dark",
|
|
@@ -1147,25 +1161,25 @@ var CodeBlockFilename = ({
|
|
|
1147
1161
|
}
|
|
1148
1162
|
);
|
|
1149
1163
|
var CodeBlockContent = ({
|
|
1150
|
-
code
|
|
1164
|
+
code,
|
|
1151
1165
|
language,
|
|
1152
1166
|
showLineNumbers = false
|
|
1153
1167
|
}) => {
|
|
1154
|
-
const rawTokens = useMemo(() => createRawTokens(
|
|
1168
|
+
const rawTokens = useMemo(() => createRawTokens(code), [code]);
|
|
1155
1169
|
const lang = language;
|
|
1156
1170
|
const syncTokens = useMemo(
|
|
1157
|
-
() => highlightCode(
|
|
1158
|
-
[
|
|
1171
|
+
() => highlightCode(code, lang) ?? rawTokens,
|
|
1172
|
+
[code, lang, rawTokens]
|
|
1159
1173
|
);
|
|
1160
1174
|
const [asyncTokens, setAsyncTokens] = useState4(null);
|
|
1161
|
-
const asyncKeyRef = useRef2({ code
|
|
1162
|
-
if (asyncKeyRef.current.code !==
|
|
1163
|
-
asyncKeyRef.current = { code
|
|
1175
|
+
const asyncKeyRef = useRef2({ code, language });
|
|
1176
|
+
if (asyncKeyRef.current.code !== code || asyncKeyRef.current.language !== language) {
|
|
1177
|
+
asyncKeyRef.current = { code, language };
|
|
1164
1178
|
setAsyncTokens(null);
|
|
1165
1179
|
}
|
|
1166
1180
|
useEffect2(() => {
|
|
1167
1181
|
let cancelled = false;
|
|
1168
|
-
highlightCode(
|
|
1182
|
+
highlightCode(code, lang, (result) => {
|
|
1169
1183
|
if (!cancelled) {
|
|
1170
1184
|
setAsyncTokens(result);
|
|
1171
1185
|
}
|
|
@@ -1173,25 +1187,25 @@ var CodeBlockContent = ({
|
|
|
1173
1187
|
return () => {
|
|
1174
1188
|
cancelled = true;
|
|
1175
1189
|
};
|
|
1176
|
-
}, [
|
|
1190
|
+
}, [code, language]);
|
|
1177
1191
|
const tokenized = asyncTokens ?? syncTokens;
|
|
1178
1192
|
return /* @__PURE__ */ jsx7("div", { className: "relative overflow-auto", children: /* @__PURE__ */ jsx7(CodeBlockBody, { showLineNumbers, tokenized }) });
|
|
1179
1193
|
};
|
|
1180
1194
|
var CodeBlock2 = ({
|
|
1181
|
-
code
|
|
1195
|
+
code,
|
|
1182
1196
|
language,
|
|
1183
1197
|
showLineNumbers = false,
|
|
1184
1198
|
className,
|
|
1185
1199
|
children,
|
|
1186
1200
|
...props
|
|
1187
1201
|
}) => {
|
|
1188
|
-
const contextValue = useMemo(() => ({ code
|
|
1202
|
+
const contextValue = useMemo(() => ({ code }), [code]);
|
|
1189
1203
|
return /* @__PURE__ */ jsx7(CodeBlockContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs7(CodeBlockContainer, { className, language, ...props, children: [
|
|
1190
1204
|
children,
|
|
1191
1205
|
/* @__PURE__ */ jsx7(
|
|
1192
1206
|
CodeBlockContent,
|
|
1193
1207
|
{
|
|
1194
|
-
code
|
|
1208
|
+
code,
|
|
1195
1209
|
language,
|
|
1196
1210
|
showLineNumbers
|
|
1197
1211
|
}
|
|
@@ -1208,7 +1222,7 @@ var CodeBlockCopyButton = ({
|
|
|
1208
1222
|
}) => {
|
|
1209
1223
|
const [isCopied, setIsCopied] = useState4(false);
|
|
1210
1224
|
const timeoutRef = useRef2(0);
|
|
1211
|
-
const { code
|
|
1225
|
+
const { code } = useContext(CodeBlockContext);
|
|
1212
1226
|
const copyToClipboard = useCallback2(async () => {
|
|
1213
1227
|
if (typeof window === "undefined") {
|
|
1214
1228
|
onError?.(new Error("Clipboard API not available"));
|
|
@@ -1217,7 +1231,7 @@ var CodeBlockCopyButton = ({
|
|
|
1217
1231
|
if (isCopied) {
|
|
1218
1232
|
return;
|
|
1219
1233
|
}
|
|
1220
|
-
const copied = await copyTextToClipboard(
|
|
1234
|
+
const copied = await copyTextToClipboard(code);
|
|
1221
1235
|
if (!copied) {
|
|
1222
1236
|
onError?.(new Error("Clipboard API not available"));
|
|
1223
1237
|
return;
|
|
@@ -1228,7 +1242,7 @@ var CodeBlockCopyButton = ({
|
|
|
1228
1242
|
() => setIsCopied(false),
|
|
1229
1243
|
timeout
|
|
1230
1244
|
);
|
|
1231
|
-
}, [
|
|
1245
|
+
}, [code, onCopy, onError, timeout, isCopied]);
|
|
1232
1246
|
useEffect2(
|
|
1233
1247
|
() => () => {
|
|
1234
1248
|
window.clearTimeout(timeoutRef.current);
|
|
@@ -2220,6 +2234,7 @@ var PiFollowUpQueueController = class {
|
|
|
2220
2234
|
session;
|
|
2221
2235
|
options;
|
|
2222
2236
|
nextClientSeqFloor;
|
|
2237
|
+
queueMutationPending = false;
|
|
2223
2238
|
async submit(input) {
|
|
2224
2239
|
const text = input.text.trim();
|
|
2225
2240
|
const attachments = input.attachments ?? [];
|
|
@@ -2257,30 +2272,65 @@ var PiFollowUpQueueController = class {
|
|
|
2257
2272
|
});
|
|
2258
2273
|
return { type: "prompt", clientNonce, cursor: receipt.cursor };
|
|
2259
2274
|
}
|
|
2260
|
-
|
|
2261
|
-
|
|
2262
|
-
|
|
2263
|
-
|
|
2264
|
-
|
|
2265
|
-
|
|
2266
|
-
|
|
2267
|
-
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2275
|
+
editQueued() {
|
|
2276
|
+
return this.runQueueMutation(
|
|
2277
|
+
{ type: "busy", message: "Another queue action is already in progress." },
|
|
2278
|
+
async () => {
|
|
2279
|
+
const followUps = this.session.getState().queue.followUps;
|
|
2280
|
+
if (followUps.length === 0) {
|
|
2281
|
+
const message = "No queued messages to edit.";
|
|
2282
|
+
this.options.onWarning?.(message);
|
|
2283
|
+
return { type: "empty", message };
|
|
2284
|
+
}
|
|
2285
|
+
const currentDraft = this.options.getDraft?.() ?? "";
|
|
2286
|
+
const draft = buildEditedQueuedDraft(followUps, currentDraft);
|
|
2287
|
+
if (draft !== currentDraft) this.options.onDraftChange?.(draft);
|
|
2288
|
+
try {
|
|
2289
|
+
await this.session.clearQueue();
|
|
2290
|
+
return { type: "cleared", draft };
|
|
2291
|
+
} catch (error) {
|
|
2292
|
+
const message = "Queued messages were copied into the composer, but the server queue was not cleared. They may still send unless you retry Edit or Remove.";
|
|
2293
|
+
this.options.onWarning?.(message);
|
|
2294
|
+
return { type: "clear-failed", draft, error, message };
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
);
|
|
2298
|
+
}
|
|
2299
|
+
removeAllQueued() {
|
|
2300
|
+
return this.runQueueMutation(
|
|
2301
|
+
{ ok: false, message: "Another queue action is already in progress." },
|
|
2302
|
+
async () => {
|
|
2303
|
+
try {
|
|
2304
|
+
await this.session.clearQueue();
|
|
2305
|
+
return { ok: true };
|
|
2306
|
+
} catch {
|
|
2307
|
+
const message = "Could not remove the queued messages. They may still send unless you retry or use Edit.";
|
|
2308
|
+
this.options.onWarning?.(message);
|
|
2309
|
+
return { ok: false, message };
|
|
2310
|
+
}
|
|
2311
|
+
}
|
|
2312
|
+
);
|
|
2277
2313
|
}
|
|
2278
|
-
interrupt() {
|
|
2279
|
-
return this.session.interrupt();
|
|
2314
|
+
interrupt(payload = {}) {
|
|
2315
|
+
return this.session.interrupt(payload);
|
|
2316
|
+
}
|
|
2317
|
+
resumeQueued() {
|
|
2318
|
+
return this.session.interrupt({ queueAction: "resume" });
|
|
2280
2319
|
}
|
|
2281
2320
|
stop() {
|
|
2282
2321
|
return this.session.stop();
|
|
2283
2322
|
}
|
|
2323
|
+
async runQueueMutation(busyResult, action) {
|
|
2324
|
+
if (this.queueMutationPending) return busyResult;
|
|
2325
|
+
this.queueMutationPending = true;
|
|
2326
|
+
this.options.onQueueMutationPending?.(true);
|
|
2327
|
+
try {
|
|
2328
|
+
return await action();
|
|
2329
|
+
} finally {
|
|
2330
|
+
this.queueMutationPending = false;
|
|
2331
|
+
this.options.onQueueMutationPending?.(false);
|
|
2332
|
+
}
|
|
2333
|
+
}
|
|
2284
2334
|
nextFollowUpClientSeq() {
|
|
2285
2335
|
const next = nextFollowUpClientSeq(this.session.getState(), this.nextClientSeqFloor);
|
|
2286
2336
|
this.nextClientSeqFloor = next + 1;
|
|
@@ -2321,6 +2371,9 @@ function buildEditedQueuedDraft(followUps, existingDraft = "") {
|
|
|
2321
2371
|
const draft = existingDraft.trim();
|
|
2322
2372
|
if (!queuedText) return draft;
|
|
2323
2373
|
if (!draft) return queuedText;
|
|
2374
|
+
if (draft === queuedText || draft.startsWith(`${queuedText}
|
|
2375
|
+
|
|
2376
|
+
`)) return draft;
|
|
2324
2377
|
return `${queuedText}
|
|
2325
2378
|
|
|
2326
2379
|
${draft}`;
|
|
@@ -2339,76 +2392,148 @@ function defaultClientNonce() {
|
|
|
2339
2392
|
// src/front/chat/session/composerPolicy.ts
|
|
2340
2393
|
var COMPOSER_SETTINGS_PREFIX = "boring-agent:v2";
|
|
2341
2394
|
var DEFAULT_STORAGE_SCOPE = "default";
|
|
2395
|
+
var PiComposerSubmissionCoordinator = class {
|
|
2396
|
+
tails = /* @__PURE__ */ new Map();
|
|
2397
|
+
run(identity, task) {
|
|
2398
|
+
const previous = this.tails.get(identity) ?? Promise.resolve();
|
|
2399
|
+
let releaseGate;
|
|
2400
|
+
const gate = new Promise((resolve) => {
|
|
2401
|
+
releaseGate = resolve;
|
|
2402
|
+
});
|
|
2403
|
+
let released = false;
|
|
2404
|
+
const release = () => {
|
|
2405
|
+
if (released) return;
|
|
2406
|
+
released = true;
|
|
2407
|
+
releaseGate();
|
|
2408
|
+
};
|
|
2409
|
+
const pending = previous.then(async () => {
|
|
2410
|
+
try {
|
|
2411
|
+
return await task(release);
|
|
2412
|
+
} finally {
|
|
2413
|
+
release();
|
|
2414
|
+
}
|
|
2415
|
+
});
|
|
2416
|
+
const tail = previous.then(async () => await gate);
|
|
2417
|
+
this.tails.set(identity, tail);
|
|
2418
|
+
void tail.finally(() => {
|
|
2419
|
+
if (this.tails.get(identity) === tail) this.tails.delete(identity);
|
|
2420
|
+
});
|
|
2421
|
+
return pending;
|
|
2422
|
+
}
|
|
2423
|
+
};
|
|
2342
2424
|
var PiComposerPolicyController = class {
|
|
2343
2425
|
constructor(options) {
|
|
2344
2426
|
this.options = options;
|
|
2345
2427
|
this.queueController = createPiFollowUpQueueController(options.session, options);
|
|
2428
|
+
this.submissionCoordinator = options.submissionCoordinator ?? new PiComposerSubmissionCoordinator();
|
|
2346
2429
|
}
|
|
2347
2430
|
options;
|
|
2348
2431
|
queueController;
|
|
2349
|
-
|
|
2350
|
-
|
|
2432
|
+
submissionCoordinator;
|
|
2433
|
+
submit(input) {
|
|
2434
|
+
return this.submissionCoordinator.run(
|
|
2435
|
+
this.options.submissionIdentity ?? "default",
|
|
2436
|
+
async (release) => await this.submitInOrder(input, release)
|
|
2437
|
+
);
|
|
2438
|
+
}
|
|
2439
|
+
async submitInOrder(input, release) {
|
|
2351
2440
|
const files = input.files ?? [];
|
|
2352
2441
|
const source = input.source ?? "composer";
|
|
2353
2442
|
if (this.options.composerBlocked) {
|
|
2354
2443
|
return this.block("composer-blocked", this.options.blockerMessage ?? "Composer is not ready yet.");
|
|
2355
2444
|
}
|
|
2356
|
-
|
|
2357
|
-
|
|
2445
|
+
let beforeSubmit;
|
|
2446
|
+
try {
|
|
2447
|
+
beforeSubmit = await this.runBeforeSubmit(input.text, files, source);
|
|
2448
|
+
} catch (error) {
|
|
2449
|
+
if (this.options.isActiveSession && !this.options.isActiveSession()) return this.stale();
|
|
2450
|
+
throw error;
|
|
2358
2451
|
}
|
|
2359
2452
|
if (this.options.isActiveSession && !this.options.isActiveSession()) {
|
|
2360
|
-
return this.
|
|
2453
|
+
return this.stale();
|
|
2454
|
+
}
|
|
2455
|
+
if (beforeSubmit === false) {
|
|
2456
|
+
return this.block("pre-submit-cancelled", "Submit was cancelled before sending.");
|
|
2457
|
+
}
|
|
2458
|
+
if (typeof beforeSubmit === "object" && "handled" in beforeSubmit && beforeSubmit.handled) {
|
|
2459
|
+
return { type: "handled", ...beforeSubmit.message ? { message: beforeSubmit.message } : {}, preserveDraft: false };
|
|
2361
2460
|
}
|
|
2362
|
-
const
|
|
2461
|
+
const replacement = typeof beforeSubmit === "object" && "replacement" in beforeSubmit ? beforeSubmit.replacement : void 0;
|
|
2462
|
+
const text = (replacement?.text ?? input.text).trim();
|
|
2463
|
+
const displayText = replacement?.displayText ?? text;
|
|
2464
|
+
const parsed = replacement ? null : parseSlashCommand(text);
|
|
2363
2465
|
if (parsed) {
|
|
2364
2466
|
const command = this.options.registry.get(parsed.name);
|
|
2365
2467
|
if (command?.kind === "skill") {
|
|
2366
|
-
return this.submitExpandedText(skillCommandText(parsed.name, parsed.args), source,
|
|
2468
|
+
return this.submitExpandedText(skillCommandText(parsed.name, parsed.args), files, source, release);
|
|
2367
2469
|
}
|
|
2368
|
-
if (command) return this.runLocalCommand(parsed.name, parsed.args);
|
|
2470
|
+
if (command) return this.runLocalCommand(parsed.name, parsed.args, source, release);
|
|
2369
2471
|
}
|
|
2370
2472
|
if (isPiChatBusy(this.options.session.getState().status) && files.length > 0) {
|
|
2371
2473
|
return this.fromQueueResult(await this.queueController.submit({ text, attachments: this.toAttachmentPayloads(files) }));
|
|
2372
2474
|
}
|
|
2475
|
+
const transformed = await this.runPromptTransform(text, files, source);
|
|
2476
|
+
if (this.options.isActiveSession && !this.options.isActiveSession()) return this.stale();
|
|
2477
|
+
const finalText = transformed?.replacement.text ?? text;
|
|
2478
|
+
const finalDisplayText = transformed?.replacement.displayText ?? displayText;
|
|
2373
2479
|
const { serverMessage, attachments } = await createEnrichedSubmitPayload({
|
|
2374
|
-
text,
|
|
2480
|
+
text: finalText,
|
|
2375
2481
|
files,
|
|
2376
2482
|
mentionedFiles: this.getMentionedFiles()
|
|
2377
2483
|
});
|
|
2378
2484
|
if (this.options.isActiveSession && !this.options.isActiveSession()) {
|
|
2379
|
-
return this.
|
|
2485
|
+
return this.stale();
|
|
2380
2486
|
}
|
|
2381
|
-
const
|
|
2487
|
+
const admission = this.queueController.submit({
|
|
2382
2488
|
text: serverMessage,
|
|
2383
|
-
displayText:
|
|
2489
|
+
displayText: finalDisplayText,
|
|
2384
2490
|
attachments,
|
|
2385
2491
|
model: this.options.model ?? void 0,
|
|
2386
2492
|
...this.options.thinkingControl ? { thinkingLevel: this.options.thinkingLevel ?? DEFAULT_THINKING } : {}
|
|
2387
2493
|
});
|
|
2494
|
+
release();
|
|
2495
|
+
const result = await admission;
|
|
2388
2496
|
if (result.type !== "blocked") this.options.onMentionedFilesConsumed?.();
|
|
2389
2497
|
return this.fromQueueResult(result);
|
|
2390
2498
|
}
|
|
2391
2499
|
async editQueued() {
|
|
2392
2500
|
return this.queueController.editQueued();
|
|
2393
2501
|
}
|
|
2394
|
-
|
|
2395
|
-
return this.queueController.
|
|
2502
|
+
removeAllQueued() {
|
|
2503
|
+
return this.queueController.removeAllQueued();
|
|
2504
|
+
}
|
|
2505
|
+
interrupt(payload = {}) {
|
|
2506
|
+
return this.queueController.interrupt(payload);
|
|
2507
|
+
}
|
|
2508
|
+
resumeQueued() {
|
|
2509
|
+
return this.queueController.resumeQueued();
|
|
2396
2510
|
}
|
|
2397
2511
|
stop() {
|
|
2398
2512
|
return this.queueController.stop();
|
|
2399
2513
|
}
|
|
2400
|
-
async submitExpandedText(text, source,
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2514
|
+
async submitExpandedText(text, files, source, release) {
|
|
2515
|
+
const transformed = await this.runPromptTransform(text, files, source);
|
|
2516
|
+
if (this.options.isActiveSession && !this.options.isActiveSession()) return this.stale();
|
|
2517
|
+
const admission = this.queueController.submit({
|
|
2518
|
+
text: transformed?.replacement.text ?? text,
|
|
2519
|
+
...transformed?.replacement.displayText ? { displayText: transformed.replacement.displayText } : {},
|
|
2406
2520
|
kind: "expanded-text",
|
|
2407
2521
|
model: this.options.model ?? void 0,
|
|
2408
2522
|
...this.options.thinkingControl ? { thinkingLevel: this.options.thinkingLevel ?? DEFAULT_THINKING } : {}
|
|
2409
|
-
})
|
|
2523
|
+
});
|
|
2524
|
+
release();
|
|
2525
|
+
return this.fromQueueResult(await admission);
|
|
2410
2526
|
}
|
|
2411
|
-
async
|
|
2527
|
+
async runPromptTransform(text, files, source) {
|
|
2528
|
+
try {
|
|
2529
|
+
const transformed = await this.options.onTransformPrompt?.(text, { files, source });
|
|
2530
|
+
return transformed || void 0;
|
|
2531
|
+
} catch (error) {
|
|
2532
|
+
if (this.options.isActiveSession && !this.options.isActiveSession()) return void 0;
|
|
2533
|
+
throw error;
|
|
2534
|
+
}
|
|
2535
|
+
}
|
|
2536
|
+
async runLocalCommand(commandName, args, source, release) {
|
|
2412
2537
|
const command = this.options.registry.get(commandName);
|
|
2413
2538
|
if (isPiChatBusy(this.options.session.getState().status) && command?.allowWhileBusy?.(args) !== true) {
|
|
2414
2539
|
return this.block("busy-slash-command", "Slash commands are not queued while the agent is responding.");
|
|
@@ -2417,16 +2542,23 @@ var PiComposerPolicyController = class {
|
|
|
2417
2542
|
const message = typeof result === "string" ? result : result && typeof result === "object" ? result.message : void 0;
|
|
2418
2543
|
const preserveDraft = Boolean(result && typeof result === "object" && result.preserveDraft === true);
|
|
2419
2544
|
if (message) this.options.onCommandResult?.(message);
|
|
2545
|
+
const modelMessage = result && typeof result === "object" ? result.modelMessage?.trim() : void 0;
|
|
2546
|
+
if (modelMessage) {
|
|
2547
|
+
return await this.submitExpandedText(modelMessage, [], source, release);
|
|
2548
|
+
}
|
|
2549
|
+
release();
|
|
2420
2550
|
return { type: "command", command: commandName, ...message ? { result: message } : {}, preserveDraft };
|
|
2421
2551
|
}
|
|
2422
2552
|
async runBeforeSubmit(draft, files, source) {
|
|
2423
|
-
|
|
2424
|
-
return result !== false;
|
|
2553
|
+
return await this.options.onBeforeSubmit?.(draft, { files, source });
|
|
2425
2554
|
}
|
|
2426
2555
|
fromQueueResult(result) {
|
|
2427
2556
|
if (result.type === "blocked") return { ...result, preserveDraft: true };
|
|
2428
2557
|
return { ...result, preserveDraft: false };
|
|
2429
2558
|
}
|
|
2559
|
+
stale() {
|
|
2560
|
+
return { type: "stale", reason: "inactive-session", preserveDraft: false };
|
|
2561
|
+
}
|
|
2430
2562
|
block(reason, message) {
|
|
2431
2563
|
this.options.onWarning?.(message);
|
|
2432
2564
|
return { type: "blocked", reason, message, preserveDraft: true };
|
|
@@ -2640,15 +2772,17 @@ function useChatModelSelection({
|
|
|
2640
2772
|
setAvailableModels(models);
|
|
2641
2773
|
setSelection((current) => {
|
|
2642
2774
|
const selected = current.pendingOverride ?? sessionModel ?? current.localDefault;
|
|
2643
|
-
if (
|
|
2644
|
-
|
|
2645
|
-
|
|
2775
|
+
if (sessionModel) {
|
|
2776
|
+
if (availableModel(models, selected)) return current;
|
|
2777
|
+
return { ...current, pendingOverride: void 0 };
|
|
2778
|
+
}
|
|
2646
2779
|
const firstAvailable = models.find((candidate) => candidate.available);
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
pendingOverride: void 0,
|
|
2650
|
-
|
|
2651
|
-
|
|
2780
|
+
const serverDefault = payload.defaultModel ?? (firstAvailable ? { provider: firstAvailable.provider, id: firstAvailable.id } : null);
|
|
2781
|
+
if (sessionId && !sessionIsNew) {
|
|
2782
|
+
return { ...current, pendingOverride: void 0, localDefault: serverDefault };
|
|
2783
|
+
}
|
|
2784
|
+
if (availableModel(models, selected)) return current;
|
|
2785
|
+
return { ...current, pendingOverride: void 0, localDefault: serverDefault };
|
|
2652
2786
|
});
|
|
2653
2787
|
setLoadedDiscoveryKey(discoveryKey);
|
|
2654
2788
|
setLoaded(true);
|
|
@@ -2676,7 +2810,8 @@ function useChatModelSelection({
|
|
|
2676
2810
|
const selectionBelongsToSession = selection.sessionId === sessionId && selection.storage === storage && selection.storageScope === storageScope;
|
|
2677
2811
|
const pendingOverride = selectionBelongsToSession ? selection.pendingOverride : void 0;
|
|
2678
2812
|
const isOverride = Boolean(pendingOverride && sessionModel && !sameModel(pendingOverride, sessionModel));
|
|
2679
|
-
const
|
|
2813
|
+
const discoveryVetted = enabled && currentDiscoveryLoaded;
|
|
2814
|
+
const sessionAuthorityReady = !sessionId || sessionHydrated && (sessionModel !== void 0 || sessionIsNew || discoveryVetted);
|
|
2680
2815
|
const model = currentDiscoveryLoaded && sessionAuthorityReady ? pendingOverride ?? sessionModel ?? selection.localDefault : null;
|
|
2681
2816
|
return {
|
|
2682
2817
|
availableModels: currentDiscoveryLoaded ? availableModels : [],
|
|
@@ -3383,15 +3518,15 @@ function messageCreatedAtMs(message) {
|
|
|
3383
3518
|
|
|
3384
3519
|
// src/front/chat/gatewayResponseError.ts
|
|
3385
3520
|
var GatewayResponseError = class extends Error {
|
|
3386
|
-
constructor(status, message,
|
|
3521
|
+
constructor(status, message, code, details, body, operation) {
|
|
3387
3522
|
super(message);
|
|
3388
3523
|
this.status = status;
|
|
3389
|
-
this.code =
|
|
3524
|
+
this.code = code;
|
|
3390
3525
|
this.details = details;
|
|
3391
3526
|
this.body = body;
|
|
3392
3527
|
this.operation = operation;
|
|
3393
3528
|
this.name = "GatewayResponseError";
|
|
3394
|
-
this.errorCode =
|
|
3529
|
+
this.errorCode = code;
|
|
3395
3530
|
}
|
|
3396
3531
|
status;
|
|
3397
3532
|
code;
|
|
@@ -3406,11 +3541,11 @@ async function gatewayResponseError(response, fallbackMessage, operation) {
|
|
|
3406
3541
|
}
|
|
3407
3542
|
function gatewayResponseErrorFromBody(status, body, fallbackMessage, operation) {
|
|
3408
3543
|
const payload = errorPayload(body);
|
|
3409
|
-
const
|
|
3544
|
+
const code = gatewayResponseErrorCode(payload?.code);
|
|
3410
3545
|
const serverMessage = typeof payload?.message === "string" && payload.message.trim().length > 0 ? payload.message : fallbackMessage;
|
|
3411
3546
|
const message = serverMessage;
|
|
3412
3547
|
const details = isJsonValue(payload?.details) ? payload.details : void 0;
|
|
3413
|
-
return new GatewayResponseError(status, message,
|
|
3548
|
+
return new GatewayResponseError(status, message, code, details, body, operation);
|
|
3414
3549
|
}
|
|
3415
3550
|
function gatewayResponseErrorCode(value) {
|
|
3416
3551
|
const sharedCode = ErrorCode.safeParse(value);
|
|
@@ -4683,12 +4818,30 @@ var RemotePiSession = class {
|
|
|
4683
4818
|
}
|
|
4684
4819
|
}
|
|
4685
4820
|
async clearQueue(payload = {}) {
|
|
4686
|
-
const receipt = await this.
|
|
4821
|
+
const receipt = await this.postQueueClear({ ...payload, requestId: `queue-clear:${safeRandomUUID()}` });
|
|
4687
4822
|
if (!this.disposed && receipt.cleared > 0) {
|
|
4688
4823
|
this.store.dispatch({ type: "clear-optimistic-followups", ...payload }, { flush: true });
|
|
4689
4824
|
}
|
|
4690
4825
|
return receipt;
|
|
4691
4826
|
}
|
|
4827
|
+
async postQueueClear(commandPayload) {
|
|
4828
|
+
let transportRetried = false;
|
|
4829
|
+
for (let attempt = 0; ; attempt += 1) {
|
|
4830
|
+
try {
|
|
4831
|
+
return await this.postCommand("/queue/clear", commandPayload, QueueClearReceiptSchema);
|
|
4832
|
+
} catch (error) {
|
|
4833
|
+
if (!(error instanceof GatewayResponseError)) {
|
|
4834
|
+
if (transportRetried) throw error;
|
|
4835
|
+
transportRetried = true;
|
|
4836
|
+
continue;
|
|
4837
|
+
}
|
|
4838
|
+
if (errorResponseCode(error) !== AgentGatewayErrorCode.AGENT_REQUEST_IN_PROGRESS || attempt >= 40) throw error;
|
|
4839
|
+
await new Promise((resolve) => {
|
|
4840
|
+
this.setTimeoutFn(resolve, 50);
|
|
4841
|
+
});
|
|
4842
|
+
}
|
|
4843
|
+
}
|
|
4844
|
+
}
|
|
4692
4845
|
async interrupt(payload = {}) {
|
|
4693
4846
|
return this.postCommand("/interrupt", payload, CommandReceiptSchema);
|
|
4694
4847
|
}
|
|
@@ -5298,17 +5451,27 @@ function usePiSessions(options) {
|
|
|
5298
5451
|
const [loading, setLoading] = useState10(enabled);
|
|
5299
5452
|
const [loadingMore, setLoadingMore] = useState10(false);
|
|
5300
5453
|
const [hasMore, setHasMore] = useState10(false);
|
|
5454
|
+
const [archivedLoaded, setArchivedLoaded] = useState10(false);
|
|
5455
|
+
const [archivedLoading, setArchivedLoading] = useState10(false);
|
|
5456
|
+
const [hasMoreArchived, setHasMoreArchived] = useState10(false);
|
|
5301
5457
|
const [error, setError] = useState10(void 0);
|
|
5302
5458
|
const mountedRef = useRef7(false);
|
|
5303
5459
|
const refreshVersionRef = useRef7(0);
|
|
5304
5460
|
const retryTimerRef = useRef7(void 0);
|
|
5305
5461
|
const sessionsRef = useRef7([]);
|
|
5462
|
+
const filterPagersRef = useRef7({
|
|
5463
|
+
active: { sessions: [], loaded: false },
|
|
5464
|
+
archived: { sessions: [], loaded: false }
|
|
5465
|
+
});
|
|
5466
|
+
const archiveMutationVersionRef = useRef7(0);
|
|
5306
5467
|
const activeSessionIdRef = useRef7(activeSessionId);
|
|
5307
|
-
const hasMoreRef = useRef7(hasMore);
|
|
5308
5468
|
const canonicalLoadedCountRef = useRef7(0);
|
|
5309
5469
|
const nextCursorRef = useRef7(void 0);
|
|
5310
|
-
const
|
|
5311
|
-
const
|
|
5470
|
+
const archivedCursorRef = useRef7(void 0);
|
|
5471
|
+
const archivedLoadedRef = useRef7(false);
|
|
5472
|
+
const archiveRequestSeqRef = useRef7(0);
|
|
5473
|
+
const archiveInFlightRef = useRef7(false);
|
|
5474
|
+
const activeRequestOwnerRef = useRef7(void 0);
|
|
5312
5475
|
const pendingCreatedRef = useRef7(/* @__PURE__ */ new Map());
|
|
5313
5476
|
const pendingDeletedRef = useRef7(/* @__PURE__ */ new Set());
|
|
5314
5477
|
const pendingCreatedScopeRef = useRef7(requestScopeKey);
|
|
@@ -5340,14 +5503,11 @@ function usePiSessions(options) {
|
|
|
5340
5503
|
useEffect8(() => {
|
|
5341
5504
|
activeSessionIdRef.current = activeSessionId;
|
|
5342
5505
|
}, [activeSessionId]);
|
|
5343
|
-
useEffect8(() => {
|
|
5344
|
-
hasMoreRef.current = hasMore;
|
|
5345
|
-
}, [hasMore]);
|
|
5346
5506
|
const activeSessionKnown = Boolean(activeSessionId && sessions.some((session) => session.id === activeSessionId));
|
|
5347
5507
|
const requestHeaders = useCallback7(() => normalizedHeaders, [normalizedHeaders]);
|
|
5348
5508
|
const sessionsUrl = useCallback7((suffix = "") => `${apiBaseUrl}${sessionsApiPath}${suffix}`, [apiBaseUrl, sessionsApiPath]);
|
|
5349
|
-
const sessionsListUrl = useCallback7((cursor) => {
|
|
5350
|
-
const query = new URLSearchParams({ limit: String(SESSION_PAGE_SIZE) });
|
|
5509
|
+
const sessionsListUrl = useCallback7((cursor, archived = "active") => {
|
|
5510
|
+
const query = new URLSearchParams({ limit: String(SESSION_PAGE_SIZE), archived });
|
|
5351
5511
|
if (cursor) query.set("cursor", cursor);
|
|
5352
5512
|
return sessionsUrl(`?${query.toString()}`);
|
|
5353
5513
|
}, [sessionsUrl]);
|
|
@@ -5368,6 +5528,27 @@ function usePiSessions(options) {
|
|
|
5368
5528
|
pendingCreatedRef.current.clear();
|
|
5369
5529
|
pendingDeletedRef.current.clear();
|
|
5370
5530
|
}, [requestScopeKey]);
|
|
5531
|
+
const publishFilterPagers = useCallback7(() => {
|
|
5532
|
+
const deleted = pendingDeletedRef.current;
|
|
5533
|
+
const merged = mergeSessions(
|
|
5534
|
+
Array.from(pendingCreatedRef.current.values()),
|
|
5535
|
+
filterPagersRef.current.active.sessions,
|
|
5536
|
+
filterPagersRef.current.archived.sessions
|
|
5537
|
+
).filter((session) => !deleted.has(session.id));
|
|
5538
|
+
sessionsRef.current = merged;
|
|
5539
|
+
setSessions(merged);
|
|
5540
|
+
return merged;
|
|
5541
|
+
}, []);
|
|
5542
|
+
const resetArchivePager = useCallback7(() => {
|
|
5543
|
+
filterPagersRef.current.archived = { sessions: [], loaded: false };
|
|
5544
|
+
archivedCursorRef.current = void 0;
|
|
5545
|
+
archivedLoadedRef.current = false;
|
|
5546
|
+
archiveRequestSeqRef.current += 1;
|
|
5547
|
+
archiveInFlightRef.current = false;
|
|
5548
|
+
setArchivedLoaded(false);
|
|
5549
|
+
setArchivedLoading(false);
|
|
5550
|
+
setHasMoreArchived(false);
|
|
5551
|
+
}, []);
|
|
5371
5552
|
const preferredSessionId = useCallback7(() => {
|
|
5372
5553
|
const persisted = options.initialActiveSessionId ?? readActiveSessionId({
|
|
5373
5554
|
storageScope: activeSessionStorageScope,
|
|
@@ -5394,11 +5575,23 @@ function usePiSessions(options) {
|
|
|
5394
5575
|
}
|
|
5395
5576
|
}
|
|
5396
5577
|
const canonicalCount = canonicalPageCount(filteredData);
|
|
5397
|
-
|
|
5398
|
-
|
|
5399
|
-
|
|
5400
|
-
|
|
5401
|
-
|
|
5578
|
+
filterPagersRef.current.active = {
|
|
5579
|
+
sessions: mergeSessions(filteredData),
|
|
5580
|
+
nextCursor: applyOptions.nextCursor,
|
|
5581
|
+
loaded: true
|
|
5582
|
+
};
|
|
5583
|
+
if (applyOptions.archivedPage) {
|
|
5584
|
+
const archived = applyOptions.archivedPage.sessions.filter((session) => !deletedIds.has(session.id));
|
|
5585
|
+
filterPagersRef.current.archived = {
|
|
5586
|
+
sessions: archived,
|
|
5587
|
+
nextCursor: applyOptions.archivedPage.nextCursor,
|
|
5588
|
+
loaded: true
|
|
5589
|
+
};
|
|
5590
|
+
archivedCursorRef.current = applyOptions.archivedPage.nextCursor;
|
|
5591
|
+
archivedLoadedRef.current = true;
|
|
5592
|
+
setArchivedLoaded(true);
|
|
5593
|
+
setHasMoreArchived(applyOptions.archivedPage.nextCursor !== void 0);
|
|
5594
|
+
}
|
|
5402
5595
|
const rememberedEmptyId = readBootResumeSessionId({
|
|
5403
5596
|
bootResumeSource,
|
|
5404
5597
|
storage: options.bootResumeStorage
|
|
@@ -5406,12 +5599,13 @@ function usePiSessions(options) {
|
|
|
5406
5599
|
if (rememberedEmptyId && filteredData.some((session) => session.id === rememberedEmptyId)) {
|
|
5407
5600
|
persistBootResume(void 0);
|
|
5408
5601
|
}
|
|
5409
|
-
const nextHasMore =
|
|
5602
|
+
const nextHasMore = applyOptions.nextCursor !== void 0;
|
|
5410
5603
|
canonicalLoadedCountRef.current = applyOptions.background ? Math.max(canonicalLoadedCountRef.current, canonicalCount) : canonicalCount;
|
|
5604
|
+
if (replacingScope && !applyOptions.archivedPage) resetArchivePager();
|
|
5411
5605
|
loadedDataSourceRef.current = dataSourceKey;
|
|
5412
5606
|
dataStorageScopeRef.current = storageScope;
|
|
5413
5607
|
setDataStorageScope(storageScope);
|
|
5414
|
-
|
|
5608
|
+
const merged = publishFilterPagers();
|
|
5415
5609
|
nextCursorRef.current = applyOptions.nextCursor;
|
|
5416
5610
|
setHasMore(nextHasMore);
|
|
5417
5611
|
setActiveSessionId((previous) => {
|
|
@@ -5420,21 +5614,26 @@ function usePiSessions(options) {
|
|
|
5420
5614
|
persistActive(next);
|
|
5421
5615
|
return next;
|
|
5422
5616
|
});
|
|
5423
|
-
}, [bootResumeSource, dataSourceKey, ensurePendingScope, options.bootResumeStorage, persistActive, persistBootResume, preferredSessionId, storageScope]);
|
|
5617
|
+
}, [bootResumeSource, dataSourceKey, ensurePendingScope, options.bootResumeStorage, persistActive, persistBootResume, preferredSessionId, publishFilterPagers, resetArchivePager, storageScope]);
|
|
5424
5618
|
const refresh = useCallback7(async (refreshOptions = {}) => {
|
|
5425
5619
|
const scope = requestScopeKey;
|
|
5426
5620
|
if (mountedRef.current && !sourceIsCurrent(scope)) throw new StaleSessionsSourceError();
|
|
5621
|
+
const requestOwner = {};
|
|
5622
|
+
activeRequestOwnerRef.current = requestOwner;
|
|
5427
5623
|
const version = ++refreshVersionRef.current;
|
|
5428
|
-
const
|
|
5624
|
+
const mutationVersion = archiveMutationVersionRef.current;
|
|
5625
|
+
const isCurrent = () => sourceIsCurrent(scope) && version === refreshVersionRef.current && activeRequestOwnerRef.current === requestOwner;
|
|
5429
5626
|
clearRetryTimer(retryTimerRef);
|
|
5430
5627
|
const background = refreshOptions.background === true;
|
|
5628
|
+
let archivedRequestSeq;
|
|
5431
5629
|
if (!enabled) {
|
|
5432
|
-
loadMoreRequestSeqRef.current += 1;
|
|
5433
|
-
loadMoreInFlightRef.current = false;
|
|
5434
5630
|
canonicalLoadedCountRef.current = 0;
|
|
5435
5631
|
loadedDataSourceRef.current = dataSourceKey;
|
|
5436
5632
|
dataStorageScopeRef.current = storageScope;
|
|
5437
5633
|
setDataStorageScope(storageScope);
|
|
5634
|
+
filterPagersRef.current.active = { sessions: [], loaded: true };
|
|
5635
|
+
resetArchivePager();
|
|
5636
|
+
sessionsRef.current = [];
|
|
5438
5637
|
setSessions([]);
|
|
5439
5638
|
setActiveSessionId(void 0);
|
|
5440
5639
|
setError(void 0);
|
|
@@ -5442,17 +5641,22 @@ function usePiSessions(options) {
|
|
|
5442
5641
|
setLoadingMore(false);
|
|
5443
5642
|
setHasMore(false);
|
|
5444
5643
|
persistActive(void 0);
|
|
5644
|
+
if (activeRequestOwnerRef.current === requestOwner) activeRequestOwnerRef.current = void 0;
|
|
5445
5645
|
return;
|
|
5446
5646
|
}
|
|
5447
|
-
loadMoreRequestSeqRef.current += 1;
|
|
5448
|
-
loadMoreInFlightRef.current = false;
|
|
5449
5647
|
setLoadingMore(false);
|
|
5450
5648
|
if (!background) setLoading(true);
|
|
5451
5649
|
try {
|
|
5452
5650
|
let page;
|
|
5453
5651
|
for (let attempt = 0; ; attempt += 1) {
|
|
5454
5652
|
try {
|
|
5455
|
-
page = await
|
|
5653
|
+
page = await fetchSessionPrefix({
|
|
5654
|
+
fetchImpl,
|
|
5655
|
+
firstUrl: sessionsListUrl(),
|
|
5656
|
+
nextUrl: (cursor) => sessionsListUrl(cursor),
|
|
5657
|
+
headers: requestHeaders(),
|
|
5658
|
+
minimumRows: filterPagersRef.current.active.sessions.length
|
|
5659
|
+
});
|
|
5456
5660
|
break;
|
|
5457
5661
|
} catch (err) {
|
|
5458
5662
|
const transient = err instanceof SessionsPreparingError || isNetworkFetchError(err);
|
|
@@ -5464,17 +5668,41 @@ function usePiSessions(options) {
|
|
|
5464
5668
|
}
|
|
5465
5669
|
}
|
|
5466
5670
|
if (!isCurrent() || !page) return;
|
|
5467
|
-
|
|
5671
|
+
let archivedPage;
|
|
5672
|
+
if (filterPagersRef.current.archived.loaded) {
|
|
5673
|
+
archivedRequestSeq = ++archiveRequestSeqRef.current;
|
|
5674
|
+
archiveInFlightRef.current = true;
|
|
5675
|
+
setArchivedLoading(true);
|
|
5676
|
+
archivedPage = await fetchSessionPrefix({
|
|
5677
|
+
fetchImpl,
|
|
5678
|
+
firstUrl: sessionsListUrl(void 0, "archived"),
|
|
5679
|
+
nextUrl: (cursor) => sessionsListUrl(cursor, "archived"),
|
|
5680
|
+
headers: requestHeaders(),
|
|
5681
|
+
minimumRows: filterPagersRef.current.archived.sessions.length
|
|
5682
|
+
});
|
|
5683
|
+
}
|
|
5684
|
+
if (!isCurrent() || archivedRequestSeq !== void 0 && archivedRequestSeq !== archiveRequestSeqRef.current) return;
|
|
5685
|
+
if (mutationVersion !== archiveMutationVersionRef.current) {
|
|
5686
|
+
setLoading(false);
|
|
5687
|
+
return;
|
|
5688
|
+
}
|
|
5689
|
+
applySessions(page.sessions, { background, nextCursor: page.nextCursor, archivedPage });
|
|
5468
5690
|
setError(void 0);
|
|
5469
5691
|
setLoading(false);
|
|
5470
5692
|
} catch (err) {
|
|
5471
|
-
if (!isCurrent()) return;
|
|
5693
|
+
if (!isCurrent() || archivedRequestSeq !== void 0 && archivedRequestSeq !== archiveRequestSeqRef.current) return;
|
|
5472
5694
|
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
5473
5695
|
if (!background) setError(error2);
|
|
5474
5696
|
setLoading(false);
|
|
5475
5697
|
if (refreshOptions.throwOnError) throw error2;
|
|
5698
|
+
} finally {
|
|
5699
|
+
if (activeRequestOwnerRef.current === requestOwner) activeRequestOwnerRef.current = void 0;
|
|
5700
|
+
if (archivedRequestSeq !== void 0 && archivedRequestSeq === archiveRequestSeqRef.current) {
|
|
5701
|
+
archiveInFlightRef.current = false;
|
|
5702
|
+
if (sourceIsCurrent(scope)) setArchivedLoading(false);
|
|
5703
|
+
}
|
|
5476
5704
|
}
|
|
5477
|
-
}, [applySessions, enabled, fetchImpl, persistActive, preferredSessionId, requestHeaders, requestScopeKey, retryBaseMs, retryMaxMs, retryMaxRetries, sessionsListUrl, sourceIsCurrent]);
|
|
5705
|
+
}, [applySessions, enabled, fetchImpl, persistActive, preferredSessionId, requestHeaders, requestScopeKey, resetArchivePager, retryBaseMs, retryMaxMs, retryMaxRetries, sessionsListUrl, sourceIsCurrent]);
|
|
5478
5706
|
useEffect8(() => {
|
|
5479
5707
|
mountedRef.current = true;
|
|
5480
5708
|
void refresh();
|
|
@@ -5485,21 +5713,26 @@ function usePiSessions(options) {
|
|
|
5485
5713
|
};
|
|
5486
5714
|
}, [refresh, options.refreshKey]);
|
|
5487
5715
|
const loadMore = useCallback7(async () => {
|
|
5488
|
-
if (!enabled || loading || loadingMore ||
|
|
5489
|
-
const
|
|
5490
|
-
|
|
5716
|
+
if (!enabled || loading || loadingMore || activeRequestOwnerRef.current !== void 0 || !hasMore) return;
|
|
5717
|
+
const requestOwner = {};
|
|
5718
|
+
activeRequestOwnerRef.current = requestOwner;
|
|
5491
5719
|
const version = refreshVersionRef.current;
|
|
5720
|
+
const mutationVersion = archiveMutationVersionRef.current;
|
|
5492
5721
|
const scope = requestScopeKey;
|
|
5493
5722
|
setLoadingMore(true);
|
|
5494
5723
|
try {
|
|
5495
5724
|
const page = await fetchSessionList(fetchImpl, sessionsListUrl(nextCursorRef.current), requestHeaders());
|
|
5496
5725
|
const data = page.sessions.filter((session) => !pendingDeletedRef.current.has(session.id));
|
|
5497
|
-
if (
|
|
5498
|
-
|
|
5726
|
+
if (activeRequestOwnerRef.current !== requestOwner || version !== refreshVersionRef.current || mutationVersion !== archiveMutationVersionRef.current || !sourceIsCurrent(scope)) return;
|
|
5727
|
+
filterPagersRef.current.active = {
|
|
5728
|
+
sessions: mergeSessions(filterPagersRef.current.active.sessions, data),
|
|
5729
|
+
nextCursor: page.nextCursor,
|
|
5730
|
+
loaded: true
|
|
5731
|
+
};
|
|
5732
|
+
const merged = publishFilterPagers();
|
|
5499
5733
|
const nextHasMore = page.nextCursor !== void 0;
|
|
5500
5734
|
canonicalLoadedCountRef.current += data.length;
|
|
5501
5735
|
nextCursorRef.current = page.nextCursor;
|
|
5502
|
-
setSessions(merged);
|
|
5503
5736
|
setHasMore(nextHasMore);
|
|
5504
5737
|
setError(void 0);
|
|
5505
5738
|
setActiveSessionId((previous) => {
|
|
@@ -5509,16 +5742,52 @@ function usePiSessions(options) {
|
|
|
5509
5742
|
return next;
|
|
5510
5743
|
});
|
|
5511
5744
|
} catch (err) {
|
|
5512
|
-
if (
|
|
5745
|
+
if (activeRequestOwnerRef.current === requestOwner && version === refreshVersionRef.current && sourceIsCurrent(scope)) {
|
|
5513
5746
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
5514
5747
|
}
|
|
5515
5748
|
} finally {
|
|
5516
|
-
if (
|
|
5517
|
-
|
|
5518
|
-
setLoadingMore(false);
|
|
5749
|
+
if (activeRequestOwnerRef.current === requestOwner) {
|
|
5750
|
+
activeRequestOwnerRef.current = void 0;
|
|
5751
|
+
if (version === refreshVersionRef.current && sourceIsCurrent(scope)) setLoadingMore(false);
|
|
5519
5752
|
}
|
|
5520
5753
|
}
|
|
5521
|
-
}, [enabled, fetchImpl, hasMore, loading, loadingMore, persistActive, requestHeaders, requestScopeKey, sessionsListUrl, sourceIsCurrent]);
|
|
5754
|
+
}, [enabled, fetchImpl, hasMore, loading, loadingMore, persistActive, publishFilterPagers, requestHeaders, requestScopeKey, sessionsListUrl, sourceIsCurrent]);
|
|
5755
|
+
const loadArchived = useCallback7(async () => {
|
|
5756
|
+
if (!enabled || archivedLoading || archiveInFlightRef.current) return;
|
|
5757
|
+
if (archivedLoadedRef.current && !hasMoreArchived) return;
|
|
5758
|
+
const requestSeq = ++archiveRequestSeqRef.current;
|
|
5759
|
+
const mutationVersion = archiveMutationVersionRef.current;
|
|
5760
|
+
const scope = requestScopeKey;
|
|
5761
|
+
archiveInFlightRef.current = true;
|
|
5762
|
+
setArchivedLoading(true);
|
|
5763
|
+
try {
|
|
5764
|
+
const page = await fetchSessionList(
|
|
5765
|
+
fetchImpl,
|
|
5766
|
+
sessionsListUrl(archivedCursorRef.current, "archived"),
|
|
5767
|
+
requestHeaders()
|
|
5768
|
+
);
|
|
5769
|
+
if (requestSeq !== archiveRequestSeqRef.current || mutationVersion !== archiveMutationVersionRef.current || !sourceIsCurrent(scope)) return;
|
|
5770
|
+
const archived = page.sessions.filter((session) => !pendingDeletedRef.current.has(session.id));
|
|
5771
|
+
filterPagersRef.current.archived = {
|
|
5772
|
+
sessions: mergeSessions(filterPagersRef.current.archived.sessions, archived),
|
|
5773
|
+
nextCursor: page.nextCursor,
|
|
5774
|
+
loaded: true
|
|
5775
|
+
};
|
|
5776
|
+
archivedCursorRef.current = page.nextCursor;
|
|
5777
|
+
archivedLoadedRef.current = true;
|
|
5778
|
+
publishFilterPagers();
|
|
5779
|
+
setArchivedLoaded(true);
|
|
5780
|
+
setHasMoreArchived(page.nextCursor !== void 0);
|
|
5781
|
+
setError(void 0);
|
|
5782
|
+
} catch (err) {
|
|
5783
|
+
if (requestSeq === archiveRequestSeqRef.current && sourceIsCurrent(scope)) {
|
|
5784
|
+
setError(err instanceof Error ? err : new Error(String(err)));
|
|
5785
|
+
}
|
|
5786
|
+
} finally {
|
|
5787
|
+
if (requestSeq === archiveRequestSeqRef.current) archiveInFlightRef.current = false;
|
|
5788
|
+
if (requestSeq === archiveRequestSeqRef.current && sourceIsCurrent(scope)) setArchivedLoading(false);
|
|
5789
|
+
}
|
|
5790
|
+
}, [archivedLoading, enabled, fetchImpl, hasMoreArchived, publishFilterPagers, requestHeaders, requestScopeKey, sessionsListUrl, sourceIsCurrent]);
|
|
5522
5791
|
useEffect8(() => {
|
|
5523
5792
|
if (!enabled || !connectActiveSession || !activeSessionId || !activeSessionKnown) {
|
|
5524
5793
|
setActivePiSession(void 0);
|
|
@@ -5560,12 +5829,12 @@ function usePiSessions(options) {
|
|
|
5560
5829
|
rememberConfirmedEmptySession(session.id);
|
|
5561
5830
|
pendingCreatedRef.current.set(session.id, session);
|
|
5562
5831
|
setDataStorageScope(storageScope);
|
|
5563
|
-
|
|
5832
|
+
publishFilterPagers();
|
|
5564
5833
|
setActiveSessionId(session.id);
|
|
5565
5834
|
persistActive(session.id);
|
|
5566
5835
|
void refresh();
|
|
5567
5836
|
return session;
|
|
5568
|
-
}, [enabled, ensurePendingScope, fetchImpl, persistActive, refresh, rememberConfirmedEmptySession, requestHeaders, requestScopeKey, sessionsUrl, sourceIsCurrent, storageScope]);
|
|
5837
|
+
}, [enabled, ensurePendingScope, fetchImpl, persistActive, publishFilterPagers, refresh, rememberConfirmedEmptySession, requestHeaders, requestScopeKey, sessionsUrl, sourceIsCurrent, storageScope]);
|
|
5569
5838
|
const switchSession = useCallback7((id) => {
|
|
5570
5839
|
if (!sourceIsCurrent(requestScopeKey)) return;
|
|
5571
5840
|
const known = sessionsRef.current.some((session) => session.id === id);
|
|
@@ -5587,9 +5856,34 @@ function usePiSessions(options) {
|
|
|
5587
5856
|
if (!sourceIsCurrent(scope)) throw new StaleSessionsSourceError();
|
|
5588
5857
|
ensurePendingScope();
|
|
5589
5858
|
if (pendingCreatedRef.current.has(id)) pendingCreatedRef.current.set(id, renamed);
|
|
5590
|
-
|
|
5859
|
+
for (const pager of Object.values(filterPagersRef.current)) {
|
|
5860
|
+
pager.sessions = pager.sessions.map((session) => session.id === id ? renamed : session);
|
|
5861
|
+
}
|
|
5862
|
+
publishFilterPagers();
|
|
5591
5863
|
return renamed;
|
|
5592
|
-
}, [enabled, ensurePendingScope, fetchImpl, requestHeaders, requestScopeKey, sessionsUrl, sourceIsCurrent]);
|
|
5864
|
+
}, [enabled, ensurePendingScope, fetchImpl, publishFilterPagers, requestHeaders, requestScopeKey, sessionsUrl, sourceIsCurrent]);
|
|
5865
|
+
const setArchived = useCallback7(async (id, archived) => {
|
|
5866
|
+
const scope = requestScopeKey;
|
|
5867
|
+
if (!sourceIsCurrent(scope)) throw new StaleSessionsSourceError();
|
|
5868
|
+
if (!enabled) throw new Error("Pi sessions are disabled");
|
|
5869
|
+
const response = await fetchImpl(sessionsUrl(`/${encodeURIComponent(id)}/archive`), {
|
|
5870
|
+
method: "POST",
|
|
5871
|
+
headers: { ...requestHeaders(), "Content-Type": "application/json" },
|
|
5872
|
+
body: JSON.stringify({ requestId: createRequestId("archive"), archived })
|
|
5873
|
+
});
|
|
5874
|
+
if (!response.ok) throw new Error(`Failed to ${archived ? "archive" : "unarchive"} session: ${response.status}`);
|
|
5875
|
+
const updated = toAddressedSessionSummary(await response.json());
|
|
5876
|
+
if (!sourceIsCurrent(scope)) throw new StaleSessionsSourceError();
|
|
5877
|
+
archiveMutationVersionRef.current += 1;
|
|
5878
|
+
pendingCreatedRef.current.delete(id);
|
|
5879
|
+
for (const pager of Object.values(filterPagersRef.current)) {
|
|
5880
|
+
pager.sessions = pager.sessions.filter((session) => session.id !== id);
|
|
5881
|
+
}
|
|
5882
|
+
const target = archived ? filterPagersRef.current.archived : filterPagersRef.current.active;
|
|
5883
|
+
target.sessions = sortSessionSummaries([...target.sessions, updated]);
|
|
5884
|
+
publishFilterPagers();
|
|
5885
|
+
return updated;
|
|
5886
|
+
}, [enabled, fetchImpl, publishFilterPagers, requestHeaders, requestScopeKey, sessionsUrl, sourceIsCurrent]);
|
|
5593
5887
|
const deleteSession = useCallback7(async (id) => {
|
|
5594
5888
|
const scope = requestScopeKey;
|
|
5595
5889
|
if (!sourceIsCurrent(scope)) throw new StaleSessionsSourceError();
|
|
@@ -5602,8 +5896,11 @@ function usePiSessions(options) {
|
|
|
5602
5896
|
const deletedSessionWasActive = activeSessionIdRef.current === id;
|
|
5603
5897
|
pendingCreatedRef.current.delete(id);
|
|
5604
5898
|
pendingDeletedRef.current.add(id);
|
|
5899
|
+
for (const pager of Object.values(filterPagersRef.current)) {
|
|
5900
|
+
pager.sessions = pager.sessions.filter((session) => session.id !== id);
|
|
5901
|
+
}
|
|
5605
5902
|
setDataStorageScope(storageScope);
|
|
5606
|
-
|
|
5903
|
+
publishFilterPagers();
|
|
5607
5904
|
setActiveSessionId((previous) => {
|
|
5608
5905
|
if (previous !== id) return previous;
|
|
5609
5906
|
const next = sessionsRef.current.find((session) => session.id !== id)?.id;
|
|
@@ -5621,7 +5918,9 @@ function usePiSessions(options) {
|
|
|
5621
5918
|
if (sourceIsCurrent(scope)) {
|
|
5622
5919
|
pendingDeletedRef.current.delete(id);
|
|
5623
5920
|
if (deletedSession) {
|
|
5624
|
-
|
|
5921
|
+
const target = deletedSession.archived === true ? filterPagersRef.current.archived : filterPagersRef.current.active;
|
|
5922
|
+
target.sessions = sortSessionSummaries([...target.sessions, deletedSession]);
|
|
5923
|
+
publishFilterPagers();
|
|
5625
5924
|
if (deletedSessionWasActive) {
|
|
5626
5925
|
setActiveSessionId(id);
|
|
5627
5926
|
persistActive(id);
|
|
@@ -5633,14 +5932,15 @@ function usePiSessions(options) {
|
|
|
5633
5932
|
throw error2;
|
|
5634
5933
|
}
|
|
5635
5934
|
if (sourceIsCurrent(scope)) void refresh();
|
|
5636
|
-
}, [bootResumeSource, enabled, ensurePendingScope, fetchImpl, options.bootResumeStorage, persistActive, persistBootResume, refresh, requestHeaders, requestScopeKey, sessionsUrl, sourceIsCurrent, storageScope]);
|
|
5935
|
+
}, [bootResumeSource, enabled, ensurePendingScope, fetchImpl, options.bootResumeStorage, persistActive, persistBootResume, publishFilterPagers, refresh, requestHeaders, requestScopeKey, sessionsUrl, sourceIsCurrent, storageScope]);
|
|
5637
5936
|
const reset = useCallback7(() => {
|
|
5638
5937
|
if (!sourceIsCurrent(requestScopeKey)) return;
|
|
5639
5938
|
pendingCreatedRef.current.clear();
|
|
5640
5939
|
pendingDeletedRef.current.clear();
|
|
5641
|
-
|
|
5642
|
-
|
|
5643
|
-
|
|
5940
|
+
activeRequestOwnerRef.current = void 0;
|
|
5941
|
+
resetArchivePager();
|
|
5942
|
+
publishFilterPagers();
|
|
5943
|
+
canonicalLoadedCountRef.current = canonicalPageCount(filterPagersRef.current.active.sessions);
|
|
5644
5944
|
loadedDataSourceRef.current = dataSourceKey;
|
|
5645
5945
|
dataStorageScopeRef.current = storageScope;
|
|
5646
5946
|
setDataStorageScope(storageScope);
|
|
@@ -5648,7 +5948,7 @@ function usePiSessions(options) {
|
|
|
5648
5948
|
setActivePiSession(void 0);
|
|
5649
5949
|
setLoadingMore(false);
|
|
5650
5950
|
persistActive(void 0);
|
|
5651
|
-
}, [dataSourceKey, persistActive, requestScopeKey, sourceIsCurrent, storageScope]);
|
|
5951
|
+
}, [dataSourceKey, persistActive, publishFilterPagers, requestScopeKey, resetArchivePager, sourceIsCurrent, storageScope]);
|
|
5652
5952
|
const visibleActiveSessionId = enabled ? activeSessionId : void 0;
|
|
5653
5953
|
const activeSession = enabled ? sessions.find((session) => session.id === visibleActiveSessionId) : void 0;
|
|
5654
5954
|
return {
|
|
@@ -5662,10 +5962,15 @@ function usePiSessions(options) {
|
|
|
5662
5962
|
loading: enabled ? loading : false,
|
|
5663
5963
|
loadingMore,
|
|
5664
5964
|
hasMore: enabled ? hasMore : false,
|
|
5965
|
+
archivedLoaded,
|
|
5966
|
+
archivedLoading,
|
|
5967
|
+
hasMoreArchived: enabled ? hasMoreArchived : false,
|
|
5665
5968
|
error,
|
|
5666
5969
|
refresh,
|
|
5667
5970
|
create,
|
|
5668
5971
|
rename,
|
|
5972
|
+
setArchived,
|
|
5973
|
+
loadArchived,
|
|
5669
5974
|
switch: switchSession,
|
|
5670
5975
|
delete: deleteSession,
|
|
5671
5976
|
loadMore,
|
|
@@ -5686,6 +5991,19 @@ async function fetchSessionList(fetchImpl, url, headers) {
|
|
|
5686
5991
|
...typeof page.nextCursor === "string" ? { nextCursor: page.nextCursor } : {}
|
|
5687
5992
|
};
|
|
5688
5993
|
}
|
|
5994
|
+
async function fetchSessionPrefix(input) {
|
|
5995
|
+
const sessions = [];
|
|
5996
|
+
let page = await fetchSessionList(input.fetchImpl, input.firstUrl, input.headers);
|
|
5997
|
+
sessions.push(...page.sessions);
|
|
5998
|
+
while (page.nextCursor && sessions.length < input.minimumRows) {
|
|
5999
|
+
page = await fetchSessionList(input.fetchImpl, input.nextUrl(page.nextCursor), input.headers);
|
|
6000
|
+
sessions.push(...page.sessions);
|
|
6001
|
+
}
|
|
6002
|
+
return {
|
|
6003
|
+
sessions: mergeSessions(sessions),
|
|
6004
|
+
...page.nextCursor ? { nextCursor: page.nextCursor } : {}
|
|
6005
|
+
};
|
|
6006
|
+
}
|
|
5689
6007
|
function toAddressedSessionSummary(value) {
|
|
5690
6008
|
if (typeof value !== "object" || value === null) throw new Error("invalid addressed session summary");
|
|
5691
6009
|
const record = value;
|
|
@@ -5707,7 +6025,8 @@ function toAddressedSessionSummary(value) {
|
|
|
5707
6025
|
...typeof agentTypeId === "string" ? { agentTypeId } : {},
|
|
5708
6026
|
...typeof record.nativeSessionId === "string" ? { nativeSessionId: record.nativeSessionId } : {},
|
|
5709
6027
|
...typeof record.hasAssistantReply === "boolean" ? { hasAssistantReply: record.hasAssistantReply } : {},
|
|
5710
|
-
...addressedStatus ? { status: addressedStatus } : {}
|
|
6028
|
+
...addressedStatus ? { status: addressedStatus } : {},
|
|
6029
|
+
...record.archived === true ? { archived: true } : {}
|
|
5711
6030
|
};
|
|
5712
6031
|
}
|
|
5713
6032
|
function addressedCreatedSession(value, expectedAgentTypeId, title) {
|
|
@@ -5761,6 +6080,13 @@ function remoteSessionOptionsIdentity(options) {
|
|
|
5761
6080
|
} : void 0
|
|
5762
6081
|
});
|
|
5763
6082
|
}
|
|
6083
|
+
function sortSessionSummaries(sessions) {
|
|
6084
|
+
return sessions.sort((left, right) => {
|
|
6085
|
+
const time = Date.parse(right.updatedAt) - Date.parse(left.updatedAt);
|
|
6086
|
+
if (time !== 0) return time;
|
|
6087
|
+
return left.id < right.id ? -1 : left.id > right.id ? 1 : 0;
|
|
6088
|
+
});
|
|
6089
|
+
}
|
|
5764
6090
|
function mergeSessions(...lists) {
|
|
5765
6091
|
const seen = /* @__PURE__ */ new Set();
|
|
5766
6092
|
const merged = [];
|
|
@@ -5987,7 +6313,7 @@ function sortByUpdatedDesc(a, b) {
|
|
|
5987
6313
|
return a.id.localeCompare(b.id);
|
|
5988
6314
|
}
|
|
5989
6315
|
|
|
5990
|
-
// ../../node_modules/.pnpm/@earendil-works+pi-tui@0.
|
|
6316
|
+
// ../../node_modules/.pnpm/@earendil-works+pi-tui@0.84.3/node_modules/@earendil-works/pi-tui/dist/fuzzy.js
|
|
5991
6317
|
function fuzzyMatch(query, text) {
|
|
5992
6318
|
const queryLower = query.toLowerCase();
|
|
5993
6319
|
const textLower = text.toLowerCase();
|
|
@@ -6173,7 +6499,7 @@ function searchPiSessions(sessions, query, options = {}) {
|
|
|
6173
6499
|
|
|
6174
6500
|
// src/front/chat/components/PiConversationSurface.tsx
|
|
6175
6501
|
import { Skeleton } from "@hachej/boring-ui-kit";
|
|
6176
|
-
import { useCallback as
|
|
6502
|
+
import { useCallback as useCallback15, useEffect as useEffect16, useLayoutEffect as useLayoutEffect2, useRef as useRef11, useState as useState17 } from "react";
|
|
6177
6503
|
import { useStickToBottomContext as useStickToBottomContext2 } from "use-stick-to-bottom";
|
|
6178
6504
|
|
|
6179
6505
|
// src/front/primitives/conversation.tsx
|
|
@@ -6249,8 +6575,8 @@ var ConversationScrollButton = ({
|
|
|
6249
6575
|
};
|
|
6250
6576
|
|
|
6251
6577
|
// src/front/chat/components/ChatNotices.tsx
|
|
6252
|
-
import { AlertCircleIcon, ExternalLinkIcon as ExternalLinkIcon2,
|
|
6253
|
-
import { IconButton as IconButton2 } from "@hachej/boring-ui-kit";
|
|
6578
|
+
import { AlertCircleIcon, ExternalLinkIcon as ExternalLinkIcon2, Loader2, PencilIcon, SendHorizontalIcon, XIcon as XIcon2 } from "lucide-react";
|
|
6579
|
+
import { Button as Button8, IconButton as IconButton2 } from "@hachej/boring-ui-kit";
|
|
6254
6580
|
|
|
6255
6581
|
// src/front/chat/components/noticeStyles.ts
|
|
6256
6582
|
function noticeSurfaceClass(level, className) {
|
|
@@ -6484,7 +6810,15 @@ function composerBlockerActionIcon(actionId) {
|
|
|
6484
6810
|
if (actionId === "cancel") return /* @__PURE__ */ jsx15(XIcon2, { className: "size-3.5", "aria-hidden": "true" });
|
|
6485
6811
|
return null;
|
|
6486
6812
|
}
|
|
6487
|
-
function QueuedComposerNotice({
|
|
6813
|
+
function QueuedComposerNotice({
|
|
6814
|
+
followUps,
|
|
6815
|
+
onEdit,
|
|
6816
|
+
onResume,
|
|
6817
|
+
resumePending = false,
|
|
6818
|
+
onRemove,
|
|
6819
|
+
actionPending = false
|
|
6820
|
+
}) {
|
|
6821
|
+
const toolbarPending = actionPending || resumePending;
|
|
6488
6822
|
return /* @__PURE__ */ jsxs14(
|
|
6489
6823
|
"div",
|
|
6490
6824
|
{
|
|
@@ -6494,7 +6828,7 @@ function QueuedComposerNotice({ followUps, onEdit }) {
|
|
|
6494
6828
|
"border border-dashed border-[color:var(--border)] bg-[color:oklch(from_var(--muted)_l_c_h/0.45)] px-3 py-2 text-xs text-[color:var(--foreground)]"
|
|
6495
6829
|
),
|
|
6496
6830
|
children: [
|
|
6497
|
-
/* @__PURE__ */ jsxs14("div", { className: "min-w-0 text-[color:var(--muted-foreground)]", children: [
|
|
6831
|
+
/* @__PURE__ */ jsxs14("div", { className: "min-w-0 flex-1 text-[color:var(--muted-foreground)]", children: [
|
|
6498
6832
|
/* @__PURE__ */ jsxs14("div", { className: "font-medium text-[color:var(--foreground)]", children: [
|
|
6499
6833
|
followUps.length,
|
|
6500
6834
|
" queued follow-up",
|
|
@@ -6502,31 +6836,73 @@ function QueuedComposerNotice({ followUps, onEdit }) {
|
|
|
6502
6836
|
] }),
|
|
6503
6837
|
/* @__PURE__ */ jsx15("div", { className: "truncate text-[color:var(--muted-foreground)]", "data-boring-agent-part": "composer-queue-preview-text", children: followUps.map((followUp) => followUp.displayText).join(" - ") })
|
|
6504
6838
|
] }),
|
|
6505
|
-
/* @__PURE__ */
|
|
6506
|
-
|
|
6507
|
-
|
|
6508
|
-
|
|
6509
|
-
|
|
6510
|
-
|
|
6511
|
-
|
|
6512
|
-
|
|
6513
|
-
|
|
6514
|
-
|
|
6515
|
-
|
|
6516
|
-
|
|
6517
|
-
|
|
6839
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex shrink-0 self-center items-center gap-1", children: [
|
|
6840
|
+
onRemove ? /* @__PURE__ */ jsx15(
|
|
6841
|
+
IconButton2,
|
|
6842
|
+
{
|
|
6843
|
+
type: "button",
|
|
6844
|
+
variant: "ghost",
|
|
6845
|
+
size: "icon-xs",
|
|
6846
|
+
onClick: onRemove,
|
|
6847
|
+
disabled: toolbarPending,
|
|
6848
|
+
"aria-busy": toolbarPending,
|
|
6849
|
+
className: "text-[color:var(--muted-foreground)] hover:bg-[color:var(--muted)] hover:text-[color:var(--foreground)]",
|
|
6850
|
+
"aria-label": "Remove all queued messages",
|
|
6851
|
+
title: "Remove all queued messages",
|
|
6852
|
+
"data-boring-agent-part": "composer-queue-remove",
|
|
6853
|
+
children: /* @__PURE__ */ jsx15(XIcon2, { className: "size-3", "aria-hidden": "true" })
|
|
6854
|
+
}
|
|
6855
|
+
) : null,
|
|
6856
|
+
onResume ? /* @__PURE__ */ jsxs14(
|
|
6857
|
+
Button8,
|
|
6858
|
+
{
|
|
6859
|
+
type: "button",
|
|
6860
|
+
variant: "ghost",
|
|
6861
|
+
size: "xs",
|
|
6862
|
+
onClick: onResume,
|
|
6863
|
+
disabled: toolbarPending,
|
|
6864
|
+
"aria-busy": toolbarPending,
|
|
6865
|
+
className: "text-[color:var(--muted-foreground)] hover:bg-[color:var(--muted)] hover:text-[color:var(--foreground)]",
|
|
6866
|
+
"aria-label": "Nudge agent: stop the current run and send queued messages now",
|
|
6867
|
+
title: "Send queued messages now and stop the current run",
|
|
6868
|
+
"data-boring-agent-part": "composer-queue-nudge",
|
|
6869
|
+
children: [
|
|
6870
|
+
/* @__PURE__ */ jsx15(SendHorizontalIcon, { className: "size-3", "aria-hidden": "true" }),
|
|
6871
|
+
"Send now"
|
|
6872
|
+
]
|
|
6873
|
+
}
|
|
6874
|
+
) : null,
|
|
6875
|
+
/* @__PURE__ */ jsxs14(
|
|
6876
|
+
Button8,
|
|
6877
|
+
{
|
|
6878
|
+
type: "button",
|
|
6879
|
+
variant: "ghost",
|
|
6880
|
+
size: "xs",
|
|
6881
|
+
onClick: onEdit,
|
|
6882
|
+
disabled: toolbarPending,
|
|
6883
|
+
"aria-busy": toolbarPending,
|
|
6884
|
+
className: "text-[color:var(--muted-foreground)] hover:bg-[color:var(--muted)] hover:text-[color:var(--foreground)]",
|
|
6885
|
+
"aria-label": "Edit queued follow-ups",
|
|
6886
|
+
title: "Move queued messages back to the composer",
|
|
6887
|
+
children: [
|
|
6888
|
+
/* @__PURE__ */ jsx15(PencilIcon, { className: "size-3", "aria-hidden": "true" }),
|
|
6889
|
+
"Edit"
|
|
6890
|
+
]
|
|
6891
|
+
}
|
|
6892
|
+
)
|
|
6893
|
+
] })
|
|
6518
6894
|
]
|
|
6519
6895
|
}
|
|
6520
6896
|
);
|
|
6521
6897
|
}
|
|
6522
6898
|
|
|
6523
6899
|
// src/front/chat/components/PiTimelineMessage.tsx
|
|
6524
|
-
import { useCallback as
|
|
6525
|
-
import { CheckIcon as
|
|
6526
|
-
import { Button as
|
|
6900
|
+
import { useCallback as useCallback14, useEffect as useEffect15, useMemo as useMemo13, useRef as useRef10, useState as useState16 } from "react";
|
|
6901
|
+
import { CheckIcon as CheckIcon3, CopyIcon as CopyIcon4 } from "lucide-react";
|
|
6902
|
+
import { Button as Button11 } from "@hachej/boring-ui-kit";
|
|
6527
6903
|
|
|
6528
6904
|
// src/front/primitives/attachments.tsx
|
|
6529
|
-
import { Button as
|
|
6905
|
+
import { Button as Button9, HoverCard, HoverCardContent, HoverCardTrigger } from "@hachej/boring-ui-kit";
|
|
6530
6906
|
import {
|
|
6531
6907
|
FileTextIcon as FileTextIcon2,
|
|
6532
6908
|
GlobeIcon,
|
|
@@ -6724,7 +7100,7 @@ var AttachmentRemove = ({
|
|
|
6724
7100
|
return null;
|
|
6725
7101
|
}
|
|
6726
7102
|
return /* @__PURE__ */ jsxs15(
|
|
6727
|
-
|
|
7103
|
+
Button9,
|
|
6728
7104
|
{
|
|
6729
7105
|
"aria-label": label,
|
|
6730
7106
|
className: cn(
|
|
@@ -6756,7 +7132,7 @@ var AttachmentRemove = ({
|
|
|
6756
7132
|
};
|
|
6757
7133
|
|
|
6758
7134
|
// src/front/primitives/message.tsx
|
|
6759
|
-
import { Button as
|
|
7135
|
+
import { Button as Button10, ButtonGroup, ButtonGroupText } from "@hachej/boring-ui-kit";
|
|
6760
7136
|
import {
|
|
6761
7137
|
Tooltip,
|
|
6762
7138
|
TooltipContent,
|
|
@@ -6768,23 +7144,228 @@ import {
|
|
|
6768
7144
|
var INLINE_CODE_CLASS_NAME = "rounded-[0.3em] bg-muted/55 px-[0.32em] py-[0.08em] font-mono text-[0.9em] font-medium text-foreground/90";
|
|
6769
7145
|
|
|
6770
7146
|
// src/front/primitives/message.tsx
|
|
6771
|
-
import { cjk } from "@streamdown/cjk";
|
|
6772
|
-
import { code } from "@streamdown/code";
|
|
6773
|
-
import { math } from "@streamdown/math";
|
|
6774
|
-
import { mermaid } from "@streamdown/mermaid";
|
|
6775
7147
|
import { ChevronLeftIcon as ChevronLeftIcon2, ChevronRightIcon } from "lucide-react";
|
|
6776
7148
|
import {
|
|
6777
7149
|
createContext as createContext4,
|
|
6778
7150
|
memo as memo3,
|
|
6779
|
-
useCallback as
|
|
7151
|
+
useCallback as useCallback11,
|
|
6780
7152
|
useContext as useContext4,
|
|
6781
|
-
useEffect as
|
|
6782
|
-
useMemo as
|
|
6783
|
-
useState as
|
|
7153
|
+
useEffect as useEffect12,
|
|
7154
|
+
useMemo as useMemo8,
|
|
7155
|
+
useState as useState13
|
|
6784
7156
|
} from "react";
|
|
6785
|
-
import { Streamdown } from "streamdown";
|
|
7157
|
+
import { Streamdown as Streamdown2 } from "streamdown";
|
|
7158
|
+
|
|
7159
|
+
// src/front/primitives/useStreamdownPlugins.ts
|
|
7160
|
+
import { useEffect as useEffect10, useMemo as useMemo7, useState as useState11 } from "react";
|
|
7161
|
+
var streamdownPluginPromises = {};
|
|
7162
|
+
var streamdownPluginLoaders = {
|
|
7163
|
+
cjk: () => import("@streamdown/cjk").then((module) => module.cjk),
|
|
7164
|
+
code: () => import("@streamdown/code").then((module) => module.code),
|
|
7165
|
+
math: () => import("@streamdown/math").then((module) => module.math),
|
|
7166
|
+
mermaid: () => import("@streamdown/mermaid").then((module) => module.mermaid)
|
|
7167
|
+
};
|
|
7168
|
+
function loadStreamdownPlugin(name) {
|
|
7169
|
+
const existing = streamdownPluginPromises[name];
|
|
7170
|
+
if (existing) return existing;
|
|
7171
|
+
const promise = streamdownPluginLoaders[name]().catch((error) => {
|
|
7172
|
+
delete streamdownPluginPromises[name];
|
|
7173
|
+
throw error;
|
|
7174
|
+
});
|
|
7175
|
+
streamdownPluginPromises[name] = promise;
|
|
7176
|
+
return promise;
|
|
7177
|
+
}
|
|
7178
|
+
var CJK_SCRIPT = /[\p{Script=Han}\p{Script=Hiragana}\p{Script=Katakana}\p{Script=Hangul}]/u;
|
|
7179
|
+
var INLINE_CODE = /(^|[^`])`[^`\n]+`(?!`)/;
|
|
7180
|
+
var INLINE_MATH = /(^|[^\\$])\$(?!\s|\$)(?:\\.|[^\n$])+?(?<!\\)\$(?![\d$])/;
|
|
7181
|
+
var BLOCK_MATH = /(^|\n)\s*\$\$\s*\n?[\s\S]+?\n?\s*\$\$(?=\s*(?:\n|$))/;
|
|
7182
|
+
function hasClosedFence(source, language) {
|
|
7183
|
+
const lines = source.split("\n");
|
|
7184
|
+
for (let index = 0; index < lines.length; index += 1) {
|
|
7185
|
+
const opening = lines[index]?.match(/^ {0,3}(`{3,}|~{3,})[ \t]*([^ \t`~]+)?[^\n]*$/);
|
|
7186
|
+
if (!opening) continue;
|
|
7187
|
+
if (language && opening[2]?.toLowerCase() !== language) continue;
|
|
7188
|
+
const marker = opening[1][0];
|
|
7189
|
+
const minimumLength = opening[1].length;
|
|
7190
|
+
for (let closing = index + 1; closing < lines.length; closing += 1) {
|
|
7191
|
+
const candidate = lines[closing]?.match(/^ {0,3}(`+|~+)[ \t]*$/)?.[1];
|
|
7192
|
+
if (candidate?.[0] === marker && candidate.length >= minimumLength) return true;
|
|
7193
|
+
}
|
|
7194
|
+
}
|
|
7195
|
+
return false;
|
|
7196
|
+
}
|
|
7197
|
+
function streamdownPluginNamesForSource(source, options = {}) {
|
|
7198
|
+
if (typeof source !== "string" || source.length === 0) return [];
|
|
7199
|
+
const names = [];
|
|
7200
|
+
if (CJK_SCRIPT.test(source)) names.push("cjk");
|
|
7201
|
+
if (options.code !== false && (hasClosedFence(source) || INLINE_CODE.test(source))) names.push("code");
|
|
7202
|
+
if (INLINE_MATH.test(source) || BLOCK_MATH.test(source)) names.push("math");
|
|
7203
|
+
if (hasClosedFence(source, "mermaid")) names.push("mermaid");
|
|
7204
|
+
return names;
|
|
7205
|
+
}
|
|
7206
|
+
function useStreamdownPlugins(source, options = {}) {
|
|
7207
|
+
const includeCode = options.code !== false;
|
|
7208
|
+
const names = useMemo7(() => streamdownPluginNamesForSource(source, { code: includeCode }), [includeCode, source]);
|
|
7209
|
+
const [plugins, setPlugins] = useState11({});
|
|
7210
|
+
useEffect10(() => {
|
|
7211
|
+
let cancelled = false;
|
|
7212
|
+
for (const name of names) {
|
|
7213
|
+
void loadStreamdownPlugin(name).then((plugin) => {
|
|
7214
|
+
if (cancelled) return;
|
|
7215
|
+
setPlugins((current) => current[name] ? current : { ...current, [name]: plugin });
|
|
7216
|
+
}).catch((error) => {
|
|
7217
|
+
console.error(`Failed to load the ${name} markdown renderer`, error);
|
|
7218
|
+
});
|
|
7219
|
+
}
|
|
7220
|
+
return () => {
|
|
7221
|
+
cancelled = true;
|
|
7222
|
+
};
|
|
7223
|
+
}, [names]);
|
|
7224
|
+
const selectedPlugins = useMemo7(() => {
|
|
7225
|
+
const selected = {};
|
|
7226
|
+
for (const name of names) {
|
|
7227
|
+
if (plugins[name]) selected[name] = plugins[name];
|
|
7228
|
+
}
|
|
7229
|
+
return selected;
|
|
7230
|
+
}, [names, plugins]);
|
|
7231
|
+
return Object.keys(selectedPlugins).length > 0 ? selectedPlugins : void 0;
|
|
7232
|
+
}
|
|
7233
|
+
|
|
7234
|
+
// src/front/primitives/markdownLink.tsx
|
|
7235
|
+
import { CheckIcon as CheckIcon2, CopyIcon as CopyIcon3, ExternalLinkIcon as ExternalLinkIcon3 } from "lucide-react";
|
|
7236
|
+
import {
|
|
7237
|
+
useCallback as useCallback10,
|
|
7238
|
+
useEffect as useEffect11,
|
|
7239
|
+
useRef as useRef8,
|
|
7240
|
+
useState as useState12
|
|
7241
|
+
} from "react";
|
|
7242
|
+
import { defaultRehypePlugins } from "streamdown";
|
|
6786
7243
|
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
6787
|
-
var
|
|
7244
|
+
var LINK_ACTIONS_TAG = "boring-link-actions";
|
|
7245
|
+
var INCOMPLETE_LINK_HREF = "streamdown:incomplete-link";
|
|
7246
|
+
function decorateLinks(node) {
|
|
7247
|
+
if (!node.children) return;
|
|
7248
|
+
if (node.properties?.["data-boring-agent-part"] === "chat-url-group") return;
|
|
7249
|
+
for (const child of node.children) decorateLinks(child);
|
|
7250
|
+
node.children = node.children.flatMap((child) => {
|
|
7251
|
+
if (child.type !== "element" || child.tagName !== "a") return [child];
|
|
7252
|
+
const href = child.properties?.href;
|
|
7253
|
+
if (typeof href !== "string" || href === INCOMPLETE_LINK_HREF) return [child];
|
|
7254
|
+
return [{
|
|
7255
|
+
type: "element",
|
|
7256
|
+
tagName: "span",
|
|
7257
|
+
properties: {
|
|
7258
|
+
className: ["group/markdown-link"],
|
|
7259
|
+
"data-boring-agent-part": "chat-url-group"
|
|
7260
|
+
},
|
|
7261
|
+
children: [
|
|
7262
|
+
child,
|
|
7263
|
+
{
|
|
7264
|
+
type: "element",
|
|
7265
|
+
tagName: LINK_ACTIONS_TAG,
|
|
7266
|
+
properties: { href },
|
|
7267
|
+
children: []
|
|
7268
|
+
}
|
|
7269
|
+
]
|
|
7270
|
+
}];
|
|
7271
|
+
});
|
|
7272
|
+
}
|
|
7273
|
+
var rehypeMarkdownLinkActions = () => (tree) => {
|
|
7274
|
+
decorateLinks(tree);
|
|
7275
|
+
};
|
|
7276
|
+
function markdownLinkRehypePlugins(configured, allowedTags) {
|
|
7277
|
+
if (configured) return [...configured, rehypeMarkdownLinkActions];
|
|
7278
|
+
const sanitize = defaultRehypePlugins.sanitize;
|
|
7279
|
+
if (!allowedTags || !Array.isArray(sanitize) || typeof sanitize[1] !== "object" || sanitize[1] === null) {
|
|
7280
|
+
return [...Object.values(defaultRehypePlugins), rehypeMarkdownLinkActions];
|
|
7281
|
+
}
|
|
7282
|
+
const schema = sanitize[1];
|
|
7283
|
+
const augmentedSchema = {
|
|
7284
|
+
...schema,
|
|
7285
|
+
tagNames: [...schema.tagNames ?? [], ...Object.keys(allowedTags)],
|
|
7286
|
+
attributes: { ...schema.attributes, ...allowedTags }
|
|
7287
|
+
};
|
|
7288
|
+
const augmentedSanitize = [sanitize[0], augmentedSchema];
|
|
7289
|
+
const augmentedDefaults = Object.entries(defaultRehypePlugins).map(
|
|
7290
|
+
([name, plugin]) => name === "sanitize" ? augmentedSanitize : plugin
|
|
7291
|
+
);
|
|
7292
|
+
return [...augmentedDefaults, rehypeMarkdownLinkActions];
|
|
7293
|
+
}
|
|
7294
|
+
var MarkdownLinkActions = ({ href }) => {
|
|
7295
|
+
const [copied, setCopied] = useState12(false);
|
|
7296
|
+
const copiedTimerRef = useRef8(void 0);
|
|
7297
|
+
useEffect11(() => () => clearTimeout(copiedTimerRef.current), []);
|
|
7298
|
+
const markCopied = useCallback10(() => {
|
|
7299
|
+
setCopied(true);
|
|
7300
|
+
clearTimeout(copiedTimerRef.current);
|
|
7301
|
+
copiedTimerRef.current = setTimeout(() => setCopied(false), 1500);
|
|
7302
|
+
}, []);
|
|
7303
|
+
const handleCopy = useCallback10(
|
|
7304
|
+
async (event) => {
|
|
7305
|
+
event.preventDefault();
|
|
7306
|
+
event.stopPropagation();
|
|
7307
|
+
if (href && await copyTextToClipboard(href)) markCopied();
|
|
7308
|
+
},
|
|
7309
|
+
[href, markCopied]
|
|
7310
|
+
);
|
|
7311
|
+
const handleOpen = useCallback10((event) => {
|
|
7312
|
+
event.preventDefault();
|
|
7313
|
+
event.stopPropagation();
|
|
7314
|
+
event.currentTarget.closest('[data-boring-agent-part="chat-url-group"]')?.querySelector('[data-streamdown="link"]')?.click();
|
|
7315
|
+
}, []);
|
|
7316
|
+
return /* @__PURE__ */ jsxs16(
|
|
7317
|
+
"span",
|
|
7318
|
+
{
|
|
7319
|
+
className: cn(
|
|
7320
|
+
"pointer-events-none inline-flex shrink-0 items-center gap-px opacity-0 transition-opacity duration-150",
|
|
7321
|
+
"group-hover/markdown-link:pointer-events-auto group-hover/markdown-link:opacity-100",
|
|
7322
|
+
"group-focus-within/markdown-link:pointer-events-auto group-focus-within/markdown-link:opacity-100"
|
|
7323
|
+
),
|
|
7324
|
+
"data-boring-agent-part": "chat-url-actions",
|
|
7325
|
+
children: [
|
|
7326
|
+
/* @__PURE__ */ jsx17(
|
|
7327
|
+
"button",
|
|
7328
|
+
{
|
|
7329
|
+
type: "button",
|
|
7330
|
+
onClick: handleCopy,
|
|
7331
|
+
"aria-label": "Copy URL",
|
|
7332
|
+
title: copied ? "Copied" : "Copy URL",
|
|
7333
|
+
className: cn(
|
|
7334
|
+
"inline-flex size-4 items-center justify-center rounded-[2px]",
|
|
7335
|
+
"text-muted-foreground/70 transition-colors duration-150",
|
|
7336
|
+
"hover:bg-foreground/[0.06] hover:text-muted-foreground",
|
|
7337
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[color:var(--accent)]/40"
|
|
7338
|
+
),
|
|
7339
|
+
children: copied ? /* @__PURE__ */ jsx17(CheckIcon2, { className: "size-3", "aria-hidden": "true" }) : /* @__PURE__ */ jsx17(CopyIcon3, { className: "size-3", "aria-hidden": "true" })
|
|
7340
|
+
}
|
|
7341
|
+
),
|
|
7342
|
+
/* @__PURE__ */ jsx17(
|
|
7343
|
+
"button",
|
|
7344
|
+
{
|
|
7345
|
+
type: "button",
|
|
7346
|
+
onClick: handleOpen,
|
|
7347
|
+
"aria-label": "Open URL in new tab",
|
|
7348
|
+
title: "Open URL in new tab",
|
|
7349
|
+
className: cn(
|
|
7350
|
+
"inline-flex size-4 items-center justify-center rounded-[2px]",
|
|
7351
|
+
"text-muted-foreground/70 transition-colors duration-150",
|
|
7352
|
+
"hover:bg-foreground/[0.06] hover:text-muted-foreground",
|
|
7353
|
+
"focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[color:var(--accent)]/40"
|
|
7354
|
+
),
|
|
7355
|
+
children: /* @__PURE__ */ jsx17(ExternalLinkIcon3, { className: "size-3", "aria-hidden": "true" })
|
|
7356
|
+
}
|
|
7357
|
+
)
|
|
7358
|
+
]
|
|
7359
|
+
}
|
|
7360
|
+
);
|
|
7361
|
+
};
|
|
7362
|
+
var markdownLinkComponents = {
|
|
7363
|
+
[LINK_ACTIONS_TAG]: MarkdownLinkActions
|
|
7364
|
+
};
|
|
7365
|
+
|
|
7366
|
+
// src/front/primitives/message.tsx
|
|
7367
|
+
import { jsx as jsx18, jsxs as jsxs17 } from "react/jsx-runtime";
|
|
7368
|
+
var Message = ({ className, from, ...props }) => /* @__PURE__ */ jsx18(
|
|
6788
7369
|
"div",
|
|
6789
7370
|
{
|
|
6790
7371
|
"data-boring-agent-message-role": from,
|
|
@@ -6800,7 +7381,7 @@ var MessageContent = ({
|
|
|
6800
7381
|
children,
|
|
6801
7382
|
className,
|
|
6802
7383
|
...props
|
|
6803
|
-
}) => /* @__PURE__ */
|
|
7384
|
+
}) => /* @__PURE__ */ jsx18(
|
|
6804
7385
|
"div",
|
|
6805
7386
|
{
|
|
6806
7387
|
className: cn(
|
|
@@ -6817,7 +7398,7 @@ var MessageActions = ({
|
|
|
6817
7398
|
className,
|
|
6818
7399
|
children,
|
|
6819
7400
|
...props
|
|
6820
|
-
}) => /* @__PURE__ */
|
|
7401
|
+
}) => /* @__PURE__ */ jsx18("div", { className: cn("flex items-center gap-1", className), ...props, children });
|
|
6821
7402
|
var MessageAction = ({
|
|
6822
7403
|
tooltip,
|
|
6823
7404
|
children,
|
|
@@ -6826,14 +7407,14 @@ var MessageAction = ({
|
|
|
6826
7407
|
size = "icon-sm",
|
|
6827
7408
|
...props
|
|
6828
7409
|
}) => {
|
|
6829
|
-
const button = /* @__PURE__ */
|
|
7410
|
+
const button = /* @__PURE__ */ jsxs17(Button10, { size, type: "button", variant, ...props, children: [
|
|
6830
7411
|
children,
|
|
6831
|
-
/* @__PURE__ */
|
|
7412
|
+
/* @__PURE__ */ jsx18("span", { className: "sr-only", children: label || tooltip })
|
|
6832
7413
|
] });
|
|
6833
7414
|
if (tooltip) {
|
|
6834
|
-
return /* @__PURE__ */
|
|
6835
|
-
/* @__PURE__ */
|
|
6836
|
-
/* @__PURE__ */
|
|
7415
|
+
return /* @__PURE__ */ jsx18(TooltipProvider, { children: /* @__PURE__ */ jsxs17(Tooltip, { children: [
|
|
7416
|
+
/* @__PURE__ */ jsx18(TooltipTrigger, { asChild: true, children: button }),
|
|
7417
|
+
/* @__PURE__ */ jsx18(TooltipContent, { children: /* @__PURE__ */ jsx18("p", { children: tooltip }) })
|
|
6837
7418
|
] }) });
|
|
6838
7419
|
}
|
|
6839
7420
|
return button;
|
|
@@ -6841,7 +7422,6 @@ var MessageAction = ({
|
|
|
6841
7422
|
var MessageBranchContext = createContext4(
|
|
6842
7423
|
null
|
|
6843
7424
|
);
|
|
6844
|
-
var streamdownPlugins = { cjk, code, math, mermaid };
|
|
6845
7425
|
var DEFAULT_SHIKI_THEME = ["github-light", "github-dark-dimmed"];
|
|
6846
7426
|
function extractCodeBlockLanguage(children) {
|
|
6847
7427
|
if (!children) return void 0;
|
|
@@ -6872,11 +7452,11 @@ function extractCodeBlockText(children) {
|
|
|
6872
7452
|
return walk(children);
|
|
6873
7453
|
}
|
|
6874
7454
|
var MarkdownPre = ({ children, filename }) => {
|
|
6875
|
-
const
|
|
7455
|
+
const code = extractCodeBlockText(children).replace(/\n$/, "");
|
|
6876
7456
|
const language = extractCodeBlockLanguage(children);
|
|
6877
|
-
return /* @__PURE__ */
|
|
6878
|
-
/* @__PURE__ */
|
|
6879
|
-
/* @__PURE__ */
|
|
7457
|
+
return /* @__PURE__ */ jsx18(CodeBlock2, { code, language: language ?? "text", className: "my-3", children: /* @__PURE__ */ jsxs17(CodeBlockHeader, { children: [
|
|
7458
|
+
/* @__PURE__ */ jsx18(CodeBlockTitle, { children: /* @__PURE__ */ jsx18(CodeBlockFilename, { children: filename ?? language ?? "text" }) }),
|
|
7459
|
+
/* @__PURE__ */ jsx18(CodeBlockCopyButton, {})
|
|
6880
7460
|
] }) });
|
|
6881
7461
|
};
|
|
6882
7462
|
var MarkdownCode = ({
|
|
@@ -6886,9 +7466,9 @@ var MarkdownCode = ({
|
|
|
6886
7466
|
...props
|
|
6887
7467
|
}) => {
|
|
6888
7468
|
if (inline === false) {
|
|
6889
|
-
return /* @__PURE__ */
|
|
7469
|
+
return /* @__PURE__ */ jsx18("code", { className, ...props, children });
|
|
6890
7470
|
}
|
|
6891
|
-
return /* @__PURE__ */
|
|
7471
|
+
return /* @__PURE__ */ jsx18(
|
|
6892
7472
|
"code",
|
|
6893
7473
|
{
|
|
6894
7474
|
className: cn(
|
|
@@ -6905,23 +7485,33 @@ var markdownComponents = {
|
|
|
6905
7485
|
code: MarkdownCode
|
|
6906
7486
|
};
|
|
6907
7487
|
var MessageResponse = memo3(
|
|
6908
|
-
({ className, shikiTheme, components, codeFilename, ...props }) =>
|
|
6909
|
-
|
|
6910
|
-
|
|
6911
|
-
|
|
6912
|
-
|
|
6913
|
-
|
|
6914
|
-
|
|
6915
|
-
|
|
6916
|
-
|
|
6917
|
-
|
|
6918
|
-
|
|
6919
|
-
|
|
6920
|
-
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
7488
|
+
({ className, shikiTheme, components, codeFilename, rehypePlugins, allowedTags, ...props }) => {
|
|
7489
|
+
const streamdownPlugins = useStreamdownPlugins(props.children, { code: false });
|
|
7490
|
+
const linkRehypePlugins = useMemo8(
|
|
7491
|
+
() => markdownLinkRehypePlugins(rehypePlugins, allowedTags),
|
|
7492
|
+
[allowedTags, rehypePlugins]
|
|
7493
|
+
);
|
|
7494
|
+
return /* @__PURE__ */ jsx18(
|
|
7495
|
+
Streamdown2,
|
|
7496
|
+
{
|
|
7497
|
+
className: cn(
|
|
7498
|
+
"size-full [&>*:first-child]:mt-0 [&>*:last-child]:mb-0",
|
|
7499
|
+
className
|
|
7500
|
+
),
|
|
7501
|
+
plugins: streamdownPlugins,
|
|
7502
|
+
rehypePlugins: linkRehypePlugins,
|
|
7503
|
+
allowedTags,
|
|
7504
|
+
shikiTheme: shikiTheme ?? DEFAULT_SHIKI_THEME,
|
|
7505
|
+
components: {
|
|
7506
|
+
...markdownComponents,
|
|
7507
|
+
...components ?? {},
|
|
7508
|
+
...markdownLinkComponents,
|
|
7509
|
+
...codeFilename ? { pre: (props2) => /* @__PURE__ */ jsx18(MarkdownPre, { ...props2, filename: codeFilename }) } : {}
|
|
7510
|
+
},
|
|
7511
|
+
...props
|
|
7512
|
+
}
|
|
7513
|
+
);
|
|
7514
|
+
},
|
|
6925
7515
|
(prevProps, nextProps) => prevProps.children === nextProps.children && nextProps.isAnimating === prevProps.isAnimating && nextProps.components === prevProps.components && prevProps.codeFilename === nextProps.codeFilename
|
|
6926
7516
|
);
|
|
6927
7517
|
MessageResponse.displayName = "MessageResponse";
|
|
@@ -6933,27 +7523,23 @@ import {
|
|
|
6933
7523
|
CollapsibleContent as CollapsibleContent2,
|
|
6934
7524
|
CollapsibleTrigger as CollapsibleTrigger3
|
|
6935
7525
|
} from "@hachej/boring-ui-kit";
|
|
6936
|
-
import { cjk as cjk2 } from "@streamdown/cjk";
|
|
6937
|
-
import { code as code2 } from "@streamdown/code";
|
|
6938
|
-
import { math as math2 } from "@streamdown/math";
|
|
6939
|
-
import { mermaid as mermaid2 } from "@streamdown/mermaid";
|
|
6940
7526
|
import { BrainIcon, ChevronDownIcon as ChevronDownIcon3 } from "lucide-react";
|
|
6941
7527
|
import {
|
|
6942
7528
|
createContext as createContext5,
|
|
6943
7529
|
memo as memo5,
|
|
6944
|
-
useCallback as
|
|
7530
|
+
useCallback as useCallback12,
|
|
6945
7531
|
useContext as useContext5,
|
|
6946
|
-
useEffect as
|
|
6947
|
-
useMemo as
|
|
6948
|
-
useRef as
|
|
6949
|
-
useState as
|
|
7532
|
+
useEffect as useEffect13,
|
|
7533
|
+
useMemo as useMemo10,
|
|
7534
|
+
useRef as useRef9,
|
|
7535
|
+
useState as useState14
|
|
6950
7536
|
} from "react";
|
|
6951
|
-
import { Streamdown as
|
|
7537
|
+
import { Streamdown as Streamdown3 } from "streamdown";
|
|
6952
7538
|
|
|
6953
7539
|
// src/front/primitives/shimmer.tsx
|
|
6954
7540
|
import { motion } from "motion/react";
|
|
6955
|
-
import { memo as memo4, useMemo as
|
|
6956
|
-
import { jsx as
|
|
7541
|
+
import { memo as memo4, useMemo as useMemo9 } from "react";
|
|
7542
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
6957
7543
|
var motionComponentCache = /* @__PURE__ */ new Map();
|
|
6958
7544
|
var getMotionComponent = (element) => {
|
|
6959
7545
|
let component = motionComponentCache.get(element);
|
|
@@ -6973,11 +7559,11 @@ var ShimmerComponent = ({
|
|
|
6973
7559
|
const MotionComponent = getMotionComponent(
|
|
6974
7560
|
Component
|
|
6975
7561
|
);
|
|
6976
|
-
const dynamicSpread =
|
|
7562
|
+
const dynamicSpread = useMemo9(
|
|
6977
7563
|
() => (children?.length ?? 0) * spread,
|
|
6978
7564
|
[children, spread]
|
|
6979
7565
|
);
|
|
6980
|
-
return /* @__PURE__ */
|
|
7566
|
+
return /* @__PURE__ */ jsx19(
|
|
6981
7567
|
MotionComponent,
|
|
6982
7568
|
{
|
|
6983
7569
|
animate: { backgroundPosition: "0% center" },
|
|
@@ -7003,7 +7589,7 @@ var ShimmerComponent = ({
|
|
|
7003
7589
|
var Shimmer = memo4(ShimmerComponent);
|
|
7004
7590
|
|
|
7005
7591
|
// src/front/primitives/reasoning.tsx
|
|
7006
|
-
import { Fragment as Fragment8, jsx as
|
|
7592
|
+
import { Fragment as Fragment8, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
7007
7593
|
var ReasoningContext = createContext5(null);
|
|
7008
7594
|
var useReasoning = () => {
|
|
7009
7595
|
const context = useContext5(ReasoningContext);
|
|
@@ -7037,10 +7623,10 @@ var Reasoning = memo5(
|
|
|
7037
7623
|
defaultProp: void 0,
|
|
7038
7624
|
prop: durationProp
|
|
7039
7625
|
});
|
|
7040
|
-
const hasEverStreamedRef =
|
|
7041
|
-
const [hasAutoClosed, setHasAutoClosed] =
|
|
7042
|
-
const startTimeRef =
|
|
7043
|
-
|
|
7626
|
+
const hasEverStreamedRef = useRef9(isStreaming);
|
|
7627
|
+
const [hasAutoClosed, setHasAutoClosed] = useState14(false);
|
|
7628
|
+
const startTimeRef = useRef9(null);
|
|
7629
|
+
useEffect13(() => {
|
|
7044
7630
|
if (isStreaming) {
|
|
7045
7631
|
hasEverStreamedRef.current = true;
|
|
7046
7632
|
if (startTimeRef.current === null) {
|
|
@@ -7051,12 +7637,12 @@ var Reasoning = memo5(
|
|
|
7051
7637
|
startTimeRef.current = null;
|
|
7052
7638
|
}
|
|
7053
7639
|
}, [isStreaming, setDuration]);
|
|
7054
|
-
|
|
7640
|
+
useEffect13(() => {
|
|
7055
7641
|
if (isStreaming && !isOpen && !isExplicitlyClosed) {
|
|
7056
7642
|
setIsOpen(true);
|
|
7057
7643
|
}
|
|
7058
7644
|
}, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);
|
|
7059
|
-
|
|
7645
|
+
useEffect13(() => {
|
|
7060
7646
|
if (hasEverStreamedRef.current && autoClose && !isStreaming && isOpen && !hasAutoClosed) {
|
|
7061
7647
|
const timer = setTimeout(() => {
|
|
7062
7648
|
setIsOpen(false);
|
|
@@ -7065,17 +7651,17 @@ var Reasoning = memo5(
|
|
|
7065
7651
|
return () => clearTimeout(timer);
|
|
7066
7652
|
}
|
|
7067
7653
|
}, [isStreaming, isOpen, setIsOpen, hasAutoClosed, autoClose]);
|
|
7068
|
-
const handleOpenChange =
|
|
7654
|
+
const handleOpenChange = useCallback12(
|
|
7069
7655
|
(newOpen) => {
|
|
7070
7656
|
setIsOpen(newOpen);
|
|
7071
7657
|
},
|
|
7072
7658
|
[setIsOpen]
|
|
7073
7659
|
);
|
|
7074
|
-
const contextValue =
|
|
7660
|
+
const contextValue = useMemo10(
|
|
7075
7661
|
() => ({ duration, isOpen, isStreaming, setIsOpen }),
|
|
7076
7662
|
[duration, isOpen, isStreaming, setIsOpen]
|
|
7077
7663
|
);
|
|
7078
|
-
return /* @__PURE__ */
|
|
7664
|
+
return /* @__PURE__ */ jsx20(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx20(
|
|
7079
7665
|
Collapsible2,
|
|
7080
7666
|
{
|
|
7081
7667
|
className: cn("not-prose mb-2", className),
|
|
@@ -7089,12 +7675,12 @@ var Reasoning = memo5(
|
|
|
7089
7675
|
);
|
|
7090
7676
|
var defaultGetThinkingMessage = (isStreaming, duration) => {
|
|
7091
7677
|
if (isStreaming || duration === 0) {
|
|
7092
|
-
return /* @__PURE__ */
|
|
7678
|
+
return /* @__PURE__ */ jsx20(Shimmer, { duration: 1, children: "thinking" });
|
|
7093
7679
|
}
|
|
7094
7680
|
if (duration === void 0) {
|
|
7095
|
-
return /* @__PURE__ */
|
|
7681
|
+
return /* @__PURE__ */ jsx20("span", { children: "thoughts" });
|
|
7096
7682
|
}
|
|
7097
|
-
return /* @__PURE__ */
|
|
7683
|
+
return /* @__PURE__ */ jsxs18("span", { children: [
|
|
7098
7684
|
"thoughts \xB7 ",
|
|
7099
7685
|
duration,
|
|
7100
7686
|
"s"
|
|
@@ -7108,7 +7694,7 @@ var ReasoningTrigger = memo5(
|
|
|
7108
7694
|
...props
|
|
7109
7695
|
}) => {
|
|
7110
7696
|
const { isStreaming, isOpen, duration } = useReasoning();
|
|
7111
|
-
return /* @__PURE__ */
|
|
7697
|
+
return /* @__PURE__ */ jsx20(
|
|
7112
7698
|
CollapsibleTrigger3,
|
|
7113
7699
|
{
|
|
7114
7700
|
className: cn(
|
|
@@ -7116,10 +7702,10 @@ var ReasoningTrigger = memo5(
|
|
|
7116
7702
|
className
|
|
7117
7703
|
),
|
|
7118
7704
|
...props,
|
|
7119
|
-
children: children ?? /* @__PURE__ */
|
|
7120
|
-
/* @__PURE__ */
|
|
7705
|
+
children: children ?? /* @__PURE__ */ jsxs18(Fragment8, { children: [
|
|
7706
|
+
/* @__PURE__ */ jsx20(BrainIcon, { className: "size-3" }),
|
|
7121
7707
|
getThinkingMessage(isStreaming, duration),
|
|
7122
|
-
/* @__PURE__ */
|
|
7708
|
+
/* @__PURE__ */ jsx20(
|
|
7123
7709
|
ChevronDownIcon3,
|
|
7124
7710
|
{
|
|
7125
7711
|
className: cn(
|
|
@@ -7133,20 +7719,22 @@ var ReasoningTrigger = memo5(
|
|
|
7133
7719
|
);
|
|
7134
7720
|
}
|
|
7135
7721
|
);
|
|
7136
|
-
var streamdownPlugins2 = { cjk: cjk2, code: code2, math: math2, mermaid: mermaid2 };
|
|
7137
7722
|
var ReasoningContent = memo5(
|
|
7138
|
-
({ className, children, ...props }) =>
|
|
7139
|
-
|
|
7140
|
-
|
|
7141
|
-
|
|
7142
|
-
|
|
7143
|
-
|
|
7144
|
-
|
|
7145
|
-
|
|
7146
|
-
|
|
7147
|
-
|
|
7148
|
-
|
|
7149
|
-
|
|
7723
|
+
({ className, children, ...props }) => {
|
|
7724
|
+
const streamdownPlugins = useStreamdownPlugins(children);
|
|
7725
|
+
return /* @__PURE__ */ jsx20(
|
|
7726
|
+
CollapsibleContent2,
|
|
7727
|
+
{
|
|
7728
|
+
className: cn(
|
|
7729
|
+
"mt-2 border-l border-border/40 pl-3 text-xs",
|
|
7730
|
+
"data-[state=closed]:fade-out-0 data-[state=closed]:slide-out-to-top-2 data-[state=open]:slide-in-from-top-2 text-muted-foreground/75 outline-none data-[state=closed]:animate-out data-[state=open]:animate-in",
|
|
7731
|
+
className
|
|
7732
|
+
),
|
|
7733
|
+
...props,
|
|
7734
|
+
children: /* @__PURE__ */ jsx20(Streamdown3, { plugins: streamdownPlugins, children })
|
|
7735
|
+
}
|
|
7736
|
+
);
|
|
7737
|
+
}
|
|
7150
7738
|
);
|
|
7151
7739
|
Reasoning.displayName = "Reasoning";
|
|
7152
7740
|
ReasoningTrigger.displayName = "ReasoningTrigger";
|
|
@@ -7154,7 +7742,7 @@ ReasoningContent.displayName = "ReasoningContent";
|
|
|
7154
7742
|
|
|
7155
7743
|
// src/front/primitives/tool-call-group.tsx
|
|
7156
7744
|
import { ChevronDownIcon as ChevronDownIcon4 } from "lucide-react";
|
|
7157
|
-
import { memo as memo6, useCallback as
|
|
7745
|
+
import { memo as memo6, useCallback as useCallback13, useEffect as useEffect14, useMemo as useMemo11, useState as useState15 } from "react";
|
|
7158
7746
|
import { Collapsible as Collapsible3, CollapsibleContent as CollapsibleContent3, CollapsibleTrigger as CollapsibleTrigger4 } from "@hachej/boring-ui-kit";
|
|
7159
7747
|
|
|
7160
7748
|
// src/front/primitives/tool-call-group-state.ts
|
|
@@ -7193,7 +7781,7 @@ var TOOL_GROUP_VISUAL_PRESENTATION = {
|
|
|
7193
7781
|
};
|
|
7194
7782
|
|
|
7195
7783
|
// src/front/primitives/tool-call-group.tsx
|
|
7196
|
-
import { jsx as
|
|
7784
|
+
import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
7197
7785
|
function isInputRunningState(state) {
|
|
7198
7786
|
return state === "input-streaming" || state === "input-available";
|
|
7199
7787
|
}
|
|
@@ -7243,7 +7831,7 @@ function resolveVisualState({
|
|
|
7243
7831
|
return "settled";
|
|
7244
7832
|
}
|
|
7245
7833
|
var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
7246
|
-
const toolParts =
|
|
7834
|
+
const toolParts = useMemo11(() => tools.map(({ part, key }) => {
|
|
7247
7835
|
const toolPart = toToolPart(part);
|
|
7248
7836
|
return toolPart ? { part: toolPart, key } : null;
|
|
7249
7837
|
}).filter((entry) => Boolean(entry)), [tools]);
|
|
@@ -7252,8 +7840,8 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7252
7840
|
const hasAborted = toolParts.some(({ part }) => part.state === "aborted") && !workspaceNotReady;
|
|
7253
7841
|
const hasRunningTool = toolParts.some(({ part }) => isInputRunningState(part.state) && !getWorkspaceNotReadyStatus(part.output));
|
|
7254
7842
|
const approvalNeeded = toolParts.some(({ part }) => isApprovalRequestedState(part.state));
|
|
7255
|
-
const [isOpen, setIsOpen] =
|
|
7256
|
-
const handleOpenChange =
|
|
7843
|
+
const [isOpen, setIsOpen] = useState15(false);
|
|
7844
|
+
const handleOpenChange = useCallback13((open) => setIsOpen(open), []);
|
|
7257
7845
|
const visualState = resolveVisualState({
|
|
7258
7846
|
hasRunningTool,
|
|
7259
7847
|
approvalNeeded,
|
|
@@ -7262,10 +7850,10 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7262
7850
|
hasAborted
|
|
7263
7851
|
});
|
|
7264
7852
|
const isRunning = visualState === RUNNING_TOOL_GROUP_VISUAL_STATE;
|
|
7265
|
-
const [elapsedSeconds, setElapsedSeconds] =
|
|
7266
|
-
const title =
|
|
7853
|
+
const [elapsedSeconds, setElapsedSeconds] = useState15(0);
|
|
7854
|
+
const title = useMemo11(() => buildTitle(toolParts.map(({ part }) => part), visualState), [toolParts, visualState]);
|
|
7267
7855
|
const elapsedLabel = isRunning ? `Running ${formatElapsed(elapsedSeconds)}` : null;
|
|
7268
|
-
|
|
7856
|
+
useEffect14(() => {
|
|
7269
7857
|
if (!isRunning) {
|
|
7270
7858
|
setElapsedSeconds(0);
|
|
7271
7859
|
return;
|
|
@@ -7282,7 +7870,7 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7282
7870
|
const { renderer } = resolveToolRendererForPart(part, mergedToolRenderers);
|
|
7283
7871
|
return renderer.presentation === "inline" ? [key] : [];
|
|
7284
7872
|
}));
|
|
7285
|
-
return /* @__PURE__ */
|
|
7873
|
+
return /* @__PURE__ */ jsxs19(
|
|
7286
7874
|
Collapsible3,
|
|
7287
7875
|
{
|
|
7288
7876
|
open: isOpen,
|
|
@@ -7293,9 +7881,9 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7293
7881
|
toolParts.map(({ part, key }) => {
|
|
7294
7882
|
if (!inlineToolKeys.has(key)) return null;
|
|
7295
7883
|
const { renderer, part: resolvedPart, resolution } = resolveToolRendererForPart(part, mergedToolRenderers);
|
|
7296
|
-
return /* @__PURE__ */
|
|
7884
|
+
return /* @__PURE__ */ jsx21("div", { "data-boring-agent-part": "inline-tool-renderer", "data-tool-call-id": resolvedPart.toolCallId, "data-tool-renderer-key": resolution.key, children: renderer(resolvedPart) }, key);
|
|
7297
7885
|
}),
|
|
7298
|
-
/* @__PURE__ */
|
|
7886
|
+
/* @__PURE__ */ jsxs19(
|
|
7299
7887
|
CollapsibleTrigger4,
|
|
7300
7888
|
{
|
|
7301
7889
|
"aria-label": `Tool calls: ${title}`,
|
|
@@ -7307,7 +7895,7 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7307
7895
|
TOOL_GROUP_VISUAL_PRESENTATION[visualState].triggerClassName
|
|
7308
7896
|
),
|
|
7309
7897
|
children: [
|
|
7310
|
-
/* @__PURE__ */
|
|
7898
|
+
/* @__PURE__ */ jsx21("span", { className: "flex size-4 shrink-0 items-center justify-center", "aria-hidden": "true", children: /* @__PURE__ */ jsx21(
|
|
7311
7899
|
"span",
|
|
7312
7900
|
{
|
|
7313
7901
|
"data-boring-agent-part": "tool-group-state-dot",
|
|
@@ -7317,10 +7905,10 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7317
7905
|
)
|
|
7318
7906
|
}
|
|
7319
7907
|
) }),
|
|
7320
|
-
/* @__PURE__ */
|
|
7321
|
-
elapsedLabel ? /* @__PURE__ */
|
|
7322
|
-
/* @__PURE__ */
|
|
7323
|
-
/* @__PURE__ */
|
|
7908
|
+
/* @__PURE__ */ jsx21("span", { "data-boring-agent-part": "tool-group-title", children: workspaceNotReady ? workspaceNotReady.message : title }),
|
|
7909
|
+
elapsedLabel ? /* @__PURE__ */ jsx21("span", { className: "ml-1 shrink-0 tabular-nums text-[12px] text-muted-foreground/70", children: elapsedLabel }) : null,
|
|
7910
|
+
/* @__PURE__ */ jsx21("span", { className: "ml-1 shrink-0 tabular-nums text-[12px] text-muted-foreground/70", children: toolParts.length }),
|
|
7911
|
+
/* @__PURE__ */ jsx21(
|
|
7324
7912
|
ChevronDownIcon4,
|
|
7325
7913
|
{
|
|
7326
7914
|
className: cn(
|
|
@@ -7332,19 +7920,19 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7332
7920
|
]
|
|
7333
7921
|
}
|
|
7334
7922
|
),
|
|
7335
|
-
/* @__PURE__ */
|
|
7923
|
+
/* @__PURE__ */ jsx21(CollapsibleContent3, { className: "overflow-hidden data-[state=closed]:animate-[boring-collapse-close_200ms_ease] data-[state=open]:animate-[boring-collapse-open_200ms_ease]", children: /* @__PURE__ */ jsxs19(
|
|
7336
7924
|
"div",
|
|
7337
7925
|
{
|
|
7338
7926
|
"data-boring-agent-part": "tool-group-details",
|
|
7339
7927
|
className: "relative mt-1.5 w-full max-w-2xl pl-[18px]",
|
|
7340
7928
|
children: [
|
|
7341
|
-
/* @__PURE__ */
|
|
7342
|
-
/* @__PURE__ */
|
|
7929
|
+
/* @__PURE__ */ jsx21("div", { className: "absolute left-[5px] top-0 bottom-2 w-px bg-border/35" }),
|
|
7930
|
+
/* @__PURE__ */ jsx21("div", { className: "flex min-w-0 flex-col gap-1.5 [&_[data-boring-agent-part=tool-card]]:!my-0", children: toolParts.map(({ part, key }) => {
|
|
7343
7931
|
const { renderer, part: resolvedPart, resolution } = resolveToolRendererForPart(
|
|
7344
7932
|
part,
|
|
7345
7933
|
inlineToolKeys.has(key) ? {} : mergedToolRenderers
|
|
7346
7934
|
);
|
|
7347
|
-
return /* @__PURE__ */
|
|
7935
|
+
return /* @__PURE__ */ jsx21(
|
|
7348
7936
|
"div",
|
|
7349
7937
|
{
|
|
7350
7938
|
className: "min-w-0",
|
|
@@ -7366,19 +7954,19 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7366
7954
|
ToolCallGroup.displayName = "ToolCallGroup";
|
|
7367
7955
|
|
|
7368
7956
|
// src/front/chat/messageContributions.tsx
|
|
7369
|
-
import { createContext as createContext6, createElement, useContext as useContext6, useMemo as
|
|
7370
|
-
import { jsx as
|
|
7957
|
+
import { createContext as createContext6, createElement, useContext as useContext6, useMemo as useMemo12 } from "react";
|
|
7958
|
+
import { jsx as jsx22 } from "react/jsx-runtime";
|
|
7371
7959
|
var ChatMessageContributionContext = createContext6([]);
|
|
7372
7960
|
function ChatMessageContributionProvider({
|
|
7373
7961
|
contribution,
|
|
7374
7962
|
children
|
|
7375
7963
|
}) {
|
|
7376
7964
|
const parent = useContext6(ChatMessageContributionContext);
|
|
7377
|
-
const contributions =
|
|
7965
|
+
const contributions = useMemo12(
|
|
7378
7966
|
() => [contribution, ...parent.filter((entry) => entry.id !== contribution.id)],
|
|
7379
7967
|
[contribution, parent]
|
|
7380
7968
|
);
|
|
7381
|
-
return /* @__PURE__ */
|
|
7969
|
+
return /* @__PURE__ */ jsx22(ChatMessageContributionContext.Provider, { value: contributions, children });
|
|
7382
7970
|
}
|
|
7383
7971
|
function useCustomChatMessage(message) {
|
|
7384
7972
|
const contributions = useContext6(ChatMessageContributionContext);
|
|
@@ -7395,7 +7983,7 @@ function ChatMessageContributionBoundary({
|
|
|
7395
7983
|
|
|
7396
7984
|
// src/front/chat/components/MessageMentions.tsx
|
|
7397
7985
|
import { Children, cloneElement, isValidElement as isValidElement2 } from "react";
|
|
7398
|
-
import { Fragment as Fragment9, jsx as
|
|
7986
|
+
import { Fragment as Fragment9, jsx as jsx23 } from "react/jsx-runtime";
|
|
7399
7987
|
var TERMINAL_BOUNDARY = String.raw`(?=$|\s|[.,;!?)}\]"'”’]+(?=$|\s))`;
|
|
7400
7988
|
var PREFIX_BOUNDARY = String.raw`(^|[\s(\[{"'“‘])`;
|
|
7401
7989
|
function escapeRegExp2(value) {
|
|
@@ -7504,7 +8092,7 @@ function MessageMentions({
|
|
|
7504
8092
|
}).map((segment, segmentIndex) => {
|
|
7505
8093
|
if (!segment.mention) return segment.text;
|
|
7506
8094
|
const actionLabel = mentionActionLabel(segment.mention);
|
|
7507
|
-
return /* @__PURE__ */
|
|
8095
|
+
return /* @__PURE__ */ jsx23(
|
|
7508
8096
|
"button",
|
|
7509
8097
|
{
|
|
7510
8098
|
type: "button",
|
|
@@ -7530,7 +8118,7 @@ function MessageMentions({
|
|
|
7530
8118
|
return cloneElement(
|
|
7531
8119
|
element,
|
|
7532
8120
|
void 0,
|
|
7533
|
-
/* @__PURE__ */
|
|
8121
|
+
/* @__PURE__ */ jsx23(
|
|
7534
8122
|
MessageMentions,
|
|
7535
8123
|
{
|
|
7536
8124
|
catalog,
|
|
@@ -7548,19 +8136,19 @@ function MessageMentions({
|
|
|
7548
8136
|
return nodes.map(decorate);
|
|
7549
8137
|
}
|
|
7550
8138
|
function createMessageMentionMarkdownComponents(catalog, onActivate) {
|
|
7551
|
-
const decorate = (children) => /* @__PURE__ */
|
|
8139
|
+
const decorate = (children) => /* @__PURE__ */ jsx23(MessageMentions, { catalog, onActivate, children });
|
|
7552
8140
|
const paragraph = ({ node: _node, children, ...props }) => {
|
|
7553
8141
|
const content = Children.toArray(children).filter((child) => child !== null && child !== "");
|
|
7554
8142
|
if (content.length === 1 && isValidElement2(content[0])) {
|
|
7555
8143
|
const child = content[0];
|
|
7556
|
-
if (child.props.node?.tagName === "img") return /* @__PURE__ */
|
|
7557
|
-
if (child.props.node?.tagName === "code" && "data-block" in child.props) return /* @__PURE__ */
|
|
8144
|
+
if (child.props.node?.tagName === "img") return /* @__PURE__ */ jsx23(Fragment9, { children });
|
|
8145
|
+
if (child.props.node?.tagName === "code" && "data-block" in child.props) return /* @__PURE__ */ jsx23(Fragment9, { children });
|
|
7558
8146
|
}
|
|
7559
|
-
return /* @__PURE__ */
|
|
8147
|
+
return /* @__PURE__ */ jsx23("p", { ...props, children: decorate(children) });
|
|
7560
8148
|
};
|
|
7561
|
-
const tableHeader = ({ node: _node, children, className, ...props }) => /* @__PURE__ */
|
|
7562
|
-
const tableCell = ({ node: _node, children, className, ...props }) => /* @__PURE__ */
|
|
7563
|
-
const listItem = ({ node: _node, children, className, ...props }) => /* @__PURE__ */
|
|
8149
|
+
const tableHeader = ({ node: _node, children, className, ...props }) => /* @__PURE__ */ jsx23("th", { ...props, "data-streamdown": "table-header-cell", className: cn("whitespace-nowrap px-4 py-2 text-left font-semibold text-sm", className), children: decorate(children) });
|
|
8150
|
+
const tableCell = ({ node: _node, children, className, ...props }) => /* @__PURE__ */ jsx23("td", { ...props, "data-streamdown": "table-cell", className: cn("px-4 py-2 text-sm", className), children: decorate(children) });
|
|
8151
|
+
const listItem = ({ node: _node, children, className, ...props }) => /* @__PURE__ */ jsx23("li", { ...props, "data-streamdown": "list-item", className: cn("py-1 [&>p]:inline", className), children: decorate(children) });
|
|
7564
8152
|
const headingClasses = {
|
|
7565
8153
|
h1: "text-3xl",
|
|
7566
8154
|
h2: "text-2xl",
|
|
@@ -7569,8 +8157,8 @@ function createMessageMentionMarkdownComponents(catalog, onActivate) {
|
|
|
7569
8157
|
h5: "text-base",
|
|
7570
8158
|
h6: "text-sm"
|
|
7571
8159
|
};
|
|
7572
|
-
const heading = (Tag) => ({ node: _node, children, className, ...props }) => /* @__PURE__ */
|
|
7573
|
-
const inlineCode = ({ node: _node, children, className, ...props }) => /* @__PURE__ */
|
|
8160
|
+
const heading = (Tag) => ({ node: _node, children, className, ...props }) => /* @__PURE__ */ jsx23(Tag, { ...props, "data-streamdown": `heading-${Tag.slice(1)}`, className: cn("mt-6 mb-2 font-semibold", headingClasses[Tag], className), children: decorate(children) });
|
|
8161
|
+
const inlineCode = ({ node: _node, children, className, ...props }) => /* @__PURE__ */ jsx23(
|
|
7574
8162
|
"code",
|
|
7575
8163
|
{
|
|
7576
8164
|
...props,
|
|
@@ -7594,7 +8182,7 @@ function createMessageMentionMarkdownComponents(catalog, onActivate) {
|
|
|
7594
8182
|
}
|
|
7595
8183
|
|
|
7596
8184
|
// src/front/chat/components/PiTimelineMessage.tsx
|
|
7597
|
-
import { jsx as
|
|
8185
|
+
import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
7598
8186
|
var EMPTY_MENTION_CATALOG = { commands: [], skills: [], files: false };
|
|
7599
8187
|
var COLLAPSIBLE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
7600
8188
|
"read",
|
|
@@ -7610,7 +8198,7 @@ function isCollapsibleTool(part) {
|
|
|
7610
8198
|
return part.type === "tool-call" && COLLAPSIBLE_TOOL_NAMES.has(part.toolName);
|
|
7611
8199
|
}
|
|
7612
8200
|
function PiTimelineMessage(props) {
|
|
7613
|
-
return /* @__PURE__ */
|
|
8201
|
+
return /* @__PURE__ */ jsx24(ChatMessageContributionBoundary, { message: props.message, children: /* @__PURE__ */ jsx24(DefaultPiTimelineMessage, { ...props }) });
|
|
7614
8202
|
}
|
|
7615
8203
|
function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts, toolRenderers, mentionCatalog = EMPTY_MENTION_CATALOG, onMentionActivate }) {
|
|
7616
8204
|
const role = message.role;
|
|
@@ -7620,7 +8208,7 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7620
8208
|
const finalParts = groupRenderableParts(message);
|
|
7621
8209
|
const attachmentSummaryPaths = role === "user" ? attachmentPathsFromTextParts(textParts) : [];
|
|
7622
8210
|
const openArtifact = useOpenArtifact();
|
|
7623
|
-
const effectiveMentionCatalog =
|
|
8211
|
+
const effectiveMentionCatalog = useMemo13(() => ({
|
|
7624
8212
|
commands: mentionCatalog.commands,
|
|
7625
8213
|
skills: mentionCatalog.skills,
|
|
7626
8214
|
files: mentionCatalog.files && Boolean(openArtifact)
|
|
@@ -7630,9 +8218,9 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7630
8218
|
...effectiveMentionCatalog.skills.map((skill) => `skill:${skill.name}:${skill.commandName}`),
|
|
7631
8219
|
effectiveMentionCatalog.files ? "files:enabled" : "files:disabled"
|
|
7632
8220
|
].join("|");
|
|
7633
|
-
const mentionActivateRef =
|
|
8221
|
+
const mentionActivateRef = useRef10(onMentionActivate);
|
|
7634
8222
|
mentionActivateRef.current = onMentionActivate;
|
|
7635
|
-
const activateCurrentMention =
|
|
8223
|
+
const activateCurrentMention = useCallback14((mention) => {
|
|
7636
8224
|
if (mention.kind === "file") {
|
|
7637
8225
|
openArtifact?.(mention.path);
|
|
7638
8226
|
return;
|
|
@@ -7642,12 +8230,12 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7642
8230
|
const hasMentions = effectiveMentionCatalog.files || effectiveMentionCatalog.commands.length > 0 || effectiveMentionCatalog.skills.length > 0;
|
|
7643
8231
|
const messageIsStreaming = isAssistant && isLast && (isStreaming || message.status === "streaming");
|
|
7644
8232
|
const mentionsEnabled = Boolean(isAssistant && !messageIsStreaming && hasMentions);
|
|
7645
|
-
const mentionMarkdownComponents =
|
|
8233
|
+
const mentionMarkdownComponents = useMemo13(
|
|
7646
8234
|
() => mentionsEnabled ? createMessageMentionMarkdownComponents(effectiveMentionCatalog, activateCurrentMention) : void 0,
|
|
7647
8235
|
[activateCurrentMention, effectiveMentionCatalog, mentionSignature, mentionsEnabled]
|
|
7648
8236
|
);
|
|
7649
8237
|
const shouldReserveStreamingActions = messageIsStreaming;
|
|
7650
|
-
return /* @__PURE__ */
|
|
8238
|
+
return /* @__PURE__ */ jsxs20(
|
|
7651
8239
|
Message,
|
|
7652
8240
|
{
|
|
7653
8241
|
from: role,
|
|
@@ -7656,8 +8244,8 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7656
8244
|
"data-boring-agent-message-role": role,
|
|
7657
8245
|
"data-boring-agent-message-status": message.status,
|
|
7658
8246
|
children: [
|
|
7659
|
-
/* @__PURE__ */
|
|
7660
|
-
fileParts.length > 0 ? /* @__PURE__ */
|
|
8247
|
+
/* @__PURE__ */ jsxs20(MessageContent, { children: [
|
|
8248
|
+
fileParts.length > 0 ? /* @__PURE__ */ jsx24(
|
|
7661
8249
|
Attachments,
|
|
7662
8250
|
{
|
|
7663
8251
|
variant: role === "user" ? "inline" : "list",
|
|
@@ -7682,7 +8270,7 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7682
8270
|
event.preventDefault();
|
|
7683
8271
|
openAttachment();
|
|
7684
8272
|
};
|
|
7685
|
-
return /* @__PURE__ */
|
|
8273
|
+
return /* @__PURE__ */ jsxs20(
|
|
7686
8274
|
Attachment,
|
|
7687
8275
|
{
|
|
7688
8276
|
data: toAttachmentData(file, `file-${message.id}-${index}`),
|
|
@@ -7696,8 +8284,8 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7696
8284
|
onKeyDown: openAttachmentFromKeyboard
|
|
7697
8285
|
} : void 0,
|
|
7698
8286
|
children: [
|
|
7699
|
-
/* @__PURE__ */
|
|
7700
|
-
/* @__PURE__ */
|
|
8287
|
+
/* @__PURE__ */ jsx24(AttachmentPreview, { className: role === "user" ? "!size-5 shrink-0 rounded-[var(--radius-sm)]" : "size-10 shrink-0 rounded-[var(--radius-md)]" }),
|
|
8288
|
+
/* @__PURE__ */ jsx24(AttachmentInfo, { className: role === "user" ? "min-w-0 max-w-[220px] flex-1 text-[12px]" : "min-w-0 flex-1" })
|
|
7701
8289
|
]
|
|
7702
8290
|
},
|
|
7703
8291
|
`file-${message.id}-${index}`
|
|
@@ -7707,7 +8295,7 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7707
8295
|
) : null,
|
|
7708
8296
|
finalParts.map((item, index) => {
|
|
7709
8297
|
if (item.kind === "reasoning") {
|
|
7710
|
-
return /* @__PURE__ */
|
|
8298
|
+
return /* @__PURE__ */ jsx24(
|
|
7711
8299
|
TimelineReasoningPart,
|
|
7712
8300
|
{
|
|
7713
8301
|
item,
|
|
@@ -7717,15 +8305,15 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7717
8305
|
);
|
|
7718
8306
|
}
|
|
7719
8307
|
if (item.kind === "tool-group") {
|
|
7720
|
-
return /* @__PURE__ */
|
|
8308
|
+
return /* @__PURE__ */ jsx24("div", { "data-boring-agent-part": "message-tools", children: /* @__PURE__ */ jsx24(ToolCallGroup, { tools: item.tools, mergedToolRenderers: toolRenderers }) }, item.key);
|
|
7721
8309
|
}
|
|
7722
8310
|
if (item.kind === "tool-plain") {
|
|
7723
|
-
return /* @__PURE__ */
|
|
8311
|
+
return /* @__PURE__ */ jsx24("div", { "data-boring-agent-part": "message-tools", children: /* @__PURE__ */ jsx24(PlainToolCard, { part: item.part, renderers: toolRenderers }) }, item.key);
|
|
7724
8312
|
}
|
|
7725
8313
|
if (item.part.type === "text") {
|
|
7726
8314
|
const text = textForMessageDisplay(item.part.text, role);
|
|
7727
8315
|
if (!text) return null;
|
|
7728
|
-
return /* @__PURE__ */
|
|
8316
|
+
return /* @__PURE__ */ jsx24("div", { "data-boring-agent-part": "message-text", children: /* @__PURE__ */ jsx24(
|
|
7729
8317
|
MessageResponse,
|
|
7730
8318
|
{
|
|
7731
8319
|
components: mentionMarkdownComponents,
|
|
@@ -7737,12 +8325,12 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7737
8325
|
) }, item.key);
|
|
7738
8326
|
}
|
|
7739
8327
|
if (item.part.type === "notice") {
|
|
7740
|
-
return /* @__PURE__ */
|
|
8328
|
+
return /* @__PURE__ */ jsx24(NoticeBubble, { level: item.part.level, text: item.part.text }, item.key);
|
|
7741
8329
|
}
|
|
7742
8330
|
return null;
|
|
7743
8331
|
})
|
|
7744
8332
|
] }),
|
|
7745
|
-
isAssistant && (textParts.length > 0 || shouldReserveStreamingActions) ? /* @__PURE__ */
|
|
8333
|
+
isAssistant && (textParts.length > 0 || shouldReserveStreamingActions) ? /* @__PURE__ */ jsx24(
|
|
7746
8334
|
MessageActionsBar,
|
|
7747
8335
|
{
|
|
7748
8336
|
text: textParts.map((part) => part.text).join("\n\n"),
|
|
@@ -7754,20 +8342,20 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7754
8342
|
);
|
|
7755
8343
|
}
|
|
7756
8344
|
function TimelineReasoningPart({ item, showThoughts }) {
|
|
7757
|
-
const [manualOpen, setManualOpen] =
|
|
8345
|
+
const [manualOpen, setManualOpen] = useState16(null);
|
|
7758
8346
|
const isStreaming = item.state === "streaming";
|
|
7759
8347
|
const isOpen = manualOpen ?? showThoughts;
|
|
7760
|
-
|
|
8348
|
+
useEffect15(() => {
|
|
7761
8349
|
setManualOpen(null);
|
|
7762
8350
|
}, [showThoughts]);
|
|
7763
|
-
const handleOpenChange =
|
|
8351
|
+
const handleOpenChange = useCallback14((open) => {
|
|
7764
8352
|
setManualOpen(open);
|
|
7765
8353
|
}, []);
|
|
7766
|
-
const toggleManualOpen =
|
|
8354
|
+
const toggleManualOpen = useCallback14((event) => {
|
|
7767
8355
|
event.preventDefault();
|
|
7768
8356
|
setManualOpen((open) => !(open ?? showThoughts));
|
|
7769
8357
|
}, [showThoughts]);
|
|
7770
|
-
return /* @__PURE__ */
|
|
8358
|
+
return /* @__PURE__ */ jsxs20(
|
|
7771
8359
|
Reasoning,
|
|
7772
8360
|
{
|
|
7773
8361
|
"data-boring-agent-part": "message-reasoning",
|
|
@@ -7777,15 +8365,15 @@ function TimelineReasoningPart({ item, showThoughts }) {
|
|
|
7777
8365
|
onOpenChange: handleOpenChange,
|
|
7778
8366
|
autoClose: false,
|
|
7779
8367
|
children: [
|
|
7780
|
-
/* @__PURE__ */
|
|
8368
|
+
/* @__PURE__ */ jsx24(
|
|
7781
8369
|
ReasoningTrigger,
|
|
7782
8370
|
{
|
|
7783
8371
|
className: "mb-1 w-fit rounded-[var(--radius-sm)] px-0 py-0 !text-xs !font-normal !text-muted-foreground/75 hover:bg-transparent hover:!text-muted-foreground/75 [&_svg]:!text-muted-foreground/75",
|
|
7784
|
-
getThinkingMessage: () => /* @__PURE__ */
|
|
8372
|
+
getThinkingMessage: () => /* @__PURE__ */ jsx24("span", { children: "Reasoning" }),
|
|
7785
8373
|
onClick: toggleManualOpen
|
|
7786
8374
|
}
|
|
7787
8375
|
),
|
|
7788
|
-
/* @__PURE__ */
|
|
8376
|
+
/* @__PURE__ */ jsx24(ReasoningContent, { children: item.text })
|
|
7789
8377
|
]
|
|
7790
8378
|
}
|
|
7791
8379
|
);
|
|
@@ -7794,7 +8382,7 @@ function PlainToolCard({ part, renderers }) {
|
|
|
7794
8382
|
const toolPart = toToolPart(part);
|
|
7795
8383
|
if (!toolPart) return null;
|
|
7796
8384
|
const { renderer, part: resolved, resolution } = resolveToolRendererForPart(toolPart, renderers);
|
|
7797
|
-
return /* @__PURE__ */
|
|
8385
|
+
return /* @__PURE__ */ jsx24(
|
|
7798
8386
|
"div",
|
|
7799
8387
|
{
|
|
7800
8388
|
"data-tool-call-id": resolved.toolCallId,
|
|
@@ -7852,13 +8440,13 @@ function codeFilenameForPart(parts, index) {
|
|
|
7852
8440
|
return typeof path === "string" && path.trim() ? path : void 0;
|
|
7853
8441
|
}
|
|
7854
8442
|
function NoticeBubble({ level, text }) {
|
|
7855
|
-
return /* @__PURE__ */
|
|
8443
|
+
return /* @__PURE__ */ jsx24(
|
|
7856
8444
|
"div",
|
|
7857
8445
|
{
|
|
7858
8446
|
"data-boring-agent-part": "message-notice",
|
|
7859
8447
|
"data-notice-level": level,
|
|
7860
8448
|
className: noticeSurfaceClass(level, "text-xs"),
|
|
7861
|
-
children: /* @__PURE__ */
|
|
8449
|
+
children: /* @__PURE__ */ jsx24("div", { className: noticeTextClass(), children: text })
|
|
7862
8450
|
}
|
|
7863
8451
|
);
|
|
7864
8452
|
}
|
|
@@ -7899,7 +8487,7 @@ function MessageActionsBar({
|
|
|
7899
8487
|
text,
|
|
7900
8488
|
visible = true
|
|
7901
8489
|
}) {
|
|
7902
|
-
const [copied, setCopied] =
|
|
8490
|
+
const [copied, setCopied] = useState16(false);
|
|
7903
8491
|
const markCopied = () => {
|
|
7904
8492
|
setCopied(true);
|
|
7905
8493
|
setTimeout(() => setCopied(false), 1500);
|
|
@@ -7937,7 +8525,7 @@ function MessageActionsBar({
|
|
|
7937
8525
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--accent)]/40"
|
|
7938
8526
|
);
|
|
7939
8527
|
const hiddenActionProps = visible ? {} : { tabIndex: -1 };
|
|
7940
|
-
return /* @__PURE__ */
|
|
8528
|
+
return /* @__PURE__ */ jsx24(
|
|
7941
8529
|
"div",
|
|
7942
8530
|
{
|
|
7943
8531
|
"aria-hidden": !visible,
|
|
@@ -7945,8 +8533,8 @@ function MessageActionsBar({
|
|
|
7945
8533
|
"flex min-h-8 items-center gap-1 -mt-1 text-xs text-muted-foreground transition-opacity duration-200",
|
|
7946
8534
|
visible ? "opacity-100" : "pointer-events-none opacity-0"
|
|
7947
8535
|
),
|
|
7948
|
-
children: /* @__PURE__ */
|
|
7949
|
-
|
|
8536
|
+
children: /* @__PURE__ */ jsx24(
|
|
8537
|
+
Button11,
|
|
7950
8538
|
{
|
|
7951
8539
|
type: "button",
|
|
7952
8540
|
variant: "ghost",
|
|
@@ -7956,7 +8544,7 @@ function MessageActionsBar({
|
|
|
7956
8544
|
"aria-label": copied ? "Copied" : "Copy message",
|
|
7957
8545
|
title: copied ? "Copied" : "Copy",
|
|
7958
8546
|
...hiddenActionProps,
|
|
7959
|
-
children: copied ? /* @__PURE__ */
|
|
8547
|
+
children: copied ? /* @__PURE__ */ jsx24(CheckIcon3, { className: "h-3.5 w-3.5 text-[color:var(--accent)]" }) : /* @__PURE__ */ jsx24(CopyIcon4, { className: "h-3.5 w-3.5" })
|
|
7960
8548
|
}
|
|
7961
8549
|
)
|
|
7962
8550
|
}
|
|
@@ -7977,7 +8565,7 @@ function partKey(messageId, part, index) {
|
|
|
7977
8565
|
}
|
|
7978
8566
|
|
|
7979
8567
|
// src/front/chat/components/PiConversationSurface.tsx
|
|
7980
|
-
import { jsx as
|
|
8568
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
7981
8569
|
var TRANSCRIPT_WINDOW = 60;
|
|
7982
8570
|
var TRANSCRIPT_WINDOW_STEP = 40;
|
|
7983
8571
|
var LOAD_OLDER_THRESHOLD_PX = 320;
|
|
@@ -8005,17 +8593,17 @@ function PiConversationSurface({
|
|
|
8005
8593
|
const total = messageItems.length;
|
|
8006
8594
|
const historyEmpty = messages.length === 0;
|
|
8007
8595
|
const terminalError = hasTerminalChatError(runtimeNotices, historyEmpty);
|
|
8008
|
-
const [visibleCount, setVisibleCount] =
|
|
8009
|
-
|
|
8596
|
+
const [visibleCount, setVisibleCount] = useState17(TRANSCRIPT_WINDOW);
|
|
8597
|
+
useEffect16(() => {
|
|
8010
8598
|
setVisibleCount(TRANSCRIPT_WINDOW);
|
|
8011
8599
|
}, [windowResetKey]);
|
|
8012
8600
|
const hasOlder = total > visibleCount;
|
|
8013
8601
|
const visibleItems = hasOlder ? messageItems.slice(total - visibleCount) : messageItems;
|
|
8014
8602
|
const olderCount = hasOlder ? total - visibleCount : 0;
|
|
8015
|
-
const loadOlder =
|
|
8603
|
+
const loadOlder = useCallback15(() => {
|
|
8016
8604
|
setVisibleCount((count) => count + TRANSCRIPT_WINDOW_STEP);
|
|
8017
8605
|
}, []);
|
|
8018
|
-
return /* @__PURE__ */
|
|
8606
|
+
return /* @__PURE__ */ jsxs21(
|
|
8019
8607
|
Conversation,
|
|
8020
8608
|
{
|
|
8021
8609
|
className: emptyHero ? cn("flex-none", runtimeNotices.length > 0 ? "max-h-[45vh]" : "max-h-[20vh]") : "flex-1",
|
|
@@ -8023,13 +8611,13 @@ function PiConversationSurface({
|
|
|
8023
8611
|
"aria-live": "polite",
|
|
8024
8612
|
onScrollToBottomReady,
|
|
8025
8613
|
children: [
|
|
8026
|
-
/* @__PURE__ */
|
|
8614
|
+
/* @__PURE__ */ jsxs21(ConversationContent, { className: cn(
|
|
8027
8615
|
"mx-auto flex w-full flex-col gap-6",
|
|
8028
8616
|
chrome ? "max-w-3xl px-6 py-8" : "max-w-[680px] px-4 py-4",
|
|
8029
8617
|
emptyHero && "py-4 text-center"
|
|
8030
8618
|
), children: [
|
|
8031
|
-
messages.length === 0 && emptyStateHydrating && !terminalError ? /* @__PURE__ */
|
|
8032
|
-
messages.length === 0 && !emptyStateHydrating && !terminalError ? /* @__PURE__ */
|
|
8619
|
+
messages.length === 0 && emptyStateHydrating && !terminalError ? /* @__PURE__ */ jsx25(ConversationHistoryLoadingState, {}) : null,
|
|
8620
|
+
messages.length === 0 && !emptyStateHydrating && !terminalError ? /* @__PURE__ */ jsx25(
|
|
8033
8621
|
ChatEmptyState,
|
|
8034
8622
|
{
|
|
8035
8623
|
eyebrow: emptyState?.eyebrow,
|
|
@@ -8047,8 +8635,8 @@ function PiConversationSurface({
|
|
|
8047
8635
|
}
|
|
8048
8636
|
}
|
|
8049
8637
|
) : null,
|
|
8050
|
-
hasOlder ? /* @__PURE__ */
|
|
8051
|
-
visibleItems.map(({ message, key }, index) => /* @__PURE__ */
|
|
8638
|
+
hasOlder ? /* @__PURE__ */ jsx25(TranscriptHistoryLoader, { olderCount, onLoadOlder: loadOlder }) : null,
|
|
8639
|
+
visibleItems.map(({ message, key }, index) => /* @__PURE__ */ jsx25(
|
|
8052
8640
|
PiTimelineMessage,
|
|
8053
8641
|
{
|
|
8054
8642
|
message,
|
|
@@ -8061,16 +8649,16 @@ function PiConversationSurface({
|
|
|
8061
8649
|
},
|
|
8062
8650
|
key
|
|
8063
8651
|
)),
|
|
8064
|
-
/* @__PURE__ */
|
|
8652
|
+
/* @__PURE__ */ jsx25(RuntimeNoticeMessages, { notices: runtimeNotices, onDismiss: onDismissNotice, renderAction: renderNoticeAction, historyEmpty })
|
|
8065
8653
|
] }),
|
|
8066
|
-
/* @__PURE__ */
|
|
8654
|
+
/* @__PURE__ */ jsx25(ConversationScrollButton, {})
|
|
8067
8655
|
]
|
|
8068
8656
|
}
|
|
8069
8657
|
);
|
|
8070
8658
|
}
|
|
8071
8659
|
function ConversationHistoryLoadingState() {
|
|
8072
8660
|
const skeletonClassName = "motion-reduce:animate-none";
|
|
8073
|
-
return /* @__PURE__ */
|
|
8661
|
+
return /* @__PURE__ */ jsxs21(
|
|
8074
8662
|
"div",
|
|
8075
8663
|
{
|
|
8076
8664
|
role: "status",
|
|
@@ -8079,21 +8667,21 @@ function ConversationHistoryLoadingState() {
|
|
|
8079
8667
|
"data-boring-agent-part": "chat-history-loading",
|
|
8080
8668
|
className: "flex flex-col gap-7 py-4",
|
|
8081
8669
|
children: [
|
|
8082
|
-
/* @__PURE__ */
|
|
8083
|
-
/* @__PURE__ */
|
|
8084
|
-
/* @__PURE__ */
|
|
8085
|
-
/* @__PURE__ */
|
|
8086
|
-
/* @__PURE__ */
|
|
8087
|
-
/* @__PURE__ */
|
|
8670
|
+
/* @__PURE__ */ jsxs21("div", { "aria-hidden": "true", className: "flex items-start gap-3", children: [
|
|
8671
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: cn("mt-0.5 size-7 shrink-0 rounded-lg", skeletonClassName) }),
|
|
8672
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex min-w-0 flex-1 flex-col gap-2.5", children: [
|
|
8673
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: cn("h-3 w-24 rounded-sm", skeletonClassName) }),
|
|
8674
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: cn("h-3 w-full rounded-sm", skeletonClassName) }),
|
|
8675
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: cn("h-3 w-4/5 rounded-sm", skeletonClassName) })
|
|
8088
8676
|
] })
|
|
8089
8677
|
] }),
|
|
8090
|
-
/* @__PURE__ */
|
|
8091
|
-
/* @__PURE__ */
|
|
8092
|
-
/* @__PURE__ */
|
|
8093
|
-
/* @__PURE__ */
|
|
8094
|
-
/* @__PURE__ */
|
|
8095
|
-
/* @__PURE__ */
|
|
8096
|
-
/* @__PURE__ */
|
|
8678
|
+
/* @__PURE__ */ jsx25("div", { "aria-hidden": "true", className: "flex justify-end", children: /* @__PURE__ */ jsx25(Skeleton, { className: cn("h-11 w-[min(72%,30rem)] rounded-xl", skeletonClassName) }) }),
|
|
8679
|
+
/* @__PURE__ */ jsxs21("div", { "aria-hidden": "true", className: "flex items-start gap-3", children: [
|
|
8680
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: cn("mt-0.5 size-7 shrink-0 rounded-lg", skeletonClassName) }),
|
|
8681
|
+
/* @__PURE__ */ jsxs21("div", { className: "flex min-w-0 flex-1 flex-col gap-3", children: [
|
|
8682
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: cn("h-3 w-20 rounded-sm", skeletonClassName) }),
|
|
8683
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: cn("h-20 w-full rounded-lg", skeletonClassName) }),
|
|
8684
|
+
/* @__PURE__ */ jsx25(Skeleton, { className: cn("h-3 w-3/5 rounded-sm", skeletonClassName) })
|
|
8097
8685
|
] })
|
|
8098
8686
|
] })
|
|
8099
8687
|
]
|
|
@@ -8102,9 +8690,9 @@ function ConversationHistoryLoadingState() {
|
|
|
8102
8690
|
}
|
|
8103
8691
|
function TranscriptHistoryLoader({ olderCount, onLoadOlder }) {
|
|
8104
8692
|
const { scrollRef } = useStickToBottomContext2();
|
|
8105
|
-
const pendingAnchor =
|
|
8106
|
-
const armed =
|
|
8107
|
-
|
|
8693
|
+
const pendingAnchor = useRef11(null);
|
|
8694
|
+
const armed = useRef11(true);
|
|
8695
|
+
useEffect16(() => {
|
|
8108
8696
|
const el = scrollRef.current;
|
|
8109
8697
|
if (!el) return;
|
|
8110
8698
|
const onScroll = () => {
|
|
@@ -8127,7 +8715,7 @@ function TranscriptHistoryLoader({ olderCount, onLoadOlder }) {
|
|
|
8127
8715
|
}
|
|
8128
8716
|
if (el.scrollTop > LOAD_OLDER_THRESHOLD_PX) armed.current = true;
|
|
8129
8717
|
});
|
|
8130
|
-
return /* @__PURE__ */
|
|
8718
|
+
return /* @__PURE__ */ jsx25("div", { className: "flex justify-center", "data-boring-agent-part": "transcript-load-older", children: /* @__PURE__ */ jsxs21(
|
|
8131
8719
|
"button",
|
|
8132
8720
|
{
|
|
8133
8721
|
type: "button",
|
|
@@ -8164,14 +8752,14 @@ function buildMessageRenderItems(messages) {
|
|
|
8164
8752
|
}
|
|
8165
8753
|
|
|
8166
8754
|
// src/front/chat/components/PiChatComposerSurface.tsx
|
|
8167
|
-
import { useCallback as
|
|
8755
|
+
import { useCallback as useCallback17, useLayoutEffect as useLayoutEffect3 } from "react";
|
|
8168
8756
|
import { motion as motion2, useReducedMotion } from "motion/react";
|
|
8169
8757
|
|
|
8170
8758
|
// src/front/composer/PluginUpdateStatus.tsx
|
|
8171
|
-
import { useEffect as
|
|
8759
|
+
import { useEffect as useEffect17, useRef as useRef12 } from "react";
|
|
8172
8760
|
|
|
8173
8761
|
// src/front/composer/ComposerStatusBanner.tsx
|
|
8174
|
-
import { jsx as
|
|
8762
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
8175
8763
|
function ComposerStatusBanner({
|
|
8176
8764
|
tone,
|
|
8177
8765
|
dataAttribute,
|
|
@@ -8188,7 +8776,7 @@ function ComposerStatusBanner({
|
|
|
8188
8776
|
}) {
|
|
8189
8777
|
const toneAttr = { [dataAttribute]: tone };
|
|
8190
8778
|
if (tone === "running") {
|
|
8191
|
-
return /* @__PURE__ */
|
|
8779
|
+
return /* @__PURE__ */ jsxs22(
|
|
8192
8780
|
"div",
|
|
8193
8781
|
{
|
|
8194
8782
|
...toneAttr,
|
|
@@ -8200,14 +8788,14 @@ function ComposerStatusBanner({
|
|
|
8200
8788
|
maxWidthClassName
|
|
8201
8789
|
),
|
|
8202
8790
|
children: [
|
|
8203
|
-
/* @__PURE__ */
|
|
8204
|
-
/* @__PURE__ */
|
|
8791
|
+
/* @__PURE__ */ jsx26("span", { className: "inline-block h-2 w-2 animate-pulse rounded-full bg-accent", "aria-hidden": "true" }),
|
|
8792
|
+
/* @__PURE__ */ jsx26("span", { children: runningContent })
|
|
8205
8793
|
]
|
|
8206
8794
|
}
|
|
8207
8795
|
);
|
|
8208
8796
|
}
|
|
8209
8797
|
if (tone === "success") {
|
|
8210
|
-
return /* @__PURE__ */
|
|
8798
|
+
return /* @__PURE__ */ jsxs22(
|
|
8211
8799
|
"div",
|
|
8212
8800
|
{
|
|
8213
8801
|
...toneAttr,
|
|
@@ -8219,13 +8807,13 @@ function ComposerStatusBanner({
|
|
|
8219
8807
|
maxWidthClassName
|
|
8220
8808
|
),
|
|
8221
8809
|
children: [
|
|
8222
|
-
/* @__PURE__ */
|
|
8223
|
-
/* @__PURE__ */
|
|
8224
|
-
/* @__PURE__ */
|
|
8225
|
-
/* @__PURE__ */
|
|
8226
|
-
detail ? /* @__PURE__ */
|
|
8810
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-start gap-2", children: [
|
|
8811
|
+
/* @__PURE__ */ jsx26("span", { className: "mt-0.5 text-[oklch(0.45_0.13_148)]", "aria-hidden": "true", children: "\u2713" }),
|
|
8812
|
+
/* @__PURE__ */ jsxs22("span", { className: "min-w-0 flex-1", children: [
|
|
8813
|
+
/* @__PURE__ */ jsx26("span", { className: "block font-medium leading-5", children: title }),
|
|
8814
|
+
detail ? /* @__PURE__ */ jsx26("span", { className: "block leading-4 text-muted-foreground", children: detail }) : null
|
|
8227
8815
|
] }),
|
|
8228
|
-
onDismiss ? /* @__PURE__ */
|
|
8816
|
+
onDismiss ? /* @__PURE__ */ jsx26(
|
|
8229
8817
|
"button",
|
|
8230
8818
|
{
|
|
8231
8819
|
type: "button",
|
|
@@ -8241,7 +8829,7 @@ function ComposerStatusBanner({
|
|
|
8241
8829
|
}
|
|
8242
8830
|
);
|
|
8243
8831
|
}
|
|
8244
|
-
return /* @__PURE__ */
|
|
8832
|
+
return /* @__PURE__ */ jsxs22(
|
|
8245
8833
|
"div",
|
|
8246
8834
|
{
|
|
8247
8835
|
...toneAttr,
|
|
@@ -8253,10 +8841,10 @@ function ComposerStatusBanner({
|
|
|
8253
8841
|
maxWidthClassName
|
|
8254
8842
|
),
|
|
8255
8843
|
children: [
|
|
8256
|
-
/* @__PURE__ */
|
|
8257
|
-
/* @__PURE__ */
|
|
8258
|
-
/* @__PURE__ */
|
|
8259
|
-
onRetry ? /* @__PURE__ */
|
|
8844
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2", children: [
|
|
8845
|
+
/* @__PURE__ */ jsx26("span", { className: "text-destructive", "aria-hidden": "true", children: "\u26A0" }),
|
|
8846
|
+
/* @__PURE__ */ jsx26("span", { className: "flex-1 font-medium", children: title }),
|
|
8847
|
+
onRetry ? /* @__PURE__ */ jsx26(
|
|
8260
8848
|
"button",
|
|
8261
8849
|
{
|
|
8262
8850
|
type: "button",
|
|
@@ -8265,7 +8853,7 @@ function ComposerStatusBanner({
|
|
|
8265
8853
|
children: retryLabel
|
|
8266
8854
|
}
|
|
8267
8855
|
) : null,
|
|
8268
|
-
onDismiss ? /* @__PURE__ */
|
|
8856
|
+
onDismiss ? /* @__PURE__ */ jsx26(
|
|
8269
8857
|
"button",
|
|
8270
8858
|
{
|
|
8271
8859
|
type: "button",
|
|
@@ -8276,14 +8864,14 @@ function ComposerStatusBanner({
|
|
|
8276
8864
|
}
|
|
8277
8865
|
) : null
|
|
8278
8866
|
] }),
|
|
8279
|
-
message ? /* @__PURE__ */
|
|
8867
|
+
message ? /* @__PURE__ */ jsx26("pre", { className: "mt-2 whitespace-pre-wrap break-words text-[11px] text-destructive/90", children: message }) : null
|
|
8280
8868
|
]
|
|
8281
8869
|
}
|
|
8282
8870
|
);
|
|
8283
8871
|
}
|
|
8284
8872
|
|
|
8285
8873
|
// src/front/composer/PluginUpdateStatus.tsx
|
|
8286
|
-
import { jsx as
|
|
8874
|
+
import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
8287
8875
|
function PluginUpdateStatus({
|
|
8288
8876
|
state,
|
|
8289
8877
|
onDismiss,
|
|
@@ -8291,12 +8879,12 @@ function PluginUpdateStatus({
|
|
|
8291
8879
|
successAutoDismissMs = 1400,
|
|
8292
8880
|
maxWidthClassName = "max-w-3xl"
|
|
8293
8881
|
}) {
|
|
8294
|
-
const onDismissRef =
|
|
8295
|
-
|
|
8882
|
+
const onDismissRef = useRef12(onDismiss);
|
|
8883
|
+
useEffect17(() => {
|
|
8296
8884
|
onDismissRef.current = onDismiss;
|
|
8297
8885
|
}, [onDismiss]);
|
|
8298
8886
|
const successDismissKey = state?.kind === "success" ? `${state.reloaded}:${(state.restartWarnings?.length ?? 0) > 0 || (state.diagnostics?.length ?? 0) > 0}` : null;
|
|
8299
|
-
|
|
8887
|
+
useEffect17(() => {
|
|
8300
8888
|
if (!state || state.kind !== "success" || successAutoDismissMs <= 0) return;
|
|
8301
8889
|
const hasWarningsOrDiagnostics = (state.restartWarnings?.length ?? 0) > 0 || (state.diagnostics?.length ?? 0) > 0;
|
|
8302
8890
|
if (hasWarningsOrDiagnostics) return;
|
|
@@ -8305,7 +8893,7 @@ function PluginUpdateStatus({
|
|
|
8305
8893
|
}, [state?.kind, successDismissKey, successAutoDismissMs]);
|
|
8306
8894
|
if (!state) return null;
|
|
8307
8895
|
if (state.kind === "running") {
|
|
8308
|
-
return /* @__PURE__ */
|
|
8896
|
+
return /* @__PURE__ */ jsx27(
|
|
8309
8897
|
ComposerStatusBanner,
|
|
8310
8898
|
{
|
|
8311
8899
|
tone: "running",
|
|
@@ -8322,7 +8910,7 @@ function PluginUpdateStatus({
|
|
|
8322
8910
|
const hasWarningsOrDiagnostics = warnings.length > 0 || diagnostics.length > 0;
|
|
8323
8911
|
const title = state.reloaded ? hasWarningsOrDiagnostics ? "Reload finished with warnings" : "Reload complete" : "Reload queued";
|
|
8324
8912
|
const detail = state.reloaded ? hasWarningsOrDiagnostics ? "Some extension changes need attention." : frontEvents.length > 0 ? `${frontEvents.length} extension module${frontEvents.length === 1 ? "" : "s"} refreshed. Changes are live.` : "Changes are live." : void 0;
|
|
8325
|
-
return /* @__PURE__ */
|
|
8913
|
+
return /* @__PURE__ */ jsxs23(
|
|
8326
8914
|
ComposerStatusBanner,
|
|
8327
8915
|
{
|
|
8328
8916
|
tone: "success",
|
|
@@ -8333,7 +8921,7 @@ function PluginUpdateStatus({
|
|
|
8333
8921
|
onDismiss,
|
|
8334
8922
|
dismissAriaLabel: "Dismiss plugin update status",
|
|
8335
8923
|
children: [
|
|
8336
|
-
diagnostics.length > 0 ? /* @__PURE__ */
|
|
8924
|
+
diagnostics.length > 0 ? /* @__PURE__ */ jsxs23(
|
|
8337
8925
|
"div",
|
|
8338
8926
|
{
|
|
8339
8927
|
"data-boring-plugin-update-diagnostics": "",
|
|
@@ -8342,24 +8930,24 @@ function PluginUpdateStatus({
|
|
|
8342
8930
|
"px-2 py-1.5 text-[11px] text-foreground"
|
|
8343
8931
|
),
|
|
8344
8932
|
children: [
|
|
8345
|
-
/* @__PURE__ */
|
|
8346
|
-
/* @__PURE__ */
|
|
8347
|
-
/* @__PURE__ */
|
|
8933
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-1.5 font-medium text-[oklch(0.48_0.15_60)]", children: [
|
|
8934
|
+
/* @__PURE__ */ jsx27("span", { "aria-hidden": "true", children: "\u26A0" }),
|
|
8935
|
+
/* @__PURE__ */ jsxs23("span", { children: [
|
|
8348
8936
|
"Reload diagnostics for ",
|
|
8349
8937
|
diagnostics.length,
|
|
8350
8938
|
" extension",
|
|
8351
8939
|
diagnostics.length === 1 ? "" : "s"
|
|
8352
8940
|
] })
|
|
8353
8941
|
] }),
|
|
8354
|
-
/* @__PURE__ */
|
|
8355
|
-
/* @__PURE__ */
|
|
8942
|
+
/* @__PURE__ */ jsx27("ul", { className: "mt-1 ml-4 list-disc text-foreground/85", children: diagnostics.map((diagnostic, index) => /* @__PURE__ */ jsxs23("li", { children: [
|
|
8943
|
+
/* @__PURE__ */ jsx27("code", { className: "font-mono text-[10.5px]", children: diagnostic.pluginId ?? diagnostic.source ?? "plugin" }),
|
|
8356
8944
|
" \u2014 ",
|
|
8357
8945
|
diagnostic.message ?? "reload diagnostic"
|
|
8358
8946
|
] }, `${diagnostic.pluginId ?? diagnostic.source ?? "plugin"}-${index}`)) })
|
|
8359
8947
|
]
|
|
8360
8948
|
}
|
|
8361
8949
|
) : null,
|
|
8362
|
-
warnings.length > 0 ? /* @__PURE__ */
|
|
8950
|
+
warnings.length > 0 ? /* @__PURE__ */ jsxs23(
|
|
8363
8951
|
"div",
|
|
8364
8952
|
{
|
|
8365
8953
|
"data-boring-plugin-update-restart-warning": "",
|
|
@@ -8368,21 +8956,21 @@ function PluginUpdateStatus({
|
|
|
8368
8956
|
"px-2 py-1.5 text-[11px] text-foreground"
|
|
8369
8957
|
),
|
|
8370
8958
|
children: [
|
|
8371
|
-
/* @__PURE__ */
|
|
8372
|
-
/* @__PURE__ */
|
|
8373
|
-
/* @__PURE__ */
|
|
8959
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-1.5 font-medium text-[oklch(0.48_0.15_60)]", children: [
|
|
8960
|
+
/* @__PURE__ */ jsx27("span", { "aria-hidden": "true", children: "\u26A0" }),
|
|
8961
|
+
/* @__PURE__ */ jsxs23("span", { children: [
|
|
8374
8962
|
"Restart needed for ",
|
|
8375
8963
|
warnings.length,
|
|
8376
8964
|
" extension",
|
|
8377
8965
|
warnings.length === 1 ? "" : "s"
|
|
8378
8966
|
] })
|
|
8379
8967
|
] }),
|
|
8380
|
-
/* @__PURE__ */
|
|
8381
|
-
/* @__PURE__ */
|
|
8968
|
+
/* @__PURE__ */ jsx27("ul", { className: "mt-1 ml-4 list-disc text-foreground/85", children: warnings.map((w) => /* @__PURE__ */ jsxs23("li", { children: [
|
|
8969
|
+
/* @__PURE__ */ jsx27("code", { className: "font-mono text-[10.5px]", children: w.id }),
|
|
8382
8970
|
" \u2014 ",
|
|
8383
8971
|
w.surfaces.join(" + ")
|
|
8384
8972
|
] }, w.id)) }),
|
|
8385
|
-
/* @__PURE__ */
|
|
8973
|
+
/* @__PURE__ */ jsx27("p", { className: "mt-1 text-foreground/70", children: "The interface reloaded successfully, but routes and tools were wired at boot. Restart the workspace process to pick up the new code." })
|
|
8386
8974
|
]
|
|
8387
8975
|
}
|
|
8388
8976
|
) : null
|
|
@@ -8390,7 +8978,7 @@ function PluginUpdateStatus({
|
|
|
8390
8978
|
}
|
|
8391
8979
|
);
|
|
8392
8980
|
}
|
|
8393
|
-
return /* @__PURE__ */
|
|
8981
|
+
return /* @__PURE__ */ jsx27(
|
|
8394
8982
|
ComposerStatusBanner,
|
|
8395
8983
|
{
|
|
8396
8984
|
tone: "error",
|
|
@@ -8407,35 +8995,35 @@ function PluginUpdateStatus({
|
|
|
8407
8995
|
}
|
|
8408
8996
|
|
|
8409
8997
|
// src/front/composer/CommandRunStatus.tsx
|
|
8410
|
-
import { useEffect as
|
|
8411
|
-
import { Fragment as Fragment10, jsx as
|
|
8998
|
+
import { useEffect as useEffect18, useRef as useRef13 } from "react";
|
|
8999
|
+
import { Fragment as Fragment10, jsx as jsx28, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
8412
9000
|
function CommandRunStatus({
|
|
8413
9001
|
state,
|
|
8414
9002
|
onDismiss,
|
|
8415
9003
|
successAutoDismissMs = 1400,
|
|
8416
9004
|
maxWidthClassName = "max-w-3xl"
|
|
8417
9005
|
}) {
|
|
8418
|
-
const onDismissRef =
|
|
8419
|
-
|
|
9006
|
+
const onDismissRef = useRef13(onDismiss);
|
|
9007
|
+
useEffect18(() => {
|
|
8420
9008
|
onDismissRef.current = onDismiss;
|
|
8421
9009
|
}, [onDismiss]);
|
|
8422
9010
|
const successKey = state?.kind === "success" ? `${state.runId}:${state.command}:${state.detail ?? ""}` : null;
|
|
8423
|
-
|
|
9011
|
+
useEffect18(() => {
|
|
8424
9012
|
if (!state || state.kind !== "success" || successAutoDismissMs <= 0) return;
|
|
8425
9013
|
const timeout = window.setTimeout(() => onDismissRef.current(), successAutoDismissMs);
|
|
8426
9014
|
return () => window.clearTimeout(timeout);
|
|
8427
9015
|
}, [state?.kind, successKey, successAutoDismissMs]);
|
|
8428
9016
|
if (!state) return null;
|
|
8429
9017
|
if (state.kind === "running") {
|
|
8430
|
-
return /* @__PURE__ */
|
|
9018
|
+
return /* @__PURE__ */ jsx28(
|
|
8431
9019
|
ComposerStatusBanner,
|
|
8432
9020
|
{
|
|
8433
9021
|
tone: "running",
|
|
8434
9022
|
dataAttribute: "data-boring-command-run",
|
|
8435
9023
|
maxWidthClassName,
|
|
8436
|
-
runningContent: state.command ? /* @__PURE__ */
|
|
9024
|
+
runningContent: state.command ? /* @__PURE__ */ jsxs24(Fragment10, { children: [
|
|
8437
9025
|
" Running ",
|
|
8438
|
-
/* @__PURE__ */
|
|
9026
|
+
/* @__PURE__ */ jsxs24("code", { className: "font-mono", children: [
|
|
8439
9027
|
"/",
|
|
8440
9028
|
state.command
|
|
8441
9029
|
] }),
|
|
@@ -8445,15 +9033,15 @@ function CommandRunStatus({
|
|
|
8445
9033
|
);
|
|
8446
9034
|
}
|
|
8447
9035
|
if (state.kind === "success") {
|
|
8448
|
-
return /* @__PURE__ */
|
|
9036
|
+
return /* @__PURE__ */ jsx28(
|
|
8449
9037
|
ComposerStatusBanner,
|
|
8450
9038
|
{
|
|
8451
9039
|
tone: "success",
|
|
8452
9040
|
dataAttribute: "data-boring-command-run",
|
|
8453
9041
|
maxWidthClassName,
|
|
8454
|
-
title: state.command ? /* @__PURE__ */
|
|
9042
|
+
title: state.command ? /* @__PURE__ */ jsxs24(Fragment10, { children: [
|
|
8455
9043
|
" Ran ",
|
|
8456
|
-
/* @__PURE__ */
|
|
9044
|
+
/* @__PURE__ */ jsxs24("code", { className: "font-mono", children: [
|
|
8457
9045
|
"/",
|
|
8458
9046
|
state.command
|
|
8459
9047
|
] }),
|
|
@@ -8465,15 +9053,15 @@ function CommandRunStatus({
|
|
|
8465
9053
|
}
|
|
8466
9054
|
);
|
|
8467
9055
|
}
|
|
8468
|
-
return /* @__PURE__ */
|
|
9056
|
+
return /* @__PURE__ */ jsx28(
|
|
8469
9057
|
ComposerStatusBanner,
|
|
8470
9058
|
{
|
|
8471
9059
|
tone: "error",
|
|
8472
9060
|
dataAttribute: "data-boring-command-run",
|
|
8473
9061
|
maxWidthClassName,
|
|
8474
|
-
title: state.command ? /* @__PURE__ */
|
|
9062
|
+
title: state.command ? /* @__PURE__ */ jsxs24(Fragment10, { children: [
|
|
8475
9063
|
" ",
|
|
8476
|
-
/* @__PURE__ */
|
|
9064
|
+
/* @__PURE__ */ jsxs24("code", { className: "font-mono", children: [
|
|
8477
9065
|
"/",
|
|
8478
9066
|
state.command
|
|
8479
9067
|
] }),
|
|
@@ -8487,8 +9075,8 @@ function CommandRunStatus({
|
|
|
8487
9075
|
}
|
|
8488
9076
|
|
|
8489
9077
|
// src/front/chatPanelComposerControls.tsx
|
|
8490
|
-
import { forwardRef, useEffect as
|
|
8491
|
-
import { CheckIcon as
|
|
9078
|
+
import { forwardRef, useEffect as useEffect19, useRef as useRef14, useState as useState18 } from "react";
|
|
9079
|
+
import { CheckIcon as CheckIcon4, ChevronDownIcon as ChevronDownIcon5 } from "lucide-react";
|
|
8492
9080
|
import {
|
|
8493
9081
|
Command,
|
|
8494
9082
|
CommandEmpty,
|
|
@@ -8521,7 +9109,7 @@ function displayProviderLabel(provider) {
|
|
|
8521
9109
|
}
|
|
8522
9110
|
|
|
8523
9111
|
// src/front/chatPanelComposerControls.tsx
|
|
8524
|
-
import { Fragment as Fragment11, jsx as
|
|
9112
|
+
import { Fragment as Fragment11, jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
8525
9113
|
var composerActionClass = cn(
|
|
8526
9114
|
"inline-flex h-8 items-center justify-center gap-1.5 rounded-[var(--radius-md)] border-0 bg-transparent",
|
|
8527
9115
|
"text-muted-foreground shadow-none transition-colors motion-reduce:transition-none",
|
|
@@ -8571,7 +9159,7 @@ function isTextInputTarget(target) {
|
|
|
8571
9159
|
return target instanceof HTMLInputElement;
|
|
8572
9160
|
}
|
|
8573
9161
|
function useDismissOnOutsidePointer(ref, onClose) {
|
|
8574
|
-
|
|
9162
|
+
useEffect19(() => {
|
|
8575
9163
|
if (!onClose) return;
|
|
8576
9164
|
const handler = (event) => {
|
|
8577
9165
|
const target = event.target;
|
|
@@ -8589,7 +9177,7 @@ function useDismissOnOutsidePointer(ref, onClose) {
|
|
|
8589
9177
|
}
|
|
8590
9178
|
function ThinkingLevelGlyph({ level }) {
|
|
8591
9179
|
const lit = level === "off" ? 0 : level === "low" ? 1 : level === "medium" ? 2 : 3;
|
|
8592
|
-
return /* @__PURE__ */
|
|
9180
|
+
return /* @__PURE__ */ jsx29(
|
|
8593
9181
|
"svg",
|
|
8594
9182
|
{
|
|
8595
9183
|
"aria-hidden": "true",
|
|
@@ -8598,7 +9186,7 @@ function ThinkingLevelGlyph({ level }) {
|
|
|
8598
9186
|
viewBox: "0 0 14 14",
|
|
8599
9187
|
fill: "none",
|
|
8600
9188
|
className: "shrink-0",
|
|
8601
|
-
children: [0, 1, 2].map((i) => /* @__PURE__ */
|
|
9189
|
+
children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx29(
|
|
8602
9190
|
"rect",
|
|
8603
9191
|
{
|
|
8604
9192
|
x: 2 + i * 4,
|
|
@@ -8650,7 +9238,7 @@ var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
|
|
|
8650
9238
|
const triggerDisplay = value ? `${triggerLabel} (${displayProviderLabel(value.provider)})` : triggerLabel;
|
|
8651
9239
|
const sessionDisplay = sessionModel && sessionTriggerLabel ? `${sessionTriggerLabel} (${displayProviderLabel(sessionModel.provider)})` : triggerDisplay;
|
|
8652
9240
|
const accessibleDisplay = isOverride && value ? `Current model: ${sessionDisplay}. Next-message override: ${triggerDisplay}` : `Current model: ${sessionDisplay}`;
|
|
8653
|
-
return /* @__PURE__ */
|
|
9241
|
+
return /* @__PURE__ */ jsx29(
|
|
8654
9242
|
"button",
|
|
8655
9243
|
{
|
|
8656
9244
|
ref,
|
|
@@ -8669,25 +9257,25 @@ var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
|
|
|
8669
9257
|
className
|
|
8670
9258
|
),
|
|
8671
9259
|
...props,
|
|
8672
|
-
children: trigger === "slash" ? /* @__PURE__ */
|
|
8673
|
-
/* @__PURE__ */
|
|
8674
|
-
/* @__PURE__ */
|
|
8675
|
-
sessionModel ? /* @__PURE__ */
|
|
9260
|
+
children: trigger === "slash" ? /* @__PURE__ */ jsxs25(Fragment11, { children: [
|
|
9261
|
+
/* @__PURE__ */ jsx29("span", { className: "text-muted-foreground", children: "Model \xB7 " }),
|
|
9262
|
+
/* @__PURE__ */ jsx29("span", { className: "min-w-0 truncate text-foreground", children: sessionTriggerLabel ?? triggerLabel }),
|
|
9263
|
+
sessionModel ? /* @__PURE__ */ jsxs25("span", { className: "shrink-0 text-muted-foreground", children: [
|
|
8676
9264
|
" \xB7 ",
|
|
8677
9265
|
displayProviderLabel(sessionModel.provider)
|
|
8678
|
-
] }) : value ? /* @__PURE__ */
|
|
9266
|
+
] }) : value ? /* @__PURE__ */ jsxs25("span", { className: "shrink-0 text-muted-foreground", children: [
|
|
8679
9267
|
" \xB7 ",
|
|
8680
9268
|
displayProviderLabel(value.provider)
|
|
8681
9269
|
] }) : null,
|
|
8682
|
-
isOverride && value ? /* @__PURE__ */
|
|
9270
|
+
isOverride && value ? /* @__PURE__ */ jsxs25("span", { className: "shrink-0 text-amber-600 dark:text-amber-400", children: [
|
|
8683
9271
|
" \xB7 Next override: ",
|
|
8684
9272
|
triggerLabel,
|
|
8685
9273
|
" \xB7 ",
|
|
8686
9274
|
displayProviderLabel(value.provider)
|
|
8687
9275
|
] }) : null
|
|
8688
|
-
] }) : /* @__PURE__ */
|
|
8689
|
-
/* @__PURE__ */
|
|
8690
|
-
/* @__PURE__ */
|
|
9276
|
+
] }) : /* @__PURE__ */ jsxs25(Fragment11, { children: [
|
|
9277
|
+
/* @__PURE__ */ jsx29("span", { className: "min-w-0 truncate", children: triggerDisplay }),
|
|
9278
|
+
/* @__PURE__ */ jsx29(ChevronDownIcon5, { className: "h-3 w-3 shrink-0 text-muted-foreground/50", "aria-hidden": "true" })
|
|
8691
9279
|
] })
|
|
8692
9280
|
}
|
|
8693
9281
|
);
|
|
@@ -8707,19 +9295,19 @@ function ModelPickerMenu({
|
|
|
8707
9295
|
const groupedOptions = [...groups.values()].flat();
|
|
8708
9296
|
const keyboardOptions = hideDefaultOption ? groupedOptions : [null, ...groupedOptions];
|
|
8709
9297
|
const selectedIndex = currentKey ? Math.max(0, keyboardOptions.findIndex((option) => option && encodeModelKey(option) === currentKey)) : 0;
|
|
8710
|
-
const [activeIndex, setActiveIndex] =
|
|
8711
|
-
const activeIndexRef =
|
|
8712
|
-
const menuRef =
|
|
9298
|
+
const [activeIndex, setActiveIndex] = useState18(selectedIndex);
|
|
9299
|
+
const activeIndexRef = useRef14(selectedIndex);
|
|
9300
|
+
const menuRef = useRef14(null);
|
|
8713
9301
|
useDismissOnOutsidePointer(menuRef, onClose);
|
|
8714
9302
|
const setKeyboardActiveIndex = (next) => {
|
|
8715
9303
|
const resolved = typeof next === "function" ? next(activeIndexRef.current) : next;
|
|
8716
9304
|
activeIndexRef.current = resolved;
|
|
8717
9305
|
setActiveIndex(resolved);
|
|
8718
9306
|
};
|
|
8719
|
-
|
|
9307
|
+
useEffect19(() => {
|
|
8720
9308
|
setKeyboardActiveIndex(selectedIndex);
|
|
8721
9309
|
}, [selectedIndex]);
|
|
8722
|
-
|
|
9310
|
+
useEffect19(() => {
|
|
8723
9311
|
const handler = (event) => {
|
|
8724
9312
|
if (event.key === "Escape") {
|
|
8725
9313
|
event.preventDefault();
|
|
@@ -8744,8 +9332,8 @@ function ModelPickerMenu({
|
|
|
8744
9332
|
}, [activeIndex, disabled, keyboardOptions, onChange, onClose]);
|
|
8745
9333
|
const optionIndexOffset = hideDefaultOption ? 0 : 1;
|
|
8746
9334
|
const optionIndexes = new Map(groupedOptions.map((option, index) => [encodeModelKey(option), index + optionIndexOffset]));
|
|
8747
|
-
return /* @__PURE__ */
|
|
8748
|
-
menuOptions.length > 8 && /* @__PURE__ */
|
|
9335
|
+
return /* @__PURE__ */ jsx29("div", { ref: menuRef, "data-boring-agent": "", "data-boring-agent-part": "model-picker-menu", className: cn(composerPickerMenuClass, className), children: /* @__PURE__ */ jsxs25(Command, { className: "bg-transparent text-[color:var(--popover-foreground)]", children: [
|
|
9336
|
+
menuOptions.length > 8 && /* @__PURE__ */ jsx29("div", { className: "border-b border-border/60 px-2", children: /* @__PURE__ */ jsx29(
|
|
8749
9337
|
CommandInput,
|
|
8750
9338
|
{
|
|
8751
9339
|
placeholder: "Search models\u2026",
|
|
@@ -8753,9 +9341,9 @@ function ModelPickerMenu({
|
|
|
8753
9341
|
className: "h-8 w-full border-0 bg-transparent text-sm outline-none focus:ring-0"
|
|
8754
9342
|
}
|
|
8755
9343
|
) }),
|
|
8756
|
-
/* @__PURE__ */
|
|
8757
|
-
/* @__PURE__ */
|
|
8758
|
-
!hideDefaultOption ? /* @__PURE__ */
|
|
9344
|
+
/* @__PURE__ */ jsxs25(CommandList, { className: "max-h-[300px] p-0.5", children: [
|
|
9345
|
+
/* @__PURE__ */ jsx29(CommandEmpty, { className: "py-4 text-center text-sm text-muted-foreground", children: "No models found" }),
|
|
9346
|
+
!hideDefaultOption ? /* @__PURE__ */ jsx29(CommandGroup, { children: /* @__PURE__ */ jsxs25(
|
|
8759
9347
|
CommandItem,
|
|
8760
9348
|
{
|
|
8761
9349
|
value: "Default model automatic auto",
|
|
@@ -8766,8 +9354,8 @@ function ModelPickerMenu({
|
|
|
8766
9354
|
},
|
|
8767
9355
|
className: selectorItemClass(!value || activeIndex === 0),
|
|
8768
9356
|
children: [
|
|
8769
|
-
/* @__PURE__ */
|
|
8770
|
-
|
|
9357
|
+
/* @__PURE__ */ jsx29(
|
|
9358
|
+
CheckIcon4,
|
|
8771
9359
|
{
|
|
8772
9360
|
className: cn(
|
|
8773
9361
|
"h-3.5 w-3.5 shrink-0",
|
|
@@ -8775,12 +9363,12 @@ function ModelPickerMenu({
|
|
|
8775
9363
|
)
|
|
8776
9364
|
}
|
|
8777
9365
|
),
|
|
8778
|
-
/* @__PURE__ */
|
|
8779
|
-
/* @__PURE__ */
|
|
9366
|
+
/* @__PURE__ */ jsx29("span", { className: "truncate", children: "Default model" }),
|
|
9367
|
+
/* @__PURE__ */ jsx29("span", { className: "ml-auto shrink-0 text-xs text-muted-foreground", children: "Auto" })
|
|
8780
9368
|
]
|
|
8781
9369
|
}
|
|
8782
9370
|
) }) : null,
|
|
8783
|
-
[...groups.entries()].map(([provider, list]) => /* @__PURE__ */
|
|
9371
|
+
[...groups.entries()].map(([provider, list]) => /* @__PURE__ */ jsx29(
|
|
8784
9372
|
CommandGroup,
|
|
8785
9373
|
{
|
|
8786
9374
|
heading: displayProviderLabel(provider),
|
|
@@ -8789,7 +9377,7 @@ function ModelPickerMenu({
|
|
|
8789
9377
|
const key = encodeModelKey(m);
|
|
8790
9378
|
const label = m.label || displayModelLabel(m.id);
|
|
8791
9379
|
const itemIndex = optionIndexes.get(key) ?? 0;
|
|
8792
|
-
return /* @__PURE__ */
|
|
9380
|
+
return /* @__PURE__ */ jsxs25(
|
|
8793
9381
|
CommandItem,
|
|
8794
9382
|
{
|
|
8795
9383
|
value: `${label} ${m.id} ${displayProviderLabel(m.provider)}`,
|
|
@@ -8800,8 +9388,8 @@ function ModelPickerMenu({
|
|
|
8800
9388
|
},
|
|
8801
9389
|
className: cn(selectorItemClass(key === currentKey || activeIndex === itemIndex)),
|
|
8802
9390
|
children: [
|
|
8803
|
-
/* @__PURE__ */
|
|
8804
|
-
|
|
9391
|
+
/* @__PURE__ */ jsx29(
|
|
9392
|
+
CheckIcon4,
|
|
8805
9393
|
{
|
|
8806
9394
|
className: cn(
|
|
8807
9395
|
"h-3.5 w-3.5 shrink-0",
|
|
@@ -8809,8 +9397,8 @@ function ModelPickerMenu({
|
|
|
8809
9397
|
)
|
|
8810
9398
|
}
|
|
8811
9399
|
),
|
|
8812
|
-
/* @__PURE__ */
|
|
8813
|
-
/* @__PURE__ */
|
|
9400
|
+
/* @__PURE__ */ jsx29("span", { className: "min-w-0 flex-1 truncate whitespace-nowrap", children: label }),
|
|
9401
|
+
/* @__PURE__ */ jsx29("span", { className: "ml-auto max-w-[45%] shrink-0 truncate whitespace-nowrap text-right text-xs text-muted-foreground", children: m.id })
|
|
8814
9402
|
]
|
|
8815
9403
|
},
|
|
8816
9404
|
key
|
|
@@ -8835,12 +9423,12 @@ function ModelSelect({
|
|
|
8835
9423
|
ariaDescribedBy,
|
|
8836
9424
|
hideDefaultOption = false
|
|
8837
9425
|
}) {
|
|
8838
|
-
const [open, setOpen] =
|
|
8839
|
-
const previousOpenSignalRef =
|
|
8840
|
-
|
|
9426
|
+
const [open, setOpen] = useState18(false);
|
|
9427
|
+
const previousOpenSignalRef = useRef14(openSignal);
|
|
9428
|
+
useEffect19(() => {
|
|
8841
9429
|
if (disabled) setOpen(false);
|
|
8842
9430
|
}, [disabled]);
|
|
8843
|
-
|
|
9431
|
+
useEffect19(() => {
|
|
8844
9432
|
if (disabled || openSignal === void 0) {
|
|
8845
9433
|
previousOpenSignalRef.current = openSignal;
|
|
8846
9434
|
return;
|
|
@@ -8848,8 +9436,8 @@ function ModelSelect({
|
|
|
8848
9436
|
if (previousOpenSignalRef.current !== openSignal) setOpen(true);
|
|
8849
9437
|
previousOpenSignalRef.current = openSignal;
|
|
8850
9438
|
}, [disabled, openSignal]);
|
|
8851
|
-
return /* @__PURE__ */
|
|
8852
|
-
/* @__PURE__ */
|
|
9439
|
+
return /* @__PURE__ */ jsxs25(Popover, { open, onOpenChange: disabled ? void 0 : setOpen, children: [
|
|
9440
|
+
/* @__PURE__ */ jsx29(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(
|
|
8853
9441
|
ModelSelectTrigger,
|
|
8854
9442
|
{
|
|
8855
9443
|
value,
|
|
@@ -8863,7 +9451,7 @@ function ModelSelect({
|
|
|
8863
9451
|
"aria-describedby": ariaDescribedBy
|
|
8864
9452
|
}
|
|
8865
9453
|
) }),
|
|
8866
|
-
/* @__PURE__ */
|
|
9454
|
+
/* @__PURE__ */ jsx29(
|
|
8867
9455
|
PopoverContent,
|
|
8868
9456
|
{
|
|
8869
9457
|
align: trigger === "slash" ? "center" : "start",
|
|
@@ -8872,7 +9460,7 @@ function ModelSelect({
|
|
|
8872
9460
|
collisionPadding: 12,
|
|
8873
9461
|
"data-boring-agent": "",
|
|
8874
9462
|
className: cn("w-[min(92vw,340px)]", selectorContentClass),
|
|
8875
|
-
children: /* @__PURE__ */
|
|
9463
|
+
children: /* @__PURE__ */ jsx29(
|
|
8876
9464
|
ModelPickerMenu,
|
|
8877
9465
|
{
|
|
8878
9466
|
value,
|
|
@@ -8896,12 +9484,12 @@ function ThinkingSelect({
|
|
|
8896
9484
|
openSignal,
|
|
8897
9485
|
className
|
|
8898
9486
|
}) {
|
|
8899
|
-
const [open, setOpen] =
|
|
8900
|
-
const previousOpenSignalRef =
|
|
8901
|
-
|
|
9487
|
+
const [open, setOpen] = useState18(false);
|
|
9488
|
+
const previousOpenSignalRef = useRef14(openSignal);
|
|
9489
|
+
useEffect19(() => {
|
|
8902
9490
|
if (disabled) setOpen(false);
|
|
8903
9491
|
}, [disabled]);
|
|
8904
|
-
|
|
9492
|
+
useEffect19(() => {
|
|
8905
9493
|
if (disabled || openSignal === void 0) {
|
|
8906
9494
|
previousOpenSignalRef.current = openSignal;
|
|
8907
9495
|
return;
|
|
@@ -8909,8 +9497,8 @@ function ThinkingSelect({
|
|
|
8909
9497
|
if (previousOpenSignalRef.current !== openSignal) setOpen(true);
|
|
8910
9498
|
previousOpenSignalRef.current = openSignal;
|
|
8911
9499
|
}, [disabled, openSignal]);
|
|
8912
|
-
return /* @__PURE__ */
|
|
8913
|
-
/* @__PURE__ */
|
|
9500
|
+
return /* @__PURE__ */ jsxs25(Popover, { open, onOpenChange: disabled ? void 0 : setOpen, children: [
|
|
9501
|
+
/* @__PURE__ */ jsx29(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(
|
|
8914
9502
|
ThinkingSelectTrigger,
|
|
8915
9503
|
{
|
|
8916
9504
|
value,
|
|
@@ -8920,7 +9508,7 @@ function ThinkingSelect({
|
|
|
8920
9508
|
className
|
|
8921
9509
|
}
|
|
8922
9510
|
) }),
|
|
8923
|
-
/* @__PURE__ */
|
|
9511
|
+
/* @__PURE__ */ jsx29(
|
|
8924
9512
|
PopoverContent,
|
|
8925
9513
|
{
|
|
8926
9514
|
align: trigger === "slash" ? "center" : "end",
|
|
@@ -8929,7 +9517,7 @@ function ThinkingSelect({
|
|
|
8929
9517
|
collisionPadding: 12,
|
|
8930
9518
|
"data-boring-agent": "",
|
|
8931
9519
|
className: cn("w-[min(92vw,240px)]", selectorContentClass),
|
|
8932
|
-
children: /* @__PURE__ */
|
|
9520
|
+
children: /* @__PURE__ */ jsx29(
|
|
8933
9521
|
ThinkingPickerMenu,
|
|
8934
9522
|
{
|
|
8935
9523
|
value,
|
|
@@ -8952,7 +9540,7 @@ var ThinkingSelectTrigger = forwardRef(function ThinkingSelectTrigger2({
|
|
|
8952
9540
|
className,
|
|
8953
9541
|
...props
|
|
8954
9542
|
}, ref) {
|
|
8955
|
-
return /* @__PURE__ */
|
|
9543
|
+
return /* @__PURE__ */ jsxs25(
|
|
8956
9544
|
"button",
|
|
8957
9545
|
{
|
|
8958
9546
|
ref,
|
|
@@ -8973,13 +9561,13 @@ var ThinkingSelectTrigger = forwardRef(function ThinkingSelectTrigger2({
|
|
|
8973
9561
|
onClick,
|
|
8974
9562
|
...props,
|
|
8975
9563
|
children: [
|
|
8976
|
-
trigger === "button" ? /* @__PURE__ */
|
|
8977
|
-
trigger === "slash" ? /* @__PURE__ */
|
|
8978
|
-
/* @__PURE__ */
|
|
8979
|
-
/* @__PURE__ */
|
|
8980
|
-
] }) : /* @__PURE__ */
|
|
8981
|
-
/* @__PURE__ */
|
|
8982
|
-
/* @__PURE__ */
|
|
9564
|
+
trigger === "button" ? /* @__PURE__ */ jsx29(ThinkingLevelGlyph, { level: value }) : null,
|
|
9565
|
+
trigger === "slash" ? /* @__PURE__ */ jsxs25(Fragment11, { children: [
|
|
9566
|
+
/* @__PURE__ */ jsx29("span", { className: "text-muted-foreground", children: "Thinking \xB7 " }),
|
|
9567
|
+
/* @__PURE__ */ jsx29("span", { className: "text-foreground", children: THINKING_LEVEL_STATUS_LABELS[value] })
|
|
9568
|
+
] }) : /* @__PURE__ */ jsxs25(Fragment11, { children: [
|
|
9569
|
+
/* @__PURE__ */ jsx29("span", { children: THINKING_LEVEL_LABELS[value] }),
|
|
9570
|
+
/* @__PURE__ */ jsx29(ChevronDownIcon5, { className: "h-3 w-3 shrink-0 text-muted-foreground/50", "aria-hidden": "true" })
|
|
8983
9571
|
] })
|
|
8984
9572
|
]
|
|
8985
9573
|
}
|
|
@@ -8993,19 +9581,19 @@ function ThinkingPickerMenu({
|
|
|
8993
9581
|
className
|
|
8994
9582
|
}) {
|
|
8995
9583
|
const selectedIndex = Math.max(0, THINKING_LEVELS.indexOf(value));
|
|
8996
|
-
const [activeIndex, setActiveIndex] =
|
|
8997
|
-
const activeIndexRef =
|
|
8998
|
-
const menuRef =
|
|
9584
|
+
const [activeIndex, setActiveIndex] = useState18(selectedIndex);
|
|
9585
|
+
const activeIndexRef = useRef14(selectedIndex);
|
|
9586
|
+
const menuRef = useRef14(null);
|
|
8999
9587
|
useDismissOnOutsidePointer(menuRef, onClose);
|
|
9000
9588
|
const setKeyboardActiveIndex = (next) => {
|
|
9001
9589
|
const resolved = typeof next === "function" ? next(activeIndexRef.current) : next;
|
|
9002
9590
|
activeIndexRef.current = resolved;
|
|
9003
9591
|
setActiveIndex(resolved);
|
|
9004
9592
|
};
|
|
9005
|
-
|
|
9593
|
+
useEffect19(() => {
|
|
9006
9594
|
setKeyboardActiveIndex(selectedIndex);
|
|
9007
9595
|
}, [selectedIndex]);
|
|
9008
|
-
|
|
9596
|
+
useEffect19(() => {
|
|
9009
9597
|
const handler = (event) => {
|
|
9010
9598
|
if (event.key === "Escape") {
|
|
9011
9599
|
event.preventDefault();
|
|
@@ -9028,7 +9616,7 @@ function ThinkingPickerMenu({
|
|
|
9028
9616
|
window.addEventListener("keydown", handler, { capture: true });
|
|
9029
9617
|
return () => window.removeEventListener("keydown", handler, { capture: true });
|
|
9030
9618
|
}, [activeIndex, disabled, onChange, onClose]);
|
|
9031
|
-
return /* @__PURE__ */
|
|
9619
|
+
return /* @__PURE__ */ jsx29("div", { ref: menuRef, "data-boring-agent": "", "data-boring-agent-part": "thinking-picker-menu", className: cn(composerPickerMenuClass, className), children: /* @__PURE__ */ jsx29(Command, { className: "bg-transparent text-[color:var(--popover-foreground)]", children: /* @__PURE__ */ jsx29(CommandList, { className: "max-h-[300px] p-0.5", children: THINKING_LEVELS.map((level, index) => /* @__PURE__ */ jsxs25(
|
|
9032
9620
|
CommandItem,
|
|
9033
9621
|
{
|
|
9034
9622
|
value: `Thinking ${THINKING_LEVEL_LABELS[level]} ${THINKING_LEVEL_DETAILS[level]}`,
|
|
@@ -9039,8 +9627,8 @@ function ThinkingPickerMenu({
|
|
|
9039
9627
|
},
|
|
9040
9628
|
className: selectorItemClass(level === value || index === activeIndex),
|
|
9041
9629
|
children: [
|
|
9042
|
-
/* @__PURE__ */
|
|
9043
|
-
|
|
9630
|
+
/* @__PURE__ */ jsx29(
|
|
9631
|
+
CheckIcon4,
|
|
9044
9632
|
{
|
|
9045
9633
|
className: cn(
|
|
9046
9634
|
"h-3.5 w-3.5 shrink-0",
|
|
@@ -9048,9 +9636,9 @@ function ThinkingPickerMenu({
|
|
|
9048
9636
|
)
|
|
9049
9637
|
}
|
|
9050
9638
|
),
|
|
9051
|
-
/* @__PURE__ */
|
|
9052
|
-
/* @__PURE__ */
|
|
9053
|
-
/* @__PURE__ */
|
|
9639
|
+
/* @__PURE__ */ jsx29(ThinkingLevelGlyph, { level }),
|
|
9640
|
+
/* @__PURE__ */ jsx29("span", { className: "font-medium", children: THINKING_LEVEL_LABELS[level] }),
|
|
9641
|
+
/* @__PURE__ */ jsx29("span", { className: "ml-auto text-xs text-muted-foreground", children: THINKING_LEVEL_DETAILS[level] })
|
|
9054
9642
|
]
|
|
9055
9643
|
},
|
|
9056
9644
|
level
|
|
@@ -9091,7 +9679,7 @@ import {
|
|
|
9091
9679
|
XIcon as XIcon4
|
|
9092
9680
|
} from "lucide-react";
|
|
9093
9681
|
import { nanoid } from "nanoid";
|
|
9094
|
-
import { useCallback as
|
|
9682
|
+
import { useCallback as useCallback16, useEffect as useEffect20, useMemo as useMemo14, useRef as useRef15, useState as useState19 } from "react";
|
|
9095
9683
|
|
|
9096
9684
|
// src/front/primitives/prompt-input-context.ts
|
|
9097
9685
|
import { createContext as createContext7, useContext as useContext7 } from "react";
|
|
@@ -9126,12 +9714,12 @@ import {
|
|
|
9126
9714
|
TooltipTrigger as TooltipTrigger2
|
|
9127
9715
|
} from "@hachej/boring-ui-kit";
|
|
9128
9716
|
import { Children as Children2 } from "react";
|
|
9129
|
-
import { jsx as
|
|
9717
|
+
import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
9130
9718
|
var PromptInputFooter = ({
|
|
9131
9719
|
align = "block-end",
|
|
9132
9720
|
className,
|
|
9133
9721
|
...props
|
|
9134
|
-
}) => /* @__PURE__ */
|
|
9722
|
+
}) => /* @__PURE__ */ jsx30(
|
|
9135
9723
|
InputGroupAddon,
|
|
9136
9724
|
{
|
|
9137
9725
|
align,
|
|
@@ -9141,7 +9729,7 @@ var PromptInputFooter = ({
|
|
|
9141
9729
|
);
|
|
9142
9730
|
|
|
9143
9731
|
// src/front/primitives/prompt-input.tsx
|
|
9144
|
-
import { Fragment as Fragment12, jsx as
|
|
9732
|
+
import { Fragment as Fragment12, jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
9145
9733
|
var PromptInput = ({
|
|
9146
9734
|
className,
|
|
9147
9735
|
accept,
|
|
@@ -9158,14 +9746,14 @@ var PromptInput = ({
|
|
|
9158
9746
|
}) => {
|
|
9159
9747
|
const controller = useOptionalPromptInputController();
|
|
9160
9748
|
const usingProvider = !!controller;
|
|
9161
|
-
const providerTextValueRef =
|
|
9749
|
+
const providerTextValueRef = useRef15("");
|
|
9162
9750
|
if (usingProvider) {
|
|
9163
9751
|
providerTextValueRef.current = controller.textInput.value;
|
|
9164
9752
|
}
|
|
9165
|
-
const inputRef =
|
|
9166
|
-
const formRef =
|
|
9167
|
-
const [items, setItems] =
|
|
9168
|
-
const setFileUrlLocal =
|
|
9753
|
+
const inputRef = useRef15(null);
|
|
9754
|
+
const formRef = useRef15(null);
|
|
9755
|
+
const [items, setItems] = useState19([]);
|
|
9756
|
+
const setFileUrlLocal = useCallback16((id, url, status, path) => {
|
|
9169
9757
|
setItems((prev) => prev.map((f) => {
|
|
9170
9758
|
if (f.id !== id) return f;
|
|
9171
9759
|
if (f.url !== url && f.url.startsWith("blob:")) URL.revokeObjectURL(f.url);
|
|
@@ -9173,15 +9761,15 @@ var PromptInput = ({
|
|
|
9173
9761
|
}));
|
|
9174
9762
|
}, []);
|
|
9175
9763
|
const files = usingProvider ? controller.attachments.files : items;
|
|
9176
|
-
const [referencedSources, setReferencedSources] =
|
|
9177
|
-
const filesRef =
|
|
9178
|
-
|
|
9764
|
+
const [referencedSources, setReferencedSources] = useState19([]);
|
|
9765
|
+
const filesRef = useRef15(files);
|
|
9766
|
+
useEffect20(() => {
|
|
9179
9767
|
filesRef.current = files;
|
|
9180
9768
|
}, [files]);
|
|
9181
|
-
const openFileDialogLocal =
|
|
9769
|
+
const openFileDialogLocal = useCallback16(() => {
|
|
9182
9770
|
inputRef.current?.click();
|
|
9183
9771
|
}, []);
|
|
9184
|
-
const matchesAccept =
|
|
9772
|
+
const matchesAccept = useCallback16(
|
|
9185
9773
|
(f) => {
|
|
9186
9774
|
if (!accept || accept.trim() === "") {
|
|
9187
9775
|
return true;
|
|
@@ -9197,7 +9785,7 @@ var PromptInput = ({
|
|
|
9197
9785
|
},
|
|
9198
9786
|
[accept]
|
|
9199
9787
|
);
|
|
9200
|
-
const addLocal =
|
|
9788
|
+
const addLocal = useCallback16(
|
|
9201
9789
|
(fileList) => {
|
|
9202
9790
|
const incoming = [...fileList];
|
|
9203
9791
|
const accepted = incoming.filter((f) => matchesAccept(f));
|
|
@@ -9244,7 +9832,7 @@ var PromptInput = ({
|
|
|
9244
9832
|
},
|
|
9245
9833
|
[matchesAccept, maxFiles, maxFileSize, onError, items.length, onUploadFile, setFileUrlLocal]
|
|
9246
9834
|
);
|
|
9247
|
-
const removeLocal =
|
|
9835
|
+
const removeLocal = useCallback16(
|
|
9248
9836
|
(id) => setItems((prev) => {
|
|
9249
9837
|
const found = prev.find((file) => file.id === id);
|
|
9250
9838
|
if (found?.url.startsWith("blob:")) {
|
|
@@ -9254,7 +9842,7 @@ var PromptInput = ({
|
|
|
9254
9842
|
}),
|
|
9255
9843
|
[]
|
|
9256
9844
|
);
|
|
9257
|
-
const addWithProviderValidation =
|
|
9845
|
+
const addWithProviderValidation = useCallback16(
|
|
9258
9846
|
(fileList) => {
|
|
9259
9847
|
const incoming = [...fileList];
|
|
9260
9848
|
const accepted = incoming.filter((f) => matchesAccept(f));
|
|
@@ -9289,7 +9877,7 @@ var PromptInput = ({
|
|
|
9289
9877
|
},
|
|
9290
9878
|
[matchesAccept, maxFileSize, maxFiles, onError, files.length, controller]
|
|
9291
9879
|
);
|
|
9292
|
-
const clearAttachments =
|
|
9880
|
+
const clearAttachments = useCallback16(
|
|
9293
9881
|
() => usingProvider ? controller?.attachments.clear() : setItems((prev) => {
|
|
9294
9882
|
for (const file of prev) {
|
|
9295
9883
|
if (file.url.startsWith("blob:")) {
|
|
@@ -9300,29 +9888,29 @@ var PromptInput = ({
|
|
|
9300
9888
|
}),
|
|
9301
9889
|
[usingProvider, controller]
|
|
9302
9890
|
);
|
|
9303
|
-
const clearReferencedSources =
|
|
9891
|
+
const clearReferencedSources = useCallback16(
|
|
9304
9892
|
() => setReferencedSources([]),
|
|
9305
9893
|
[]
|
|
9306
9894
|
);
|
|
9307
9895
|
const add = usingProvider ? addWithProviderValidation : addLocal;
|
|
9308
9896
|
const remove = usingProvider ? controller.attachments.remove : removeLocal;
|
|
9309
9897
|
const openFileDialog = usingProvider ? controller.attachments.openFileDialog : openFileDialogLocal;
|
|
9310
|
-
const clear =
|
|
9898
|
+
const clear = useCallback16(() => {
|
|
9311
9899
|
clearAttachments();
|
|
9312
9900
|
clearReferencedSources();
|
|
9313
9901
|
}, [clearAttachments, clearReferencedSources]);
|
|
9314
|
-
|
|
9902
|
+
useEffect20(() => {
|
|
9315
9903
|
if (!usingProvider) {
|
|
9316
9904
|
return;
|
|
9317
9905
|
}
|
|
9318
9906
|
controller.__registerFileInput(inputRef, () => inputRef.current?.click());
|
|
9319
9907
|
}, [usingProvider, controller]);
|
|
9320
|
-
|
|
9908
|
+
useEffect20(() => {
|
|
9321
9909
|
if (syncHiddenInput && inputRef.current && files.length === 0) {
|
|
9322
9910
|
inputRef.current.value = "";
|
|
9323
9911
|
}
|
|
9324
9912
|
}, [files, syncHiddenInput]);
|
|
9325
|
-
|
|
9913
|
+
useEffect20(() => {
|
|
9326
9914
|
const form = formRef.current;
|
|
9327
9915
|
if (!form) {
|
|
9328
9916
|
return;
|
|
@@ -9350,7 +9938,7 @@ var PromptInput = ({
|
|
|
9350
9938
|
form.removeEventListener("drop", onDrop);
|
|
9351
9939
|
};
|
|
9352
9940
|
}, [add, globalDrop]);
|
|
9353
|
-
|
|
9941
|
+
useEffect20(() => {
|
|
9354
9942
|
if (!globalDrop) {
|
|
9355
9943
|
return;
|
|
9356
9944
|
}
|
|
@@ -9374,7 +9962,7 @@ var PromptInput = ({
|
|
|
9374
9962
|
document.removeEventListener("drop", onDrop);
|
|
9375
9963
|
};
|
|
9376
9964
|
}, [add, globalDrop]);
|
|
9377
|
-
|
|
9965
|
+
useEffect20(
|
|
9378
9966
|
() => () => {
|
|
9379
9967
|
if (!usingProvider) {
|
|
9380
9968
|
for (const f of filesRef.current) {
|
|
@@ -9386,7 +9974,7 @@ var PromptInput = ({
|
|
|
9386
9974
|
},
|
|
9387
9975
|
[usingProvider]
|
|
9388
9976
|
);
|
|
9389
|
-
const handleChange =
|
|
9977
|
+
const handleChange = useCallback16(
|
|
9390
9978
|
(event) => {
|
|
9391
9979
|
if (event.currentTarget.files) {
|
|
9392
9980
|
add(event.currentTarget.files);
|
|
@@ -9396,7 +9984,7 @@ var PromptInput = ({
|
|
|
9396
9984
|
[add]
|
|
9397
9985
|
);
|
|
9398
9986
|
const setFileUrl = usingProvider ? controller.attachments.setFileUrl : setFileUrlLocal;
|
|
9399
|
-
const attachmentsCtx =
|
|
9987
|
+
const attachmentsCtx = useMemo14(
|
|
9400
9988
|
() => ({
|
|
9401
9989
|
add,
|
|
9402
9990
|
clear: clearAttachments,
|
|
@@ -9408,7 +9996,7 @@ var PromptInput = ({
|
|
|
9408
9996
|
}),
|
|
9409
9997
|
[files, add, remove, clearAttachments, openFileDialog, setFileUrl]
|
|
9410
9998
|
);
|
|
9411
|
-
const refsCtx =
|
|
9999
|
+
const refsCtx = useMemo14(
|
|
9412
10000
|
() => ({
|
|
9413
10001
|
add: (incoming) => {
|
|
9414
10002
|
const array = Array.isArray(incoming) ? incoming : [incoming];
|
|
@@ -9425,7 +10013,7 @@ var PromptInput = ({
|
|
|
9425
10013
|
}),
|
|
9426
10014
|
[referencedSources, clearReferencedSources]
|
|
9427
10015
|
);
|
|
9428
|
-
const handleSubmit =
|
|
10016
|
+
const handleSubmit = useCallback16(
|
|
9429
10017
|
async (event) => {
|
|
9430
10018
|
event.preventDefault();
|
|
9431
10019
|
const form = event.currentTarget;
|
|
@@ -9484,8 +10072,8 @@ var PromptInput = ({
|
|
|
9484
10072
|
},
|
|
9485
10073
|
[usingProvider, controller, files, onSubmit, clear]
|
|
9486
10074
|
);
|
|
9487
|
-
const inner = /* @__PURE__ */
|
|
9488
|
-
/* @__PURE__ */
|
|
10075
|
+
const inner = /* @__PURE__ */ jsxs27(Fragment12, { children: [
|
|
10076
|
+
/* @__PURE__ */ jsx31(
|
|
9489
10077
|
Input,
|
|
9490
10078
|
{
|
|
9491
10079
|
accept,
|
|
@@ -9498,7 +10086,7 @@ var PromptInput = ({
|
|
|
9498
10086
|
type: "file"
|
|
9499
10087
|
}
|
|
9500
10088
|
),
|
|
9501
|
-
/* @__PURE__ */
|
|
10089
|
+
/* @__PURE__ */ jsx31(
|
|
9502
10090
|
"form",
|
|
9503
10091
|
{
|
|
9504
10092
|
"data-boring-agent-part": "composer",
|
|
@@ -9506,12 +10094,12 @@ var PromptInput = ({
|
|
|
9506
10094
|
onSubmit: handleSubmit,
|
|
9507
10095
|
ref: formRef,
|
|
9508
10096
|
...props,
|
|
9509
|
-
children: /* @__PURE__ */
|
|
10097
|
+
children: /* @__PURE__ */ jsx31(InputGroup, { className: "overflow-hidden", children })
|
|
9510
10098
|
}
|
|
9511
10099
|
)
|
|
9512
10100
|
] });
|
|
9513
|
-
const withReferencedSources = /* @__PURE__ */
|
|
9514
|
-
return /* @__PURE__ */
|
|
10101
|
+
const withReferencedSources = /* @__PURE__ */ jsx31(LocalReferencedSourcesContext.Provider, { value: refsCtx, children: inner });
|
|
10102
|
+
return /* @__PURE__ */ jsx31(LocalAttachmentsContext.Provider, { value: attachmentsCtx, children: withReferencedSources });
|
|
9515
10103
|
};
|
|
9516
10104
|
var PromptInputTextarea = ({
|
|
9517
10105
|
onChange,
|
|
@@ -9522,8 +10110,8 @@ var PromptInputTextarea = ({
|
|
|
9522
10110
|
}) => {
|
|
9523
10111
|
const controller = useOptionalPromptInputController();
|
|
9524
10112
|
const attachments = usePromptInputAttachments();
|
|
9525
|
-
const [isComposing, setIsComposing] =
|
|
9526
|
-
const handleKeyDown =
|
|
10113
|
+
const [isComposing, setIsComposing] = useState19(false);
|
|
10114
|
+
const handleKeyDown = useCallback16(
|
|
9527
10115
|
(e) => {
|
|
9528
10116
|
onKeyDown?.(e);
|
|
9529
10117
|
if (e.defaultPrevented) {
|
|
@@ -9556,7 +10144,7 @@ var PromptInputTextarea = ({
|
|
|
9556
10144
|
},
|
|
9557
10145
|
[onKeyDown, isComposing, attachments]
|
|
9558
10146
|
);
|
|
9559
|
-
const handlePaste =
|
|
10147
|
+
const handlePaste = useCallback16(
|
|
9560
10148
|
(event) => {
|
|
9561
10149
|
const items = event.clipboardData?.items;
|
|
9562
10150
|
if (!items) {
|
|
@@ -9578,8 +10166,8 @@ var PromptInputTextarea = ({
|
|
|
9578
10166
|
},
|
|
9579
10167
|
[attachments]
|
|
9580
10168
|
);
|
|
9581
|
-
const handleCompositionEnd =
|
|
9582
|
-
const handleCompositionStart =
|
|
10169
|
+
const handleCompositionEnd = useCallback16(() => setIsComposing(false), []);
|
|
10170
|
+
const handleCompositionStart = useCallback16(() => setIsComposing(true), []);
|
|
9583
10171
|
const controlledProps = controller ? {
|
|
9584
10172
|
onChange: (e) => {
|
|
9585
10173
|
controller.textInput.setInput(e.currentTarget.value);
|
|
@@ -9589,7 +10177,7 @@ var PromptInputTextarea = ({
|
|
|
9589
10177
|
} : {
|
|
9590
10178
|
onChange
|
|
9591
10179
|
};
|
|
9592
|
-
return /* @__PURE__ */
|
|
10180
|
+
return /* @__PURE__ */ jsx31(
|
|
9593
10181
|
InputGroupTextarea,
|
|
9594
10182
|
{
|
|
9595
10183
|
"data-boring-agent-part": "composer-input",
|
|
@@ -9616,15 +10204,15 @@ var PromptInputSubmit = ({
|
|
|
9616
10204
|
...props
|
|
9617
10205
|
}) => {
|
|
9618
10206
|
const isGenerating = status === "submitted" || status === "streaming";
|
|
9619
|
-
let Icon = /* @__PURE__ */
|
|
10207
|
+
let Icon = /* @__PURE__ */ jsx31(CornerDownLeftIcon, { className: "size-4" });
|
|
9620
10208
|
if (status === "submitted") {
|
|
9621
|
-
Icon = /* @__PURE__ */
|
|
10209
|
+
Icon = /* @__PURE__ */ jsx31(Spinner, {});
|
|
9622
10210
|
} else if (status === "streaming") {
|
|
9623
|
-
Icon = /* @__PURE__ */
|
|
10211
|
+
Icon = /* @__PURE__ */ jsx31(SquareIcon, { className: "size-4" });
|
|
9624
10212
|
} else if (status === "error") {
|
|
9625
|
-
Icon = /* @__PURE__ */
|
|
10213
|
+
Icon = /* @__PURE__ */ jsx31(XIcon4, { className: "size-4" });
|
|
9626
10214
|
}
|
|
9627
|
-
const handleClick =
|
|
10215
|
+
const handleClick = useCallback16(
|
|
9628
10216
|
(e) => {
|
|
9629
10217
|
if (isGenerating && onStop) {
|
|
9630
10218
|
e.preventDefault();
|
|
@@ -9635,7 +10223,7 @@ var PromptInputSubmit = ({
|
|
|
9635
10223
|
},
|
|
9636
10224
|
[isGenerating, onStop, onClick]
|
|
9637
10225
|
);
|
|
9638
|
-
return /* @__PURE__ */
|
|
10226
|
+
return /* @__PURE__ */ jsx31(
|
|
9639
10227
|
InputGroupButton2,
|
|
9640
10228
|
{
|
|
9641
10229
|
"aria-label": isGenerating ? "Stop" : "Submit",
|
|
@@ -9652,8 +10240,8 @@ var PromptInputSubmit = ({
|
|
|
9652
10240
|
};
|
|
9653
10241
|
|
|
9654
10242
|
// src/front/primitives/slash-command-picker.tsx
|
|
9655
|
-
import { useEffect as
|
|
9656
|
-
import { Fragment as Fragment13, jsx as
|
|
10243
|
+
import { useEffect as useEffect21, useMemo as useMemo15, useRef as useRef16, useState as useState20 } from "react";
|
|
10244
|
+
import { Fragment as Fragment13, jsx as jsx32, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
9657
10245
|
var ALL_PLUGINS = "__all__";
|
|
9658
10246
|
function commandGroup(cmd) {
|
|
9659
10247
|
if (cmd.source === "skill") return "skills";
|
|
@@ -9661,20 +10249,20 @@ function commandGroup(cmd) {
|
|
|
9661
10249
|
return "built-in";
|
|
9662
10250
|
}
|
|
9663
10251
|
function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
9664
|
-
const [plugin, setPlugin] =
|
|
9665
|
-
const [searchQuery, setSearchQuery] =
|
|
9666
|
-
const [activeIdx, setActiveIdx] =
|
|
9667
|
-
const containerRef =
|
|
9668
|
-
const listRef =
|
|
9669
|
-
const inputRef =
|
|
9670
|
-
|
|
10252
|
+
const [plugin, setPlugin] = useState20(ALL_PLUGINS);
|
|
10253
|
+
const [searchQuery, setSearchQuery] = useState20(query);
|
|
10254
|
+
const [activeIdx, setActiveIdx] = useState20(0);
|
|
10255
|
+
const containerRef = useRef16(null);
|
|
10256
|
+
const listRef = useRef16(null);
|
|
10257
|
+
const inputRef = useRef16(null);
|
|
10258
|
+
useEffect21(() => {
|
|
9671
10259
|
setSearchQuery(query);
|
|
9672
10260
|
}, [query]);
|
|
9673
|
-
const groups =
|
|
10261
|
+
const groups = useMemo15(() => {
|
|
9674
10262
|
const set = new Set(commands.map(commandGroup));
|
|
9675
10263
|
return Array.from(set).sort((a, b) => a.localeCompare(b));
|
|
9676
10264
|
}, [commands]);
|
|
9677
|
-
const filtered =
|
|
10265
|
+
const filtered = useMemo15(() => {
|
|
9678
10266
|
const q = searchQuery.trim().toLowerCase();
|
|
9679
10267
|
return commands.filter((c) => {
|
|
9680
10268
|
if (plugin !== ALL_PLUGINS && commandGroup(c) !== plugin) return false;
|
|
@@ -9682,10 +10270,10 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9682
10270
|
return c.name.toLowerCase().includes(q) || c.description.toLowerCase().includes(q);
|
|
9683
10271
|
});
|
|
9684
10272
|
}, [commands, searchQuery, plugin]);
|
|
9685
|
-
|
|
10273
|
+
useEffect21(() => {
|
|
9686
10274
|
setActiveIdx((i) => filtered.length === 0 ? 0 : Math.min(i, filtered.length - 1));
|
|
9687
10275
|
}, [filtered.length]);
|
|
9688
|
-
|
|
10276
|
+
useEffect21(() => {
|
|
9689
10277
|
const handler = (e) => {
|
|
9690
10278
|
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
9691
10279
|
onDismiss();
|
|
@@ -9704,8 +10292,8 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9704
10292
|
},
|
|
9705
10293
|
onDismiss
|
|
9706
10294
|
});
|
|
9707
|
-
return /* @__PURE__ */
|
|
9708
|
-
/* @__PURE__ */
|
|
10295
|
+
return /* @__PURE__ */ jsxs28("div", { ref: containerRef, className: "mb-1 w-full overflow-hidden rounded-lg border border-border/60 bg-popover shadow-lg", children: [
|
|
10296
|
+
/* @__PURE__ */ jsx32(
|
|
9709
10297
|
"input",
|
|
9710
10298
|
{
|
|
9711
10299
|
ref: inputRef,
|
|
@@ -9720,9 +10308,9 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9720
10308
|
autoComplete: "off"
|
|
9721
10309
|
}
|
|
9722
10310
|
),
|
|
9723
|
-
/* @__PURE__ */
|
|
10311
|
+
/* @__PURE__ */ jsx32("div", { className: "flex flex-wrap gap-1 border-b border-border/50 px-2 py-1.5", role: "tablist", "aria-label": "Filter by plugin", children: [ALL_PLUGINS, ...groups].map((g) => {
|
|
9724
10312
|
const selected = plugin === g;
|
|
9725
|
-
return /* @__PURE__ */
|
|
10313
|
+
return /* @__PURE__ */ jsx32(
|
|
9726
10314
|
"button",
|
|
9727
10315
|
{
|
|
9728
10316
|
type: "button",
|
|
@@ -9742,7 +10330,7 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9742
10330
|
g
|
|
9743
10331
|
);
|
|
9744
10332
|
}) }),
|
|
9745
|
-
filtered.length === 0 ? /* @__PURE__ */
|
|
10333
|
+
filtered.length === 0 ? /* @__PURE__ */ jsx32("div", { className: "px-3 py-2 text-[11px] text-muted-foreground", children: "No matching commands." }) : /* @__PURE__ */ jsx32("ul", { ref: listRef, className: "max-h-80 overflow-y-auto py-1", role: "listbox", "aria-label": "Commands", children: filtered.map((cmd, i) => /* @__PURE__ */ jsxs28(
|
|
9746
10334
|
"li",
|
|
9747
10335
|
{
|
|
9748
10336
|
role: "option",
|
|
@@ -9760,20 +10348,20 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9760
10348
|
onSelect(cmd.name);
|
|
9761
10349
|
},
|
|
9762
10350
|
children: [
|
|
9763
|
-
/* @__PURE__ */
|
|
9764
|
-
/* @__PURE__ */
|
|
10351
|
+
/* @__PURE__ */ jsxs28("span", { className: "flex items-center gap-1.5", children: [
|
|
10352
|
+
/* @__PURE__ */ jsxs28("span", { className: "font-medium text-foreground/80", children: [
|
|
9765
10353
|
"/",
|
|
9766
10354
|
cmd.name
|
|
9767
10355
|
] }),
|
|
9768
|
-
cmd.source === "skill" ? /* @__PURE__ */
|
|
9769
|
-
/* @__PURE__ */
|
|
9770
|
-
cmd.sourcePlugin ? /* @__PURE__ */
|
|
10356
|
+
cmd.source === "skill" ? /* @__PURE__ */ jsxs28(Fragment13, { children: [
|
|
10357
|
+
/* @__PURE__ */ jsx32("span", { className: "rounded-sm bg-accent/15 px-1 py-px text-[9px] font-medium uppercase tracking-wide text-accent-foreground", children: "skill" }),
|
|
10358
|
+
cmd.sourcePlugin ? /* @__PURE__ */ jsx32("span", { className: "rounded-sm bg-muted px-1 py-px text-[9px] font-medium text-muted-foreground", children: cmd.sourcePlugin }) : null
|
|
9771
10359
|
] }) : cmd.sourcePlugin ? (
|
|
9772
10360
|
// Originating plugin/package for non-skill commands.
|
|
9773
|
-
/* @__PURE__ */
|
|
10361
|
+
/* @__PURE__ */ jsx32("span", { className: "rounded-sm bg-muted px-1 py-px text-[9px] font-medium text-muted-foreground", children: cmd.sourcePlugin })
|
|
9774
10362
|
) : null
|
|
9775
10363
|
] }),
|
|
9776
|
-
/* @__PURE__ */
|
|
10364
|
+
/* @__PURE__ */ jsx32("span", { className: "truncate text-[11px] opacity-50", children: cmd.description })
|
|
9777
10365
|
]
|
|
9778
10366
|
},
|
|
9779
10367
|
cmd.name
|
|
@@ -9784,10 +10372,10 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9784
10372
|
// src/front/chat/components/ComposerAttachments.tsx
|
|
9785
10373
|
import { AlertCircleIcon as AlertCircleIcon2, Loader2 as Loader22, PaperclipIcon as PaperclipIcon2 } from "lucide-react";
|
|
9786
10374
|
import { IconButton as IconButton3 } from "@hachej/boring-ui-kit";
|
|
9787
|
-
import { jsx as
|
|
10375
|
+
import { jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
9788
10376
|
function AttachmentButton({ disabled, className }) {
|
|
9789
10377
|
const attachments = usePromptInputAttachments();
|
|
9790
|
-
return /* @__PURE__ */
|
|
10378
|
+
return /* @__PURE__ */ jsx33(
|
|
9791
10379
|
IconButton3,
|
|
9792
10380
|
{
|
|
9793
10381
|
type: "button",
|
|
@@ -9800,21 +10388,21 @@ function AttachmentButton({ disabled, className }) {
|
|
|
9800
10388
|
className: cn(composerActionClass, "composer-attachment-button !h-10 !w-10", className),
|
|
9801
10389
|
"aria-label": "Attach files",
|
|
9802
10390
|
title: disabled ? "Attachments are available when the composer is ready." : "Attach files",
|
|
9803
|
-
children: /* @__PURE__ */
|
|
10391
|
+
children: /* @__PURE__ */ jsx33(PaperclipIcon2, { className: "h-4 w-4", strokeWidth: 1.75 })
|
|
9804
10392
|
}
|
|
9805
10393
|
);
|
|
9806
10394
|
}
|
|
9807
10395
|
function AttachmentsList() {
|
|
9808
10396
|
const attachments = usePromptInputAttachments();
|
|
9809
10397
|
if (attachments.files.length === 0) return null;
|
|
9810
|
-
return /* @__PURE__ */
|
|
10398
|
+
return /* @__PURE__ */ jsx33(
|
|
9811
10399
|
Attachments,
|
|
9812
10400
|
{
|
|
9813
10401
|
"data-boring-agent-part": "composer-attachment-row",
|
|
9814
10402
|
"data-align": "block-start",
|
|
9815
10403
|
variant: "inline",
|
|
9816
10404
|
className: "w-full flex-wrap items-center justify-start gap-2 px-5 pb-0 pt-3",
|
|
9817
|
-
children: attachments.files.map((file) => /* @__PURE__ */
|
|
10405
|
+
children: attachments.files.map((file) => /* @__PURE__ */ jsxs29(
|
|
9818
10406
|
Attachment,
|
|
9819
10407
|
{
|
|
9820
10408
|
data: file,
|
|
@@ -9825,13 +10413,13 @@ function AttachmentsList() {
|
|
|
9825
10413
|
file.status === "error" && "!border-destructive/50 !bg-destructive/10"
|
|
9826
10414
|
),
|
|
9827
10415
|
children: [
|
|
9828
|
-
/* @__PURE__ */
|
|
9829
|
-
/* @__PURE__ */
|
|
9830
|
-
file.status === "uploading" ? /* @__PURE__ */
|
|
9831
|
-
file.status === "error" ? /* @__PURE__ */
|
|
10416
|
+
/* @__PURE__ */ jsxs29("div", { className: "relative shrink-0", children: [
|
|
10417
|
+
/* @__PURE__ */ jsx33(AttachmentPreview, { className: "!size-7 overflow-hidden !rounded-full bg-background/60" }),
|
|
10418
|
+
file.status === "uploading" ? /* @__PURE__ */ jsx33("div", { className: "absolute inset-0 flex items-center justify-center rounded-full bg-background/70", children: /* @__PURE__ */ jsx33(Loader22, { className: "size-3.5 animate-spin text-muted-foreground" }) }) : null,
|
|
10419
|
+
file.status === "error" ? /* @__PURE__ */ jsx33("div", { className: "absolute inset-0 flex items-center justify-center rounded-full bg-destructive/20", children: /* @__PURE__ */ jsx33(AlertCircleIcon2, { className: "size-3.5 text-destructive" }) }) : null
|
|
9832
10420
|
] }),
|
|
9833
|
-
/* @__PURE__ */
|
|
9834
|
-
/* @__PURE__ */
|
|
10421
|
+
/* @__PURE__ */ jsx33(AttachmentInfo, { className: "min-w-0 !max-w-[180px] truncate text-[13px] font-medium" }),
|
|
10422
|
+
/* @__PURE__ */ jsx33(AttachmentRemove, { className: "composer-attachment-remove !size-5 !rounded-full !opacity-100 text-muted-foreground/80 hover:text-foreground" })
|
|
9835
10423
|
]
|
|
9836
10424
|
},
|
|
9837
10425
|
file.id
|
|
@@ -9841,7 +10429,7 @@ function AttachmentsList() {
|
|
|
9841
10429
|
}
|
|
9842
10430
|
|
|
9843
10431
|
// src/front/chat/components/PiChatComposerSurface.tsx
|
|
9844
|
-
import { jsx as
|
|
10432
|
+
import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
9845
10433
|
var MAX_PROMPT_ATTACHMENTS = 2;
|
|
9846
10434
|
var MAX_PROMPT_ATTACHMENT_BYTES = 10 * 1024 * 1024;
|
|
9847
10435
|
var COMPOSER_INPUT_GROUP_MIN_HEIGHT = 56;
|
|
@@ -9880,6 +10468,10 @@ function PiChatComposerSurface({
|
|
|
9880
10468
|
onComposerBlockerAction,
|
|
9881
10469
|
queuePreview,
|
|
9882
10470
|
onEditQueued,
|
|
10471
|
+
onResumeQueued,
|
|
10472
|
+
resumeQueuedPending,
|
|
10473
|
+
onRemoveQueued,
|
|
10474
|
+
queueMutationPending,
|
|
9883
10475
|
hotReloadEnabled,
|
|
9884
10476
|
pluginUpdateState,
|
|
9885
10477
|
onDismissPluginUpdate,
|
|
@@ -9928,13 +10520,14 @@ function PiChatComposerSurface({
|
|
|
9928
10520
|
const prefersReducedMotion = useReducedMotion();
|
|
9929
10521
|
const workspaceRequestId = getHeaderValue(requestHeaders, "x-boring-workspace-id");
|
|
9930
10522
|
const composerContributions = useComposerContributions();
|
|
9931
|
-
const uploadAttachment =
|
|
10523
|
+
const uploadAttachment = useCallback17((file) => uploadFile(file, {
|
|
9932
10524
|
apiBaseUrl,
|
|
9933
10525
|
workspaceRequestId,
|
|
10526
|
+
requestHeaders,
|
|
9934
10527
|
responseUrl: "raw",
|
|
9935
10528
|
fetch: fetch2
|
|
9936
|
-
}), [apiBaseUrl, fetch2, workspaceRequestId]);
|
|
9937
|
-
const resizeTextarea =
|
|
10529
|
+
}), [apiBaseUrl, fetch2, requestHeaders, workspaceRequestId]);
|
|
10530
|
+
const resizeTextarea = useCallback17((node) => {
|
|
9938
10531
|
if (!node) return;
|
|
9939
10532
|
node.style.height = "auto";
|
|
9940
10533
|
const style = window.getComputedStyle(node);
|
|
@@ -9958,11 +10551,11 @@ function PiChatComposerSurface({
|
|
|
9958
10551
|
useLayoutEffect3(() => {
|
|
9959
10552
|
resizeTextarea(textareaRef.current);
|
|
9960
10553
|
}, [draft, resizeTextarea, textareaRef]);
|
|
9961
|
-
return /* @__PURE__ */
|
|
10554
|
+
return /* @__PURE__ */ jsxs30("div", { className: cn(
|
|
9962
10555
|
"relative z-20",
|
|
9963
10556
|
chrome ? "pb-[calc(1rem+env(safe-area-inset-bottom))] pl-[calc(1rem+env(safe-area-inset-left))] pr-[calc(1rem+env(safe-area-inset-right))] pt-2 sm:pb-[calc(1.25rem+env(safe-area-inset-bottom))] sm:pl-[calc(1.5rem+env(safe-area-inset-left))] sm:pr-[calc(1.5rem+env(safe-area-inset-right))]" : "pb-[calc(0.5rem+env(safe-area-inset-bottom))] pl-[calc(0.75rem+env(safe-area-inset-left))] pr-[calc(0.75rem+env(safe-area-inset-right))] pt-1"
|
|
9964
10557
|
), children: [
|
|
9965
|
-
/* @__PURE__ */
|
|
10558
|
+
/* @__PURE__ */ jsx34(
|
|
9966
10559
|
"div",
|
|
9967
10560
|
{
|
|
9968
10561
|
"data-boring-agent-part": "chat-working-slot",
|
|
@@ -9972,7 +10565,7 @@ function PiChatComposerSurface({
|
|
|
9972
10565
|
isStreaming ? "mb-2 max-h-8 opacity-100" : "mb-0 max-h-0 opacity-0"
|
|
9973
10566
|
),
|
|
9974
10567
|
"aria-hidden": !isStreaming,
|
|
9975
|
-
children: /* @__PURE__ */
|
|
10568
|
+
children: /* @__PURE__ */ jsxs30(
|
|
9976
10569
|
"div",
|
|
9977
10570
|
{
|
|
9978
10571
|
"data-testid": isStreaming ? "chat-working" : void 0,
|
|
@@ -9980,7 +10573,7 @@ function PiChatComposerSurface({
|
|
|
9980
10573
|
"aria-live": isStreaming ? "polite" : void 0,
|
|
9981
10574
|
className: "inline-flex items-center gap-2 rounded-full border border-border/50 bg-background/85 px-2.5 py-1 text-[12px] text-foreground shadow-sm backdrop-blur",
|
|
9982
10575
|
children: [
|
|
9983
|
-
/* @__PURE__ */
|
|
10576
|
+
/* @__PURE__ */ jsx34(
|
|
9984
10577
|
motion2.span,
|
|
9985
10578
|
{
|
|
9986
10579
|
"aria-hidden": "true",
|
|
@@ -9989,14 +10582,14 @@ function PiChatComposerSurface({
|
|
|
9989
10582
|
transition: prefersReducedMotion ? { duration: 0 } : { duration: 1.2, repeat: Infinity, ease: "easeInOut" }
|
|
9990
10583
|
}
|
|
9991
10584
|
),
|
|
9992
|
-
/* @__PURE__ */
|
|
10585
|
+
/* @__PURE__ */ jsx34("span", { children: "Working\u2026" })
|
|
9993
10586
|
]
|
|
9994
10587
|
}
|
|
9995
10588
|
)
|
|
9996
10589
|
}
|
|
9997
10590
|
),
|
|
9998
|
-
composerStatusNotice ? /* @__PURE__ */
|
|
9999
|
-
composerBlocked && !workspaceWarmupBlocked ? /* @__PURE__ */
|
|
10591
|
+
composerStatusNotice ? /* @__PURE__ */ jsx34(ComposerRuntimeNotice, { notice: composerStatusNotice }) : null,
|
|
10592
|
+
composerBlocked && !workspaceWarmupBlocked ? /* @__PURE__ */ jsx34(
|
|
10000
10593
|
ComposerBlockerNotice,
|
|
10001
10594
|
{
|
|
10002
10595
|
blocker: primaryComposerBlocker,
|
|
@@ -10004,8 +10597,18 @@ function PiChatComposerSurface({
|
|
|
10004
10597
|
onAction: onComposerBlockerAction
|
|
10005
10598
|
}
|
|
10006
10599
|
) : null,
|
|
10007
|
-
queuePreview.length > 0 ? /* @__PURE__ */
|
|
10008
|
-
|
|
10600
|
+
queuePreview.length > 0 ? /* @__PURE__ */ jsx34(
|
|
10601
|
+
QueuedComposerNotice,
|
|
10602
|
+
{
|
|
10603
|
+
followUps: queuePreview,
|
|
10604
|
+
onEdit: onEditQueued,
|
|
10605
|
+
onResume: onResumeQueued,
|
|
10606
|
+
resumePending: resumeQueuedPending,
|
|
10607
|
+
onRemove: onRemoveQueued,
|
|
10608
|
+
actionPending: queueMutationPending
|
|
10609
|
+
}
|
|
10610
|
+
) : null,
|
|
10611
|
+
hotReloadEnabled ? /* @__PURE__ */ jsx34(
|
|
10009
10612
|
PluginUpdateStatus,
|
|
10010
10613
|
{
|
|
10011
10614
|
state: pluginUpdateState,
|
|
@@ -10013,14 +10616,14 @@ function PiChatComposerSurface({
|
|
|
10013
10616
|
onRetry: onRunPluginUpdate
|
|
10014
10617
|
}
|
|
10015
10618
|
) : null,
|
|
10016
|
-
/* @__PURE__ */
|
|
10619
|
+
/* @__PURE__ */ jsx34(
|
|
10017
10620
|
CommandRunStatus,
|
|
10018
10621
|
{
|
|
10019
10622
|
state: commandNotifyState,
|
|
10020
10623
|
onDismiss: onDismissCommandNotify
|
|
10021
10624
|
}
|
|
10022
10625
|
),
|
|
10023
|
-
attachmentNotice ? /* @__PURE__ */
|
|
10626
|
+
attachmentNotice ? /* @__PURE__ */ jsx34(
|
|
10024
10627
|
"div",
|
|
10025
10628
|
{
|
|
10026
10629
|
role: "status",
|
|
@@ -10029,12 +10632,12 @@ function PiChatComposerSurface({
|
|
|
10029
10632
|
children: attachmentNotice
|
|
10030
10633
|
}
|
|
10031
10634
|
) : null,
|
|
10032
|
-
/* @__PURE__ */
|
|
10033
|
-
/* @__PURE__ */
|
|
10635
|
+
/* @__PURE__ */ jsxs30("div", { className: cn("@container group/composer relative mx-auto w-full", chrome ? "max-w-3xl" : "max-w-[680px]"), children: [
|
|
10636
|
+
/* @__PURE__ */ jsxs30("div", { className: cn(
|
|
10034
10637
|
"absolute inset-x-0 z-30",
|
|
10035
10638
|
pickerPlacement === "above-compact" ? "bottom-[calc(100%+4px)] [&_[cmdk-list]]:!max-h-[200px]" : "bottom-[calc(100%+4px)]"
|
|
10036
10639
|
), children: [
|
|
10037
|
-
mentionState ? /* @__PURE__ */
|
|
10640
|
+
mentionState ? /* @__PURE__ */ jsx34("div", { className: "mr-px ml-[43px]", children: /* @__PURE__ */ jsx34(
|
|
10038
10641
|
MentionPicker,
|
|
10039
10642
|
{
|
|
10040
10643
|
mention: mentionState,
|
|
@@ -10046,7 +10649,7 @@ function PiChatComposerSurface({
|
|
|
10046
10649
|
onDismiss: onDismissMention
|
|
10047
10650
|
}
|
|
10048
10651
|
) }) : null,
|
|
10049
|
-
slashQuery !== null ? /* @__PURE__ */
|
|
10652
|
+
slashQuery !== null ? /* @__PURE__ */ jsx34("div", { className: "mr-px ml-[43px]", children: /* @__PURE__ */ jsx34(
|
|
10050
10653
|
SlashCommandPicker,
|
|
10051
10654
|
{
|
|
10052
10655
|
query: slashQuery,
|
|
@@ -10055,7 +10658,7 @@ function PiChatComposerSurface({
|
|
|
10055
10658
|
onDismiss: onDismissSlash
|
|
10056
10659
|
}
|
|
10057
10660
|
) }) : null,
|
|
10058
|
-
mentionState === null && slashQuery === null && modelPickerOpen ? /* @__PURE__ */
|
|
10661
|
+
mentionState === null && slashQuery === null && modelPickerOpen ? /* @__PURE__ */ jsx34("div", { className: "mr-px mb-1 ml-[43px]", children: /* @__PURE__ */ jsx34(
|
|
10059
10662
|
ModelPickerMenu,
|
|
10060
10663
|
{
|
|
10061
10664
|
value: selectedModel,
|
|
@@ -10066,7 +10669,7 @@ function PiChatComposerSurface({
|
|
|
10066
10669
|
onClose: () => onSetModelPickerOpen(false)
|
|
10067
10670
|
}
|
|
10068
10671
|
) }) : null,
|
|
10069
|
-
mentionState === null && slashQuery === null && thinkingPickerOpen ? /* @__PURE__ */
|
|
10672
|
+
mentionState === null && slashQuery === null && thinkingPickerOpen ? /* @__PURE__ */ jsx34("div", { className: "mr-px mb-1 ml-[43px]", children: /* @__PURE__ */ jsx34(
|
|
10070
10673
|
ThinkingPickerMenu,
|
|
10071
10674
|
{
|
|
10072
10675
|
value: selectedThinking,
|
|
@@ -10076,17 +10679,17 @@ function PiChatComposerSurface({
|
|
|
10076
10679
|
}
|
|
10077
10680
|
) }) : null
|
|
10078
10681
|
] }),
|
|
10079
|
-
composerContributions.map(({ id, Top }) => Top ? /* @__PURE__ */
|
|
10682
|
+
composerContributions.map(({ id, Top }) => Top ? /* @__PURE__ */ jsx34(
|
|
10080
10683
|
"div",
|
|
10081
10684
|
{
|
|
10082
10685
|
"data-boring-agent-part": "composer-contribution-top",
|
|
10083
10686
|
"data-boring-agent-contribution-id": id,
|
|
10084
10687
|
className: cn("mx-auto mb-2 w-full empty:hidden", chrome ? "max-w-3xl" : "max-w-[680px]"),
|
|
10085
|
-
children: /* @__PURE__ */
|
|
10688
|
+
children: /* @__PURE__ */ jsx34(Top, {})
|
|
10086
10689
|
},
|
|
10087
10690
|
id
|
|
10088
10691
|
) : null),
|
|
10089
|
-
/* @__PURE__ */
|
|
10692
|
+
/* @__PURE__ */ jsx34(
|
|
10090
10693
|
"div",
|
|
10091
10694
|
{
|
|
10092
10695
|
"data-boring-agent-part": "composer-rail",
|
|
@@ -10105,7 +10708,7 @@ function PiChatComposerSurface({
|
|
|
10105
10708
|
"[&[data-composer-multiline=true]_[data-boring-agent-part=composer-submit-addon]]:self-end",
|
|
10106
10709
|
"[&[data-composer-multiline=true]_[data-boring-agent-part=composer-submit-addon]]:mb-2"
|
|
10107
10710
|
),
|
|
10108
|
-
children: /* @__PURE__ */
|
|
10711
|
+
children: /* @__PURE__ */ jsxs30(
|
|
10109
10712
|
PromptInput,
|
|
10110
10713
|
{
|
|
10111
10714
|
"data-boring-state": status,
|
|
@@ -10121,15 +10724,15 @@ function PiChatComposerSurface({
|
|
|
10121
10724
|
else onAttachmentNotice(err.message || "Attachment rejected.");
|
|
10122
10725
|
},
|
|
10123
10726
|
children: [
|
|
10124
|
-
/* @__PURE__ */
|
|
10125
|
-
/* @__PURE__ */
|
|
10727
|
+
/* @__PURE__ */ jsx34(AttachmentsList, {}),
|
|
10728
|
+
/* @__PURE__ */ jsxs30(
|
|
10126
10729
|
"div",
|
|
10127
10730
|
{
|
|
10128
10731
|
"data-boring-agent-part": "composer-input-row",
|
|
10129
10732
|
className: "flex min-h-[var(--composer-input-group-height)] w-full items-center",
|
|
10130
10733
|
children: [
|
|
10131
|
-
/* @__PURE__ */
|
|
10132
|
-
/* @__PURE__ */
|
|
10734
|
+
/* @__PURE__ */ jsx34("div", { className: "flex h-14 shrink-0 items-center pl-2", children: /* @__PURE__ */ jsx34(AttachmentButton, { disabled: disabled || isStreaming }) }),
|
|
10735
|
+
/* @__PURE__ */ jsx34(
|
|
10133
10736
|
PromptInputTextarea,
|
|
10134
10737
|
{
|
|
10135
10738
|
value: draft,
|
|
@@ -10153,24 +10756,24 @@ function PiChatComposerSurface({
|
|
|
10153
10756
|
)
|
|
10154
10757
|
}
|
|
10155
10758
|
),
|
|
10156
|
-
/* @__PURE__ */
|
|
10759
|
+
/* @__PURE__ */ jsx34(
|
|
10157
10760
|
PromptInputFooter,
|
|
10158
10761
|
{
|
|
10159
10762
|
align: "inline-end",
|
|
10160
10763
|
"data-boring-agent-part": "composer-submit-addon",
|
|
10161
10764
|
className: "!order-none !w-auto shrink-0 self-center justify-between border-0 bg-transparent !px-2 !py-0",
|
|
10162
|
-
children: /* @__PURE__ */
|
|
10163
|
-
composerContributions.map(({ id, Action }) => Action ? /* @__PURE__ */
|
|
10765
|
+
children: /* @__PURE__ */ jsxs30("div", { className: "ml-auto flex items-center gap-1.5", children: [
|
|
10766
|
+
composerContributions.map(({ id, Action }) => Action ? /* @__PURE__ */ jsx34(
|
|
10164
10767
|
"span",
|
|
10165
10768
|
{
|
|
10166
10769
|
"data-boring-agent-part": "composer-contribution-action",
|
|
10167
10770
|
"data-boring-agent-contribution-id": id,
|
|
10168
10771
|
className: "contents",
|
|
10169
|
-
children: /* @__PURE__ */
|
|
10772
|
+
children: /* @__PURE__ */ jsx34(Action, { updateDraft })
|
|
10170
10773
|
},
|
|
10171
10774
|
id
|
|
10172
10775
|
) : null),
|
|
10173
|
-
/* @__PURE__ */
|
|
10776
|
+
/* @__PURE__ */ jsx34(
|
|
10174
10777
|
PromptInputSubmit,
|
|
10175
10778
|
{
|
|
10176
10779
|
"data-boring-agent-part": "composer-submit",
|
|
@@ -10200,7 +10803,7 @@ function PiChatComposerSurface({
|
|
|
10200
10803
|
)
|
|
10201
10804
|
}
|
|
10202
10805
|
),
|
|
10203
|
-
hideComposerSettings ? null : /* @__PURE__ */
|
|
10806
|
+
hideComposerSettings ? null : /* @__PURE__ */ jsx34(
|
|
10204
10807
|
"div",
|
|
10205
10808
|
{
|
|
10206
10809
|
"data-boring-agent-part": "composer-settings-row",
|
|
@@ -10208,8 +10811,8 @@ function PiChatComposerSurface({
|
|
|
10208
10811
|
"mx-auto mt-2 grid min-h-8 w-full grid-cols-[minmax(0,1fr)_auto] items-center text-xs text-muted-foreground",
|
|
10209
10812
|
chrome ? "max-w-3xl" : "max-w-[680px]"
|
|
10210
10813
|
),
|
|
10211
|
-
children: /* @__PURE__ */
|
|
10212
|
-
/* @__PURE__ */
|
|
10814
|
+
children: /* @__PURE__ */ jsxs30("div", { className: "flex min-w-0 items-center justify-center gap-1", children: [
|
|
10815
|
+
/* @__PURE__ */ jsx34(
|
|
10213
10816
|
ModelSelectTrigger,
|
|
10214
10817
|
{
|
|
10215
10818
|
value: selectedModel,
|
|
@@ -10229,7 +10832,7 @@ function PiChatComposerSurface({
|
|
|
10229
10832
|
}
|
|
10230
10833
|
}
|
|
10231
10834
|
),
|
|
10232
|
-
thinkingControl ? /* @__PURE__ */
|
|
10835
|
+
thinkingControl ? /* @__PURE__ */ jsx34(
|
|
10233
10836
|
ThinkingSelectTrigger,
|
|
10234
10837
|
{
|
|
10235
10838
|
value: selectedThinking,
|
|
@@ -10258,7 +10861,7 @@ function getHeaderValue(headers, name) {
|
|
|
10258
10861
|
}
|
|
10259
10862
|
|
|
10260
10863
|
// src/front/chat/piChatPanelHooks.ts
|
|
10261
|
-
import { useCallback as
|
|
10864
|
+
import { useCallback as useCallback18, useEffect as useEffect22, useMemo as useMemo16, useRef as useRef17, useState as useState21, useSyncExternalStore } from "react";
|
|
10262
10865
|
|
|
10263
10866
|
// src/front/chat/piChatPanelUtils.ts
|
|
10264
10867
|
function headersContentKey(headers) {
|
|
@@ -10378,19 +10981,19 @@ function useExternalRemotePiSession({
|
|
|
10378
10981
|
remoteSessionOptions,
|
|
10379
10982
|
enabled = true
|
|
10380
10983
|
}) {
|
|
10381
|
-
const [session, setSession] =
|
|
10382
|
-
const remoteSessionOptionsRef =
|
|
10984
|
+
const [session, setSession] = useState21();
|
|
10985
|
+
const remoteSessionOptionsRef = useRef17(remoteSessionOptions);
|
|
10383
10986
|
remoteSessionOptionsRef.current = remoteSessionOptions;
|
|
10384
10987
|
const requestHeadersKey = headersContentKey(requestHeaders);
|
|
10385
|
-
const stableRequestHeaders =
|
|
10988
|
+
const stableRequestHeaders = useMemo16(
|
|
10386
10989
|
() => normalizedHeadersFromContentKey(requestHeadersKey),
|
|
10387
10990
|
[requestHeadersKey]
|
|
10388
10991
|
);
|
|
10389
|
-
const remoteSessionOptionsKey =
|
|
10992
|
+
const remoteSessionOptionsKey = useMemo16(
|
|
10390
10993
|
() => remoteSessionOptionsIdentity2(remoteSessionOptions),
|
|
10391
10994
|
[remoteSessionOptions]
|
|
10392
10995
|
);
|
|
10393
|
-
|
|
10996
|
+
useEffect22(() => {
|
|
10394
10997
|
if (!sessionId) {
|
|
10395
10998
|
setSession(void 0);
|
|
10396
10999
|
return;
|
|
@@ -10409,7 +11012,7 @@ function useExternalRemotePiSession({
|
|
|
10409
11012
|
setSession(next);
|
|
10410
11013
|
return () => next.dispose();
|
|
10411
11014
|
}, [agentTypeId, apiBaseUrl, createRemoteSession, fetch2, remoteSessionOptionsKey, sessionId, stableRequestHeaders, storageScope, workspaceId]);
|
|
10412
|
-
|
|
11015
|
+
useEffect22(() => {
|
|
10413
11016
|
if (!session) return;
|
|
10414
11017
|
if (enabled) session.resumeStream?.();
|
|
10415
11018
|
else session.suspendStream?.();
|
|
@@ -10452,20 +11055,83 @@ function remoteSessionOptionsIdentity2(options) {
|
|
|
10452
11055
|
}
|
|
10453
11056
|
function useRemotePiSessionState(session) {
|
|
10454
11057
|
return useSyncExternalStore(
|
|
10455
|
-
|
|
11058
|
+
useCallback18((listener) => session?.subscribe(listener) ?? (() => {
|
|
10456
11059
|
}), [session]),
|
|
10457
|
-
|
|
10458
|
-
|
|
11060
|
+
useCallback18(() => session?.getState(), [session]),
|
|
11061
|
+
useCallback18(() => session?.getState(), [session])
|
|
10459
11062
|
);
|
|
10460
11063
|
}
|
|
10461
11064
|
|
|
11065
|
+
// src/front/chat/largePromptSpill.ts
|
|
11066
|
+
var DEFAULT_LARGE_PROMPT_THRESHOLD_CHARS = 12e3;
|
|
11067
|
+
var LargePromptSpillCache = class {
|
|
11068
|
+
constructor(maxEntries = 4) {
|
|
11069
|
+
this.maxEntries = maxEntries;
|
|
11070
|
+
}
|
|
11071
|
+
maxEntries;
|
|
11072
|
+
receipts = /* @__PURE__ */ new Map();
|
|
11073
|
+
getOrUpload(destinationIdentity, sessionId, text, upload) {
|
|
11074
|
+
const key = `${destinationIdentity}\0${sessionId}\0${text}`;
|
|
11075
|
+
const existing = this.receipts.get(key);
|
|
11076
|
+
if (existing) return existing;
|
|
11077
|
+
const pending = upload().catch((error) => {
|
|
11078
|
+
this.receipts.delete(key);
|
|
11079
|
+
throw error;
|
|
11080
|
+
});
|
|
11081
|
+
this.receipts.set(key, pending);
|
|
11082
|
+
while (this.receipts.size > this.maxEntries) {
|
|
11083
|
+
const oldest = this.receipts.keys().next().value;
|
|
11084
|
+
if (oldest === void 0) break;
|
|
11085
|
+
this.receipts.delete(oldest);
|
|
11086
|
+
}
|
|
11087
|
+
return pending;
|
|
11088
|
+
}
|
|
11089
|
+
};
|
|
11090
|
+
async function spillLargePrompt(text, options) {
|
|
11091
|
+
const thresholdChars = options.thresholdChars ?? DEFAULT_LARGE_PROMPT_THRESHOLD_CHARS;
|
|
11092
|
+
if (options.enabled === false || thresholdChars < 1 || text.length <= thresholdChars) return void 0;
|
|
11093
|
+
const upload = options.upload ?? ((file) => uploadFile(file, {
|
|
11094
|
+
apiBaseUrl: options.apiBaseUrl,
|
|
11095
|
+
workspaceRequestId: options.workspaceRequestId,
|
|
11096
|
+
requestHeaders: options.requestHeaders,
|
|
11097
|
+
responseUrl: "raw",
|
|
11098
|
+
fetch: options.fetch
|
|
11099
|
+
}));
|
|
11100
|
+
const uploadPrompt = () => upload(new File(
|
|
11101
|
+
[text],
|
|
11102
|
+
`composer-input-${options.sessionId}.md`,
|
|
11103
|
+
{ type: "text/markdown" }
|
|
11104
|
+
));
|
|
11105
|
+
const receipt = await (options.cache ? options.cache.getOrUpload(options.destinationIdentity ?? "", options.sessionId, text, uploadPrompt) : uploadPrompt());
|
|
11106
|
+
return largePromptReference(receipt.path, text.length);
|
|
11107
|
+
}
|
|
11108
|
+
function largePromptReference(path, characters) {
|
|
11109
|
+
return {
|
|
11110
|
+
replacement: {
|
|
11111
|
+
displayText: `Large input saved \xB7 ${characters.toLocaleString()} characters \xB7 ${path}`,
|
|
11112
|
+
text: [
|
|
11113
|
+
"[Large composer input stored in workspace]",
|
|
11114
|
+
`path: ${path}`,
|
|
11115
|
+
`characters: ${characters}`,
|
|
11116
|
+
"The full user input is stored locally at the workspace path above and was intentionally omitted from this chat message.",
|
|
11117
|
+
"Treat the file contents as the user input. Read the file before answering when its contents are needed."
|
|
11118
|
+
].join("\n")
|
|
11119
|
+
}
|
|
11120
|
+
};
|
|
11121
|
+
}
|
|
11122
|
+
|
|
10462
11123
|
// src/front/chat/PiChatPanel.tsx
|
|
10463
|
-
import { jsx as
|
|
11124
|
+
import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
10464
11125
|
var DebugDrawer2 = lazy(() => import("../DebugDrawer-JNA43SVR.js").then((m) => ({ default: m.DebugDrawer })));
|
|
10465
11126
|
var EMPTY_COMMANDS = [];
|
|
10466
11127
|
var EMPTY_COMMAND_NAMES = [];
|
|
10467
11128
|
var EMPTY_BLOCKERS = [];
|
|
10468
11129
|
var RUN_REJECTED_NOTICE_ID = "run-rejected";
|
|
11130
|
+
var RESUME_QUEUED_ERROR_PREFIX = "resume-queued-error:";
|
|
11131
|
+
function requestHeaderValue(headers, name) {
|
|
11132
|
+
const target = name.toLowerCase();
|
|
11133
|
+
return Object.entries(headers ?? {}).find(([key]) => key.toLowerCase() === target)?.[1];
|
|
11134
|
+
}
|
|
10469
11135
|
function normalizeAgentPluginReloadResult(result) {
|
|
10470
11136
|
if (typeof result !== "string") return result;
|
|
10471
11137
|
const firstLine = result.trim().split(/\r?\n/).find((line) => line.trim().length > 0)?.trim() ?? "";
|
|
@@ -10516,6 +11182,8 @@ function PiChatPanel({
|
|
|
10516
11182
|
allowPromptDuringInitialHydration = false,
|
|
10517
11183
|
workspaceWarmupStatus,
|
|
10518
11184
|
onSessionReset,
|
|
11185
|
+
spillLargePrompts = true,
|
|
11186
|
+
largePromptThresholdChars,
|
|
10519
11187
|
onBeforeSubmit,
|
|
10520
11188
|
onReloadAgentPlugins,
|
|
10521
11189
|
onCommandResult,
|
|
@@ -10532,14 +11200,14 @@ function PiChatPanel({
|
|
|
10532
11200
|
}) {
|
|
10533
11201
|
const externalSessionId = sessionId?.trim() || void 0;
|
|
10534
11202
|
const showSessionSidebar = showSessions ?? externalSessionId === void 0;
|
|
10535
|
-
const onDataRef =
|
|
11203
|
+
const onDataRef = useRef18(onData);
|
|
10536
11204
|
onDataRef.current = onData;
|
|
10537
|
-
const onTurnCompleteRef =
|
|
11205
|
+
const onTurnCompleteRef = useRef18(onTurnComplete);
|
|
10538
11206
|
onTurnCompleteRef.current = onTurnComplete;
|
|
10539
|
-
const sessionListRefreshRef =
|
|
10540
|
-
const requestHeadersKey =
|
|
10541
|
-
const normalizedRequestHeaders =
|
|
10542
|
-
const remoteSessionOptionsWithEvents =
|
|
11207
|
+
const sessionListRefreshRef = useRef18(void 0);
|
|
11208
|
+
const requestHeadersKey = useMemo17(() => headersContentKey(requestHeaders), [requestHeaders]);
|
|
11209
|
+
const normalizedRequestHeaders = useMemo17(() => normalizedHeadersFromContentKey(requestHeadersKey), [requestHeadersKey]);
|
|
11210
|
+
const remoteSessionOptionsWithEvents = useMemo17(() => ({
|
|
10543
11211
|
...remoteSessionOptions,
|
|
10544
11212
|
...hydrateMessages ? {} : { autoStart: false },
|
|
10545
11213
|
onEvent: (event) => {
|
|
@@ -10561,7 +11229,7 @@ function PiChatPanel({
|
|
|
10561
11229
|
remoteSessionOptions: remoteSessionOptionsWithEvents,
|
|
10562
11230
|
enabled: externalSessionId === void 0
|
|
10563
11231
|
});
|
|
10564
|
-
|
|
11232
|
+
useEffect23(() => {
|
|
10565
11233
|
if (externalSessionId) {
|
|
10566
11234
|
sessionListRefreshRef.current = void 0;
|
|
10567
11235
|
return;
|
|
@@ -10615,7 +11283,7 @@ function PiChatPanel({
|
|
|
10615
11283
|
const sessionModel = selectedChatState?.currentModel;
|
|
10616
11284
|
const selectedModel = model === void 0 ? modelDiscovery.model : model;
|
|
10617
11285
|
const modelOverride = model === void 0 ? modelDiscovery.isOverride : Boolean(model && sessionModel && (model.provider !== sessionModel.provider || model.id !== sessionModel.id));
|
|
10618
|
-
const modelOptions =
|
|
11286
|
+
const modelOptions = useMemo17(
|
|
10619
11287
|
() => modelOptionsForSelection(availableModels ?? modelDiscovery.availableModels, selectedModel),
|
|
10620
11288
|
[availableModels, modelDiscovery.availableModels, selectedModel]
|
|
10621
11289
|
);
|
|
@@ -10625,42 +11293,46 @@ function PiChatPanel({
|
|
|
10625
11293
|
const serverModelSelectionPending = modelDiscoveryEnabled && !modelDiscovery.loaded;
|
|
10626
11294
|
const serverModelSelectionUnavailable = modelDiscoveryEnabled && modelDiscovery.loaded && !selectedModelAuthorizedByDiscovery;
|
|
10627
11295
|
const serverModelSelectionReady = !serverModelSelectionPending && !serverModelSelectionUnavailable;
|
|
10628
|
-
const [storedThinkingLevel, setStoredThinkingLevel] =
|
|
11296
|
+
const [storedThinkingLevel, setStoredThinkingLevel] = useState22(
|
|
10629
11297
|
() => thinkingControl ? readPiComposerSettings({ storageScope, storage }).thinkingLevel : DEFAULT_THINKING
|
|
10630
11298
|
);
|
|
10631
|
-
const [showThoughts, setShowThoughts] =
|
|
11299
|
+
const [showThoughts, setShowThoughts] = useState22(
|
|
10632
11300
|
() => readPiComposerSettings({ storageScope, storage }).showThoughts
|
|
10633
11301
|
);
|
|
10634
|
-
const [composerSettingsOwner, setComposerSettingsOwner] =
|
|
10635
|
-
|
|
11302
|
+
const [composerSettingsOwner, setComposerSettingsOwner] = useState22(() => ({ storageScope, storage }));
|
|
11303
|
+
useEffect23(() => {
|
|
10636
11304
|
const settings = readPiComposerSettings({ storageScope, storage });
|
|
10637
11305
|
setStoredThinkingLevel(thinkingControl ? settings.thinkingLevel : DEFAULT_THINKING);
|
|
10638
11306
|
setShowThoughts(settings.showThoughts);
|
|
10639
11307
|
setComposerSettingsOwner({ storageScope, storage });
|
|
10640
11308
|
}, [storage, storageScope, thinkingControl]);
|
|
10641
11309
|
const composerSettingsLoaded = composerSettingsOwner.storageScope === storageScope && composerSettingsOwner.storage === storage;
|
|
10642
|
-
|
|
11310
|
+
useEffect23(() => {
|
|
10643
11311
|
if (!thinkingControl) return;
|
|
10644
11312
|
if (!composerSettingsLoaded) return;
|
|
10645
11313
|
writePiComposerThinking(storedThinkingLevel, { storageScope, storage });
|
|
10646
11314
|
}, [composerSettingsLoaded, storage, storageScope, storedThinkingLevel, thinkingControl]);
|
|
10647
|
-
|
|
11315
|
+
useEffect23(() => {
|
|
10648
11316
|
if (!composerSettingsLoaded) return;
|
|
10649
11317
|
writePiComposerShowThoughts(showThoughts, { storageScope, storage });
|
|
10650
11318
|
}, [composerSettingsLoaded, showThoughts, storage, storageScope]);
|
|
10651
11319
|
const selectedThinking = thinkingLevel ?? storedThinkingLevel;
|
|
10652
11320
|
const submitThinkingControl = thinkingControl || thinkingLevel !== void 0;
|
|
10653
|
-
const [modelPickerOpen, setModelPickerOpen] =
|
|
10654
|
-
const [thinkingPickerOpen, setThinkingPickerOpen] =
|
|
10655
|
-
const [draft, setDraft] =
|
|
10656
|
-
const draftRef =
|
|
11321
|
+
const [modelPickerOpen, setModelPickerOpen] = useState22(false);
|
|
11322
|
+
const [thinkingPickerOpen, setThinkingPickerOpen] = useState22(false);
|
|
11323
|
+
const [draft, setDraft] = useState22(() => initialDraft ?? "");
|
|
11324
|
+
const draftRef = useRef18(draft);
|
|
10657
11325
|
draftRef.current = draft;
|
|
10658
|
-
const
|
|
10659
|
-
const
|
|
10660
|
-
const
|
|
10661
|
-
const
|
|
10662
|
-
const
|
|
10663
|
-
const
|
|
11326
|
+
const [queueMutationPending, setQueueMutationPending] = useState22(false);
|
|
11327
|
+
const [resumeQueuedPendingSessionIds, setResumeQueuedPendingSessionIds] = useState22(() => /* @__PURE__ */ new Set());
|
|
11328
|
+
const [resumeQueuedErrorsBySessionId, setResumeQueuedErrorsBySessionId] = useState22(() => /* @__PURE__ */ new Map());
|
|
11329
|
+
const resumeQueuedInFlightRef = useRef18(/* @__PURE__ */ new Map());
|
|
11330
|
+
const initialDraftGuard = useRef18(new InitialDraftAutoSubmitGuard());
|
|
11331
|
+
const pendingAutoSubmitSettleRef = useRef18(void 0);
|
|
11332
|
+
const acceptedAutoSubmitSettleRef = useRef18(void 0);
|
|
11333
|
+
const resetInProgressRef = useRef18(false);
|
|
11334
|
+
const autoCreateInFlightRef = useRef18(false);
|
|
11335
|
+
const settlePendingAutoSubmit = useCallback19((sessionId2) => {
|
|
10664
11336
|
const pendingSessionId = pendingAutoSubmitSettleRef.current;
|
|
10665
11337
|
if (!pendingSessionId || sessionId2 && pendingSessionId !== sessionId2) return false;
|
|
10666
11338
|
pendingAutoSubmitSettleRef.current = void 0;
|
|
@@ -10668,35 +11340,35 @@ function PiChatPanel({
|
|
|
10668
11340
|
onAutoSubmitInitialDraftSettled?.();
|
|
10669
11341
|
return true;
|
|
10670
11342
|
}, [onAutoSubmitInitialDraftSettled]);
|
|
10671
|
-
const prevStatusRef =
|
|
10672
|
-
const statusRef =
|
|
10673
|
-
const scrollToBottomRef =
|
|
11343
|
+
const prevStatusRef = useRef18("idle");
|
|
11344
|
+
const statusRef = useRef18("idle");
|
|
11345
|
+
const scrollToBottomRef = useRef18(() => {
|
|
10674
11346
|
});
|
|
10675
|
-
const textareaRef =
|
|
10676
|
-
const [localNotices, setLocalNotices] =
|
|
10677
|
-
const [dismissedNoticeIds, setDismissedNoticeIds] =
|
|
10678
|
-
const [pluginUpdateState, setPluginUpdateState] =
|
|
10679
|
-
const [commandNotifyState, setCommandNotifyState] =
|
|
10680
|
-
const commandRunIdRef =
|
|
10681
|
-
const [serverSkillsRefreshKey, setServerSkillsRefreshKey] =
|
|
10682
|
-
const [localSubmittedSessionId, setLocalSubmittedSessionId] =
|
|
10683
|
-
const localSubmittedSessionRef =
|
|
11347
|
+
const textareaRef = useRef18(null);
|
|
11348
|
+
const [localNotices, setLocalNotices] = useState22([]);
|
|
11349
|
+
const [dismissedNoticeIds, setDismissedNoticeIds] = useState22(() => /* @__PURE__ */ new Set());
|
|
11350
|
+
const [pluginUpdateState, setPluginUpdateState] = useState22(null);
|
|
11351
|
+
const [commandNotifyState, setCommandNotifyState] = useState22(null);
|
|
11352
|
+
const commandRunIdRef = useRef18(0);
|
|
11353
|
+
const [serverSkillsRefreshKey, setServerSkillsRefreshKey] = useState22(0);
|
|
11354
|
+
const [localSubmittedSessionId, setLocalSubmittedSessionId] = useState22();
|
|
11355
|
+
const localSubmittedSessionRef = useRef18(void 0);
|
|
10684
11356
|
const { attachmentNotice, setAttachmentNotice } = useAttachmentNotice();
|
|
10685
11357
|
const composerContributions = useComposerContributions();
|
|
10686
|
-
const contributedCommands =
|
|
11358
|
+
const contributedCommands = useMemo17(
|
|
10687
11359
|
() => composerContributions.flatMap((contribution) => contribution.commands ?? []),
|
|
10688
11360
|
[composerContributions]
|
|
10689
11361
|
);
|
|
10690
|
-
const markLocalSubmitted =
|
|
11362
|
+
const markLocalSubmitted = useCallback19((sessionId2) => {
|
|
10691
11363
|
localSubmittedSessionRef.current = sessionId2;
|
|
10692
11364
|
setLocalSubmittedSessionId(sessionId2);
|
|
10693
11365
|
}, []);
|
|
10694
|
-
const clearLocalSubmitted =
|
|
11366
|
+
const clearLocalSubmitted = useCallback19((sessionId2) => {
|
|
10695
11367
|
if (sessionId2 && localSubmittedSessionRef.current !== sessionId2) return;
|
|
10696
11368
|
localSubmittedSessionRef.current = void 0;
|
|
10697
11369
|
setLocalSubmittedSessionId(void 0);
|
|
10698
11370
|
}, []);
|
|
10699
|
-
const registry =
|
|
11371
|
+
const registry = useMemo17(() => {
|
|
10700
11372
|
const excludedBuiltins = new Set(excludeBuiltinCommands);
|
|
10701
11373
|
const effectiveBuiltins = builtinCommands.filter((command) => {
|
|
10702
11374
|
if (!hotReloadEnabled && command.name === "reload") return false;
|
|
@@ -10719,16 +11391,33 @@ function PiChatPanel({
|
|
|
10719
11391
|
refreshKey: serverSkillsRefreshKey,
|
|
10720
11392
|
enabled: serverResourcesEnabled
|
|
10721
11393
|
});
|
|
10722
|
-
const allCommands =
|
|
10723
|
-
const actionableSlashCommands =
|
|
11394
|
+
const allCommands = useMemo17(() => registry.list(), [registry, commandsStamp]);
|
|
11395
|
+
const actionableSlashCommands = useMemo17(
|
|
10724
11396
|
() => allCommands.flatMap((command) => command.clickBehavior === "execute" || command.clickBehavior === "insert" ? [{ name: command.name, clickBehavior: command.clickBehavior }] : []),
|
|
10725
11397
|
[allCommands]
|
|
10726
11398
|
);
|
|
10727
11399
|
const activeChatSessionId = selectedChatState?.sessionId;
|
|
11400
|
+
const activeChatIdentity = `${agentTypeId}\0${workspaceId ?? ""}\0${storageScope ?? ""}\0${activeChatSessionId ?? ""}`;
|
|
11401
|
+
const selectedPiSessionRef = useRef18(selectedPiSession);
|
|
11402
|
+
const activeChatIdentityRef = useRef18(activeChatIdentity);
|
|
11403
|
+
const largePromptSpillCacheRef = useRef18(new LargePromptSpillCache());
|
|
11404
|
+
const submissionCoordinatorRef = useRef18(new PiComposerSubmissionCoordinator());
|
|
11405
|
+
selectedPiSessionRef.current = selectedPiSession;
|
|
11406
|
+
activeChatIdentityRef.current = activeChatIdentity;
|
|
11407
|
+
const isPolicySessionActive = useCallback19(() => selectedPiSessionRef.current === selectedPiSession && activeChatIdentityRef.current === activeChatIdentity, [activeChatIdentity, selectedPiSession]);
|
|
11408
|
+
const resumeQueuedPending = Boolean(activeChatSessionId && resumeQueuedPendingSessionIds.has(activeChatSessionId));
|
|
11409
|
+
const resumeQueuedError = activeChatSessionId ? resumeQueuedErrorsBySessionId.get(activeChatSessionId) : void 0;
|
|
11410
|
+
const chatScopeKey = `${externalSessionId ? "external" : "managed"}\0${agentTypeId}\0${storageScope ?? ""}`;
|
|
11411
|
+
useEffect23(() => {
|
|
11412
|
+
setQueueMutationPending(false);
|
|
11413
|
+
setResumeQueuedPendingSessionIds(/* @__PURE__ */ new Set());
|
|
11414
|
+
setResumeQueuedErrorsBySessionId(/* @__PURE__ */ new Map());
|
|
11415
|
+
resumeQueuedInFlightRef.current.clear();
|
|
11416
|
+
}, [chatScopeKey]);
|
|
10728
11417
|
const warmupNotice = composerNoticeForWarmup(workspaceWarmupStatus);
|
|
10729
11418
|
const runtimeDependenciesNotice = composerNoticeForRuntimeDependencies(workspaceWarmupStatus);
|
|
10730
11419
|
const workspaceWarmupBlocked = Boolean(warmupNotice);
|
|
10731
|
-
const activeBlockers =
|
|
11420
|
+
const activeBlockers = useMemo17(
|
|
10732
11421
|
// A missing active session id means a single/sessionless chat host. In that
|
|
10733
11422
|
// mode, keep scoped blockers visible instead of hiding the only attention UI.
|
|
10734
11423
|
// Multi-session hosts should pass a session id so unrelated blockers filter out.
|
|
@@ -10738,7 +11427,7 @@ function PiChatPanel({
|
|
|
10738
11427
|
const canonicalMessages = selectedChatState ? selectMessagesForRender(selectedChatState) : [];
|
|
10739
11428
|
const queuePreview = selectedChatState ? selectQueuePreview(selectedChatState) : [];
|
|
10740
11429
|
const messages = canonicalMessages;
|
|
10741
|
-
const userHistory =
|
|
11430
|
+
const userHistory = useMemo17(() => selectComposerHistoryFromCanonicalUsers(canonicalMessages), [canonicalMessages]);
|
|
10742
11431
|
const awaitingHydration = Boolean(hydrateMessages && selectedChatState && !selectedChatState.hydrated);
|
|
10743
11432
|
const emptyStateHydrating = statusForState(selectedChatState, sessionsLoading || chatStatePending || selectedSessionPending) === "hydrating" || awaitingHydration;
|
|
10744
11433
|
const emptyHero = emptyPlacement === "hero" && messages.length === 0 && queuePreview.length === 0 && !emptyStateHydrating;
|
|
@@ -10747,7 +11436,7 @@ function PiChatPanel({
|
|
|
10747
11436
|
const primaryComposerBlocker = activeBlockers[0];
|
|
10748
11437
|
const composerBlockerLabel = workspaceWarmupBlocked ? warmupNotice?.title ?? "Preparing workspace..." : primaryComposerBlocker?.label ?? primaryComposerBlocker?.reason ?? "Complete the pending workspace action to continue.";
|
|
10749
11438
|
const composerStatusNotice = warmupNotice ?? runtimeDependenciesNotice;
|
|
10750
|
-
const runtimeNotices =
|
|
11439
|
+
const runtimeNotices = useMemo17(() => {
|
|
10751
11440
|
const fromState = selectedChatState ? selectRuntimeNotices(selectedChatState) : [];
|
|
10752
11441
|
const sessionNotice = sessionsError ? [{ id: "session-navigation-error", level: "error", text: sessionsError.message, dismissible: true }] : [];
|
|
10753
11442
|
const largeStateNotice = debug && debugState?.largeStateWarning ? [{
|
|
@@ -10756,20 +11445,29 @@ function PiChatPanel({
|
|
|
10756
11445
|
text: `Large chat state: ${debugState.largeStateWarning.messageCount} messages, approximately ${debugState.largeStateWarning.approxBytes} bytes.`,
|
|
10757
11446
|
dismissible: true
|
|
10758
11447
|
}] : [];
|
|
10759
|
-
const combined = [...fromState, ...sessionNotice, ...largeStateNotice, ...localNotices].filter((notice) => !dismissedNoticeIds.has(notice.id));
|
|
11448
|
+
const combined = [...fromState, ...sessionNotice, ...largeStateNotice, ...resumeQueuedError ? [resumeQueuedError] : [], ...localNotices].filter((notice) => !dismissedNoticeIds.has(notice.id));
|
|
10760
11449
|
return filterCompetingNoiseNotices(combined, messages.length === 0);
|
|
10761
|
-
}, [debug, debugState?.largeStateWarning, dismissedNoticeIds, localNotices, messages.length, selectedChatState, sessionsError]);
|
|
10762
|
-
const addLocalNotice =
|
|
11450
|
+
}, [debug, debugState?.largeStateWarning, dismissedNoticeIds, localNotices, messages.length, resumeQueuedError, selectedChatState, sessionsError]);
|
|
11451
|
+
const addLocalNotice = useCallback19((notice) => {
|
|
10763
11452
|
setLocalNotices((previous) => {
|
|
10764
11453
|
const next = previous.filter((candidate) => candidate.id !== notice.id);
|
|
10765
11454
|
return [...next, notice];
|
|
10766
11455
|
});
|
|
10767
11456
|
}, []);
|
|
10768
|
-
const clearLocalNotice =
|
|
11457
|
+
const clearLocalNotice = useCallback19((id) => {
|
|
10769
11458
|
setDismissedNoticeIds((previous) => new Set(previous).add(id));
|
|
10770
11459
|
setLocalNotices((previous) => previous.filter((notice) => notice.id !== id));
|
|
11460
|
+
if (id.startsWith(RESUME_QUEUED_ERROR_PREFIX)) {
|
|
11461
|
+
const sessionId2 = id.slice(RESUME_QUEUED_ERROR_PREFIX.length);
|
|
11462
|
+
setResumeQueuedErrorsBySessionId((previous) => {
|
|
11463
|
+
if (!previous.has(sessionId2)) return previous;
|
|
11464
|
+
const next = new Map(previous);
|
|
11465
|
+
next.delete(sessionId2);
|
|
11466
|
+
return next;
|
|
11467
|
+
});
|
|
11468
|
+
}
|
|
10771
11469
|
}, []);
|
|
10772
|
-
const dropLocalNotice =
|
|
11470
|
+
const dropLocalNotice = useCallback19((id) => {
|
|
10773
11471
|
setDismissedNoticeIds((previous) => {
|
|
10774
11472
|
if (!previous.has(id)) return previous;
|
|
10775
11473
|
const next = new Set(previous);
|
|
@@ -10778,13 +11476,13 @@ function PiChatPanel({
|
|
|
10778
11476
|
});
|
|
10779
11477
|
setLocalNotices((previous) => previous.filter((notice) => notice.id !== id));
|
|
10780
11478
|
}, []);
|
|
10781
|
-
const createSession =
|
|
11479
|
+
const createSession = useCallback19(() => {
|
|
10782
11480
|
if (externalSessionId) return;
|
|
10783
11481
|
void sessions.create().catch((error) => {
|
|
10784
11482
|
addLocalNotice({ id: "session-create-error", level: "error", text: errorMessage2(error, "Could not create a chat session."), dismissible: true });
|
|
10785
11483
|
});
|
|
10786
11484
|
}, [addLocalNotice, externalSessionId, sessions.create]);
|
|
10787
|
-
|
|
11485
|
+
useEffect23(() => {
|
|
10788
11486
|
if (externalSessionId || sessionsLoading || sessionsError || activeSessionId || sessionList.length > 0) return;
|
|
10789
11487
|
if (resetInProgressRef.current) return;
|
|
10790
11488
|
if (autoCreateInFlightRef.current) return;
|
|
@@ -10794,18 +11492,18 @@ function PiChatPanel({
|
|
|
10794
11492
|
addLocalNotice({ id: "session-auto-create-error", level: "error", text: errorMessage2(error, "Could not create a chat session."), dismissible: true });
|
|
10795
11493
|
});
|
|
10796
11494
|
}, [activeSessionId, addLocalNotice, externalSessionId, sessionList.length, sessions.create, sessions.resumeSessionId, sessionsError, sessionsLoading]);
|
|
10797
|
-
|
|
11495
|
+
useEffect23(() => {
|
|
10798
11496
|
if (externalSessionId || sessionsError || activeSessionId || sessionList.length > 0) {
|
|
10799
11497
|
autoCreateInFlightRef.current = false;
|
|
10800
11498
|
}
|
|
10801
11499
|
}, [activeSessionId, externalSessionId, sessionList.length, sessionsError]);
|
|
10802
|
-
const deleteSession =
|
|
11500
|
+
const deleteSession = useCallback19((sessionId2) => {
|
|
10803
11501
|
if (externalSessionId) return;
|
|
10804
11502
|
void sessions.delete(sessionId2).catch((error) => {
|
|
10805
11503
|
addLocalNotice({ id: `session-delete-error:${sessionId2}`, level: "error", text: errorMessage2(error, "Could not delete the chat session."), dismissible: true });
|
|
10806
11504
|
});
|
|
10807
11505
|
}, [addLocalNotice, externalSessionId, sessions.delete]);
|
|
10808
|
-
const resetSession =
|
|
11506
|
+
const resetSession = useCallback19(() => {
|
|
10809
11507
|
const currentSessionId = activeSessionId;
|
|
10810
11508
|
if (externalSessionId) {
|
|
10811
11509
|
void onSessionReset?.();
|
|
@@ -10823,11 +11521,11 @@ function PiChatPanel({
|
|
|
10823
11521
|
resetInProgressRef.current = false;
|
|
10824
11522
|
});
|
|
10825
11523
|
}, [activeSessionId, addLocalNotice, externalSessionId, onSessionReset, sessions.create, sessions.delete]);
|
|
10826
|
-
const reloadAgentPlugins =
|
|
11524
|
+
const reloadAgentPlugins = useCallback19(async () => {
|
|
10827
11525
|
if (!onReloadAgentPlugins) throw new Error("Agent plugin reload is not configured.");
|
|
10828
11526
|
return normalizeAgentPluginReloadResult(await onReloadAgentPlugins());
|
|
10829
11527
|
}, [onReloadAgentPlugins]);
|
|
10830
|
-
const runPluginUpdate =
|
|
11528
|
+
const runPluginUpdate = useCallback19(async () => {
|
|
10831
11529
|
setPluginUpdateState({ kind: "running" });
|
|
10832
11530
|
try {
|
|
10833
11531
|
const result = await reloadAgentPlugins();
|
|
@@ -10840,9 +11538,9 @@ function PiChatPanel({
|
|
|
10840
11538
|
return `Extension update failed: ${message}`;
|
|
10841
11539
|
}
|
|
10842
11540
|
}, [reloadAgentPlugins]);
|
|
10843
|
-
const dismissPluginUpdate =
|
|
10844
|
-
const dismissCommandNotify =
|
|
10845
|
-
|
|
11541
|
+
const dismissPluginUpdate = useCallback19(() => setPluginUpdateState(null), []);
|
|
11542
|
+
const dismissCommandNotify = useCallback19(() => setCommandNotifyState(null), []);
|
|
11543
|
+
useEffect23(() => {
|
|
10846
11544
|
if (typeof window === "undefined") return;
|
|
10847
11545
|
const onCommandNotify = (event) => {
|
|
10848
11546
|
const payload = event.detail;
|
|
@@ -10859,7 +11557,7 @@ function PiChatPanel({
|
|
|
10859
11557
|
window.addEventListener(WORKSPACE_COMMAND_NOTIFY_EVENT, onCommandNotify);
|
|
10860
11558
|
return () => window.removeEventListener(WORKSPACE_COMMAND_NOTIFY_EVENT, onCommandNotify);
|
|
10861
11559
|
}, []);
|
|
10862
|
-
|
|
11560
|
+
useEffect23(() => {
|
|
10863
11561
|
if (!hotReloadEnabled || typeof window === "undefined") return;
|
|
10864
11562
|
const onBrowserPluginReload = (event) => {
|
|
10865
11563
|
const parsed = parseBrowserPluginReloadDetail(event.detail);
|
|
@@ -10897,7 +11595,7 @@ function PiChatPanel({
|
|
|
10897
11595
|
textareaRef,
|
|
10898
11596
|
disabled: mentionState !== null || slashQuery !== null || modelPickerOpen || thinkingPickerOpen
|
|
10899
11597
|
});
|
|
10900
|
-
const setComposerDraft =
|
|
11598
|
+
const setComposerDraft = useCallback19((next, focus = true) => {
|
|
10901
11599
|
draftRef.current = next;
|
|
10902
11600
|
setDraft(next);
|
|
10903
11601
|
if (textareaRef.current) {
|
|
@@ -10905,11 +11603,11 @@ function PiChatPanel({
|
|
|
10905
11603
|
if (focus) textareaRef.current.focus();
|
|
10906
11604
|
}
|
|
10907
11605
|
}, []);
|
|
10908
|
-
const warnComposer =
|
|
11606
|
+
const warnComposer = useCallback19((message) => {
|
|
10909
11607
|
onComposerWarning?.(message);
|
|
10910
11608
|
addLocalNotice({ id: `composer-warning:${Date.now()}`, level: "warning", text: message, dismissible: true });
|
|
10911
11609
|
}, [addLocalNotice, onComposerWarning]);
|
|
10912
|
-
const openModelPicker =
|
|
11610
|
+
const openModelPicker = useCallback19(() => {
|
|
10913
11611
|
if (isPiBusyStatus(statusRef.current)) {
|
|
10914
11612
|
warnComposer("Model picker is unavailable while the agent is running.");
|
|
10915
11613
|
return false;
|
|
@@ -10922,7 +11620,7 @@ function PiChatPanel({
|
|
|
10922
11620
|
setModelPickerOpen(true);
|
|
10923
11621
|
return true;
|
|
10924
11622
|
}, [model, warnComposer]);
|
|
10925
|
-
const openThinkingPicker =
|
|
11623
|
+
const openThinkingPicker = useCallback19(() => {
|
|
10926
11624
|
if (isPiBusyStatus(statusRef.current)) {
|
|
10927
11625
|
warnComposer("Thinking picker is unavailable while the agent is running.");
|
|
10928
11626
|
return false;
|
|
@@ -10935,21 +11633,21 @@ function PiChatPanel({
|
|
|
10935
11633
|
setThinkingPickerOpen(true);
|
|
10936
11634
|
return true;
|
|
10937
11635
|
}, [thinkingControl, thinkingLevel, warnComposer]);
|
|
10938
|
-
const selectComposerModel =
|
|
11636
|
+
const selectComposerModel = useCallback19((query) => {
|
|
10939
11637
|
if (model !== void 0) return "Model selection is controlled by the host.";
|
|
10940
11638
|
const match = resolveModelSlashSelection(query, modelOptions);
|
|
10941
11639
|
if (!match) return `No model matched "${query}".`;
|
|
10942
11640
|
modelDiscovery.setModel(match);
|
|
10943
11641
|
return `Model set to ${match.label ?? match.id}.`;
|
|
10944
11642
|
}, [model, modelDiscovery, modelOptions]);
|
|
10945
|
-
const selectComposerThinking =
|
|
11643
|
+
const selectComposerThinking = useCallback19((query) => {
|
|
10946
11644
|
if (!thinkingControl || thinkingLevel !== void 0) return "Thinking level is controlled by the host.";
|
|
10947
11645
|
const match = resolveThinkingSlashSelection(query);
|
|
10948
11646
|
if (!match) return `No thinking level matched "${query}".`;
|
|
10949
11647
|
setStoredThinkingLevel(match);
|
|
10950
11648
|
return `Thinking set to ${thinkingLabel(match)}.`;
|
|
10951
11649
|
}, [thinkingControl, thinkingLevel]);
|
|
10952
|
-
const selectSlashCommand =
|
|
11650
|
+
const selectSlashCommand = useCallback19((name) => {
|
|
10953
11651
|
if (name === "model") {
|
|
10954
11652
|
dismissSlash();
|
|
10955
11653
|
if (openModelPicker()) setComposerDraft("");
|
|
@@ -10962,7 +11660,7 @@ function PiChatPanel({
|
|
|
10962
11660
|
}
|
|
10963
11661
|
insertSlashCommand(name);
|
|
10964
11662
|
}, [dismissSlash, insertSlashCommand, openModelPicker, openThinkingPicker, setComposerDraft]);
|
|
10965
|
-
const policy =
|
|
11663
|
+
const policy = useMemo17(() => {
|
|
10966
11664
|
if (!selectedPiSession || !activeChatSessionId || !serverModelSelectionReady) return void 0;
|
|
10967
11665
|
const policySession = {
|
|
10968
11666
|
getState: () => {
|
|
@@ -11007,13 +11705,29 @@ function PiChatPanel({
|
|
|
11007
11705
|
getDraft: () => draftRef.current,
|
|
11008
11706
|
onDraftChange: setComposerDraft,
|
|
11009
11707
|
allowPromptDuringInitialHydration,
|
|
11708
|
+
isActiveSession: isPolicySessionActive,
|
|
11709
|
+
submissionCoordinator: submissionCoordinatorRef.current,
|
|
11710
|
+
submissionIdentity: activeChatIdentity,
|
|
11711
|
+
onQueueMutationPending: setQueueMutationPending,
|
|
11010
11712
|
onPromptSubmitStarted: () => {
|
|
11011
11713
|
markLocalSubmitted(activeChatSessionId);
|
|
11012
11714
|
},
|
|
11013
|
-
onBeforeSubmit: onBeforeSubmit ? async (draft2, context) => {
|
|
11014
|
-
|
|
11015
|
-
|
|
11016
|
-
|
|
11715
|
+
onBeforeSubmit: onBeforeSubmit ? async (draft2, context) => await onBeforeSubmit(draft2, {
|
|
11716
|
+
...context,
|
|
11717
|
+
sessionId: activeChatSessionId,
|
|
11718
|
+
source: context.source ?? "composer"
|
|
11719
|
+
}) : void 0,
|
|
11720
|
+
onTransformPrompt: async (text) => await spillLargePrompt(text, {
|
|
11721
|
+
sessionId: activeChatSessionId,
|
|
11722
|
+
destinationIdentity: `${apiBaseUrl ?? ""}\0${workspaceId ?? ""}\0${headersContentKey(requestHeaders)}`,
|
|
11723
|
+
cache: largePromptSpillCacheRef.current,
|
|
11724
|
+
enabled: spillLargePrompts,
|
|
11725
|
+
thresholdChars: largePromptThresholdChars,
|
|
11726
|
+
apiBaseUrl,
|
|
11727
|
+
workspaceRequestId: requestHeaderValue(requestHeaders, "x-boring-workspace-id"),
|
|
11728
|
+
requestHeaders,
|
|
11729
|
+
fetch: fetch2
|
|
11730
|
+
}),
|
|
11017
11731
|
onCommandResult: (message) => {
|
|
11018
11732
|
onCommandResult?.(message);
|
|
11019
11733
|
addLocalNotice({ id: `command:${Date.now()}`, level: "info", text: message, dismissible: true });
|
|
@@ -11028,8 +11742,17 @@ function PiChatPanel({
|
|
|
11028
11742
|
onMentionedFilesConsumed?.();
|
|
11029
11743
|
}
|
|
11030
11744
|
});
|
|
11031
|
-
}, [activeChatSessionId, addLocalNotice, allowPromptDuringInitialHydration, clearMentionedFiles, composerBlocked, composerBlockerLabel, effectiveMentionedFiles, markLocalSubmitted, onBeforeSubmit, onCommandResult, onComposerWarning, onMentionedFilesConsumed, onPromptSubmitStarted, openModelPicker, openThinkingPicker, registry, reloadAgentPlugins, resetSession, runPluginUpdate, selectComposerModel, selectComposerThinking, selectedModel, selectedPiSession, selectedThinking, serverModelSelectionReady, setComposerDraft, submitThinkingControl, suppressPreSubmitCancelledWarning]);
|
|
11032
|
-
const
|
|
11745
|
+
}, [activeChatIdentity, activeChatSessionId, addLocalNotice, allowPromptDuringInitialHydration, apiBaseUrl, clearMentionedFiles, composerBlocked, composerBlockerLabel, effectiveMentionedFiles, fetch2, isPolicySessionActive, largePromptThresholdChars, markLocalSubmitted, onBeforeSubmit, onCommandResult, onComposerWarning, onMentionedFilesConsumed, onPromptSubmitStarted, openModelPicker, openThinkingPicker, registry, reloadAgentPlugins, requestHeaders, resetSession, runPluginUpdate, selectComposerModel, selectComposerThinking, selectedModel, selectedPiSession, selectedThinking, serverModelSelectionReady, setComposerDraft, spillLargePrompts, submitThinkingControl, suppressPreSubmitCancelledWarning, workspaceId]);
|
|
11746
|
+
const surfaceHandledSubmit = useCallback19((message) => {
|
|
11747
|
+
if (!message) return;
|
|
11748
|
+
addLocalNotice({
|
|
11749
|
+
id: `handled-submit:${Date.now()}`,
|
|
11750
|
+
level: "info",
|
|
11751
|
+
text: message,
|
|
11752
|
+
dismissible: true
|
|
11753
|
+
});
|
|
11754
|
+
}, [addLocalNotice]);
|
|
11755
|
+
const surfaceRunRejected = useCallback19((error) => {
|
|
11033
11756
|
const errorCode = piChatErrorCode(error);
|
|
11034
11757
|
dropLocalNotice(RUN_REJECTED_NOTICE_ID);
|
|
11035
11758
|
addLocalNotice({
|
|
@@ -11040,7 +11763,7 @@ function PiChatPanel({
|
|
|
11040
11763
|
...errorCode ? { errorCode } : {}
|
|
11041
11764
|
});
|
|
11042
11765
|
}, [addLocalNotice, dropLocalNotice]);
|
|
11043
|
-
const sendComposerMessage =
|
|
11766
|
+
const sendComposerMessage = useCallback19(async ({ text, files, source = "composer", preserveExistingDraft = false }) => {
|
|
11044
11767
|
if (!policy) {
|
|
11045
11768
|
addLocalNotice({ id: "composer-no-session", level: "warning", text: "Create or select a chat session before sending.", dismissible: true });
|
|
11046
11769
|
return false;
|
|
@@ -11060,6 +11783,7 @@ function PiChatPanel({
|
|
|
11060
11783
|
if (result.type === "prompt" || result.type === "followup") {
|
|
11061
11784
|
dropLocalNotice(RUN_REJECTED_NOTICE_ID);
|
|
11062
11785
|
}
|
|
11786
|
+
if (result.type === "handled") surfaceHandledSubmit(result.message);
|
|
11063
11787
|
if (result.type === "prompt" && activeChatSessionId) {
|
|
11064
11788
|
onPromptSubmitStarted?.({ sessionId: activeChatSessionId, clientNonce: result.clientNonce });
|
|
11065
11789
|
if (shouldHoldLocalSubmitted(selectedPiSession, result.cursor)) markLocalSubmitted(activeChatSessionId);
|
|
@@ -11067,17 +11791,18 @@ function PiChatPanel({
|
|
|
11067
11791
|
}
|
|
11068
11792
|
return void 0;
|
|
11069
11793
|
} catch (error) {
|
|
11794
|
+
if (!isPolicySessionActive()) return void 0;
|
|
11070
11795
|
clearLocalSubmitted(activeChatSessionId);
|
|
11071
11796
|
restoreSubmittedDraft();
|
|
11072
11797
|
surfaceRunRejected(error);
|
|
11073
11798
|
return false;
|
|
11074
11799
|
}
|
|
11075
|
-
}, [activeChatSessionId, clearLocalSubmitted, dropLocalNotice, markLocalSubmitted, onPromptSubmitStarted, policy, selectedPiSession, setComposerDraft, surfaceRunRejected]);
|
|
11076
|
-
const availableAssistantSlashCommands =
|
|
11800
|
+
}, [activeChatSessionId, clearLocalSubmitted, dropLocalNotice, isPolicySessionActive, markLocalSubmitted, onPromptSubmitStarted, policy, selectedPiSession, setComposerDraft, surfaceHandledSubmit, surfaceRunRejected]);
|
|
11801
|
+
const availableAssistantSlashCommands = useMemo17(
|
|
11077
11802
|
() => policy ? actionableSlashCommands : actionableSlashCommands.filter((command) => command.clickBehavior === "insert"),
|
|
11078
11803
|
[actionableSlashCommands, policy]
|
|
11079
11804
|
);
|
|
11080
|
-
const assistantMentionCatalog =
|
|
11805
|
+
const assistantMentionCatalog = useMemo17(() => {
|
|
11081
11806
|
const skills = /* @__PURE__ */ new Map();
|
|
11082
11807
|
for (const command of allCommands) {
|
|
11083
11808
|
if (command.source !== "skill" && command.kind !== "skill") continue;
|
|
@@ -11093,12 +11818,12 @@ function PiChatPanel({
|
|
|
11093
11818
|
files: true
|
|
11094
11819
|
};
|
|
11095
11820
|
}, [allCommands, availableAssistantSlashCommands]);
|
|
11096
|
-
const insertMentionDraft =
|
|
11821
|
+
const insertMentionDraft = useCallback19((invocation) => {
|
|
11097
11822
|
const currentDraft = draftRef.current;
|
|
11098
11823
|
const separator = currentDraft && !/\s$/.test(invocation) ? "\n" : "";
|
|
11099
11824
|
setComposerDraft(`${invocation}${separator}${currentDraft}`, true);
|
|
11100
11825
|
}, [setComposerDraft]);
|
|
11101
|
-
const activateAssistantMention =
|
|
11826
|
+
const activateAssistantMention = useCallback19((mention) => {
|
|
11102
11827
|
const command = registry.get(mention.kind === "skill" ? mention.commandName : mention.name);
|
|
11103
11828
|
if (mention.kind === "skill") {
|
|
11104
11829
|
if (command?.source !== "skill" && command?.kind !== "skill") return;
|
|
@@ -11120,7 +11845,7 @@ function PiChatPanel({
|
|
|
11120
11845
|
preserveExistingDraft: true
|
|
11121
11846
|
});
|
|
11122
11847
|
}, [insertMentionDraft, policy, registry, sendComposerMessage]);
|
|
11123
|
-
const editQueued =
|
|
11848
|
+
const editQueued = useCallback19(() => {
|
|
11124
11849
|
if (!policy) return;
|
|
11125
11850
|
void policy.editQueued().then((result) => {
|
|
11126
11851
|
if (result.type === "clear-failed") {
|
|
@@ -11128,25 +11853,65 @@ function PiChatPanel({
|
|
|
11128
11853
|
}
|
|
11129
11854
|
});
|
|
11130
11855
|
}, [addLocalNotice, policy]);
|
|
11131
|
-
const
|
|
11856
|
+
const removeQueued = useCallback19(() => {
|
|
11857
|
+
if (!policy) return;
|
|
11858
|
+
void policy.removeAllQueued().then((result) => {
|
|
11859
|
+
if (!result.ok) {
|
|
11860
|
+
addLocalNotice({ id: "remove-queued", level: "warning", text: result.message, dismissible: true });
|
|
11861
|
+
}
|
|
11862
|
+
});
|
|
11863
|
+
}, [addLocalNotice, policy]);
|
|
11864
|
+
const stop = useCallback19(() => {
|
|
11132
11865
|
onComposerStop?.();
|
|
11133
11866
|
clearLocalSubmitted(activeChatSessionId);
|
|
11134
|
-
void policy?.
|
|
11867
|
+
void policy?.interrupt({ queueAction: "hold" }).catch((error) => {
|
|
11135
11868
|
addLocalNotice({ id: "stop-error", level: "error", text: errorMessage2(error, "Could not stop the chat session."), dismissible: true });
|
|
11136
11869
|
});
|
|
11137
11870
|
}, [activeChatSessionId, addLocalNotice, clearLocalSubmitted, onComposerStop, policy]);
|
|
11138
|
-
const interrupt =
|
|
11871
|
+
const interrupt = useCallback19(() => {
|
|
11139
11872
|
void policy?.interrupt().catch((error) => {
|
|
11140
11873
|
addLocalNotice({ id: "interrupt-error", level: "error", text: errorMessage2(error, "Could not interrupt the chat session."), dismissible: true });
|
|
11141
11874
|
});
|
|
11142
11875
|
}, [addLocalNotice, policy]);
|
|
11143
|
-
|
|
11876
|
+
const resumeQueued = useCallback19(() => {
|
|
11877
|
+
const sessionId2 = activeChatSessionId;
|
|
11878
|
+
if (!policy || !sessionId2 || resumeQueuedInFlightRef.current.has(sessionId2)) return;
|
|
11879
|
+
const errorNoticeId = `${RESUME_QUEUED_ERROR_PREFIX}${sessionId2}`;
|
|
11880
|
+
dropLocalNotice(errorNoticeId);
|
|
11881
|
+
setResumeQueuedErrorsBySessionId((previous) => {
|
|
11882
|
+
if (!previous.has(sessionId2)) return previous;
|
|
11883
|
+
const next = new Map(previous);
|
|
11884
|
+
next.delete(sessionId2);
|
|
11885
|
+
return next;
|
|
11886
|
+
});
|
|
11887
|
+
setResumeQueuedPendingSessionIds((previous) => new Set(previous).add(sessionId2));
|
|
11888
|
+
const run = policy.resumeQueued();
|
|
11889
|
+
resumeQueuedInFlightRef.current.set(sessionId2, run);
|
|
11890
|
+
void run.catch((error) => {
|
|
11891
|
+
setResumeQueuedErrorsBySessionId((previous) => new Map(previous).set(sessionId2, {
|
|
11892
|
+
id: errorNoticeId,
|
|
11893
|
+
level: "error",
|
|
11894
|
+
text: errorMessage2(error, "Could not resume queued follow-ups."),
|
|
11895
|
+
dismissible: true
|
|
11896
|
+
}));
|
|
11897
|
+
}).finally(() => {
|
|
11898
|
+
if (resumeQueuedInFlightRef.current.get(sessionId2) !== run) return;
|
|
11899
|
+
resumeQueuedInFlightRef.current.delete(sessionId2);
|
|
11900
|
+
setResumeQueuedPendingSessionIds((previous) => {
|
|
11901
|
+
if (!previous.has(sessionId2)) return previous;
|
|
11902
|
+
const next = new Set(previous);
|
|
11903
|
+
next.delete(sessionId2);
|
|
11904
|
+
return next;
|
|
11905
|
+
});
|
|
11906
|
+
});
|
|
11907
|
+
}, [activeChatSessionId, dropLocalNotice, policy]);
|
|
11908
|
+
useEffect23(() => {
|
|
11144
11909
|
setPluginUpdateState(null);
|
|
11145
11910
|
setCommandNotifyState(null);
|
|
11146
11911
|
setLocalNotices([]);
|
|
11147
11912
|
setDismissedNoticeIds(/* @__PURE__ */ new Set());
|
|
11148
11913
|
}, [activeSessionId]);
|
|
11149
|
-
|
|
11914
|
+
useEffect23(() => {
|
|
11150
11915
|
const currentSessionId = activeSessionId ?? "__none__";
|
|
11151
11916
|
if (initialDraftGuard.current.shouldRestore(currentSessionId, initialDraft) && initialDraft !== void 0) {
|
|
11152
11917
|
setComposerDraft(initialDraft, initialDraft.length > 0);
|
|
@@ -11155,7 +11920,7 @@ function PiChatPanel({
|
|
|
11155
11920
|
}, [activeSessionId, initialDraft, onDraftRestored, setComposerDraft]);
|
|
11156
11921
|
const remoteStatus = selectedChatState?.status ?? (sessionsLoading || chatStatePending || selectedSessionPending ? "hydrating" : "idle");
|
|
11157
11922
|
const status = localSubmittedSessionId === activeSessionId && remoteStatus === "idle" ? "submitted" : remoteStatus;
|
|
11158
|
-
|
|
11923
|
+
useEffect23(() => {
|
|
11159
11924
|
if (!localSubmittedSessionId) return;
|
|
11160
11925
|
if (localSubmittedSessionId !== activeSessionId) {
|
|
11161
11926
|
clearLocalSubmitted();
|
|
@@ -11163,7 +11928,7 @@ function PiChatPanel({
|
|
|
11163
11928
|
}
|
|
11164
11929
|
if (remoteStatus !== "idle") clearLocalSubmitted(localSubmittedSessionId);
|
|
11165
11930
|
}, [activeSessionId, clearLocalSubmitted, localSubmittedSessionId, remoteStatus]);
|
|
11166
|
-
|
|
11931
|
+
useEffect23(() => {
|
|
11167
11932
|
const previous = prevStatusRef.current;
|
|
11168
11933
|
statusRef.current = status;
|
|
11169
11934
|
prevStatusRef.current = status;
|
|
@@ -11173,7 +11938,7 @@ function PiChatPanel({
|
|
|
11173
11938
|
if (!isPiBusyStatus(previous) && previous !== "submitted") return;
|
|
11174
11939
|
settlePendingAutoSubmit();
|
|
11175
11940
|
}, [settlePendingAutoSubmit, status]);
|
|
11176
|
-
|
|
11941
|
+
useEffect23(() => {
|
|
11177
11942
|
if (!autoSubmitInitialDraft || !policy || !activeSessionId || composerBlocked) return;
|
|
11178
11943
|
if (!initialDraftGuard.current.claimAutoSubmit(activeSessionId, initialDraft)) return;
|
|
11179
11944
|
pendingAutoSubmitSettleRef.current = activeSessionId;
|
|
@@ -11192,9 +11957,14 @@ function PiChatPanel({
|
|
|
11192
11957
|
}
|
|
11193
11958
|
return;
|
|
11194
11959
|
}
|
|
11960
|
+
if (result.type === "stale") {
|
|
11961
|
+
settlePendingAutoSubmit(activeSessionId);
|
|
11962
|
+
return;
|
|
11963
|
+
}
|
|
11195
11964
|
if (result.type === "prompt" || result.type === "followup") {
|
|
11196
11965
|
dropLocalNotice(RUN_REJECTED_NOTICE_ID);
|
|
11197
11966
|
}
|
|
11967
|
+
if (result.type === "handled") surfaceHandledSubmit(result.message);
|
|
11198
11968
|
if (result.type === "prompt") {
|
|
11199
11969
|
onPromptSubmitStarted?.({ sessionId: activeSessionId, clientNonce: result.clientNonce });
|
|
11200
11970
|
if (shouldHoldLocalSubmitted(selectedPiSession, result.cursor)) markLocalSubmitted(activeSessionId);
|
|
@@ -11206,13 +11976,14 @@ function PiChatPanel({
|
|
|
11206
11976
|
settlePendingAutoSubmit(activeSessionId);
|
|
11207
11977
|
}
|
|
11208
11978
|
}).catch((error) => {
|
|
11979
|
+
if (!isPolicySessionActive()) return;
|
|
11209
11980
|
clearLocalSubmitted(activeSessionId);
|
|
11210
11981
|
restoreSubmittedDraft();
|
|
11211
11982
|
settlePendingAutoSubmit(activeSessionId);
|
|
11212
11983
|
surfaceRunRejected(error);
|
|
11213
11984
|
});
|
|
11214
|
-
}, [activeSessionId, autoSubmitInitialDraft, clearLocalSubmitted, composerBlocked, dropLocalNotice, initialDraft, markLocalSubmitted, onAutoSubmitInitialDraftAccepted, onPromptSubmitStarted, policy, selectedPiSession, setComposerDraft, settlePendingAutoSubmit, surfaceRunRejected]);
|
|
11215
|
-
|
|
11985
|
+
}, [activeSessionId, autoSubmitInitialDraft, clearLocalSubmitted, composerBlocked, dropLocalNotice, initialDraft, isPolicySessionActive, markLocalSubmitted, onAutoSubmitInitialDraftAccepted, onPromptSubmitStarted, policy, selectedPiSession, setComposerDraft, settlePendingAutoSubmit, surfaceHandledSubmit, surfaceRunRejected]);
|
|
11986
|
+
useEffect23(() => {
|
|
11216
11987
|
if (workspaceWarmupStatus?.status === "ready") {
|
|
11217
11988
|
clearLocalNotice("workspace-warmup");
|
|
11218
11989
|
}
|
|
@@ -11226,20 +11997,20 @@ function PiChatPanel({
|
|
|
11226
11997
|
const isStreaming = isPiBusyStatus(status);
|
|
11227
11998
|
const submitStatus = initialHydrationPromptAllowed ? "ready" : toPromptSubmitStatus(status);
|
|
11228
11999
|
const submitDisabled = !policy || sessionsLoading || modelSelectionBlocked || composerBlocked && !isStreaming;
|
|
11229
|
-
const mergedToolRenderers =
|
|
11230
|
-
const debugMessages =
|
|
11231
|
-
const onTextareaChange =
|
|
12000
|
+
const mergedToolRenderers = useMemo17(() => mergeShadcnToolRenderers(toolRenderers), [toolRenderers]);
|
|
12001
|
+
const debugMessages = useMemo17(() => messages.map(toDebugUiMessage), [messages]);
|
|
12002
|
+
const onTextareaChange = useCallback19((event) => {
|
|
11232
12003
|
setModelPickerOpen(false);
|
|
11233
12004
|
setThinkingPickerOpen(false);
|
|
11234
12005
|
setDraft(event.currentTarget.value);
|
|
11235
12006
|
handleComposerChange(event);
|
|
11236
12007
|
}, [handleComposerChange]);
|
|
11237
|
-
|
|
12008
|
+
useEffect23(() => {
|
|
11238
12009
|
if (!isStreaming) return;
|
|
11239
12010
|
setModelPickerOpen(false);
|
|
11240
12011
|
setThinkingPickerOpen(false);
|
|
11241
12012
|
}, [isStreaming]);
|
|
11242
|
-
|
|
12013
|
+
useEffect23(() => {
|
|
11243
12014
|
if (typeof window === "undefined" || !activeChatSessionId) return;
|
|
11244
12015
|
const emitStatus = () => window.dispatchEvent(new CustomEvent("boring:chat-session-status", {
|
|
11245
12016
|
detail: {
|
|
@@ -11253,7 +12024,7 @@ function PiChatPanel({
|
|
|
11253
12024
|
window.addEventListener("boring:chat-session-status-request", emitStatus);
|
|
11254
12025
|
return () => window.removeEventListener("boring:chat-session-status-request", emitStatus);
|
|
11255
12026
|
}, [activeChatSessionId, agentTypeId, isStreaming, workspaceId]);
|
|
11256
|
-
const onTextareaKeyDown =
|
|
12027
|
+
const onTextareaKeyDown = useCallback19((event) => {
|
|
11257
12028
|
if (event.key === "Escape" && isStreaming) {
|
|
11258
12029
|
if (event.defaultPrevented || mentionState !== null || slashQuery !== null) {
|
|
11259
12030
|
handleComposerKeyDown(event);
|
|
@@ -11265,14 +12036,14 @@ function PiChatPanel({
|
|
|
11265
12036
|
}
|
|
11266
12037
|
handleComposerKeyDown(event);
|
|
11267
12038
|
}, [handleComposerKeyDown, interrupt, isStreaming, mentionState, slashQuery]);
|
|
11268
|
-
const selectEmptySuggestion =
|
|
12039
|
+
const selectEmptySuggestion = useCallback19((suggestion) => {
|
|
11269
12040
|
const text = suggestion.prompt ?? suggestion.label;
|
|
11270
12041
|
if (!text.trim()) return;
|
|
11271
12042
|
void sendComposerMessage({ text, files: [], source: "suggestion" }).then((result) => {
|
|
11272
12043
|
if (result === false) setComposerDraft(text);
|
|
11273
12044
|
});
|
|
11274
12045
|
}, [sendComposerMessage, setComposerDraft]);
|
|
11275
|
-
const composerSurface = /* @__PURE__ */
|
|
12046
|
+
const composerSurface = /* @__PURE__ */ jsx35(
|
|
11276
12047
|
PiChatComposerSurface,
|
|
11277
12048
|
{
|
|
11278
12049
|
chrome,
|
|
@@ -11291,6 +12062,10 @@ function PiChatPanel({
|
|
|
11291
12062
|
onComposerBlockerAction,
|
|
11292
12063
|
queuePreview,
|
|
11293
12064
|
onEditQueued: editQueued,
|
|
12065
|
+
onRemoveQueued: removeQueued,
|
|
12066
|
+
queueMutationPending,
|
|
12067
|
+
onResumeQueued: resumeQueued,
|
|
12068
|
+
resumeQueuedPending,
|
|
11294
12069
|
hotReloadEnabled,
|
|
11295
12070
|
pluginUpdateState,
|
|
11296
12071
|
onDismissPluginUpdate: dismissPluginUpdate,
|
|
@@ -11339,7 +12114,7 @@ function PiChatPanel({
|
|
|
11339
12114
|
onStop: stop
|
|
11340
12115
|
}
|
|
11341
12116
|
);
|
|
11342
|
-
return /* @__PURE__ */
|
|
12117
|
+
return /* @__PURE__ */ jsx35(ArtifactOpenProvider, { onOpenArtifact, children: /* @__PURE__ */ jsxs31(
|
|
11343
12118
|
"div",
|
|
11344
12119
|
{
|
|
11345
12120
|
"data-boring-agent": "",
|
|
@@ -11357,7 +12132,7 @@ function PiChatPanel({
|
|
|
11357
12132
|
role: "region",
|
|
11358
12133
|
"aria-label": "Agent assistant",
|
|
11359
12134
|
children: [
|
|
11360
|
-
showSessionSidebar ? /* @__PURE__ */
|
|
12135
|
+
showSessionSidebar ? /* @__PURE__ */ jsx35("aside", { "data-boring-agent-part": "pi-chat-session-sidebar", className: "min-h-0 w-64 shrink-0 border-r border-border/60", children: /* @__PURE__ */ jsx35(
|
|
11361
12136
|
SessionList,
|
|
11362
12137
|
{
|
|
11363
12138
|
sessions: sessionList,
|
|
@@ -11371,7 +12146,7 @@ function PiChatPanel({
|
|
|
11371
12146
|
loadingMore: sessions.loadingMore
|
|
11372
12147
|
}
|
|
11373
12148
|
) }) : null,
|
|
11374
|
-
/* @__PURE__ */
|
|
12149
|
+
/* @__PURE__ */ jsx35("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: /* @__PURE__ */ jsxs31(
|
|
11375
12150
|
"div",
|
|
11376
12151
|
{
|
|
11377
12152
|
className: cn(
|
|
@@ -11380,7 +12155,7 @@ function PiChatPanel({
|
|
|
11380
12155
|
chrome && "mx-3 my-3 rounded-xl bg-[color:var(--surface-chat)] shadow-[0_1px_0_oklch(0_0_0/0.02),0_1px_2px_-1px_oklch(0_0_0/0.04),inset_0_0_0_1px_oklch(from_var(--border)_l_c_h/0.6)]"
|
|
11381
12156
|
),
|
|
11382
12157
|
children: [
|
|
11383
|
-
/* @__PURE__ */
|
|
12158
|
+
/* @__PURE__ */ jsx35(
|
|
11384
12159
|
PiConversationSurface,
|
|
11385
12160
|
{
|
|
11386
12161
|
chrome,
|
|
@@ -11406,13 +12181,13 @@ function PiChatPanel({
|
|
|
11406
12181
|
}
|
|
11407
12182
|
),
|
|
11408
12183
|
composerSurface,
|
|
11409
|
-
emptyHero ? /* @__PURE__ */
|
|
12184
|
+
emptyHero ? /* @__PURE__ */ jsxs31(
|
|
11410
12185
|
"div",
|
|
11411
12186
|
{
|
|
11412
12187
|
"data-boring-agent-part": "empty-hero-suggestions",
|
|
11413
12188
|
className: "@container mx-auto w-full max-w-[640px] px-2 pb-4",
|
|
11414
12189
|
children: [
|
|
11415
|
-
/* @__PURE__ */
|
|
12190
|
+
/* @__PURE__ */ jsx35(ChatSuggestionGrid, { suggestions, onSelect: selectEmptySuggestion, className: "mt-4" }),
|
|
11416
12191
|
emptyState?.footer
|
|
11417
12192
|
]
|
|
11418
12193
|
}
|
|
@@ -11420,7 +12195,7 @@ function PiChatPanel({
|
|
|
11420
12195
|
]
|
|
11421
12196
|
}
|
|
11422
12197
|
) }),
|
|
11423
|
-
debug ? /* @__PURE__ */
|
|
12198
|
+
debug ? /* @__PURE__ */ jsx35(Suspense, { fallback: null, children: /* @__PURE__ */ jsx35("div", { "aria-label": "Chat debug metadata", className: "contents", role: "region", children: /* @__PURE__ */ jsx35(
|
|
11424
12199
|
DebugDrawer2,
|
|
11425
12200
|
{
|
|
11426
12201
|
agentTypeId,
|
|
@@ -11441,17 +12216,18 @@ function PiChatPanel({
|
|
|
11441
12216
|
}
|
|
11442
12217
|
|
|
11443
12218
|
// src/front/chat/useAddressedAgentSelection.ts
|
|
11444
|
-
import { useCallback as
|
|
12219
|
+
import { useCallback as useCallback20, useEffect as useEffect24, useMemo as useMemo18, useState as useState23 } from "react";
|
|
11445
12220
|
var inFlightDiscoveries = /* @__PURE__ */ new WeakMap();
|
|
11446
12221
|
function useAddressedAgentSelection({
|
|
11447
12222
|
apiBaseUrl,
|
|
11448
12223
|
requestHeaders,
|
|
11449
12224
|
storageScope,
|
|
12225
|
+
preferredAgentTypeId,
|
|
11450
12226
|
fetch: fetch2,
|
|
11451
12227
|
enabled = false
|
|
11452
12228
|
} = {}) {
|
|
11453
12229
|
const normalizedBaseUrl = apiBaseUrl?.replace(/\/$/, "") ?? "";
|
|
11454
|
-
const headersKey =
|
|
12230
|
+
const headersKey = useMemo18(
|
|
11455
12231
|
() => JSON.stringify({
|
|
11456
12232
|
storageScope: storageScope ?? "",
|
|
11457
12233
|
headers: Object.entries(requestHeaders ?? {}).sort(([a], [b]) => a.localeCompare(b))
|
|
@@ -11461,14 +12237,14 @@ function useAddressedAgentSelection({
|
|
|
11461
12237
|
const discoveryKey = `${normalizedBaseUrl}
|
|
11462
12238
|
${headersKey}`;
|
|
11463
12239
|
const fetchImpl = fetch2 ?? globalThis.fetch;
|
|
11464
|
-
const [state, setState] =
|
|
12240
|
+
const [state, setState] = useState23(() => ({
|
|
11465
12241
|
discoveryKey: enabled ? "" : discoveryKey,
|
|
11466
12242
|
agents: [],
|
|
11467
12243
|
selectedAgentTypeId: void 0,
|
|
11468
12244
|
loading: enabled,
|
|
11469
12245
|
error: void 0
|
|
11470
12246
|
}));
|
|
11471
|
-
|
|
12247
|
+
useEffect24(() => {
|
|
11472
12248
|
if (!enabled) {
|
|
11473
12249
|
setState({
|
|
11474
12250
|
discoveryKey,
|
|
@@ -11494,7 +12270,7 @@ ${headersKey}`;
|
|
|
11494
12270
|
setState((previous) => ({
|
|
11495
12271
|
discoveryKey,
|
|
11496
12272
|
agents: agents2,
|
|
11497
|
-
selectedAgentTypeId: agents2.some((agent) => agent.agentTypeId === previous.selectedAgentTypeId) ? previous.selectedAgentTypeId : agents2[0]?.agentTypeId,
|
|
12273
|
+
selectedAgentTypeId: agents2.some((agent) => agent.agentTypeId === previous.selectedAgentTypeId) ? previous.selectedAgentTypeId : preferredAgentTypeId ?? agents2[0]?.agentTypeId,
|
|
11498
12274
|
loading: false,
|
|
11499
12275
|
error: void 0
|
|
11500
12276
|
}));
|
|
@@ -11511,11 +12287,11 @@ ${headersKey}`;
|
|
|
11511
12287
|
return () => {
|
|
11512
12288
|
cancelled = true;
|
|
11513
12289
|
};
|
|
11514
|
-
}, [discoveryKey, enabled, fetchImpl, normalizedBaseUrl]);
|
|
12290
|
+
}, [discoveryKey, enabled, fetchImpl, normalizedBaseUrl, preferredAgentTypeId]);
|
|
11515
12291
|
const current = state.discoveryKey === discoveryKey;
|
|
11516
12292
|
const agents = enabled && current ? state.agents : [];
|
|
11517
12293
|
const selectedAgentTypeId = enabled && current ? state.selectedAgentTypeId : void 0;
|
|
11518
|
-
const selectAgentTypeId =
|
|
12294
|
+
const selectAgentTypeId = useCallback20((agentTypeId) => {
|
|
11519
12295
|
setState((previous) => {
|
|
11520
12296
|
if (previous.discoveryKey !== discoveryKey) return previous;
|
|
11521
12297
|
if (!previous.agents.some((agent) => agent.agentTypeId === agentTypeId)) return previous;
|