@hachej/boring-agent 0.1.105 → 0.1.108
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-F2OJI2LX.js → chunk-GS4ADE34.js} +863 -358
- package/dist/{chunk-LFN45QDZ.js → chunk-KDXIXVF6.js} +5076 -3640
- 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-GMBZZPTN.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 +36 -7
- package/dist/front/index.js +1491 -727
- package/dist/front/styles.css +57 -0
- 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 +167 -212
- package/dist/server/index.js +13 -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-BTsdaAQ2.d.ts → types-B7-PN5jV.d.ts} +47 -14
- package/docs/AGENT_GATEWAY_V0.md +40 -2
- package/docs/ERROR_CODES.md +1 -0
- 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";
|
|
@@ -550,7 +557,7 @@ import { useCallback, useState as useState3 } from "react";
|
|
|
550
557
|
import { Button as Button4 } from "@hachej/boring-ui-kit";
|
|
551
558
|
import { jsx as jsx5, jsxs as jsxs5 } from "react/jsx-runtime";
|
|
552
559
|
function CodeBlock({
|
|
553
|
-
code
|
|
560
|
+
code,
|
|
554
561
|
language,
|
|
555
562
|
filename,
|
|
556
563
|
className,
|
|
@@ -559,13 +566,13 @@ function CodeBlock({
|
|
|
559
566
|
}) {
|
|
560
567
|
const [copied, setCopied] = useState3(false);
|
|
561
568
|
const handleCopy = useCallback(() => {
|
|
562
|
-
void copyTextToClipboard(
|
|
569
|
+
void copyTextToClipboard(code).then((ok) => {
|
|
563
570
|
if (!ok) return;
|
|
564
571
|
setCopied(true);
|
|
565
572
|
setTimeout(() => setCopied(false), 2e3);
|
|
566
573
|
});
|
|
567
|
-
}, [
|
|
568
|
-
const lines =
|
|
574
|
+
}, [code]);
|
|
575
|
+
const lines = code.split("\n");
|
|
569
576
|
const lineNumberWidth = `${String(lines.length).length + 1}ch`;
|
|
570
577
|
return /* @__PURE__ */ jsxs5(
|
|
571
578
|
"div",
|
|
@@ -582,7 +589,7 @@ function CodeBlock({
|
|
|
582
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: [
|
|
583
590
|
/* @__PURE__ */ jsx5("span", { className: "mr-4 inline-block select-none text-right opacity-40", style: { width: lineNumberWidth }, children: i + 1 }),
|
|
584
591
|
line
|
|
585
|
-
] }, i)) :
|
|
592
|
+
] }, i)) : code }) }),
|
|
586
593
|
copyable && !filename && !language && /* @__PURE__ */ jsx5(
|
|
587
594
|
Button4,
|
|
588
595
|
{
|
|
@@ -929,7 +936,6 @@ import {
|
|
|
929
936
|
useRef as useRef2,
|
|
930
937
|
useState as useState4
|
|
931
938
|
} from "react";
|
|
932
|
-
import { createHighlighter } from "shiki";
|
|
933
939
|
import { jsx as jsx7, jsxs as jsxs7 } from "react/jsx-runtime";
|
|
934
940
|
var isItalic = (fontStyle) => fontStyle && fontStyle & 1;
|
|
935
941
|
var isBold = (fontStyle) => fontStyle && fontStyle & 2;
|
|
@@ -981,27 +987,27 @@ var CodeBlockContext = createContext({
|
|
|
981
987
|
var highlighterCache = /* @__PURE__ */ new Map();
|
|
982
988
|
var tokensCache = /* @__PURE__ */ new Map();
|
|
983
989
|
var subscribers = /* @__PURE__ */ new Map();
|
|
984
|
-
var getTokensCacheKey = (
|
|
985
|
-
const start =
|
|
986
|
-
const end =
|
|
987
|
-
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}`;
|
|
988
994
|
};
|
|
989
995
|
var getHighlighter = (language) => {
|
|
990
996
|
const cached = highlighterCache.get(language);
|
|
991
997
|
if (cached) {
|
|
992
998
|
return cached;
|
|
993
999
|
}
|
|
994
|
-
const highlighterPromise = createHighlighter({
|
|
1000
|
+
const highlighterPromise = import("shiki").then(({ createHighlighter }) => createHighlighter({
|
|
995
1001
|
langs: [language],
|
|
996
1002
|
themes: ["github-light", "github-dark"]
|
|
997
|
-
});
|
|
1003
|
+
}));
|
|
998
1004
|
highlighterCache.set(language, highlighterPromise);
|
|
999
1005
|
return highlighterPromise;
|
|
1000
1006
|
};
|
|
1001
|
-
var createRawTokens = (
|
|
1007
|
+
var createRawTokens = (code) => ({
|
|
1002
1008
|
bg: "transparent",
|
|
1003
1009
|
fg: "inherit",
|
|
1004
|
-
tokens:
|
|
1010
|
+
tokens: code.split("\n").map(
|
|
1005
1011
|
(line) => line === "" ? [] : [
|
|
1006
1012
|
{
|
|
1007
1013
|
color: "inherit",
|
|
@@ -1010,8 +1016,8 @@ var createRawTokens = (code3) => ({
|
|
|
1010
1016
|
]
|
|
1011
1017
|
)
|
|
1012
1018
|
});
|
|
1013
|
-
var highlightCode = (
|
|
1014
|
-
const tokensCacheKey = getTokensCacheKey(
|
|
1019
|
+
var highlightCode = (code, language, callback) => {
|
|
1020
|
+
const tokensCacheKey = getTokensCacheKey(code, language);
|
|
1015
1021
|
const cached = tokensCache.get(tokensCacheKey);
|
|
1016
1022
|
if (cached) {
|
|
1017
1023
|
return cached;
|
|
@@ -1025,7 +1031,7 @@ var highlightCode = (code3, language, callback) => {
|
|
|
1025
1031
|
getHighlighter(language).then((highlighter) => {
|
|
1026
1032
|
const availableLangs = highlighter.getLoadedLanguages();
|
|
1027
1033
|
const langToUse = availableLangs.includes(language) ? language : "text";
|
|
1028
|
-
const result = highlighter.codeToTokens(
|
|
1034
|
+
const result = highlighter.codeToTokens(code, {
|
|
1029
1035
|
lang: langToUse,
|
|
1030
1036
|
themes: {
|
|
1031
1037
|
dark: "github-dark",
|
|
@@ -1155,25 +1161,25 @@ var CodeBlockFilename = ({
|
|
|
1155
1161
|
}
|
|
1156
1162
|
);
|
|
1157
1163
|
var CodeBlockContent = ({
|
|
1158
|
-
code
|
|
1164
|
+
code,
|
|
1159
1165
|
language,
|
|
1160
1166
|
showLineNumbers = false
|
|
1161
1167
|
}) => {
|
|
1162
|
-
const rawTokens = useMemo(() => createRawTokens(
|
|
1168
|
+
const rawTokens = useMemo(() => createRawTokens(code), [code]);
|
|
1163
1169
|
const lang = language;
|
|
1164
1170
|
const syncTokens = useMemo(
|
|
1165
|
-
() => highlightCode(
|
|
1166
|
-
[
|
|
1171
|
+
() => highlightCode(code, lang) ?? rawTokens,
|
|
1172
|
+
[code, lang, rawTokens]
|
|
1167
1173
|
);
|
|
1168
1174
|
const [asyncTokens, setAsyncTokens] = useState4(null);
|
|
1169
|
-
const asyncKeyRef = useRef2({ code
|
|
1170
|
-
if (asyncKeyRef.current.code !==
|
|
1171
|
-
asyncKeyRef.current = { code
|
|
1175
|
+
const asyncKeyRef = useRef2({ code, language });
|
|
1176
|
+
if (asyncKeyRef.current.code !== code || asyncKeyRef.current.language !== language) {
|
|
1177
|
+
asyncKeyRef.current = { code, language };
|
|
1172
1178
|
setAsyncTokens(null);
|
|
1173
1179
|
}
|
|
1174
1180
|
useEffect2(() => {
|
|
1175
1181
|
let cancelled = false;
|
|
1176
|
-
highlightCode(
|
|
1182
|
+
highlightCode(code, lang, (result) => {
|
|
1177
1183
|
if (!cancelled) {
|
|
1178
1184
|
setAsyncTokens(result);
|
|
1179
1185
|
}
|
|
@@ -1181,25 +1187,25 @@ var CodeBlockContent = ({
|
|
|
1181
1187
|
return () => {
|
|
1182
1188
|
cancelled = true;
|
|
1183
1189
|
};
|
|
1184
|
-
}, [
|
|
1190
|
+
}, [code, language]);
|
|
1185
1191
|
const tokenized = asyncTokens ?? syncTokens;
|
|
1186
1192
|
return /* @__PURE__ */ jsx7("div", { className: "relative overflow-auto", children: /* @__PURE__ */ jsx7(CodeBlockBody, { showLineNumbers, tokenized }) });
|
|
1187
1193
|
};
|
|
1188
1194
|
var CodeBlock2 = ({
|
|
1189
|
-
code
|
|
1195
|
+
code,
|
|
1190
1196
|
language,
|
|
1191
1197
|
showLineNumbers = false,
|
|
1192
1198
|
className,
|
|
1193
1199
|
children,
|
|
1194
1200
|
...props
|
|
1195
1201
|
}) => {
|
|
1196
|
-
const contextValue = useMemo(() => ({ code
|
|
1202
|
+
const contextValue = useMemo(() => ({ code }), [code]);
|
|
1197
1203
|
return /* @__PURE__ */ jsx7(CodeBlockContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsxs7(CodeBlockContainer, { className, language, ...props, children: [
|
|
1198
1204
|
children,
|
|
1199
1205
|
/* @__PURE__ */ jsx7(
|
|
1200
1206
|
CodeBlockContent,
|
|
1201
1207
|
{
|
|
1202
|
-
code
|
|
1208
|
+
code,
|
|
1203
1209
|
language,
|
|
1204
1210
|
showLineNumbers
|
|
1205
1211
|
}
|
|
@@ -1216,7 +1222,7 @@ var CodeBlockCopyButton = ({
|
|
|
1216
1222
|
}) => {
|
|
1217
1223
|
const [isCopied, setIsCopied] = useState4(false);
|
|
1218
1224
|
const timeoutRef = useRef2(0);
|
|
1219
|
-
const { code
|
|
1225
|
+
const { code } = useContext(CodeBlockContext);
|
|
1220
1226
|
const copyToClipboard = useCallback2(async () => {
|
|
1221
1227
|
if (typeof window === "undefined") {
|
|
1222
1228
|
onError?.(new Error("Clipboard API not available"));
|
|
@@ -1225,7 +1231,7 @@ var CodeBlockCopyButton = ({
|
|
|
1225
1231
|
if (isCopied) {
|
|
1226
1232
|
return;
|
|
1227
1233
|
}
|
|
1228
|
-
const copied = await copyTextToClipboard(
|
|
1234
|
+
const copied = await copyTextToClipboard(code);
|
|
1229
1235
|
if (!copied) {
|
|
1230
1236
|
onError?.(new Error("Clipboard API not available"));
|
|
1231
1237
|
return;
|
|
@@ -1236,7 +1242,7 @@ var CodeBlockCopyButton = ({
|
|
|
1236
1242
|
() => setIsCopied(false),
|
|
1237
1243
|
timeout
|
|
1238
1244
|
);
|
|
1239
|
-
}, [
|
|
1245
|
+
}, [code, onCopy, onError, timeout, isCopied]);
|
|
1240
1246
|
useEffect2(
|
|
1241
1247
|
() => () => {
|
|
1242
1248
|
window.clearTimeout(timeoutRef.current);
|
|
@@ -2228,6 +2234,7 @@ var PiFollowUpQueueController = class {
|
|
|
2228
2234
|
session;
|
|
2229
2235
|
options;
|
|
2230
2236
|
nextClientSeqFloor;
|
|
2237
|
+
queueMutationPending = false;
|
|
2231
2238
|
async submit(input) {
|
|
2232
2239
|
const text = input.text.trim();
|
|
2233
2240
|
const attachments = input.attachments ?? [];
|
|
@@ -2265,30 +2272,65 @@ var PiFollowUpQueueController = class {
|
|
|
2265
2272
|
});
|
|
2266
2273
|
return { type: "prompt", clientNonce, cursor: receipt.cursor };
|
|
2267
2274
|
}
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2271
|
-
|
|
2272
|
-
|
|
2273
|
-
|
|
2274
|
-
|
|
2275
|
-
|
|
2276
|
-
|
|
2277
|
-
|
|
2278
|
-
|
|
2279
|
-
|
|
2280
|
-
|
|
2281
|
-
|
|
2282
|
-
|
|
2283
|
-
|
|
2284
|
-
|
|
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
|
+
);
|
|
2285
2298
|
}
|
|
2286
|
-
|
|
2287
|
-
return this.
|
|
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
|
+
);
|
|
2313
|
+
}
|
|
2314
|
+
interrupt(payload = {}) {
|
|
2315
|
+
return this.session.interrupt(payload);
|
|
2316
|
+
}
|
|
2317
|
+
resumeQueued() {
|
|
2318
|
+
return this.session.interrupt({ queueAction: "resume" });
|
|
2288
2319
|
}
|
|
2289
2320
|
stop() {
|
|
2290
2321
|
return this.session.stop();
|
|
2291
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
|
+
}
|
|
2292
2334
|
nextFollowUpClientSeq() {
|
|
2293
2335
|
const next = nextFollowUpClientSeq(this.session.getState(), this.nextClientSeqFloor);
|
|
2294
2336
|
this.nextClientSeqFloor = next + 1;
|
|
@@ -2329,6 +2371,9 @@ function buildEditedQueuedDraft(followUps, existingDraft = "") {
|
|
|
2329
2371
|
const draft = existingDraft.trim();
|
|
2330
2372
|
if (!queuedText) return draft;
|
|
2331
2373
|
if (!draft) return queuedText;
|
|
2374
|
+
if (draft === queuedText || draft.startsWith(`${queuedText}
|
|
2375
|
+
|
|
2376
|
+
`)) return draft;
|
|
2332
2377
|
return `${queuedText}
|
|
2333
2378
|
|
|
2334
2379
|
${draft}`;
|
|
@@ -2347,76 +2392,148 @@ function defaultClientNonce() {
|
|
|
2347
2392
|
// src/front/chat/session/composerPolicy.ts
|
|
2348
2393
|
var COMPOSER_SETTINGS_PREFIX = "boring-agent:v2";
|
|
2349
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
|
+
};
|
|
2350
2424
|
var PiComposerPolicyController = class {
|
|
2351
2425
|
constructor(options) {
|
|
2352
2426
|
this.options = options;
|
|
2353
2427
|
this.queueController = createPiFollowUpQueueController(options.session, options);
|
|
2428
|
+
this.submissionCoordinator = options.submissionCoordinator ?? new PiComposerSubmissionCoordinator();
|
|
2354
2429
|
}
|
|
2355
2430
|
options;
|
|
2356
2431
|
queueController;
|
|
2357
|
-
|
|
2358
|
-
|
|
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) {
|
|
2359
2440
|
const files = input.files ?? [];
|
|
2360
2441
|
const source = input.source ?? "composer";
|
|
2361
2442
|
if (this.options.composerBlocked) {
|
|
2362
2443
|
return this.block("composer-blocked", this.options.blockerMessage ?? "Composer is not ready yet.");
|
|
2363
2444
|
}
|
|
2364
|
-
|
|
2365
|
-
|
|
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;
|
|
2366
2451
|
}
|
|
2367
2452
|
if (this.options.isActiveSession && !this.options.isActiveSession()) {
|
|
2368
|
-
return this.
|
|
2453
|
+
return this.stale();
|
|
2454
|
+
}
|
|
2455
|
+
if (beforeSubmit === false) {
|
|
2456
|
+
return this.block("pre-submit-cancelled", "Submit was cancelled before sending.");
|
|
2369
2457
|
}
|
|
2370
|
-
|
|
2458
|
+
if (typeof beforeSubmit === "object" && "handled" in beforeSubmit && beforeSubmit.handled) {
|
|
2459
|
+
return { type: "handled", ...beforeSubmit.message ? { message: beforeSubmit.message } : {}, preserveDraft: false };
|
|
2460
|
+
}
|
|
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);
|
|
2371
2465
|
if (parsed) {
|
|
2372
2466
|
const command = this.options.registry.get(parsed.name);
|
|
2373
2467
|
if (command?.kind === "skill") {
|
|
2374
|
-
return this.submitExpandedText(skillCommandText(parsed.name, parsed.args), source,
|
|
2468
|
+
return this.submitExpandedText(skillCommandText(parsed.name, parsed.args), files, source, release);
|
|
2375
2469
|
}
|
|
2376
|
-
if (command) return this.runLocalCommand(parsed.name, parsed.args, source);
|
|
2470
|
+
if (command) return this.runLocalCommand(parsed.name, parsed.args, source, release);
|
|
2377
2471
|
}
|
|
2378
2472
|
if (isPiChatBusy(this.options.session.getState().status) && files.length > 0) {
|
|
2379
2473
|
return this.fromQueueResult(await this.queueController.submit({ text, attachments: this.toAttachmentPayloads(files) }));
|
|
2380
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;
|
|
2381
2479
|
const { serverMessage, attachments } = await createEnrichedSubmitPayload({
|
|
2382
|
-
text,
|
|
2480
|
+
text: finalText,
|
|
2383
2481
|
files,
|
|
2384
2482
|
mentionedFiles: this.getMentionedFiles()
|
|
2385
2483
|
});
|
|
2386
2484
|
if (this.options.isActiveSession && !this.options.isActiveSession()) {
|
|
2387
|
-
return this.
|
|
2485
|
+
return this.stale();
|
|
2388
2486
|
}
|
|
2389
|
-
const
|
|
2487
|
+
const admission = this.queueController.submit({
|
|
2390
2488
|
text: serverMessage,
|
|
2391
|
-
displayText:
|
|
2489
|
+
displayText: finalDisplayText,
|
|
2392
2490
|
attachments,
|
|
2393
2491
|
model: this.options.model ?? void 0,
|
|
2394
2492
|
...this.options.thinkingControl ? { thinkingLevel: this.options.thinkingLevel ?? DEFAULT_THINKING } : {}
|
|
2395
2493
|
});
|
|
2494
|
+
release();
|
|
2495
|
+
const result = await admission;
|
|
2396
2496
|
if (result.type !== "blocked") this.options.onMentionedFilesConsumed?.();
|
|
2397
2497
|
return this.fromQueueResult(result);
|
|
2398
2498
|
}
|
|
2399
2499
|
async editQueued() {
|
|
2400
2500
|
return this.queueController.editQueued();
|
|
2401
2501
|
}
|
|
2402
|
-
|
|
2403
|
-
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();
|
|
2404
2510
|
}
|
|
2405
2511
|
stop() {
|
|
2406
2512
|
return this.queueController.stop();
|
|
2407
2513
|
}
|
|
2408
|
-
async submitExpandedText(text, source,
|
|
2409
|
-
|
|
2410
|
-
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
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 } : {},
|
|
2414
2520
|
kind: "expanded-text",
|
|
2415
2521
|
model: this.options.model ?? void 0,
|
|
2416
2522
|
...this.options.thinkingControl ? { thinkingLevel: this.options.thinkingLevel ?? DEFAULT_THINKING } : {}
|
|
2417
|
-
})
|
|
2523
|
+
});
|
|
2524
|
+
release();
|
|
2525
|
+
return this.fromQueueResult(await admission);
|
|
2418
2526
|
}
|
|
2419
|
-
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) {
|
|
2420
2537
|
const command = this.options.registry.get(commandName);
|
|
2421
2538
|
if (isPiChatBusy(this.options.session.getState().status) && command?.allowWhileBusy?.(args) !== true) {
|
|
2422
2539
|
return this.block("busy-slash-command", "Slash commands are not queued while the agent is responding.");
|
|
@@ -2427,18 +2544,21 @@ var PiComposerPolicyController = class {
|
|
|
2427
2544
|
if (message) this.options.onCommandResult?.(message);
|
|
2428
2545
|
const modelMessage = result && typeof result === "object" ? result.modelMessage?.trim() : void 0;
|
|
2429
2546
|
if (modelMessage) {
|
|
2430
|
-
return await this.submitExpandedText(modelMessage, source,
|
|
2547
|
+
return await this.submitExpandedText(modelMessage, [], source, release);
|
|
2431
2548
|
}
|
|
2549
|
+
release();
|
|
2432
2550
|
return { type: "command", command: commandName, ...message ? { result: message } : {}, preserveDraft };
|
|
2433
2551
|
}
|
|
2434
2552
|
async runBeforeSubmit(draft, files, source) {
|
|
2435
|
-
|
|
2436
|
-
return result !== false;
|
|
2553
|
+
return await this.options.onBeforeSubmit?.(draft, { files, source });
|
|
2437
2554
|
}
|
|
2438
2555
|
fromQueueResult(result) {
|
|
2439
2556
|
if (result.type === "blocked") return { ...result, preserveDraft: true };
|
|
2440
2557
|
return { ...result, preserveDraft: false };
|
|
2441
2558
|
}
|
|
2559
|
+
stale() {
|
|
2560
|
+
return { type: "stale", reason: "inactive-session", preserveDraft: false };
|
|
2561
|
+
}
|
|
2442
2562
|
block(reason, message) {
|
|
2443
2563
|
this.options.onWarning?.(message);
|
|
2444
2564
|
return { type: "blocked", reason, message, preserveDraft: true };
|
|
@@ -2652,15 +2772,17 @@ function useChatModelSelection({
|
|
|
2652
2772
|
setAvailableModels(models);
|
|
2653
2773
|
setSelection((current) => {
|
|
2654
2774
|
const selected = current.pendingOverride ?? sessionModel ?? current.localDefault;
|
|
2655
|
-
if (
|
|
2656
|
-
|
|
2657
|
-
|
|
2775
|
+
if (sessionModel) {
|
|
2776
|
+
if (availableModel(models, selected)) return current;
|
|
2777
|
+
return { ...current, pendingOverride: void 0 };
|
|
2778
|
+
}
|
|
2658
2779
|
const firstAvailable = models.find((candidate) => candidate.available);
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
pendingOverride: void 0,
|
|
2662
|
-
|
|
2663
|
-
|
|
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 };
|
|
2664
2786
|
});
|
|
2665
2787
|
setLoadedDiscoveryKey(discoveryKey);
|
|
2666
2788
|
setLoaded(true);
|
|
@@ -2688,7 +2810,8 @@ function useChatModelSelection({
|
|
|
2688
2810
|
const selectionBelongsToSession = selection.sessionId === sessionId && selection.storage === storage && selection.storageScope === storageScope;
|
|
2689
2811
|
const pendingOverride = selectionBelongsToSession ? selection.pendingOverride : void 0;
|
|
2690
2812
|
const isOverride = Boolean(pendingOverride && sessionModel && !sameModel(pendingOverride, sessionModel));
|
|
2691
|
-
const
|
|
2813
|
+
const discoveryVetted = enabled && currentDiscoveryLoaded;
|
|
2814
|
+
const sessionAuthorityReady = !sessionId || sessionHydrated && (sessionModel !== void 0 || sessionIsNew || discoveryVetted);
|
|
2692
2815
|
const model = currentDiscoveryLoaded && sessionAuthorityReady ? pendingOverride ?? sessionModel ?? selection.localDefault : null;
|
|
2693
2816
|
return {
|
|
2694
2817
|
availableModels: currentDiscoveryLoaded ? availableModels : [],
|
|
@@ -3395,15 +3518,15 @@ function messageCreatedAtMs(message) {
|
|
|
3395
3518
|
|
|
3396
3519
|
// src/front/chat/gatewayResponseError.ts
|
|
3397
3520
|
var GatewayResponseError = class extends Error {
|
|
3398
|
-
constructor(status, message,
|
|
3521
|
+
constructor(status, message, code, details, body, operation) {
|
|
3399
3522
|
super(message);
|
|
3400
3523
|
this.status = status;
|
|
3401
|
-
this.code =
|
|
3524
|
+
this.code = code;
|
|
3402
3525
|
this.details = details;
|
|
3403
3526
|
this.body = body;
|
|
3404
3527
|
this.operation = operation;
|
|
3405
3528
|
this.name = "GatewayResponseError";
|
|
3406
|
-
this.errorCode =
|
|
3529
|
+
this.errorCode = code;
|
|
3407
3530
|
}
|
|
3408
3531
|
status;
|
|
3409
3532
|
code;
|
|
@@ -3418,11 +3541,11 @@ async function gatewayResponseError(response, fallbackMessage, operation) {
|
|
|
3418
3541
|
}
|
|
3419
3542
|
function gatewayResponseErrorFromBody(status, body, fallbackMessage, operation) {
|
|
3420
3543
|
const payload = errorPayload(body);
|
|
3421
|
-
const
|
|
3544
|
+
const code = gatewayResponseErrorCode(payload?.code);
|
|
3422
3545
|
const serverMessage = typeof payload?.message === "string" && payload.message.trim().length > 0 ? payload.message : fallbackMessage;
|
|
3423
3546
|
const message = serverMessage;
|
|
3424
3547
|
const details = isJsonValue(payload?.details) ? payload.details : void 0;
|
|
3425
|
-
return new GatewayResponseError(status, message,
|
|
3548
|
+
return new GatewayResponseError(status, message, code, details, body, operation);
|
|
3426
3549
|
}
|
|
3427
3550
|
function gatewayResponseErrorCode(value) {
|
|
3428
3551
|
const sharedCode = ErrorCode.safeParse(value);
|
|
@@ -4695,12 +4818,30 @@ var RemotePiSession = class {
|
|
|
4695
4818
|
}
|
|
4696
4819
|
}
|
|
4697
4820
|
async clearQueue(payload = {}) {
|
|
4698
|
-
const receipt = await this.
|
|
4821
|
+
const receipt = await this.postQueueClear({ ...payload, requestId: `queue-clear:${safeRandomUUID()}` });
|
|
4699
4822
|
if (!this.disposed && receipt.cleared > 0) {
|
|
4700
4823
|
this.store.dispatch({ type: "clear-optimistic-followups", ...payload }, { flush: true });
|
|
4701
4824
|
}
|
|
4702
4825
|
return receipt;
|
|
4703
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
|
+
}
|
|
4704
4845
|
async interrupt(payload = {}) {
|
|
4705
4846
|
return this.postCommand("/interrupt", payload, CommandReceiptSchema);
|
|
4706
4847
|
}
|
|
@@ -5310,17 +5451,27 @@ function usePiSessions(options) {
|
|
|
5310
5451
|
const [loading, setLoading] = useState10(enabled);
|
|
5311
5452
|
const [loadingMore, setLoadingMore] = useState10(false);
|
|
5312
5453
|
const [hasMore, setHasMore] = useState10(false);
|
|
5454
|
+
const [archivedLoaded, setArchivedLoaded] = useState10(false);
|
|
5455
|
+
const [archivedLoading, setArchivedLoading] = useState10(false);
|
|
5456
|
+
const [hasMoreArchived, setHasMoreArchived] = useState10(false);
|
|
5313
5457
|
const [error, setError] = useState10(void 0);
|
|
5314
5458
|
const mountedRef = useRef7(false);
|
|
5315
5459
|
const refreshVersionRef = useRef7(0);
|
|
5316
5460
|
const retryTimerRef = useRef7(void 0);
|
|
5317
5461
|
const sessionsRef = useRef7([]);
|
|
5462
|
+
const filterPagersRef = useRef7({
|
|
5463
|
+
active: { sessions: [], loaded: false },
|
|
5464
|
+
archived: { sessions: [], loaded: false }
|
|
5465
|
+
});
|
|
5466
|
+
const archiveMutationVersionRef = useRef7(0);
|
|
5318
5467
|
const activeSessionIdRef = useRef7(activeSessionId);
|
|
5319
|
-
const hasMoreRef = useRef7(hasMore);
|
|
5320
5468
|
const canonicalLoadedCountRef = useRef7(0);
|
|
5321
5469
|
const nextCursorRef = useRef7(void 0);
|
|
5322
|
-
const
|
|
5323
|
-
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);
|
|
5324
5475
|
const pendingCreatedRef = useRef7(/* @__PURE__ */ new Map());
|
|
5325
5476
|
const pendingDeletedRef = useRef7(/* @__PURE__ */ new Set());
|
|
5326
5477
|
const pendingCreatedScopeRef = useRef7(requestScopeKey);
|
|
@@ -5352,14 +5503,11 @@ function usePiSessions(options) {
|
|
|
5352
5503
|
useEffect8(() => {
|
|
5353
5504
|
activeSessionIdRef.current = activeSessionId;
|
|
5354
5505
|
}, [activeSessionId]);
|
|
5355
|
-
useEffect8(() => {
|
|
5356
|
-
hasMoreRef.current = hasMore;
|
|
5357
|
-
}, [hasMore]);
|
|
5358
5506
|
const activeSessionKnown = Boolean(activeSessionId && sessions.some((session) => session.id === activeSessionId));
|
|
5359
5507
|
const requestHeaders = useCallback7(() => normalizedHeaders, [normalizedHeaders]);
|
|
5360
5508
|
const sessionsUrl = useCallback7((suffix = "") => `${apiBaseUrl}${sessionsApiPath}${suffix}`, [apiBaseUrl, sessionsApiPath]);
|
|
5361
|
-
const sessionsListUrl = useCallback7((cursor) => {
|
|
5362
|
-
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 });
|
|
5363
5511
|
if (cursor) query.set("cursor", cursor);
|
|
5364
5512
|
return sessionsUrl(`?${query.toString()}`);
|
|
5365
5513
|
}, [sessionsUrl]);
|
|
@@ -5380,6 +5528,27 @@ function usePiSessions(options) {
|
|
|
5380
5528
|
pendingCreatedRef.current.clear();
|
|
5381
5529
|
pendingDeletedRef.current.clear();
|
|
5382
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
|
+
}, []);
|
|
5383
5552
|
const preferredSessionId = useCallback7(() => {
|
|
5384
5553
|
const persisted = options.initialActiveSessionId ?? readActiveSessionId({
|
|
5385
5554
|
storageScope: activeSessionStorageScope,
|
|
@@ -5406,11 +5575,23 @@ function usePiSessions(options) {
|
|
|
5406
5575
|
}
|
|
5407
5576
|
}
|
|
5408
5577
|
const canonicalCount = canonicalPageCount(filteredData);
|
|
5409
|
-
|
|
5410
|
-
|
|
5411
|
-
|
|
5412
|
-
|
|
5413
|
-
|
|
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
|
+
}
|
|
5414
5595
|
const rememberedEmptyId = readBootResumeSessionId({
|
|
5415
5596
|
bootResumeSource,
|
|
5416
5597
|
storage: options.bootResumeStorage
|
|
@@ -5418,12 +5599,13 @@ function usePiSessions(options) {
|
|
|
5418
5599
|
if (rememberedEmptyId && filteredData.some((session) => session.id === rememberedEmptyId)) {
|
|
5419
5600
|
persistBootResume(void 0);
|
|
5420
5601
|
}
|
|
5421
|
-
const nextHasMore =
|
|
5602
|
+
const nextHasMore = applyOptions.nextCursor !== void 0;
|
|
5422
5603
|
canonicalLoadedCountRef.current = applyOptions.background ? Math.max(canonicalLoadedCountRef.current, canonicalCount) : canonicalCount;
|
|
5604
|
+
if (replacingScope && !applyOptions.archivedPage) resetArchivePager();
|
|
5423
5605
|
loadedDataSourceRef.current = dataSourceKey;
|
|
5424
5606
|
dataStorageScopeRef.current = storageScope;
|
|
5425
5607
|
setDataStorageScope(storageScope);
|
|
5426
|
-
|
|
5608
|
+
const merged = publishFilterPagers();
|
|
5427
5609
|
nextCursorRef.current = applyOptions.nextCursor;
|
|
5428
5610
|
setHasMore(nextHasMore);
|
|
5429
5611
|
setActiveSessionId((previous) => {
|
|
@@ -5432,21 +5614,26 @@ function usePiSessions(options) {
|
|
|
5432
5614
|
persistActive(next);
|
|
5433
5615
|
return next;
|
|
5434
5616
|
});
|
|
5435
|
-
}, [bootResumeSource, dataSourceKey, ensurePendingScope, options.bootResumeStorage, persistActive, persistBootResume, preferredSessionId, storageScope]);
|
|
5617
|
+
}, [bootResumeSource, dataSourceKey, ensurePendingScope, options.bootResumeStorage, persistActive, persistBootResume, preferredSessionId, publishFilterPagers, resetArchivePager, storageScope]);
|
|
5436
5618
|
const refresh = useCallback7(async (refreshOptions = {}) => {
|
|
5437
5619
|
const scope = requestScopeKey;
|
|
5438
5620
|
if (mountedRef.current && !sourceIsCurrent(scope)) throw new StaleSessionsSourceError();
|
|
5621
|
+
const requestOwner = {};
|
|
5622
|
+
activeRequestOwnerRef.current = requestOwner;
|
|
5439
5623
|
const version = ++refreshVersionRef.current;
|
|
5440
|
-
const
|
|
5624
|
+
const mutationVersion = archiveMutationVersionRef.current;
|
|
5625
|
+
const isCurrent = () => sourceIsCurrent(scope) && version === refreshVersionRef.current && activeRequestOwnerRef.current === requestOwner;
|
|
5441
5626
|
clearRetryTimer(retryTimerRef);
|
|
5442
5627
|
const background = refreshOptions.background === true;
|
|
5628
|
+
let archivedRequestSeq;
|
|
5443
5629
|
if (!enabled) {
|
|
5444
|
-
loadMoreRequestSeqRef.current += 1;
|
|
5445
|
-
loadMoreInFlightRef.current = false;
|
|
5446
5630
|
canonicalLoadedCountRef.current = 0;
|
|
5447
5631
|
loadedDataSourceRef.current = dataSourceKey;
|
|
5448
5632
|
dataStorageScopeRef.current = storageScope;
|
|
5449
5633
|
setDataStorageScope(storageScope);
|
|
5634
|
+
filterPagersRef.current.active = { sessions: [], loaded: true };
|
|
5635
|
+
resetArchivePager();
|
|
5636
|
+
sessionsRef.current = [];
|
|
5450
5637
|
setSessions([]);
|
|
5451
5638
|
setActiveSessionId(void 0);
|
|
5452
5639
|
setError(void 0);
|
|
@@ -5454,17 +5641,22 @@ function usePiSessions(options) {
|
|
|
5454
5641
|
setLoadingMore(false);
|
|
5455
5642
|
setHasMore(false);
|
|
5456
5643
|
persistActive(void 0);
|
|
5644
|
+
if (activeRequestOwnerRef.current === requestOwner) activeRequestOwnerRef.current = void 0;
|
|
5457
5645
|
return;
|
|
5458
5646
|
}
|
|
5459
|
-
loadMoreRequestSeqRef.current += 1;
|
|
5460
|
-
loadMoreInFlightRef.current = false;
|
|
5461
5647
|
setLoadingMore(false);
|
|
5462
5648
|
if (!background) setLoading(true);
|
|
5463
5649
|
try {
|
|
5464
5650
|
let page;
|
|
5465
5651
|
for (let attempt = 0; ; attempt += 1) {
|
|
5466
5652
|
try {
|
|
5467
|
-
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
|
+
});
|
|
5468
5660
|
break;
|
|
5469
5661
|
} catch (err) {
|
|
5470
5662
|
const transient = err instanceof SessionsPreparingError || isNetworkFetchError(err);
|
|
@@ -5476,17 +5668,41 @@ function usePiSessions(options) {
|
|
|
5476
5668
|
}
|
|
5477
5669
|
}
|
|
5478
5670
|
if (!isCurrent() || !page) return;
|
|
5479
|
-
|
|
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 });
|
|
5480
5690
|
setError(void 0);
|
|
5481
5691
|
setLoading(false);
|
|
5482
5692
|
} catch (err) {
|
|
5483
|
-
if (!isCurrent()) return;
|
|
5693
|
+
if (!isCurrent() || archivedRequestSeq !== void 0 && archivedRequestSeq !== archiveRequestSeqRef.current) return;
|
|
5484
5694
|
const error2 = err instanceof Error ? err : new Error(String(err));
|
|
5485
5695
|
if (!background) setError(error2);
|
|
5486
5696
|
setLoading(false);
|
|
5487
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
|
+
}
|
|
5488
5704
|
}
|
|
5489
|
-
}, [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]);
|
|
5490
5706
|
useEffect8(() => {
|
|
5491
5707
|
mountedRef.current = true;
|
|
5492
5708
|
void refresh();
|
|
@@ -5497,21 +5713,26 @@ function usePiSessions(options) {
|
|
|
5497
5713
|
};
|
|
5498
5714
|
}, [refresh, options.refreshKey]);
|
|
5499
5715
|
const loadMore = useCallback7(async () => {
|
|
5500
|
-
if (!enabled || loading || loadingMore ||
|
|
5501
|
-
const
|
|
5502
|
-
|
|
5716
|
+
if (!enabled || loading || loadingMore || activeRequestOwnerRef.current !== void 0 || !hasMore) return;
|
|
5717
|
+
const requestOwner = {};
|
|
5718
|
+
activeRequestOwnerRef.current = requestOwner;
|
|
5503
5719
|
const version = refreshVersionRef.current;
|
|
5720
|
+
const mutationVersion = archiveMutationVersionRef.current;
|
|
5504
5721
|
const scope = requestScopeKey;
|
|
5505
5722
|
setLoadingMore(true);
|
|
5506
5723
|
try {
|
|
5507
5724
|
const page = await fetchSessionList(fetchImpl, sessionsListUrl(nextCursorRef.current), requestHeaders());
|
|
5508
5725
|
const data = page.sessions.filter((session) => !pendingDeletedRef.current.has(session.id));
|
|
5509
|
-
if (
|
|
5510
|
-
|
|
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();
|
|
5511
5733
|
const nextHasMore = page.nextCursor !== void 0;
|
|
5512
5734
|
canonicalLoadedCountRef.current += data.length;
|
|
5513
5735
|
nextCursorRef.current = page.nextCursor;
|
|
5514
|
-
setSessions(merged);
|
|
5515
5736
|
setHasMore(nextHasMore);
|
|
5516
5737
|
setError(void 0);
|
|
5517
5738
|
setActiveSessionId((previous) => {
|
|
@@ -5521,16 +5742,52 @@ function usePiSessions(options) {
|
|
|
5521
5742
|
return next;
|
|
5522
5743
|
});
|
|
5523
5744
|
} catch (err) {
|
|
5524
|
-
if (
|
|
5745
|
+
if (activeRequestOwnerRef.current === requestOwner && version === refreshVersionRef.current && sourceIsCurrent(scope)) {
|
|
5525
5746
|
setError(err instanceof Error ? err : new Error(String(err)));
|
|
5526
5747
|
}
|
|
5527
5748
|
} finally {
|
|
5528
|
-
if (
|
|
5529
|
-
|
|
5530
|
-
setLoadingMore(false);
|
|
5749
|
+
if (activeRequestOwnerRef.current === requestOwner) {
|
|
5750
|
+
activeRequestOwnerRef.current = void 0;
|
|
5751
|
+
if (version === refreshVersionRef.current && sourceIsCurrent(scope)) setLoadingMore(false);
|
|
5531
5752
|
}
|
|
5532
5753
|
}
|
|
5533
|
-
}, [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]);
|
|
5534
5791
|
useEffect8(() => {
|
|
5535
5792
|
if (!enabled || !connectActiveSession || !activeSessionId || !activeSessionKnown) {
|
|
5536
5793
|
setActivePiSession(void 0);
|
|
@@ -5572,12 +5829,12 @@ function usePiSessions(options) {
|
|
|
5572
5829
|
rememberConfirmedEmptySession(session.id);
|
|
5573
5830
|
pendingCreatedRef.current.set(session.id, session);
|
|
5574
5831
|
setDataStorageScope(storageScope);
|
|
5575
|
-
|
|
5832
|
+
publishFilterPagers();
|
|
5576
5833
|
setActiveSessionId(session.id);
|
|
5577
5834
|
persistActive(session.id);
|
|
5578
5835
|
void refresh();
|
|
5579
5836
|
return session;
|
|
5580
|
-
}, [enabled, ensurePendingScope, fetchImpl, persistActive, refresh, rememberConfirmedEmptySession, requestHeaders, requestScopeKey, sessionsUrl, sourceIsCurrent, storageScope]);
|
|
5837
|
+
}, [enabled, ensurePendingScope, fetchImpl, persistActive, publishFilterPagers, refresh, rememberConfirmedEmptySession, requestHeaders, requestScopeKey, sessionsUrl, sourceIsCurrent, storageScope]);
|
|
5581
5838
|
const switchSession = useCallback7((id) => {
|
|
5582
5839
|
if (!sourceIsCurrent(requestScopeKey)) return;
|
|
5583
5840
|
const known = sessionsRef.current.some((session) => session.id === id);
|
|
@@ -5599,9 +5856,34 @@ function usePiSessions(options) {
|
|
|
5599
5856
|
if (!sourceIsCurrent(scope)) throw new StaleSessionsSourceError();
|
|
5600
5857
|
ensurePendingScope();
|
|
5601
5858
|
if (pendingCreatedRef.current.has(id)) pendingCreatedRef.current.set(id, renamed);
|
|
5602
|
-
|
|
5859
|
+
for (const pager of Object.values(filterPagersRef.current)) {
|
|
5860
|
+
pager.sessions = pager.sessions.map((session) => session.id === id ? renamed : session);
|
|
5861
|
+
}
|
|
5862
|
+
publishFilterPagers();
|
|
5603
5863
|
return renamed;
|
|
5604
|
-
}, [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]);
|
|
5605
5887
|
const deleteSession = useCallback7(async (id) => {
|
|
5606
5888
|
const scope = requestScopeKey;
|
|
5607
5889
|
if (!sourceIsCurrent(scope)) throw new StaleSessionsSourceError();
|
|
@@ -5614,8 +5896,11 @@ function usePiSessions(options) {
|
|
|
5614
5896
|
const deletedSessionWasActive = activeSessionIdRef.current === id;
|
|
5615
5897
|
pendingCreatedRef.current.delete(id);
|
|
5616
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
|
+
}
|
|
5617
5902
|
setDataStorageScope(storageScope);
|
|
5618
|
-
|
|
5903
|
+
publishFilterPagers();
|
|
5619
5904
|
setActiveSessionId((previous) => {
|
|
5620
5905
|
if (previous !== id) return previous;
|
|
5621
5906
|
const next = sessionsRef.current.find((session) => session.id !== id)?.id;
|
|
@@ -5633,7 +5918,9 @@ function usePiSessions(options) {
|
|
|
5633
5918
|
if (sourceIsCurrent(scope)) {
|
|
5634
5919
|
pendingDeletedRef.current.delete(id);
|
|
5635
5920
|
if (deletedSession) {
|
|
5636
|
-
|
|
5921
|
+
const target = deletedSession.archived === true ? filterPagersRef.current.archived : filterPagersRef.current.active;
|
|
5922
|
+
target.sessions = sortSessionSummaries([...target.sessions, deletedSession]);
|
|
5923
|
+
publishFilterPagers();
|
|
5637
5924
|
if (deletedSessionWasActive) {
|
|
5638
5925
|
setActiveSessionId(id);
|
|
5639
5926
|
persistActive(id);
|
|
@@ -5645,14 +5932,15 @@ function usePiSessions(options) {
|
|
|
5645
5932
|
throw error2;
|
|
5646
5933
|
}
|
|
5647
5934
|
if (sourceIsCurrent(scope)) void refresh();
|
|
5648
|
-
}, [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]);
|
|
5649
5936
|
const reset = useCallback7(() => {
|
|
5650
5937
|
if (!sourceIsCurrent(requestScopeKey)) return;
|
|
5651
5938
|
pendingCreatedRef.current.clear();
|
|
5652
5939
|
pendingDeletedRef.current.clear();
|
|
5653
|
-
|
|
5654
|
-
|
|
5655
|
-
|
|
5940
|
+
activeRequestOwnerRef.current = void 0;
|
|
5941
|
+
resetArchivePager();
|
|
5942
|
+
publishFilterPagers();
|
|
5943
|
+
canonicalLoadedCountRef.current = canonicalPageCount(filterPagersRef.current.active.sessions);
|
|
5656
5944
|
loadedDataSourceRef.current = dataSourceKey;
|
|
5657
5945
|
dataStorageScopeRef.current = storageScope;
|
|
5658
5946
|
setDataStorageScope(storageScope);
|
|
@@ -5660,7 +5948,7 @@ function usePiSessions(options) {
|
|
|
5660
5948
|
setActivePiSession(void 0);
|
|
5661
5949
|
setLoadingMore(false);
|
|
5662
5950
|
persistActive(void 0);
|
|
5663
|
-
}, [dataSourceKey, persistActive, requestScopeKey, sourceIsCurrent, storageScope]);
|
|
5951
|
+
}, [dataSourceKey, persistActive, publishFilterPagers, requestScopeKey, resetArchivePager, sourceIsCurrent, storageScope]);
|
|
5664
5952
|
const visibleActiveSessionId = enabled ? activeSessionId : void 0;
|
|
5665
5953
|
const activeSession = enabled ? sessions.find((session) => session.id === visibleActiveSessionId) : void 0;
|
|
5666
5954
|
return {
|
|
@@ -5674,10 +5962,15 @@ function usePiSessions(options) {
|
|
|
5674
5962
|
loading: enabled ? loading : false,
|
|
5675
5963
|
loadingMore,
|
|
5676
5964
|
hasMore: enabled ? hasMore : false,
|
|
5965
|
+
archivedLoaded,
|
|
5966
|
+
archivedLoading,
|
|
5967
|
+
hasMoreArchived: enabled ? hasMoreArchived : false,
|
|
5677
5968
|
error,
|
|
5678
5969
|
refresh,
|
|
5679
5970
|
create,
|
|
5680
5971
|
rename,
|
|
5972
|
+
setArchived,
|
|
5973
|
+
loadArchived,
|
|
5681
5974
|
switch: switchSession,
|
|
5682
5975
|
delete: deleteSession,
|
|
5683
5976
|
loadMore,
|
|
@@ -5698,6 +5991,19 @@ async function fetchSessionList(fetchImpl, url, headers) {
|
|
|
5698
5991
|
...typeof page.nextCursor === "string" ? { nextCursor: page.nextCursor } : {}
|
|
5699
5992
|
};
|
|
5700
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
|
+
}
|
|
5701
6007
|
function toAddressedSessionSummary(value) {
|
|
5702
6008
|
if (typeof value !== "object" || value === null) throw new Error("invalid addressed session summary");
|
|
5703
6009
|
const record = value;
|
|
@@ -5719,7 +6025,8 @@ function toAddressedSessionSummary(value) {
|
|
|
5719
6025
|
...typeof agentTypeId === "string" ? { agentTypeId } : {},
|
|
5720
6026
|
...typeof record.nativeSessionId === "string" ? { nativeSessionId: record.nativeSessionId } : {},
|
|
5721
6027
|
...typeof record.hasAssistantReply === "boolean" ? { hasAssistantReply: record.hasAssistantReply } : {},
|
|
5722
|
-
...addressedStatus ? { status: addressedStatus } : {}
|
|
6028
|
+
...addressedStatus ? { status: addressedStatus } : {},
|
|
6029
|
+
...record.archived === true ? { archived: true } : {}
|
|
5723
6030
|
};
|
|
5724
6031
|
}
|
|
5725
6032
|
function addressedCreatedSession(value, expectedAgentTypeId, title) {
|
|
@@ -5773,6 +6080,13 @@ function remoteSessionOptionsIdentity(options) {
|
|
|
5773
6080
|
} : void 0
|
|
5774
6081
|
});
|
|
5775
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
|
+
}
|
|
5776
6090
|
function mergeSessions(...lists) {
|
|
5777
6091
|
const seen = /* @__PURE__ */ new Set();
|
|
5778
6092
|
const merged = [];
|
|
@@ -5999,7 +6313,7 @@ function sortByUpdatedDesc(a, b) {
|
|
|
5999
6313
|
return a.id.localeCompare(b.id);
|
|
6000
6314
|
}
|
|
6001
6315
|
|
|
6002
|
-
// ../../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
|
|
6003
6317
|
function fuzzyMatch(query, text) {
|
|
6004
6318
|
const queryLower = query.toLowerCase();
|
|
6005
6319
|
const textLower = text.toLowerCase();
|
|
@@ -6185,7 +6499,7 @@ function searchPiSessions(sessions, query, options = {}) {
|
|
|
6185
6499
|
|
|
6186
6500
|
// src/front/chat/components/PiConversationSurface.tsx
|
|
6187
6501
|
import { Skeleton } from "@hachej/boring-ui-kit";
|
|
6188
|
-
import { useCallback as
|
|
6502
|
+
import { useCallback as useCallback15, useEffect as useEffect16, useLayoutEffect as useLayoutEffect2, useRef as useRef11, useState as useState17 } from "react";
|
|
6189
6503
|
import { useStickToBottomContext as useStickToBottomContext2 } from "use-stick-to-bottom";
|
|
6190
6504
|
|
|
6191
6505
|
// src/front/primitives/conversation.tsx
|
|
@@ -6261,8 +6575,8 @@ var ConversationScrollButton = ({
|
|
|
6261
6575
|
};
|
|
6262
6576
|
|
|
6263
6577
|
// src/front/chat/components/ChatNotices.tsx
|
|
6264
|
-
import { AlertCircleIcon, ExternalLinkIcon as ExternalLinkIcon2,
|
|
6265
|
-
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";
|
|
6266
6580
|
|
|
6267
6581
|
// src/front/chat/components/noticeStyles.ts
|
|
6268
6582
|
function noticeSurfaceClass(level, className) {
|
|
@@ -6496,7 +6810,15 @@ function composerBlockerActionIcon(actionId) {
|
|
|
6496
6810
|
if (actionId === "cancel") return /* @__PURE__ */ jsx15(XIcon2, { className: "size-3.5", "aria-hidden": "true" });
|
|
6497
6811
|
return null;
|
|
6498
6812
|
}
|
|
6499
|
-
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;
|
|
6500
6822
|
return /* @__PURE__ */ jsxs14(
|
|
6501
6823
|
"div",
|
|
6502
6824
|
{
|
|
@@ -6506,7 +6828,7 @@ function QueuedComposerNotice({ followUps, onEdit }) {
|
|
|
6506
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)]"
|
|
6507
6829
|
),
|
|
6508
6830
|
children: [
|
|
6509
|
-
/* @__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: [
|
|
6510
6832
|
/* @__PURE__ */ jsxs14("div", { className: "font-medium text-[color:var(--foreground)]", children: [
|
|
6511
6833
|
followUps.length,
|
|
6512
6834
|
" queued follow-up",
|
|
@@ -6514,31 +6836,73 @@ function QueuedComposerNotice({ followUps, onEdit }) {
|
|
|
6514
6836
|
] }),
|
|
6515
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(" - ") })
|
|
6516
6838
|
] }),
|
|
6517
|
-
/* @__PURE__ */
|
|
6518
|
-
|
|
6519
|
-
|
|
6520
|
-
|
|
6521
|
-
|
|
6522
|
-
|
|
6523
|
-
|
|
6524
|
-
|
|
6525
|
-
|
|
6526
|
-
|
|
6527
|
-
|
|
6528
|
-
|
|
6529
|
-
|
|
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
|
+
] })
|
|
6530
6894
|
]
|
|
6531
6895
|
}
|
|
6532
6896
|
);
|
|
6533
6897
|
}
|
|
6534
6898
|
|
|
6535
6899
|
// src/front/chat/components/PiTimelineMessage.tsx
|
|
6536
|
-
import { useCallback as
|
|
6537
|
-
import { CheckIcon as
|
|
6538
|
-
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";
|
|
6539
6903
|
|
|
6540
6904
|
// src/front/primitives/attachments.tsx
|
|
6541
|
-
import { Button as
|
|
6905
|
+
import { Button as Button9, HoverCard, HoverCardContent, HoverCardTrigger } from "@hachej/boring-ui-kit";
|
|
6542
6906
|
import {
|
|
6543
6907
|
FileTextIcon as FileTextIcon2,
|
|
6544
6908
|
GlobeIcon,
|
|
@@ -6736,7 +7100,7 @@ var AttachmentRemove = ({
|
|
|
6736
7100
|
return null;
|
|
6737
7101
|
}
|
|
6738
7102
|
return /* @__PURE__ */ jsxs15(
|
|
6739
|
-
|
|
7103
|
+
Button9,
|
|
6740
7104
|
{
|
|
6741
7105
|
"aria-label": label,
|
|
6742
7106
|
className: cn(
|
|
@@ -6768,7 +7132,7 @@ var AttachmentRemove = ({
|
|
|
6768
7132
|
};
|
|
6769
7133
|
|
|
6770
7134
|
// src/front/primitives/message.tsx
|
|
6771
|
-
import { Button as
|
|
7135
|
+
import { Button as Button10, ButtonGroup, ButtonGroupText } from "@hachej/boring-ui-kit";
|
|
6772
7136
|
import {
|
|
6773
7137
|
Tooltip,
|
|
6774
7138
|
TooltipContent,
|
|
@@ -6780,23 +7144,228 @@ import {
|
|
|
6780
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";
|
|
6781
7145
|
|
|
6782
7146
|
// src/front/primitives/message.tsx
|
|
6783
|
-
import { cjk } from "@streamdown/cjk";
|
|
6784
|
-
import { code } from "@streamdown/code";
|
|
6785
|
-
import { math } from "@streamdown/math";
|
|
6786
|
-
import { mermaid } from "@streamdown/mermaid";
|
|
6787
7147
|
import { ChevronLeftIcon as ChevronLeftIcon2, ChevronRightIcon } from "lucide-react";
|
|
6788
7148
|
import {
|
|
6789
7149
|
createContext as createContext4,
|
|
6790
7150
|
memo as memo3,
|
|
6791
|
-
useCallback as
|
|
7151
|
+
useCallback as useCallback11,
|
|
6792
7152
|
useContext as useContext4,
|
|
6793
|
-
useEffect as
|
|
6794
|
-
useMemo as
|
|
6795
|
-
useState as
|
|
7153
|
+
useEffect as useEffect12,
|
|
7154
|
+
useMemo as useMemo8,
|
|
7155
|
+
useState as useState13
|
|
7156
|
+
} from "react";
|
|
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
|
|
6796
7241
|
} from "react";
|
|
6797
|
-
import {
|
|
7242
|
+
import { defaultRehypePlugins } from "streamdown";
|
|
6798
7243
|
import { jsx as jsx17, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
6799
|
-
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(
|
|
6800
7369
|
"div",
|
|
6801
7370
|
{
|
|
6802
7371
|
"data-boring-agent-message-role": from,
|
|
@@ -6812,7 +7381,7 @@ var MessageContent = ({
|
|
|
6812
7381
|
children,
|
|
6813
7382
|
className,
|
|
6814
7383
|
...props
|
|
6815
|
-
}) => /* @__PURE__ */
|
|
7384
|
+
}) => /* @__PURE__ */ jsx18(
|
|
6816
7385
|
"div",
|
|
6817
7386
|
{
|
|
6818
7387
|
className: cn(
|
|
@@ -6829,7 +7398,7 @@ var MessageActions = ({
|
|
|
6829
7398
|
className,
|
|
6830
7399
|
children,
|
|
6831
7400
|
...props
|
|
6832
|
-
}) => /* @__PURE__ */
|
|
7401
|
+
}) => /* @__PURE__ */ jsx18("div", { className: cn("flex items-center gap-1", className), ...props, children });
|
|
6833
7402
|
var MessageAction = ({
|
|
6834
7403
|
tooltip,
|
|
6835
7404
|
children,
|
|
@@ -6838,14 +7407,14 @@ var MessageAction = ({
|
|
|
6838
7407
|
size = "icon-sm",
|
|
6839
7408
|
...props
|
|
6840
7409
|
}) => {
|
|
6841
|
-
const button = /* @__PURE__ */
|
|
7410
|
+
const button = /* @__PURE__ */ jsxs17(Button10, { size, type: "button", variant, ...props, children: [
|
|
6842
7411
|
children,
|
|
6843
|
-
/* @__PURE__ */
|
|
7412
|
+
/* @__PURE__ */ jsx18("span", { className: "sr-only", children: label || tooltip })
|
|
6844
7413
|
] });
|
|
6845
7414
|
if (tooltip) {
|
|
6846
|
-
return /* @__PURE__ */
|
|
6847
|
-
/* @__PURE__ */
|
|
6848
|
-
/* @__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 }) })
|
|
6849
7418
|
] }) });
|
|
6850
7419
|
}
|
|
6851
7420
|
return button;
|
|
@@ -6853,7 +7422,6 @@ var MessageAction = ({
|
|
|
6853
7422
|
var MessageBranchContext = createContext4(
|
|
6854
7423
|
null
|
|
6855
7424
|
);
|
|
6856
|
-
var streamdownPlugins = { cjk, code, math, mermaid };
|
|
6857
7425
|
var DEFAULT_SHIKI_THEME = ["github-light", "github-dark-dimmed"];
|
|
6858
7426
|
function extractCodeBlockLanguage(children) {
|
|
6859
7427
|
if (!children) return void 0;
|
|
@@ -6884,11 +7452,11 @@ function extractCodeBlockText(children) {
|
|
|
6884
7452
|
return walk(children);
|
|
6885
7453
|
}
|
|
6886
7454
|
var MarkdownPre = ({ children, filename }) => {
|
|
6887
|
-
const
|
|
7455
|
+
const code = extractCodeBlockText(children).replace(/\n$/, "");
|
|
6888
7456
|
const language = extractCodeBlockLanguage(children);
|
|
6889
|
-
return /* @__PURE__ */
|
|
6890
|
-
/* @__PURE__ */
|
|
6891
|
-
/* @__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, {})
|
|
6892
7460
|
] }) });
|
|
6893
7461
|
};
|
|
6894
7462
|
var MarkdownCode = ({
|
|
@@ -6898,9 +7466,9 @@ var MarkdownCode = ({
|
|
|
6898
7466
|
...props
|
|
6899
7467
|
}) => {
|
|
6900
7468
|
if (inline === false) {
|
|
6901
|
-
return /* @__PURE__ */
|
|
7469
|
+
return /* @__PURE__ */ jsx18("code", { className, ...props, children });
|
|
6902
7470
|
}
|
|
6903
|
-
return /* @__PURE__ */
|
|
7471
|
+
return /* @__PURE__ */ jsx18(
|
|
6904
7472
|
"code",
|
|
6905
7473
|
{
|
|
6906
7474
|
className: cn(
|
|
@@ -6917,23 +7485,33 @@ var markdownComponents = {
|
|
|
6917
7485
|
code: MarkdownCode
|
|
6918
7486
|
};
|
|
6919
7487
|
var MessageResponse = memo3(
|
|
6920
|
-
({ className, shikiTheme, components, codeFilename, ...props }) =>
|
|
6921
|
-
|
|
6922
|
-
|
|
6923
|
-
|
|
6924
|
-
|
|
6925
|
-
|
|
6926
|
-
|
|
6927
|
-
|
|
6928
|
-
|
|
6929
|
-
|
|
6930
|
-
|
|
6931
|
-
|
|
6932
|
-
|
|
6933
|
-
|
|
6934
|
-
|
|
6935
|
-
|
|
6936
|
-
|
|
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
|
+
},
|
|
6937
7515
|
(prevProps, nextProps) => prevProps.children === nextProps.children && nextProps.isAnimating === prevProps.isAnimating && nextProps.components === prevProps.components && prevProps.codeFilename === nextProps.codeFilename
|
|
6938
7516
|
);
|
|
6939
7517
|
MessageResponse.displayName = "MessageResponse";
|
|
@@ -6945,27 +7523,23 @@ import {
|
|
|
6945
7523
|
CollapsibleContent as CollapsibleContent2,
|
|
6946
7524
|
CollapsibleTrigger as CollapsibleTrigger3
|
|
6947
7525
|
} from "@hachej/boring-ui-kit";
|
|
6948
|
-
import { cjk as cjk2 } from "@streamdown/cjk";
|
|
6949
|
-
import { code as code2 } from "@streamdown/code";
|
|
6950
|
-
import { math as math2 } from "@streamdown/math";
|
|
6951
|
-
import { mermaid as mermaid2 } from "@streamdown/mermaid";
|
|
6952
7526
|
import { BrainIcon, ChevronDownIcon as ChevronDownIcon3 } from "lucide-react";
|
|
6953
7527
|
import {
|
|
6954
7528
|
createContext as createContext5,
|
|
6955
7529
|
memo as memo5,
|
|
6956
|
-
useCallback as
|
|
7530
|
+
useCallback as useCallback12,
|
|
6957
7531
|
useContext as useContext5,
|
|
6958
|
-
useEffect as
|
|
6959
|
-
useMemo as
|
|
6960
|
-
useRef as
|
|
6961
|
-
useState as
|
|
7532
|
+
useEffect as useEffect13,
|
|
7533
|
+
useMemo as useMemo10,
|
|
7534
|
+
useRef as useRef9,
|
|
7535
|
+
useState as useState14
|
|
6962
7536
|
} from "react";
|
|
6963
|
-
import { Streamdown as
|
|
7537
|
+
import { Streamdown as Streamdown3 } from "streamdown";
|
|
6964
7538
|
|
|
6965
7539
|
// src/front/primitives/shimmer.tsx
|
|
6966
7540
|
import { motion } from "motion/react";
|
|
6967
|
-
import { memo as memo4, useMemo as
|
|
6968
|
-
import { jsx as
|
|
7541
|
+
import { memo as memo4, useMemo as useMemo9 } from "react";
|
|
7542
|
+
import { jsx as jsx19 } from "react/jsx-runtime";
|
|
6969
7543
|
var motionComponentCache = /* @__PURE__ */ new Map();
|
|
6970
7544
|
var getMotionComponent = (element) => {
|
|
6971
7545
|
let component = motionComponentCache.get(element);
|
|
@@ -6985,11 +7559,11 @@ var ShimmerComponent = ({
|
|
|
6985
7559
|
const MotionComponent = getMotionComponent(
|
|
6986
7560
|
Component
|
|
6987
7561
|
);
|
|
6988
|
-
const dynamicSpread =
|
|
7562
|
+
const dynamicSpread = useMemo9(
|
|
6989
7563
|
() => (children?.length ?? 0) * spread,
|
|
6990
7564
|
[children, spread]
|
|
6991
7565
|
);
|
|
6992
|
-
return /* @__PURE__ */
|
|
7566
|
+
return /* @__PURE__ */ jsx19(
|
|
6993
7567
|
MotionComponent,
|
|
6994
7568
|
{
|
|
6995
7569
|
animate: { backgroundPosition: "0% center" },
|
|
@@ -7015,7 +7589,7 @@ var ShimmerComponent = ({
|
|
|
7015
7589
|
var Shimmer = memo4(ShimmerComponent);
|
|
7016
7590
|
|
|
7017
7591
|
// src/front/primitives/reasoning.tsx
|
|
7018
|
-
import { Fragment as Fragment8, jsx as
|
|
7592
|
+
import { Fragment as Fragment8, jsx as jsx20, jsxs as jsxs18 } from "react/jsx-runtime";
|
|
7019
7593
|
var ReasoningContext = createContext5(null);
|
|
7020
7594
|
var useReasoning = () => {
|
|
7021
7595
|
const context = useContext5(ReasoningContext);
|
|
@@ -7049,10 +7623,10 @@ var Reasoning = memo5(
|
|
|
7049
7623
|
defaultProp: void 0,
|
|
7050
7624
|
prop: durationProp
|
|
7051
7625
|
});
|
|
7052
|
-
const hasEverStreamedRef =
|
|
7053
|
-
const [hasAutoClosed, setHasAutoClosed] =
|
|
7054
|
-
const startTimeRef =
|
|
7055
|
-
|
|
7626
|
+
const hasEverStreamedRef = useRef9(isStreaming);
|
|
7627
|
+
const [hasAutoClosed, setHasAutoClosed] = useState14(false);
|
|
7628
|
+
const startTimeRef = useRef9(null);
|
|
7629
|
+
useEffect13(() => {
|
|
7056
7630
|
if (isStreaming) {
|
|
7057
7631
|
hasEverStreamedRef.current = true;
|
|
7058
7632
|
if (startTimeRef.current === null) {
|
|
@@ -7063,12 +7637,12 @@ var Reasoning = memo5(
|
|
|
7063
7637
|
startTimeRef.current = null;
|
|
7064
7638
|
}
|
|
7065
7639
|
}, [isStreaming, setDuration]);
|
|
7066
|
-
|
|
7640
|
+
useEffect13(() => {
|
|
7067
7641
|
if (isStreaming && !isOpen && !isExplicitlyClosed) {
|
|
7068
7642
|
setIsOpen(true);
|
|
7069
7643
|
}
|
|
7070
7644
|
}, [isStreaming, isOpen, setIsOpen, isExplicitlyClosed]);
|
|
7071
|
-
|
|
7645
|
+
useEffect13(() => {
|
|
7072
7646
|
if (hasEverStreamedRef.current && autoClose && !isStreaming && isOpen && !hasAutoClosed) {
|
|
7073
7647
|
const timer = setTimeout(() => {
|
|
7074
7648
|
setIsOpen(false);
|
|
@@ -7077,17 +7651,17 @@ var Reasoning = memo5(
|
|
|
7077
7651
|
return () => clearTimeout(timer);
|
|
7078
7652
|
}
|
|
7079
7653
|
}, [isStreaming, isOpen, setIsOpen, hasAutoClosed, autoClose]);
|
|
7080
|
-
const handleOpenChange =
|
|
7654
|
+
const handleOpenChange = useCallback12(
|
|
7081
7655
|
(newOpen) => {
|
|
7082
7656
|
setIsOpen(newOpen);
|
|
7083
7657
|
},
|
|
7084
7658
|
[setIsOpen]
|
|
7085
7659
|
);
|
|
7086
|
-
const contextValue =
|
|
7660
|
+
const contextValue = useMemo10(
|
|
7087
7661
|
() => ({ duration, isOpen, isStreaming, setIsOpen }),
|
|
7088
7662
|
[duration, isOpen, isStreaming, setIsOpen]
|
|
7089
7663
|
);
|
|
7090
|
-
return /* @__PURE__ */
|
|
7664
|
+
return /* @__PURE__ */ jsx20(ReasoningContext.Provider, { value: contextValue, children: /* @__PURE__ */ jsx20(
|
|
7091
7665
|
Collapsible2,
|
|
7092
7666
|
{
|
|
7093
7667
|
className: cn("not-prose mb-2", className),
|
|
@@ -7101,12 +7675,12 @@ var Reasoning = memo5(
|
|
|
7101
7675
|
);
|
|
7102
7676
|
var defaultGetThinkingMessage = (isStreaming, duration) => {
|
|
7103
7677
|
if (isStreaming || duration === 0) {
|
|
7104
|
-
return /* @__PURE__ */
|
|
7678
|
+
return /* @__PURE__ */ jsx20(Shimmer, { duration: 1, children: "thinking" });
|
|
7105
7679
|
}
|
|
7106
7680
|
if (duration === void 0) {
|
|
7107
|
-
return /* @__PURE__ */
|
|
7681
|
+
return /* @__PURE__ */ jsx20("span", { children: "thoughts" });
|
|
7108
7682
|
}
|
|
7109
|
-
return /* @__PURE__ */
|
|
7683
|
+
return /* @__PURE__ */ jsxs18("span", { children: [
|
|
7110
7684
|
"thoughts \xB7 ",
|
|
7111
7685
|
duration,
|
|
7112
7686
|
"s"
|
|
@@ -7120,7 +7694,7 @@ var ReasoningTrigger = memo5(
|
|
|
7120
7694
|
...props
|
|
7121
7695
|
}) => {
|
|
7122
7696
|
const { isStreaming, isOpen, duration } = useReasoning();
|
|
7123
|
-
return /* @__PURE__ */
|
|
7697
|
+
return /* @__PURE__ */ jsx20(
|
|
7124
7698
|
CollapsibleTrigger3,
|
|
7125
7699
|
{
|
|
7126
7700
|
className: cn(
|
|
@@ -7128,10 +7702,10 @@ var ReasoningTrigger = memo5(
|
|
|
7128
7702
|
className
|
|
7129
7703
|
),
|
|
7130
7704
|
...props,
|
|
7131
|
-
children: children ?? /* @__PURE__ */
|
|
7132
|
-
/* @__PURE__ */
|
|
7705
|
+
children: children ?? /* @__PURE__ */ jsxs18(Fragment8, { children: [
|
|
7706
|
+
/* @__PURE__ */ jsx20(BrainIcon, { className: "size-3" }),
|
|
7133
7707
|
getThinkingMessage(isStreaming, duration),
|
|
7134
|
-
/* @__PURE__ */
|
|
7708
|
+
/* @__PURE__ */ jsx20(
|
|
7135
7709
|
ChevronDownIcon3,
|
|
7136
7710
|
{
|
|
7137
7711
|
className: cn(
|
|
@@ -7145,20 +7719,22 @@ var ReasoningTrigger = memo5(
|
|
|
7145
7719
|
);
|
|
7146
7720
|
}
|
|
7147
7721
|
);
|
|
7148
|
-
var streamdownPlugins2 = { cjk: cjk2, code: code2, math: math2, mermaid: mermaid2 };
|
|
7149
7722
|
var ReasoningContent = memo5(
|
|
7150
|
-
({ className, children, ...props }) =>
|
|
7151
|
-
|
|
7152
|
-
|
|
7153
|
-
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
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
|
+
}
|
|
7162
7738
|
);
|
|
7163
7739
|
Reasoning.displayName = "Reasoning";
|
|
7164
7740
|
ReasoningTrigger.displayName = "ReasoningTrigger";
|
|
@@ -7166,7 +7742,7 @@ ReasoningContent.displayName = "ReasoningContent";
|
|
|
7166
7742
|
|
|
7167
7743
|
// src/front/primitives/tool-call-group.tsx
|
|
7168
7744
|
import { ChevronDownIcon as ChevronDownIcon4 } from "lucide-react";
|
|
7169
|
-
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";
|
|
7170
7746
|
import { Collapsible as Collapsible3, CollapsibleContent as CollapsibleContent3, CollapsibleTrigger as CollapsibleTrigger4 } from "@hachej/boring-ui-kit";
|
|
7171
7747
|
|
|
7172
7748
|
// src/front/primitives/tool-call-group-state.ts
|
|
@@ -7205,7 +7781,7 @@ var TOOL_GROUP_VISUAL_PRESENTATION = {
|
|
|
7205
7781
|
};
|
|
7206
7782
|
|
|
7207
7783
|
// src/front/primitives/tool-call-group.tsx
|
|
7208
|
-
import { jsx as
|
|
7784
|
+
import { jsx as jsx21, jsxs as jsxs19 } from "react/jsx-runtime";
|
|
7209
7785
|
function isInputRunningState(state) {
|
|
7210
7786
|
return state === "input-streaming" || state === "input-available";
|
|
7211
7787
|
}
|
|
@@ -7255,7 +7831,7 @@ function resolveVisualState({
|
|
|
7255
7831
|
return "settled";
|
|
7256
7832
|
}
|
|
7257
7833
|
var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
7258
|
-
const toolParts =
|
|
7834
|
+
const toolParts = useMemo11(() => tools.map(({ part, key }) => {
|
|
7259
7835
|
const toolPart = toToolPart(part);
|
|
7260
7836
|
return toolPart ? { part: toolPart, key } : null;
|
|
7261
7837
|
}).filter((entry) => Boolean(entry)), [tools]);
|
|
@@ -7264,8 +7840,8 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7264
7840
|
const hasAborted = toolParts.some(({ part }) => part.state === "aborted") && !workspaceNotReady;
|
|
7265
7841
|
const hasRunningTool = toolParts.some(({ part }) => isInputRunningState(part.state) && !getWorkspaceNotReadyStatus(part.output));
|
|
7266
7842
|
const approvalNeeded = toolParts.some(({ part }) => isApprovalRequestedState(part.state));
|
|
7267
|
-
const [isOpen, setIsOpen] =
|
|
7268
|
-
const handleOpenChange =
|
|
7843
|
+
const [isOpen, setIsOpen] = useState15(false);
|
|
7844
|
+
const handleOpenChange = useCallback13((open) => setIsOpen(open), []);
|
|
7269
7845
|
const visualState = resolveVisualState({
|
|
7270
7846
|
hasRunningTool,
|
|
7271
7847
|
approvalNeeded,
|
|
@@ -7274,10 +7850,10 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7274
7850
|
hasAborted
|
|
7275
7851
|
});
|
|
7276
7852
|
const isRunning = visualState === RUNNING_TOOL_GROUP_VISUAL_STATE;
|
|
7277
|
-
const [elapsedSeconds, setElapsedSeconds] =
|
|
7278
|
-
const title =
|
|
7853
|
+
const [elapsedSeconds, setElapsedSeconds] = useState15(0);
|
|
7854
|
+
const title = useMemo11(() => buildTitle(toolParts.map(({ part }) => part), visualState), [toolParts, visualState]);
|
|
7279
7855
|
const elapsedLabel = isRunning ? `Running ${formatElapsed(elapsedSeconds)}` : null;
|
|
7280
|
-
|
|
7856
|
+
useEffect14(() => {
|
|
7281
7857
|
if (!isRunning) {
|
|
7282
7858
|
setElapsedSeconds(0);
|
|
7283
7859
|
return;
|
|
@@ -7294,7 +7870,7 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7294
7870
|
const { renderer } = resolveToolRendererForPart(part, mergedToolRenderers);
|
|
7295
7871
|
return renderer.presentation === "inline" ? [key] : [];
|
|
7296
7872
|
}));
|
|
7297
|
-
return /* @__PURE__ */
|
|
7873
|
+
return /* @__PURE__ */ jsxs19(
|
|
7298
7874
|
Collapsible3,
|
|
7299
7875
|
{
|
|
7300
7876
|
open: isOpen,
|
|
@@ -7305,9 +7881,9 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7305
7881
|
toolParts.map(({ part, key }) => {
|
|
7306
7882
|
if (!inlineToolKeys.has(key)) return null;
|
|
7307
7883
|
const { renderer, part: resolvedPart, resolution } = resolveToolRendererForPart(part, mergedToolRenderers);
|
|
7308
|
-
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);
|
|
7309
7885
|
}),
|
|
7310
|
-
/* @__PURE__ */
|
|
7886
|
+
/* @__PURE__ */ jsxs19(
|
|
7311
7887
|
CollapsibleTrigger4,
|
|
7312
7888
|
{
|
|
7313
7889
|
"aria-label": `Tool calls: ${title}`,
|
|
@@ -7319,7 +7895,7 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7319
7895
|
TOOL_GROUP_VISUAL_PRESENTATION[visualState].triggerClassName
|
|
7320
7896
|
),
|
|
7321
7897
|
children: [
|
|
7322
|
-
/* @__PURE__ */
|
|
7898
|
+
/* @__PURE__ */ jsx21("span", { className: "flex size-4 shrink-0 items-center justify-center", "aria-hidden": "true", children: /* @__PURE__ */ jsx21(
|
|
7323
7899
|
"span",
|
|
7324
7900
|
{
|
|
7325
7901
|
"data-boring-agent-part": "tool-group-state-dot",
|
|
@@ -7329,10 +7905,10 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7329
7905
|
)
|
|
7330
7906
|
}
|
|
7331
7907
|
) }),
|
|
7332
|
-
/* @__PURE__ */
|
|
7333
|
-
elapsedLabel ? /* @__PURE__ */
|
|
7334
|
-
/* @__PURE__ */
|
|
7335
|
-
/* @__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(
|
|
7336
7912
|
ChevronDownIcon4,
|
|
7337
7913
|
{
|
|
7338
7914
|
className: cn(
|
|
@@ -7344,19 +7920,19 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7344
7920
|
]
|
|
7345
7921
|
}
|
|
7346
7922
|
),
|
|
7347
|
-
/* @__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(
|
|
7348
7924
|
"div",
|
|
7349
7925
|
{
|
|
7350
7926
|
"data-boring-agent-part": "tool-group-details",
|
|
7351
7927
|
className: "relative mt-1.5 w-full max-w-2xl pl-[18px]",
|
|
7352
7928
|
children: [
|
|
7353
|
-
/* @__PURE__ */
|
|
7354
|
-
/* @__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 }) => {
|
|
7355
7931
|
const { renderer, part: resolvedPart, resolution } = resolveToolRendererForPart(
|
|
7356
7932
|
part,
|
|
7357
7933
|
inlineToolKeys.has(key) ? {} : mergedToolRenderers
|
|
7358
7934
|
);
|
|
7359
|
-
return /* @__PURE__ */
|
|
7935
|
+
return /* @__PURE__ */ jsx21(
|
|
7360
7936
|
"div",
|
|
7361
7937
|
{
|
|
7362
7938
|
className: "min-w-0",
|
|
@@ -7378,19 +7954,19 @@ var ToolCallGroup = memo6(({ tools, mergedToolRenderers }) => {
|
|
|
7378
7954
|
ToolCallGroup.displayName = "ToolCallGroup";
|
|
7379
7955
|
|
|
7380
7956
|
// src/front/chat/messageContributions.tsx
|
|
7381
|
-
import { createContext as createContext6, createElement, useContext as useContext6, useMemo as
|
|
7382
|
-
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";
|
|
7383
7959
|
var ChatMessageContributionContext = createContext6([]);
|
|
7384
7960
|
function ChatMessageContributionProvider({
|
|
7385
7961
|
contribution,
|
|
7386
7962
|
children
|
|
7387
7963
|
}) {
|
|
7388
7964
|
const parent = useContext6(ChatMessageContributionContext);
|
|
7389
|
-
const contributions =
|
|
7965
|
+
const contributions = useMemo12(
|
|
7390
7966
|
() => [contribution, ...parent.filter((entry) => entry.id !== contribution.id)],
|
|
7391
7967
|
[contribution, parent]
|
|
7392
7968
|
);
|
|
7393
|
-
return /* @__PURE__ */
|
|
7969
|
+
return /* @__PURE__ */ jsx22(ChatMessageContributionContext.Provider, { value: contributions, children });
|
|
7394
7970
|
}
|
|
7395
7971
|
function useCustomChatMessage(message) {
|
|
7396
7972
|
const contributions = useContext6(ChatMessageContributionContext);
|
|
@@ -7407,7 +7983,7 @@ function ChatMessageContributionBoundary({
|
|
|
7407
7983
|
|
|
7408
7984
|
// src/front/chat/components/MessageMentions.tsx
|
|
7409
7985
|
import { Children, cloneElement, isValidElement as isValidElement2 } from "react";
|
|
7410
|
-
import { Fragment as Fragment9, jsx as
|
|
7986
|
+
import { Fragment as Fragment9, jsx as jsx23 } from "react/jsx-runtime";
|
|
7411
7987
|
var TERMINAL_BOUNDARY = String.raw`(?=$|\s|[.,;!?)}\]"'”’]+(?=$|\s))`;
|
|
7412
7988
|
var PREFIX_BOUNDARY = String.raw`(^|[\s(\[{"'“‘])`;
|
|
7413
7989
|
function escapeRegExp2(value) {
|
|
@@ -7516,7 +8092,7 @@ function MessageMentions({
|
|
|
7516
8092
|
}).map((segment, segmentIndex) => {
|
|
7517
8093
|
if (!segment.mention) return segment.text;
|
|
7518
8094
|
const actionLabel = mentionActionLabel(segment.mention);
|
|
7519
|
-
return /* @__PURE__ */
|
|
8095
|
+
return /* @__PURE__ */ jsx23(
|
|
7520
8096
|
"button",
|
|
7521
8097
|
{
|
|
7522
8098
|
type: "button",
|
|
@@ -7542,7 +8118,7 @@ function MessageMentions({
|
|
|
7542
8118
|
return cloneElement(
|
|
7543
8119
|
element,
|
|
7544
8120
|
void 0,
|
|
7545
|
-
/* @__PURE__ */
|
|
8121
|
+
/* @__PURE__ */ jsx23(
|
|
7546
8122
|
MessageMentions,
|
|
7547
8123
|
{
|
|
7548
8124
|
catalog,
|
|
@@ -7560,19 +8136,19 @@ function MessageMentions({
|
|
|
7560
8136
|
return nodes.map(decorate);
|
|
7561
8137
|
}
|
|
7562
8138
|
function createMessageMentionMarkdownComponents(catalog, onActivate) {
|
|
7563
|
-
const decorate = (children) => /* @__PURE__ */
|
|
8139
|
+
const decorate = (children) => /* @__PURE__ */ jsx23(MessageMentions, { catalog, onActivate, children });
|
|
7564
8140
|
const paragraph = ({ node: _node, children, ...props }) => {
|
|
7565
8141
|
const content = Children.toArray(children).filter((child) => child !== null && child !== "");
|
|
7566
8142
|
if (content.length === 1 && isValidElement2(content[0])) {
|
|
7567
8143
|
const child = content[0];
|
|
7568
|
-
if (child.props.node?.tagName === "img") return /* @__PURE__ */
|
|
7569
|
-
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 });
|
|
7570
8146
|
}
|
|
7571
|
-
return /* @__PURE__ */
|
|
8147
|
+
return /* @__PURE__ */ jsx23("p", { ...props, children: decorate(children) });
|
|
7572
8148
|
};
|
|
7573
|
-
const tableHeader = ({ node: _node, children, className, ...props }) => /* @__PURE__ */
|
|
7574
|
-
const tableCell = ({ node: _node, children, className, ...props }) => /* @__PURE__ */
|
|
7575
|
-
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) });
|
|
7576
8152
|
const headingClasses = {
|
|
7577
8153
|
h1: "text-3xl",
|
|
7578
8154
|
h2: "text-2xl",
|
|
@@ -7581,8 +8157,8 @@ function createMessageMentionMarkdownComponents(catalog, onActivate) {
|
|
|
7581
8157
|
h5: "text-base",
|
|
7582
8158
|
h6: "text-sm"
|
|
7583
8159
|
};
|
|
7584
|
-
const heading = (Tag) => ({ node: _node, children, className, ...props }) => /* @__PURE__ */
|
|
7585
|
-
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(
|
|
7586
8162
|
"code",
|
|
7587
8163
|
{
|
|
7588
8164
|
...props,
|
|
@@ -7606,7 +8182,7 @@ function createMessageMentionMarkdownComponents(catalog, onActivate) {
|
|
|
7606
8182
|
}
|
|
7607
8183
|
|
|
7608
8184
|
// src/front/chat/components/PiTimelineMessage.tsx
|
|
7609
|
-
import { jsx as
|
|
8185
|
+
import { jsx as jsx24, jsxs as jsxs20 } from "react/jsx-runtime";
|
|
7610
8186
|
var EMPTY_MENTION_CATALOG = { commands: [], skills: [], files: false };
|
|
7611
8187
|
var COLLAPSIBLE_TOOL_NAMES = /* @__PURE__ */ new Set([
|
|
7612
8188
|
"read",
|
|
@@ -7622,7 +8198,7 @@ function isCollapsibleTool(part) {
|
|
|
7622
8198
|
return part.type === "tool-call" && COLLAPSIBLE_TOOL_NAMES.has(part.toolName);
|
|
7623
8199
|
}
|
|
7624
8200
|
function PiTimelineMessage(props) {
|
|
7625
|
-
return /* @__PURE__ */
|
|
8201
|
+
return /* @__PURE__ */ jsx24(ChatMessageContributionBoundary, { message: props.message, children: /* @__PURE__ */ jsx24(DefaultPiTimelineMessage, { ...props }) });
|
|
7626
8202
|
}
|
|
7627
8203
|
function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts, toolRenderers, mentionCatalog = EMPTY_MENTION_CATALOG, onMentionActivate }) {
|
|
7628
8204
|
const role = message.role;
|
|
@@ -7632,7 +8208,7 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7632
8208
|
const finalParts = groupRenderableParts(message);
|
|
7633
8209
|
const attachmentSummaryPaths = role === "user" ? attachmentPathsFromTextParts(textParts) : [];
|
|
7634
8210
|
const openArtifact = useOpenArtifact();
|
|
7635
|
-
const effectiveMentionCatalog =
|
|
8211
|
+
const effectiveMentionCatalog = useMemo13(() => ({
|
|
7636
8212
|
commands: mentionCatalog.commands,
|
|
7637
8213
|
skills: mentionCatalog.skills,
|
|
7638
8214
|
files: mentionCatalog.files && Boolean(openArtifact)
|
|
@@ -7642,9 +8218,9 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7642
8218
|
...effectiveMentionCatalog.skills.map((skill) => `skill:${skill.name}:${skill.commandName}`),
|
|
7643
8219
|
effectiveMentionCatalog.files ? "files:enabled" : "files:disabled"
|
|
7644
8220
|
].join("|");
|
|
7645
|
-
const mentionActivateRef =
|
|
8221
|
+
const mentionActivateRef = useRef10(onMentionActivate);
|
|
7646
8222
|
mentionActivateRef.current = onMentionActivate;
|
|
7647
|
-
const activateCurrentMention =
|
|
8223
|
+
const activateCurrentMention = useCallback14((mention) => {
|
|
7648
8224
|
if (mention.kind === "file") {
|
|
7649
8225
|
openArtifact?.(mention.path);
|
|
7650
8226
|
return;
|
|
@@ -7654,12 +8230,12 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7654
8230
|
const hasMentions = effectiveMentionCatalog.files || effectiveMentionCatalog.commands.length > 0 || effectiveMentionCatalog.skills.length > 0;
|
|
7655
8231
|
const messageIsStreaming = isAssistant && isLast && (isStreaming || message.status === "streaming");
|
|
7656
8232
|
const mentionsEnabled = Boolean(isAssistant && !messageIsStreaming && hasMentions);
|
|
7657
|
-
const mentionMarkdownComponents =
|
|
8233
|
+
const mentionMarkdownComponents = useMemo13(
|
|
7658
8234
|
() => mentionsEnabled ? createMessageMentionMarkdownComponents(effectiveMentionCatalog, activateCurrentMention) : void 0,
|
|
7659
8235
|
[activateCurrentMention, effectiveMentionCatalog, mentionSignature, mentionsEnabled]
|
|
7660
8236
|
);
|
|
7661
8237
|
const shouldReserveStreamingActions = messageIsStreaming;
|
|
7662
|
-
return /* @__PURE__ */
|
|
8238
|
+
return /* @__PURE__ */ jsxs20(
|
|
7663
8239
|
Message,
|
|
7664
8240
|
{
|
|
7665
8241
|
from: role,
|
|
@@ -7668,8 +8244,8 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7668
8244
|
"data-boring-agent-message-role": role,
|
|
7669
8245
|
"data-boring-agent-message-status": message.status,
|
|
7670
8246
|
children: [
|
|
7671
|
-
/* @__PURE__ */
|
|
7672
|
-
fileParts.length > 0 ? /* @__PURE__ */
|
|
8247
|
+
/* @__PURE__ */ jsxs20(MessageContent, { children: [
|
|
8248
|
+
fileParts.length > 0 ? /* @__PURE__ */ jsx24(
|
|
7673
8249
|
Attachments,
|
|
7674
8250
|
{
|
|
7675
8251
|
variant: role === "user" ? "inline" : "list",
|
|
@@ -7694,7 +8270,7 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7694
8270
|
event.preventDefault();
|
|
7695
8271
|
openAttachment();
|
|
7696
8272
|
};
|
|
7697
|
-
return /* @__PURE__ */
|
|
8273
|
+
return /* @__PURE__ */ jsxs20(
|
|
7698
8274
|
Attachment,
|
|
7699
8275
|
{
|
|
7700
8276
|
data: toAttachmentData(file, `file-${message.id}-${index}`),
|
|
@@ -7708,8 +8284,8 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7708
8284
|
onKeyDown: openAttachmentFromKeyboard
|
|
7709
8285
|
} : void 0,
|
|
7710
8286
|
children: [
|
|
7711
|
-
/* @__PURE__ */
|
|
7712
|
-
/* @__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" })
|
|
7713
8289
|
]
|
|
7714
8290
|
},
|
|
7715
8291
|
`file-${message.id}-${index}`
|
|
@@ -7719,7 +8295,7 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7719
8295
|
) : null,
|
|
7720
8296
|
finalParts.map((item, index) => {
|
|
7721
8297
|
if (item.kind === "reasoning") {
|
|
7722
|
-
return /* @__PURE__ */
|
|
8298
|
+
return /* @__PURE__ */ jsx24(
|
|
7723
8299
|
TimelineReasoningPart,
|
|
7724
8300
|
{
|
|
7725
8301
|
item,
|
|
@@ -7729,15 +8305,15 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7729
8305
|
);
|
|
7730
8306
|
}
|
|
7731
8307
|
if (item.kind === "tool-group") {
|
|
7732
|
-
return /* @__PURE__ */
|
|
8308
|
+
return /* @__PURE__ */ jsx24("div", { "data-boring-agent-part": "message-tools", children: /* @__PURE__ */ jsx24(ToolCallGroup, { tools: item.tools, mergedToolRenderers: toolRenderers }) }, item.key);
|
|
7733
8309
|
}
|
|
7734
8310
|
if (item.kind === "tool-plain") {
|
|
7735
|
-
return /* @__PURE__ */
|
|
8311
|
+
return /* @__PURE__ */ jsx24("div", { "data-boring-agent-part": "message-tools", children: /* @__PURE__ */ jsx24(PlainToolCard, { part: item.part, renderers: toolRenderers }) }, item.key);
|
|
7736
8312
|
}
|
|
7737
8313
|
if (item.part.type === "text") {
|
|
7738
8314
|
const text = textForMessageDisplay(item.part.text, role);
|
|
7739
8315
|
if (!text) return null;
|
|
7740
|
-
return /* @__PURE__ */
|
|
8316
|
+
return /* @__PURE__ */ jsx24("div", { "data-boring-agent-part": "message-text", children: /* @__PURE__ */ jsx24(
|
|
7741
8317
|
MessageResponse,
|
|
7742
8318
|
{
|
|
7743
8319
|
components: mentionMarkdownComponents,
|
|
@@ -7749,12 +8325,12 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7749
8325
|
) }, item.key);
|
|
7750
8326
|
}
|
|
7751
8327
|
if (item.part.type === "notice") {
|
|
7752
|
-
return /* @__PURE__ */
|
|
8328
|
+
return /* @__PURE__ */ jsx24(NoticeBubble, { level: item.part.level, text: item.part.text }, item.key);
|
|
7753
8329
|
}
|
|
7754
8330
|
return null;
|
|
7755
8331
|
})
|
|
7756
8332
|
] }),
|
|
7757
|
-
isAssistant && (textParts.length > 0 || shouldReserveStreamingActions) ? /* @__PURE__ */
|
|
8333
|
+
isAssistant && (textParts.length > 0 || shouldReserveStreamingActions) ? /* @__PURE__ */ jsx24(
|
|
7758
8334
|
MessageActionsBar,
|
|
7759
8335
|
{
|
|
7760
8336
|
text: textParts.map((part) => part.text).join("\n\n"),
|
|
@@ -7766,20 +8342,20 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7766
8342
|
);
|
|
7767
8343
|
}
|
|
7768
8344
|
function TimelineReasoningPart({ item, showThoughts }) {
|
|
7769
|
-
const [manualOpen, setManualOpen] =
|
|
8345
|
+
const [manualOpen, setManualOpen] = useState16(null);
|
|
7770
8346
|
const isStreaming = item.state === "streaming";
|
|
7771
8347
|
const isOpen = manualOpen ?? showThoughts;
|
|
7772
|
-
|
|
8348
|
+
useEffect15(() => {
|
|
7773
8349
|
setManualOpen(null);
|
|
7774
8350
|
}, [showThoughts]);
|
|
7775
|
-
const handleOpenChange =
|
|
8351
|
+
const handleOpenChange = useCallback14((open) => {
|
|
7776
8352
|
setManualOpen(open);
|
|
7777
8353
|
}, []);
|
|
7778
|
-
const toggleManualOpen =
|
|
8354
|
+
const toggleManualOpen = useCallback14((event) => {
|
|
7779
8355
|
event.preventDefault();
|
|
7780
8356
|
setManualOpen((open) => !(open ?? showThoughts));
|
|
7781
8357
|
}, [showThoughts]);
|
|
7782
|
-
return /* @__PURE__ */
|
|
8358
|
+
return /* @__PURE__ */ jsxs20(
|
|
7783
8359
|
Reasoning,
|
|
7784
8360
|
{
|
|
7785
8361
|
"data-boring-agent-part": "message-reasoning",
|
|
@@ -7789,15 +8365,15 @@ function TimelineReasoningPart({ item, showThoughts }) {
|
|
|
7789
8365
|
onOpenChange: handleOpenChange,
|
|
7790
8366
|
autoClose: false,
|
|
7791
8367
|
children: [
|
|
7792
|
-
/* @__PURE__ */
|
|
8368
|
+
/* @__PURE__ */ jsx24(
|
|
7793
8369
|
ReasoningTrigger,
|
|
7794
8370
|
{
|
|
7795
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",
|
|
7796
|
-
getThinkingMessage: () => /* @__PURE__ */
|
|
8372
|
+
getThinkingMessage: () => /* @__PURE__ */ jsx24("span", { children: "Reasoning" }),
|
|
7797
8373
|
onClick: toggleManualOpen
|
|
7798
8374
|
}
|
|
7799
8375
|
),
|
|
7800
|
-
/* @__PURE__ */
|
|
8376
|
+
/* @__PURE__ */ jsx24(ReasoningContent, { children: item.text })
|
|
7801
8377
|
]
|
|
7802
8378
|
}
|
|
7803
8379
|
);
|
|
@@ -7806,7 +8382,7 @@ function PlainToolCard({ part, renderers }) {
|
|
|
7806
8382
|
const toolPart = toToolPart(part);
|
|
7807
8383
|
if (!toolPart) return null;
|
|
7808
8384
|
const { renderer, part: resolved, resolution } = resolveToolRendererForPart(toolPart, renderers);
|
|
7809
|
-
return /* @__PURE__ */
|
|
8385
|
+
return /* @__PURE__ */ jsx24(
|
|
7810
8386
|
"div",
|
|
7811
8387
|
{
|
|
7812
8388
|
"data-tool-call-id": resolved.toolCallId,
|
|
@@ -7864,13 +8440,13 @@ function codeFilenameForPart(parts, index) {
|
|
|
7864
8440
|
return typeof path === "string" && path.trim() ? path : void 0;
|
|
7865
8441
|
}
|
|
7866
8442
|
function NoticeBubble({ level, text }) {
|
|
7867
|
-
return /* @__PURE__ */
|
|
8443
|
+
return /* @__PURE__ */ jsx24(
|
|
7868
8444
|
"div",
|
|
7869
8445
|
{
|
|
7870
8446
|
"data-boring-agent-part": "message-notice",
|
|
7871
8447
|
"data-notice-level": level,
|
|
7872
8448
|
className: noticeSurfaceClass(level, "text-xs"),
|
|
7873
|
-
children: /* @__PURE__ */
|
|
8449
|
+
children: /* @__PURE__ */ jsx24("div", { className: noticeTextClass(), children: text })
|
|
7874
8450
|
}
|
|
7875
8451
|
);
|
|
7876
8452
|
}
|
|
@@ -7911,7 +8487,7 @@ function MessageActionsBar({
|
|
|
7911
8487
|
text,
|
|
7912
8488
|
visible = true
|
|
7913
8489
|
}) {
|
|
7914
|
-
const [copied, setCopied] =
|
|
8490
|
+
const [copied, setCopied] = useState16(false);
|
|
7915
8491
|
const markCopied = () => {
|
|
7916
8492
|
setCopied(true);
|
|
7917
8493
|
setTimeout(() => setCopied(false), 1500);
|
|
@@ -7949,7 +8525,7 @@ function MessageActionsBar({
|
|
|
7949
8525
|
"focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-[color:var(--accent)]/40"
|
|
7950
8526
|
);
|
|
7951
8527
|
const hiddenActionProps = visible ? {} : { tabIndex: -1 };
|
|
7952
|
-
return /* @__PURE__ */
|
|
8528
|
+
return /* @__PURE__ */ jsx24(
|
|
7953
8529
|
"div",
|
|
7954
8530
|
{
|
|
7955
8531
|
"aria-hidden": !visible,
|
|
@@ -7957,8 +8533,8 @@ function MessageActionsBar({
|
|
|
7957
8533
|
"flex min-h-8 items-center gap-1 -mt-1 text-xs text-muted-foreground transition-opacity duration-200",
|
|
7958
8534
|
visible ? "opacity-100" : "pointer-events-none opacity-0"
|
|
7959
8535
|
),
|
|
7960
|
-
children: /* @__PURE__ */
|
|
7961
|
-
|
|
8536
|
+
children: /* @__PURE__ */ jsx24(
|
|
8537
|
+
Button11,
|
|
7962
8538
|
{
|
|
7963
8539
|
type: "button",
|
|
7964
8540
|
variant: "ghost",
|
|
@@ -7968,7 +8544,7 @@ function MessageActionsBar({
|
|
|
7968
8544
|
"aria-label": copied ? "Copied" : "Copy message",
|
|
7969
8545
|
title: copied ? "Copied" : "Copy",
|
|
7970
8546
|
...hiddenActionProps,
|
|
7971
|
-
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" })
|
|
7972
8548
|
}
|
|
7973
8549
|
)
|
|
7974
8550
|
}
|
|
@@ -7989,7 +8565,7 @@ function partKey(messageId, part, index) {
|
|
|
7989
8565
|
}
|
|
7990
8566
|
|
|
7991
8567
|
// src/front/chat/components/PiConversationSurface.tsx
|
|
7992
|
-
import { jsx as
|
|
8568
|
+
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
7993
8569
|
var TRANSCRIPT_WINDOW = 60;
|
|
7994
8570
|
var TRANSCRIPT_WINDOW_STEP = 40;
|
|
7995
8571
|
var LOAD_OLDER_THRESHOLD_PX = 320;
|
|
@@ -8017,17 +8593,17 @@ function PiConversationSurface({
|
|
|
8017
8593
|
const total = messageItems.length;
|
|
8018
8594
|
const historyEmpty = messages.length === 0;
|
|
8019
8595
|
const terminalError = hasTerminalChatError(runtimeNotices, historyEmpty);
|
|
8020
|
-
const [visibleCount, setVisibleCount] =
|
|
8021
|
-
|
|
8596
|
+
const [visibleCount, setVisibleCount] = useState17(TRANSCRIPT_WINDOW);
|
|
8597
|
+
useEffect16(() => {
|
|
8022
8598
|
setVisibleCount(TRANSCRIPT_WINDOW);
|
|
8023
8599
|
}, [windowResetKey]);
|
|
8024
8600
|
const hasOlder = total > visibleCount;
|
|
8025
8601
|
const visibleItems = hasOlder ? messageItems.slice(total - visibleCount) : messageItems;
|
|
8026
8602
|
const olderCount = hasOlder ? total - visibleCount : 0;
|
|
8027
|
-
const loadOlder =
|
|
8603
|
+
const loadOlder = useCallback15(() => {
|
|
8028
8604
|
setVisibleCount((count) => count + TRANSCRIPT_WINDOW_STEP);
|
|
8029
8605
|
}, []);
|
|
8030
|
-
return /* @__PURE__ */
|
|
8606
|
+
return /* @__PURE__ */ jsxs21(
|
|
8031
8607
|
Conversation,
|
|
8032
8608
|
{
|
|
8033
8609
|
className: emptyHero ? cn("flex-none", runtimeNotices.length > 0 ? "max-h-[45vh]" : "max-h-[20vh]") : "flex-1",
|
|
@@ -8035,13 +8611,13 @@ function PiConversationSurface({
|
|
|
8035
8611
|
"aria-live": "polite",
|
|
8036
8612
|
onScrollToBottomReady,
|
|
8037
8613
|
children: [
|
|
8038
|
-
/* @__PURE__ */
|
|
8614
|
+
/* @__PURE__ */ jsxs21(ConversationContent, { className: cn(
|
|
8039
8615
|
"mx-auto flex w-full flex-col gap-6",
|
|
8040
8616
|
chrome ? "max-w-3xl px-6 py-8" : "max-w-[680px] px-4 py-4",
|
|
8041
8617
|
emptyHero && "py-4 text-center"
|
|
8042
8618
|
), children: [
|
|
8043
|
-
messages.length === 0 && emptyStateHydrating && !terminalError ? /* @__PURE__ */
|
|
8044
|
-
messages.length === 0 && !emptyStateHydrating && !terminalError ? /* @__PURE__ */
|
|
8619
|
+
messages.length === 0 && emptyStateHydrating && !terminalError ? /* @__PURE__ */ jsx25(ConversationHistoryLoadingState, {}) : null,
|
|
8620
|
+
messages.length === 0 && !emptyStateHydrating && !terminalError ? /* @__PURE__ */ jsx25(
|
|
8045
8621
|
ChatEmptyState,
|
|
8046
8622
|
{
|
|
8047
8623
|
eyebrow: emptyState?.eyebrow,
|
|
@@ -8059,8 +8635,8 @@ function PiConversationSurface({
|
|
|
8059
8635
|
}
|
|
8060
8636
|
}
|
|
8061
8637
|
) : null,
|
|
8062
|
-
hasOlder ? /* @__PURE__ */
|
|
8063
|
-
visibleItems.map(({ message, key }, index) => /* @__PURE__ */
|
|
8638
|
+
hasOlder ? /* @__PURE__ */ jsx25(TranscriptHistoryLoader, { olderCount, onLoadOlder: loadOlder }) : null,
|
|
8639
|
+
visibleItems.map(({ message, key }, index) => /* @__PURE__ */ jsx25(
|
|
8064
8640
|
PiTimelineMessage,
|
|
8065
8641
|
{
|
|
8066
8642
|
message,
|
|
@@ -8073,16 +8649,16 @@ function PiConversationSurface({
|
|
|
8073
8649
|
},
|
|
8074
8650
|
key
|
|
8075
8651
|
)),
|
|
8076
|
-
/* @__PURE__ */
|
|
8652
|
+
/* @__PURE__ */ jsx25(RuntimeNoticeMessages, { notices: runtimeNotices, onDismiss: onDismissNotice, renderAction: renderNoticeAction, historyEmpty })
|
|
8077
8653
|
] }),
|
|
8078
|
-
/* @__PURE__ */
|
|
8654
|
+
/* @__PURE__ */ jsx25(ConversationScrollButton, {})
|
|
8079
8655
|
]
|
|
8080
8656
|
}
|
|
8081
8657
|
);
|
|
8082
8658
|
}
|
|
8083
8659
|
function ConversationHistoryLoadingState() {
|
|
8084
8660
|
const skeletonClassName = "motion-reduce:animate-none";
|
|
8085
|
-
return /* @__PURE__ */
|
|
8661
|
+
return /* @__PURE__ */ jsxs21(
|
|
8086
8662
|
"div",
|
|
8087
8663
|
{
|
|
8088
8664
|
role: "status",
|
|
@@ -8091,21 +8667,21 @@ function ConversationHistoryLoadingState() {
|
|
|
8091
8667
|
"data-boring-agent-part": "chat-history-loading",
|
|
8092
8668
|
className: "flex flex-col gap-7 py-4",
|
|
8093
8669
|
children: [
|
|
8094
|
-
/* @__PURE__ */
|
|
8095
|
-
/* @__PURE__ */
|
|
8096
|
-
/* @__PURE__ */
|
|
8097
|
-
/* @__PURE__ */
|
|
8098
|
-
/* @__PURE__ */
|
|
8099
|
-
/* @__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) })
|
|
8100
8676
|
] })
|
|
8101
8677
|
] }),
|
|
8102
|
-
/* @__PURE__ */
|
|
8103
|
-
/* @__PURE__ */
|
|
8104
|
-
/* @__PURE__ */
|
|
8105
|
-
/* @__PURE__ */
|
|
8106
|
-
/* @__PURE__ */
|
|
8107
|
-
/* @__PURE__ */
|
|
8108
|
-
/* @__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) })
|
|
8109
8685
|
] })
|
|
8110
8686
|
] })
|
|
8111
8687
|
]
|
|
@@ -8114,9 +8690,9 @@ function ConversationHistoryLoadingState() {
|
|
|
8114
8690
|
}
|
|
8115
8691
|
function TranscriptHistoryLoader({ olderCount, onLoadOlder }) {
|
|
8116
8692
|
const { scrollRef } = useStickToBottomContext2();
|
|
8117
|
-
const pendingAnchor =
|
|
8118
|
-
const armed =
|
|
8119
|
-
|
|
8693
|
+
const pendingAnchor = useRef11(null);
|
|
8694
|
+
const armed = useRef11(true);
|
|
8695
|
+
useEffect16(() => {
|
|
8120
8696
|
const el = scrollRef.current;
|
|
8121
8697
|
if (!el) return;
|
|
8122
8698
|
const onScroll = () => {
|
|
@@ -8139,7 +8715,7 @@ function TranscriptHistoryLoader({ olderCount, onLoadOlder }) {
|
|
|
8139
8715
|
}
|
|
8140
8716
|
if (el.scrollTop > LOAD_OLDER_THRESHOLD_PX) armed.current = true;
|
|
8141
8717
|
});
|
|
8142
|
-
return /* @__PURE__ */
|
|
8718
|
+
return /* @__PURE__ */ jsx25("div", { className: "flex justify-center", "data-boring-agent-part": "transcript-load-older", children: /* @__PURE__ */ jsxs21(
|
|
8143
8719
|
"button",
|
|
8144
8720
|
{
|
|
8145
8721
|
type: "button",
|
|
@@ -8176,14 +8752,14 @@ function buildMessageRenderItems(messages) {
|
|
|
8176
8752
|
}
|
|
8177
8753
|
|
|
8178
8754
|
// src/front/chat/components/PiChatComposerSurface.tsx
|
|
8179
|
-
import { useCallback as
|
|
8755
|
+
import { useCallback as useCallback17, useLayoutEffect as useLayoutEffect3 } from "react";
|
|
8180
8756
|
import { motion as motion2, useReducedMotion } from "motion/react";
|
|
8181
8757
|
|
|
8182
8758
|
// src/front/composer/PluginUpdateStatus.tsx
|
|
8183
|
-
import { useEffect as
|
|
8759
|
+
import { useEffect as useEffect17, useRef as useRef12 } from "react";
|
|
8184
8760
|
|
|
8185
8761
|
// src/front/composer/ComposerStatusBanner.tsx
|
|
8186
|
-
import { jsx as
|
|
8762
|
+
import { jsx as jsx26, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
8187
8763
|
function ComposerStatusBanner({
|
|
8188
8764
|
tone,
|
|
8189
8765
|
dataAttribute,
|
|
@@ -8200,7 +8776,7 @@ function ComposerStatusBanner({
|
|
|
8200
8776
|
}) {
|
|
8201
8777
|
const toneAttr = { [dataAttribute]: tone };
|
|
8202
8778
|
if (tone === "running") {
|
|
8203
|
-
return /* @__PURE__ */
|
|
8779
|
+
return /* @__PURE__ */ jsxs22(
|
|
8204
8780
|
"div",
|
|
8205
8781
|
{
|
|
8206
8782
|
...toneAttr,
|
|
@@ -8212,14 +8788,14 @@ function ComposerStatusBanner({
|
|
|
8212
8788
|
maxWidthClassName
|
|
8213
8789
|
),
|
|
8214
8790
|
children: [
|
|
8215
|
-
/* @__PURE__ */
|
|
8216
|
-
/* @__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 })
|
|
8217
8793
|
]
|
|
8218
8794
|
}
|
|
8219
8795
|
);
|
|
8220
8796
|
}
|
|
8221
8797
|
if (tone === "success") {
|
|
8222
|
-
return /* @__PURE__ */
|
|
8798
|
+
return /* @__PURE__ */ jsxs22(
|
|
8223
8799
|
"div",
|
|
8224
8800
|
{
|
|
8225
8801
|
...toneAttr,
|
|
@@ -8231,13 +8807,13 @@ function ComposerStatusBanner({
|
|
|
8231
8807
|
maxWidthClassName
|
|
8232
8808
|
),
|
|
8233
8809
|
children: [
|
|
8234
|
-
/* @__PURE__ */
|
|
8235
|
-
/* @__PURE__ */
|
|
8236
|
-
/* @__PURE__ */
|
|
8237
|
-
/* @__PURE__ */
|
|
8238
|
-
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
|
|
8239
8815
|
] }),
|
|
8240
|
-
onDismiss ? /* @__PURE__ */
|
|
8816
|
+
onDismiss ? /* @__PURE__ */ jsx26(
|
|
8241
8817
|
"button",
|
|
8242
8818
|
{
|
|
8243
8819
|
type: "button",
|
|
@@ -8253,7 +8829,7 @@ function ComposerStatusBanner({
|
|
|
8253
8829
|
}
|
|
8254
8830
|
);
|
|
8255
8831
|
}
|
|
8256
|
-
return /* @__PURE__ */
|
|
8832
|
+
return /* @__PURE__ */ jsxs22(
|
|
8257
8833
|
"div",
|
|
8258
8834
|
{
|
|
8259
8835
|
...toneAttr,
|
|
@@ -8265,10 +8841,10 @@ function ComposerStatusBanner({
|
|
|
8265
8841
|
maxWidthClassName
|
|
8266
8842
|
),
|
|
8267
8843
|
children: [
|
|
8268
|
-
/* @__PURE__ */
|
|
8269
|
-
/* @__PURE__ */
|
|
8270
|
-
/* @__PURE__ */
|
|
8271
|
-
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(
|
|
8272
8848
|
"button",
|
|
8273
8849
|
{
|
|
8274
8850
|
type: "button",
|
|
@@ -8277,7 +8853,7 @@ function ComposerStatusBanner({
|
|
|
8277
8853
|
children: retryLabel
|
|
8278
8854
|
}
|
|
8279
8855
|
) : null,
|
|
8280
|
-
onDismiss ? /* @__PURE__ */
|
|
8856
|
+
onDismiss ? /* @__PURE__ */ jsx26(
|
|
8281
8857
|
"button",
|
|
8282
8858
|
{
|
|
8283
8859
|
type: "button",
|
|
@@ -8288,14 +8864,14 @@ function ComposerStatusBanner({
|
|
|
8288
8864
|
}
|
|
8289
8865
|
) : null
|
|
8290
8866
|
] }),
|
|
8291
|
-
message ? /* @__PURE__ */
|
|
8867
|
+
message ? /* @__PURE__ */ jsx26("pre", { className: "mt-2 whitespace-pre-wrap break-words text-[11px] text-destructive/90", children: message }) : null
|
|
8292
8868
|
]
|
|
8293
8869
|
}
|
|
8294
8870
|
);
|
|
8295
8871
|
}
|
|
8296
8872
|
|
|
8297
8873
|
// src/front/composer/PluginUpdateStatus.tsx
|
|
8298
|
-
import { jsx as
|
|
8874
|
+
import { jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
8299
8875
|
function PluginUpdateStatus({
|
|
8300
8876
|
state,
|
|
8301
8877
|
onDismiss,
|
|
@@ -8303,12 +8879,12 @@ function PluginUpdateStatus({
|
|
|
8303
8879
|
successAutoDismissMs = 1400,
|
|
8304
8880
|
maxWidthClassName = "max-w-3xl"
|
|
8305
8881
|
}) {
|
|
8306
|
-
const onDismissRef =
|
|
8307
|
-
|
|
8882
|
+
const onDismissRef = useRef12(onDismiss);
|
|
8883
|
+
useEffect17(() => {
|
|
8308
8884
|
onDismissRef.current = onDismiss;
|
|
8309
8885
|
}, [onDismiss]);
|
|
8310
8886
|
const successDismissKey = state?.kind === "success" ? `${state.reloaded}:${(state.restartWarnings?.length ?? 0) > 0 || (state.diagnostics?.length ?? 0) > 0}` : null;
|
|
8311
|
-
|
|
8887
|
+
useEffect17(() => {
|
|
8312
8888
|
if (!state || state.kind !== "success" || successAutoDismissMs <= 0) return;
|
|
8313
8889
|
const hasWarningsOrDiagnostics = (state.restartWarnings?.length ?? 0) > 0 || (state.diagnostics?.length ?? 0) > 0;
|
|
8314
8890
|
if (hasWarningsOrDiagnostics) return;
|
|
@@ -8317,7 +8893,7 @@ function PluginUpdateStatus({
|
|
|
8317
8893
|
}, [state?.kind, successDismissKey, successAutoDismissMs]);
|
|
8318
8894
|
if (!state) return null;
|
|
8319
8895
|
if (state.kind === "running") {
|
|
8320
|
-
return /* @__PURE__ */
|
|
8896
|
+
return /* @__PURE__ */ jsx27(
|
|
8321
8897
|
ComposerStatusBanner,
|
|
8322
8898
|
{
|
|
8323
8899
|
tone: "running",
|
|
@@ -8334,7 +8910,7 @@ function PluginUpdateStatus({
|
|
|
8334
8910
|
const hasWarningsOrDiagnostics = warnings.length > 0 || diagnostics.length > 0;
|
|
8335
8911
|
const title = state.reloaded ? hasWarningsOrDiagnostics ? "Reload finished with warnings" : "Reload complete" : "Reload queued";
|
|
8336
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;
|
|
8337
|
-
return /* @__PURE__ */
|
|
8913
|
+
return /* @__PURE__ */ jsxs23(
|
|
8338
8914
|
ComposerStatusBanner,
|
|
8339
8915
|
{
|
|
8340
8916
|
tone: "success",
|
|
@@ -8345,7 +8921,7 @@ function PluginUpdateStatus({
|
|
|
8345
8921
|
onDismiss,
|
|
8346
8922
|
dismissAriaLabel: "Dismiss plugin update status",
|
|
8347
8923
|
children: [
|
|
8348
|
-
diagnostics.length > 0 ? /* @__PURE__ */
|
|
8924
|
+
diagnostics.length > 0 ? /* @__PURE__ */ jsxs23(
|
|
8349
8925
|
"div",
|
|
8350
8926
|
{
|
|
8351
8927
|
"data-boring-plugin-update-diagnostics": "",
|
|
@@ -8354,24 +8930,24 @@ function PluginUpdateStatus({
|
|
|
8354
8930
|
"px-2 py-1.5 text-[11px] text-foreground"
|
|
8355
8931
|
),
|
|
8356
8932
|
children: [
|
|
8357
|
-
/* @__PURE__ */
|
|
8358
|
-
/* @__PURE__ */
|
|
8359
|
-
/* @__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: [
|
|
8360
8936
|
"Reload diagnostics for ",
|
|
8361
8937
|
diagnostics.length,
|
|
8362
8938
|
" extension",
|
|
8363
8939
|
diagnostics.length === 1 ? "" : "s"
|
|
8364
8940
|
] })
|
|
8365
8941
|
] }),
|
|
8366
|
-
/* @__PURE__ */
|
|
8367
|
-
/* @__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" }),
|
|
8368
8944
|
" \u2014 ",
|
|
8369
8945
|
diagnostic.message ?? "reload diagnostic"
|
|
8370
8946
|
] }, `${diagnostic.pluginId ?? diagnostic.source ?? "plugin"}-${index}`)) })
|
|
8371
8947
|
]
|
|
8372
8948
|
}
|
|
8373
8949
|
) : null,
|
|
8374
|
-
warnings.length > 0 ? /* @__PURE__ */
|
|
8950
|
+
warnings.length > 0 ? /* @__PURE__ */ jsxs23(
|
|
8375
8951
|
"div",
|
|
8376
8952
|
{
|
|
8377
8953
|
"data-boring-plugin-update-restart-warning": "",
|
|
@@ -8380,21 +8956,21 @@ function PluginUpdateStatus({
|
|
|
8380
8956
|
"px-2 py-1.5 text-[11px] text-foreground"
|
|
8381
8957
|
),
|
|
8382
8958
|
children: [
|
|
8383
|
-
/* @__PURE__ */
|
|
8384
|
-
/* @__PURE__ */
|
|
8385
|
-
/* @__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: [
|
|
8386
8962
|
"Restart needed for ",
|
|
8387
8963
|
warnings.length,
|
|
8388
8964
|
" extension",
|
|
8389
8965
|
warnings.length === 1 ? "" : "s"
|
|
8390
8966
|
] })
|
|
8391
8967
|
] }),
|
|
8392
|
-
/* @__PURE__ */
|
|
8393
|
-
/* @__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 }),
|
|
8394
8970
|
" \u2014 ",
|
|
8395
8971
|
w.surfaces.join(" + ")
|
|
8396
8972
|
] }, w.id)) }),
|
|
8397
|
-
/* @__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." })
|
|
8398
8974
|
]
|
|
8399
8975
|
}
|
|
8400
8976
|
) : null
|
|
@@ -8402,7 +8978,7 @@ function PluginUpdateStatus({
|
|
|
8402
8978
|
}
|
|
8403
8979
|
);
|
|
8404
8980
|
}
|
|
8405
|
-
return /* @__PURE__ */
|
|
8981
|
+
return /* @__PURE__ */ jsx27(
|
|
8406
8982
|
ComposerStatusBanner,
|
|
8407
8983
|
{
|
|
8408
8984
|
tone: "error",
|
|
@@ -8419,35 +8995,35 @@ function PluginUpdateStatus({
|
|
|
8419
8995
|
}
|
|
8420
8996
|
|
|
8421
8997
|
// src/front/composer/CommandRunStatus.tsx
|
|
8422
|
-
import { useEffect as
|
|
8423
|
-
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";
|
|
8424
9000
|
function CommandRunStatus({
|
|
8425
9001
|
state,
|
|
8426
9002
|
onDismiss,
|
|
8427
9003
|
successAutoDismissMs = 1400,
|
|
8428
9004
|
maxWidthClassName = "max-w-3xl"
|
|
8429
9005
|
}) {
|
|
8430
|
-
const onDismissRef =
|
|
8431
|
-
|
|
9006
|
+
const onDismissRef = useRef13(onDismiss);
|
|
9007
|
+
useEffect18(() => {
|
|
8432
9008
|
onDismissRef.current = onDismiss;
|
|
8433
9009
|
}, [onDismiss]);
|
|
8434
9010
|
const successKey = state?.kind === "success" ? `${state.runId}:${state.command}:${state.detail ?? ""}` : null;
|
|
8435
|
-
|
|
9011
|
+
useEffect18(() => {
|
|
8436
9012
|
if (!state || state.kind !== "success" || successAutoDismissMs <= 0) return;
|
|
8437
9013
|
const timeout = window.setTimeout(() => onDismissRef.current(), successAutoDismissMs);
|
|
8438
9014
|
return () => window.clearTimeout(timeout);
|
|
8439
9015
|
}, [state?.kind, successKey, successAutoDismissMs]);
|
|
8440
9016
|
if (!state) return null;
|
|
8441
9017
|
if (state.kind === "running") {
|
|
8442
|
-
return /* @__PURE__ */
|
|
9018
|
+
return /* @__PURE__ */ jsx28(
|
|
8443
9019
|
ComposerStatusBanner,
|
|
8444
9020
|
{
|
|
8445
9021
|
tone: "running",
|
|
8446
9022
|
dataAttribute: "data-boring-command-run",
|
|
8447
9023
|
maxWidthClassName,
|
|
8448
|
-
runningContent: state.command ? /* @__PURE__ */
|
|
9024
|
+
runningContent: state.command ? /* @__PURE__ */ jsxs24(Fragment10, { children: [
|
|
8449
9025
|
" Running ",
|
|
8450
|
-
/* @__PURE__ */
|
|
9026
|
+
/* @__PURE__ */ jsxs24("code", { className: "font-mono", children: [
|
|
8451
9027
|
"/",
|
|
8452
9028
|
state.command
|
|
8453
9029
|
] }),
|
|
@@ -8457,15 +9033,15 @@ function CommandRunStatus({
|
|
|
8457
9033
|
);
|
|
8458
9034
|
}
|
|
8459
9035
|
if (state.kind === "success") {
|
|
8460
|
-
return /* @__PURE__ */
|
|
9036
|
+
return /* @__PURE__ */ jsx28(
|
|
8461
9037
|
ComposerStatusBanner,
|
|
8462
9038
|
{
|
|
8463
9039
|
tone: "success",
|
|
8464
9040
|
dataAttribute: "data-boring-command-run",
|
|
8465
9041
|
maxWidthClassName,
|
|
8466
|
-
title: state.command ? /* @__PURE__ */
|
|
9042
|
+
title: state.command ? /* @__PURE__ */ jsxs24(Fragment10, { children: [
|
|
8467
9043
|
" Ran ",
|
|
8468
|
-
/* @__PURE__ */
|
|
9044
|
+
/* @__PURE__ */ jsxs24("code", { className: "font-mono", children: [
|
|
8469
9045
|
"/",
|
|
8470
9046
|
state.command
|
|
8471
9047
|
] }),
|
|
@@ -8477,15 +9053,15 @@ function CommandRunStatus({
|
|
|
8477
9053
|
}
|
|
8478
9054
|
);
|
|
8479
9055
|
}
|
|
8480
|
-
return /* @__PURE__ */
|
|
9056
|
+
return /* @__PURE__ */ jsx28(
|
|
8481
9057
|
ComposerStatusBanner,
|
|
8482
9058
|
{
|
|
8483
9059
|
tone: "error",
|
|
8484
9060
|
dataAttribute: "data-boring-command-run",
|
|
8485
9061
|
maxWidthClassName,
|
|
8486
|
-
title: state.command ? /* @__PURE__ */
|
|
9062
|
+
title: state.command ? /* @__PURE__ */ jsxs24(Fragment10, { children: [
|
|
8487
9063
|
" ",
|
|
8488
|
-
/* @__PURE__ */
|
|
9064
|
+
/* @__PURE__ */ jsxs24("code", { className: "font-mono", children: [
|
|
8489
9065
|
"/",
|
|
8490
9066
|
state.command
|
|
8491
9067
|
] }),
|
|
@@ -8499,8 +9075,8 @@ function CommandRunStatus({
|
|
|
8499
9075
|
}
|
|
8500
9076
|
|
|
8501
9077
|
// src/front/chatPanelComposerControls.tsx
|
|
8502
|
-
import { forwardRef, useEffect as
|
|
8503
|
-
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";
|
|
8504
9080
|
import {
|
|
8505
9081
|
Command,
|
|
8506
9082
|
CommandEmpty,
|
|
@@ -8533,7 +9109,7 @@ function displayProviderLabel(provider) {
|
|
|
8533
9109
|
}
|
|
8534
9110
|
|
|
8535
9111
|
// src/front/chatPanelComposerControls.tsx
|
|
8536
|
-
import { Fragment as Fragment11, jsx as
|
|
9112
|
+
import { Fragment as Fragment11, jsx as jsx29, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
8537
9113
|
var composerActionClass = cn(
|
|
8538
9114
|
"inline-flex h-8 items-center justify-center gap-1.5 rounded-[var(--radius-md)] border-0 bg-transparent",
|
|
8539
9115
|
"text-muted-foreground shadow-none transition-colors motion-reduce:transition-none",
|
|
@@ -8583,7 +9159,7 @@ function isTextInputTarget(target) {
|
|
|
8583
9159
|
return target instanceof HTMLInputElement;
|
|
8584
9160
|
}
|
|
8585
9161
|
function useDismissOnOutsidePointer(ref, onClose) {
|
|
8586
|
-
|
|
9162
|
+
useEffect19(() => {
|
|
8587
9163
|
if (!onClose) return;
|
|
8588
9164
|
const handler = (event) => {
|
|
8589
9165
|
const target = event.target;
|
|
@@ -8601,7 +9177,7 @@ function useDismissOnOutsidePointer(ref, onClose) {
|
|
|
8601
9177
|
}
|
|
8602
9178
|
function ThinkingLevelGlyph({ level }) {
|
|
8603
9179
|
const lit = level === "off" ? 0 : level === "low" ? 1 : level === "medium" ? 2 : 3;
|
|
8604
|
-
return /* @__PURE__ */
|
|
9180
|
+
return /* @__PURE__ */ jsx29(
|
|
8605
9181
|
"svg",
|
|
8606
9182
|
{
|
|
8607
9183
|
"aria-hidden": "true",
|
|
@@ -8610,7 +9186,7 @@ function ThinkingLevelGlyph({ level }) {
|
|
|
8610
9186
|
viewBox: "0 0 14 14",
|
|
8611
9187
|
fill: "none",
|
|
8612
9188
|
className: "shrink-0",
|
|
8613
|
-
children: [0, 1, 2].map((i) => /* @__PURE__ */
|
|
9189
|
+
children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx29(
|
|
8614
9190
|
"rect",
|
|
8615
9191
|
{
|
|
8616
9192
|
x: 2 + i * 4,
|
|
@@ -8662,7 +9238,7 @@ var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
|
|
|
8662
9238
|
const triggerDisplay = value ? `${triggerLabel} (${displayProviderLabel(value.provider)})` : triggerLabel;
|
|
8663
9239
|
const sessionDisplay = sessionModel && sessionTriggerLabel ? `${sessionTriggerLabel} (${displayProviderLabel(sessionModel.provider)})` : triggerDisplay;
|
|
8664
9240
|
const accessibleDisplay = isOverride && value ? `Current model: ${sessionDisplay}. Next-message override: ${triggerDisplay}` : `Current model: ${sessionDisplay}`;
|
|
8665
|
-
return /* @__PURE__ */
|
|
9241
|
+
return /* @__PURE__ */ jsx29(
|
|
8666
9242
|
"button",
|
|
8667
9243
|
{
|
|
8668
9244
|
ref,
|
|
@@ -8681,25 +9257,25 @@ var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
|
|
|
8681
9257
|
className
|
|
8682
9258
|
),
|
|
8683
9259
|
...props,
|
|
8684
|
-
children: trigger === "slash" ? /* @__PURE__ */
|
|
8685
|
-
/* @__PURE__ */
|
|
8686
|
-
/* @__PURE__ */
|
|
8687
|
-
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: [
|
|
8688
9264
|
" \xB7 ",
|
|
8689
9265
|
displayProviderLabel(sessionModel.provider)
|
|
8690
|
-
] }) : value ? /* @__PURE__ */
|
|
9266
|
+
] }) : value ? /* @__PURE__ */ jsxs25("span", { className: "shrink-0 text-muted-foreground", children: [
|
|
8691
9267
|
" \xB7 ",
|
|
8692
9268
|
displayProviderLabel(value.provider)
|
|
8693
9269
|
] }) : null,
|
|
8694
|
-
isOverride && value ? /* @__PURE__ */
|
|
9270
|
+
isOverride && value ? /* @__PURE__ */ jsxs25("span", { className: "shrink-0 text-amber-600 dark:text-amber-400", children: [
|
|
8695
9271
|
" \xB7 Next override: ",
|
|
8696
9272
|
triggerLabel,
|
|
8697
9273
|
" \xB7 ",
|
|
8698
9274
|
displayProviderLabel(value.provider)
|
|
8699
9275
|
] }) : null
|
|
8700
|
-
] }) : /* @__PURE__ */
|
|
8701
|
-
/* @__PURE__ */
|
|
8702
|
-
/* @__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" })
|
|
8703
9279
|
] })
|
|
8704
9280
|
}
|
|
8705
9281
|
);
|
|
@@ -8719,19 +9295,19 @@ function ModelPickerMenu({
|
|
|
8719
9295
|
const groupedOptions = [...groups.values()].flat();
|
|
8720
9296
|
const keyboardOptions = hideDefaultOption ? groupedOptions : [null, ...groupedOptions];
|
|
8721
9297
|
const selectedIndex = currentKey ? Math.max(0, keyboardOptions.findIndex((option) => option && encodeModelKey(option) === currentKey)) : 0;
|
|
8722
|
-
const [activeIndex, setActiveIndex] =
|
|
8723
|
-
const activeIndexRef =
|
|
8724
|
-
const menuRef =
|
|
9298
|
+
const [activeIndex, setActiveIndex] = useState18(selectedIndex);
|
|
9299
|
+
const activeIndexRef = useRef14(selectedIndex);
|
|
9300
|
+
const menuRef = useRef14(null);
|
|
8725
9301
|
useDismissOnOutsidePointer(menuRef, onClose);
|
|
8726
9302
|
const setKeyboardActiveIndex = (next) => {
|
|
8727
9303
|
const resolved = typeof next === "function" ? next(activeIndexRef.current) : next;
|
|
8728
9304
|
activeIndexRef.current = resolved;
|
|
8729
9305
|
setActiveIndex(resolved);
|
|
8730
9306
|
};
|
|
8731
|
-
|
|
9307
|
+
useEffect19(() => {
|
|
8732
9308
|
setKeyboardActiveIndex(selectedIndex);
|
|
8733
9309
|
}, [selectedIndex]);
|
|
8734
|
-
|
|
9310
|
+
useEffect19(() => {
|
|
8735
9311
|
const handler = (event) => {
|
|
8736
9312
|
if (event.key === "Escape") {
|
|
8737
9313
|
event.preventDefault();
|
|
@@ -8756,8 +9332,8 @@ function ModelPickerMenu({
|
|
|
8756
9332
|
}, [activeIndex, disabled, keyboardOptions, onChange, onClose]);
|
|
8757
9333
|
const optionIndexOffset = hideDefaultOption ? 0 : 1;
|
|
8758
9334
|
const optionIndexes = new Map(groupedOptions.map((option, index) => [encodeModelKey(option), index + optionIndexOffset]));
|
|
8759
|
-
return /* @__PURE__ */
|
|
8760
|
-
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(
|
|
8761
9337
|
CommandInput,
|
|
8762
9338
|
{
|
|
8763
9339
|
placeholder: "Search models\u2026",
|
|
@@ -8765,9 +9341,9 @@ function ModelPickerMenu({
|
|
|
8765
9341
|
className: "h-8 w-full border-0 bg-transparent text-sm outline-none focus:ring-0"
|
|
8766
9342
|
}
|
|
8767
9343
|
) }),
|
|
8768
|
-
/* @__PURE__ */
|
|
8769
|
-
/* @__PURE__ */
|
|
8770
|
-
!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(
|
|
8771
9347
|
CommandItem,
|
|
8772
9348
|
{
|
|
8773
9349
|
value: "Default model automatic auto",
|
|
@@ -8778,8 +9354,8 @@ function ModelPickerMenu({
|
|
|
8778
9354
|
},
|
|
8779
9355
|
className: selectorItemClass(!value || activeIndex === 0),
|
|
8780
9356
|
children: [
|
|
8781
|
-
/* @__PURE__ */
|
|
8782
|
-
|
|
9357
|
+
/* @__PURE__ */ jsx29(
|
|
9358
|
+
CheckIcon4,
|
|
8783
9359
|
{
|
|
8784
9360
|
className: cn(
|
|
8785
9361
|
"h-3.5 w-3.5 shrink-0",
|
|
@@ -8787,12 +9363,12 @@ function ModelPickerMenu({
|
|
|
8787
9363
|
)
|
|
8788
9364
|
}
|
|
8789
9365
|
),
|
|
8790
|
-
/* @__PURE__ */
|
|
8791
|
-
/* @__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" })
|
|
8792
9368
|
]
|
|
8793
9369
|
}
|
|
8794
9370
|
) }) : null,
|
|
8795
|
-
[...groups.entries()].map(([provider, list]) => /* @__PURE__ */
|
|
9371
|
+
[...groups.entries()].map(([provider, list]) => /* @__PURE__ */ jsx29(
|
|
8796
9372
|
CommandGroup,
|
|
8797
9373
|
{
|
|
8798
9374
|
heading: displayProviderLabel(provider),
|
|
@@ -8801,7 +9377,7 @@ function ModelPickerMenu({
|
|
|
8801
9377
|
const key = encodeModelKey(m);
|
|
8802
9378
|
const label = m.label || displayModelLabel(m.id);
|
|
8803
9379
|
const itemIndex = optionIndexes.get(key) ?? 0;
|
|
8804
|
-
return /* @__PURE__ */
|
|
9380
|
+
return /* @__PURE__ */ jsxs25(
|
|
8805
9381
|
CommandItem,
|
|
8806
9382
|
{
|
|
8807
9383
|
value: `${label} ${m.id} ${displayProviderLabel(m.provider)}`,
|
|
@@ -8812,8 +9388,8 @@ function ModelPickerMenu({
|
|
|
8812
9388
|
},
|
|
8813
9389
|
className: cn(selectorItemClass(key === currentKey || activeIndex === itemIndex)),
|
|
8814
9390
|
children: [
|
|
8815
|
-
/* @__PURE__ */
|
|
8816
|
-
|
|
9391
|
+
/* @__PURE__ */ jsx29(
|
|
9392
|
+
CheckIcon4,
|
|
8817
9393
|
{
|
|
8818
9394
|
className: cn(
|
|
8819
9395
|
"h-3.5 w-3.5 shrink-0",
|
|
@@ -8821,8 +9397,8 @@ function ModelPickerMenu({
|
|
|
8821
9397
|
)
|
|
8822
9398
|
}
|
|
8823
9399
|
),
|
|
8824
|
-
/* @__PURE__ */
|
|
8825
|
-
/* @__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 })
|
|
8826
9402
|
]
|
|
8827
9403
|
},
|
|
8828
9404
|
key
|
|
@@ -8847,12 +9423,12 @@ function ModelSelect({
|
|
|
8847
9423
|
ariaDescribedBy,
|
|
8848
9424
|
hideDefaultOption = false
|
|
8849
9425
|
}) {
|
|
8850
|
-
const [open, setOpen] =
|
|
8851
|
-
const previousOpenSignalRef =
|
|
8852
|
-
|
|
9426
|
+
const [open, setOpen] = useState18(false);
|
|
9427
|
+
const previousOpenSignalRef = useRef14(openSignal);
|
|
9428
|
+
useEffect19(() => {
|
|
8853
9429
|
if (disabled) setOpen(false);
|
|
8854
9430
|
}, [disabled]);
|
|
8855
|
-
|
|
9431
|
+
useEffect19(() => {
|
|
8856
9432
|
if (disabled || openSignal === void 0) {
|
|
8857
9433
|
previousOpenSignalRef.current = openSignal;
|
|
8858
9434
|
return;
|
|
@@ -8860,8 +9436,8 @@ function ModelSelect({
|
|
|
8860
9436
|
if (previousOpenSignalRef.current !== openSignal) setOpen(true);
|
|
8861
9437
|
previousOpenSignalRef.current = openSignal;
|
|
8862
9438
|
}, [disabled, openSignal]);
|
|
8863
|
-
return /* @__PURE__ */
|
|
8864
|
-
/* @__PURE__ */
|
|
9439
|
+
return /* @__PURE__ */ jsxs25(Popover, { open, onOpenChange: disabled ? void 0 : setOpen, children: [
|
|
9440
|
+
/* @__PURE__ */ jsx29(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(
|
|
8865
9441
|
ModelSelectTrigger,
|
|
8866
9442
|
{
|
|
8867
9443
|
value,
|
|
@@ -8875,7 +9451,7 @@ function ModelSelect({
|
|
|
8875
9451
|
"aria-describedby": ariaDescribedBy
|
|
8876
9452
|
}
|
|
8877
9453
|
) }),
|
|
8878
|
-
/* @__PURE__ */
|
|
9454
|
+
/* @__PURE__ */ jsx29(
|
|
8879
9455
|
PopoverContent,
|
|
8880
9456
|
{
|
|
8881
9457
|
align: trigger === "slash" ? "center" : "start",
|
|
@@ -8884,7 +9460,7 @@ function ModelSelect({
|
|
|
8884
9460
|
collisionPadding: 12,
|
|
8885
9461
|
"data-boring-agent": "",
|
|
8886
9462
|
className: cn("w-[min(92vw,340px)]", selectorContentClass),
|
|
8887
|
-
children: /* @__PURE__ */
|
|
9463
|
+
children: /* @__PURE__ */ jsx29(
|
|
8888
9464
|
ModelPickerMenu,
|
|
8889
9465
|
{
|
|
8890
9466
|
value,
|
|
@@ -8908,12 +9484,12 @@ function ThinkingSelect({
|
|
|
8908
9484
|
openSignal,
|
|
8909
9485
|
className
|
|
8910
9486
|
}) {
|
|
8911
|
-
const [open, setOpen] =
|
|
8912
|
-
const previousOpenSignalRef =
|
|
8913
|
-
|
|
9487
|
+
const [open, setOpen] = useState18(false);
|
|
9488
|
+
const previousOpenSignalRef = useRef14(openSignal);
|
|
9489
|
+
useEffect19(() => {
|
|
8914
9490
|
if (disabled) setOpen(false);
|
|
8915
9491
|
}, [disabled]);
|
|
8916
|
-
|
|
9492
|
+
useEffect19(() => {
|
|
8917
9493
|
if (disabled || openSignal === void 0) {
|
|
8918
9494
|
previousOpenSignalRef.current = openSignal;
|
|
8919
9495
|
return;
|
|
@@ -8921,8 +9497,8 @@ function ThinkingSelect({
|
|
|
8921
9497
|
if (previousOpenSignalRef.current !== openSignal) setOpen(true);
|
|
8922
9498
|
previousOpenSignalRef.current = openSignal;
|
|
8923
9499
|
}, [disabled, openSignal]);
|
|
8924
|
-
return /* @__PURE__ */
|
|
8925
|
-
/* @__PURE__ */
|
|
9500
|
+
return /* @__PURE__ */ jsxs25(Popover, { open, onOpenChange: disabled ? void 0 : setOpen, children: [
|
|
9501
|
+
/* @__PURE__ */ jsx29(PopoverTrigger, { asChild: true, children: /* @__PURE__ */ jsx29(
|
|
8926
9502
|
ThinkingSelectTrigger,
|
|
8927
9503
|
{
|
|
8928
9504
|
value,
|
|
@@ -8932,7 +9508,7 @@ function ThinkingSelect({
|
|
|
8932
9508
|
className
|
|
8933
9509
|
}
|
|
8934
9510
|
) }),
|
|
8935
|
-
/* @__PURE__ */
|
|
9511
|
+
/* @__PURE__ */ jsx29(
|
|
8936
9512
|
PopoverContent,
|
|
8937
9513
|
{
|
|
8938
9514
|
align: trigger === "slash" ? "center" : "end",
|
|
@@ -8941,7 +9517,7 @@ function ThinkingSelect({
|
|
|
8941
9517
|
collisionPadding: 12,
|
|
8942
9518
|
"data-boring-agent": "",
|
|
8943
9519
|
className: cn("w-[min(92vw,240px)]", selectorContentClass),
|
|
8944
|
-
children: /* @__PURE__ */
|
|
9520
|
+
children: /* @__PURE__ */ jsx29(
|
|
8945
9521
|
ThinkingPickerMenu,
|
|
8946
9522
|
{
|
|
8947
9523
|
value,
|
|
@@ -8964,7 +9540,7 @@ var ThinkingSelectTrigger = forwardRef(function ThinkingSelectTrigger2({
|
|
|
8964
9540
|
className,
|
|
8965
9541
|
...props
|
|
8966
9542
|
}, ref) {
|
|
8967
|
-
return /* @__PURE__ */
|
|
9543
|
+
return /* @__PURE__ */ jsxs25(
|
|
8968
9544
|
"button",
|
|
8969
9545
|
{
|
|
8970
9546
|
ref,
|
|
@@ -8985,13 +9561,13 @@ var ThinkingSelectTrigger = forwardRef(function ThinkingSelectTrigger2({
|
|
|
8985
9561
|
onClick,
|
|
8986
9562
|
...props,
|
|
8987
9563
|
children: [
|
|
8988
|
-
trigger === "button" ? /* @__PURE__ */
|
|
8989
|
-
trigger === "slash" ? /* @__PURE__ */
|
|
8990
|
-
/* @__PURE__ */
|
|
8991
|
-
/* @__PURE__ */
|
|
8992
|
-
] }) : /* @__PURE__ */
|
|
8993
|
-
/* @__PURE__ */
|
|
8994
|
-
/* @__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" })
|
|
8995
9571
|
] })
|
|
8996
9572
|
]
|
|
8997
9573
|
}
|
|
@@ -9005,19 +9581,19 @@ function ThinkingPickerMenu({
|
|
|
9005
9581
|
className
|
|
9006
9582
|
}) {
|
|
9007
9583
|
const selectedIndex = Math.max(0, THINKING_LEVELS.indexOf(value));
|
|
9008
|
-
const [activeIndex, setActiveIndex] =
|
|
9009
|
-
const activeIndexRef =
|
|
9010
|
-
const menuRef =
|
|
9584
|
+
const [activeIndex, setActiveIndex] = useState18(selectedIndex);
|
|
9585
|
+
const activeIndexRef = useRef14(selectedIndex);
|
|
9586
|
+
const menuRef = useRef14(null);
|
|
9011
9587
|
useDismissOnOutsidePointer(menuRef, onClose);
|
|
9012
9588
|
const setKeyboardActiveIndex = (next) => {
|
|
9013
9589
|
const resolved = typeof next === "function" ? next(activeIndexRef.current) : next;
|
|
9014
9590
|
activeIndexRef.current = resolved;
|
|
9015
9591
|
setActiveIndex(resolved);
|
|
9016
9592
|
};
|
|
9017
|
-
|
|
9593
|
+
useEffect19(() => {
|
|
9018
9594
|
setKeyboardActiveIndex(selectedIndex);
|
|
9019
9595
|
}, [selectedIndex]);
|
|
9020
|
-
|
|
9596
|
+
useEffect19(() => {
|
|
9021
9597
|
const handler = (event) => {
|
|
9022
9598
|
if (event.key === "Escape") {
|
|
9023
9599
|
event.preventDefault();
|
|
@@ -9040,7 +9616,7 @@ function ThinkingPickerMenu({
|
|
|
9040
9616
|
window.addEventListener("keydown", handler, { capture: true });
|
|
9041
9617
|
return () => window.removeEventListener("keydown", handler, { capture: true });
|
|
9042
9618
|
}, [activeIndex, disabled, onChange, onClose]);
|
|
9043
|
-
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(
|
|
9044
9620
|
CommandItem,
|
|
9045
9621
|
{
|
|
9046
9622
|
value: `Thinking ${THINKING_LEVEL_LABELS[level]} ${THINKING_LEVEL_DETAILS[level]}`,
|
|
@@ -9051,8 +9627,8 @@ function ThinkingPickerMenu({
|
|
|
9051
9627
|
},
|
|
9052
9628
|
className: selectorItemClass(level === value || index === activeIndex),
|
|
9053
9629
|
children: [
|
|
9054
|
-
/* @__PURE__ */
|
|
9055
|
-
|
|
9630
|
+
/* @__PURE__ */ jsx29(
|
|
9631
|
+
CheckIcon4,
|
|
9056
9632
|
{
|
|
9057
9633
|
className: cn(
|
|
9058
9634
|
"h-3.5 w-3.5 shrink-0",
|
|
@@ -9060,9 +9636,9 @@ function ThinkingPickerMenu({
|
|
|
9060
9636
|
)
|
|
9061
9637
|
}
|
|
9062
9638
|
),
|
|
9063
|
-
/* @__PURE__ */
|
|
9064
|
-
/* @__PURE__ */
|
|
9065
|
-
/* @__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] })
|
|
9066
9642
|
]
|
|
9067
9643
|
},
|
|
9068
9644
|
level
|
|
@@ -9103,7 +9679,7 @@ import {
|
|
|
9103
9679
|
XIcon as XIcon4
|
|
9104
9680
|
} from "lucide-react";
|
|
9105
9681
|
import { nanoid } from "nanoid";
|
|
9106
|
-
import { useCallback as
|
|
9682
|
+
import { useCallback as useCallback16, useEffect as useEffect20, useMemo as useMemo14, useRef as useRef15, useState as useState19 } from "react";
|
|
9107
9683
|
|
|
9108
9684
|
// src/front/primitives/prompt-input-context.ts
|
|
9109
9685
|
import { createContext as createContext7, useContext as useContext7 } from "react";
|
|
@@ -9138,12 +9714,12 @@ import {
|
|
|
9138
9714
|
TooltipTrigger as TooltipTrigger2
|
|
9139
9715
|
} from "@hachej/boring-ui-kit";
|
|
9140
9716
|
import { Children as Children2 } from "react";
|
|
9141
|
-
import { jsx as
|
|
9717
|
+
import { jsx as jsx30, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
9142
9718
|
var PromptInputFooter = ({
|
|
9143
9719
|
align = "block-end",
|
|
9144
9720
|
className,
|
|
9145
9721
|
...props
|
|
9146
|
-
}) => /* @__PURE__ */
|
|
9722
|
+
}) => /* @__PURE__ */ jsx30(
|
|
9147
9723
|
InputGroupAddon,
|
|
9148
9724
|
{
|
|
9149
9725
|
align,
|
|
@@ -9153,7 +9729,7 @@ var PromptInputFooter = ({
|
|
|
9153
9729
|
);
|
|
9154
9730
|
|
|
9155
9731
|
// src/front/primitives/prompt-input.tsx
|
|
9156
|
-
import { Fragment as Fragment12, jsx as
|
|
9732
|
+
import { Fragment as Fragment12, jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
9157
9733
|
var PromptInput = ({
|
|
9158
9734
|
className,
|
|
9159
9735
|
accept,
|
|
@@ -9170,14 +9746,14 @@ var PromptInput = ({
|
|
|
9170
9746
|
}) => {
|
|
9171
9747
|
const controller = useOptionalPromptInputController();
|
|
9172
9748
|
const usingProvider = !!controller;
|
|
9173
|
-
const providerTextValueRef =
|
|
9749
|
+
const providerTextValueRef = useRef15("");
|
|
9174
9750
|
if (usingProvider) {
|
|
9175
9751
|
providerTextValueRef.current = controller.textInput.value;
|
|
9176
9752
|
}
|
|
9177
|
-
const inputRef =
|
|
9178
|
-
const formRef =
|
|
9179
|
-
const [items, setItems] =
|
|
9180
|
-
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) => {
|
|
9181
9757
|
setItems((prev) => prev.map((f) => {
|
|
9182
9758
|
if (f.id !== id) return f;
|
|
9183
9759
|
if (f.url !== url && f.url.startsWith("blob:")) URL.revokeObjectURL(f.url);
|
|
@@ -9185,15 +9761,15 @@ var PromptInput = ({
|
|
|
9185
9761
|
}));
|
|
9186
9762
|
}, []);
|
|
9187
9763
|
const files = usingProvider ? controller.attachments.files : items;
|
|
9188
|
-
const [referencedSources, setReferencedSources] =
|
|
9189
|
-
const filesRef =
|
|
9190
|
-
|
|
9764
|
+
const [referencedSources, setReferencedSources] = useState19([]);
|
|
9765
|
+
const filesRef = useRef15(files);
|
|
9766
|
+
useEffect20(() => {
|
|
9191
9767
|
filesRef.current = files;
|
|
9192
9768
|
}, [files]);
|
|
9193
|
-
const openFileDialogLocal =
|
|
9769
|
+
const openFileDialogLocal = useCallback16(() => {
|
|
9194
9770
|
inputRef.current?.click();
|
|
9195
9771
|
}, []);
|
|
9196
|
-
const matchesAccept =
|
|
9772
|
+
const matchesAccept = useCallback16(
|
|
9197
9773
|
(f) => {
|
|
9198
9774
|
if (!accept || accept.trim() === "") {
|
|
9199
9775
|
return true;
|
|
@@ -9209,7 +9785,7 @@ var PromptInput = ({
|
|
|
9209
9785
|
},
|
|
9210
9786
|
[accept]
|
|
9211
9787
|
);
|
|
9212
|
-
const addLocal =
|
|
9788
|
+
const addLocal = useCallback16(
|
|
9213
9789
|
(fileList) => {
|
|
9214
9790
|
const incoming = [...fileList];
|
|
9215
9791
|
const accepted = incoming.filter((f) => matchesAccept(f));
|
|
@@ -9256,7 +9832,7 @@ var PromptInput = ({
|
|
|
9256
9832
|
},
|
|
9257
9833
|
[matchesAccept, maxFiles, maxFileSize, onError, items.length, onUploadFile, setFileUrlLocal]
|
|
9258
9834
|
);
|
|
9259
|
-
const removeLocal =
|
|
9835
|
+
const removeLocal = useCallback16(
|
|
9260
9836
|
(id) => setItems((prev) => {
|
|
9261
9837
|
const found = prev.find((file) => file.id === id);
|
|
9262
9838
|
if (found?.url.startsWith("blob:")) {
|
|
@@ -9266,7 +9842,7 @@ var PromptInput = ({
|
|
|
9266
9842
|
}),
|
|
9267
9843
|
[]
|
|
9268
9844
|
);
|
|
9269
|
-
const addWithProviderValidation =
|
|
9845
|
+
const addWithProviderValidation = useCallback16(
|
|
9270
9846
|
(fileList) => {
|
|
9271
9847
|
const incoming = [...fileList];
|
|
9272
9848
|
const accepted = incoming.filter((f) => matchesAccept(f));
|
|
@@ -9301,7 +9877,7 @@ var PromptInput = ({
|
|
|
9301
9877
|
},
|
|
9302
9878
|
[matchesAccept, maxFileSize, maxFiles, onError, files.length, controller]
|
|
9303
9879
|
);
|
|
9304
|
-
const clearAttachments =
|
|
9880
|
+
const clearAttachments = useCallback16(
|
|
9305
9881
|
() => usingProvider ? controller?.attachments.clear() : setItems((prev) => {
|
|
9306
9882
|
for (const file of prev) {
|
|
9307
9883
|
if (file.url.startsWith("blob:")) {
|
|
@@ -9312,29 +9888,29 @@ var PromptInput = ({
|
|
|
9312
9888
|
}),
|
|
9313
9889
|
[usingProvider, controller]
|
|
9314
9890
|
);
|
|
9315
|
-
const clearReferencedSources =
|
|
9891
|
+
const clearReferencedSources = useCallback16(
|
|
9316
9892
|
() => setReferencedSources([]),
|
|
9317
9893
|
[]
|
|
9318
9894
|
);
|
|
9319
9895
|
const add = usingProvider ? addWithProviderValidation : addLocal;
|
|
9320
9896
|
const remove = usingProvider ? controller.attachments.remove : removeLocal;
|
|
9321
9897
|
const openFileDialog = usingProvider ? controller.attachments.openFileDialog : openFileDialogLocal;
|
|
9322
|
-
const clear =
|
|
9898
|
+
const clear = useCallback16(() => {
|
|
9323
9899
|
clearAttachments();
|
|
9324
9900
|
clearReferencedSources();
|
|
9325
9901
|
}, [clearAttachments, clearReferencedSources]);
|
|
9326
|
-
|
|
9902
|
+
useEffect20(() => {
|
|
9327
9903
|
if (!usingProvider) {
|
|
9328
9904
|
return;
|
|
9329
9905
|
}
|
|
9330
9906
|
controller.__registerFileInput(inputRef, () => inputRef.current?.click());
|
|
9331
9907
|
}, [usingProvider, controller]);
|
|
9332
|
-
|
|
9908
|
+
useEffect20(() => {
|
|
9333
9909
|
if (syncHiddenInput && inputRef.current && files.length === 0) {
|
|
9334
9910
|
inputRef.current.value = "";
|
|
9335
9911
|
}
|
|
9336
9912
|
}, [files, syncHiddenInput]);
|
|
9337
|
-
|
|
9913
|
+
useEffect20(() => {
|
|
9338
9914
|
const form = formRef.current;
|
|
9339
9915
|
if (!form) {
|
|
9340
9916
|
return;
|
|
@@ -9362,7 +9938,7 @@ var PromptInput = ({
|
|
|
9362
9938
|
form.removeEventListener("drop", onDrop);
|
|
9363
9939
|
};
|
|
9364
9940
|
}, [add, globalDrop]);
|
|
9365
|
-
|
|
9941
|
+
useEffect20(() => {
|
|
9366
9942
|
if (!globalDrop) {
|
|
9367
9943
|
return;
|
|
9368
9944
|
}
|
|
@@ -9386,7 +9962,7 @@ var PromptInput = ({
|
|
|
9386
9962
|
document.removeEventListener("drop", onDrop);
|
|
9387
9963
|
};
|
|
9388
9964
|
}, [add, globalDrop]);
|
|
9389
|
-
|
|
9965
|
+
useEffect20(
|
|
9390
9966
|
() => () => {
|
|
9391
9967
|
if (!usingProvider) {
|
|
9392
9968
|
for (const f of filesRef.current) {
|
|
@@ -9398,7 +9974,7 @@ var PromptInput = ({
|
|
|
9398
9974
|
},
|
|
9399
9975
|
[usingProvider]
|
|
9400
9976
|
);
|
|
9401
|
-
const handleChange =
|
|
9977
|
+
const handleChange = useCallback16(
|
|
9402
9978
|
(event) => {
|
|
9403
9979
|
if (event.currentTarget.files) {
|
|
9404
9980
|
add(event.currentTarget.files);
|
|
@@ -9408,7 +9984,7 @@ var PromptInput = ({
|
|
|
9408
9984
|
[add]
|
|
9409
9985
|
);
|
|
9410
9986
|
const setFileUrl = usingProvider ? controller.attachments.setFileUrl : setFileUrlLocal;
|
|
9411
|
-
const attachmentsCtx =
|
|
9987
|
+
const attachmentsCtx = useMemo14(
|
|
9412
9988
|
() => ({
|
|
9413
9989
|
add,
|
|
9414
9990
|
clear: clearAttachments,
|
|
@@ -9420,7 +9996,7 @@ var PromptInput = ({
|
|
|
9420
9996
|
}),
|
|
9421
9997
|
[files, add, remove, clearAttachments, openFileDialog, setFileUrl]
|
|
9422
9998
|
);
|
|
9423
|
-
const refsCtx =
|
|
9999
|
+
const refsCtx = useMemo14(
|
|
9424
10000
|
() => ({
|
|
9425
10001
|
add: (incoming) => {
|
|
9426
10002
|
const array = Array.isArray(incoming) ? incoming : [incoming];
|
|
@@ -9437,7 +10013,7 @@ var PromptInput = ({
|
|
|
9437
10013
|
}),
|
|
9438
10014
|
[referencedSources, clearReferencedSources]
|
|
9439
10015
|
);
|
|
9440
|
-
const handleSubmit =
|
|
10016
|
+
const handleSubmit = useCallback16(
|
|
9441
10017
|
async (event) => {
|
|
9442
10018
|
event.preventDefault();
|
|
9443
10019
|
const form = event.currentTarget;
|
|
@@ -9496,8 +10072,8 @@ var PromptInput = ({
|
|
|
9496
10072
|
},
|
|
9497
10073
|
[usingProvider, controller, files, onSubmit, clear]
|
|
9498
10074
|
);
|
|
9499
|
-
const inner = /* @__PURE__ */
|
|
9500
|
-
/* @__PURE__ */
|
|
10075
|
+
const inner = /* @__PURE__ */ jsxs27(Fragment12, { children: [
|
|
10076
|
+
/* @__PURE__ */ jsx31(
|
|
9501
10077
|
Input,
|
|
9502
10078
|
{
|
|
9503
10079
|
accept,
|
|
@@ -9510,7 +10086,7 @@ var PromptInput = ({
|
|
|
9510
10086
|
type: "file"
|
|
9511
10087
|
}
|
|
9512
10088
|
),
|
|
9513
|
-
/* @__PURE__ */
|
|
10089
|
+
/* @__PURE__ */ jsx31(
|
|
9514
10090
|
"form",
|
|
9515
10091
|
{
|
|
9516
10092
|
"data-boring-agent-part": "composer",
|
|
@@ -9518,12 +10094,12 @@ var PromptInput = ({
|
|
|
9518
10094
|
onSubmit: handleSubmit,
|
|
9519
10095
|
ref: formRef,
|
|
9520
10096
|
...props,
|
|
9521
|
-
children: /* @__PURE__ */
|
|
10097
|
+
children: /* @__PURE__ */ jsx31(InputGroup, { className: "overflow-hidden", children })
|
|
9522
10098
|
}
|
|
9523
10099
|
)
|
|
9524
10100
|
] });
|
|
9525
|
-
const withReferencedSources = /* @__PURE__ */
|
|
9526
|
-
return /* @__PURE__ */
|
|
10101
|
+
const withReferencedSources = /* @__PURE__ */ jsx31(LocalReferencedSourcesContext.Provider, { value: refsCtx, children: inner });
|
|
10102
|
+
return /* @__PURE__ */ jsx31(LocalAttachmentsContext.Provider, { value: attachmentsCtx, children: withReferencedSources });
|
|
9527
10103
|
};
|
|
9528
10104
|
var PromptInputTextarea = ({
|
|
9529
10105
|
onChange,
|
|
@@ -9534,8 +10110,8 @@ var PromptInputTextarea = ({
|
|
|
9534
10110
|
}) => {
|
|
9535
10111
|
const controller = useOptionalPromptInputController();
|
|
9536
10112
|
const attachments = usePromptInputAttachments();
|
|
9537
|
-
const [isComposing, setIsComposing] =
|
|
9538
|
-
const handleKeyDown =
|
|
10113
|
+
const [isComposing, setIsComposing] = useState19(false);
|
|
10114
|
+
const handleKeyDown = useCallback16(
|
|
9539
10115
|
(e) => {
|
|
9540
10116
|
onKeyDown?.(e);
|
|
9541
10117
|
if (e.defaultPrevented) {
|
|
@@ -9568,7 +10144,7 @@ var PromptInputTextarea = ({
|
|
|
9568
10144
|
},
|
|
9569
10145
|
[onKeyDown, isComposing, attachments]
|
|
9570
10146
|
);
|
|
9571
|
-
const handlePaste =
|
|
10147
|
+
const handlePaste = useCallback16(
|
|
9572
10148
|
(event) => {
|
|
9573
10149
|
const items = event.clipboardData?.items;
|
|
9574
10150
|
if (!items) {
|
|
@@ -9590,8 +10166,8 @@ var PromptInputTextarea = ({
|
|
|
9590
10166
|
},
|
|
9591
10167
|
[attachments]
|
|
9592
10168
|
);
|
|
9593
|
-
const handleCompositionEnd =
|
|
9594
|
-
const handleCompositionStart =
|
|
10169
|
+
const handleCompositionEnd = useCallback16(() => setIsComposing(false), []);
|
|
10170
|
+
const handleCompositionStart = useCallback16(() => setIsComposing(true), []);
|
|
9595
10171
|
const controlledProps = controller ? {
|
|
9596
10172
|
onChange: (e) => {
|
|
9597
10173
|
controller.textInput.setInput(e.currentTarget.value);
|
|
@@ -9601,7 +10177,7 @@ var PromptInputTextarea = ({
|
|
|
9601
10177
|
} : {
|
|
9602
10178
|
onChange
|
|
9603
10179
|
};
|
|
9604
|
-
return /* @__PURE__ */
|
|
10180
|
+
return /* @__PURE__ */ jsx31(
|
|
9605
10181
|
InputGroupTextarea,
|
|
9606
10182
|
{
|
|
9607
10183
|
"data-boring-agent-part": "composer-input",
|
|
@@ -9628,15 +10204,15 @@ var PromptInputSubmit = ({
|
|
|
9628
10204
|
...props
|
|
9629
10205
|
}) => {
|
|
9630
10206
|
const isGenerating = status === "submitted" || status === "streaming";
|
|
9631
|
-
let Icon = /* @__PURE__ */
|
|
10207
|
+
let Icon = /* @__PURE__ */ jsx31(CornerDownLeftIcon, { className: "size-4" });
|
|
9632
10208
|
if (status === "submitted") {
|
|
9633
|
-
Icon = /* @__PURE__ */
|
|
10209
|
+
Icon = /* @__PURE__ */ jsx31(Spinner, {});
|
|
9634
10210
|
} else if (status === "streaming") {
|
|
9635
|
-
Icon = /* @__PURE__ */
|
|
10211
|
+
Icon = /* @__PURE__ */ jsx31(SquareIcon, { className: "size-4" });
|
|
9636
10212
|
} else if (status === "error") {
|
|
9637
|
-
Icon = /* @__PURE__ */
|
|
10213
|
+
Icon = /* @__PURE__ */ jsx31(XIcon4, { className: "size-4" });
|
|
9638
10214
|
}
|
|
9639
|
-
const handleClick =
|
|
10215
|
+
const handleClick = useCallback16(
|
|
9640
10216
|
(e) => {
|
|
9641
10217
|
if (isGenerating && onStop) {
|
|
9642
10218
|
e.preventDefault();
|
|
@@ -9647,7 +10223,7 @@ var PromptInputSubmit = ({
|
|
|
9647
10223
|
},
|
|
9648
10224
|
[isGenerating, onStop, onClick]
|
|
9649
10225
|
);
|
|
9650
|
-
return /* @__PURE__ */
|
|
10226
|
+
return /* @__PURE__ */ jsx31(
|
|
9651
10227
|
InputGroupButton2,
|
|
9652
10228
|
{
|
|
9653
10229
|
"aria-label": isGenerating ? "Stop" : "Submit",
|
|
@@ -9664,8 +10240,8 @@ var PromptInputSubmit = ({
|
|
|
9664
10240
|
};
|
|
9665
10241
|
|
|
9666
10242
|
// src/front/primitives/slash-command-picker.tsx
|
|
9667
|
-
import { useEffect as
|
|
9668
|
-
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";
|
|
9669
10245
|
var ALL_PLUGINS = "__all__";
|
|
9670
10246
|
function commandGroup(cmd) {
|
|
9671
10247
|
if (cmd.source === "skill") return "skills";
|
|
@@ -9673,20 +10249,20 @@ function commandGroup(cmd) {
|
|
|
9673
10249
|
return "built-in";
|
|
9674
10250
|
}
|
|
9675
10251
|
function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
9676
|
-
const [plugin, setPlugin] =
|
|
9677
|
-
const [searchQuery, setSearchQuery] =
|
|
9678
|
-
const [activeIdx, setActiveIdx] =
|
|
9679
|
-
const containerRef =
|
|
9680
|
-
const listRef =
|
|
9681
|
-
const inputRef =
|
|
9682
|
-
|
|
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(() => {
|
|
9683
10259
|
setSearchQuery(query);
|
|
9684
10260
|
}, [query]);
|
|
9685
|
-
const groups =
|
|
10261
|
+
const groups = useMemo15(() => {
|
|
9686
10262
|
const set = new Set(commands.map(commandGroup));
|
|
9687
10263
|
return Array.from(set).sort((a, b) => a.localeCompare(b));
|
|
9688
10264
|
}, [commands]);
|
|
9689
|
-
const filtered =
|
|
10265
|
+
const filtered = useMemo15(() => {
|
|
9690
10266
|
const q = searchQuery.trim().toLowerCase();
|
|
9691
10267
|
return commands.filter((c) => {
|
|
9692
10268
|
if (plugin !== ALL_PLUGINS && commandGroup(c) !== plugin) return false;
|
|
@@ -9694,10 +10270,10 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9694
10270
|
return c.name.toLowerCase().includes(q) || c.description.toLowerCase().includes(q);
|
|
9695
10271
|
});
|
|
9696
10272
|
}, [commands, searchQuery, plugin]);
|
|
9697
|
-
|
|
10273
|
+
useEffect21(() => {
|
|
9698
10274
|
setActiveIdx((i) => filtered.length === 0 ? 0 : Math.min(i, filtered.length - 1));
|
|
9699
10275
|
}, [filtered.length]);
|
|
9700
|
-
|
|
10276
|
+
useEffect21(() => {
|
|
9701
10277
|
const handler = (e) => {
|
|
9702
10278
|
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
9703
10279
|
onDismiss();
|
|
@@ -9716,8 +10292,8 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9716
10292
|
},
|
|
9717
10293
|
onDismiss
|
|
9718
10294
|
});
|
|
9719
|
-
return /* @__PURE__ */
|
|
9720
|
-
/* @__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(
|
|
9721
10297
|
"input",
|
|
9722
10298
|
{
|
|
9723
10299
|
ref: inputRef,
|
|
@@ -9732,9 +10308,9 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9732
10308
|
autoComplete: "off"
|
|
9733
10309
|
}
|
|
9734
10310
|
),
|
|
9735
|
-
/* @__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) => {
|
|
9736
10312
|
const selected = plugin === g;
|
|
9737
|
-
return /* @__PURE__ */
|
|
10313
|
+
return /* @__PURE__ */ jsx32(
|
|
9738
10314
|
"button",
|
|
9739
10315
|
{
|
|
9740
10316
|
type: "button",
|
|
@@ -9754,7 +10330,7 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9754
10330
|
g
|
|
9755
10331
|
);
|
|
9756
10332
|
}) }),
|
|
9757
|
-
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(
|
|
9758
10334
|
"li",
|
|
9759
10335
|
{
|
|
9760
10336
|
role: "option",
|
|
@@ -9772,20 +10348,20 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9772
10348
|
onSelect(cmd.name);
|
|
9773
10349
|
},
|
|
9774
10350
|
children: [
|
|
9775
|
-
/* @__PURE__ */
|
|
9776
|
-
/* @__PURE__ */
|
|
10351
|
+
/* @__PURE__ */ jsxs28("span", { className: "flex items-center gap-1.5", children: [
|
|
10352
|
+
/* @__PURE__ */ jsxs28("span", { className: "font-medium text-foreground/80", children: [
|
|
9777
10353
|
"/",
|
|
9778
10354
|
cmd.name
|
|
9779
10355
|
] }),
|
|
9780
|
-
cmd.source === "skill" ? /* @__PURE__ */
|
|
9781
|
-
/* @__PURE__ */
|
|
9782
|
-
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
|
|
9783
10359
|
] }) : cmd.sourcePlugin ? (
|
|
9784
10360
|
// Originating plugin/package for non-skill commands.
|
|
9785
|
-
/* @__PURE__ */
|
|
10361
|
+
/* @__PURE__ */ jsx32("span", { className: "rounded-sm bg-muted px-1 py-px text-[9px] font-medium text-muted-foreground", children: cmd.sourcePlugin })
|
|
9786
10362
|
) : null
|
|
9787
10363
|
] }),
|
|
9788
|
-
/* @__PURE__ */
|
|
10364
|
+
/* @__PURE__ */ jsx32("span", { className: "truncate text-[11px] opacity-50", children: cmd.description })
|
|
9789
10365
|
]
|
|
9790
10366
|
},
|
|
9791
10367
|
cmd.name
|
|
@@ -9796,10 +10372,10 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9796
10372
|
// src/front/chat/components/ComposerAttachments.tsx
|
|
9797
10373
|
import { AlertCircleIcon as AlertCircleIcon2, Loader2 as Loader22, PaperclipIcon as PaperclipIcon2 } from "lucide-react";
|
|
9798
10374
|
import { IconButton as IconButton3 } from "@hachej/boring-ui-kit";
|
|
9799
|
-
import { jsx as
|
|
10375
|
+
import { jsx as jsx33, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
9800
10376
|
function AttachmentButton({ disabled, className }) {
|
|
9801
10377
|
const attachments = usePromptInputAttachments();
|
|
9802
|
-
return /* @__PURE__ */
|
|
10378
|
+
return /* @__PURE__ */ jsx33(
|
|
9803
10379
|
IconButton3,
|
|
9804
10380
|
{
|
|
9805
10381
|
type: "button",
|
|
@@ -9812,21 +10388,21 @@ function AttachmentButton({ disabled, className }) {
|
|
|
9812
10388
|
className: cn(composerActionClass, "composer-attachment-button !h-10 !w-10", className),
|
|
9813
10389
|
"aria-label": "Attach files",
|
|
9814
10390
|
title: disabled ? "Attachments are available when the composer is ready." : "Attach files",
|
|
9815
|
-
children: /* @__PURE__ */
|
|
10391
|
+
children: /* @__PURE__ */ jsx33(PaperclipIcon2, { className: "h-4 w-4", strokeWidth: 1.75 })
|
|
9816
10392
|
}
|
|
9817
10393
|
);
|
|
9818
10394
|
}
|
|
9819
10395
|
function AttachmentsList() {
|
|
9820
10396
|
const attachments = usePromptInputAttachments();
|
|
9821
10397
|
if (attachments.files.length === 0) return null;
|
|
9822
|
-
return /* @__PURE__ */
|
|
10398
|
+
return /* @__PURE__ */ jsx33(
|
|
9823
10399
|
Attachments,
|
|
9824
10400
|
{
|
|
9825
10401
|
"data-boring-agent-part": "composer-attachment-row",
|
|
9826
10402
|
"data-align": "block-start",
|
|
9827
10403
|
variant: "inline",
|
|
9828
10404
|
className: "w-full flex-wrap items-center justify-start gap-2 px-5 pb-0 pt-3",
|
|
9829
|
-
children: attachments.files.map((file) => /* @__PURE__ */
|
|
10405
|
+
children: attachments.files.map((file) => /* @__PURE__ */ jsxs29(
|
|
9830
10406
|
Attachment,
|
|
9831
10407
|
{
|
|
9832
10408
|
data: file,
|
|
@@ -9837,13 +10413,13 @@ function AttachmentsList() {
|
|
|
9837
10413
|
file.status === "error" && "!border-destructive/50 !bg-destructive/10"
|
|
9838
10414
|
),
|
|
9839
10415
|
children: [
|
|
9840
|
-
/* @__PURE__ */
|
|
9841
|
-
/* @__PURE__ */
|
|
9842
|
-
file.status === "uploading" ? /* @__PURE__ */
|
|
9843
|
-
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
|
|
9844
10420
|
] }),
|
|
9845
|
-
/* @__PURE__ */
|
|
9846
|
-
/* @__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" })
|
|
9847
10423
|
]
|
|
9848
10424
|
},
|
|
9849
10425
|
file.id
|
|
@@ -9853,7 +10429,7 @@ function AttachmentsList() {
|
|
|
9853
10429
|
}
|
|
9854
10430
|
|
|
9855
10431
|
// src/front/chat/components/PiChatComposerSurface.tsx
|
|
9856
|
-
import { jsx as
|
|
10432
|
+
import { jsx as jsx34, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
9857
10433
|
var MAX_PROMPT_ATTACHMENTS = 2;
|
|
9858
10434
|
var MAX_PROMPT_ATTACHMENT_BYTES = 10 * 1024 * 1024;
|
|
9859
10435
|
var COMPOSER_INPUT_GROUP_MIN_HEIGHT = 56;
|
|
@@ -9892,6 +10468,10 @@ function PiChatComposerSurface({
|
|
|
9892
10468
|
onComposerBlockerAction,
|
|
9893
10469
|
queuePreview,
|
|
9894
10470
|
onEditQueued,
|
|
10471
|
+
onResumeQueued,
|
|
10472
|
+
resumeQueuedPending,
|
|
10473
|
+
onRemoveQueued,
|
|
10474
|
+
queueMutationPending,
|
|
9895
10475
|
hotReloadEnabled,
|
|
9896
10476
|
pluginUpdateState,
|
|
9897
10477
|
onDismissPluginUpdate,
|
|
@@ -9940,13 +10520,14 @@ function PiChatComposerSurface({
|
|
|
9940
10520
|
const prefersReducedMotion = useReducedMotion();
|
|
9941
10521
|
const workspaceRequestId = getHeaderValue(requestHeaders, "x-boring-workspace-id");
|
|
9942
10522
|
const composerContributions = useComposerContributions();
|
|
9943
|
-
const uploadAttachment =
|
|
10523
|
+
const uploadAttachment = useCallback17((file) => uploadFile(file, {
|
|
9944
10524
|
apiBaseUrl,
|
|
9945
10525
|
workspaceRequestId,
|
|
10526
|
+
requestHeaders,
|
|
9946
10527
|
responseUrl: "raw",
|
|
9947
10528
|
fetch: fetch2
|
|
9948
|
-
}), [apiBaseUrl, fetch2, workspaceRequestId]);
|
|
9949
|
-
const resizeTextarea =
|
|
10529
|
+
}), [apiBaseUrl, fetch2, requestHeaders, workspaceRequestId]);
|
|
10530
|
+
const resizeTextarea = useCallback17((node) => {
|
|
9950
10531
|
if (!node) return;
|
|
9951
10532
|
node.style.height = "auto";
|
|
9952
10533
|
const style = window.getComputedStyle(node);
|
|
@@ -9970,11 +10551,11 @@ function PiChatComposerSurface({
|
|
|
9970
10551
|
useLayoutEffect3(() => {
|
|
9971
10552
|
resizeTextarea(textareaRef.current);
|
|
9972
10553
|
}, [draft, resizeTextarea, textareaRef]);
|
|
9973
|
-
return /* @__PURE__ */
|
|
10554
|
+
return /* @__PURE__ */ jsxs30("div", { className: cn(
|
|
9974
10555
|
"relative z-20",
|
|
9975
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"
|
|
9976
10557
|
), children: [
|
|
9977
|
-
/* @__PURE__ */
|
|
10558
|
+
/* @__PURE__ */ jsx34(
|
|
9978
10559
|
"div",
|
|
9979
10560
|
{
|
|
9980
10561
|
"data-boring-agent-part": "chat-working-slot",
|
|
@@ -9984,7 +10565,7 @@ function PiChatComposerSurface({
|
|
|
9984
10565
|
isStreaming ? "mb-2 max-h-8 opacity-100" : "mb-0 max-h-0 opacity-0"
|
|
9985
10566
|
),
|
|
9986
10567
|
"aria-hidden": !isStreaming,
|
|
9987
|
-
children: /* @__PURE__ */
|
|
10568
|
+
children: /* @__PURE__ */ jsxs30(
|
|
9988
10569
|
"div",
|
|
9989
10570
|
{
|
|
9990
10571
|
"data-testid": isStreaming ? "chat-working" : void 0,
|
|
@@ -9992,7 +10573,7 @@ function PiChatComposerSurface({
|
|
|
9992
10573
|
"aria-live": isStreaming ? "polite" : void 0,
|
|
9993
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",
|
|
9994
10575
|
children: [
|
|
9995
|
-
/* @__PURE__ */
|
|
10576
|
+
/* @__PURE__ */ jsx34(
|
|
9996
10577
|
motion2.span,
|
|
9997
10578
|
{
|
|
9998
10579
|
"aria-hidden": "true",
|
|
@@ -10001,14 +10582,14 @@ function PiChatComposerSurface({
|
|
|
10001
10582
|
transition: prefersReducedMotion ? { duration: 0 } : { duration: 1.2, repeat: Infinity, ease: "easeInOut" }
|
|
10002
10583
|
}
|
|
10003
10584
|
),
|
|
10004
|
-
/* @__PURE__ */
|
|
10585
|
+
/* @__PURE__ */ jsx34("span", { children: "Working\u2026" })
|
|
10005
10586
|
]
|
|
10006
10587
|
}
|
|
10007
10588
|
)
|
|
10008
10589
|
}
|
|
10009
10590
|
),
|
|
10010
|
-
composerStatusNotice ? /* @__PURE__ */
|
|
10011
|
-
composerBlocked && !workspaceWarmupBlocked ? /* @__PURE__ */
|
|
10591
|
+
composerStatusNotice ? /* @__PURE__ */ jsx34(ComposerRuntimeNotice, { notice: composerStatusNotice }) : null,
|
|
10592
|
+
composerBlocked && !workspaceWarmupBlocked ? /* @__PURE__ */ jsx34(
|
|
10012
10593
|
ComposerBlockerNotice,
|
|
10013
10594
|
{
|
|
10014
10595
|
blocker: primaryComposerBlocker,
|
|
@@ -10016,8 +10597,18 @@ function PiChatComposerSurface({
|
|
|
10016
10597
|
onAction: onComposerBlockerAction
|
|
10017
10598
|
}
|
|
10018
10599
|
) : null,
|
|
10019
|
-
queuePreview.length > 0 ? /* @__PURE__ */
|
|
10020
|
-
|
|
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(
|
|
10021
10612
|
PluginUpdateStatus,
|
|
10022
10613
|
{
|
|
10023
10614
|
state: pluginUpdateState,
|
|
@@ -10025,14 +10616,14 @@ function PiChatComposerSurface({
|
|
|
10025
10616
|
onRetry: onRunPluginUpdate
|
|
10026
10617
|
}
|
|
10027
10618
|
) : null,
|
|
10028
|
-
/* @__PURE__ */
|
|
10619
|
+
/* @__PURE__ */ jsx34(
|
|
10029
10620
|
CommandRunStatus,
|
|
10030
10621
|
{
|
|
10031
10622
|
state: commandNotifyState,
|
|
10032
10623
|
onDismiss: onDismissCommandNotify
|
|
10033
10624
|
}
|
|
10034
10625
|
),
|
|
10035
|
-
attachmentNotice ? /* @__PURE__ */
|
|
10626
|
+
attachmentNotice ? /* @__PURE__ */ jsx34(
|
|
10036
10627
|
"div",
|
|
10037
10628
|
{
|
|
10038
10629
|
role: "status",
|
|
@@ -10041,12 +10632,12 @@ function PiChatComposerSurface({
|
|
|
10041
10632
|
children: attachmentNotice
|
|
10042
10633
|
}
|
|
10043
10634
|
) : null,
|
|
10044
|
-
/* @__PURE__ */
|
|
10045
|
-
/* @__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(
|
|
10046
10637
|
"absolute inset-x-0 z-30",
|
|
10047
10638
|
pickerPlacement === "above-compact" ? "bottom-[calc(100%+4px)] [&_[cmdk-list]]:!max-h-[200px]" : "bottom-[calc(100%+4px)]"
|
|
10048
10639
|
), children: [
|
|
10049
|
-
mentionState ? /* @__PURE__ */
|
|
10640
|
+
mentionState ? /* @__PURE__ */ jsx34("div", { className: "mr-px ml-[43px]", children: /* @__PURE__ */ jsx34(
|
|
10050
10641
|
MentionPicker,
|
|
10051
10642
|
{
|
|
10052
10643
|
mention: mentionState,
|
|
@@ -10058,7 +10649,7 @@ function PiChatComposerSurface({
|
|
|
10058
10649
|
onDismiss: onDismissMention
|
|
10059
10650
|
}
|
|
10060
10651
|
) }) : null,
|
|
10061
|
-
slashQuery !== null ? /* @__PURE__ */
|
|
10652
|
+
slashQuery !== null ? /* @__PURE__ */ jsx34("div", { className: "mr-px ml-[43px]", children: /* @__PURE__ */ jsx34(
|
|
10062
10653
|
SlashCommandPicker,
|
|
10063
10654
|
{
|
|
10064
10655
|
query: slashQuery,
|
|
@@ -10067,7 +10658,7 @@ function PiChatComposerSurface({
|
|
|
10067
10658
|
onDismiss: onDismissSlash
|
|
10068
10659
|
}
|
|
10069
10660
|
) }) : null,
|
|
10070
|
-
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(
|
|
10071
10662
|
ModelPickerMenu,
|
|
10072
10663
|
{
|
|
10073
10664
|
value: selectedModel,
|
|
@@ -10078,7 +10669,7 @@ function PiChatComposerSurface({
|
|
|
10078
10669
|
onClose: () => onSetModelPickerOpen(false)
|
|
10079
10670
|
}
|
|
10080
10671
|
) }) : null,
|
|
10081
|
-
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(
|
|
10082
10673
|
ThinkingPickerMenu,
|
|
10083
10674
|
{
|
|
10084
10675
|
value: selectedThinking,
|
|
@@ -10088,17 +10679,17 @@ function PiChatComposerSurface({
|
|
|
10088
10679
|
}
|
|
10089
10680
|
) }) : null
|
|
10090
10681
|
] }),
|
|
10091
|
-
composerContributions.map(({ id, Top }) => Top ? /* @__PURE__ */
|
|
10682
|
+
composerContributions.map(({ id, Top }) => Top ? /* @__PURE__ */ jsx34(
|
|
10092
10683
|
"div",
|
|
10093
10684
|
{
|
|
10094
10685
|
"data-boring-agent-part": "composer-contribution-top",
|
|
10095
10686
|
"data-boring-agent-contribution-id": id,
|
|
10096
10687
|
className: cn("mx-auto mb-2 w-full empty:hidden", chrome ? "max-w-3xl" : "max-w-[680px]"),
|
|
10097
|
-
children: /* @__PURE__ */
|
|
10688
|
+
children: /* @__PURE__ */ jsx34(Top, {})
|
|
10098
10689
|
},
|
|
10099
10690
|
id
|
|
10100
10691
|
) : null),
|
|
10101
|
-
/* @__PURE__ */
|
|
10692
|
+
/* @__PURE__ */ jsx34(
|
|
10102
10693
|
"div",
|
|
10103
10694
|
{
|
|
10104
10695
|
"data-boring-agent-part": "composer-rail",
|
|
@@ -10117,7 +10708,7 @@ function PiChatComposerSurface({
|
|
|
10117
10708
|
"[&[data-composer-multiline=true]_[data-boring-agent-part=composer-submit-addon]]:self-end",
|
|
10118
10709
|
"[&[data-composer-multiline=true]_[data-boring-agent-part=composer-submit-addon]]:mb-2"
|
|
10119
10710
|
),
|
|
10120
|
-
children: /* @__PURE__ */
|
|
10711
|
+
children: /* @__PURE__ */ jsxs30(
|
|
10121
10712
|
PromptInput,
|
|
10122
10713
|
{
|
|
10123
10714
|
"data-boring-state": status,
|
|
@@ -10133,15 +10724,15 @@ function PiChatComposerSurface({
|
|
|
10133
10724
|
else onAttachmentNotice(err.message || "Attachment rejected.");
|
|
10134
10725
|
},
|
|
10135
10726
|
children: [
|
|
10136
|
-
/* @__PURE__ */
|
|
10137
|
-
/* @__PURE__ */
|
|
10727
|
+
/* @__PURE__ */ jsx34(AttachmentsList, {}),
|
|
10728
|
+
/* @__PURE__ */ jsxs30(
|
|
10138
10729
|
"div",
|
|
10139
10730
|
{
|
|
10140
10731
|
"data-boring-agent-part": "composer-input-row",
|
|
10141
10732
|
className: "flex min-h-[var(--composer-input-group-height)] w-full items-center",
|
|
10142
10733
|
children: [
|
|
10143
|
-
/* @__PURE__ */
|
|
10144
|
-
/* @__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(
|
|
10145
10736
|
PromptInputTextarea,
|
|
10146
10737
|
{
|
|
10147
10738
|
value: draft,
|
|
@@ -10165,24 +10756,24 @@ function PiChatComposerSurface({
|
|
|
10165
10756
|
)
|
|
10166
10757
|
}
|
|
10167
10758
|
),
|
|
10168
|
-
/* @__PURE__ */
|
|
10759
|
+
/* @__PURE__ */ jsx34(
|
|
10169
10760
|
PromptInputFooter,
|
|
10170
10761
|
{
|
|
10171
10762
|
align: "inline-end",
|
|
10172
10763
|
"data-boring-agent-part": "composer-submit-addon",
|
|
10173
10764
|
className: "!order-none !w-auto shrink-0 self-center justify-between border-0 bg-transparent !px-2 !py-0",
|
|
10174
|
-
children: /* @__PURE__ */
|
|
10175
|
-
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(
|
|
10176
10767
|
"span",
|
|
10177
10768
|
{
|
|
10178
10769
|
"data-boring-agent-part": "composer-contribution-action",
|
|
10179
10770
|
"data-boring-agent-contribution-id": id,
|
|
10180
10771
|
className: "contents",
|
|
10181
|
-
children: /* @__PURE__ */
|
|
10772
|
+
children: /* @__PURE__ */ jsx34(Action, { updateDraft })
|
|
10182
10773
|
},
|
|
10183
10774
|
id
|
|
10184
10775
|
) : null),
|
|
10185
|
-
/* @__PURE__ */
|
|
10776
|
+
/* @__PURE__ */ jsx34(
|
|
10186
10777
|
PromptInputSubmit,
|
|
10187
10778
|
{
|
|
10188
10779
|
"data-boring-agent-part": "composer-submit",
|
|
@@ -10212,7 +10803,7 @@ function PiChatComposerSurface({
|
|
|
10212
10803
|
)
|
|
10213
10804
|
}
|
|
10214
10805
|
),
|
|
10215
|
-
hideComposerSettings ? null : /* @__PURE__ */
|
|
10806
|
+
hideComposerSettings ? null : /* @__PURE__ */ jsx34(
|
|
10216
10807
|
"div",
|
|
10217
10808
|
{
|
|
10218
10809
|
"data-boring-agent-part": "composer-settings-row",
|
|
@@ -10220,8 +10811,8 @@ function PiChatComposerSurface({
|
|
|
10220
10811
|
"mx-auto mt-2 grid min-h-8 w-full grid-cols-[minmax(0,1fr)_auto] items-center text-xs text-muted-foreground",
|
|
10221
10812
|
chrome ? "max-w-3xl" : "max-w-[680px]"
|
|
10222
10813
|
),
|
|
10223
|
-
children: /* @__PURE__ */
|
|
10224
|
-
/* @__PURE__ */
|
|
10814
|
+
children: /* @__PURE__ */ jsxs30("div", { className: "flex min-w-0 items-center justify-center gap-1", children: [
|
|
10815
|
+
/* @__PURE__ */ jsx34(
|
|
10225
10816
|
ModelSelectTrigger,
|
|
10226
10817
|
{
|
|
10227
10818
|
value: selectedModel,
|
|
@@ -10241,7 +10832,7 @@ function PiChatComposerSurface({
|
|
|
10241
10832
|
}
|
|
10242
10833
|
}
|
|
10243
10834
|
),
|
|
10244
|
-
thinkingControl ? /* @__PURE__ */
|
|
10835
|
+
thinkingControl ? /* @__PURE__ */ jsx34(
|
|
10245
10836
|
ThinkingSelectTrigger,
|
|
10246
10837
|
{
|
|
10247
10838
|
value: selectedThinking,
|
|
@@ -10270,7 +10861,7 @@ function getHeaderValue(headers, name) {
|
|
|
10270
10861
|
}
|
|
10271
10862
|
|
|
10272
10863
|
// src/front/chat/piChatPanelHooks.ts
|
|
10273
|
-
import { useCallback as
|
|
10864
|
+
import { useCallback as useCallback18, useEffect as useEffect22, useMemo as useMemo16, useRef as useRef17, useState as useState21, useSyncExternalStore } from "react";
|
|
10274
10865
|
|
|
10275
10866
|
// src/front/chat/piChatPanelUtils.ts
|
|
10276
10867
|
function headersContentKey(headers) {
|
|
@@ -10390,19 +10981,19 @@ function useExternalRemotePiSession({
|
|
|
10390
10981
|
remoteSessionOptions,
|
|
10391
10982
|
enabled = true
|
|
10392
10983
|
}) {
|
|
10393
|
-
const [session, setSession] =
|
|
10394
|
-
const remoteSessionOptionsRef =
|
|
10984
|
+
const [session, setSession] = useState21();
|
|
10985
|
+
const remoteSessionOptionsRef = useRef17(remoteSessionOptions);
|
|
10395
10986
|
remoteSessionOptionsRef.current = remoteSessionOptions;
|
|
10396
10987
|
const requestHeadersKey = headersContentKey(requestHeaders);
|
|
10397
|
-
const stableRequestHeaders =
|
|
10988
|
+
const stableRequestHeaders = useMemo16(
|
|
10398
10989
|
() => normalizedHeadersFromContentKey(requestHeadersKey),
|
|
10399
10990
|
[requestHeadersKey]
|
|
10400
10991
|
);
|
|
10401
|
-
const remoteSessionOptionsKey =
|
|
10992
|
+
const remoteSessionOptionsKey = useMemo16(
|
|
10402
10993
|
() => remoteSessionOptionsIdentity2(remoteSessionOptions),
|
|
10403
10994
|
[remoteSessionOptions]
|
|
10404
10995
|
);
|
|
10405
|
-
|
|
10996
|
+
useEffect22(() => {
|
|
10406
10997
|
if (!sessionId) {
|
|
10407
10998
|
setSession(void 0);
|
|
10408
10999
|
return;
|
|
@@ -10421,7 +11012,7 @@ function useExternalRemotePiSession({
|
|
|
10421
11012
|
setSession(next);
|
|
10422
11013
|
return () => next.dispose();
|
|
10423
11014
|
}, [agentTypeId, apiBaseUrl, createRemoteSession, fetch2, remoteSessionOptionsKey, sessionId, stableRequestHeaders, storageScope, workspaceId]);
|
|
10424
|
-
|
|
11015
|
+
useEffect22(() => {
|
|
10425
11016
|
if (!session) return;
|
|
10426
11017
|
if (enabled) session.resumeStream?.();
|
|
10427
11018
|
else session.suspendStream?.();
|
|
@@ -10464,20 +11055,83 @@ function remoteSessionOptionsIdentity2(options) {
|
|
|
10464
11055
|
}
|
|
10465
11056
|
function useRemotePiSessionState(session) {
|
|
10466
11057
|
return useSyncExternalStore(
|
|
10467
|
-
|
|
11058
|
+
useCallback18((listener) => session?.subscribe(listener) ?? (() => {
|
|
10468
11059
|
}), [session]),
|
|
10469
|
-
|
|
10470
|
-
|
|
11060
|
+
useCallback18(() => session?.getState(), [session]),
|
|
11061
|
+
useCallback18(() => session?.getState(), [session])
|
|
10471
11062
|
);
|
|
10472
11063
|
}
|
|
10473
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
|
+
|
|
10474
11123
|
// src/front/chat/PiChatPanel.tsx
|
|
10475
|
-
import { jsx as
|
|
11124
|
+
import { jsx as jsx35, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
10476
11125
|
var DebugDrawer2 = lazy(() => import("../DebugDrawer-JNA43SVR.js").then((m) => ({ default: m.DebugDrawer })));
|
|
10477
11126
|
var EMPTY_COMMANDS = [];
|
|
10478
11127
|
var EMPTY_COMMAND_NAMES = [];
|
|
10479
11128
|
var EMPTY_BLOCKERS = [];
|
|
10480
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
|
+
}
|
|
10481
11135
|
function normalizeAgentPluginReloadResult(result) {
|
|
10482
11136
|
if (typeof result !== "string") return result;
|
|
10483
11137
|
const firstLine = result.trim().split(/\r?\n/).find((line) => line.trim().length > 0)?.trim() ?? "";
|
|
@@ -10528,6 +11182,8 @@ function PiChatPanel({
|
|
|
10528
11182
|
allowPromptDuringInitialHydration = false,
|
|
10529
11183
|
workspaceWarmupStatus,
|
|
10530
11184
|
onSessionReset,
|
|
11185
|
+
spillLargePrompts = true,
|
|
11186
|
+
largePromptThresholdChars,
|
|
10531
11187
|
onBeforeSubmit,
|
|
10532
11188
|
onReloadAgentPlugins,
|
|
10533
11189
|
onCommandResult,
|
|
@@ -10544,14 +11200,14 @@ function PiChatPanel({
|
|
|
10544
11200
|
}) {
|
|
10545
11201
|
const externalSessionId = sessionId?.trim() || void 0;
|
|
10546
11202
|
const showSessionSidebar = showSessions ?? externalSessionId === void 0;
|
|
10547
|
-
const onDataRef =
|
|
11203
|
+
const onDataRef = useRef18(onData);
|
|
10548
11204
|
onDataRef.current = onData;
|
|
10549
|
-
const onTurnCompleteRef =
|
|
11205
|
+
const onTurnCompleteRef = useRef18(onTurnComplete);
|
|
10550
11206
|
onTurnCompleteRef.current = onTurnComplete;
|
|
10551
|
-
const sessionListRefreshRef =
|
|
10552
|
-
const requestHeadersKey =
|
|
10553
|
-
const normalizedRequestHeaders =
|
|
10554
|
-
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(() => ({
|
|
10555
11211
|
...remoteSessionOptions,
|
|
10556
11212
|
...hydrateMessages ? {} : { autoStart: false },
|
|
10557
11213
|
onEvent: (event) => {
|
|
@@ -10573,7 +11229,7 @@ function PiChatPanel({
|
|
|
10573
11229
|
remoteSessionOptions: remoteSessionOptionsWithEvents,
|
|
10574
11230
|
enabled: externalSessionId === void 0
|
|
10575
11231
|
});
|
|
10576
|
-
|
|
11232
|
+
useEffect23(() => {
|
|
10577
11233
|
if (externalSessionId) {
|
|
10578
11234
|
sessionListRefreshRef.current = void 0;
|
|
10579
11235
|
return;
|
|
@@ -10627,7 +11283,7 @@ function PiChatPanel({
|
|
|
10627
11283
|
const sessionModel = selectedChatState?.currentModel;
|
|
10628
11284
|
const selectedModel = model === void 0 ? modelDiscovery.model : model;
|
|
10629
11285
|
const modelOverride = model === void 0 ? modelDiscovery.isOverride : Boolean(model && sessionModel && (model.provider !== sessionModel.provider || model.id !== sessionModel.id));
|
|
10630
|
-
const modelOptions =
|
|
11286
|
+
const modelOptions = useMemo17(
|
|
10631
11287
|
() => modelOptionsForSelection(availableModels ?? modelDiscovery.availableModels, selectedModel),
|
|
10632
11288
|
[availableModels, modelDiscovery.availableModels, selectedModel]
|
|
10633
11289
|
);
|
|
@@ -10637,42 +11293,46 @@ function PiChatPanel({
|
|
|
10637
11293
|
const serverModelSelectionPending = modelDiscoveryEnabled && !modelDiscovery.loaded;
|
|
10638
11294
|
const serverModelSelectionUnavailable = modelDiscoveryEnabled && modelDiscovery.loaded && !selectedModelAuthorizedByDiscovery;
|
|
10639
11295
|
const serverModelSelectionReady = !serverModelSelectionPending && !serverModelSelectionUnavailable;
|
|
10640
|
-
const [storedThinkingLevel, setStoredThinkingLevel] =
|
|
11296
|
+
const [storedThinkingLevel, setStoredThinkingLevel] = useState22(
|
|
10641
11297
|
() => thinkingControl ? readPiComposerSettings({ storageScope, storage }).thinkingLevel : DEFAULT_THINKING
|
|
10642
11298
|
);
|
|
10643
|
-
const [showThoughts, setShowThoughts] =
|
|
11299
|
+
const [showThoughts, setShowThoughts] = useState22(
|
|
10644
11300
|
() => readPiComposerSettings({ storageScope, storage }).showThoughts
|
|
10645
11301
|
);
|
|
10646
|
-
const [composerSettingsOwner, setComposerSettingsOwner] =
|
|
10647
|
-
|
|
11302
|
+
const [composerSettingsOwner, setComposerSettingsOwner] = useState22(() => ({ storageScope, storage }));
|
|
11303
|
+
useEffect23(() => {
|
|
10648
11304
|
const settings = readPiComposerSettings({ storageScope, storage });
|
|
10649
11305
|
setStoredThinkingLevel(thinkingControl ? settings.thinkingLevel : DEFAULT_THINKING);
|
|
10650
11306
|
setShowThoughts(settings.showThoughts);
|
|
10651
11307
|
setComposerSettingsOwner({ storageScope, storage });
|
|
10652
11308
|
}, [storage, storageScope, thinkingControl]);
|
|
10653
11309
|
const composerSettingsLoaded = composerSettingsOwner.storageScope === storageScope && composerSettingsOwner.storage === storage;
|
|
10654
|
-
|
|
11310
|
+
useEffect23(() => {
|
|
10655
11311
|
if (!thinkingControl) return;
|
|
10656
11312
|
if (!composerSettingsLoaded) return;
|
|
10657
11313
|
writePiComposerThinking(storedThinkingLevel, { storageScope, storage });
|
|
10658
11314
|
}, [composerSettingsLoaded, storage, storageScope, storedThinkingLevel, thinkingControl]);
|
|
10659
|
-
|
|
11315
|
+
useEffect23(() => {
|
|
10660
11316
|
if (!composerSettingsLoaded) return;
|
|
10661
11317
|
writePiComposerShowThoughts(showThoughts, { storageScope, storage });
|
|
10662
11318
|
}, [composerSettingsLoaded, showThoughts, storage, storageScope]);
|
|
10663
11319
|
const selectedThinking = thinkingLevel ?? storedThinkingLevel;
|
|
10664
11320
|
const submitThinkingControl = thinkingControl || thinkingLevel !== void 0;
|
|
10665
|
-
const [modelPickerOpen, setModelPickerOpen] =
|
|
10666
|
-
const [thinkingPickerOpen, setThinkingPickerOpen] =
|
|
10667
|
-
const [draft, setDraft] =
|
|
10668
|
-
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);
|
|
10669
11325
|
draftRef.current = draft;
|
|
10670
|
-
const
|
|
10671
|
-
const
|
|
10672
|
-
const
|
|
10673
|
-
const
|
|
10674
|
-
const
|
|
10675
|
-
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) => {
|
|
10676
11336
|
const pendingSessionId = pendingAutoSubmitSettleRef.current;
|
|
10677
11337
|
if (!pendingSessionId || sessionId2 && pendingSessionId !== sessionId2) return false;
|
|
10678
11338
|
pendingAutoSubmitSettleRef.current = void 0;
|
|
@@ -10680,35 +11340,35 @@ function PiChatPanel({
|
|
|
10680
11340
|
onAutoSubmitInitialDraftSettled?.();
|
|
10681
11341
|
return true;
|
|
10682
11342
|
}, [onAutoSubmitInitialDraftSettled]);
|
|
10683
|
-
const prevStatusRef =
|
|
10684
|
-
const statusRef =
|
|
10685
|
-
const scrollToBottomRef =
|
|
11343
|
+
const prevStatusRef = useRef18("idle");
|
|
11344
|
+
const statusRef = useRef18("idle");
|
|
11345
|
+
const scrollToBottomRef = useRef18(() => {
|
|
10686
11346
|
});
|
|
10687
|
-
const textareaRef =
|
|
10688
|
-
const [localNotices, setLocalNotices] =
|
|
10689
|
-
const [dismissedNoticeIds, setDismissedNoticeIds] =
|
|
10690
|
-
const [pluginUpdateState, setPluginUpdateState] =
|
|
10691
|
-
const [commandNotifyState, setCommandNotifyState] =
|
|
10692
|
-
const commandRunIdRef =
|
|
10693
|
-
const [serverSkillsRefreshKey, setServerSkillsRefreshKey] =
|
|
10694
|
-
const [localSubmittedSessionId, setLocalSubmittedSessionId] =
|
|
10695
|
-
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);
|
|
10696
11356
|
const { attachmentNotice, setAttachmentNotice } = useAttachmentNotice();
|
|
10697
11357
|
const composerContributions = useComposerContributions();
|
|
10698
|
-
const contributedCommands =
|
|
11358
|
+
const contributedCommands = useMemo17(
|
|
10699
11359
|
() => composerContributions.flatMap((contribution) => contribution.commands ?? []),
|
|
10700
11360
|
[composerContributions]
|
|
10701
11361
|
);
|
|
10702
|
-
const markLocalSubmitted =
|
|
11362
|
+
const markLocalSubmitted = useCallback19((sessionId2) => {
|
|
10703
11363
|
localSubmittedSessionRef.current = sessionId2;
|
|
10704
11364
|
setLocalSubmittedSessionId(sessionId2);
|
|
10705
11365
|
}, []);
|
|
10706
|
-
const clearLocalSubmitted =
|
|
11366
|
+
const clearLocalSubmitted = useCallback19((sessionId2) => {
|
|
10707
11367
|
if (sessionId2 && localSubmittedSessionRef.current !== sessionId2) return;
|
|
10708
11368
|
localSubmittedSessionRef.current = void 0;
|
|
10709
11369
|
setLocalSubmittedSessionId(void 0);
|
|
10710
11370
|
}, []);
|
|
10711
|
-
const registry =
|
|
11371
|
+
const registry = useMemo17(() => {
|
|
10712
11372
|
const excludedBuiltins = new Set(excludeBuiltinCommands);
|
|
10713
11373
|
const effectiveBuiltins = builtinCommands.filter((command) => {
|
|
10714
11374
|
if (!hotReloadEnabled && command.name === "reload") return false;
|
|
@@ -10731,16 +11391,33 @@ function PiChatPanel({
|
|
|
10731
11391
|
refreshKey: serverSkillsRefreshKey,
|
|
10732
11392
|
enabled: serverResourcesEnabled
|
|
10733
11393
|
});
|
|
10734
|
-
const allCommands =
|
|
10735
|
-
const actionableSlashCommands =
|
|
11394
|
+
const allCommands = useMemo17(() => registry.list(), [registry, commandsStamp]);
|
|
11395
|
+
const actionableSlashCommands = useMemo17(
|
|
10736
11396
|
() => allCommands.flatMap((command) => command.clickBehavior === "execute" || command.clickBehavior === "insert" ? [{ name: command.name, clickBehavior: command.clickBehavior }] : []),
|
|
10737
11397
|
[allCommands]
|
|
10738
11398
|
);
|
|
10739
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]);
|
|
10740
11417
|
const warmupNotice = composerNoticeForWarmup(workspaceWarmupStatus);
|
|
10741
11418
|
const runtimeDependenciesNotice = composerNoticeForRuntimeDependencies(workspaceWarmupStatus);
|
|
10742
11419
|
const workspaceWarmupBlocked = Boolean(warmupNotice);
|
|
10743
|
-
const activeBlockers =
|
|
11420
|
+
const activeBlockers = useMemo17(
|
|
10744
11421
|
// A missing active session id means a single/sessionless chat host. In that
|
|
10745
11422
|
// mode, keep scoped blockers visible instead of hiding the only attention UI.
|
|
10746
11423
|
// Multi-session hosts should pass a session id so unrelated blockers filter out.
|
|
@@ -10750,7 +11427,7 @@ function PiChatPanel({
|
|
|
10750
11427
|
const canonicalMessages = selectedChatState ? selectMessagesForRender(selectedChatState) : [];
|
|
10751
11428
|
const queuePreview = selectedChatState ? selectQueuePreview(selectedChatState) : [];
|
|
10752
11429
|
const messages = canonicalMessages;
|
|
10753
|
-
const userHistory =
|
|
11430
|
+
const userHistory = useMemo17(() => selectComposerHistoryFromCanonicalUsers(canonicalMessages), [canonicalMessages]);
|
|
10754
11431
|
const awaitingHydration = Boolean(hydrateMessages && selectedChatState && !selectedChatState.hydrated);
|
|
10755
11432
|
const emptyStateHydrating = statusForState(selectedChatState, sessionsLoading || chatStatePending || selectedSessionPending) === "hydrating" || awaitingHydration;
|
|
10756
11433
|
const emptyHero = emptyPlacement === "hero" && messages.length === 0 && queuePreview.length === 0 && !emptyStateHydrating;
|
|
@@ -10759,7 +11436,7 @@ function PiChatPanel({
|
|
|
10759
11436
|
const primaryComposerBlocker = activeBlockers[0];
|
|
10760
11437
|
const composerBlockerLabel = workspaceWarmupBlocked ? warmupNotice?.title ?? "Preparing workspace..." : primaryComposerBlocker?.label ?? primaryComposerBlocker?.reason ?? "Complete the pending workspace action to continue.";
|
|
10761
11438
|
const composerStatusNotice = warmupNotice ?? runtimeDependenciesNotice;
|
|
10762
|
-
const runtimeNotices =
|
|
11439
|
+
const runtimeNotices = useMemo17(() => {
|
|
10763
11440
|
const fromState = selectedChatState ? selectRuntimeNotices(selectedChatState) : [];
|
|
10764
11441
|
const sessionNotice = sessionsError ? [{ id: "session-navigation-error", level: "error", text: sessionsError.message, dismissible: true }] : [];
|
|
10765
11442
|
const largeStateNotice = debug && debugState?.largeStateWarning ? [{
|
|
@@ -10768,20 +11445,29 @@ function PiChatPanel({
|
|
|
10768
11445
|
text: `Large chat state: ${debugState.largeStateWarning.messageCount} messages, approximately ${debugState.largeStateWarning.approxBytes} bytes.`,
|
|
10769
11446
|
dismissible: true
|
|
10770
11447
|
}] : [];
|
|
10771
|
-
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));
|
|
10772
11449
|
return filterCompetingNoiseNotices(combined, messages.length === 0);
|
|
10773
|
-
}, [debug, debugState?.largeStateWarning, dismissedNoticeIds, localNotices, messages.length, selectedChatState, sessionsError]);
|
|
10774
|
-
const addLocalNotice =
|
|
11450
|
+
}, [debug, debugState?.largeStateWarning, dismissedNoticeIds, localNotices, messages.length, resumeQueuedError, selectedChatState, sessionsError]);
|
|
11451
|
+
const addLocalNotice = useCallback19((notice) => {
|
|
10775
11452
|
setLocalNotices((previous) => {
|
|
10776
11453
|
const next = previous.filter((candidate) => candidate.id !== notice.id);
|
|
10777
11454
|
return [...next, notice];
|
|
10778
11455
|
});
|
|
10779
11456
|
}, []);
|
|
10780
|
-
const clearLocalNotice =
|
|
11457
|
+
const clearLocalNotice = useCallback19((id) => {
|
|
10781
11458
|
setDismissedNoticeIds((previous) => new Set(previous).add(id));
|
|
10782
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
|
+
}
|
|
10783
11469
|
}, []);
|
|
10784
|
-
const dropLocalNotice =
|
|
11470
|
+
const dropLocalNotice = useCallback19((id) => {
|
|
10785
11471
|
setDismissedNoticeIds((previous) => {
|
|
10786
11472
|
if (!previous.has(id)) return previous;
|
|
10787
11473
|
const next = new Set(previous);
|
|
@@ -10790,13 +11476,13 @@ function PiChatPanel({
|
|
|
10790
11476
|
});
|
|
10791
11477
|
setLocalNotices((previous) => previous.filter((notice) => notice.id !== id));
|
|
10792
11478
|
}, []);
|
|
10793
|
-
const createSession =
|
|
11479
|
+
const createSession = useCallback19(() => {
|
|
10794
11480
|
if (externalSessionId) return;
|
|
10795
11481
|
void sessions.create().catch((error) => {
|
|
10796
11482
|
addLocalNotice({ id: "session-create-error", level: "error", text: errorMessage2(error, "Could not create a chat session."), dismissible: true });
|
|
10797
11483
|
});
|
|
10798
11484
|
}, [addLocalNotice, externalSessionId, sessions.create]);
|
|
10799
|
-
|
|
11485
|
+
useEffect23(() => {
|
|
10800
11486
|
if (externalSessionId || sessionsLoading || sessionsError || activeSessionId || sessionList.length > 0) return;
|
|
10801
11487
|
if (resetInProgressRef.current) return;
|
|
10802
11488
|
if (autoCreateInFlightRef.current) return;
|
|
@@ -10806,18 +11492,18 @@ function PiChatPanel({
|
|
|
10806
11492
|
addLocalNotice({ id: "session-auto-create-error", level: "error", text: errorMessage2(error, "Could not create a chat session."), dismissible: true });
|
|
10807
11493
|
});
|
|
10808
11494
|
}, [activeSessionId, addLocalNotice, externalSessionId, sessionList.length, sessions.create, sessions.resumeSessionId, sessionsError, sessionsLoading]);
|
|
10809
|
-
|
|
11495
|
+
useEffect23(() => {
|
|
10810
11496
|
if (externalSessionId || sessionsError || activeSessionId || sessionList.length > 0) {
|
|
10811
11497
|
autoCreateInFlightRef.current = false;
|
|
10812
11498
|
}
|
|
10813
11499
|
}, [activeSessionId, externalSessionId, sessionList.length, sessionsError]);
|
|
10814
|
-
const deleteSession =
|
|
11500
|
+
const deleteSession = useCallback19((sessionId2) => {
|
|
10815
11501
|
if (externalSessionId) return;
|
|
10816
11502
|
void sessions.delete(sessionId2).catch((error) => {
|
|
10817
11503
|
addLocalNotice({ id: `session-delete-error:${sessionId2}`, level: "error", text: errorMessage2(error, "Could not delete the chat session."), dismissible: true });
|
|
10818
11504
|
});
|
|
10819
11505
|
}, [addLocalNotice, externalSessionId, sessions.delete]);
|
|
10820
|
-
const resetSession =
|
|
11506
|
+
const resetSession = useCallback19(() => {
|
|
10821
11507
|
const currentSessionId = activeSessionId;
|
|
10822
11508
|
if (externalSessionId) {
|
|
10823
11509
|
void onSessionReset?.();
|
|
@@ -10835,11 +11521,11 @@ function PiChatPanel({
|
|
|
10835
11521
|
resetInProgressRef.current = false;
|
|
10836
11522
|
});
|
|
10837
11523
|
}, [activeSessionId, addLocalNotice, externalSessionId, onSessionReset, sessions.create, sessions.delete]);
|
|
10838
|
-
const reloadAgentPlugins =
|
|
11524
|
+
const reloadAgentPlugins = useCallback19(async () => {
|
|
10839
11525
|
if (!onReloadAgentPlugins) throw new Error("Agent plugin reload is not configured.");
|
|
10840
11526
|
return normalizeAgentPluginReloadResult(await onReloadAgentPlugins());
|
|
10841
11527
|
}, [onReloadAgentPlugins]);
|
|
10842
|
-
const runPluginUpdate =
|
|
11528
|
+
const runPluginUpdate = useCallback19(async () => {
|
|
10843
11529
|
setPluginUpdateState({ kind: "running" });
|
|
10844
11530
|
try {
|
|
10845
11531
|
const result = await reloadAgentPlugins();
|
|
@@ -10852,9 +11538,9 @@ function PiChatPanel({
|
|
|
10852
11538
|
return `Extension update failed: ${message}`;
|
|
10853
11539
|
}
|
|
10854
11540
|
}, [reloadAgentPlugins]);
|
|
10855
|
-
const dismissPluginUpdate =
|
|
10856
|
-
const dismissCommandNotify =
|
|
10857
|
-
|
|
11541
|
+
const dismissPluginUpdate = useCallback19(() => setPluginUpdateState(null), []);
|
|
11542
|
+
const dismissCommandNotify = useCallback19(() => setCommandNotifyState(null), []);
|
|
11543
|
+
useEffect23(() => {
|
|
10858
11544
|
if (typeof window === "undefined") return;
|
|
10859
11545
|
const onCommandNotify = (event) => {
|
|
10860
11546
|
const payload = event.detail;
|
|
@@ -10871,7 +11557,7 @@ function PiChatPanel({
|
|
|
10871
11557
|
window.addEventListener(WORKSPACE_COMMAND_NOTIFY_EVENT, onCommandNotify);
|
|
10872
11558
|
return () => window.removeEventListener(WORKSPACE_COMMAND_NOTIFY_EVENT, onCommandNotify);
|
|
10873
11559
|
}, []);
|
|
10874
|
-
|
|
11560
|
+
useEffect23(() => {
|
|
10875
11561
|
if (!hotReloadEnabled || typeof window === "undefined") return;
|
|
10876
11562
|
const onBrowserPluginReload = (event) => {
|
|
10877
11563
|
const parsed = parseBrowserPluginReloadDetail(event.detail);
|
|
@@ -10909,7 +11595,7 @@ function PiChatPanel({
|
|
|
10909
11595
|
textareaRef,
|
|
10910
11596
|
disabled: mentionState !== null || slashQuery !== null || modelPickerOpen || thinkingPickerOpen
|
|
10911
11597
|
});
|
|
10912
|
-
const setComposerDraft =
|
|
11598
|
+
const setComposerDraft = useCallback19((next, focus = true) => {
|
|
10913
11599
|
draftRef.current = next;
|
|
10914
11600
|
setDraft(next);
|
|
10915
11601
|
if (textareaRef.current) {
|
|
@@ -10917,11 +11603,11 @@ function PiChatPanel({
|
|
|
10917
11603
|
if (focus) textareaRef.current.focus();
|
|
10918
11604
|
}
|
|
10919
11605
|
}, []);
|
|
10920
|
-
const warnComposer =
|
|
11606
|
+
const warnComposer = useCallback19((message) => {
|
|
10921
11607
|
onComposerWarning?.(message);
|
|
10922
11608
|
addLocalNotice({ id: `composer-warning:${Date.now()}`, level: "warning", text: message, dismissible: true });
|
|
10923
11609
|
}, [addLocalNotice, onComposerWarning]);
|
|
10924
|
-
const openModelPicker =
|
|
11610
|
+
const openModelPicker = useCallback19(() => {
|
|
10925
11611
|
if (isPiBusyStatus(statusRef.current)) {
|
|
10926
11612
|
warnComposer("Model picker is unavailable while the agent is running.");
|
|
10927
11613
|
return false;
|
|
@@ -10934,7 +11620,7 @@ function PiChatPanel({
|
|
|
10934
11620
|
setModelPickerOpen(true);
|
|
10935
11621
|
return true;
|
|
10936
11622
|
}, [model, warnComposer]);
|
|
10937
|
-
const openThinkingPicker =
|
|
11623
|
+
const openThinkingPicker = useCallback19(() => {
|
|
10938
11624
|
if (isPiBusyStatus(statusRef.current)) {
|
|
10939
11625
|
warnComposer("Thinking picker is unavailable while the agent is running.");
|
|
10940
11626
|
return false;
|
|
@@ -10947,21 +11633,21 @@ function PiChatPanel({
|
|
|
10947
11633
|
setThinkingPickerOpen(true);
|
|
10948
11634
|
return true;
|
|
10949
11635
|
}, [thinkingControl, thinkingLevel, warnComposer]);
|
|
10950
|
-
const selectComposerModel =
|
|
11636
|
+
const selectComposerModel = useCallback19((query) => {
|
|
10951
11637
|
if (model !== void 0) return "Model selection is controlled by the host.";
|
|
10952
11638
|
const match = resolveModelSlashSelection(query, modelOptions);
|
|
10953
11639
|
if (!match) return `No model matched "${query}".`;
|
|
10954
11640
|
modelDiscovery.setModel(match);
|
|
10955
11641
|
return `Model set to ${match.label ?? match.id}.`;
|
|
10956
11642
|
}, [model, modelDiscovery, modelOptions]);
|
|
10957
|
-
const selectComposerThinking =
|
|
11643
|
+
const selectComposerThinking = useCallback19((query) => {
|
|
10958
11644
|
if (!thinkingControl || thinkingLevel !== void 0) return "Thinking level is controlled by the host.";
|
|
10959
11645
|
const match = resolveThinkingSlashSelection(query);
|
|
10960
11646
|
if (!match) return `No thinking level matched "${query}".`;
|
|
10961
11647
|
setStoredThinkingLevel(match);
|
|
10962
11648
|
return `Thinking set to ${thinkingLabel(match)}.`;
|
|
10963
11649
|
}, [thinkingControl, thinkingLevel]);
|
|
10964
|
-
const selectSlashCommand =
|
|
11650
|
+
const selectSlashCommand = useCallback19((name) => {
|
|
10965
11651
|
if (name === "model") {
|
|
10966
11652
|
dismissSlash();
|
|
10967
11653
|
if (openModelPicker()) setComposerDraft("");
|
|
@@ -10974,7 +11660,7 @@ function PiChatPanel({
|
|
|
10974
11660
|
}
|
|
10975
11661
|
insertSlashCommand(name);
|
|
10976
11662
|
}, [dismissSlash, insertSlashCommand, openModelPicker, openThinkingPicker, setComposerDraft]);
|
|
10977
|
-
const policy =
|
|
11663
|
+
const policy = useMemo17(() => {
|
|
10978
11664
|
if (!selectedPiSession || !activeChatSessionId || !serverModelSelectionReady) return void 0;
|
|
10979
11665
|
const policySession = {
|
|
10980
11666
|
getState: () => {
|
|
@@ -11019,13 +11705,29 @@ function PiChatPanel({
|
|
|
11019
11705
|
getDraft: () => draftRef.current,
|
|
11020
11706
|
onDraftChange: setComposerDraft,
|
|
11021
11707
|
allowPromptDuringInitialHydration,
|
|
11708
|
+
isActiveSession: isPolicySessionActive,
|
|
11709
|
+
submissionCoordinator: submissionCoordinatorRef.current,
|
|
11710
|
+
submissionIdentity: activeChatIdentity,
|
|
11711
|
+
onQueueMutationPending: setQueueMutationPending,
|
|
11022
11712
|
onPromptSubmitStarted: () => {
|
|
11023
11713
|
markLocalSubmitted(activeChatSessionId);
|
|
11024
11714
|
},
|
|
11025
|
-
onBeforeSubmit: onBeforeSubmit ? async (draft2, context) => {
|
|
11026
|
-
|
|
11027
|
-
|
|
11028
|
-
|
|
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
|
+
}),
|
|
11029
11731
|
onCommandResult: (message) => {
|
|
11030
11732
|
onCommandResult?.(message);
|
|
11031
11733
|
addLocalNotice({ id: `command:${Date.now()}`, level: "info", text: message, dismissible: true });
|
|
@@ -11040,8 +11742,17 @@ function PiChatPanel({
|
|
|
11040
11742
|
onMentionedFilesConsumed?.();
|
|
11041
11743
|
}
|
|
11042
11744
|
});
|
|
11043
|
-
}, [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]);
|
|
11044
|
-
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) => {
|
|
11045
11756
|
const errorCode = piChatErrorCode(error);
|
|
11046
11757
|
dropLocalNotice(RUN_REJECTED_NOTICE_ID);
|
|
11047
11758
|
addLocalNotice({
|
|
@@ -11052,7 +11763,7 @@ function PiChatPanel({
|
|
|
11052
11763
|
...errorCode ? { errorCode } : {}
|
|
11053
11764
|
});
|
|
11054
11765
|
}, [addLocalNotice, dropLocalNotice]);
|
|
11055
|
-
const sendComposerMessage =
|
|
11766
|
+
const sendComposerMessage = useCallback19(async ({ text, files, source = "composer", preserveExistingDraft = false }) => {
|
|
11056
11767
|
if (!policy) {
|
|
11057
11768
|
addLocalNotice({ id: "composer-no-session", level: "warning", text: "Create or select a chat session before sending.", dismissible: true });
|
|
11058
11769
|
return false;
|
|
@@ -11072,6 +11783,7 @@ function PiChatPanel({
|
|
|
11072
11783
|
if (result.type === "prompt" || result.type === "followup") {
|
|
11073
11784
|
dropLocalNotice(RUN_REJECTED_NOTICE_ID);
|
|
11074
11785
|
}
|
|
11786
|
+
if (result.type === "handled") surfaceHandledSubmit(result.message);
|
|
11075
11787
|
if (result.type === "prompt" && activeChatSessionId) {
|
|
11076
11788
|
onPromptSubmitStarted?.({ sessionId: activeChatSessionId, clientNonce: result.clientNonce });
|
|
11077
11789
|
if (shouldHoldLocalSubmitted(selectedPiSession, result.cursor)) markLocalSubmitted(activeChatSessionId);
|
|
@@ -11079,17 +11791,18 @@ function PiChatPanel({
|
|
|
11079
11791
|
}
|
|
11080
11792
|
return void 0;
|
|
11081
11793
|
} catch (error) {
|
|
11794
|
+
if (!isPolicySessionActive()) return void 0;
|
|
11082
11795
|
clearLocalSubmitted(activeChatSessionId);
|
|
11083
11796
|
restoreSubmittedDraft();
|
|
11084
11797
|
surfaceRunRejected(error);
|
|
11085
11798
|
return false;
|
|
11086
11799
|
}
|
|
11087
|
-
}, [activeChatSessionId, clearLocalSubmitted, dropLocalNotice, markLocalSubmitted, onPromptSubmitStarted, policy, selectedPiSession, setComposerDraft, surfaceRunRejected]);
|
|
11088
|
-
const availableAssistantSlashCommands =
|
|
11800
|
+
}, [activeChatSessionId, clearLocalSubmitted, dropLocalNotice, isPolicySessionActive, markLocalSubmitted, onPromptSubmitStarted, policy, selectedPiSession, setComposerDraft, surfaceHandledSubmit, surfaceRunRejected]);
|
|
11801
|
+
const availableAssistantSlashCommands = useMemo17(
|
|
11089
11802
|
() => policy ? actionableSlashCommands : actionableSlashCommands.filter((command) => command.clickBehavior === "insert"),
|
|
11090
11803
|
[actionableSlashCommands, policy]
|
|
11091
11804
|
);
|
|
11092
|
-
const assistantMentionCatalog =
|
|
11805
|
+
const assistantMentionCatalog = useMemo17(() => {
|
|
11093
11806
|
const skills = /* @__PURE__ */ new Map();
|
|
11094
11807
|
for (const command of allCommands) {
|
|
11095
11808
|
if (command.source !== "skill" && command.kind !== "skill") continue;
|
|
@@ -11105,12 +11818,12 @@ function PiChatPanel({
|
|
|
11105
11818
|
files: true
|
|
11106
11819
|
};
|
|
11107
11820
|
}, [allCommands, availableAssistantSlashCommands]);
|
|
11108
|
-
const insertMentionDraft =
|
|
11821
|
+
const insertMentionDraft = useCallback19((invocation) => {
|
|
11109
11822
|
const currentDraft = draftRef.current;
|
|
11110
11823
|
const separator = currentDraft && !/\s$/.test(invocation) ? "\n" : "";
|
|
11111
11824
|
setComposerDraft(`${invocation}${separator}${currentDraft}`, true);
|
|
11112
11825
|
}, [setComposerDraft]);
|
|
11113
|
-
const activateAssistantMention =
|
|
11826
|
+
const activateAssistantMention = useCallback19((mention) => {
|
|
11114
11827
|
const command = registry.get(mention.kind === "skill" ? mention.commandName : mention.name);
|
|
11115
11828
|
if (mention.kind === "skill") {
|
|
11116
11829
|
if (command?.source !== "skill" && command?.kind !== "skill") return;
|
|
@@ -11132,7 +11845,7 @@ function PiChatPanel({
|
|
|
11132
11845
|
preserveExistingDraft: true
|
|
11133
11846
|
});
|
|
11134
11847
|
}, [insertMentionDraft, policy, registry, sendComposerMessage]);
|
|
11135
|
-
const editQueued =
|
|
11848
|
+
const editQueued = useCallback19(() => {
|
|
11136
11849
|
if (!policy) return;
|
|
11137
11850
|
void policy.editQueued().then((result) => {
|
|
11138
11851
|
if (result.type === "clear-failed") {
|
|
@@ -11140,25 +11853,65 @@ function PiChatPanel({
|
|
|
11140
11853
|
}
|
|
11141
11854
|
});
|
|
11142
11855
|
}, [addLocalNotice, policy]);
|
|
11143
|
-
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(() => {
|
|
11144
11865
|
onComposerStop?.();
|
|
11145
11866
|
clearLocalSubmitted(activeChatSessionId);
|
|
11146
|
-
void policy?.
|
|
11867
|
+
void policy?.interrupt({ queueAction: "hold" }).catch((error) => {
|
|
11147
11868
|
addLocalNotice({ id: "stop-error", level: "error", text: errorMessage2(error, "Could not stop the chat session."), dismissible: true });
|
|
11148
11869
|
});
|
|
11149
11870
|
}, [activeChatSessionId, addLocalNotice, clearLocalSubmitted, onComposerStop, policy]);
|
|
11150
|
-
const interrupt =
|
|
11871
|
+
const interrupt = useCallback19(() => {
|
|
11151
11872
|
void policy?.interrupt().catch((error) => {
|
|
11152
11873
|
addLocalNotice({ id: "interrupt-error", level: "error", text: errorMessage2(error, "Could not interrupt the chat session."), dismissible: true });
|
|
11153
11874
|
});
|
|
11154
11875
|
}, [addLocalNotice, policy]);
|
|
11155
|
-
|
|
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(() => {
|
|
11156
11909
|
setPluginUpdateState(null);
|
|
11157
11910
|
setCommandNotifyState(null);
|
|
11158
11911
|
setLocalNotices([]);
|
|
11159
11912
|
setDismissedNoticeIds(/* @__PURE__ */ new Set());
|
|
11160
11913
|
}, [activeSessionId]);
|
|
11161
|
-
|
|
11914
|
+
useEffect23(() => {
|
|
11162
11915
|
const currentSessionId = activeSessionId ?? "__none__";
|
|
11163
11916
|
if (initialDraftGuard.current.shouldRestore(currentSessionId, initialDraft) && initialDraft !== void 0) {
|
|
11164
11917
|
setComposerDraft(initialDraft, initialDraft.length > 0);
|
|
@@ -11167,7 +11920,7 @@ function PiChatPanel({
|
|
|
11167
11920
|
}, [activeSessionId, initialDraft, onDraftRestored, setComposerDraft]);
|
|
11168
11921
|
const remoteStatus = selectedChatState?.status ?? (sessionsLoading || chatStatePending || selectedSessionPending ? "hydrating" : "idle");
|
|
11169
11922
|
const status = localSubmittedSessionId === activeSessionId && remoteStatus === "idle" ? "submitted" : remoteStatus;
|
|
11170
|
-
|
|
11923
|
+
useEffect23(() => {
|
|
11171
11924
|
if (!localSubmittedSessionId) return;
|
|
11172
11925
|
if (localSubmittedSessionId !== activeSessionId) {
|
|
11173
11926
|
clearLocalSubmitted();
|
|
@@ -11175,7 +11928,7 @@ function PiChatPanel({
|
|
|
11175
11928
|
}
|
|
11176
11929
|
if (remoteStatus !== "idle") clearLocalSubmitted(localSubmittedSessionId);
|
|
11177
11930
|
}, [activeSessionId, clearLocalSubmitted, localSubmittedSessionId, remoteStatus]);
|
|
11178
|
-
|
|
11931
|
+
useEffect23(() => {
|
|
11179
11932
|
const previous = prevStatusRef.current;
|
|
11180
11933
|
statusRef.current = status;
|
|
11181
11934
|
prevStatusRef.current = status;
|
|
@@ -11185,7 +11938,7 @@ function PiChatPanel({
|
|
|
11185
11938
|
if (!isPiBusyStatus(previous) && previous !== "submitted") return;
|
|
11186
11939
|
settlePendingAutoSubmit();
|
|
11187
11940
|
}, [settlePendingAutoSubmit, status]);
|
|
11188
|
-
|
|
11941
|
+
useEffect23(() => {
|
|
11189
11942
|
if (!autoSubmitInitialDraft || !policy || !activeSessionId || composerBlocked) return;
|
|
11190
11943
|
if (!initialDraftGuard.current.claimAutoSubmit(activeSessionId, initialDraft)) return;
|
|
11191
11944
|
pendingAutoSubmitSettleRef.current = activeSessionId;
|
|
@@ -11204,9 +11957,14 @@ function PiChatPanel({
|
|
|
11204
11957
|
}
|
|
11205
11958
|
return;
|
|
11206
11959
|
}
|
|
11960
|
+
if (result.type === "stale") {
|
|
11961
|
+
settlePendingAutoSubmit(activeSessionId);
|
|
11962
|
+
return;
|
|
11963
|
+
}
|
|
11207
11964
|
if (result.type === "prompt" || result.type === "followup") {
|
|
11208
11965
|
dropLocalNotice(RUN_REJECTED_NOTICE_ID);
|
|
11209
11966
|
}
|
|
11967
|
+
if (result.type === "handled") surfaceHandledSubmit(result.message);
|
|
11210
11968
|
if (result.type === "prompt") {
|
|
11211
11969
|
onPromptSubmitStarted?.({ sessionId: activeSessionId, clientNonce: result.clientNonce });
|
|
11212
11970
|
if (shouldHoldLocalSubmitted(selectedPiSession, result.cursor)) markLocalSubmitted(activeSessionId);
|
|
@@ -11218,13 +11976,14 @@ function PiChatPanel({
|
|
|
11218
11976
|
settlePendingAutoSubmit(activeSessionId);
|
|
11219
11977
|
}
|
|
11220
11978
|
}).catch((error) => {
|
|
11979
|
+
if (!isPolicySessionActive()) return;
|
|
11221
11980
|
clearLocalSubmitted(activeSessionId);
|
|
11222
11981
|
restoreSubmittedDraft();
|
|
11223
11982
|
settlePendingAutoSubmit(activeSessionId);
|
|
11224
11983
|
surfaceRunRejected(error);
|
|
11225
11984
|
});
|
|
11226
|
-
}, [activeSessionId, autoSubmitInitialDraft, clearLocalSubmitted, composerBlocked, dropLocalNotice, initialDraft, markLocalSubmitted, onAutoSubmitInitialDraftAccepted, onPromptSubmitStarted, policy, selectedPiSession, setComposerDraft, settlePendingAutoSubmit, surfaceRunRejected]);
|
|
11227
|
-
|
|
11985
|
+
}, [activeSessionId, autoSubmitInitialDraft, clearLocalSubmitted, composerBlocked, dropLocalNotice, initialDraft, isPolicySessionActive, markLocalSubmitted, onAutoSubmitInitialDraftAccepted, onPromptSubmitStarted, policy, selectedPiSession, setComposerDraft, settlePendingAutoSubmit, surfaceHandledSubmit, surfaceRunRejected]);
|
|
11986
|
+
useEffect23(() => {
|
|
11228
11987
|
if (workspaceWarmupStatus?.status === "ready") {
|
|
11229
11988
|
clearLocalNotice("workspace-warmup");
|
|
11230
11989
|
}
|
|
@@ -11238,20 +11997,20 @@ function PiChatPanel({
|
|
|
11238
11997
|
const isStreaming = isPiBusyStatus(status);
|
|
11239
11998
|
const submitStatus = initialHydrationPromptAllowed ? "ready" : toPromptSubmitStatus(status);
|
|
11240
11999
|
const submitDisabled = !policy || sessionsLoading || modelSelectionBlocked || composerBlocked && !isStreaming;
|
|
11241
|
-
const mergedToolRenderers =
|
|
11242
|
-
const debugMessages =
|
|
11243
|
-
const onTextareaChange =
|
|
12000
|
+
const mergedToolRenderers = useMemo17(() => mergeShadcnToolRenderers(toolRenderers), [toolRenderers]);
|
|
12001
|
+
const debugMessages = useMemo17(() => messages.map(toDebugUiMessage), [messages]);
|
|
12002
|
+
const onTextareaChange = useCallback19((event) => {
|
|
11244
12003
|
setModelPickerOpen(false);
|
|
11245
12004
|
setThinkingPickerOpen(false);
|
|
11246
12005
|
setDraft(event.currentTarget.value);
|
|
11247
12006
|
handleComposerChange(event);
|
|
11248
12007
|
}, [handleComposerChange]);
|
|
11249
|
-
|
|
12008
|
+
useEffect23(() => {
|
|
11250
12009
|
if (!isStreaming) return;
|
|
11251
12010
|
setModelPickerOpen(false);
|
|
11252
12011
|
setThinkingPickerOpen(false);
|
|
11253
12012
|
}, [isStreaming]);
|
|
11254
|
-
|
|
12013
|
+
useEffect23(() => {
|
|
11255
12014
|
if (typeof window === "undefined" || !activeChatSessionId) return;
|
|
11256
12015
|
const emitStatus = () => window.dispatchEvent(new CustomEvent("boring:chat-session-status", {
|
|
11257
12016
|
detail: {
|
|
@@ -11265,7 +12024,7 @@ function PiChatPanel({
|
|
|
11265
12024
|
window.addEventListener("boring:chat-session-status-request", emitStatus);
|
|
11266
12025
|
return () => window.removeEventListener("boring:chat-session-status-request", emitStatus);
|
|
11267
12026
|
}, [activeChatSessionId, agentTypeId, isStreaming, workspaceId]);
|
|
11268
|
-
const onTextareaKeyDown =
|
|
12027
|
+
const onTextareaKeyDown = useCallback19((event) => {
|
|
11269
12028
|
if (event.key === "Escape" && isStreaming) {
|
|
11270
12029
|
if (event.defaultPrevented || mentionState !== null || slashQuery !== null) {
|
|
11271
12030
|
handleComposerKeyDown(event);
|
|
@@ -11277,14 +12036,14 @@ function PiChatPanel({
|
|
|
11277
12036
|
}
|
|
11278
12037
|
handleComposerKeyDown(event);
|
|
11279
12038
|
}, [handleComposerKeyDown, interrupt, isStreaming, mentionState, slashQuery]);
|
|
11280
|
-
const selectEmptySuggestion =
|
|
12039
|
+
const selectEmptySuggestion = useCallback19((suggestion) => {
|
|
11281
12040
|
const text = suggestion.prompt ?? suggestion.label;
|
|
11282
12041
|
if (!text.trim()) return;
|
|
11283
12042
|
void sendComposerMessage({ text, files: [], source: "suggestion" }).then((result) => {
|
|
11284
12043
|
if (result === false) setComposerDraft(text);
|
|
11285
12044
|
});
|
|
11286
12045
|
}, [sendComposerMessage, setComposerDraft]);
|
|
11287
|
-
const composerSurface = /* @__PURE__ */
|
|
12046
|
+
const composerSurface = /* @__PURE__ */ jsx35(
|
|
11288
12047
|
PiChatComposerSurface,
|
|
11289
12048
|
{
|
|
11290
12049
|
chrome,
|
|
@@ -11303,6 +12062,10 @@ function PiChatPanel({
|
|
|
11303
12062
|
onComposerBlockerAction,
|
|
11304
12063
|
queuePreview,
|
|
11305
12064
|
onEditQueued: editQueued,
|
|
12065
|
+
onRemoveQueued: removeQueued,
|
|
12066
|
+
queueMutationPending,
|
|
12067
|
+
onResumeQueued: resumeQueued,
|
|
12068
|
+
resumeQueuedPending,
|
|
11306
12069
|
hotReloadEnabled,
|
|
11307
12070
|
pluginUpdateState,
|
|
11308
12071
|
onDismissPluginUpdate: dismissPluginUpdate,
|
|
@@ -11351,7 +12114,7 @@ function PiChatPanel({
|
|
|
11351
12114
|
onStop: stop
|
|
11352
12115
|
}
|
|
11353
12116
|
);
|
|
11354
|
-
return /* @__PURE__ */
|
|
12117
|
+
return /* @__PURE__ */ jsx35(ArtifactOpenProvider, { onOpenArtifact, children: /* @__PURE__ */ jsxs31(
|
|
11355
12118
|
"div",
|
|
11356
12119
|
{
|
|
11357
12120
|
"data-boring-agent": "",
|
|
@@ -11369,7 +12132,7 @@ function PiChatPanel({
|
|
|
11369
12132
|
role: "region",
|
|
11370
12133
|
"aria-label": "Agent assistant",
|
|
11371
12134
|
children: [
|
|
11372
|
-
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(
|
|
11373
12136
|
SessionList,
|
|
11374
12137
|
{
|
|
11375
12138
|
sessions: sessionList,
|
|
@@ -11383,7 +12146,7 @@ function PiChatPanel({
|
|
|
11383
12146
|
loadingMore: sessions.loadingMore
|
|
11384
12147
|
}
|
|
11385
12148
|
) }) : null,
|
|
11386
|
-
/* @__PURE__ */
|
|
12149
|
+
/* @__PURE__ */ jsx35("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: /* @__PURE__ */ jsxs31(
|
|
11387
12150
|
"div",
|
|
11388
12151
|
{
|
|
11389
12152
|
className: cn(
|
|
@@ -11392,7 +12155,7 @@ function PiChatPanel({
|
|
|
11392
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)]"
|
|
11393
12156
|
),
|
|
11394
12157
|
children: [
|
|
11395
|
-
/* @__PURE__ */
|
|
12158
|
+
/* @__PURE__ */ jsx35(
|
|
11396
12159
|
PiConversationSurface,
|
|
11397
12160
|
{
|
|
11398
12161
|
chrome,
|
|
@@ -11418,13 +12181,13 @@ function PiChatPanel({
|
|
|
11418
12181
|
}
|
|
11419
12182
|
),
|
|
11420
12183
|
composerSurface,
|
|
11421
|
-
emptyHero ? /* @__PURE__ */
|
|
12184
|
+
emptyHero ? /* @__PURE__ */ jsxs31(
|
|
11422
12185
|
"div",
|
|
11423
12186
|
{
|
|
11424
12187
|
"data-boring-agent-part": "empty-hero-suggestions",
|
|
11425
12188
|
className: "@container mx-auto w-full max-w-[640px] px-2 pb-4",
|
|
11426
12189
|
children: [
|
|
11427
|
-
/* @__PURE__ */
|
|
12190
|
+
/* @__PURE__ */ jsx35(ChatSuggestionGrid, { suggestions, onSelect: selectEmptySuggestion, className: "mt-4" }),
|
|
11428
12191
|
emptyState?.footer
|
|
11429
12192
|
]
|
|
11430
12193
|
}
|
|
@@ -11432,7 +12195,7 @@ function PiChatPanel({
|
|
|
11432
12195
|
]
|
|
11433
12196
|
}
|
|
11434
12197
|
) }),
|
|
11435
|
-
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(
|
|
11436
12199
|
DebugDrawer2,
|
|
11437
12200
|
{
|
|
11438
12201
|
agentTypeId,
|
|
@@ -11453,17 +12216,18 @@ function PiChatPanel({
|
|
|
11453
12216
|
}
|
|
11454
12217
|
|
|
11455
12218
|
// src/front/chat/useAddressedAgentSelection.ts
|
|
11456
|
-
import { useCallback as
|
|
12219
|
+
import { useCallback as useCallback20, useEffect as useEffect24, useMemo as useMemo18, useState as useState23 } from "react";
|
|
11457
12220
|
var inFlightDiscoveries = /* @__PURE__ */ new WeakMap();
|
|
11458
12221
|
function useAddressedAgentSelection({
|
|
11459
12222
|
apiBaseUrl,
|
|
11460
12223
|
requestHeaders,
|
|
11461
12224
|
storageScope,
|
|
12225
|
+
preferredAgentTypeId,
|
|
11462
12226
|
fetch: fetch2,
|
|
11463
12227
|
enabled = false
|
|
11464
12228
|
} = {}) {
|
|
11465
12229
|
const normalizedBaseUrl = apiBaseUrl?.replace(/\/$/, "") ?? "";
|
|
11466
|
-
const headersKey =
|
|
12230
|
+
const headersKey = useMemo18(
|
|
11467
12231
|
() => JSON.stringify({
|
|
11468
12232
|
storageScope: storageScope ?? "",
|
|
11469
12233
|
headers: Object.entries(requestHeaders ?? {}).sort(([a], [b]) => a.localeCompare(b))
|
|
@@ -11473,14 +12237,14 @@ function useAddressedAgentSelection({
|
|
|
11473
12237
|
const discoveryKey = `${normalizedBaseUrl}
|
|
11474
12238
|
${headersKey}`;
|
|
11475
12239
|
const fetchImpl = fetch2 ?? globalThis.fetch;
|
|
11476
|
-
const [state, setState] =
|
|
12240
|
+
const [state, setState] = useState23(() => ({
|
|
11477
12241
|
discoveryKey: enabled ? "" : discoveryKey,
|
|
11478
12242
|
agents: [],
|
|
11479
12243
|
selectedAgentTypeId: void 0,
|
|
11480
12244
|
loading: enabled,
|
|
11481
12245
|
error: void 0
|
|
11482
12246
|
}));
|
|
11483
|
-
|
|
12247
|
+
useEffect24(() => {
|
|
11484
12248
|
if (!enabled) {
|
|
11485
12249
|
setState({
|
|
11486
12250
|
discoveryKey,
|
|
@@ -11506,7 +12270,7 @@ ${headersKey}`;
|
|
|
11506
12270
|
setState((previous) => ({
|
|
11507
12271
|
discoveryKey,
|
|
11508
12272
|
agents: agents2,
|
|
11509
|
-
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,
|
|
11510
12274
|
loading: false,
|
|
11511
12275
|
error: void 0
|
|
11512
12276
|
}));
|
|
@@ -11523,11 +12287,11 @@ ${headersKey}`;
|
|
|
11523
12287
|
return () => {
|
|
11524
12288
|
cancelled = true;
|
|
11525
12289
|
};
|
|
11526
|
-
}, [discoveryKey, enabled, fetchImpl, normalizedBaseUrl]);
|
|
12290
|
+
}, [discoveryKey, enabled, fetchImpl, normalizedBaseUrl, preferredAgentTypeId]);
|
|
11527
12291
|
const current = state.discoveryKey === discoveryKey;
|
|
11528
12292
|
const agents = enabled && current ? state.agents : [];
|
|
11529
12293
|
const selectedAgentTypeId = enabled && current ? state.selectedAgentTypeId : void 0;
|
|
11530
|
-
const selectAgentTypeId =
|
|
12294
|
+
const selectAgentTypeId = useCallback20((agentTypeId) => {
|
|
11531
12295
|
setState((previous) => {
|
|
11532
12296
|
if (previous.discoveryKey !== discoveryKey) return previous;
|
|
11533
12297
|
if (!previous.agents.some((agent) => agent.agentTypeId === agentTypeId)) return previous;
|