@hachej/boring-agent 0.1.63 → 0.1.65
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-Ddn5DQ5E.d.ts → agentPluginEvents-ChUzG2Lh.d.ts} +3 -134
- package/dist/chatSubmitPayload-DwOHyiqR.d.ts +22 -0
- package/dist/chunk-4LXA7OOV.js +290 -0
- package/dist/chunk-AJZHR626.js +85 -0
- package/dist/chunk-AQBXNPMD.js +17 -0
- package/dist/chunk-HHW2UNBK.js +1812 -0
- package/dist/chunk-NKP5AR4C.js +2755 -0
- package/dist/chunk-WSQ5QNIY.js +18 -0
- package/dist/chunk-XZKU7FBV.js +96 -0
- package/dist/{chunk-HDOSWEXG.js → chunk-ZD7MM2LQ.js} +0 -15
- package/dist/core/index.d.ts +9 -0
- package/dist/core/index.js +15 -0
- package/dist/createHarness-LA2OO2DL.js +17 -0
- package/dist/front/index.d.ts +32 -27
- package/dist/front/index.js +84 -30
- package/dist/front/styles.css +67 -70
- package/dist/harness-DN9KdrT7.d.ts +265 -0
- package/dist/piChatCommand-C5ZM-AMG.d.ts +40 -0
- package/dist/{piChatEvent-B6GDifo2.d.ts → piChatEvent-B6Lg9ft-.d.ts} +88 -98
- package/dist/server/index.d.ts +238 -6
- package/dist/server/index.js +3294 -6225
- package/dist/shared/index.d.ts +212 -208
- package/dist/shared/index.js +21 -9
- package/docs/ERROR_CODES.md +3 -0
- package/docs/plans/archive/harness-followup-capabilities.md +1 -1
- package/docs/plans/archive/pi-tools-migration.md +1 -1
- package/docs/plans/archive/vercel-persistent-sandbox-adapter.md +1 -1
- package/docs/runtime.md +22 -9
- package/package.json +39 -34
- package/dist/chatSubmitPayload-DHqQL2wD.d.ts +0 -48
- package/dist/chunk-G6YPXDHR.js +0 -376
package/dist/front/index.js
CHANGED
|
@@ -4,7 +4,6 @@ import {
|
|
|
4
4
|
} from "../chunk-DGRKMMXO.js";
|
|
5
5
|
import {
|
|
6
6
|
CommandReceiptSchema,
|
|
7
|
-
ErrorCode,
|
|
8
7
|
FollowUpReceiptSchema,
|
|
9
8
|
PiChatSnapshotSchema,
|
|
10
9
|
PiChatStreamFrameSchema,
|
|
@@ -13,7 +12,10 @@ import {
|
|
|
13
12
|
StopReceiptSchema,
|
|
14
13
|
extractToolUiMetadata,
|
|
15
14
|
sanitizeToolUiMetadata
|
|
16
|
-
} from "../chunk-
|
|
15
|
+
} from "../chunk-4LXA7OOV.js";
|
|
16
|
+
import {
|
|
17
|
+
ErrorCode
|
|
18
|
+
} from "../chunk-XZKU7FBV.js";
|
|
17
19
|
import {
|
|
18
20
|
DebugDrawer,
|
|
19
21
|
cn,
|
|
@@ -1534,7 +1536,7 @@ function toHeaderProps(part) {
|
|
|
1534
1536
|
toolName: part.toolName
|
|
1535
1537
|
};
|
|
1536
1538
|
}
|
|
1537
|
-
function PathLabel({ path }) {
|
|
1539
|
+
function PathLabel({ path, filesystem }) {
|
|
1538
1540
|
const onOpen = useOpenArtifact();
|
|
1539
1541
|
if (!onOpen) {
|
|
1540
1542
|
return /* @__PURE__ */ jsx11("span", { className: "font-mono text-[12.5px] text-foreground/85", children: path });
|
|
@@ -1542,7 +1544,8 @@ function PathLabel({ path }) {
|
|
|
1542
1544
|
const open = (e) => {
|
|
1543
1545
|
e.preventDefault();
|
|
1544
1546
|
e.stopPropagation();
|
|
1545
|
-
onOpen(path);
|
|
1547
|
+
if (filesystem) onOpen(path, { filesystem });
|
|
1548
|
+
else onOpen(path);
|
|
1546
1549
|
};
|
|
1547
1550
|
const handleKeyDown = (e) => {
|
|
1548
1551
|
if (e.key === "Enter" || e.key === " ") open(e);
|
|
@@ -1603,11 +1606,11 @@ function renderRuntimeNotReady(part) {
|
|
|
1603
1606
|
function renderReadinessBlock(part) {
|
|
1604
1607
|
return renderWorkspaceNotReady(part) ?? renderRuntimeNotReady(part);
|
|
1605
1608
|
}
|
|
1606
|
-
function pathTitle(prefix, path) {
|
|
1609
|
+
function pathTitle(prefix, path, filesystem) {
|
|
1607
1610
|
return /* @__PURE__ */ jsxs10("span", { className: "flex min-w-0 items-center gap-1.5", children: [
|
|
1608
1611
|
/* @__PURE__ */ jsx11("span", { className: "text-muted-foreground", children: prefix }),
|
|
1609
1612
|
/* @__PURE__ */ jsx11("span", { className: "text-muted-foreground/40", "aria-hidden": "true", children: "\xB7" }),
|
|
1610
|
-
/* @__PURE__ */ jsx11(PathLabel, { path })
|
|
1613
|
+
/* @__PURE__ */ jsx11(PathLabel, { path, filesystem })
|
|
1611
1614
|
] });
|
|
1612
1615
|
}
|
|
1613
1616
|
function renderBash2(part) {
|
|
@@ -1649,10 +1652,11 @@ function renderRead2(part) {
|
|
|
1649
1652
|
const input = asRecord2(part.input);
|
|
1650
1653
|
const output = asRecord2(part.output);
|
|
1651
1654
|
const path = typeof input.path === "string" ? input.path : "";
|
|
1655
|
+
const filesystem = typeof input.filesystem === "string" ? input.filesystem : void 0;
|
|
1652
1656
|
const content = extractTextContent(output);
|
|
1653
1657
|
const lang = langFromPath(path);
|
|
1654
1658
|
return /* @__PURE__ */ jsxs10(Tool2, { children: [
|
|
1655
|
-
/* @__PURE__ */ jsx11(ToolHeader, { icon: /* @__PURE__ */ jsx11(FileTextIcon, { className: "size-4 text-muted-foreground" }), title: pathTitle("read", path), ...toHeaderProps(part) }),
|
|
1659
|
+
/* @__PURE__ */ jsx11(ToolHeader, { icon: /* @__PURE__ */ jsx11(FileTextIcon, { className: "size-4 text-muted-foreground" }), title: pathTitle("read", path, filesystem), ...toHeaderProps(part) }),
|
|
1656
1660
|
/* @__PURE__ */ jsxs10(ToolContent, { children: [
|
|
1657
1661
|
/* @__PURE__ */ jsx11(ToolInput, { input }),
|
|
1658
1662
|
content && /* @__PURE__ */ jsxs10("section", { className: "space-y-2", children: [
|
|
@@ -1667,11 +1671,12 @@ function renderWrite2(part) {
|
|
|
1667
1671
|
if (readiness) return readiness;
|
|
1668
1672
|
const input = asRecord2(part.input);
|
|
1669
1673
|
const path = typeof input.path === "string" ? input.path : "";
|
|
1674
|
+
const filesystem = typeof input.filesystem === "string" ? input.filesystem : void 0;
|
|
1670
1675
|
const content = typeof input.content === "string" ? input.content : "";
|
|
1671
1676
|
const bytes = content.length;
|
|
1672
1677
|
const lang = langFromPath(path);
|
|
1673
1678
|
return /* @__PURE__ */ jsxs10(Tool2, { children: [
|
|
1674
|
-
/* @__PURE__ */ jsx11(ToolHeader, { icon: /* @__PURE__ */ jsx11(FilePlus2Icon, { className: "size-4 text-muted-foreground" }), title: pathTitle("write", path), ...toHeaderProps(part) }),
|
|
1679
|
+
/* @__PURE__ */ jsx11(ToolHeader, { icon: /* @__PURE__ */ jsx11(FilePlus2Icon, { className: "size-4 text-muted-foreground" }), title: pathTitle("write", path, filesystem), ...toHeaderProps(part) }),
|
|
1675
1680
|
/* @__PURE__ */ jsx11(ToolContent, { children: /* @__PURE__ */ jsxs10(Artifact, { className: "rounded-none border-0 bg-transparent shadow-none", children: [
|
|
1676
1681
|
/* @__PURE__ */ jsxs10(ArtifactHeader, { className: "border-0 px-0 pt-0 pb-2", children: [
|
|
1677
1682
|
/* @__PURE__ */ jsxs10("div", { children: [
|
|
@@ -1728,10 +1733,11 @@ function renderEdit2(part) {
|
|
|
1728
1733
|
if (readiness) return readiness;
|
|
1729
1734
|
const input = asRecord2(part.input);
|
|
1730
1735
|
const path = typeof input.path === "string" ? input.path : "";
|
|
1736
|
+
const filesystem = typeof input.filesystem === "string" ? input.filesystem : void 0;
|
|
1731
1737
|
const oldString = typeof input.oldString === "string" ? input.oldString : "";
|
|
1732
1738
|
const newString = typeof input.newString === "string" ? input.newString : "";
|
|
1733
1739
|
return /* @__PURE__ */ jsxs10(Tool2, { children: [
|
|
1734
|
-
/* @__PURE__ */ jsx11(ToolHeader, { icon: /* @__PURE__ */ jsx11(FileDiffIcon, { className: "size-4 text-muted-foreground" }), title: pathTitle("edit", path), ...toHeaderProps(part) }),
|
|
1740
|
+
/* @__PURE__ */ jsx11(ToolHeader, { icon: /* @__PURE__ */ jsx11(FileDiffIcon, { className: "size-4 text-muted-foreground" }), title: pathTitle("edit", path, filesystem), ...toHeaderProps(part) }),
|
|
1735
1741
|
/* @__PURE__ */ jsxs10(ToolContent, { children: [
|
|
1736
1742
|
/* @__PURE__ */ jsxs10("section", { className: "space-y-2", children: [
|
|
1737
1743
|
/* @__PURE__ */ jsx11("h4", { className: "font-medium text-muted-foreground text-xs uppercase tracking-wide", children: "Diff" }),
|
|
@@ -2658,7 +2664,17 @@ function useChatModelSelection({
|
|
|
2658
2664
|
setModelState(next);
|
|
2659
2665
|
writePiComposerModelSelection(next, { storageScope, storage });
|
|
2660
2666
|
}, [storage, storageScope]);
|
|
2667
|
+
const discoveryKey = useMemo2(
|
|
2668
|
+
() => JSON.stringify({
|
|
2669
|
+
apiBaseUrl: apiBaseUrl ?? "",
|
|
2670
|
+
headers: Object.entries(requestHeaders ?? {}).sort(([a], [b]) => a.localeCompare(b)),
|
|
2671
|
+
storageScope: storageScope ?? ""
|
|
2672
|
+
}),
|
|
2673
|
+
[apiBaseUrl, requestHeaders, storageScope]
|
|
2674
|
+
);
|
|
2661
2675
|
const [availableModels, setAvailableModels] = useState7([]);
|
|
2676
|
+
const [loaded, setLoaded] = useState7(!enabled);
|
|
2677
|
+
const [loadedDiscoveryKey, setLoadedDiscoveryKey] = useState7(enabled ? null : discoveryKey);
|
|
2662
2678
|
useEffect5(() => {
|
|
2663
2679
|
if (loadedSettingsSourceRef.current.storage !== storage || loadedSettingsSourceRef.current.storageScope !== storageScope) return;
|
|
2664
2680
|
if (!userSelectedModel || !model) return;
|
|
@@ -2676,14 +2692,31 @@ function useChatModelSelection({
|
|
|
2676
2692
|
setModelState(defaultModel);
|
|
2677
2693
|
}, [defaultModel]);
|
|
2678
2694
|
useEffect5(() => {
|
|
2679
|
-
if (!enabled)
|
|
2695
|
+
if (!enabled) {
|
|
2696
|
+
setLoaded(true);
|
|
2697
|
+
setLoadedDiscoveryKey(discoveryKey);
|
|
2698
|
+
return;
|
|
2699
|
+
}
|
|
2680
2700
|
let aborted = false;
|
|
2701
|
+
setLoaded(false);
|
|
2681
2702
|
const nextFetch = fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
2682
2703
|
nextFetch(agentResourceUrl(apiBaseUrl, "/api/v1/agent/models"), {
|
|
2683
2704
|
headers: scopedHeaders2(requestHeaders, storageScope)
|
|
2684
2705
|
}).then((res) => res.ok ? res.json() : null).then((payload) => {
|
|
2685
|
-
if (aborted
|
|
2706
|
+
if (aborted) return;
|
|
2707
|
+
if (!payload?.models) {
|
|
2708
|
+
userSelectedModelRef.current = false;
|
|
2709
|
+
setUserSelectedModel(false);
|
|
2710
|
+
setAvailableModels([]);
|
|
2711
|
+
setModelState(null);
|
|
2712
|
+
writePiComposerModelSelection(null, { storageScope, storage });
|
|
2713
|
+
setLoadedDiscoveryKey(discoveryKey);
|
|
2714
|
+
setLoaded(true);
|
|
2715
|
+
return;
|
|
2716
|
+
}
|
|
2686
2717
|
setAvailableModels(payload.models);
|
|
2718
|
+
setLoadedDiscoveryKey(discoveryKey);
|
|
2719
|
+
setLoaded(true);
|
|
2687
2720
|
const available = payload.models.filter((m) => m.available);
|
|
2688
2721
|
setModelState((current) => {
|
|
2689
2722
|
const currentAvailable = current ? available.some((m) => m.provider === current.provider && m.id === current.id) : false;
|
|
@@ -2691,14 +2724,24 @@ function useChatModelSelection({
|
|
|
2691
2724
|
userSelectedModelRef.current = false;
|
|
2692
2725
|
setUserSelectedModel(false);
|
|
2693
2726
|
writePiComposerModelSelection(null, { storageScope, storage });
|
|
2694
|
-
|
|
2727
|
+
if (payload.defaultModel) return { provider: payload.defaultModel.provider, id: payload.defaultModel.id };
|
|
2728
|
+
const firstAvailable = available[0];
|
|
2729
|
+
return firstAvailable ? { provider: firstAvailable.provider, id: firstAvailable.id } : null;
|
|
2695
2730
|
});
|
|
2696
2731
|
}).catch(() => {
|
|
2732
|
+
if (aborted) return;
|
|
2733
|
+
userSelectedModelRef.current = false;
|
|
2734
|
+
setUserSelectedModel(false);
|
|
2735
|
+
setAvailableModels([]);
|
|
2736
|
+
setModelState(null);
|
|
2737
|
+
writePiComposerModelSelection(null, { storageScope, storage });
|
|
2738
|
+
setLoadedDiscoveryKey(discoveryKey);
|
|
2739
|
+
setLoaded(true);
|
|
2697
2740
|
});
|
|
2698
2741
|
return () => {
|
|
2699
2742
|
aborted = true;
|
|
2700
2743
|
};
|
|
2701
|
-
}, [apiBaseUrl, enabled, fetchImpl, requestHeaders, storage, storageScope]);
|
|
2744
|
+
}, [apiBaseUrl, discoveryKey, enabled, fetchImpl, requestHeaders, storage, storageScope]);
|
|
2702
2745
|
useEffect5(() => {
|
|
2703
2746
|
const onChange = (event) => {
|
|
2704
2747
|
const next = parseModelSelection(event.detail);
|
|
@@ -2707,7 +2750,10 @@ function useChatModelSelection({
|
|
|
2707
2750
|
globalThis.addEventListener?.("boring:model-change", onChange);
|
|
2708
2751
|
return () => globalThis.removeEventListener?.("boring:model-change", onChange);
|
|
2709
2752
|
}, [setModel]);
|
|
2710
|
-
|
|
2753
|
+
const currentDiscoveryLoaded = !enabled || loaded && loadedDiscoveryKey === discoveryKey;
|
|
2754
|
+
const currentAvailableModels = currentDiscoveryLoaded ? availableModels : [];
|
|
2755
|
+
const currentModel = currentDiscoveryLoaded ? model : null;
|
|
2756
|
+
return { availableModels: currentAvailableModels, loaded: currentDiscoveryLoaded, model: currentModel, setModel };
|
|
2711
2757
|
}
|
|
2712
2758
|
function agentResourceUrl(apiBaseUrl, path) {
|
|
2713
2759
|
const base = apiBaseUrl?.replace(/\/$/, "") ?? "";
|
|
@@ -2723,6 +2769,11 @@ function scopedHeaders2(headers, storageScope) {
|
|
|
2723
2769
|
|
|
2724
2770
|
// src/front/hooks/useServerCommands.ts
|
|
2725
2771
|
import { useEffect as useEffect6, useRef as useRef7, useState as useState8 } from "react";
|
|
2772
|
+
function serverCommandErrorMessage(body, fallback) {
|
|
2773
|
+
if (typeof body.error === "string") return body.error;
|
|
2774
|
+
if (body.error && typeof body.error === "object" && typeof body.error.message === "string") return body.error.message;
|
|
2775
|
+
return fallback;
|
|
2776
|
+
}
|
|
2726
2777
|
function toSlashCommand(command, getSessionId, apiBaseUrl, requestHeaders, fetchImpl) {
|
|
2727
2778
|
return {
|
|
2728
2779
|
name: command.name,
|
|
@@ -2743,7 +2794,7 @@ function toSlashCommand(command, getSessionId, apiBaseUrl, requestHeaders, fetch
|
|
|
2743
2794
|
const body = await res.json().catch(() => ({}));
|
|
2744
2795
|
if (typeof globalThis.dispatchEvent === "function") {
|
|
2745
2796
|
globalThis.dispatchEvent(new CustomEvent(WORKSPACE_COMMAND_NOTIFY_EVENT, {
|
|
2746
|
-
detail: { message: body
|
|
2797
|
+
detail: { message: serverCommandErrorMessage(body, `/${command.name} failed`), tone: "error", command: command.name }
|
|
2747
2798
|
}));
|
|
2748
2799
|
}
|
|
2749
2800
|
}
|
|
@@ -5663,7 +5714,7 @@ function sortByUpdatedDesc(a, b) {
|
|
|
5663
5714
|
return a.id.localeCompare(b.id);
|
|
5664
5715
|
}
|
|
5665
5716
|
|
|
5666
|
-
// ../../node_modules/.pnpm/@earendil-works+pi-tui@0.
|
|
5717
|
+
// ../../node_modules/.pnpm/@earendil-works+pi-tui@0.80.3/node_modules/@earendil-works/pi-tui/dist/fuzzy.js
|
|
5667
5718
|
function fuzzyMatch(query, text) {
|
|
5668
5719
|
const queryLower = query.toLowerCase();
|
|
5669
5720
|
const textLower = text.toLowerCase();
|
|
@@ -6082,7 +6133,7 @@ function ComposerBlockerNotice({
|
|
|
6082
6133
|
{
|
|
6083
6134
|
role: "status",
|
|
6084
6135
|
"aria-live": "polite",
|
|
6085
|
-
className: noticeSurfaceClass("info", "mx-auto mb-2 w-full max-w-3xl text-xs"),
|
|
6136
|
+
className: noticeSurfaceClass("info", "relative z-20 mx-auto mb-2 w-full max-w-3xl text-xs"),
|
|
6086
6137
|
children: [
|
|
6087
6138
|
/* @__PURE__ */ jsx16("span", { children: label }),
|
|
6088
6139
|
blocker?.actions?.map((action) => {
|
|
@@ -7046,7 +7097,8 @@ function PiTimelineMessage({ message, isLast, isStreaming, showThoughts, toolRen
|
|
|
7046
7097
|
const canOpen = Boolean(openArtifact && openPath);
|
|
7047
7098
|
const openAttachment = () => {
|
|
7048
7099
|
if (!openPath) return;
|
|
7049
|
-
openArtifact?.(openPath);
|
|
7100
|
+
if (file.filesystem) openArtifact?.(openPath, { filesystem: file.filesystem });
|
|
7101
|
+
else openArtifact?.(openPath);
|
|
7050
7102
|
};
|
|
7051
7103
|
const openAttachmentFromKeyboard = (event) => {
|
|
7052
7104
|
if (event.key !== "Enter" && event.key !== " ") return;
|
|
@@ -9149,7 +9201,7 @@ function PiChatComposerSurface({
|
|
|
9149
9201
|
useLayoutEffect2(() => {
|
|
9150
9202
|
resizeTextarea(textareaRef.current);
|
|
9151
9203
|
}, [draft, resizeTextarea, textareaRef]);
|
|
9152
|
-
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: [
|
|
9204
|
+
return /* @__PURE__ */ jsxs30("div", { className: cn("relative z-20", chrome ? "px-4 pb-4 pt-2 sm:px-6 sm:pb-5" : "px-3 pb-2 pt-1"), children: [
|
|
9153
9205
|
/* @__PURE__ */ jsx32(
|
|
9154
9206
|
"div",
|
|
9155
9207
|
{
|
|
@@ -9733,6 +9785,7 @@ function PiChatPanel({
|
|
|
9733
9785
|
const selectedPiSession = selectedChatState ? activePiSession : void 0;
|
|
9734
9786
|
const chatStatePending = Boolean(activeSessionId && chatState && chatState.sessionId !== activeSessionId);
|
|
9735
9787
|
const selectedSessionPending = Boolean(activeSessionId && !selectedChatState);
|
|
9788
|
+
const modelDiscoveryEnabled = serverResourcesEnabled && availableModels === void 0;
|
|
9736
9789
|
const modelDiscovery = useChatModelSelection({
|
|
9737
9790
|
apiBaseUrl,
|
|
9738
9791
|
defaultModel,
|
|
@@ -9740,13 +9793,19 @@ function PiChatPanel({
|
|
|
9740
9793
|
requestHeaders: normalizedRequestHeaders,
|
|
9741
9794
|
storage,
|
|
9742
9795
|
storageScope,
|
|
9743
|
-
enabled:
|
|
9796
|
+
enabled: modelDiscoveryEnabled
|
|
9744
9797
|
});
|
|
9745
9798
|
const selectedModel = model === void 0 ? modelDiscovery.model : model;
|
|
9746
9799
|
const modelOptions = useMemo13(
|
|
9747
9800
|
() => modelOptionsForSelection(availableModels ?? modelDiscovery.availableModels, selectedModel),
|
|
9748
9801
|
[availableModels, modelDiscovery.availableModels, selectedModel]
|
|
9749
9802
|
);
|
|
9803
|
+
const selectedModelAuthorizedByDiscovery = !modelDiscoveryEnabled || Boolean(selectedModel && modelDiscovery.availableModels.some(
|
|
9804
|
+
(modelOption) => modelOption.available && modelOption.provider === selectedModel.provider && modelOption.id === selectedModel.id
|
|
9805
|
+
));
|
|
9806
|
+
const serverModelSelectionPending = modelDiscoveryEnabled && !modelDiscovery.loaded;
|
|
9807
|
+
const serverModelSelectionUnavailable = modelDiscoveryEnabled && modelDiscovery.loaded && !selectedModelAuthorizedByDiscovery;
|
|
9808
|
+
const serverModelSelectionReady = !serverModelSelectionPending && !serverModelSelectionUnavailable;
|
|
9750
9809
|
const [storedThinkingLevel, setStoredThinkingLevel] = useState20(
|
|
9751
9810
|
() => thinkingControl ? readPiComposerSettings({ storageScope, storage }).thinkingLevel : DEFAULT_THINKING
|
|
9752
9811
|
);
|
|
@@ -10077,7 +10136,7 @@ function PiChatPanel({
|
|
|
10077
10136
|
insertSlashCommand(name);
|
|
10078
10137
|
}, [dismissSlash, insertSlashCommand, openModelPicker, openThinkingPicker, setComposerDraft]);
|
|
10079
10138
|
const policy = useMemo13(() => {
|
|
10080
|
-
if (!selectedPiSession || !activeChatSessionId) return void 0;
|
|
10139
|
+
if (!selectedPiSession || !activeChatSessionId || !serverModelSelectionReady) return void 0;
|
|
10081
10140
|
const policySession = {
|
|
10082
10141
|
getState: () => {
|
|
10083
10142
|
const state = selectedPiSession.getState();
|
|
@@ -10142,7 +10201,7 @@ function PiChatPanel({
|
|
|
10142
10201
|
onMentionedFilesConsumed?.();
|
|
10143
10202
|
}
|
|
10144
10203
|
});
|
|
10145
|
-
}, [activeChatSessionId, addLocalNotice, allowPromptDuringInitialHydration, clearMentionedFiles, composerBlocked, composerBlockerLabel, effectiveMentionedFiles, markLocalSubmitted, onBeforeSubmit, onCommandResult, onComposerWarning, onMentionedFilesConsumed, onPromptSubmitStarted, openModelPicker, openThinkingPicker, registry, reloadAgentPlugins, resetSession, runPluginUpdate, selectComposerModel, selectComposerThinking, selectedModel, selectedPiSession, selectedThinking, setComposerDraft, submitThinkingControl, suppressPreSubmitCancelledWarning]);
|
|
10204
|
+
}, [activeChatSessionId, addLocalNotice, allowPromptDuringInitialHydration, clearMentionedFiles, composerBlocked, composerBlockerLabel, effectiveMentionedFiles, markLocalSubmitted, onBeforeSubmit, onCommandResult, onComposerWarning, onMentionedFilesConsumed, onPromptSubmitStarted, openModelPicker, openThinkingPicker, registry, reloadAgentPlugins, resetSession, runPluginUpdate, selectComposerModel, selectComposerThinking, selectedModel, selectedPiSession, selectedThinking, serverModelSelectionReady, setComposerDraft, submitThinkingControl, suppressPreSubmitCancelledWarning]);
|
|
10146
10205
|
const surfaceRunRejected = useCallback18((error) => {
|
|
10147
10206
|
const errorCode = piChatErrorCode(error);
|
|
10148
10207
|
dropLocalNotice(RUN_REJECTED_NOTICE_ID);
|
|
@@ -10287,10 +10346,12 @@ function PiChatPanel({
|
|
|
10287
10346
|
const initialHydrationPromptAllowed = Boolean(
|
|
10288
10347
|
allowPromptDuringInitialHydration && selectedChatState && selectedChatState.status === "hydrating" && !selectedChatState.hydrated && selectedChatState.history.messageCount === 0 && selectedChatState.committedMessages.length === 0 && selectedChatState.queue.followUps.length === 0 && Object.keys(selectedChatState.optimisticOutbox).length === 0 && !selectedChatState.streamingMessage
|
|
10289
10348
|
);
|
|
10349
|
+
const noDiscoveredModelAvailable = modelDiscoveryEnabled && modelDiscovery.loaded && modelDiscovery.availableModels.every((modelOption) => !modelOption.available);
|
|
10350
|
+
const modelSelectionBlocked = serverModelSelectionPending || serverModelSelectionUnavailable || noDiscoveredModelAvailable;
|
|
10290
10351
|
const disabled = !policy || sessionsLoading || composerBlocked;
|
|
10291
10352
|
const isStreaming = isPiBusyStatus(status);
|
|
10292
10353
|
const submitStatus = initialHydrationPromptAllowed ? "ready" : toPromptSubmitStatus(status);
|
|
10293
|
-
const submitDisabled = !policy || sessionsLoading || composerBlocked && !isStreaming;
|
|
10354
|
+
const submitDisabled = !policy || sessionsLoading || modelSelectionBlocked || composerBlocked && !isStreaming;
|
|
10294
10355
|
const mergedToolRenderers = useMemo13(() => mergeShadcnToolRenderers(toolRenderers), [toolRenderers]);
|
|
10295
10356
|
const debugMessages = useMemo13(() => messages.map(toDebugUiMessage), [messages]);
|
|
10296
10357
|
const onTextareaChange = useCallback18((event) => {
|
|
@@ -10309,13 +10370,6 @@ function PiChatPanel({
|
|
|
10309
10370
|
window.dispatchEvent(new CustomEvent("boring:chat-session-status", {
|
|
10310
10371
|
detail: { sessionId: activeChatSessionId, working: isStreaming }
|
|
10311
10372
|
}));
|
|
10312
|
-
if (!isStreaming) return;
|
|
10313
|
-
const sessionId2 = activeChatSessionId;
|
|
10314
|
-
return () => {
|
|
10315
|
-
window.dispatchEvent(new CustomEvent("boring:chat-session-status", {
|
|
10316
|
-
detail: { sessionId: sessionId2, working: false }
|
|
10317
|
-
}));
|
|
10318
|
-
};
|
|
10319
10373
|
}, [activeChatSessionId, isStreaming]);
|
|
10320
10374
|
const onTextareaKeyDown = useCallback18((event) => {
|
|
10321
10375
|
if (event.key === "Escape" && isStreaming) {
|