@hachej/boring-agent 0.1.103 → 0.1.105
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{chunk-7QM22DU7.js → chunk-6DRHERVK.js} +7 -5
- package/dist/{chunk-TW7G33QH.js → chunk-F2OJI2LX.js} +64 -15
- package/dist/{chunk-6WKQ4FC4.js → chunk-LFN45QDZ.js} +259 -140
- package/dist/core/index.d.ts +5 -5
- package/dist/{createHarness-4Q6DQBRT.js → createHarness-GMBZZPTN.js} +1 -1
- package/dist/{errors-szpcDUFQ.d.ts → errors-DH7C01Pm.d.ts} +1 -1
- package/dist/{file-search-BXdSm-Yq.d.ts → file-search-qcD5zItr.d.ts} +3 -3
- package/dist/front/index.d.ts +12 -2
- package/dist/front/index.js +200 -135
- package/dist/front/styles.css +56 -15
- package/dist/{harness-erpL2SER.d.ts → harness-Dcd08yKr.d.ts} +1 -1
- package/dist/{lease-K-EZhdL-.d.ts → lease-DffrPrQn.d.ts} +1 -1
- package/dist/{piChatEvent-g1nIBh44.d.ts → piChatEvent-iNSXiFQq.d.ts} +5 -0
- package/dist/{piChatSessionService-DugeRHzb.d.ts → piChatSessionService-DQSQ_kWZ.d.ts} +1 -1
- package/dist/server/agent-host/testing/gatewayConformance.d.ts +5 -5
- package/dist/server/agent-host/testing/gatewayConformance.js +1 -1
- package/dist/server/index.d.ts +53 -42
- package/dist/server/index.js +5 -3
- package/dist/server/worker/index.js +3 -3
- package/dist/shared/index.d.ts +93 -19
- package/dist/shared/index.js +1 -1
- package/dist/{types-BnjMLAd5.d.ts → types-BTsdaAQ2.d.ts} +33 -14
- package/docs/ERROR_CODES.md +1 -1
- package/package.json +6 -6
package/dist/front/index.js
CHANGED
|
@@ -31,7 +31,7 @@ import {
|
|
|
31
31
|
WORKSPACE_COMMAND_NOTIFY_EVENT,
|
|
32
32
|
extractToolUiMetadata,
|
|
33
33
|
sanitizeToolUiMetadata
|
|
34
|
-
} from "../chunk-
|
|
34
|
+
} from "../chunk-6DRHERVK.js";
|
|
35
35
|
import "../chunk-YGRQ4Q5P.js";
|
|
36
36
|
import {
|
|
37
37
|
ErrorCode
|
|
@@ -85,7 +85,7 @@ function rawWorkspaceFileUrl(path, opts) {
|
|
|
85
85
|
}
|
|
86
86
|
|
|
87
87
|
// src/front/chat/PiChatPanel.tsx
|
|
88
|
-
import { lazy, Suspense, useCallback as useCallback18, useEffect as useEffect21, useMemo as useMemo16, useRef as
|
|
88
|
+
import { lazy, Suspense, useCallback as useCallback18, useEffect as useEffect21, useMemo as useMemo16, useRef as useRef17, useState as useState20 } from "react";
|
|
89
89
|
|
|
90
90
|
// src/front/chatPanelSettings.ts
|
|
91
91
|
var DEFAULT_THINKING = "medium";
|
|
@@ -280,6 +280,14 @@ function createCommandRegistry(initial) {
|
|
|
280
280
|
}
|
|
281
281
|
|
|
282
282
|
// src/front/slashCommands/builtins.ts
|
|
283
|
+
var MAX_RELOAD_MODEL_MESSAGE = 2e3;
|
|
284
|
+
function reloadResultForModel(message) {
|
|
285
|
+
const body = message.trim() || "No result reported.";
|
|
286
|
+
const bounded = body.length > MAX_RELOAD_MODEL_MESSAGE ? `${body.slice(0, MAX_RELOAD_MODEL_MESSAGE)}
|
|
287
|
+
\u2026 (truncated)` : body;
|
|
288
|
+
return `/reload result:
|
|
289
|
+
${bounded}`;
|
|
290
|
+
}
|
|
283
291
|
var builtinCommands = [
|
|
284
292
|
{
|
|
285
293
|
name: "reset",
|
|
@@ -301,9 +309,9 @@ var builtinCommands = [
|
|
|
301
309
|
name: "reload",
|
|
302
310
|
description: "Reload agent plugins",
|
|
303
311
|
clickBehavior: "execute",
|
|
304
|
-
handler(_, ctx) {
|
|
305
|
-
|
|
306
|
-
return
|
|
312
|
+
async handler(_, ctx) {
|
|
313
|
+
const message = ctx.pluginUpdate ? await ctx.pluginUpdate.run() : await ctx.reloadAgentPlugins();
|
|
314
|
+
return { message, modelMessage: reloadResultForModel(message) };
|
|
307
315
|
}
|
|
308
316
|
},
|
|
309
317
|
{
|
|
@@ -2126,7 +2134,7 @@ function useComposerPickers({
|
|
|
2126
2134
|
}
|
|
2127
2135
|
|
|
2128
2136
|
// src/front/hooks/useChatModelSelection.ts
|
|
2129
|
-
import { useCallback as useCallback6, useEffect as useEffect5, useMemo as useMemo2,
|
|
2137
|
+
import { useCallback as useCallback6, useEffect as useEffect5, useMemo as useMemo2, useState as useState7 } from "react";
|
|
2130
2138
|
|
|
2131
2139
|
// src/front/browserFiles.ts
|
|
2132
2140
|
var convertBlobUrlToDataUrl = async (url) => {
|
|
@@ -2365,7 +2373,7 @@ var PiComposerPolicyController = class {
|
|
|
2365
2373
|
if (command?.kind === "skill") {
|
|
2366
2374
|
return this.submitExpandedText(skillCommandText(parsed.name, parsed.args), source, false);
|
|
2367
2375
|
}
|
|
2368
|
-
if (command) return this.runLocalCommand(parsed.name, parsed.args);
|
|
2376
|
+
if (command) return this.runLocalCommand(parsed.name, parsed.args, source);
|
|
2369
2377
|
}
|
|
2370
2378
|
if (isPiChatBusy(this.options.session.getState().status) && files.length > 0) {
|
|
2371
2379
|
return this.fromQueueResult(await this.queueController.submit({ text, attachments: this.toAttachmentPayloads(files) }));
|
|
@@ -2408,7 +2416,7 @@ var PiComposerPolicyController = class {
|
|
|
2408
2416
|
...this.options.thinkingControl ? { thinkingLevel: this.options.thinkingLevel ?? DEFAULT_THINKING } : {}
|
|
2409
2417
|
}));
|
|
2410
2418
|
}
|
|
2411
|
-
async runLocalCommand(commandName, args) {
|
|
2419
|
+
async runLocalCommand(commandName, args, source) {
|
|
2412
2420
|
const command = this.options.registry.get(commandName);
|
|
2413
2421
|
if (isPiChatBusy(this.options.session.getState().status) && command?.allowWhileBusy?.(args) !== true) {
|
|
2414
2422
|
return this.block("busy-slash-command", "Slash commands are not queued while the agent is responding.");
|
|
@@ -2417,6 +2425,10 @@ var PiComposerPolicyController = class {
|
|
|
2417
2425
|
const message = typeof result === "string" ? result : result && typeof result === "object" ? result.message : void 0;
|
|
2418
2426
|
const preserveDraft = Boolean(result && typeof result === "object" && result.preserveDraft === true);
|
|
2419
2427
|
if (message) this.options.onCommandResult?.(message);
|
|
2428
|
+
const modelMessage = result && typeof result === "object" ? result.modelMessage?.trim() : void 0;
|
|
2429
|
+
if (modelMessage) {
|
|
2430
|
+
return await this.submitExpandedText(modelMessage, source, false);
|
|
2431
|
+
}
|
|
2420
2432
|
return { type: "command", command: commandName, ...message ? { result: message } : {}, preserveDraft };
|
|
2421
2433
|
}
|
|
2422
2434
|
async runBeforeSubmit(draft, files, source) {
|
|
@@ -2550,35 +2562,59 @@ function resolveStorage(storage) {
|
|
|
2550
2562
|
}
|
|
2551
2563
|
|
|
2552
2564
|
// src/front/hooks/useChatModelSelection.ts
|
|
2565
|
+
function sameModel(left, right) {
|
|
2566
|
+
return left?.provider === right?.provider && left?.id === right?.id;
|
|
2567
|
+
}
|
|
2568
|
+
function availableModel(models, model) {
|
|
2569
|
+
return Boolean(model && models.some((candidate) => candidate.available && candidate.provider === model.provider && candidate.id === model.id));
|
|
2570
|
+
}
|
|
2553
2571
|
function useChatModelSelection({
|
|
2554
2572
|
agentTypeId,
|
|
2555
2573
|
apiBaseUrl,
|
|
2556
2574
|
defaultModel,
|
|
2575
|
+
sessionId,
|
|
2576
|
+
sessionHydrated = sessionId === void 0,
|
|
2577
|
+
sessionIsNew = sessionId === void 0,
|
|
2578
|
+
sessionModel,
|
|
2557
2579
|
fetch: fetchImpl,
|
|
2558
2580
|
requestHeaders,
|
|
2559
2581
|
storage,
|
|
2560
2582
|
storageScope,
|
|
2561
2583
|
enabled = true
|
|
2562
2584
|
}) {
|
|
2563
|
-
const
|
|
2564
|
-
const [
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
);
|
|
2570
|
-
const userSelectedModelRef = useRef6(userSelectedModel);
|
|
2571
|
-
const loadedSettingsSourceRef = useRef6({ storage, storageScope });
|
|
2585
|
+
const initialSettings = useMemo2(() => readPiComposerSettings({ storageScope, storage }), []);
|
|
2586
|
+
const [selection, setSelection] = useState7(() => ({
|
|
2587
|
+
sessionId,
|
|
2588
|
+
storage,
|
|
2589
|
+
storageScope,
|
|
2590
|
+
localDefault: initialSettings.model ?? defaultModel ?? null
|
|
2591
|
+
}));
|
|
2572
2592
|
useEffect5(() => {
|
|
2573
|
-
|
|
2574
|
-
|
|
2593
|
+
const settings = readPiComposerSettings({ storageScope, storage });
|
|
2594
|
+
setSelection((current) => {
|
|
2595
|
+
const sameSession = current.sessionId === sessionId;
|
|
2596
|
+
const pendingOverride2 = sameSession && current.pendingOverride && sessionModel && !sameModel(current.pendingOverride, sessionModel) ? current.pendingOverride : sessionIsNew && sessionModel && settings.model && !sameModel(settings.model, sessionModel) ? settings.model : void 0;
|
|
2597
|
+
return {
|
|
2598
|
+
sessionId,
|
|
2599
|
+
storage,
|
|
2600
|
+
storageScope,
|
|
2601
|
+
localDefault: settings.model ?? defaultModel ?? null,
|
|
2602
|
+
...pendingOverride2 ? { pendingOverride: pendingOverride2 } : {}
|
|
2603
|
+
};
|
|
2604
|
+
});
|
|
2605
|
+
}, [defaultModel, sessionId, sessionIsNew, sessionModel?.id, sessionModel?.provider, storage, storageScope]);
|
|
2575
2606
|
const setModel = useCallback6((next) => {
|
|
2576
2607
|
const normalized = next === null ? null : parseModelSelection(next);
|
|
2577
|
-
|
|
2578
|
-
|
|
2579
|
-
|
|
2608
|
+
setSelection((current) => {
|
|
2609
|
+
if (sessionModel) {
|
|
2610
|
+
const pendingOverride2 = normalized && !sameModel(normalized, sessionModel) ? normalized : void 0;
|
|
2611
|
+
return { ...current, sessionId, ...pendingOverride2 ? { pendingOverride: pendingOverride2 } : { pendingOverride: void 0 } };
|
|
2612
|
+
}
|
|
2613
|
+
if (sessionId && !sessionIsNew) return current;
|
|
2614
|
+
return { ...current, sessionId, localDefault: normalized, pendingOverride: void 0 };
|
|
2615
|
+
});
|
|
2580
2616
|
writePiComposerModelSelection(normalized, { storageScope, storage });
|
|
2581
|
-
}, [storage, storageScope]);
|
|
2617
|
+
}, [sessionId, sessionIsNew, sessionModel, storage, storageScope]);
|
|
2582
2618
|
const discoveryKey = useMemo2(
|
|
2583
2619
|
() => JSON.stringify({
|
|
2584
2620
|
apiBaseUrl: apiBaseUrl ?? "",
|
|
@@ -2591,22 +2627,6 @@ function useChatModelSelection({
|
|
|
2591
2627
|
const [availableModels, setAvailableModels] = useState7([]);
|
|
2592
2628
|
const [loaded, setLoaded] = useState7(!enabled);
|
|
2593
2629
|
const [loadedDiscoveryKey, setLoadedDiscoveryKey] = useState7(enabled ? null : discoveryKey);
|
|
2594
|
-
useEffect5(() => {
|
|
2595
|
-
if (loadedSettingsSourceRef.current.storage !== storage || loadedSettingsSourceRef.current.storageScope !== storageScope) return;
|
|
2596
|
-
if (!userSelectedModel || !model) return;
|
|
2597
|
-
writePiComposerModelSelection(model, { storageScope, storage });
|
|
2598
|
-
}, [model, storage, storageScope, userSelectedModel]);
|
|
2599
|
-
useEffect5(() => {
|
|
2600
|
-
const settings = readPiComposerSettings({ storageScope, storage });
|
|
2601
|
-
loadedSettingsSourceRef.current = { storage, storageScope };
|
|
2602
|
-
userSelectedModelRef.current = settings.userSelectedModel;
|
|
2603
|
-
setUserSelectedModel(settings.userSelectedModel);
|
|
2604
|
-
setModelState(settings.model ?? defaultModel ?? null);
|
|
2605
|
-
}, [storage, storageScope]);
|
|
2606
|
-
useEffect5(() => {
|
|
2607
|
-
if (userSelectedModelRef.current || !defaultModel) return;
|
|
2608
|
-
setModelState(defaultModel);
|
|
2609
|
-
}, [defaultModel]);
|
|
2610
2630
|
useEffect5(() => {
|
|
2611
2631
|
if (!enabled) {
|
|
2612
2632
|
setLoaded(true);
|
|
@@ -2618,46 +2638,44 @@ function useChatModelSelection({
|
|
|
2618
2638
|
const nextFetch = fetchImpl ?? globalThis.fetch.bind(globalThis);
|
|
2619
2639
|
nextFetch(agentResourceUrl(apiBaseUrl, `/api/v1/agents/${encodeURIComponent(agentTypeId)}/models`), {
|
|
2620
2640
|
headers: withStorageScope(requestHeaders, storageScope)
|
|
2621
|
-
}).then((
|
|
2641
|
+
}).then((response) => response.ok ? response.json() : null).then((payload) => {
|
|
2622
2642
|
if (aborted) return;
|
|
2623
|
-
|
|
2624
|
-
|
|
2625
|
-
setUserSelectedModel(false);
|
|
2643
|
+
const models = payload?.models;
|
|
2644
|
+
if (!models) {
|
|
2626
2645
|
setAvailableModels([]);
|
|
2627
|
-
|
|
2628
|
-
writePiComposerModelSelection(null, { storageScope, storage });
|
|
2646
|
+
setSelection((current) => ({ ...current, pendingOverride: void 0, localDefault: sessionModel ?? null }));
|
|
2647
|
+
if (!sessionModel) writePiComposerModelSelection(null, { storageScope, storage });
|
|
2629
2648
|
setLoadedDiscoveryKey(discoveryKey);
|
|
2630
2649
|
setLoaded(true);
|
|
2631
2650
|
return;
|
|
2632
2651
|
}
|
|
2633
|
-
setAvailableModels(
|
|
2652
|
+
setAvailableModels(models);
|
|
2653
|
+
setSelection((current) => {
|
|
2654
|
+
const selected = current.pendingOverride ?? sessionModel ?? current.localDefault;
|
|
2655
|
+
if (availableModel(models, selected)) return current;
|
|
2656
|
+
if (sessionModel) return { ...current, pendingOverride: void 0 };
|
|
2657
|
+
if (sessionId && !sessionIsNew) return { ...current, pendingOverride: void 0, localDefault: null };
|
|
2658
|
+
const firstAvailable = models.find((candidate) => candidate.available);
|
|
2659
|
+
return {
|
|
2660
|
+
...current,
|
|
2661
|
+
pendingOverride: void 0,
|
|
2662
|
+
localDefault: payload.defaultModel ?? (firstAvailable ? { provider: firstAvailable.provider, id: firstAvailable.id } : null)
|
|
2663
|
+
};
|
|
2664
|
+
});
|
|
2634
2665
|
setLoadedDiscoveryKey(discoveryKey);
|
|
2635
2666
|
setLoaded(true);
|
|
2636
|
-
const available = payload.models.filter((m) => m.available);
|
|
2637
|
-
setModelState((current) => {
|
|
2638
|
-
const currentAvailable = current ? available.some((m) => m.provider === current.provider && m.id === current.id) : false;
|
|
2639
|
-
if (currentAvailable) return current;
|
|
2640
|
-
userSelectedModelRef.current = false;
|
|
2641
|
-
setUserSelectedModel(false);
|
|
2642
|
-
writePiComposerModelSelection(null, { storageScope, storage });
|
|
2643
|
-
if (payload.defaultModel) return { provider: payload.defaultModel.provider, id: payload.defaultModel.id };
|
|
2644
|
-
const firstAvailable = available[0];
|
|
2645
|
-
return firstAvailable ? { provider: firstAvailable.provider, id: firstAvailable.id } : null;
|
|
2646
|
-
});
|
|
2647
2667
|
}).catch(() => {
|
|
2648
2668
|
if (aborted) return;
|
|
2649
|
-
userSelectedModelRef.current = false;
|
|
2650
|
-
setUserSelectedModel(false);
|
|
2651
2669
|
setAvailableModels([]);
|
|
2652
|
-
|
|
2653
|
-
writePiComposerModelSelection(null, { storageScope, storage });
|
|
2670
|
+
setSelection((current) => ({ ...current, pendingOverride: void 0, localDefault: sessionModel ?? null }));
|
|
2671
|
+
if (!sessionModel) writePiComposerModelSelection(null, { storageScope, storage });
|
|
2654
2672
|
setLoadedDiscoveryKey(discoveryKey);
|
|
2655
2673
|
setLoaded(true);
|
|
2656
2674
|
});
|
|
2657
2675
|
return () => {
|
|
2658
2676
|
aborted = true;
|
|
2659
2677
|
};
|
|
2660
|
-
}, [agentTypeId, apiBaseUrl, discoveryKey, enabled, fetchImpl, requestHeaders, storage, storageScope]);
|
|
2678
|
+
}, [agentTypeId, apiBaseUrl, discoveryKey, enabled, fetchImpl, requestHeaders, sessionId, sessionIsNew, sessionModel, storage, storageScope]);
|
|
2661
2679
|
useEffect5(() => {
|
|
2662
2680
|
const onChange = (event) => {
|
|
2663
2681
|
const next = parseModelSelection(event.detail);
|
|
@@ -2667,13 +2685,23 @@ function useChatModelSelection({
|
|
|
2667
2685
|
return () => globalThis.removeEventListener?.("boring:model-change", onChange);
|
|
2668
2686
|
}, [setModel]);
|
|
2669
2687
|
const currentDiscoveryLoaded = !enabled || loaded && loadedDiscoveryKey === discoveryKey;
|
|
2670
|
-
const
|
|
2671
|
-
const
|
|
2672
|
-
|
|
2688
|
+
const selectionBelongsToSession = selection.sessionId === sessionId && selection.storage === storage && selection.storageScope === storageScope;
|
|
2689
|
+
const pendingOverride = selectionBelongsToSession ? selection.pendingOverride : void 0;
|
|
2690
|
+
const isOverride = Boolean(pendingOverride && sessionModel && !sameModel(pendingOverride, sessionModel));
|
|
2691
|
+
const sessionAuthorityReady = !sessionId || sessionHydrated && (sessionModel !== void 0 || sessionIsNew);
|
|
2692
|
+
const model = currentDiscoveryLoaded && sessionAuthorityReady ? pendingOverride ?? sessionModel ?? selection.localDefault : null;
|
|
2693
|
+
return {
|
|
2694
|
+
availableModels: currentDiscoveryLoaded ? availableModels : [],
|
|
2695
|
+
loaded: currentDiscoveryLoaded,
|
|
2696
|
+
model,
|
|
2697
|
+
sessionModel,
|
|
2698
|
+
isOverride,
|
|
2699
|
+
setModel
|
|
2700
|
+
};
|
|
2673
2701
|
}
|
|
2674
2702
|
|
|
2675
2703
|
// src/front/hooks/useServerCommands.ts
|
|
2676
|
-
import { useEffect as useEffect6, useRef as
|
|
2704
|
+
import { useEffect as useEffect6, useRef as useRef6, useState as useState8 } from "react";
|
|
2677
2705
|
function serverCommandErrorMessage(body, fallback) {
|
|
2678
2706
|
if (typeof body.error === "string") return body.error;
|
|
2679
2707
|
if (body.error && typeof body.error === "object" && typeof body.error.message === "string") return body.error.message;
|
|
@@ -2725,10 +2753,10 @@ function useServerCommands({
|
|
|
2725
2753
|
refreshKey = 0
|
|
2726
2754
|
}) {
|
|
2727
2755
|
const [stamp, setStamp] = useState8(0);
|
|
2728
|
-
const registrationsRef =
|
|
2756
|
+
const registrationsRef = useRef6({ registry, identity: void 0, names: /* @__PURE__ */ new Set() });
|
|
2729
2757
|
const canonicalSessionId = sessionId.trim() || void 0;
|
|
2730
2758
|
const identityKey = canonicalSessionId ? `${agentTypeId}\0${canonicalSessionId}` : void 0;
|
|
2731
|
-
const identityKeyRef =
|
|
2759
|
+
const identityKeyRef = useRef6(identityKey);
|
|
2732
2760
|
identityKeyRef.current = identityKey;
|
|
2733
2761
|
useEffect6(() => () => {
|
|
2734
2762
|
const registrations = registrationsRef.current;
|
|
@@ -3760,6 +3788,8 @@ function piChatReducer(state, action) {
|
|
|
3760
3788
|
return hydrateFromSnapshot(state, action.snapshot, { allowSeqRewind: action.allowSeqRewind });
|
|
3761
3789
|
case "cursor-sync":
|
|
3762
3790
|
return syncCursor(state, action.cursor);
|
|
3791
|
+
case "model-confirmed":
|
|
3792
|
+
return { ...state, currentModel: action.model };
|
|
3763
3793
|
case "event":
|
|
3764
3794
|
return applySequencedEvent(state, action.event);
|
|
3765
3795
|
case "optimistic-user-message":
|
|
@@ -3856,6 +3886,7 @@ function hydrateFromSnapshot(state, snapshot, options = {}) {
|
|
|
3856
3886
|
...state,
|
|
3857
3887
|
sessionId: snapshot.sessionId,
|
|
3858
3888
|
status: snapshot.status,
|
|
3889
|
+
currentModel: snapshot.currentModel,
|
|
3859
3890
|
turnId: snapshot.activeTurnId,
|
|
3860
3891
|
lastSeq: snapshot.seq,
|
|
3861
3892
|
committedMessages,
|
|
@@ -3906,6 +3937,8 @@ function applySequencedEvent(state, event) {
|
|
|
3906
3937
|
}
|
|
3907
3938
|
function reduceEvent(state, event) {
|
|
3908
3939
|
switch (event.type) {
|
|
3940
|
+
case "model-changed":
|
|
3941
|
+
return { ...state, currentModel: event.currentModel };
|
|
3909
3942
|
case "agent-start":
|
|
3910
3943
|
return { ...state, status: "streaming", turnId: event.turnId, error: void 0, streamingPreservedTextPartKeys: void 0 };
|
|
3911
3944
|
case "agent-end":
|
|
@@ -4638,6 +4671,9 @@ var RemotePiSession = class {
|
|
|
4638
4671
|
else if (!this.suspended) this.ensureReconnectScheduled();
|
|
4639
4672
|
try {
|
|
4640
4673
|
const receipt = await this.postCommand("/prompt", payload, PromptReceiptSchema);
|
|
4674
|
+
if (!this.disposed && payload.model) {
|
|
4675
|
+
this.store.dispatch({ type: "model-confirmed", model: payload.model }, { flush: true });
|
|
4676
|
+
}
|
|
4641
4677
|
return receipt;
|
|
4642
4678
|
} catch (error) {
|
|
4643
4679
|
this.rollbackOptimisticMessage(payload.clientNonce);
|
|
@@ -5212,7 +5248,7 @@ function resolveBootStorage(storage) {
|
|
|
5212
5248
|
}
|
|
5213
5249
|
|
|
5214
5250
|
// src/front/chat/session/usePiSessions.ts
|
|
5215
|
-
import { useCallback as useCallback7, useEffect as useEffect8, useLayoutEffect, useMemo as useMemo4, useRef as
|
|
5251
|
+
import { useCallback as useCallback7, useEffect as useEffect8, useLayoutEffect, useMemo as useMemo4, useRef as useRef7, useState as useState10 } from "react";
|
|
5216
5252
|
var SESSION_PAGE_SIZE = 50;
|
|
5217
5253
|
var DEFAULT_MAX_RETRIES = 60;
|
|
5218
5254
|
var DEFAULT_RETRY_BASE_MS = 250;
|
|
@@ -5275,22 +5311,22 @@ function usePiSessions(options) {
|
|
|
5275
5311
|
const [loadingMore, setLoadingMore] = useState10(false);
|
|
5276
5312
|
const [hasMore, setHasMore] = useState10(false);
|
|
5277
5313
|
const [error, setError] = useState10(void 0);
|
|
5278
|
-
const mountedRef =
|
|
5279
|
-
const refreshVersionRef =
|
|
5280
|
-
const retryTimerRef =
|
|
5281
|
-
const sessionsRef =
|
|
5282
|
-
const activeSessionIdRef =
|
|
5283
|
-
const hasMoreRef =
|
|
5284
|
-
const canonicalLoadedCountRef =
|
|
5285
|
-
const nextCursorRef =
|
|
5286
|
-
const loadMoreRequestSeqRef =
|
|
5287
|
-
const loadMoreInFlightRef =
|
|
5288
|
-
const pendingCreatedRef =
|
|
5289
|
-
const pendingDeletedRef =
|
|
5290
|
-
const pendingCreatedScopeRef =
|
|
5291
|
-
const dataStorageScopeRef =
|
|
5292
|
-
const loadedDataSourceRef =
|
|
5293
|
-
const committedRequestScopeRef =
|
|
5314
|
+
const mountedRef = useRef7(false);
|
|
5315
|
+
const refreshVersionRef = useRef7(0);
|
|
5316
|
+
const retryTimerRef = useRef7(void 0);
|
|
5317
|
+
const sessionsRef = useRef7([]);
|
|
5318
|
+
const activeSessionIdRef = useRef7(activeSessionId);
|
|
5319
|
+
const hasMoreRef = useRef7(hasMore);
|
|
5320
|
+
const canonicalLoadedCountRef = useRef7(0);
|
|
5321
|
+
const nextCursorRef = useRef7(void 0);
|
|
5322
|
+
const loadMoreRequestSeqRef = useRef7(0);
|
|
5323
|
+
const loadMoreInFlightRef = useRef7(false);
|
|
5324
|
+
const pendingCreatedRef = useRef7(/* @__PURE__ */ new Map());
|
|
5325
|
+
const pendingDeletedRef = useRef7(/* @__PURE__ */ new Set());
|
|
5326
|
+
const pendingCreatedScopeRef = useRef7(requestScopeKey);
|
|
5327
|
+
const dataStorageScopeRef = useRef7(storageScope);
|
|
5328
|
+
const loadedDataSourceRef = useRef7(dataSourceKey);
|
|
5329
|
+
const committedRequestScopeRef = useRef7(requestScopeKey);
|
|
5294
5330
|
useIsomorphicLayoutEffect(() => {
|
|
5295
5331
|
committedRequestScopeRef.current = requestScopeKey;
|
|
5296
5332
|
}, [requestScopeKey]);
|
|
@@ -5298,7 +5334,7 @@ function usePiSessions(options) {
|
|
|
5298
5334
|
(scope) => mountedRef.current && committedRequestScopeRef.current === scope,
|
|
5299
5335
|
[]
|
|
5300
5336
|
);
|
|
5301
|
-
const remoteSessionOptionsRef =
|
|
5337
|
+
const remoteSessionOptionsRef = useRef7(options.remoteSessionOptions);
|
|
5302
5338
|
remoteSessionOptionsRef.current = options.remoteSessionOptions;
|
|
5303
5339
|
const remoteSessionOptionsKey = useMemo4(
|
|
5304
5340
|
() => remoteSessionOptionsIdentity(options.remoteSessionOptions),
|
|
@@ -6149,7 +6185,7 @@ function searchPiSessions(sessions, query, options = {}) {
|
|
|
6149
6185
|
|
|
6150
6186
|
// src/front/chat/components/PiConversationSurface.tsx
|
|
6151
6187
|
import { Skeleton } from "@hachej/boring-ui-kit";
|
|
6152
|
-
import { useCallback as useCallback14, useEffect as useEffect14, useLayoutEffect as useLayoutEffect2, useRef as
|
|
6188
|
+
import { useCallback as useCallback14, useEffect as useEffect14, useLayoutEffect as useLayoutEffect2, useRef as useRef10, useState as useState15 } from "react";
|
|
6153
6189
|
import { useStickToBottomContext as useStickToBottomContext2 } from "use-stick-to-bottom";
|
|
6154
6190
|
|
|
6155
6191
|
// src/front/primitives/conversation.tsx
|
|
@@ -6497,7 +6533,7 @@ function QueuedComposerNotice({ followUps, onEdit }) {
|
|
|
6497
6533
|
}
|
|
6498
6534
|
|
|
6499
6535
|
// src/front/chat/components/PiTimelineMessage.tsx
|
|
6500
|
-
import { useCallback as useCallback13, useEffect as useEffect13, useMemo as useMemo12, useRef as
|
|
6536
|
+
import { useCallback as useCallback13, useEffect as useEffect13, useMemo as useMemo12, useRef as useRef9, useState as useState14 } from "react";
|
|
6501
6537
|
import { CheckIcon as CheckIcon2, CopyIcon as CopyIcon3 } from "lucide-react";
|
|
6502
6538
|
import { Button as Button10 } from "@hachej/boring-ui-kit";
|
|
6503
6539
|
|
|
@@ -6921,7 +6957,7 @@ import {
|
|
|
6921
6957
|
useContext as useContext5,
|
|
6922
6958
|
useEffect as useEffect11,
|
|
6923
6959
|
useMemo as useMemo9,
|
|
6924
|
-
useRef as
|
|
6960
|
+
useRef as useRef8,
|
|
6925
6961
|
useState as useState12
|
|
6926
6962
|
} from "react";
|
|
6927
6963
|
import { Streamdown as Streamdown2 } from "streamdown";
|
|
@@ -7013,9 +7049,9 @@ var Reasoning = memo5(
|
|
|
7013
7049
|
defaultProp: void 0,
|
|
7014
7050
|
prop: durationProp
|
|
7015
7051
|
});
|
|
7016
|
-
const hasEverStreamedRef =
|
|
7052
|
+
const hasEverStreamedRef = useRef8(isStreaming);
|
|
7017
7053
|
const [hasAutoClosed, setHasAutoClosed] = useState12(false);
|
|
7018
|
-
const startTimeRef =
|
|
7054
|
+
const startTimeRef = useRef8(null);
|
|
7019
7055
|
useEffect11(() => {
|
|
7020
7056
|
if (isStreaming) {
|
|
7021
7057
|
hasEverStreamedRef.current = true;
|
|
@@ -7606,7 +7642,7 @@ function DefaultPiTimelineMessage({ message, isLast, isStreaming, showThoughts,
|
|
|
7606
7642
|
...effectiveMentionCatalog.skills.map((skill) => `skill:${skill.name}:${skill.commandName}`),
|
|
7607
7643
|
effectiveMentionCatalog.files ? "files:enabled" : "files:disabled"
|
|
7608
7644
|
].join("|");
|
|
7609
|
-
const mentionActivateRef =
|
|
7645
|
+
const mentionActivateRef = useRef9(onMentionActivate);
|
|
7610
7646
|
mentionActivateRef.current = onMentionActivate;
|
|
7611
7647
|
const activateCurrentMention = useCallback13((mention) => {
|
|
7612
7648
|
if (mention.kind === "file") {
|
|
@@ -8078,8 +8114,8 @@ function ConversationHistoryLoadingState() {
|
|
|
8078
8114
|
}
|
|
8079
8115
|
function TranscriptHistoryLoader({ olderCount, onLoadOlder }) {
|
|
8080
8116
|
const { scrollRef } = useStickToBottomContext2();
|
|
8081
|
-
const pendingAnchor =
|
|
8082
|
-
const armed =
|
|
8117
|
+
const pendingAnchor = useRef10(null);
|
|
8118
|
+
const armed = useRef10(true);
|
|
8083
8119
|
useEffect14(() => {
|
|
8084
8120
|
const el = scrollRef.current;
|
|
8085
8121
|
if (!el) return;
|
|
@@ -8144,7 +8180,7 @@ import { useCallback as useCallback16, useLayoutEffect as useLayoutEffect3 } fro
|
|
|
8144
8180
|
import { motion as motion2, useReducedMotion } from "motion/react";
|
|
8145
8181
|
|
|
8146
8182
|
// src/front/composer/PluginUpdateStatus.tsx
|
|
8147
|
-
import { useEffect as useEffect15, useRef as
|
|
8183
|
+
import { useEffect as useEffect15, useRef as useRef11 } from "react";
|
|
8148
8184
|
|
|
8149
8185
|
// src/front/composer/ComposerStatusBanner.tsx
|
|
8150
8186
|
import { jsx as jsx25, jsxs as jsxs21 } from "react/jsx-runtime";
|
|
@@ -8267,7 +8303,7 @@ function PluginUpdateStatus({
|
|
|
8267
8303
|
successAutoDismissMs = 1400,
|
|
8268
8304
|
maxWidthClassName = "max-w-3xl"
|
|
8269
8305
|
}) {
|
|
8270
|
-
const onDismissRef =
|
|
8306
|
+
const onDismissRef = useRef11(onDismiss);
|
|
8271
8307
|
useEffect15(() => {
|
|
8272
8308
|
onDismissRef.current = onDismiss;
|
|
8273
8309
|
}, [onDismiss]);
|
|
@@ -8383,7 +8419,7 @@ function PluginUpdateStatus({
|
|
|
8383
8419
|
}
|
|
8384
8420
|
|
|
8385
8421
|
// src/front/composer/CommandRunStatus.tsx
|
|
8386
|
-
import { useEffect as useEffect16, useRef as
|
|
8422
|
+
import { useEffect as useEffect16, useRef as useRef12 } from "react";
|
|
8387
8423
|
import { Fragment as Fragment10, jsx as jsx27, jsxs as jsxs23 } from "react/jsx-runtime";
|
|
8388
8424
|
function CommandRunStatus({
|
|
8389
8425
|
state,
|
|
@@ -8391,7 +8427,7 @@ function CommandRunStatus({
|
|
|
8391
8427
|
successAutoDismissMs = 1400,
|
|
8392
8428
|
maxWidthClassName = "max-w-3xl"
|
|
8393
8429
|
}) {
|
|
8394
|
-
const onDismissRef =
|
|
8430
|
+
const onDismissRef = useRef12(onDismiss);
|
|
8395
8431
|
useEffect16(() => {
|
|
8396
8432
|
onDismissRef.current = onDismiss;
|
|
8397
8433
|
}, [onDismiss]);
|
|
@@ -8463,7 +8499,7 @@ function CommandRunStatus({
|
|
|
8463
8499
|
}
|
|
8464
8500
|
|
|
8465
8501
|
// src/front/chatPanelComposerControls.tsx
|
|
8466
|
-
import { forwardRef, useEffect as useEffect17, useRef as
|
|
8502
|
+
import { forwardRef, useEffect as useEffect17, useRef as useRef13, useState as useState16 } from "react";
|
|
8467
8503
|
import { CheckIcon as CheckIcon3, ChevronDownIcon as ChevronDownIcon5 } from "lucide-react";
|
|
8468
8504
|
import {
|
|
8469
8505
|
Command,
|
|
@@ -8611,6 +8647,8 @@ function groupModelOptions(options) {
|
|
|
8611
8647
|
var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
|
|
8612
8648
|
value,
|
|
8613
8649
|
options,
|
|
8650
|
+
sessionModel,
|
|
8651
|
+
isOverride = false,
|
|
8614
8652
|
disabled,
|
|
8615
8653
|
trigger = "button",
|
|
8616
8654
|
open = false,
|
|
@@ -8620,7 +8658,10 @@ var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
|
|
|
8620
8658
|
...props
|
|
8621
8659
|
}, ref) {
|
|
8622
8660
|
const triggerLabel = modelTriggerLabel(value, options, emptyLabel);
|
|
8661
|
+
const sessionTriggerLabel = sessionModel ? modelTriggerLabel(sessionModel, options) : void 0;
|
|
8623
8662
|
const triggerDisplay = value ? `${triggerLabel} (${displayProviderLabel(value.provider)})` : triggerLabel;
|
|
8663
|
+
const sessionDisplay = sessionModel && sessionTriggerLabel ? `${sessionTriggerLabel} (${displayProviderLabel(sessionModel.provider)})` : triggerDisplay;
|
|
8664
|
+
const accessibleDisplay = isOverride && value ? `Current model: ${sessionDisplay}. Next-message override: ${triggerDisplay}` : `Current model: ${sessionDisplay}`;
|
|
8624
8665
|
return /* @__PURE__ */ jsx28(
|
|
8625
8666
|
"button",
|
|
8626
8667
|
{
|
|
@@ -8628,9 +8669,10 @@ var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
|
|
|
8628
8669
|
type: "button",
|
|
8629
8670
|
"data-boring-agent-part": "model-select",
|
|
8630
8671
|
"data-boring-state": disabled ? "disabled" : void 0,
|
|
8672
|
+
"data-boring-model-override": isOverride ? "true" : void 0,
|
|
8631
8673
|
disabled,
|
|
8632
|
-
"aria-label": trigger === "slash" ? `Open model picker.
|
|
8633
|
-
title: trigger === "slash" ?
|
|
8674
|
+
"aria-label": trigger === "slash" ? `Open model picker. ${accessibleDisplay}` : "Model",
|
|
8675
|
+
title: trigger === "slash" ? accessibleDisplay : void 0,
|
|
8634
8676
|
onClick,
|
|
8635
8677
|
className: cn(
|
|
8636
8678
|
trigger === "slash" ? "h-8 max-w-[min(68vw,420px)] cursor-pointer overflow-hidden text-ellipsis whitespace-nowrap rounded-[var(--radius-md)] px-2 text-xs transition-colors hover:bg-muted/60 hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-popover disabled:pointer-events-none disabled:opacity-50 motion-reduce:transition-none" : selectorTriggerClass,
|
|
@@ -8641,8 +8683,17 @@ var ModelSelectTrigger = forwardRef(function ModelSelectTrigger2({
|
|
|
8641
8683
|
...props,
|
|
8642
8684
|
children: trigger === "slash" ? /* @__PURE__ */ jsxs24(Fragment11, { children: [
|
|
8643
8685
|
/* @__PURE__ */ jsx28("span", { className: "text-muted-foreground", children: "Model \xB7 " }),
|
|
8644
|
-
/* @__PURE__ */ jsx28("span", { className: "min-w-0 truncate text-foreground", children: triggerLabel }),
|
|
8645
|
-
|
|
8686
|
+
/* @__PURE__ */ jsx28("span", { className: "min-w-0 truncate text-foreground", children: sessionTriggerLabel ?? triggerLabel }),
|
|
8687
|
+
sessionModel ? /* @__PURE__ */ jsxs24("span", { className: "shrink-0 text-muted-foreground", children: [
|
|
8688
|
+
" \xB7 ",
|
|
8689
|
+
displayProviderLabel(sessionModel.provider)
|
|
8690
|
+
] }) : value ? /* @__PURE__ */ jsxs24("span", { className: "shrink-0 text-muted-foreground", children: [
|
|
8691
|
+
" \xB7 ",
|
|
8692
|
+
displayProviderLabel(value.provider)
|
|
8693
|
+
] }) : null,
|
|
8694
|
+
isOverride && value ? /* @__PURE__ */ jsxs24("span", { className: "shrink-0 text-amber-600 dark:text-amber-400", children: [
|
|
8695
|
+
" \xB7 Next override: ",
|
|
8696
|
+
triggerLabel,
|
|
8646
8697
|
" \xB7 ",
|
|
8647
8698
|
displayProviderLabel(value.provider)
|
|
8648
8699
|
] }) : null
|
|
@@ -8669,8 +8720,8 @@ function ModelPickerMenu({
|
|
|
8669
8720
|
const keyboardOptions = hideDefaultOption ? groupedOptions : [null, ...groupedOptions];
|
|
8670
8721
|
const selectedIndex = currentKey ? Math.max(0, keyboardOptions.findIndex((option) => option && encodeModelKey(option) === currentKey)) : 0;
|
|
8671
8722
|
const [activeIndex, setActiveIndex] = useState16(selectedIndex);
|
|
8672
|
-
const activeIndexRef =
|
|
8673
|
-
const menuRef =
|
|
8723
|
+
const activeIndexRef = useRef13(selectedIndex);
|
|
8724
|
+
const menuRef = useRef13(null);
|
|
8674
8725
|
useDismissOnOutsidePointer(menuRef, onClose);
|
|
8675
8726
|
const setKeyboardActiveIndex = (next) => {
|
|
8676
8727
|
const resolved = typeof next === "function" ? next(activeIndexRef.current) : next;
|
|
@@ -8797,7 +8848,7 @@ function ModelSelect({
|
|
|
8797
8848
|
hideDefaultOption = false
|
|
8798
8849
|
}) {
|
|
8799
8850
|
const [open, setOpen] = useState16(false);
|
|
8800
|
-
const previousOpenSignalRef =
|
|
8851
|
+
const previousOpenSignalRef = useRef13(openSignal);
|
|
8801
8852
|
useEffect17(() => {
|
|
8802
8853
|
if (disabled) setOpen(false);
|
|
8803
8854
|
}, [disabled]);
|
|
@@ -8858,7 +8909,7 @@ function ThinkingSelect({
|
|
|
8858
8909
|
className
|
|
8859
8910
|
}) {
|
|
8860
8911
|
const [open, setOpen] = useState16(false);
|
|
8861
|
-
const previousOpenSignalRef =
|
|
8912
|
+
const previousOpenSignalRef = useRef13(openSignal);
|
|
8862
8913
|
useEffect17(() => {
|
|
8863
8914
|
if (disabled) setOpen(false);
|
|
8864
8915
|
}, [disabled]);
|
|
@@ -8955,8 +9006,8 @@ function ThinkingPickerMenu({
|
|
|
8955
9006
|
}) {
|
|
8956
9007
|
const selectedIndex = Math.max(0, THINKING_LEVELS.indexOf(value));
|
|
8957
9008
|
const [activeIndex, setActiveIndex] = useState16(selectedIndex);
|
|
8958
|
-
const activeIndexRef =
|
|
8959
|
-
const menuRef =
|
|
9009
|
+
const activeIndexRef = useRef13(selectedIndex);
|
|
9010
|
+
const menuRef = useRef13(null);
|
|
8960
9011
|
useDismissOnOutsidePointer(menuRef, onClose);
|
|
8961
9012
|
const setKeyboardActiveIndex = (next) => {
|
|
8962
9013
|
const resolved = typeof next === "function" ? next(activeIndexRef.current) : next;
|
|
@@ -9052,7 +9103,7 @@ import {
|
|
|
9052
9103
|
XIcon as XIcon4
|
|
9053
9104
|
} from "lucide-react";
|
|
9054
9105
|
import { nanoid } from "nanoid";
|
|
9055
|
-
import { useCallback as useCallback15, useEffect as useEffect18, useMemo as useMemo13, useRef as
|
|
9106
|
+
import { useCallback as useCallback15, useEffect as useEffect18, useMemo as useMemo13, useRef as useRef14, useState as useState17 } from "react";
|
|
9056
9107
|
|
|
9057
9108
|
// src/front/primitives/prompt-input-context.ts
|
|
9058
9109
|
import { createContext as createContext7, useContext as useContext7 } from "react";
|
|
@@ -9119,12 +9170,12 @@ var PromptInput = ({
|
|
|
9119
9170
|
}) => {
|
|
9120
9171
|
const controller = useOptionalPromptInputController();
|
|
9121
9172
|
const usingProvider = !!controller;
|
|
9122
|
-
const providerTextValueRef =
|
|
9173
|
+
const providerTextValueRef = useRef14("");
|
|
9123
9174
|
if (usingProvider) {
|
|
9124
9175
|
providerTextValueRef.current = controller.textInput.value;
|
|
9125
9176
|
}
|
|
9126
|
-
const inputRef =
|
|
9127
|
-
const formRef =
|
|
9177
|
+
const inputRef = useRef14(null);
|
|
9178
|
+
const formRef = useRef14(null);
|
|
9128
9179
|
const [items, setItems] = useState17([]);
|
|
9129
9180
|
const setFileUrlLocal = useCallback15((id, url, status, path) => {
|
|
9130
9181
|
setItems((prev) => prev.map((f) => {
|
|
@@ -9135,7 +9186,7 @@ var PromptInput = ({
|
|
|
9135
9186
|
}, []);
|
|
9136
9187
|
const files = usingProvider ? controller.attachments.files : items;
|
|
9137
9188
|
const [referencedSources, setReferencedSources] = useState17([]);
|
|
9138
|
-
const filesRef =
|
|
9189
|
+
const filesRef = useRef14(files);
|
|
9139
9190
|
useEffect18(() => {
|
|
9140
9191
|
filesRef.current = files;
|
|
9141
9192
|
}, [files]);
|
|
@@ -9613,7 +9664,7 @@ var PromptInputSubmit = ({
|
|
|
9613
9664
|
};
|
|
9614
9665
|
|
|
9615
9666
|
// src/front/primitives/slash-command-picker.tsx
|
|
9616
|
-
import { useEffect as useEffect19, useMemo as useMemo14, useRef as
|
|
9667
|
+
import { useEffect as useEffect19, useMemo as useMemo14, useRef as useRef15, useState as useState18 } from "react";
|
|
9617
9668
|
import { Fragment as Fragment13, jsx as jsx31, jsxs as jsxs27 } from "react/jsx-runtime";
|
|
9618
9669
|
var ALL_PLUGINS = "__all__";
|
|
9619
9670
|
function commandGroup(cmd) {
|
|
@@ -9625,9 +9676,9 @@ function SlashCommandPicker({ query, commands, onSelect, onDismiss }) {
|
|
|
9625
9676
|
const [plugin, setPlugin] = useState18(ALL_PLUGINS);
|
|
9626
9677
|
const [searchQuery, setSearchQuery] = useState18(query);
|
|
9627
9678
|
const [activeIdx, setActiveIdx] = useState18(0);
|
|
9628
|
-
const containerRef =
|
|
9629
|
-
const listRef =
|
|
9630
|
-
const inputRef =
|
|
9679
|
+
const containerRef = useRef15(null);
|
|
9680
|
+
const listRef = useRef15(null);
|
|
9681
|
+
const inputRef = useRef15(null);
|
|
9631
9682
|
useEffect19(() => {
|
|
9632
9683
|
setSearchQuery(query);
|
|
9633
9684
|
}, [query]);
|
|
@@ -9862,6 +9913,8 @@ function PiChatComposerSurface({
|
|
|
9862
9913
|
onDismissSlash,
|
|
9863
9914
|
modelPickerOpen,
|
|
9864
9915
|
selectedModel,
|
|
9916
|
+
sessionModel,
|
|
9917
|
+
modelOverride,
|
|
9865
9918
|
modelOptions,
|
|
9866
9919
|
modelControlled,
|
|
9867
9920
|
hideDefaultModelOption = false,
|
|
@@ -10172,6 +10225,8 @@ function PiChatComposerSurface({
|
|
|
10172
10225
|
ModelSelectTrigger,
|
|
10173
10226
|
{
|
|
10174
10227
|
value: selectedModel,
|
|
10228
|
+
sessionModel,
|
|
10229
|
+
isOverride: modelOverride,
|
|
10175
10230
|
options: modelOptions,
|
|
10176
10231
|
disabled: isStreaming || modelControlled,
|
|
10177
10232
|
trigger: "slash",
|
|
@@ -10215,7 +10270,7 @@ function getHeaderValue(headers, name) {
|
|
|
10215
10270
|
}
|
|
10216
10271
|
|
|
10217
10272
|
// src/front/chat/piChatPanelHooks.ts
|
|
10218
|
-
import { useCallback as useCallback17, useEffect as useEffect20, useMemo as useMemo15, useRef as
|
|
10273
|
+
import { useCallback as useCallback17, useEffect as useEffect20, useMemo as useMemo15, useRef as useRef16, useState as useState19, useSyncExternalStore } from "react";
|
|
10219
10274
|
|
|
10220
10275
|
// src/front/chat/piChatPanelUtils.ts
|
|
10221
10276
|
function headersContentKey(headers) {
|
|
@@ -10336,7 +10391,7 @@ function useExternalRemotePiSession({
|
|
|
10336
10391
|
enabled = true
|
|
10337
10392
|
}) {
|
|
10338
10393
|
const [session, setSession] = useState19();
|
|
10339
|
-
const remoteSessionOptionsRef =
|
|
10394
|
+
const remoteSessionOptionsRef = useRef16(remoteSessionOptions);
|
|
10340
10395
|
remoteSessionOptionsRef.current = remoteSessionOptions;
|
|
10341
10396
|
const requestHeadersKey = headersContentKey(requestHeaders);
|
|
10342
10397
|
const stableRequestHeaders = useMemo15(
|
|
@@ -10489,11 +10544,11 @@ function PiChatPanel({
|
|
|
10489
10544
|
}) {
|
|
10490
10545
|
const externalSessionId = sessionId?.trim() || void 0;
|
|
10491
10546
|
const showSessionSidebar = showSessions ?? externalSessionId === void 0;
|
|
10492
|
-
const onDataRef =
|
|
10547
|
+
const onDataRef = useRef17(onData);
|
|
10493
10548
|
onDataRef.current = onData;
|
|
10494
|
-
const onTurnCompleteRef =
|
|
10549
|
+
const onTurnCompleteRef = useRef17(onTurnComplete);
|
|
10495
10550
|
onTurnCompleteRef.current = onTurnComplete;
|
|
10496
|
-
const sessionListRefreshRef =
|
|
10551
|
+
const sessionListRefreshRef = useRef17(void 0);
|
|
10497
10552
|
const requestHeadersKey = useMemo16(() => headersContentKey(requestHeaders), [requestHeaders]);
|
|
10498
10553
|
const normalizedRequestHeaders = useMemo16(() => normalizedHeadersFromContentKey(requestHeadersKey), [requestHeadersKey]);
|
|
10499
10554
|
const remoteSessionOptionsWithEvents = useMemo16(() => ({
|
|
@@ -10557,13 +10612,21 @@ function PiChatPanel({
|
|
|
10557
10612
|
agentTypeId,
|
|
10558
10613
|
apiBaseUrl,
|
|
10559
10614
|
defaultModel,
|
|
10615
|
+
sessionId: activeSessionId,
|
|
10616
|
+
sessionHydrated: selectedChatState?.hydrated ?? false,
|
|
10617
|
+
sessionIsNew: Boolean(
|
|
10618
|
+
selectedChatState?.hydrated && selectedChatState.history.messageCount === 0 && selectedChatState.committedMessages.length === 0 && selectedChatState.queue.followUps.length === 0 && Object.keys(selectedChatState.optimisticOutbox).length === 0 && !selectedChatState.streamingMessage
|
|
10619
|
+
),
|
|
10620
|
+
sessionModel: selectedChatState?.currentModel,
|
|
10560
10621
|
fetch: fetch2,
|
|
10561
10622
|
requestHeaders: normalizedRequestHeaders,
|
|
10562
10623
|
storage,
|
|
10563
10624
|
storageScope,
|
|
10564
10625
|
enabled: modelDiscoveryEnabled
|
|
10565
10626
|
});
|
|
10627
|
+
const sessionModel = selectedChatState?.currentModel;
|
|
10566
10628
|
const selectedModel = model === void 0 ? modelDiscovery.model : model;
|
|
10629
|
+
const modelOverride = model === void 0 ? modelDiscovery.isOverride : Boolean(model && sessionModel && (model.provider !== sessionModel.provider || model.id !== sessionModel.id));
|
|
10567
10630
|
const modelOptions = useMemo16(
|
|
10568
10631
|
() => modelOptionsForSelection(availableModels ?? modelDiscovery.availableModels, selectedModel),
|
|
10569
10632
|
[availableModels, modelDiscovery.availableModels, selectedModel]
|
|
@@ -10602,13 +10665,13 @@ function PiChatPanel({
|
|
|
10602
10665
|
const [modelPickerOpen, setModelPickerOpen] = useState20(false);
|
|
10603
10666
|
const [thinkingPickerOpen, setThinkingPickerOpen] = useState20(false);
|
|
10604
10667
|
const [draft, setDraft] = useState20(() => initialDraft ?? "");
|
|
10605
|
-
const draftRef =
|
|
10668
|
+
const draftRef = useRef17(draft);
|
|
10606
10669
|
draftRef.current = draft;
|
|
10607
|
-
const initialDraftGuard =
|
|
10608
|
-
const pendingAutoSubmitSettleRef =
|
|
10609
|
-
const acceptedAutoSubmitSettleRef =
|
|
10610
|
-
const resetInProgressRef =
|
|
10611
|
-
const autoCreateInFlightRef =
|
|
10670
|
+
const initialDraftGuard = useRef17(new InitialDraftAutoSubmitGuard());
|
|
10671
|
+
const pendingAutoSubmitSettleRef = useRef17(void 0);
|
|
10672
|
+
const acceptedAutoSubmitSettleRef = useRef17(void 0);
|
|
10673
|
+
const resetInProgressRef = useRef17(false);
|
|
10674
|
+
const autoCreateInFlightRef = useRef17(false);
|
|
10612
10675
|
const settlePendingAutoSubmit = useCallback18((sessionId2) => {
|
|
10613
10676
|
const pendingSessionId = pendingAutoSubmitSettleRef.current;
|
|
10614
10677
|
if (!pendingSessionId || sessionId2 && pendingSessionId !== sessionId2) return false;
|
|
@@ -10617,19 +10680,19 @@ function PiChatPanel({
|
|
|
10617
10680
|
onAutoSubmitInitialDraftSettled?.();
|
|
10618
10681
|
return true;
|
|
10619
10682
|
}, [onAutoSubmitInitialDraftSettled]);
|
|
10620
|
-
const prevStatusRef =
|
|
10621
|
-
const statusRef =
|
|
10622
|
-
const scrollToBottomRef =
|
|
10683
|
+
const prevStatusRef = useRef17("idle");
|
|
10684
|
+
const statusRef = useRef17("idle");
|
|
10685
|
+
const scrollToBottomRef = useRef17(() => {
|
|
10623
10686
|
});
|
|
10624
|
-
const textareaRef =
|
|
10687
|
+
const textareaRef = useRef17(null);
|
|
10625
10688
|
const [localNotices, setLocalNotices] = useState20([]);
|
|
10626
10689
|
const [dismissedNoticeIds, setDismissedNoticeIds] = useState20(() => /* @__PURE__ */ new Set());
|
|
10627
10690
|
const [pluginUpdateState, setPluginUpdateState] = useState20(null);
|
|
10628
10691
|
const [commandNotifyState, setCommandNotifyState] = useState20(null);
|
|
10629
|
-
const commandRunIdRef =
|
|
10692
|
+
const commandRunIdRef = useRef17(0);
|
|
10630
10693
|
const [serverSkillsRefreshKey, setServerSkillsRefreshKey] = useState20(0);
|
|
10631
10694
|
const [localSubmittedSessionId, setLocalSubmittedSessionId] = useState20();
|
|
10632
|
-
const localSubmittedSessionRef =
|
|
10695
|
+
const localSubmittedSessionRef = useRef17(void 0);
|
|
10633
10696
|
const { attachmentNotice, setAttachmentNotice } = useAttachmentNotice();
|
|
10634
10697
|
const composerContributions = useComposerContributions();
|
|
10635
10698
|
const contributedCommands = useMemo16(
|
|
@@ -11261,6 +11324,8 @@ function PiChatPanel({
|
|
|
11261
11324
|
onDismissSlash: dismissSlash,
|
|
11262
11325
|
modelPickerOpen,
|
|
11263
11326
|
selectedModel,
|
|
11327
|
+
sessionModel,
|
|
11328
|
+
modelOverride,
|
|
11264
11329
|
modelOptions,
|
|
11265
11330
|
modelControlled: model !== void 0,
|
|
11266
11331
|
hideDefaultModelOption,
|