@hachej/boring-agent 0.1.35 → 0.1.37
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/{agentPluginEvents-CAMp363h.d.ts → agentPluginEvents-DgNc3erX.d.ts} +39 -1
- package/dist/chunk-DGRKMMXO.js +8 -0
- package/dist/front/index.d.ts +16 -1
- package/dist/front/index.js +697 -358
- package/dist/front/styles.css +27 -0
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +110 -8
- package/dist/shared/index.d.ts +6 -6
- package/dist/shared/index.js +4 -2
- package/package.json +2 -2
- package/dist/chunk-NZN2PRET.js +0 -6
package/dist/front/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
WORKSPACE_AGENT_PLUGINS_RELOADED_EVENT
|
|
3
|
-
|
|
2
|
+
WORKSPACE_AGENT_PLUGINS_RELOADED_EVENT,
|
|
3
|
+
WORKSPACE_COMMAND_NOTIFY_EVENT
|
|
4
|
+
} from "../chunk-DGRKMMXO.js";
|
|
4
5
|
import {
|
|
5
6
|
CommandReceiptSchema,
|
|
6
7
|
ErrorCode,
|
|
@@ -56,7 +57,7 @@ async function uploadFile(file, opts = {}) {
|
|
|
56
57
|
}
|
|
57
58
|
|
|
58
59
|
// src/front/chat/PiChatPanel.tsx
|
|
59
|
-
import { lazy, Suspense, useCallback as
|
|
60
|
+
import { lazy, Suspense, useCallback as useCallback18, useEffect as useEffect21, useMemo as useMemo12, useRef as useRef16, useState as useState20 } from "react";
|
|
60
61
|
|
|
61
62
|
// src/front/ArtifactOpenContext.tsx
|
|
62
63
|
import { createContext, useContext } from "react";
|
|
@@ -234,6 +235,9 @@ function createCommandRegistry(initial) {
|
|
|
234
235
|
register(cmd) {
|
|
235
236
|
commands.set(cmd.name, cmd);
|
|
236
237
|
},
|
|
238
|
+
unregister(name) {
|
|
239
|
+
commands.delete(name);
|
|
240
|
+
},
|
|
237
241
|
get(name) {
|
|
238
242
|
return commands.get(name);
|
|
239
243
|
},
|
|
@@ -254,6 +258,13 @@ var builtinCommands = [
|
|
|
254
258
|
return "Session reset.";
|
|
255
259
|
}
|
|
256
260
|
},
|
|
261
|
+
{
|
|
262
|
+
name: "clear",
|
|
263
|
+
description: "Hide messages from display",
|
|
264
|
+
handler(_, ctx) {
|
|
265
|
+
ctx.clearMessages();
|
|
266
|
+
}
|
|
267
|
+
},
|
|
257
268
|
{
|
|
258
269
|
name: "reload",
|
|
259
270
|
description: "Reload agent plugins",
|
|
@@ -295,7 +306,12 @@ var builtinCommands = [
|
|
|
295
306
|
handler(_, ctx) {
|
|
296
307
|
const cmds = ctx.listCommands();
|
|
297
308
|
if (cmds.length === 0) return "No commands available.";
|
|
298
|
-
|
|
309
|
+
const escape = (text) => text.replace(/\|/g, "\\|").replace(/\n/g, " ");
|
|
310
|
+
return [
|
|
311
|
+
"| Command | Description |",
|
|
312
|
+
"| --- | --- |",
|
|
313
|
+
...cmds.map((c) => `| \`/${c.name}\` | ${escape(c.description ?? "")} |`)
|
|
314
|
+
].join("\n");
|
|
299
315
|
}
|
|
300
316
|
}
|
|
301
317
|
];
|
|
@@ -1976,17 +1992,18 @@ function usePickerKeyboard({
|
|
|
1976
1992
|
useEffect3(() => {
|
|
1977
1993
|
const handler = (e) => {
|
|
1978
1994
|
if (e.key === "ArrowDown") {
|
|
1979
|
-
if (count <= 0) return;
|
|
1980
1995
|
e.preventDefault();
|
|
1981
|
-
setActiveIdx((i) =>
|
|
1996
|
+
setActiveIdx((i) => count === 0 ? 0 : (i + 1) % count);
|
|
1982
1997
|
} else if (e.key === "ArrowUp") {
|
|
1983
|
-
if (count <= 0) return;
|
|
1984
1998
|
e.preventDefault();
|
|
1985
|
-
setActiveIdx((i) =>
|
|
1999
|
+
setActiveIdx((i) => count === 0 ? 0 : (i - 1 + count) % count);
|
|
1986
2000
|
} else if (e.key === "Enter" || e.key === "Tab") {
|
|
1987
|
-
if (count
|
|
1988
|
-
|
|
1989
|
-
|
|
2001
|
+
if (count > 0) {
|
|
2002
|
+
e.preventDefault();
|
|
2003
|
+
selectRef.current(activeIdx);
|
|
2004
|
+
} else {
|
|
2005
|
+
dismissRef.current();
|
|
2006
|
+
}
|
|
1990
2007
|
} else if (e.key === "Escape") {
|
|
1991
2008
|
e.preventDefault();
|
|
1992
2009
|
dismissRef.current();
|
|
@@ -2680,53 +2697,104 @@ function scopedHeaders2(headers, storageScope) {
|
|
|
2680
2697
|
return result;
|
|
2681
2698
|
}
|
|
2682
2699
|
|
|
2683
|
-
// src/front/hooks/
|
|
2684
|
-
import { useEffect as useEffect6, useState as useState8 } from "react";
|
|
2685
|
-
function
|
|
2686
|
-
|
|
2687
|
-
|
|
2700
|
+
// src/front/hooks/useServerCommands.ts
|
|
2701
|
+
import { useEffect as useEffect6, useRef as useRef7, useState as useState8 } from "react";
|
|
2702
|
+
function toSlashCommand(command, getSessionId, apiBaseUrl, requestHeaders, fetchImpl) {
|
|
2703
|
+
return {
|
|
2704
|
+
name: command.name,
|
|
2705
|
+
description: command.description ?? "",
|
|
2706
|
+
source: command.source,
|
|
2707
|
+
...command.sourcePlugin ? { sourcePlugin: command.sourcePlugin } : {},
|
|
2708
|
+
handler: async (args) => {
|
|
2709
|
+
const base = apiBaseUrl?.replace(/\/$/, "") ?? "";
|
|
2710
|
+
const params = new URLSearchParams({ sessionId: getSessionId() });
|
|
2711
|
+
const url = `${base}/api/v1/agent/commands/execute?${params.toString()}`;
|
|
2712
|
+
try {
|
|
2713
|
+
const res = await fetchImpl(url, {
|
|
2714
|
+
method: "POST",
|
|
2715
|
+
headers: { ...requestHeaders ?? {}, "content-type": "application/json" },
|
|
2716
|
+
body: JSON.stringify({ name: command.name, args })
|
|
2717
|
+
});
|
|
2718
|
+
if (!res.ok) {
|
|
2719
|
+
const body = await res.json().catch(() => ({}));
|
|
2720
|
+
if (typeof globalThis.dispatchEvent === "function") {
|
|
2721
|
+
globalThis.dispatchEvent(new CustomEvent(WORKSPACE_COMMAND_NOTIFY_EVENT, {
|
|
2722
|
+
detail: { message: body.error ?? `/${command.name} failed`, tone: "error", command: command.name }
|
|
2723
|
+
}));
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2726
|
+
} catch {
|
|
2727
|
+
if (typeof globalThis.dispatchEvent === "function") {
|
|
2728
|
+
globalThis.dispatchEvent(new CustomEvent(WORKSPACE_COMMAND_NOTIFY_EVENT, {
|
|
2729
|
+
detail: { message: `/${command.name} could not be reached`, tone: "error", command: command.name }
|
|
2730
|
+
}));
|
|
2731
|
+
}
|
|
2732
|
+
}
|
|
2733
|
+
}
|
|
2734
|
+
};
|
|
2735
|
+
}
|
|
2736
|
+
function useServerCommands({
|
|
2688
2737
|
registry,
|
|
2689
2738
|
requestHeaders,
|
|
2739
|
+
sessionId,
|
|
2740
|
+
apiBaseUrl,
|
|
2741
|
+
fetch: fetchImpl,
|
|
2690
2742
|
storageScope,
|
|
2691
|
-
|
|
2692
|
-
|
|
2743
|
+
enabled = true,
|
|
2744
|
+
refreshKey = 0
|
|
2693
2745
|
}) {
|
|
2694
|
-
const [
|
|
2746
|
+
const [stamp, setStamp] = useState8(0);
|
|
2747
|
+
const registeredNamesRef = useRef7(/* @__PURE__ */ new Set());
|
|
2748
|
+
const sessionIdRef = useRef7(sessionId);
|
|
2695
2749
|
useEffect6(() => {
|
|
2696
|
-
|
|
2750
|
+
sessionIdRef.current = sessionId;
|
|
2751
|
+
}, [sessionId]);
|
|
2752
|
+
useEffect6(() => {
|
|
2753
|
+
const clearRegistered = () => {
|
|
2754
|
+
if (registeredNamesRef.current.size === 0) return false;
|
|
2755
|
+
for (const name of registeredNamesRef.current) registry.unregister(name);
|
|
2756
|
+
registeredNamesRef.current = /* @__PURE__ */ new Set();
|
|
2757
|
+
return true;
|
|
2758
|
+
};
|
|
2759
|
+
if (!enabled) {
|
|
2760
|
+
if (clearRegistered()) setStamp((n) => n + 1);
|
|
2761
|
+
return;
|
|
2762
|
+
}
|
|
2697
2763
|
let aborted = false;
|
|
2698
2764
|
const nextFetch = fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
2699
|
-
const
|
|
2700
|
-
|
|
2701
|
-
|
|
2702
|
-
|
|
2703
|
-
if (
|
|
2704
|
-
|
|
2705
|
-
|
|
2706
|
-
|
|
2707
|
-
|
|
2708
|
-
|
|
2709
|
-
|
|
2710
|
-
|
|
2765
|
+
const base = apiBaseUrl?.replace(/\/$/, "") ?? "";
|
|
2766
|
+
const url = `${base}/api/v1/agent/commands?sessionId=${encodeURIComponent(sessionIdRef.current)}`;
|
|
2767
|
+
const headers = scopedHeaders3(requestHeaders, storageScope);
|
|
2768
|
+
nextFetch(url, { headers }).then(async (res) => {
|
|
2769
|
+
if (!res.ok) throw new Error(`commands request failed (${res.status})`);
|
|
2770
|
+
return await res.json();
|
|
2771
|
+
}).then((payload) => {
|
|
2772
|
+
if (aborted) return;
|
|
2773
|
+
const removed = clearRegistered();
|
|
2774
|
+
let added = false;
|
|
2775
|
+
for (const serverCommand of payload.commands ?? []) {
|
|
2776
|
+
const command = toSlashCommand(serverCommand, () => sessionIdRef.current, apiBaseUrl, headers, nextFetch);
|
|
2777
|
+
if (registry.get(command.name)) continue;
|
|
2778
|
+
registry.register(command);
|
|
2779
|
+
registeredNamesRef.current.add(command.name);
|
|
2780
|
+
added = true;
|
|
2711
2781
|
}
|
|
2712
|
-
if (
|
|
2782
|
+
if (removed || added) setStamp((n) => n + 1);
|
|
2713
2783
|
}).catch(() => {
|
|
2784
|
+
if (aborted) return;
|
|
2785
|
+
if (clearRegistered()) setStamp((n) => n + 1);
|
|
2714
2786
|
});
|
|
2715
2787
|
return () => {
|
|
2716
2788
|
aborted = true;
|
|
2717
2789
|
};
|
|
2718
2790
|
}, [apiBaseUrl, enabled, fetchImpl, refreshKey, requestHeaders, registry, storageScope]);
|
|
2719
|
-
return
|
|
2720
|
-
}
|
|
2721
|
-
function agentResourceUrl2(apiBaseUrl, path) {
|
|
2722
|
-
const base = apiBaseUrl?.replace(/\/$/, "") ?? "";
|
|
2723
|
-
return `${base}${path}`;
|
|
2791
|
+
return stamp;
|
|
2724
2792
|
}
|
|
2725
2793
|
function scopedHeaders3(headers, storageScope) {
|
|
2726
2794
|
if (!headers && !storageScope) return void 0;
|
|
2727
2795
|
const result = { ...headers ?? {} };
|
|
2728
|
-
const
|
|
2729
|
-
if (storageScope && !
|
|
2796
|
+
const hasScope = Object.keys(result).some((k) => k.toLowerCase() === "x-boring-storage-scope");
|
|
2797
|
+
if (storageScope && !hasScope) result["x-boring-storage-scope"] = storageScope;
|
|
2730
2798
|
return result;
|
|
2731
2799
|
}
|
|
2732
2800
|
|
|
@@ -3320,7 +3388,7 @@ function resolveStorage2(storage) {
|
|
|
3320
3388
|
}
|
|
3321
3389
|
|
|
3322
3390
|
// src/front/chat/session/usePiSessions.ts
|
|
3323
|
-
import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo3, useRef as
|
|
3391
|
+
import { useCallback as useCallback7, useEffect as useEffect8, useMemo as useMemo3, useRef as useRef8, useState as useState10 } from "react";
|
|
3324
3392
|
|
|
3325
3393
|
// src/front/chat/pi/piChatAssistantCommit.ts
|
|
3326
3394
|
function commitFinalMessage(state, messageId, final) {
|
|
@@ -4863,7 +4931,7 @@ function clearPageUnloading() {
|
|
|
4863
4931
|
// src/front/chat/session/usePiSessions.ts
|
|
4864
4932
|
var DEFAULT_SESSIONS_API_PATH = "/api/v1/agent/pi-chat/sessions";
|
|
4865
4933
|
var SESSION_PAGE_SIZE = 50;
|
|
4866
|
-
var DEFAULT_MAX_RETRIES =
|
|
4934
|
+
var DEFAULT_MAX_RETRIES = 60;
|
|
4867
4935
|
var DEFAULT_RETRY_BASE_MS = 250;
|
|
4868
4936
|
var DEFAULT_RETRY_MAX_MS = 2e3;
|
|
4869
4937
|
var SessionsPreparingError = class extends Error {
|
|
@@ -4872,6 +4940,9 @@ var SessionsPreparingError = class extends Error {
|
|
|
4872
4940
|
this.name = "SessionsPreparingError";
|
|
4873
4941
|
}
|
|
4874
4942
|
};
|
|
4943
|
+
function isNetworkFetchError(error) {
|
|
4944
|
+
return error instanceof TypeError;
|
|
4945
|
+
}
|
|
4875
4946
|
function usePiSessions(options = {}) {
|
|
4876
4947
|
const enabled = options.enabled ?? true;
|
|
4877
4948
|
const apiBaseUrl = options.apiBaseUrl?.replace(/\/$/, "") ?? "";
|
|
@@ -4895,20 +4966,20 @@ function usePiSessions(options = {}) {
|
|
|
4895
4966
|
const [loadingMore, setLoadingMore] = useState10(false);
|
|
4896
4967
|
const [hasMore, setHasMore] = useState10(false);
|
|
4897
4968
|
const [error, setError] = useState10(void 0);
|
|
4898
|
-
const mountedRef =
|
|
4899
|
-
const refreshVersionRef =
|
|
4900
|
-
const retryTimerRef =
|
|
4901
|
-
const sessionsRef =
|
|
4902
|
-
const activeSessionIdRef =
|
|
4903
|
-
const hasMoreRef =
|
|
4904
|
-
const canonicalLoadedCountRef =
|
|
4905
|
-
const loadMoreRequestSeqRef =
|
|
4906
|
-
const loadMoreInFlightRef =
|
|
4907
|
-
const pendingCreatedRef =
|
|
4908
|
-
const pendingCreatedScopeRef =
|
|
4909
|
-
const dataStorageScopeRef =
|
|
4910
|
-
const loadedDataSourceRef =
|
|
4911
|
-
const requestScopeRef =
|
|
4969
|
+
const mountedRef = useRef8(false);
|
|
4970
|
+
const refreshVersionRef = useRef8(0);
|
|
4971
|
+
const retryTimerRef = useRef8(void 0);
|
|
4972
|
+
const sessionsRef = useRef8([]);
|
|
4973
|
+
const activeSessionIdRef = useRef8(activeSessionId);
|
|
4974
|
+
const hasMoreRef = useRef8(hasMore);
|
|
4975
|
+
const canonicalLoadedCountRef = useRef8(0);
|
|
4976
|
+
const loadMoreRequestSeqRef = useRef8(0);
|
|
4977
|
+
const loadMoreInFlightRef = useRef8(false);
|
|
4978
|
+
const pendingCreatedRef = useRef8(/* @__PURE__ */ new Map());
|
|
4979
|
+
const pendingCreatedScopeRef = useRef8(requestScopeKey);
|
|
4980
|
+
const dataStorageScopeRef = useRef8(storageScope);
|
|
4981
|
+
const loadedDataSourceRef = useRef8(dataSourceKey);
|
|
4982
|
+
const requestScopeRef = useRef8(requestScopeKey);
|
|
4912
4983
|
requestScopeRef.current = requestScopeKey;
|
|
4913
4984
|
useEffect8(() => {
|
|
4914
4985
|
sessionsRef.current = sessions;
|
|
@@ -5005,7 +5076,8 @@ function usePiSessions(options = {}) {
|
|
|
5005
5076
|
data = await fetchSessionList(fetchImpl, sessionsListUrl(0, preferredSessionId()), requestHeaders());
|
|
5006
5077
|
break;
|
|
5007
5078
|
} catch (err) {
|
|
5008
|
-
const
|
|
5079
|
+
const transient = err instanceof SessionsPreparingError || isNetworkFetchError(err);
|
|
5080
|
+
const retryable = transient && attempt < retryMaxRetries;
|
|
5009
5081
|
if (!retryable) throw err;
|
|
5010
5082
|
if (!isCurrent()) return;
|
|
5011
5083
|
await delayWithRef(retryDelayMs(attempt, { baseMs: retryBaseMs, maxMs: retryMaxMs }), retryTimerRef);
|
|
@@ -5429,7 +5501,7 @@ function sortByUpdatedDesc(a, b) {
|
|
|
5429
5501
|
|
|
5430
5502
|
// src/front/chat/components/PiConversationSurface.tsx
|
|
5431
5503
|
import { Loader2 as Loader22 } from "lucide-react";
|
|
5432
|
-
import { useCallback as useCallback14, useEffect as useEffect14, useLayoutEffect, useRef as
|
|
5504
|
+
import { useCallback as useCallback14, useEffect as useEffect14, useLayoutEffect, useRef as useRef10, useState as useState15 } from "react";
|
|
5433
5505
|
import { useStickToBottomContext as useStickToBottomContext2 } from "use-stick-to-bottom";
|
|
5434
5506
|
|
|
5435
5507
|
// src/front/primitives/conversation.tsx
|
|
@@ -6125,7 +6197,7 @@ import {
|
|
|
6125
6197
|
useContext as useContext5,
|
|
6126
6198
|
useEffect as useEffect11,
|
|
6127
6199
|
useMemo as useMemo8,
|
|
6128
|
-
useRef as
|
|
6200
|
+
useRef as useRef9,
|
|
6129
6201
|
useState as useState12
|
|
6130
6202
|
} from "react";
|
|
6131
6203
|
import { Streamdown as Streamdown2 } from "streamdown";
|
|
@@ -6217,9 +6289,9 @@ var Reasoning = memo5(
|
|
|
6217
6289
|
defaultProp: void 0,
|
|
6218
6290
|
prop: durationProp
|
|
6219
6291
|
});
|
|
6220
|
-
const hasEverStreamedRef =
|
|
6292
|
+
const hasEverStreamedRef = useRef9(isStreaming);
|
|
6221
6293
|
const [hasAutoClosed, setHasAutoClosed] = useState12(false);
|
|
6222
|
-
const startTimeRef =
|
|
6294
|
+
const startTimeRef = useRef9(null);
|
|
6223
6295
|
useEffect11(() => {
|
|
6224
6296
|
if (isStreaming) {
|
|
6225
6297
|
hasEverStreamedRef.current = true;
|
|
@@ -6947,8 +7019,8 @@ function PiConversationSurface({
|
|
|
6947
7019
|
}
|
|
6948
7020
|
function TranscriptHistoryLoader({ olderCount, onLoadOlder }) {
|
|
6949
7021
|
const { scrollRef } = useStickToBottomContext2();
|
|
6950
|
-
const pendingAnchor =
|
|
6951
|
-
const armed =
|
|
7022
|
+
const pendingAnchor = useRef10(null);
|
|
7023
|
+
const armed = useRef10(true);
|
|
6952
7024
|
useEffect14(() => {
|
|
6953
7025
|
const el = scrollRef.current;
|
|
6954
7026
|
if (!el) return;
|
|
@@ -7009,38 +7081,34 @@ function buildMessageRenderItems(messages) {
|
|
|
7009
7081
|
}
|
|
7010
7082
|
|
|
7011
7083
|
// src/front/chat/components/PiChatComposerSurface.tsx
|
|
7012
|
-
import { useCallback as
|
|
7084
|
+
import { useCallback as useCallback16, useLayoutEffect as useLayoutEffect2 } from "react";
|
|
7013
7085
|
import { motion as motion2 } from "motion/react";
|
|
7014
7086
|
|
|
7015
7087
|
// src/front/composer/PluginUpdateStatus.tsx
|
|
7016
|
-
import { useEffect as useEffect15, useRef as
|
|
7017
|
-
|
|
7088
|
+
import { useEffect as useEffect15, useRef as useRef11 } from "react";
|
|
7089
|
+
|
|
7090
|
+
// src/front/composer/ComposerStatusBanner.tsx
|
|
7018
7091
|
import { jsx as jsx24, jsxs as jsxs22 } from "react/jsx-runtime";
|
|
7019
|
-
function
|
|
7020
|
-
|
|
7092
|
+
function ComposerStatusBanner({
|
|
7093
|
+
tone,
|
|
7094
|
+
dataAttribute,
|
|
7095
|
+
runningContent,
|
|
7096
|
+
title,
|
|
7097
|
+
detail,
|
|
7098
|
+
message,
|
|
7099
|
+
children,
|
|
7021
7100
|
onDismiss,
|
|
7022
7101
|
onRetry,
|
|
7023
|
-
|
|
7102
|
+
retryLabel = "Try again",
|
|
7103
|
+
dismissAriaLabel = "Dismiss status",
|
|
7024
7104
|
maxWidthClassName = "max-w-3xl"
|
|
7025
7105
|
}) {
|
|
7026
|
-
const
|
|
7027
|
-
|
|
7028
|
-
onDismissRef.current = onDismiss;
|
|
7029
|
-
}, [onDismiss]);
|
|
7030
|
-
const successDismissKey = state?.kind === "success" ? `${state.reloaded}:${(state.restartWarnings?.length ?? 0) > 0 || (state.diagnostics?.length ?? 0) > 0}` : null;
|
|
7031
|
-
useEffect15(() => {
|
|
7032
|
-
if (!state || state.kind !== "success" || successAutoDismissMs <= 0) return;
|
|
7033
|
-
const hasWarningsOrDiagnostics = (state.restartWarnings?.length ?? 0) > 0 || (state.diagnostics?.length ?? 0) > 0;
|
|
7034
|
-
if (hasWarningsOrDiagnostics) return;
|
|
7035
|
-
const timeout = window.setTimeout(() => onDismissRef.current(), successAutoDismissMs);
|
|
7036
|
-
return () => window.clearTimeout(timeout);
|
|
7037
|
-
}, [state?.kind, successDismissKey, successAutoDismissMs]);
|
|
7038
|
-
if (!state) return null;
|
|
7039
|
-
if (state.kind === "running") {
|
|
7106
|
+
const toneAttr = { [dataAttribute]: tone };
|
|
7107
|
+
if (tone === "running") {
|
|
7040
7108
|
return /* @__PURE__ */ jsxs22(
|
|
7041
7109
|
"div",
|
|
7042
7110
|
{
|
|
7043
|
-
|
|
7111
|
+
...toneAttr,
|
|
7044
7112
|
role: "status",
|
|
7045
7113
|
"aria-live": "polite",
|
|
7046
7114
|
className: cn(
|
|
@@ -7050,22 +7118,16 @@ function PluginUpdateStatus({
|
|
|
7050
7118
|
),
|
|
7051
7119
|
children: [
|
|
7052
7120
|
/* @__PURE__ */ jsx24("span", { className: "inline-block h-2 w-2 animate-pulse rounded-full bg-accent", "aria-hidden": "true" }),
|
|
7053
|
-
/* @__PURE__ */ jsx24("span", { children:
|
|
7121
|
+
/* @__PURE__ */ jsx24("span", { children: runningContent })
|
|
7054
7122
|
]
|
|
7055
7123
|
}
|
|
7056
7124
|
);
|
|
7057
7125
|
}
|
|
7058
|
-
if (
|
|
7059
|
-
const warnings = state.restartWarnings ?? [];
|
|
7060
|
-
const diagnostics = state.diagnostics ?? [];
|
|
7061
|
-
const frontEvents = state.frontEvents ?? [];
|
|
7062
|
-
const hasWarningsOrDiagnostics = warnings.length > 0 || diagnostics.length > 0;
|
|
7063
|
-
const title = state.reloaded ? hasWarningsOrDiagnostics ? "Reload finished with warnings" : "Reload complete" : "Reload queued";
|
|
7064
|
-
const detail = state.reloaded ? hasWarningsOrDiagnostics ? "Some plugin changes need attention." : frontEvents.length > 0 ? `${frontEvents.length} plugin module${frontEvents.length === 1 ? "" : "s"} refreshed. Changes are live.` : "Changes are live." : void 0;
|
|
7126
|
+
if (tone === "success") {
|
|
7065
7127
|
return /* @__PURE__ */ jsxs22(
|
|
7066
7128
|
"div",
|
|
7067
7129
|
{
|
|
7068
|
-
|
|
7130
|
+
...toneAttr,
|
|
7069
7131
|
role: "status",
|
|
7070
7132
|
"aria-live": "polite",
|
|
7071
7133
|
className: cn(
|
|
@@ -7080,18 +7142,115 @@ function PluginUpdateStatus({
|
|
|
7080
7142
|
/* @__PURE__ */ jsx24("span", { className: "block font-medium leading-5", children: title }),
|
|
7081
7143
|
detail ? /* @__PURE__ */ jsx24("span", { className: "block leading-4 text-muted-foreground", children: detail }) : null
|
|
7082
7144
|
] }),
|
|
7083
|
-
/* @__PURE__ */ jsx24(
|
|
7145
|
+
onDismiss ? /* @__PURE__ */ jsx24(
|
|
7084
7146
|
"button",
|
|
7085
7147
|
{
|
|
7086
7148
|
type: "button",
|
|
7087
7149
|
onClick: onDismiss,
|
|
7088
7150
|
className: "-mr-1 rounded border border-transparent px-1.5 py-0.5 text-[13px] leading-none text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
7089
|
-
"aria-label":
|
|
7151
|
+
"aria-label": dismissAriaLabel,
|
|
7090
7152
|
children: "\xD7"
|
|
7091
7153
|
}
|
|
7092
|
-
)
|
|
7154
|
+
) : null
|
|
7093
7155
|
] }),
|
|
7094
|
-
|
|
7156
|
+
children
|
|
7157
|
+
]
|
|
7158
|
+
}
|
|
7159
|
+
);
|
|
7160
|
+
}
|
|
7161
|
+
return /* @__PURE__ */ jsxs22(
|
|
7162
|
+
"div",
|
|
7163
|
+
{
|
|
7164
|
+
...toneAttr,
|
|
7165
|
+
role: "status",
|
|
7166
|
+
"aria-live": "polite",
|
|
7167
|
+
className: cn(
|
|
7168
|
+
"mx-auto mb-2 w-full rounded-[var(--radius-md)] border border-destructive/40 bg-destructive/10",
|
|
7169
|
+
"px-3 py-2 text-xs text-foreground",
|
|
7170
|
+
maxWidthClassName
|
|
7171
|
+
),
|
|
7172
|
+
children: [
|
|
7173
|
+
/* @__PURE__ */ jsxs22("div", { className: "flex items-center gap-2", children: [
|
|
7174
|
+
/* @__PURE__ */ jsx24("span", { className: "text-destructive", "aria-hidden": "true", children: "\u26A0" }),
|
|
7175
|
+
/* @__PURE__ */ jsx24("span", { className: "flex-1 font-medium", children: title }),
|
|
7176
|
+
onRetry ? /* @__PURE__ */ jsx24(
|
|
7177
|
+
"button",
|
|
7178
|
+
{
|
|
7179
|
+
type: "button",
|
|
7180
|
+
onClick: onRetry,
|
|
7181
|
+
className: "rounded border border-destructive/40 px-2 py-0.5 text-[11px] font-medium hover:bg-destructive/10",
|
|
7182
|
+
children: retryLabel
|
|
7183
|
+
}
|
|
7184
|
+
) : null,
|
|
7185
|
+
onDismiss ? /* @__PURE__ */ jsx24(
|
|
7186
|
+
"button",
|
|
7187
|
+
{
|
|
7188
|
+
type: "button",
|
|
7189
|
+
onClick: onDismiss,
|
|
7190
|
+
className: "rounded border border-transparent px-2 py-0.5 text-[11px] font-medium text-muted-foreground hover:bg-muted hover:text-foreground",
|
|
7191
|
+
"aria-label": dismissAriaLabel,
|
|
7192
|
+
children: "Dismiss"
|
|
7193
|
+
}
|
|
7194
|
+
) : null
|
|
7195
|
+
] }),
|
|
7196
|
+
message ? /* @__PURE__ */ jsx24("pre", { className: "mt-2 whitespace-pre-wrap break-words text-[11px] text-destructive/90", children: message }) : null
|
|
7197
|
+
]
|
|
7198
|
+
}
|
|
7199
|
+
);
|
|
7200
|
+
}
|
|
7201
|
+
|
|
7202
|
+
// src/front/composer/PluginUpdateStatus.tsx
|
|
7203
|
+
import { jsx as jsx25, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
7204
|
+
function PluginUpdateStatus({
|
|
7205
|
+
state,
|
|
7206
|
+
onDismiss,
|
|
7207
|
+
onRetry,
|
|
7208
|
+
successAutoDismissMs = 1400,
|
|
7209
|
+
maxWidthClassName = "max-w-3xl"
|
|
7210
|
+
}) {
|
|
7211
|
+
const onDismissRef = useRef11(onDismiss);
|
|
7212
|
+
useEffect15(() => {
|
|
7213
|
+
onDismissRef.current = onDismiss;
|
|
7214
|
+
}, [onDismiss]);
|
|
7215
|
+
const successDismissKey = state?.kind === "success" ? `${state.reloaded}:${(state.restartWarnings?.length ?? 0) > 0 || (state.diagnostics?.length ?? 0) > 0}` : null;
|
|
7216
|
+
useEffect15(() => {
|
|
7217
|
+
if (!state || state.kind !== "success" || successAutoDismissMs <= 0) return;
|
|
7218
|
+
const hasWarningsOrDiagnostics = (state.restartWarnings?.length ?? 0) > 0 || (state.diagnostics?.length ?? 0) > 0;
|
|
7219
|
+
if (hasWarningsOrDiagnostics) return;
|
|
7220
|
+
const timeout = window.setTimeout(() => onDismissRef.current(), successAutoDismissMs);
|
|
7221
|
+
return () => window.clearTimeout(timeout);
|
|
7222
|
+
}, [state?.kind, successDismissKey, successAutoDismissMs]);
|
|
7223
|
+
if (!state) return null;
|
|
7224
|
+
if (state.kind === "running") {
|
|
7225
|
+
return /* @__PURE__ */ jsx25(
|
|
7226
|
+
ComposerStatusBanner,
|
|
7227
|
+
{
|
|
7228
|
+
tone: "running",
|
|
7229
|
+
dataAttribute: "data-boring-plugin-update",
|
|
7230
|
+
maxWidthClassName,
|
|
7231
|
+
runningContent: "Updating plugins\u2026"
|
|
7232
|
+
}
|
|
7233
|
+
);
|
|
7234
|
+
}
|
|
7235
|
+
if (state.kind === "success") {
|
|
7236
|
+
const warnings = state.restartWarnings ?? [];
|
|
7237
|
+
const diagnostics = state.diagnostics ?? [];
|
|
7238
|
+
const frontEvents = state.frontEvents ?? [];
|
|
7239
|
+
const hasWarningsOrDiagnostics = warnings.length > 0 || diagnostics.length > 0;
|
|
7240
|
+
const title = state.reloaded ? hasWarningsOrDiagnostics ? "Reload finished with warnings" : "Reload complete" : "Reload queued";
|
|
7241
|
+
const detail = state.reloaded ? hasWarningsOrDiagnostics ? "Some plugin changes need attention." : frontEvents.length > 0 ? `${frontEvents.length} plugin module${frontEvents.length === 1 ? "" : "s"} refreshed. Changes are live.` : "Changes are live." : void 0;
|
|
7242
|
+
return /* @__PURE__ */ jsxs23(
|
|
7243
|
+
ComposerStatusBanner,
|
|
7244
|
+
{
|
|
7245
|
+
tone: "success",
|
|
7246
|
+
dataAttribute: "data-boring-plugin-update",
|
|
7247
|
+
maxWidthClassName,
|
|
7248
|
+
title,
|
|
7249
|
+
detail,
|
|
7250
|
+
onDismiss,
|
|
7251
|
+
dismissAriaLabel: "Dismiss plugin update status",
|
|
7252
|
+
children: [
|
|
7253
|
+
diagnostics.length > 0 ? /* @__PURE__ */ jsxs23(
|
|
7095
7254
|
"div",
|
|
7096
7255
|
{
|
|
7097
7256
|
"data-boring-plugin-update-diagnostics": "",
|
|
@@ -7100,24 +7259,24 @@ function PluginUpdateStatus({
|
|
|
7100
7259
|
"px-2 py-1.5 text-[11px] text-foreground"
|
|
7101
7260
|
),
|
|
7102
7261
|
children: [
|
|
7103
|
-
/* @__PURE__ */
|
|
7104
|
-
/* @__PURE__ */
|
|
7105
|
-
/* @__PURE__ */
|
|
7262
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-1.5 font-medium text-[oklch(0.48_0.15_60)]", children: [
|
|
7263
|
+
/* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: "\u26A0" }),
|
|
7264
|
+
/* @__PURE__ */ jsxs23("span", { children: [
|
|
7106
7265
|
"Reload diagnostics for ",
|
|
7107
7266
|
diagnostics.length,
|
|
7108
7267
|
" plugin",
|
|
7109
7268
|
diagnostics.length === 1 ? "" : "s"
|
|
7110
7269
|
] })
|
|
7111
7270
|
] }),
|
|
7112
|
-
/* @__PURE__ */
|
|
7113
|
-
/* @__PURE__ */
|
|
7271
|
+
/* @__PURE__ */ jsx25("ul", { className: "mt-1 ml-4 list-disc text-foreground/85", children: diagnostics.map((diagnostic, index) => /* @__PURE__ */ jsxs23("li", { children: [
|
|
7272
|
+
/* @__PURE__ */ jsx25("code", { className: "font-mono text-[10.5px]", children: diagnostic.pluginId ?? diagnostic.source ?? "plugin" }),
|
|
7114
7273
|
" \u2014 ",
|
|
7115
7274
|
diagnostic.message ?? "reload diagnostic"
|
|
7116
7275
|
] }, `${diagnostic.pluginId ?? diagnostic.source ?? "plugin"}-${index}`)) })
|
|
7117
7276
|
]
|
|
7118
7277
|
}
|
|
7119
7278
|
) : null,
|
|
7120
|
-
warnings.length > 0 ? /* @__PURE__ */
|
|
7279
|
+
warnings.length > 0 ? /* @__PURE__ */ jsxs23(
|
|
7121
7280
|
"div",
|
|
7122
7281
|
{
|
|
7123
7282
|
"data-boring-plugin-update-restart-warning": "",
|
|
@@ -7126,21 +7285,21 @@ function PluginUpdateStatus({
|
|
|
7126
7285
|
"px-2 py-1.5 text-[11px] text-foreground"
|
|
7127
7286
|
),
|
|
7128
7287
|
children: [
|
|
7129
|
-
/* @__PURE__ */
|
|
7130
|
-
/* @__PURE__ */
|
|
7131
|
-
/* @__PURE__ */
|
|
7288
|
+
/* @__PURE__ */ jsxs23("div", { className: "flex items-center gap-1.5 font-medium text-[oklch(0.48_0.15_60)]", children: [
|
|
7289
|
+
/* @__PURE__ */ jsx25("span", { "aria-hidden": "true", children: "\u26A0" }),
|
|
7290
|
+
/* @__PURE__ */ jsxs23("span", { children: [
|
|
7132
7291
|
"Restart needed for ",
|
|
7133
7292
|
warnings.length,
|
|
7134
7293
|
" plugin",
|
|
7135
7294
|
warnings.length === 1 ? "" : "s"
|
|
7136
7295
|
] })
|
|
7137
7296
|
] }),
|
|
7138
|
-
/* @__PURE__ */
|
|
7139
|
-
/* @__PURE__ */
|
|
7297
|
+
/* @__PURE__ */ jsx25("ul", { className: "mt-1 ml-4 list-disc text-foreground/85", children: warnings.map((w) => /* @__PURE__ */ jsxs23("li", { children: [
|
|
7298
|
+
/* @__PURE__ */ jsx25("code", { className: "font-mono text-[10.5px]", children: w.id }),
|
|
7140
7299
|
" \u2014 ",
|
|
7141
7300
|
w.surfaces.join(" + ")
|
|
7142
7301
|
] }, w.id)) }),
|
|
7143
|
-
/* @__PURE__ */
|
|
7302
|
+
/* @__PURE__ */ jsx25("p", { className: "mt-1 text-foreground/70", children: "The front bundle reloaded successfully, but routes and agent tools were wired at boot. Stop and restart the workspace process (Ctrl-C, then re-run your dev command) to pick up the new code." })
|
|
7144
7303
|
]
|
|
7145
7304
|
}
|
|
7146
7305
|
) : null
|
|
@@ -7148,45 +7307,104 @@ function PluginUpdateStatus({
|
|
|
7148
7307
|
}
|
|
7149
7308
|
);
|
|
7150
7309
|
}
|
|
7151
|
-
return /* @__PURE__ */
|
|
7152
|
-
|
|
7310
|
+
return /* @__PURE__ */ jsx25(
|
|
7311
|
+
ComposerStatusBanner,
|
|
7153
7312
|
{
|
|
7154
|
-
|
|
7155
|
-
|
|
7156
|
-
|
|
7157
|
-
|
|
7158
|
-
|
|
7159
|
-
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
|
|
7163
|
-
|
|
7164
|
-
|
|
7165
|
-
|
|
7166
|
-
|
|
7167
|
-
|
|
7168
|
-
|
|
7169
|
-
|
|
7170
|
-
|
|
7171
|
-
|
|
7172
|
-
|
|
7173
|
-
|
|
7174
|
-
|
|
7175
|
-
|
|
7176
|
-
|
|
7177
|
-
|
|
7178
|
-
|
|
7179
|
-
|
|
7180
|
-
|
|
7313
|
+
tone: "error",
|
|
7314
|
+
dataAttribute: "data-boring-plugin-update",
|
|
7315
|
+
maxWidthClassName,
|
|
7316
|
+
title: "Plugin update failed.",
|
|
7317
|
+
message: state.message,
|
|
7318
|
+
onRetry,
|
|
7319
|
+
onDismiss,
|
|
7320
|
+
retryLabel: "Try again",
|
|
7321
|
+
dismissAriaLabel: "Dismiss plugin update status"
|
|
7322
|
+
}
|
|
7323
|
+
);
|
|
7324
|
+
}
|
|
7325
|
+
|
|
7326
|
+
// src/front/composer/CommandRunStatus.tsx
|
|
7327
|
+
import { useEffect as useEffect16, useRef as useRef12 } from "react";
|
|
7328
|
+
import { Fragment as Fragment7, jsx as jsx26, jsxs as jsxs24 } from "react/jsx-runtime";
|
|
7329
|
+
function CommandRunStatus({
|
|
7330
|
+
state,
|
|
7331
|
+
onDismiss,
|
|
7332
|
+
successAutoDismissMs = 1400,
|
|
7333
|
+
maxWidthClassName = "max-w-3xl"
|
|
7334
|
+
}) {
|
|
7335
|
+
const onDismissRef = useRef12(onDismiss);
|
|
7336
|
+
useEffect16(() => {
|
|
7337
|
+
onDismissRef.current = onDismiss;
|
|
7338
|
+
}, [onDismiss]);
|
|
7339
|
+
const successKey = state?.kind === "success" ? `${state.runId}:${state.command}:${state.detail ?? ""}` : null;
|
|
7340
|
+
useEffect16(() => {
|
|
7341
|
+
if (!state || state.kind !== "success" || successAutoDismissMs <= 0) return;
|
|
7342
|
+
const timeout = window.setTimeout(() => onDismissRef.current(), successAutoDismissMs);
|
|
7343
|
+
return () => window.clearTimeout(timeout);
|
|
7344
|
+
}, [state?.kind, successKey, successAutoDismissMs]);
|
|
7345
|
+
if (!state) return null;
|
|
7346
|
+
if (state.kind === "running") {
|
|
7347
|
+
return /* @__PURE__ */ jsx26(
|
|
7348
|
+
ComposerStatusBanner,
|
|
7349
|
+
{
|
|
7350
|
+
tone: "running",
|
|
7351
|
+
dataAttribute: "data-boring-command-run",
|
|
7352
|
+
maxWidthClassName,
|
|
7353
|
+
runningContent: state.command ? /* @__PURE__ */ jsxs24(Fragment7, { children: [
|
|
7354
|
+
" Running ",
|
|
7355
|
+
/* @__PURE__ */ jsxs24("code", { className: "font-mono", children: [
|
|
7356
|
+
"/",
|
|
7357
|
+
state.command
|
|
7358
|
+
] }),
|
|
7359
|
+
"\u2026 "
|
|
7360
|
+
] }) : "Running command\u2026"
|
|
7361
|
+
}
|
|
7362
|
+
);
|
|
7363
|
+
}
|
|
7364
|
+
if (state.kind === "success") {
|
|
7365
|
+
return /* @__PURE__ */ jsx26(
|
|
7366
|
+
ComposerStatusBanner,
|
|
7367
|
+
{
|
|
7368
|
+
tone: "success",
|
|
7369
|
+
dataAttribute: "data-boring-command-run",
|
|
7370
|
+
maxWidthClassName,
|
|
7371
|
+
title: state.command ? /* @__PURE__ */ jsxs24(Fragment7, { children: [
|
|
7372
|
+
" Ran ",
|
|
7373
|
+
/* @__PURE__ */ jsxs24("code", { className: "font-mono", children: [
|
|
7374
|
+
"/",
|
|
7375
|
+
state.command
|
|
7376
|
+
] }),
|
|
7377
|
+
" "
|
|
7378
|
+
] }) : "Command ran",
|
|
7379
|
+
detail: state.detail,
|
|
7380
|
+
onDismiss,
|
|
7381
|
+
dismissAriaLabel: "Dismiss command status"
|
|
7382
|
+
}
|
|
7383
|
+
);
|
|
7384
|
+
}
|
|
7385
|
+
return /* @__PURE__ */ jsx26(
|
|
7386
|
+
ComposerStatusBanner,
|
|
7387
|
+
{
|
|
7388
|
+
tone: "error",
|
|
7389
|
+
dataAttribute: "data-boring-command-run",
|
|
7390
|
+
maxWidthClassName,
|
|
7391
|
+
title: state.command ? /* @__PURE__ */ jsxs24(Fragment7, { children: [
|
|
7392
|
+
" ",
|
|
7393
|
+
/* @__PURE__ */ jsxs24("code", { className: "font-mono", children: [
|
|
7394
|
+
"/",
|
|
7395
|
+
state.command
|
|
7181
7396
|
] }),
|
|
7182
|
-
|
|
7183
|
-
]
|
|
7397
|
+
" failed. "
|
|
7398
|
+
] }) : "Command failed.",
|
|
7399
|
+
message: state.message,
|
|
7400
|
+
onDismiss,
|
|
7401
|
+
dismissAriaLabel: "Dismiss command status"
|
|
7184
7402
|
}
|
|
7185
7403
|
);
|
|
7186
7404
|
}
|
|
7187
7405
|
|
|
7188
7406
|
// src/front/chatPanelComposerControls.tsx
|
|
7189
|
-
import { forwardRef, useEffect as
|
|
7407
|
+
import { forwardRef, useEffect as useEffect17, useRef as useRef13, useState as useState16 } from "react";
|
|
7190
7408
|
import { CheckIcon as CheckIcon3, ChevronDownIcon as ChevronDownIcon5 } from "lucide-react";
|
|
7191
7409
|
import {
|
|
7192
7410
|
Command,
|
|
@@ -7220,7 +7438,7 @@ function displayProviderLabel(provider) {
|
|
|
7220
7438
|
}
|
|
7221
7439
|
|
|
7222
7440
|
// src/front/chatPanelComposerControls.tsx
|
|
7223
|
-
import { Fragment as
|
|
7441
|
+
import { Fragment as Fragment8, jsx as jsx27, jsxs as jsxs25 } from "react/jsx-runtime";
|
|
7224
7442
|
var composerActionClass = cn(
|
|
7225
7443
|
"inline-flex h-8 items-center justify-center gap-1.5 rounded-[var(--radius-md)] border-0 bg-transparent",
|
|
7226
7444
|
"text-muted-foreground shadow-none transition",
|
|
@@ -7270,7 +7488,7 @@ function isTextInputTarget(target) {
|
|
|
7270
7488
|
return target instanceof HTMLInputElement;
|
|
7271
7489
|
}
|
|
7272
7490
|
function useDismissOnOutsidePointer(ref, onClose) {
|
|
7273
|
-
|
|
7491
|
+
useEffect17(() => {
|
|
7274
7492
|
if (!onClose) return;
|
|
7275
7493
|
const handler = (event) => {
|
|
7276
7494
|
const target = event.target;
|
|
@@ -7288,7 +7506,7 @@ function useDismissOnOutsidePointer(ref, onClose) {
|
|
|
7288
7506
|
}
|
|
7289
7507
|
function ThinkingLevelGlyph({ level }) {
|
|
7290
7508
|
const lit = level === "off" ? 0 : level === "low" ? 1 : level === "medium" ? 2 : 3;
|
|
7291
|
-
return /* @__PURE__ */
|
|
7509
|
+
return /* @__PURE__ */ jsx27(
|
|
7292
7510
|
"svg",
|
|
7293
7511
|
{
|
|
7294
7512
|
"aria-hidden": "true",
|
|
@@ -7297,7 +7515,7 @@ function ThinkingLevelGlyph({ level }) {
|
|
|
7297
7515
|
viewBox: "0 0 14 14",
|
|
7298
7516
|
fill: "none",
|
|
7299
7517
|
className: "shrink-0",
|
|
7300
|
-
children: [0, 1, 2].map((i) => /* @__PURE__ */
|
|
7518
|
+
children: [0, 1, 2].map((i) => /* @__PURE__ */ jsx27(
|
|
7301
7519
|
"rect",
|
|
7302
7520
|
{
|
|
7303
7521
|
x: 2 + i * 4,
|
|
@@ -7354,7 +7572,7 @@ var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
|
|
|
7354
7572
|
}, ref) {
|
|
7355
7573
|
const triggerLabel = modelTriggerLabel(value, options);
|
|
7356
7574
|
const triggerDisplay = value ? `${triggerLabel} (${displayProviderLabel(value.provider)})` : triggerLabel;
|
|
7357
|
-
return /* @__PURE__ */
|
|
7575
|
+
return /* @__PURE__ */ jsx27(
|
|
7358
7576
|
"button",
|
|
7359
7577
|
{
|
|
7360
7578
|
ref,
|
|
@@ -7372,12 +7590,12 @@ var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
|
|
|
7372
7590
|
className
|
|
7373
7591
|
),
|
|
7374
7592
|
...props,
|
|
7375
|
-
children: trigger === "slash" ? /* @__PURE__ */
|
|
7376
|
-
/* @__PURE__ */
|
|
7377
|
-
/* @__PURE__ */
|
|
7378
|
-
] }) : /* @__PURE__ */
|
|
7379
|
-
/* @__PURE__ */
|
|
7380
|
-
/* @__PURE__ */
|
|
7593
|
+
children: trigger === "slash" ? /* @__PURE__ */ jsxs25(Fragment8, { children: [
|
|
7594
|
+
/* @__PURE__ */ jsx27("span", { className: "text-muted-foreground", children: "/model: " }),
|
|
7595
|
+
/* @__PURE__ */ jsx27("span", { className: "text-foreground", children: triggerDisplay })
|
|
7596
|
+
] }) : /* @__PURE__ */ jsxs25(Fragment8, { children: [
|
|
7597
|
+
/* @__PURE__ */ jsx27("span", { className: "min-w-0 truncate", children: triggerDisplay }),
|
|
7598
|
+
/* @__PURE__ */ jsx27(ChevronDownIcon5, { className: "h-3 w-3 shrink-0 text-muted-foreground/50", "aria-hidden": "true" })
|
|
7381
7599
|
] })
|
|
7382
7600
|
}
|
|
7383
7601
|
);
|
|
@@ -7397,18 +7615,18 @@ function ModelPickerMenu({
|
|
|
7397
7615
|
const keyboardOptions = [null, ...groupedOptions];
|
|
7398
7616
|
const selectedIndex = currentKey ? Math.max(0, keyboardOptions.findIndex((option) => option && encodeModelKey(option) === currentKey)) : 0;
|
|
7399
7617
|
const [activeIndex, setActiveIndex] = useState16(selectedIndex);
|
|
7400
|
-
const activeIndexRef =
|
|
7401
|
-
const menuRef =
|
|
7618
|
+
const activeIndexRef = useRef13(selectedIndex);
|
|
7619
|
+
const menuRef = useRef13(null);
|
|
7402
7620
|
useDismissOnOutsidePointer(menuRef, onClose);
|
|
7403
7621
|
const setKeyboardActiveIndex = (next) => {
|
|
7404
7622
|
const resolved = typeof next === "function" ? next(activeIndexRef.current) : next;
|
|
7405
7623
|
activeIndexRef.current = resolved;
|
|
7406
7624
|
setActiveIndex(resolved);
|
|
7407
7625
|
};
|
|
7408
|
-
|
|
7626
|
+
useEffect17(() => {
|
|
7409
7627
|
setKeyboardActiveIndex(selectedIndex);
|
|
7410
7628
|
}, [selectedIndex]);
|
|
7411
|
-
|
|
7629
|
+
useEffect17(() => {
|
|
7412
7630
|
const handler = (event) => {
|
|
7413
7631
|
if (event.key === "Escape") {
|
|
7414
7632
|
event.preventDefault();
|
|
@@ -7432,8 +7650,8 @@ function ModelPickerMenu({
|
|
|
7432
7650
|
return () => window.removeEventListener("keydown", handler, { capture: true });
|
|
7433
7651
|
}, [activeIndex, disabled, keyboardOptions, onChange, onClose]);
|
|
7434
7652
|
const optionIndexes = new Map(groupedOptions.map((option, index) => [encodeModelKey(option), index + 1]));
|
|
7435
|
-
return /* @__PURE__ */
|
|
7436
|
-
menuOptions.length > 8 && /* @__PURE__ */
|
|
7653
|
+
return /* @__PURE__ */ jsx27("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: [
|
|
7654
|
+
menuOptions.length > 8 && /* @__PURE__ */ jsx27("div", { className: "border-b border-border/60 px-2", children: /* @__PURE__ */ jsx27(
|
|
7437
7655
|
CommandInput,
|
|
7438
7656
|
{
|
|
7439
7657
|
placeholder: "Search models\u2026",
|
|
@@ -7441,9 +7659,9 @@ function ModelPickerMenu({
|
|
|
7441
7659
|
className: "h-8 w-full border-0 bg-transparent text-[13px] outline-none focus:ring-0"
|
|
7442
7660
|
}
|
|
7443
7661
|
) }),
|
|
7444
|
-
/* @__PURE__ */
|
|
7445
|
-
/* @__PURE__ */
|
|
7446
|
-
/* @__PURE__ */
|
|
7662
|
+
/* @__PURE__ */ jsxs25(CommandList, { className: "max-h-[300px] p-0.5", children: [
|
|
7663
|
+
/* @__PURE__ */ jsx27(CommandEmpty, { className: "py-4 text-center text-[13px] text-muted-foreground", children: "No models found" }),
|
|
7664
|
+
/* @__PURE__ */ jsx27(CommandGroup, { children: /* @__PURE__ */ jsxs25(
|
|
7447
7665
|
CommandItem,
|
|
7448
7666
|
{
|
|
7449
7667
|
value: "Pi default automatic auto",
|
|
@@ -7454,7 +7672,7 @@ function ModelPickerMenu({
|
|
|
7454
7672
|
},
|
|
7455
7673
|
className: selectorItemClass(!value || activeIndex === 0),
|
|
7456
7674
|
children: [
|
|
7457
|
-
/* @__PURE__ */
|
|
7675
|
+
/* @__PURE__ */ jsx27(
|
|
7458
7676
|
CheckIcon3,
|
|
7459
7677
|
{
|
|
7460
7678
|
className: cn(
|
|
@@ -7463,12 +7681,12 @@ function ModelPickerMenu({
|
|
|
7463
7681
|
)
|
|
7464
7682
|
}
|
|
7465
7683
|
),
|
|
7466
|
-
/* @__PURE__ */
|
|
7467
|
-
/* @__PURE__ */
|
|
7684
|
+
/* @__PURE__ */ jsx27("span", { className: "truncate", children: "Pi default" }),
|
|
7685
|
+
/* @__PURE__ */ jsx27("span", { className: "ml-auto shrink-0 text-[10px] text-muted-foreground/60", children: "auto" })
|
|
7468
7686
|
]
|
|
7469
7687
|
}
|
|
7470
7688
|
) }),
|
|
7471
|
-
[...groups.entries()].map(([provider, list]) => /* @__PURE__ */
|
|
7689
|
+
[...groups.entries()].map(([provider, list]) => /* @__PURE__ */ jsx27(
|
|
7472
7690
|
CommandGroup,
|
|
7473
7691
|
{
|
|
7474
7692
|
heading: displayProviderLabel(provider),
|
|
@@ -7477,7 +7695,7 @@ function ModelPickerMenu({
|
|
|
7477
7695
|
const key = encodeModelKey(m);
|
|
7478
7696
|
const label = m.label || displayModelLabel(m.id);
|
|
7479
7697
|
const itemIndex = optionIndexes.get(key) ?? 0;
|
|
7480
|
-
return /* @__PURE__ */
|
|
7698
|
+
return /* @__PURE__ */ jsxs25(
|
|
7481
7699
|
CommandItem,
|
|
7482
7700
|
{
|
|
7483
7701
|
value: `${label} ${m.id} ${displayProviderLabel(m.provider)}`,
|
|
@@ -7488,7 +7706,7 @@ function ModelPickerMenu({
|
|
|
7488
7706
|
},
|
|
7489
7707
|
className: cn(selectorItemClass(key === currentKey || activeIndex === itemIndex)),
|
|
7490
7708
|
children: [
|
|
7491
|
-
/* @__PURE__ */
|
|
7709
|
+
/* @__PURE__ */ jsx27(
|
|
7492
7710
|
CheckIcon3,
|
|
7493
7711
|
{
|
|
7494
7712
|
className: cn(
|
|
@@ -7497,8 +7715,8 @@ function ModelPickerMenu({
|
|
|
7497
7715
|
)
|
|
7498
7716
|
}
|
|
7499
7717
|
),
|
|
7500
|
-
/* @__PURE__ */
|
|
7501
|
-
/* @__PURE__ */
|
|
7718
|
+
/* @__PURE__ */ jsx27("span", { className: "min-w-0 flex-1 truncate whitespace-nowrap", children: label }),
|
|
7719
|
+
/* @__PURE__ */ jsx27("span", { className: "ml-auto max-w-[45%] shrink-0 truncate whitespace-nowrap text-right text-[10px] text-muted-foreground/60", children: m.id })
|
|
7502
7720
|
]
|
|
7503
7721
|
},
|
|
7504
7722
|
key
|
|
@@ -7519,7 +7737,7 @@ var ThinkingSelectTrigger = forwardRef(function ThinkingSelectTrigger2({
|
|
|
7519
7737
|
className,
|
|
7520
7738
|
...props
|
|
7521
7739
|
}, ref) {
|
|
7522
|
-
return /* @__PURE__ */
|
|
7740
|
+
return /* @__PURE__ */ jsxs25(
|
|
7523
7741
|
"button",
|
|
7524
7742
|
{
|
|
7525
7743
|
ref,
|
|
@@ -7540,13 +7758,13 @@ var ThinkingSelectTrigger = forwardRef(function ThinkingSelectTrigger2({
|
|
|
7540
7758
|
onClick,
|
|
7541
7759
|
...props,
|
|
7542
7760
|
children: [
|
|
7543
|
-
trigger === "button" ? /* @__PURE__ */
|
|
7544
|
-
trigger === "slash" ? /* @__PURE__ */
|
|
7545
|
-
/* @__PURE__ */
|
|
7546
|
-
/* @__PURE__ */
|
|
7547
|
-
] }) : /* @__PURE__ */
|
|
7548
|
-
/* @__PURE__ */
|
|
7549
|
-
/* @__PURE__ */
|
|
7761
|
+
trigger === "button" ? /* @__PURE__ */ jsx27(ThinkingLevelGlyph, { level: value }) : null,
|
|
7762
|
+
trigger === "slash" ? /* @__PURE__ */ jsxs25(Fragment8, { children: [
|
|
7763
|
+
/* @__PURE__ */ jsx27("span", { className: "text-muted-foreground", children: "/thinking: " }),
|
|
7764
|
+
/* @__PURE__ */ jsx27("span", { className: "text-foreground", children: THINKING_LEVEL_STATUS_LABELS[value] })
|
|
7765
|
+
] }) : /* @__PURE__ */ jsxs25(Fragment8, { children: [
|
|
7766
|
+
/* @__PURE__ */ jsx27("span", { children: THINKING_LEVEL_LABELS[value] }),
|
|
7767
|
+
/* @__PURE__ */ jsx27(ChevronDownIcon5, { className: "h-3 w-3 shrink-0 text-muted-foreground/50", "aria-hidden": "true" })
|
|
7550
7768
|
] })
|
|
7551
7769
|
]
|
|
7552
7770
|
}
|
|
@@ -7561,18 +7779,18 @@ function ThinkingPickerMenu({
|
|
|
7561
7779
|
}) {
|
|
7562
7780
|
const selectedIndex = Math.max(0, THINKING_LEVELS.indexOf(value));
|
|
7563
7781
|
const [activeIndex, setActiveIndex] = useState16(selectedIndex);
|
|
7564
|
-
const activeIndexRef =
|
|
7565
|
-
const menuRef =
|
|
7782
|
+
const activeIndexRef = useRef13(selectedIndex);
|
|
7783
|
+
const menuRef = useRef13(null);
|
|
7566
7784
|
useDismissOnOutsidePointer(menuRef, onClose);
|
|
7567
7785
|
const setKeyboardActiveIndex = (next) => {
|
|
7568
7786
|
const resolved = typeof next === "function" ? next(activeIndexRef.current) : next;
|
|
7569
7787
|
activeIndexRef.current = resolved;
|
|
7570
7788
|
setActiveIndex(resolved);
|
|
7571
7789
|
};
|
|
7572
|
-
|
|
7790
|
+
useEffect17(() => {
|
|
7573
7791
|
setKeyboardActiveIndex(selectedIndex);
|
|
7574
7792
|
}, [selectedIndex]);
|
|
7575
|
-
|
|
7793
|
+
useEffect17(() => {
|
|
7576
7794
|
const handler = (event) => {
|
|
7577
7795
|
if (event.key === "Escape") {
|
|
7578
7796
|
event.preventDefault();
|
|
@@ -7595,7 +7813,7 @@ function ThinkingPickerMenu({
|
|
|
7595
7813
|
window.addEventListener("keydown", handler, { capture: true });
|
|
7596
7814
|
return () => window.removeEventListener("keydown", handler, { capture: true });
|
|
7597
7815
|
}, [activeIndex, disabled, onChange, onClose]);
|
|
7598
|
-
return /* @__PURE__ */
|
|
7816
|
+
return /* @__PURE__ */ jsx27("div", { ref: menuRef, "data-boring-agent": "", "data-boring-agent-part": "thinking-picker-menu", className: cn(composerPickerMenuClass, className), children: /* @__PURE__ */ jsx27(Command, { className: "bg-transparent text-[color:var(--popover-foreground)]", children: /* @__PURE__ */ jsx27(CommandList, { className: "max-h-[300px] p-0.5", children: THINKING_LEVELS.map((level, index) => /* @__PURE__ */ jsxs25(
|
|
7599
7817
|
CommandItem,
|
|
7600
7818
|
{
|
|
7601
7819
|
value: `Thinking ${THINKING_LEVEL_LABELS[level]} ${THINKING_LEVEL_DETAILS[level]}`,
|
|
@@ -7606,7 +7824,7 @@ function ThinkingPickerMenu({
|
|
|
7606
7824
|
},
|
|
7607
7825
|
className: selectorItemClass(level === value || index === activeIndex),
|
|
7608
7826
|
children: [
|
|
7609
|
-
/* @__PURE__ */
|
|
7827
|
+
/* @__PURE__ */ jsx27(
|
|
7610
7828
|
CheckIcon3,
|
|
7611
7829
|
{
|
|
7612
7830
|
className: cn(
|
|
@@ -7615,9 +7833,9 @@ function ThinkingPickerMenu({
|
|
|
7615
7833
|
)
|
|
7616
7834
|
}
|
|
7617
7835
|
),
|
|
7618
|
-
/* @__PURE__ */
|
|
7619
|
-
/* @__PURE__ */
|
|
7620
|
-
/* @__PURE__ */
|
|
7836
|
+
/* @__PURE__ */ jsx27(ThinkingLevelGlyph, { level }),
|
|
7837
|
+
/* @__PURE__ */ jsx27("span", { className: "font-medium", children: THINKING_LEVEL_LABELS[level] }),
|
|
7838
|
+
/* @__PURE__ */ jsx27("span", { className: "ml-auto text-[11px] text-muted-foreground/65", children: THINKING_LEVEL_DETAILS[level] })
|
|
7621
7839
|
]
|
|
7622
7840
|
},
|
|
7623
7841
|
level
|
|
@@ -7655,10 +7873,10 @@ import {
|
|
|
7655
7873
|
Monitor,
|
|
7656
7874
|
PlusIcon as PlusIcon2,
|
|
7657
7875
|
SquareIcon,
|
|
7658
|
-
XIcon as
|
|
7876
|
+
XIcon as XIcon4
|
|
7659
7877
|
} from "lucide-react";
|
|
7660
7878
|
import { nanoid } from "nanoid";
|
|
7661
|
-
import { useCallback as useCallback15, useEffect as
|
|
7879
|
+
import { useCallback as useCallback15, useEffect as useEffect18, useMemo as useMemo10, useRef as useRef14, useState as useState17 } from "react";
|
|
7662
7880
|
|
|
7663
7881
|
// src/front/primitives/prompt-input-context.ts
|
|
7664
7882
|
import { createContext as createContext6, useContext as useContext6 } from "react";
|
|
@@ -7693,12 +7911,12 @@ import {
|
|
|
7693
7911
|
TooltipTrigger as TooltipTrigger3
|
|
7694
7912
|
} from "@hachej/boring-ui-kit";
|
|
7695
7913
|
import { Children } from "react";
|
|
7696
|
-
import { jsx as
|
|
7914
|
+
import { jsx as jsx28, jsxs as jsxs26 } from "react/jsx-runtime";
|
|
7697
7915
|
var PromptInputFooter = ({
|
|
7698
7916
|
align = "block-end",
|
|
7699
7917
|
className,
|
|
7700
7918
|
...props
|
|
7701
|
-
}) => /* @__PURE__ */
|
|
7919
|
+
}) => /* @__PURE__ */ jsx28(
|
|
7702
7920
|
InputGroupAddon,
|
|
7703
7921
|
{
|
|
7704
7922
|
align,
|
|
@@ -7708,7 +7926,7 @@ var PromptInputFooter = ({
|
|
|
7708
7926
|
);
|
|
7709
7927
|
|
|
7710
7928
|
// src/front/primitives/prompt-input.tsx
|
|
7711
|
-
import { Fragment as
|
|
7929
|
+
import { Fragment as Fragment9, jsx as jsx29, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
7712
7930
|
var PromptInput = ({
|
|
7713
7931
|
className,
|
|
7714
7932
|
accept,
|
|
@@ -7725,12 +7943,12 @@ var PromptInput = ({
|
|
|
7725
7943
|
}) => {
|
|
7726
7944
|
const controller = useOptionalPromptInputController();
|
|
7727
7945
|
const usingProvider = !!controller;
|
|
7728
|
-
const providerTextValueRef =
|
|
7946
|
+
const providerTextValueRef = useRef14("");
|
|
7729
7947
|
if (usingProvider) {
|
|
7730
7948
|
providerTextValueRef.current = controller.textInput.value;
|
|
7731
7949
|
}
|
|
7732
|
-
const inputRef =
|
|
7733
|
-
const formRef =
|
|
7950
|
+
const inputRef = useRef14(null);
|
|
7951
|
+
const formRef = useRef14(null);
|
|
7734
7952
|
const [items, setItems] = useState17([]);
|
|
7735
7953
|
const setFileUrlLocal = useCallback15((id, url, status) => {
|
|
7736
7954
|
setItems((prev) => prev.map((f) => {
|
|
@@ -7741,8 +7959,8 @@ var PromptInput = ({
|
|
|
7741
7959
|
}, []);
|
|
7742
7960
|
const files = usingProvider ? controller.attachments.files : items;
|
|
7743
7961
|
const [referencedSources, setReferencedSources] = useState17([]);
|
|
7744
|
-
const filesRef =
|
|
7745
|
-
|
|
7962
|
+
const filesRef = useRef14(files);
|
|
7963
|
+
useEffect18(() => {
|
|
7746
7964
|
filesRef.current = files;
|
|
7747
7965
|
}, [files]);
|
|
7748
7966
|
const openFileDialogLocal = useCallback15(() => {
|
|
@@ -7878,18 +8096,18 @@ var PromptInput = ({
|
|
|
7878
8096
|
clearAttachments();
|
|
7879
8097
|
clearReferencedSources();
|
|
7880
8098
|
}, [clearAttachments, clearReferencedSources]);
|
|
7881
|
-
|
|
8099
|
+
useEffect18(() => {
|
|
7882
8100
|
if (!usingProvider) {
|
|
7883
8101
|
return;
|
|
7884
8102
|
}
|
|
7885
8103
|
controller.__registerFileInput(inputRef, () => inputRef.current?.click());
|
|
7886
8104
|
}, [usingProvider, controller]);
|
|
7887
|
-
|
|
8105
|
+
useEffect18(() => {
|
|
7888
8106
|
if (syncHiddenInput && inputRef.current && files.length === 0) {
|
|
7889
8107
|
inputRef.current.value = "";
|
|
7890
8108
|
}
|
|
7891
8109
|
}, [files, syncHiddenInput]);
|
|
7892
|
-
|
|
8110
|
+
useEffect18(() => {
|
|
7893
8111
|
const form = formRef.current;
|
|
7894
8112
|
if (!form) {
|
|
7895
8113
|
return;
|
|
@@ -7917,7 +8135,7 @@ var PromptInput = ({
|
|
|
7917
8135
|
form.removeEventListener("drop", onDrop);
|
|
7918
8136
|
};
|
|
7919
8137
|
}, [add, globalDrop]);
|
|
7920
|
-
|
|
8138
|
+
useEffect18(() => {
|
|
7921
8139
|
if (!globalDrop) {
|
|
7922
8140
|
return;
|
|
7923
8141
|
}
|
|
@@ -7941,7 +8159,7 @@ var PromptInput = ({
|
|
|
7941
8159
|
document.removeEventListener("drop", onDrop);
|
|
7942
8160
|
};
|
|
7943
8161
|
}, [add, globalDrop]);
|
|
7944
|
-
|
|
8162
|
+
useEffect18(
|
|
7945
8163
|
() => () => {
|
|
7946
8164
|
if (!usingProvider) {
|
|
7947
8165
|
for (const f of filesRef.current) {
|
|
@@ -8051,8 +8269,8 @@ var PromptInput = ({
|
|
|
8051
8269
|
},
|
|
8052
8270
|
[usingProvider, controller, files, onSubmit, clear]
|
|
8053
8271
|
);
|
|
8054
|
-
const inner = /* @__PURE__ */
|
|
8055
|
-
/* @__PURE__ */
|
|
8272
|
+
const inner = /* @__PURE__ */ jsxs27(Fragment9, { children: [
|
|
8273
|
+
/* @__PURE__ */ jsx29(
|
|
8056
8274
|
Input,
|
|
8057
8275
|
{
|
|
8058
8276
|
accept,
|
|
@@ -8065,7 +8283,7 @@ var PromptInput = ({
|
|
|
8065
8283
|
type: "file"
|
|
8066
8284
|
}
|
|
8067
8285
|
),
|
|
8068
|
-
/* @__PURE__ */
|
|
8286
|
+
/* @__PURE__ */ jsx29(
|
|
8069
8287
|
"form",
|
|
8070
8288
|
{
|
|
8071
8289
|
"data-boring-agent-part": "composer",
|
|
@@ -8073,12 +8291,12 @@ var PromptInput = ({
|
|
|
8073
8291
|
onSubmit: handleSubmit,
|
|
8074
8292
|
ref: formRef,
|
|
8075
8293
|
...props,
|
|
8076
|
-
children: /* @__PURE__ */
|
|
8294
|
+
children: /* @__PURE__ */ jsx29(InputGroup, { className: "overflow-hidden", children })
|
|
8077
8295
|
}
|
|
8078
8296
|
)
|
|
8079
8297
|
] });
|
|
8080
|
-
const withReferencedSources = /* @__PURE__ */
|
|
8081
|
-
return /* @__PURE__ */
|
|
8298
|
+
const withReferencedSources = /* @__PURE__ */ jsx29(LocalReferencedSourcesContext.Provider, { value: refsCtx, children: inner });
|
|
8299
|
+
return /* @__PURE__ */ jsx29(LocalAttachmentsContext.Provider, { value: attachmentsCtx, children: withReferencedSources });
|
|
8082
8300
|
};
|
|
8083
8301
|
var PromptInputTextarea = ({
|
|
8084
8302
|
onChange,
|
|
@@ -8156,7 +8374,7 @@ var PromptInputTextarea = ({
|
|
|
8156
8374
|
} : {
|
|
8157
8375
|
onChange
|
|
8158
8376
|
};
|
|
8159
|
-
return /* @__PURE__ */
|
|
8377
|
+
return /* @__PURE__ */ jsx29(
|
|
8160
8378
|
InputGroupTextarea,
|
|
8161
8379
|
{
|
|
8162
8380
|
"data-boring-agent-part": "composer-input",
|
|
@@ -8183,13 +8401,13 @@ var PromptInputSubmit = ({
|
|
|
8183
8401
|
...props
|
|
8184
8402
|
}) => {
|
|
8185
8403
|
const isGenerating = status === "submitted" || status === "streaming";
|
|
8186
|
-
let Icon = /* @__PURE__ */
|
|
8404
|
+
let Icon = /* @__PURE__ */ jsx29(CornerDownLeftIcon, { className: "size-4" });
|
|
8187
8405
|
if (status === "submitted") {
|
|
8188
|
-
Icon = /* @__PURE__ */
|
|
8406
|
+
Icon = /* @__PURE__ */ jsx29(Spinner, {});
|
|
8189
8407
|
} else if (status === "streaming") {
|
|
8190
|
-
Icon = /* @__PURE__ */
|
|
8408
|
+
Icon = /* @__PURE__ */ jsx29(SquareIcon, { className: "size-4" });
|
|
8191
8409
|
} else if (status === "error") {
|
|
8192
|
-
Icon = /* @__PURE__ */
|
|
8410
|
+
Icon = /* @__PURE__ */ jsx29(XIcon4, { className: "size-4" });
|
|
8193
8411
|
}
|
|
8194
8412
|
const handleClick = useCallback15(
|
|
8195
8413
|
(e) => {
|
|
@@ -8202,7 +8420,7 @@ var PromptInputSubmit = ({
|
|
|
8202
8420
|
},
|
|
8203
8421
|
[isGenerating, onStop, onClick]
|
|
8204
8422
|
);
|
|
8205
|
-
return /* @__PURE__ */
|
|
8423
|
+
return /* @__PURE__ */ jsx29(
|
|
8206
8424
|
InputGroupButton2,
|
|
8207
8425
|
{
|
|
8208
8426
|
"aria-label": isGenerating ? "Stop" : "Submit",
|
|
@@ -8219,54 +8437,142 @@ var PromptInputSubmit = ({
|
|
|
8219
8437
|
};
|
|
8220
8438
|
|
|
8221
8439
|
// src/front/primitives/slash-command-picker.tsx
|
|
8222
|
-
import {
|
|
8223
|
-
import { jsx as
|
|
8440
|
+
import { useEffect as useEffect19, useMemo as useMemo11, useRef as useRef15, useState as useState18 } from "react";
|
|
8441
|
+
import { Fragment as Fragment10, jsx as jsx30, jsxs as jsxs28 } from "react/jsx-runtime";
|
|
8442
|
+
var ALL_PLUGINS = "__all__";
|
|
8443
|
+
function commandGroup(cmd) {
|
|
8444
|
+
if (cmd.source === "skill") return "skills";
|
|
8445
|
+
if (cmd.sourcePlugin) return cmd.sourcePlugin;
|
|
8446
|
+
return "built-in";
|
|
8447
|
+
}
|
|
8224
8448
|
function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
8225
|
-
const
|
|
8226
|
-
|
|
8227
|
-
[commands, query]
|
|
8228
|
-
);
|
|
8449
|
+
const [plugin, setPlugin] = useState18(ALL_PLUGINS);
|
|
8450
|
+
const [searchQuery, setSearchQuery] = useState18(query);
|
|
8229
8451
|
const [activeIdx, setActiveIdx] = useState18(0);
|
|
8230
|
-
const
|
|
8231
|
-
|
|
8232
|
-
const
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
|
|
8237
|
-
|
|
8238
|
-
|
|
8239
|
-
|
|
8240
|
-
|
|
8241
|
-
|
|
8242
|
-
|
|
8243
|
-
|
|
8244
|
-
|
|
8245
|
-
)
|
|
8246
|
-
|
|
8247
|
-
|
|
8248
|
-
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
|
|
8252
|
-
|
|
8253
|
-
|
|
8254
|
-
|
|
8255
|
-
|
|
8256
|
-
|
|
8257
|
-
|
|
8452
|
+
const containerRef = useRef15(null);
|
|
8453
|
+
const listRef = useRef15(null);
|
|
8454
|
+
const inputRef = useRef15(null);
|
|
8455
|
+
useEffect19(() => {
|
|
8456
|
+
setSearchQuery(query);
|
|
8457
|
+
}, [query]);
|
|
8458
|
+
const groups = useMemo11(() => {
|
|
8459
|
+
const set = new Set(commands.map(commandGroup));
|
|
8460
|
+
return Array.from(set).sort((a, b) => a.localeCompare(b));
|
|
8461
|
+
}, [commands]);
|
|
8462
|
+
const filtered = useMemo11(() => {
|
|
8463
|
+
const q = searchQuery.trim().toLowerCase();
|
|
8464
|
+
return commands.filter((c) => {
|
|
8465
|
+
if (plugin !== ALL_PLUGINS && commandGroup(c) !== plugin) return false;
|
|
8466
|
+
if (!q) return true;
|
|
8467
|
+
return c.name.toLowerCase().includes(q) || c.description.toLowerCase().includes(q);
|
|
8468
|
+
});
|
|
8469
|
+
}, [commands, searchQuery, plugin]);
|
|
8470
|
+
useEffect19(() => {
|
|
8471
|
+
setActiveIdx((i) => filtered.length === 0 ? 0 : Math.min(i, filtered.length - 1));
|
|
8472
|
+
}, [filtered.length]);
|
|
8473
|
+
useEffect19(() => {
|
|
8474
|
+
const handler = (e) => {
|
|
8475
|
+
if (containerRef.current && !containerRef.current.contains(e.target)) {
|
|
8476
|
+
onDismiss();
|
|
8477
|
+
}
|
|
8478
|
+
};
|
|
8479
|
+
document.addEventListener("mousedown", handler);
|
|
8480
|
+
return () => document.removeEventListener("mousedown", handler);
|
|
8481
|
+
}, [onDismiss]);
|
|
8482
|
+
usePickerKeyboard({
|
|
8483
|
+
count: filtered.length,
|
|
8484
|
+
activeIdx,
|
|
8485
|
+
setActiveIdx,
|
|
8486
|
+
listRef,
|
|
8487
|
+
onSelect: (idx) => {
|
|
8488
|
+
if (filtered[idx]) onSelect(filtered[idx].name);
|
|
8258
8489
|
},
|
|
8259
|
-
|
|
8260
|
-
|
|
8490
|
+
onDismiss
|
|
8491
|
+
});
|
|
8492
|
+
return /* @__PURE__ */ jsxs28("div", { ref: containerRef, className: "mb-1 w-full overflow-hidden rounded-lg border border-border/60 bg-popover shadow-lg", children: [
|
|
8493
|
+
/* @__PURE__ */ jsx30(
|
|
8494
|
+
"input",
|
|
8495
|
+
{
|
|
8496
|
+
ref: inputRef,
|
|
8497
|
+
"aria-label": "Search commands",
|
|
8498
|
+
type: "text",
|
|
8499
|
+
value: searchQuery,
|
|
8500
|
+
onChange: (e) => {
|
|
8501
|
+
setSearchQuery(e.target.value);
|
|
8502
|
+
setActiveIdx(0);
|
|
8503
|
+
},
|
|
8504
|
+
className: "w-full border-b border-border/50 bg-transparent px-3 py-1.5 text-[12px] outline-none",
|
|
8505
|
+
autoComplete: "off"
|
|
8506
|
+
}
|
|
8507
|
+
),
|
|
8508
|
+
groups.length > 1 && /* @__PURE__ */ jsx30("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) => {
|
|
8509
|
+
const selected = plugin === g;
|
|
8510
|
+
return /* @__PURE__ */ jsx30(
|
|
8511
|
+
"button",
|
|
8512
|
+
{
|
|
8513
|
+
type: "button",
|
|
8514
|
+
role: "tab",
|
|
8515
|
+
"aria-selected": selected,
|
|
8516
|
+
onMouseDown: (e) => {
|
|
8517
|
+
e.preventDefault();
|
|
8518
|
+
setPlugin(g);
|
|
8519
|
+
setActiveIdx(0);
|
|
8520
|
+
},
|
|
8521
|
+
className: cn(
|
|
8522
|
+
"rounded-full px-2 py-px text-[10px] font-medium transition-colors",
|
|
8523
|
+
selected ? "bg-accent/15 text-accent-foreground" : "bg-muted/60 text-muted-foreground hover:bg-muted"
|
|
8524
|
+
),
|
|
8525
|
+
children: g === ALL_PLUGINS ? "All" : g
|
|
8526
|
+
},
|
|
8527
|
+
g
|
|
8528
|
+
);
|
|
8529
|
+
}) }),
|
|
8530
|
+
filtered.length === 0 ? /* @__PURE__ */ jsx30("div", { className: "px-3 py-2 text-[11px] text-muted-foreground", children: "No matching commands." }) : /* @__PURE__ */ jsx30("ul", { ref: listRef, className: "max-h-80 overflow-y-auto py-1", role: "listbox", "aria-label": "Commands", children: filtered.map((cmd, i) => /* @__PURE__ */ jsxs28(
|
|
8531
|
+
"li",
|
|
8532
|
+
{
|
|
8533
|
+
role: "option",
|
|
8534
|
+
"aria-selected": i === activeIdx,
|
|
8535
|
+
title: cmd.description || void 0,
|
|
8536
|
+
className: cn(
|
|
8537
|
+
"flex cursor-pointer flex-col gap-0.5 px-3 py-1.5 text-[12px]",
|
|
8538
|
+
// Single highlight: hovering moves the active row (onMouseEnter),
|
|
8539
|
+
// so the active style is the only highlight — no separate hover bg.
|
|
8540
|
+
i === activeIdx ? "bg-accent/10 text-foreground" : "text-muted-foreground"
|
|
8541
|
+
),
|
|
8542
|
+
onMouseEnter: () => setActiveIdx(i),
|
|
8543
|
+
onMouseDown: (e) => {
|
|
8544
|
+
e.preventDefault();
|
|
8545
|
+
onSelect(cmd.name);
|
|
8546
|
+
},
|
|
8547
|
+
children: [
|
|
8548
|
+
/* @__PURE__ */ jsxs28("span", { className: "flex items-center gap-1.5", children: [
|
|
8549
|
+
/* @__PURE__ */ jsxs28("span", { className: "font-medium text-foreground/80", children: [
|
|
8550
|
+
"/",
|
|
8551
|
+
cmd.name
|
|
8552
|
+
] }),
|
|
8553
|
+
cmd.source === "skill" ? /* @__PURE__ */ jsxs28(Fragment10, { children: [
|
|
8554
|
+
/* @__PURE__ */ jsx30("span", { className: "rounded-sm bg-accent/15 px-1 py-px text-[9px] font-medium uppercase tracking-wide text-accent-foreground", children: "skill" }),
|
|
8555
|
+
cmd.sourcePlugin ? /* @__PURE__ */ jsx30("span", { className: "rounded-sm bg-muted px-1 py-px text-[9px] font-medium text-muted-foreground", children: cmd.sourcePlugin }) : null
|
|
8556
|
+
] }) : cmd.sourcePlugin ? (
|
|
8557
|
+
// Originating plugin/package for non-skill commands.
|
|
8558
|
+
/* @__PURE__ */ jsx30("span", { className: "rounded-sm bg-muted px-1 py-px text-[9px] font-medium text-muted-foreground", children: cmd.sourcePlugin })
|
|
8559
|
+
) : null
|
|
8560
|
+
] }),
|
|
8561
|
+
/* @__PURE__ */ jsx30("span", { className: "truncate text-[11px] opacity-50", children: cmd.description })
|
|
8562
|
+
]
|
|
8563
|
+
},
|
|
8564
|
+
cmd.name
|
|
8565
|
+
)) })
|
|
8566
|
+
] });
|
|
8261
8567
|
}
|
|
8262
8568
|
|
|
8263
8569
|
// src/front/chat/components/ComposerAttachments.tsx
|
|
8264
|
-
import { AlertCircleIcon as
|
|
8570
|
+
import { AlertCircleIcon as AlertCircleIcon2, Loader2 as Loader23, PaperclipIcon as PaperclipIcon2 } from "lucide-react";
|
|
8265
8571
|
import { IconButton as IconButton3 } from "@hachej/boring-ui-kit";
|
|
8266
|
-
import { jsx as
|
|
8572
|
+
import { jsx as jsx31, jsxs as jsxs29 } from "react/jsx-runtime";
|
|
8267
8573
|
function AttachmentButton({ disabled, className }) {
|
|
8268
8574
|
const attachments = usePromptInputAttachments();
|
|
8269
|
-
return /* @__PURE__ */
|
|
8575
|
+
return /* @__PURE__ */ jsx31(
|
|
8270
8576
|
IconButton3,
|
|
8271
8577
|
{
|
|
8272
8578
|
type: "button",
|
|
@@ -8279,21 +8585,21 @@ function AttachmentButton({ disabled, className }) {
|
|
|
8279
8585
|
className: cn(composerActionClass, "w-8", className),
|
|
8280
8586
|
"aria-label": "Attach files",
|
|
8281
8587
|
title: disabled ? "Attachments are available when the composer is ready." : "Attach files",
|
|
8282
|
-
children: /* @__PURE__ */
|
|
8588
|
+
children: /* @__PURE__ */ jsx31(PaperclipIcon2, { className: "h-3.5 w-3.5", strokeWidth: 1.75 })
|
|
8283
8589
|
}
|
|
8284
8590
|
);
|
|
8285
8591
|
}
|
|
8286
8592
|
function AttachmentsList() {
|
|
8287
8593
|
const attachments = usePromptInputAttachments();
|
|
8288
8594
|
if (attachments.files.length === 0) return null;
|
|
8289
|
-
return /* @__PURE__ */
|
|
8595
|
+
return /* @__PURE__ */ jsx31(
|
|
8290
8596
|
Attachments,
|
|
8291
8597
|
{
|
|
8292
8598
|
"data-boring-agent-part": "composer-attachment-row",
|
|
8293
8599
|
"data-align": "block-start",
|
|
8294
8600
|
variant: "inline",
|
|
8295
8601
|
className: "w-full flex-wrap items-center justify-start gap-2 px-5 pb-0 pt-3",
|
|
8296
|
-
children: attachments.files.map((file) => /* @__PURE__ */
|
|
8602
|
+
children: attachments.files.map((file) => /* @__PURE__ */ jsxs29(
|
|
8297
8603
|
Attachment,
|
|
8298
8604
|
{
|
|
8299
8605
|
data: file,
|
|
@@ -8304,13 +8610,13 @@ function AttachmentsList() {
|
|
|
8304
8610
|
file.status === "error" && "!border-destructive/50 !bg-destructive/10"
|
|
8305
8611
|
),
|
|
8306
8612
|
children: [
|
|
8307
|
-
/* @__PURE__ */
|
|
8308
|
-
/* @__PURE__ */
|
|
8309
|
-
file.status === "uploading" ? /* @__PURE__ */
|
|
8310
|
-
file.status === "error" ? /* @__PURE__ */
|
|
8613
|
+
/* @__PURE__ */ jsxs29("div", { className: "relative shrink-0", children: [
|
|
8614
|
+
/* @__PURE__ */ jsx31(AttachmentPreview, { className: "!size-7 overflow-hidden !rounded-full bg-background/60" }),
|
|
8615
|
+
file.status === "uploading" ? /* @__PURE__ */ jsx31("div", { className: "absolute inset-0 flex items-center justify-center rounded-full bg-background/70", children: /* @__PURE__ */ jsx31(Loader23, { className: "size-3.5 animate-spin text-muted-foreground" }) }) : null,
|
|
8616
|
+
file.status === "error" ? /* @__PURE__ */ jsx31("div", { className: "absolute inset-0 flex items-center justify-center rounded-full bg-destructive/20", children: /* @__PURE__ */ jsx31(AlertCircleIcon2, { className: "size-3.5 text-destructive" }) }) : null
|
|
8311
8617
|
] }),
|
|
8312
|
-
/* @__PURE__ */
|
|
8313
|
-
/* @__PURE__ */
|
|
8618
|
+
/* @__PURE__ */ jsx31(AttachmentInfo, { className: "min-w-0 !max-w-[180px] truncate text-[13px] font-medium" }),
|
|
8619
|
+
/* @__PURE__ */ jsx31(AttachmentRemove, { className: "!size-5 !rounded-full !opacity-100 text-muted-foreground/80 hover:text-foreground" })
|
|
8314
8620
|
]
|
|
8315
8621
|
},
|
|
8316
8622
|
file.id
|
|
@@ -8320,7 +8626,7 @@ function AttachmentsList() {
|
|
|
8320
8626
|
}
|
|
8321
8627
|
|
|
8322
8628
|
// src/front/chat/components/PiChatComposerSurface.tsx
|
|
8323
|
-
import { jsx as
|
|
8629
|
+
import { jsx as jsx32, jsxs as jsxs30 } from "react/jsx-runtime";
|
|
8324
8630
|
var MAX_PROMPT_ATTACHMENTS = 2;
|
|
8325
8631
|
var MAX_PROMPT_ATTACHMENT_BYTES = 4 * 1024 * 1024;
|
|
8326
8632
|
var COMPOSER_INPUT_GROUP_MIN_HEIGHT = 56;
|
|
@@ -8362,6 +8668,8 @@ function PiChatComposerSurface({
|
|
|
8362
8668
|
pluginUpdateState,
|
|
8363
8669
|
onDismissPluginUpdate,
|
|
8364
8670
|
onRunPluginUpdate,
|
|
8671
|
+
commandNotifyState,
|
|
8672
|
+
onDismissCommandNotify,
|
|
8365
8673
|
attachmentNotice,
|
|
8366
8674
|
onAttachmentNotice,
|
|
8367
8675
|
mentionState,
|
|
@@ -8396,7 +8704,7 @@ function PiChatComposerSurface({
|
|
|
8396
8704
|
onSubmitMessage,
|
|
8397
8705
|
onStop
|
|
8398
8706
|
}) {
|
|
8399
|
-
const resizeTextarea =
|
|
8707
|
+
const resizeTextarea = useCallback16((node) => {
|
|
8400
8708
|
if (!node) return;
|
|
8401
8709
|
node.style.height = "auto";
|
|
8402
8710
|
const style = window.getComputedStyle(node);
|
|
@@ -8420,8 +8728,8 @@ function PiChatComposerSurface({
|
|
|
8420
8728
|
useLayoutEffect2(() => {
|
|
8421
8729
|
resizeTextarea(textareaRef.current);
|
|
8422
8730
|
}, [draft, resizeTextarea, textareaRef]);
|
|
8423
|
-
return /* @__PURE__ */
|
|
8424
|
-
/* @__PURE__ */
|
|
8731
|
+
return /* @__PURE__ */ jsxs30("div", { className: cn(chrome ? "px-4 pb-4 pt-2 sm:px-6 sm:pb-5" : "px-3 pb-2 pt-1"), children: [
|
|
8732
|
+
/* @__PURE__ */ jsx32(
|
|
8425
8733
|
"div",
|
|
8426
8734
|
{
|
|
8427
8735
|
"data-boring-agent-part": "chat-working-slot",
|
|
@@ -8431,7 +8739,7 @@ function PiChatComposerSurface({
|
|
|
8431
8739
|
isStreaming ? "mb-2 max-h-8 opacity-100" : "mb-0 max-h-0 opacity-0"
|
|
8432
8740
|
),
|
|
8433
8741
|
"aria-hidden": !isStreaming,
|
|
8434
|
-
children: /* @__PURE__ */
|
|
8742
|
+
children: /* @__PURE__ */ jsxs30(
|
|
8435
8743
|
"div",
|
|
8436
8744
|
{
|
|
8437
8745
|
"data-testid": isStreaming ? "chat-working" : void 0,
|
|
@@ -8439,7 +8747,7 @@ function PiChatComposerSurface({
|
|
|
8439
8747
|
"aria-live": isStreaming ? "polite" : void 0,
|
|
8440
8748
|
className: "inline-flex items-center gap-2 rounded-full border border-border/50 bg-background/85 px-2.5 py-1 text-[12px] text-muted-foreground/75 shadow-sm backdrop-blur",
|
|
8441
8749
|
children: [
|
|
8442
|
-
/* @__PURE__ */
|
|
8750
|
+
/* @__PURE__ */ jsx32(
|
|
8443
8751
|
motion2.span,
|
|
8444
8752
|
{
|
|
8445
8753
|
"aria-hidden": "true",
|
|
@@ -8448,14 +8756,14 @@ function PiChatComposerSurface({
|
|
|
8448
8756
|
transition: { duration: 1.2, repeat: Infinity, ease: "easeInOut" }
|
|
8449
8757
|
}
|
|
8450
8758
|
),
|
|
8451
|
-
/* @__PURE__ */
|
|
8759
|
+
/* @__PURE__ */ jsx32("span", { children: "Working\u2026" })
|
|
8452
8760
|
]
|
|
8453
8761
|
}
|
|
8454
8762
|
)
|
|
8455
8763
|
}
|
|
8456
8764
|
),
|
|
8457
|
-
composerStatusNotice ? /* @__PURE__ */
|
|
8458
|
-
composerBlocked && !workspaceWarmupBlocked ? /* @__PURE__ */
|
|
8765
|
+
composerStatusNotice ? /* @__PURE__ */ jsx32(ComposerRuntimeNotice, { notice: composerStatusNotice }) : null,
|
|
8766
|
+
composerBlocked && !workspaceWarmupBlocked ? /* @__PURE__ */ jsx32(
|
|
8459
8767
|
ComposerBlockerNotice,
|
|
8460
8768
|
{
|
|
8461
8769
|
blocker: primaryComposerBlocker,
|
|
@@ -8463,8 +8771,8 @@ function PiChatComposerSurface({
|
|
|
8463
8771
|
onAction: onComposerBlockerAction
|
|
8464
8772
|
}
|
|
8465
8773
|
) : null,
|
|
8466
|
-
queuePreview.length > 0 ? /* @__PURE__ */
|
|
8467
|
-
hotReloadEnabled ? /* @__PURE__ */
|
|
8774
|
+
queuePreview.length > 0 ? /* @__PURE__ */ jsx32(QueuedComposerNotice, { followUps: queuePreview, onEdit: onEditQueued }) : null,
|
|
8775
|
+
hotReloadEnabled ? /* @__PURE__ */ jsx32(
|
|
8468
8776
|
PluginUpdateStatus,
|
|
8469
8777
|
{
|
|
8470
8778
|
state: pluginUpdateState,
|
|
@@ -8472,7 +8780,14 @@ function PiChatComposerSurface({
|
|
|
8472
8780
|
onRetry: onRunPluginUpdate
|
|
8473
8781
|
}
|
|
8474
8782
|
) : null,
|
|
8475
|
-
|
|
8783
|
+
/* @__PURE__ */ jsx32(
|
|
8784
|
+
CommandRunStatus,
|
|
8785
|
+
{
|
|
8786
|
+
state: commandNotifyState,
|
|
8787
|
+
onDismiss: onDismissCommandNotify
|
|
8788
|
+
}
|
|
8789
|
+
),
|
|
8790
|
+
attachmentNotice ? /* @__PURE__ */ jsx32(
|
|
8476
8791
|
"div",
|
|
8477
8792
|
{
|
|
8478
8793
|
role: "status",
|
|
@@ -8481,8 +8796,8 @@ function PiChatComposerSurface({
|
|
|
8481
8796
|
children: attachmentNotice
|
|
8482
8797
|
}
|
|
8483
8798
|
) : null,
|
|
8484
|
-
/* @__PURE__ */
|
|
8485
|
-
mentionState ? /* @__PURE__ */
|
|
8799
|
+
/* @__PURE__ */ jsxs30("div", { className: cn("mx-auto w-full", chrome ? "max-w-3xl" : "max-w-[680px]"), children: [
|
|
8800
|
+
mentionState ? /* @__PURE__ */ jsx32(
|
|
8486
8801
|
MentionPicker,
|
|
8487
8802
|
{
|
|
8488
8803
|
mention: mentionState,
|
|
@@ -8494,7 +8809,7 @@ function PiChatComposerSurface({
|
|
|
8494
8809
|
onDismiss: onDismissMention
|
|
8495
8810
|
}
|
|
8496
8811
|
) : null,
|
|
8497
|
-
slashQuery !== null ? /* @__PURE__ */
|
|
8812
|
+
slashQuery !== null ? /* @__PURE__ */ jsx32(
|
|
8498
8813
|
SlashCommandPicker,
|
|
8499
8814
|
{
|
|
8500
8815
|
query: slashQuery,
|
|
@@ -8503,7 +8818,7 @@ function PiChatComposerSurface({
|
|
|
8503
8818
|
onDismiss: onDismissSlash
|
|
8504
8819
|
}
|
|
8505
8820
|
) : null,
|
|
8506
|
-
mentionState === null && slashQuery === null && modelPickerOpen ? /* @__PURE__ */
|
|
8821
|
+
mentionState === null && slashQuery === null && modelPickerOpen ? /* @__PURE__ */ jsx32(
|
|
8507
8822
|
ModelPickerMenu,
|
|
8508
8823
|
{
|
|
8509
8824
|
value: selectedModel,
|
|
@@ -8513,7 +8828,7 @@ function PiChatComposerSurface({
|
|
|
8513
8828
|
onClose: () => onSetModelPickerOpen(false)
|
|
8514
8829
|
}
|
|
8515
8830
|
) : null,
|
|
8516
|
-
mentionState === null && slashQuery === null && thinkingPickerOpen ? /* @__PURE__ */
|
|
8831
|
+
mentionState === null && slashQuery === null && thinkingPickerOpen ? /* @__PURE__ */ jsx32(
|
|
8517
8832
|
ThinkingPickerMenu,
|
|
8518
8833
|
{
|
|
8519
8834
|
value: selectedThinking,
|
|
@@ -8523,7 +8838,7 @@ function PiChatComposerSurface({
|
|
|
8523
8838
|
}
|
|
8524
8839
|
) : null
|
|
8525
8840
|
] }),
|
|
8526
|
-
/* @__PURE__ */
|
|
8841
|
+
/* @__PURE__ */ jsx32(
|
|
8527
8842
|
"div",
|
|
8528
8843
|
{
|
|
8529
8844
|
"data-boring-agent-part": "composer-rail",
|
|
@@ -8542,7 +8857,7 @@ function PiChatComposerSurface({
|
|
|
8542
8857
|
"[&[data-composer-multiline=true]_[data-boring-agent-part=composer-submit-addon]]:self-end",
|
|
8543
8858
|
"[&[data-composer-multiline=true]_[data-boring-agent-part=composer-submit-addon]]:mb-2"
|
|
8544
8859
|
),
|
|
8545
|
-
children: /* @__PURE__ */
|
|
8860
|
+
children: /* @__PURE__ */ jsxs30(
|
|
8546
8861
|
PromptInput,
|
|
8547
8862
|
{
|
|
8548
8863
|
"data-boring-state": status,
|
|
@@ -8557,15 +8872,15 @@ function PiChatComposerSurface({
|
|
|
8557
8872
|
else onAttachmentNotice(err.message || "Attachment rejected.");
|
|
8558
8873
|
},
|
|
8559
8874
|
children: [
|
|
8560
|
-
/* @__PURE__ */
|
|
8561
|
-
/* @__PURE__ */
|
|
8875
|
+
/* @__PURE__ */ jsx32(AttachmentsList, {}),
|
|
8876
|
+
/* @__PURE__ */ jsxs30(
|
|
8562
8877
|
"div",
|
|
8563
8878
|
{
|
|
8564
8879
|
"data-boring-agent-part": "composer-input-row",
|
|
8565
8880
|
className: "flex min-h-[var(--composer-input-group-height)] w-full items-center",
|
|
8566
8881
|
children: [
|
|
8567
|
-
/* @__PURE__ */
|
|
8568
|
-
/* @__PURE__ */
|
|
8882
|
+
/* @__PURE__ */ jsx32("div", { className: "flex h-14 shrink-0 items-center pl-2", children: /* @__PURE__ */ jsx32(AttachmentButton, { disabled: disabled || isStreaming }) }),
|
|
8883
|
+
/* @__PURE__ */ jsx32(
|
|
8569
8884
|
PromptInputTextarea,
|
|
8570
8885
|
{
|
|
8571
8886
|
value: draft,
|
|
@@ -8589,13 +8904,13 @@ function PiChatComposerSurface({
|
|
|
8589
8904
|
)
|
|
8590
8905
|
}
|
|
8591
8906
|
),
|
|
8592
|
-
/* @__PURE__ */
|
|
8907
|
+
/* @__PURE__ */ jsx32(
|
|
8593
8908
|
PromptInputFooter,
|
|
8594
8909
|
{
|
|
8595
8910
|
align: "inline-end",
|
|
8596
8911
|
"data-boring-agent-part": "composer-submit-addon",
|
|
8597
8912
|
className: "!order-none !w-auto shrink-0 self-center justify-between border-0 bg-transparent !px-2 !py-0",
|
|
8598
|
-
children: /* @__PURE__ */
|
|
8913
|
+
children: /* @__PURE__ */ jsx32("div", { className: "ml-auto flex items-center gap-1.5", children: /* @__PURE__ */ jsx32(
|
|
8599
8914
|
PromptInputSubmit,
|
|
8600
8915
|
{
|
|
8601
8916
|
"data-boring-agent-part": "composer-submit",
|
|
@@ -8625,7 +8940,7 @@ function PiChatComposerSurface({
|
|
|
8625
8940
|
)
|
|
8626
8941
|
}
|
|
8627
8942
|
),
|
|
8628
|
-
/* @__PURE__ */
|
|
8943
|
+
/* @__PURE__ */ jsxs30(
|
|
8629
8944
|
"div",
|
|
8630
8945
|
{
|
|
8631
8946
|
"data-boring-agent-part": "composer-settings-row",
|
|
@@ -8634,7 +8949,7 @@ function PiChatComposerSurface({
|
|
|
8634
8949
|
chrome ? "max-w-3xl" : "max-w-[680px]"
|
|
8635
8950
|
),
|
|
8636
8951
|
children: [
|
|
8637
|
-
/* @__PURE__ */
|
|
8952
|
+
/* @__PURE__ */ jsx32(
|
|
8638
8953
|
ModelSelectTrigger,
|
|
8639
8954
|
{
|
|
8640
8955
|
value: selectedModel,
|
|
@@ -8651,7 +8966,7 @@ function PiChatComposerSurface({
|
|
|
8651
8966
|
}
|
|
8652
8967
|
}
|
|
8653
8968
|
),
|
|
8654
|
-
thinkingControl ? /* @__PURE__ */
|
|
8969
|
+
thinkingControl ? /* @__PURE__ */ jsx32(
|
|
8655
8970
|
ThinkingSelectTrigger,
|
|
8656
8971
|
{
|
|
8657
8972
|
value: selectedThinking,
|
|
@@ -8674,7 +8989,7 @@ function PiChatComposerSurface({
|
|
|
8674
8989
|
}
|
|
8675
8990
|
|
|
8676
8991
|
// src/front/chat/piChatPanelHooks.ts
|
|
8677
|
-
import { useCallback as
|
|
8992
|
+
import { useCallback as useCallback17, useEffect as useEffect20, useState as useState19, useSyncExternalStore } from "react";
|
|
8678
8993
|
function useExternalRemotePiSession({
|
|
8679
8994
|
sessionId,
|
|
8680
8995
|
workspaceId,
|
|
@@ -8686,7 +9001,7 @@ function useExternalRemotePiSession({
|
|
|
8686
9001
|
remoteSessionOptions
|
|
8687
9002
|
}) {
|
|
8688
9003
|
const [session, setSession] = useState19();
|
|
8689
|
-
|
|
9004
|
+
useEffect20(() => {
|
|
8690
9005
|
if (!sessionId) {
|
|
8691
9006
|
setSession(void 0);
|
|
8692
9007
|
return;
|
|
@@ -8707,10 +9022,10 @@ function useExternalRemotePiSession({
|
|
|
8707
9022
|
}
|
|
8708
9023
|
function useRemotePiSessionState(session) {
|
|
8709
9024
|
return useSyncExternalStore(
|
|
8710
|
-
|
|
9025
|
+
useCallback17((listener) => session?.subscribe(listener) ?? (() => {
|
|
8711
9026
|
}), [session]),
|
|
8712
|
-
|
|
8713
|
-
|
|
9027
|
+
useCallback17(() => session?.getState(), [session]),
|
|
9028
|
+
useCallback17(() => session?.getState(), [session])
|
|
8714
9029
|
);
|
|
8715
9030
|
}
|
|
8716
9031
|
|
|
@@ -8826,7 +9141,7 @@ function errorMessage2(error, fallback) {
|
|
|
8826
9141
|
}
|
|
8827
9142
|
|
|
8828
9143
|
// src/front/chat/PiChatPanel.tsx
|
|
8829
|
-
import { jsx as
|
|
9144
|
+
import { jsx as jsx33, jsxs as jsxs31 } from "react/jsx-runtime";
|
|
8830
9145
|
var DebugDrawer2 = lazy(() => import("../DebugDrawer-2PUDZ2RL.js").then((m) => ({ default: m.DebugDrawer })));
|
|
8831
9146
|
var EMPTY_COMMANDS = [];
|
|
8832
9147
|
var EMPTY_BLOCKERS = [];
|
|
@@ -8880,9 +9195,9 @@ function PiChatPanel({
|
|
|
8880
9195
|
}) {
|
|
8881
9196
|
const externalSessionId = sessionId?.trim() || void 0;
|
|
8882
9197
|
const showSessionSidebar = showSessions ?? externalSessionId === void 0;
|
|
8883
|
-
const onDataRef =
|
|
9198
|
+
const onDataRef = useRef16(onData);
|
|
8884
9199
|
onDataRef.current = onData;
|
|
8885
|
-
const sessionListRefreshRef =
|
|
9200
|
+
const sessionListRefreshRef = useRef16(void 0);
|
|
8886
9201
|
const requestHeadersKey = useMemo12(() => headersContentKey(requestHeaders), [requestHeaders]);
|
|
8887
9202
|
const normalizedRequestHeaders = useMemo12(() => normalizedHeadersFromContentKey(requestHeadersKey), [requestHeadersKey]);
|
|
8888
9203
|
const remoteSessionOptionsWithEvents = useMemo12(() => ({
|
|
@@ -8905,7 +9220,7 @@ function PiChatPanel({
|
|
|
8905
9220
|
remoteSessionOptions: remoteSessionOptionsWithEvents,
|
|
8906
9221
|
enabled: externalSessionId === void 0
|
|
8907
9222
|
});
|
|
8908
|
-
|
|
9223
|
+
useEffect21(() => {
|
|
8909
9224
|
if (externalSessionId) {
|
|
8910
9225
|
sessionListRefreshRef.current = void 0;
|
|
8911
9226
|
return;
|
|
@@ -8959,19 +9274,19 @@ function PiChatPanel({
|
|
|
8959
9274
|
() => readPiComposerSettings({ storageScope, storage }).showThoughts
|
|
8960
9275
|
);
|
|
8961
9276
|
const [composerSettingsOwner, setComposerSettingsOwner] = useState20(() => ({ storageScope, storage }));
|
|
8962
|
-
|
|
9277
|
+
useEffect21(() => {
|
|
8963
9278
|
const settings = readPiComposerSettings({ storageScope, storage });
|
|
8964
9279
|
setStoredThinkingLevel(thinkingControl ? settings.thinkingLevel : DEFAULT_THINKING);
|
|
8965
9280
|
setShowThoughts(settings.showThoughts);
|
|
8966
9281
|
setComposerSettingsOwner({ storageScope, storage });
|
|
8967
9282
|
}, [storage, storageScope, thinkingControl]);
|
|
8968
9283
|
const composerSettingsLoaded = composerSettingsOwner.storageScope === storageScope && composerSettingsOwner.storage === storage;
|
|
8969
|
-
|
|
9284
|
+
useEffect21(() => {
|
|
8970
9285
|
if (!thinkingControl) return;
|
|
8971
9286
|
if (!composerSettingsLoaded) return;
|
|
8972
9287
|
writePiComposerThinking(storedThinkingLevel, { storageScope, storage });
|
|
8973
9288
|
}, [composerSettingsLoaded, storage, storageScope, storedThinkingLevel, thinkingControl]);
|
|
8974
|
-
|
|
9289
|
+
useEffect21(() => {
|
|
8975
9290
|
if (!composerSettingsLoaded) return;
|
|
8976
9291
|
writePiComposerShowThoughts(showThoughts, { storageScope, storage });
|
|
8977
9292
|
}, [composerSettingsLoaded, showThoughts, storage, storageScope]);
|
|
@@ -8980,14 +9295,14 @@ function PiChatPanel({
|
|
|
8980
9295
|
const [modelPickerOpen, setModelPickerOpen] = useState20(false);
|
|
8981
9296
|
const [thinkingPickerOpen, setThinkingPickerOpen] = useState20(false);
|
|
8982
9297
|
const [draft, setDraft] = useState20(() => initialDraft ?? "");
|
|
8983
|
-
const draftRef =
|
|
9298
|
+
const draftRef = useRef16(draft);
|
|
8984
9299
|
draftRef.current = draft;
|
|
8985
|
-
const initialDraftGuard =
|
|
8986
|
-
const pendingAutoSubmitSettleRef =
|
|
8987
|
-
const acceptedAutoSubmitSettleRef =
|
|
8988
|
-
const resetInProgressRef =
|
|
8989
|
-
const autoCreateInFlightRef =
|
|
8990
|
-
const settlePendingAutoSubmit =
|
|
9300
|
+
const initialDraftGuard = useRef16(new InitialDraftAutoSubmitGuard());
|
|
9301
|
+
const pendingAutoSubmitSettleRef = useRef16(void 0);
|
|
9302
|
+
const acceptedAutoSubmitSettleRef = useRef16(void 0);
|
|
9303
|
+
const resetInProgressRef = useRef16(false);
|
|
9304
|
+
const autoCreateInFlightRef = useRef16(false);
|
|
9305
|
+
const settlePendingAutoSubmit = useCallback18((sessionId2) => {
|
|
8991
9306
|
const pendingSessionId = pendingAutoSubmitSettleRef.current;
|
|
8992
9307
|
if (!pendingSessionId || sessionId2 && pendingSessionId !== sessionId2) return false;
|
|
8993
9308
|
pendingAutoSubmitSettleRef.current = void 0;
|
|
@@ -8995,23 +9310,25 @@ function PiChatPanel({
|
|
|
8995
9310
|
onAutoSubmitInitialDraftSettled?.();
|
|
8996
9311
|
return true;
|
|
8997
9312
|
}, [onAutoSubmitInitialDraftSettled]);
|
|
8998
|
-
const prevStatusRef =
|
|
8999
|
-
const statusRef =
|
|
9000
|
-
const scrollToBottomRef =
|
|
9313
|
+
const prevStatusRef = useRef16("idle");
|
|
9314
|
+
const statusRef = useRef16("idle");
|
|
9315
|
+
const scrollToBottomRef = useRef16(() => {
|
|
9001
9316
|
});
|
|
9002
|
-
const textareaRef =
|
|
9317
|
+
const textareaRef = useRef16(null);
|
|
9003
9318
|
const [localNotices, setLocalNotices] = useState20([]);
|
|
9004
9319
|
const [dismissedNoticeIds, setDismissedNoticeIds] = useState20(() => /* @__PURE__ */ new Set());
|
|
9005
9320
|
const [pluginUpdateState, setPluginUpdateState] = useState20(null);
|
|
9321
|
+
const [commandNotifyState, setCommandNotifyState] = useState20(null);
|
|
9322
|
+
const commandRunIdRef = useRef16(0);
|
|
9006
9323
|
const [serverSkillsRefreshKey, setServerSkillsRefreshKey] = useState20(0);
|
|
9007
9324
|
const [localSubmittedSessionId, setLocalSubmittedSessionId] = useState20();
|
|
9008
|
-
const localSubmittedSessionRef =
|
|
9325
|
+
const localSubmittedSessionRef = useRef16(void 0);
|
|
9009
9326
|
const { attachmentNotice, setAttachmentNotice } = useAttachmentNotice();
|
|
9010
|
-
const markLocalSubmitted =
|
|
9327
|
+
const markLocalSubmitted = useCallback18((sessionId2) => {
|
|
9011
9328
|
localSubmittedSessionRef.current = sessionId2;
|
|
9012
9329
|
setLocalSubmittedSessionId(sessionId2);
|
|
9013
9330
|
}, []);
|
|
9014
|
-
const clearLocalSubmitted =
|
|
9331
|
+
const clearLocalSubmitted = useCallback18((sessionId2) => {
|
|
9015
9332
|
if (sessionId2 && localSubmittedSessionRef.current !== sessionId2) return;
|
|
9016
9333
|
localSubmittedSessionRef.current = void 0;
|
|
9017
9334
|
setLocalSubmittedSessionId(void 0);
|
|
@@ -9023,16 +9340,17 @@ function PiChatPanel({
|
|
|
9023
9340
|
for (const command of commands) next.register(command);
|
|
9024
9341
|
return next;
|
|
9025
9342
|
}, [apiBaseUrl, commands, extraCommands, hotReloadEnabled, normalizedRequestHeaders, serverResourcesEnabled, serverSkillsRefreshKey, storageScope]);
|
|
9026
|
-
const
|
|
9027
|
-
apiBaseUrl,
|
|
9028
|
-
fetch: fetch2,
|
|
9343
|
+
const commandsStamp = useServerCommands({
|
|
9029
9344
|
registry,
|
|
9030
|
-
refreshKey: serverSkillsRefreshKey,
|
|
9031
9345
|
requestHeaders: normalizedRequestHeaders,
|
|
9346
|
+
sessionId: activeSessionId ?? "default",
|
|
9347
|
+
apiBaseUrl,
|
|
9348
|
+
fetch: fetch2,
|
|
9032
9349
|
storageScope,
|
|
9350
|
+
refreshKey: serverSkillsRefreshKey,
|
|
9033
9351
|
enabled: serverResourcesEnabled
|
|
9034
9352
|
});
|
|
9035
|
-
const allCommands = useMemo12(() => registry.list(), [registry,
|
|
9353
|
+
const allCommands = useMemo12(() => registry.list(), [registry, commandsStamp]);
|
|
9036
9354
|
const activeChatSessionId = selectedChatState?.sessionId;
|
|
9037
9355
|
const warmupNotice = composerNoticeForWarmup(workspaceWarmupStatus);
|
|
9038
9356
|
const runtimeDependenciesNotice = composerNoticeForRuntimeDependencies(workspaceWarmupStatus);
|
|
@@ -9063,23 +9381,23 @@ function PiChatPanel({
|
|
|
9063
9381
|
}] : [];
|
|
9064
9382
|
return [...fromState, ...sessionNotice, ...largeStateNotice, ...localNotices].filter((notice) => !dismissedNoticeIds.has(notice.id));
|
|
9065
9383
|
}, [debug, debugState?.largeStateWarning, dismissedNoticeIds, localNotices, selectedChatState, sessionsError]);
|
|
9066
|
-
const addLocalNotice =
|
|
9384
|
+
const addLocalNotice = useCallback18((notice) => {
|
|
9067
9385
|
setLocalNotices((previous) => {
|
|
9068
9386
|
const next = previous.filter((candidate) => candidate.id !== notice.id);
|
|
9069
9387
|
return [...next, notice];
|
|
9070
9388
|
});
|
|
9071
9389
|
}, []);
|
|
9072
|
-
const clearLocalNotice =
|
|
9390
|
+
const clearLocalNotice = useCallback18((id) => {
|
|
9073
9391
|
setDismissedNoticeIds((previous) => new Set(previous).add(id));
|
|
9074
9392
|
setLocalNotices((previous) => previous.filter((notice) => notice.id !== id));
|
|
9075
9393
|
}, []);
|
|
9076
|
-
const createSession =
|
|
9394
|
+
const createSession = useCallback18(() => {
|
|
9077
9395
|
if (externalSessionId) return;
|
|
9078
9396
|
void sessions.create().catch((error) => {
|
|
9079
9397
|
addLocalNotice({ id: "session-create-error", level: "error", text: errorMessage2(error, "Could not create a Pi session."), dismissible: true });
|
|
9080
9398
|
});
|
|
9081
9399
|
}, [addLocalNotice, externalSessionId, sessions.create]);
|
|
9082
|
-
|
|
9400
|
+
useEffect21(() => {
|
|
9083
9401
|
if (externalSessionId || sessionsLoading || sessionsError || activeSessionId || sessionList.length > 0) return;
|
|
9084
9402
|
if (resetInProgressRef.current) return;
|
|
9085
9403
|
if (autoCreateInFlightRef.current) return;
|
|
@@ -9089,18 +9407,18 @@ function PiChatPanel({
|
|
|
9089
9407
|
addLocalNotice({ id: "session-auto-create-error", level: "error", text: errorMessage2(error, "Could not create a Pi session."), dismissible: true });
|
|
9090
9408
|
});
|
|
9091
9409
|
}, [activeSessionId, addLocalNotice, externalSessionId, sessionList.length, sessions.create, sessionsError, sessionsLoading]);
|
|
9092
|
-
|
|
9410
|
+
useEffect21(() => {
|
|
9093
9411
|
if (externalSessionId || sessionsError || activeSessionId || sessionList.length > 0) {
|
|
9094
9412
|
autoCreateInFlightRef.current = false;
|
|
9095
9413
|
}
|
|
9096
9414
|
}, [activeSessionId, externalSessionId, sessionList.length, sessionsError]);
|
|
9097
|
-
const deleteSession =
|
|
9415
|
+
const deleteSession = useCallback18((sessionId2) => {
|
|
9098
9416
|
if (externalSessionId) return;
|
|
9099
9417
|
void sessions.delete(sessionId2).catch((error) => {
|
|
9100
9418
|
addLocalNotice({ id: `session-delete-error:${sessionId2}`, level: "error", text: errorMessage2(error, "Could not delete the Pi session."), dismissible: true });
|
|
9101
9419
|
});
|
|
9102
9420
|
}, [addLocalNotice, externalSessionId, sessions.delete]);
|
|
9103
|
-
const resetSession =
|
|
9421
|
+
const resetSession = useCallback18(() => {
|
|
9104
9422
|
const currentSessionId = activeSessionId;
|
|
9105
9423
|
if (externalSessionId) {
|
|
9106
9424
|
void onSessionReset?.();
|
|
@@ -9118,11 +9436,11 @@ function PiChatPanel({
|
|
|
9118
9436
|
resetInProgressRef.current = false;
|
|
9119
9437
|
});
|
|
9120
9438
|
}, [activeSessionId, addLocalNotice, externalSessionId, onSessionReset, sessions.create, sessions.delete]);
|
|
9121
|
-
const reloadAgentPlugins =
|
|
9439
|
+
const reloadAgentPlugins = useCallback18(async () => {
|
|
9122
9440
|
if (!onReloadAgentPlugins) throw new Error("Agent plugin reload is not configured.");
|
|
9123
9441
|
return await onReloadAgentPlugins();
|
|
9124
9442
|
}, [onReloadAgentPlugins]);
|
|
9125
|
-
const runPluginUpdate =
|
|
9443
|
+
const runPluginUpdate = useCallback18(async () => {
|
|
9126
9444
|
setPluginUpdateState({ kind: "running" });
|
|
9127
9445
|
try {
|
|
9128
9446
|
const message = await reloadAgentPlugins();
|
|
@@ -9140,8 +9458,26 @@ function PiChatPanel({
|
|
|
9140
9458
|
return `Plugin update failed: ${message}`;
|
|
9141
9459
|
}
|
|
9142
9460
|
}, [reloadAgentPlugins]);
|
|
9143
|
-
const dismissPluginUpdate =
|
|
9144
|
-
|
|
9461
|
+
const dismissPluginUpdate = useCallback18(() => setPluginUpdateState(null), []);
|
|
9462
|
+
const dismissCommandNotify = useCallback18(() => setCommandNotifyState(null), []);
|
|
9463
|
+
useEffect21(() => {
|
|
9464
|
+
if (typeof window === "undefined") return;
|
|
9465
|
+
const onCommandNotify = (event) => {
|
|
9466
|
+
const payload = event.detail;
|
|
9467
|
+
if (!payload || typeof payload.message !== "string") return;
|
|
9468
|
+
const tone = payload.tone;
|
|
9469
|
+
const command = payload.command ?? "";
|
|
9470
|
+
if (tone === "error") {
|
|
9471
|
+
setCommandNotifyState({ kind: "error", command, message: payload.message });
|
|
9472
|
+
} else {
|
|
9473
|
+
const runId = ++commandRunIdRef.current;
|
|
9474
|
+
setCommandNotifyState({ kind: "success", command, detail: payload.message, runId });
|
|
9475
|
+
}
|
|
9476
|
+
};
|
|
9477
|
+
window.addEventListener(WORKSPACE_COMMAND_NOTIFY_EVENT, onCommandNotify);
|
|
9478
|
+
return () => window.removeEventListener(WORKSPACE_COMMAND_NOTIFY_EVENT, onCommandNotify);
|
|
9479
|
+
}, []);
|
|
9480
|
+
useEffect21(() => {
|
|
9145
9481
|
if (!hotReloadEnabled || typeof window === "undefined") return;
|
|
9146
9482
|
const onBrowserPluginReload = (event) => {
|
|
9147
9483
|
const parsed = parseBrowserPluginReloadDetail(event.detail);
|
|
@@ -9179,7 +9515,7 @@ function PiChatPanel({
|
|
|
9179
9515
|
textareaRef,
|
|
9180
9516
|
disabled: mentionState !== null || slashQuery !== null || modelPickerOpen || thinkingPickerOpen
|
|
9181
9517
|
});
|
|
9182
|
-
const setComposerDraft =
|
|
9518
|
+
const setComposerDraft = useCallback18((next, focus = true) => {
|
|
9183
9519
|
draftRef.current = next;
|
|
9184
9520
|
setDraft(next);
|
|
9185
9521
|
if (textareaRef.current) {
|
|
@@ -9187,11 +9523,11 @@ function PiChatPanel({
|
|
|
9187
9523
|
if (focus) textareaRef.current.focus();
|
|
9188
9524
|
}
|
|
9189
9525
|
}, []);
|
|
9190
|
-
const warnComposer =
|
|
9526
|
+
const warnComposer = useCallback18((message) => {
|
|
9191
9527
|
onComposerWarning?.(message);
|
|
9192
9528
|
addLocalNotice({ id: `composer-warning:${Date.now()}`, level: "warning", text: message, dismissible: true });
|
|
9193
9529
|
}, [addLocalNotice, onComposerWarning]);
|
|
9194
|
-
const openModelPicker =
|
|
9530
|
+
const openModelPicker = useCallback18(() => {
|
|
9195
9531
|
if (isPiBusyStatus(statusRef.current)) {
|
|
9196
9532
|
warnComposer("Model picker is unavailable while the agent is running.");
|
|
9197
9533
|
return false;
|
|
@@ -9204,7 +9540,7 @@ function PiChatPanel({
|
|
|
9204
9540
|
setModelPickerOpen(true);
|
|
9205
9541
|
return true;
|
|
9206
9542
|
}, [model, warnComposer]);
|
|
9207
|
-
const openThinkingPicker =
|
|
9543
|
+
const openThinkingPicker = useCallback18(() => {
|
|
9208
9544
|
if (isPiBusyStatus(statusRef.current)) {
|
|
9209
9545
|
warnComposer("Thinking picker is unavailable while the agent is running.");
|
|
9210
9546
|
return false;
|
|
@@ -9217,21 +9553,21 @@ function PiChatPanel({
|
|
|
9217
9553
|
setThinkingPickerOpen(true);
|
|
9218
9554
|
return true;
|
|
9219
9555
|
}, [thinkingControl, thinkingLevel, warnComposer]);
|
|
9220
|
-
const selectComposerModel =
|
|
9556
|
+
const selectComposerModel = useCallback18((query) => {
|
|
9221
9557
|
if (model !== void 0) return "Model selection is controlled by the host.";
|
|
9222
9558
|
const match = resolveModelSlashSelection(query, modelOptions);
|
|
9223
9559
|
if (!match) return `No model matched "${query}".`;
|
|
9224
9560
|
modelDiscovery.setModel(match);
|
|
9225
9561
|
return `Model set to ${match.label ?? match.id}.`;
|
|
9226
9562
|
}, [model, modelDiscovery, modelOptions]);
|
|
9227
|
-
const selectComposerThinking =
|
|
9563
|
+
const selectComposerThinking = useCallback18((query) => {
|
|
9228
9564
|
if (!thinkingControl || thinkingLevel !== void 0) return "Thinking level is controlled by the host.";
|
|
9229
9565
|
const match = resolveThinkingSlashSelection(query);
|
|
9230
9566
|
if (!match) return `No thinking level matched "${query}".`;
|
|
9231
9567
|
setStoredThinkingLevel(match);
|
|
9232
9568
|
return `Thinking set to ${thinkingLabel(match)}.`;
|
|
9233
9569
|
}, [thinkingControl, thinkingLevel]);
|
|
9234
|
-
const selectSlashCommand =
|
|
9570
|
+
const selectSlashCommand = useCallback18((name) => {
|
|
9235
9571
|
if (name === "model") {
|
|
9236
9572
|
dismissSlash();
|
|
9237
9573
|
if (openModelPicker()) setComposerDraft("");
|
|
@@ -9309,7 +9645,7 @@ function PiChatPanel({
|
|
|
9309
9645
|
}
|
|
9310
9646
|
});
|
|
9311
9647
|
}, [activeChatSessionId, addLocalNotice, clearMentionedFiles, composerBlocked, composerBlockerLabel, effectiveMentionedFiles, markLocalSubmitted, onBeforeSubmit, onCommandResult, onComposerWarning, onMentionedFilesConsumed, openModelPicker, openThinkingPicker, registry, reloadAgentPlugins, resetSession, runPluginUpdate, selectComposerModel, selectComposerThinking, selectedModel, selectedPiSession, selectedThinking, setComposerDraft, submitThinkingControl]);
|
|
9312
|
-
const sendComposerMessage =
|
|
9648
|
+
const sendComposerMessage = useCallback18(async ({ text, files, source = "composer" }) => {
|
|
9313
9649
|
if (!policy) {
|
|
9314
9650
|
addLocalNotice({ id: "composer-no-session", level: "warning", text: "Create or select a Pi session before sending.", dismissible: true });
|
|
9315
9651
|
return false;
|
|
@@ -9337,7 +9673,7 @@ function PiChatPanel({
|
|
|
9337
9673
|
throw error;
|
|
9338
9674
|
}
|
|
9339
9675
|
}, [activeChatSessionId, addLocalNotice, clearLocalSubmitted, markLocalSubmitted, policy, selectedPiSession, setComposerDraft]);
|
|
9340
|
-
const editQueued =
|
|
9676
|
+
const editQueued = useCallback18(() => {
|
|
9341
9677
|
if (!policy) return;
|
|
9342
9678
|
void policy.editQueued().then((result) => {
|
|
9343
9679
|
if (result.type === "clear-failed") {
|
|
@@ -9345,23 +9681,24 @@ function PiChatPanel({
|
|
|
9345
9681
|
}
|
|
9346
9682
|
});
|
|
9347
9683
|
}, [addLocalNotice, policy]);
|
|
9348
|
-
const stop =
|
|
9684
|
+
const stop = useCallback18(() => {
|
|
9349
9685
|
onComposerStop?.();
|
|
9350
9686
|
void policy?.stop().catch((error) => {
|
|
9351
9687
|
addLocalNotice({ id: "stop-error", level: "error", text: errorMessage2(error, "Could not stop the Pi session."), dismissible: true });
|
|
9352
9688
|
});
|
|
9353
9689
|
}, [addLocalNotice, onComposerStop, policy]);
|
|
9354
|
-
const interrupt =
|
|
9690
|
+
const interrupt = useCallback18(() => {
|
|
9355
9691
|
void policy?.interrupt().catch((error) => {
|
|
9356
9692
|
addLocalNotice({ id: "interrupt-error", level: "error", text: errorMessage2(error, "Could not interrupt the Pi session."), dismissible: true });
|
|
9357
9693
|
});
|
|
9358
9694
|
}, [addLocalNotice, policy]);
|
|
9359
|
-
|
|
9695
|
+
useEffect21(() => {
|
|
9360
9696
|
setPluginUpdateState(null);
|
|
9697
|
+
setCommandNotifyState(null);
|
|
9361
9698
|
setLocalNotices([]);
|
|
9362
9699
|
setDismissedNoticeIds(/* @__PURE__ */ new Set());
|
|
9363
9700
|
}, [activeSessionId]);
|
|
9364
|
-
|
|
9701
|
+
useEffect21(() => {
|
|
9365
9702
|
const currentSessionId = activeSessionId ?? "__none__";
|
|
9366
9703
|
if (initialDraftGuard.current.shouldRestore(currentSessionId, initialDraft) && initialDraft !== void 0) {
|
|
9367
9704
|
setComposerDraft(initialDraft, initialDraft.length > 0);
|
|
@@ -9370,7 +9707,7 @@ function PiChatPanel({
|
|
|
9370
9707
|
}, [activeSessionId, initialDraft, onDraftRestored, setComposerDraft]);
|
|
9371
9708
|
const remoteStatus = selectedChatState?.status ?? (sessionsLoading || chatStatePending || selectedSessionPending ? "hydrating" : "idle");
|
|
9372
9709
|
const status = localSubmittedSessionId === activeSessionId && remoteStatus === "idle" ? "submitted" : remoteStatus;
|
|
9373
|
-
|
|
9710
|
+
useEffect21(() => {
|
|
9374
9711
|
if (!localSubmittedSessionId) return;
|
|
9375
9712
|
if (localSubmittedSessionId !== activeSessionId) {
|
|
9376
9713
|
clearLocalSubmitted();
|
|
@@ -9378,7 +9715,7 @@ function PiChatPanel({
|
|
|
9378
9715
|
}
|
|
9379
9716
|
if (remoteStatus !== "idle") clearLocalSubmitted(localSubmittedSessionId);
|
|
9380
9717
|
}, [activeSessionId, clearLocalSubmitted, localSubmittedSessionId, remoteStatus]);
|
|
9381
|
-
|
|
9718
|
+
useEffect21(() => {
|
|
9382
9719
|
const previous = prevStatusRef.current;
|
|
9383
9720
|
statusRef.current = status;
|
|
9384
9721
|
prevStatusRef.current = status;
|
|
@@ -9388,7 +9725,7 @@ function PiChatPanel({
|
|
|
9388
9725
|
if (!isPiBusyStatus(previous) && previous !== "submitted") return;
|
|
9389
9726
|
settlePendingAutoSubmit();
|
|
9390
9727
|
}, [settlePendingAutoSubmit, status]);
|
|
9391
|
-
|
|
9728
|
+
useEffect21(() => {
|
|
9392
9729
|
if (!autoSubmitInitialDraft || !policy || !activeSessionId || composerBlocked) return;
|
|
9393
9730
|
if (!initialDraftGuard.current.claimAutoSubmit(activeSessionId, initialDraft)) return;
|
|
9394
9731
|
pendingAutoSubmitSettleRef.current = activeSessionId;
|
|
@@ -9423,7 +9760,7 @@ function PiChatPanel({
|
|
|
9423
9760
|
addLocalNotice({ id: "auto-submit-error", level: "error", text: errorMessage2(error, "Could not auto-submit the initial draft."), dismissible: true });
|
|
9424
9761
|
});
|
|
9425
9762
|
}, [activeSessionId, addLocalNotice, autoSubmitInitialDraft, clearLocalSubmitted, composerBlocked, initialDraft, markLocalSubmitted, onAutoSubmitInitialDraftAccepted, policy, selectedPiSession, setComposerDraft, settlePendingAutoSubmit]);
|
|
9426
|
-
|
|
9763
|
+
useEffect21(() => {
|
|
9427
9764
|
if (workspaceWarmupStatus?.status === "ready") {
|
|
9428
9765
|
clearLocalNotice("workspace-warmup");
|
|
9429
9766
|
}
|
|
@@ -9434,18 +9771,18 @@ function PiChatPanel({
|
|
|
9434
9771
|
const submitDisabled = !policy || sessionsLoading || composerBlocked && !isStreaming;
|
|
9435
9772
|
const mergedToolRenderers = useMemo12(() => mergeShadcnToolRenderers(toolRenderers), [toolRenderers]);
|
|
9436
9773
|
const debugMessages = useMemo12(() => messages.map(toDebugUiMessage), [messages]);
|
|
9437
|
-
const onTextareaChange =
|
|
9774
|
+
const onTextareaChange = useCallback18((event) => {
|
|
9438
9775
|
setModelPickerOpen(false);
|
|
9439
9776
|
setThinkingPickerOpen(false);
|
|
9440
9777
|
setDraft(event.currentTarget.value);
|
|
9441
9778
|
handleComposerChange(event);
|
|
9442
9779
|
}, [handleComposerChange]);
|
|
9443
|
-
|
|
9780
|
+
useEffect21(() => {
|
|
9444
9781
|
if (!isStreaming) return;
|
|
9445
9782
|
setModelPickerOpen(false);
|
|
9446
9783
|
setThinkingPickerOpen(false);
|
|
9447
9784
|
}, [isStreaming]);
|
|
9448
|
-
|
|
9785
|
+
useEffect21(() => {
|
|
9449
9786
|
if (typeof window === "undefined" || !activeChatSessionId) return;
|
|
9450
9787
|
window.dispatchEvent(new CustomEvent("boring:chat-session-status", {
|
|
9451
9788
|
detail: { sessionId: activeChatSessionId, working: isStreaming }
|
|
@@ -9458,7 +9795,7 @@ function PiChatPanel({
|
|
|
9458
9795
|
}));
|
|
9459
9796
|
};
|
|
9460
9797
|
}, [activeChatSessionId, isStreaming]);
|
|
9461
|
-
const onTextareaKeyDown =
|
|
9798
|
+
const onTextareaKeyDown = useCallback18((event) => {
|
|
9462
9799
|
if (event.key === "Escape" && isStreaming) {
|
|
9463
9800
|
if (event.defaultPrevented || mentionState !== null || slashQuery !== null) {
|
|
9464
9801
|
handleComposerKeyDown(event);
|
|
@@ -9470,7 +9807,7 @@ function PiChatPanel({
|
|
|
9470
9807
|
}
|
|
9471
9808
|
handleComposerKeyDown(event);
|
|
9472
9809
|
}, [handleComposerKeyDown, interrupt, isStreaming, mentionState, slashQuery]);
|
|
9473
|
-
return /* @__PURE__ */
|
|
9810
|
+
return /* @__PURE__ */ jsx33(ArtifactOpenProvider, { onOpenArtifact, children: /* @__PURE__ */ jsxs31(
|
|
9474
9811
|
"div",
|
|
9475
9812
|
{
|
|
9476
9813
|
"data-boring-agent": "",
|
|
@@ -9487,7 +9824,7 @@ function PiChatPanel({
|
|
|
9487
9824
|
role: "region",
|
|
9488
9825
|
"aria-label": "Agent assistant",
|
|
9489
9826
|
children: [
|
|
9490
|
-
showSessionSidebar ? /* @__PURE__ */
|
|
9827
|
+
showSessionSidebar ? /* @__PURE__ */ jsx33("aside", { "data-boring-agent-part": "pi-chat-session-sidebar", className: "min-h-0 w-64 shrink-0 border-r border-border/60", children: /* @__PURE__ */ jsx33(
|
|
9491
9828
|
SessionList,
|
|
9492
9829
|
{
|
|
9493
9830
|
sessions: sessionList,
|
|
@@ -9501,7 +9838,7 @@ function PiChatPanel({
|
|
|
9501
9838
|
loadingMore: sessions.loadingMore
|
|
9502
9839
|
}
|
|
9503
9840
|
) }) : null,
|
|
9504
|
-
/* @__PURE__ */
|
|
9841
|
+
/* @__PURE__ */ jsx33("div", { className: "flex min-h-0 min-w-0 flex-1 flex-col", children: /* @__PURE__ */ jsxs31(
|
|
9505
9842
|
"div",
|
|
9506
9843
|
{
|
|
9507
9844
|
className: cn(
|
|
@@ -9510,7 +9847,7 @@ function PiChatPanel({
|
|
|
9510
9847
|
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)]"
|
|
9511
9848
|
),
|
|
9512
9849
|
children: [
|
|
9513
|
-
/* @__PURE__ */
|
|
9850
|
+
/* @__PURE__ */ jsx33(
|
|
9514
9851
|
PiConversationSurface,
|
|
9515
9852
|
{
|
|
9516
9853
|
chrome,
|
|
@@ -9532,7 +9869,7 @@ function PiChatPanel({
|
|
|
9532
9869
|
windowResetKey: activeSessionId
|
|
9533
9870
|
}
|
|
9534
9871
|
),
|
|
9535
|
-
/* @__PURE__ */
|
|
9872
|
+
/* @__PURE__ */ jsx33(
|
|
9536
9873
|
PiChatComposerSurface,
|
|
9537
9874
|
{
|
|
9538
9875
|
chrome,
|
|
@@ -9554,6 +9891,8 @@ function PiChatPanel({
|
|
|
9554
9891
|
pluginUpdateState,
|
|
9555
9892
|
onDismissPluginUpdate: dismissPluginUpdate,
|
|
9556
9893
|
onRunPluginUpdate: runPluginUpdate,
|
|
9894
|
+
commandNotifyState,
|
|
9895
|
+
onDismissCommandNotify: dismissCommandNotify,
|
|
9557
9896
|
attachmentNotice,
|
|
9558
9897
|
onAttachmentNotice: setAttachmentNotice,
|
|
9559
9898
|
mentionState,
|
|
@@ -9592,7 +9931,7 @@ function PiChatPanel({
|
|
|
9592
9931
|
]
|
|
9593
9932
|
}
|
|
9594
9933
|
) }),
|
|
9595
|
-
debug ? /* @__PURE__ */
|
|
9934
|
+
debug ? /* @__PURE__ */ jsx33(Suspense, { fallback: null, children: /* @__PURE__ */ jsx33("div", { "aria-label": "Pi chat debug metadata", className: "contents", role: "region", children: /* @__PURE__ */ jsx33(
|
|
9596
9935
|
DebugDrawer2,
|
|
9597
9936
|
{
|
|
9598
9937
|
apiBaseUrl,
|