feat: pin sessions to workspace revisions
This commit is contained in:
@@ -1,13 +1,14 @@
|
||||
// frontend/src/shell/SteerInput.tsx
|
||||
import { useEffect, useRef, useState } from "react";
|
||||
import { CornerDownLeft } from "lucide-react";
|
||||
import { useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { useQuery } from "@tanstack/react-query";
|
||||
import { postSteer, createSession } from "../api/sessions";
|
||||
import { ApiError } from "../api/client";
|
||||
import { getSettings, putSettings, type Settings } from "../api/settings";
|
||||
import { getSettings } from "../api/settings";
|
||||
import { listWorkspaces } from "../api/workspaces";
|
||||
import { listModels } from "../api/models";
|
||||
import { useSessionStore } from "../store/sessionStore";
|
||||
import { workspacePreferences, type WorkspacePreference } from "../workspaces/preferences";
|
||||
|
||||
const THINKING_LEVELS = ["low", "medium", "high"] as const;
|
||||
|
||||
@@ -151,25 +152,33 @@ export function SteerInput({
|
||||
|
||||
/**
|
||||
* Status strip beneath the composer. Left: the active workspace selector.
|
||||
* Right: live context usage plus model + thinking-level selectors (these replace
|
||||
* the old Settings dialog and persist through PUT /settings).
|
||||
* Right: live context usage plus browser-local workspace/model/thinking selectors.
|
||||
*/
|
||||
export function ComposerFooter() {
|
||||
const qc = useQueryClient();
|
||||
const { data: settings } = useQuery({ queryKey: ["settings"], queryFn: getSettings });
|
||||
const { data: workspaces = [] } = useQuery({ queryKey: ["workspaces"], queryFn: listWorkspaces });
|
||||
const { data: modelsData } = useQuery({ queryKey: ["models"], queryFn: listModels });
|
||||
const models = modelsData?.models ?? [];
|
||||
const tokenUsage = useSessionStore((state) => state.tokenUsage);
|
||||
const [preferences, setPreferences] = useState<WorkspacePreference>(() => workspacePreferences.load());
|
||||
|
||||
const workspace = settings?.workspace ?? "";
|
||||
const model = settings?.model ?? "";
|
||||
const thinking = settings?.thinking ?? "medium";
|
||||
useEffect(() => {
|
||||
if (!settings) return;
|
||||
setPreferences(workspacePreferences.migrate({
|
||||
workspaceId: settings.workspace,
|
||||
provider: settings.provider,
|
||||
model: settings.model,
|
||||
thinking: settings.thinking,
|
||||
}));
|
||||
}, [settings]);
|
||||
|
||||
// PUT /settings replaces the whole object, so always send the merged settings.
|
||||
async function update(patch: Partial<Settings>) {
|
||||
await putSettings({ workspace, provider: settings?.provider, model, thinking, ...patch });
|
||||
qc.invalidateQueries({ queryKey: ["settings"] });
|
||||
const workspace = preferences.workspaceId ?? settings?.workspace ?? "";
|
||||
const model = preferences.model ?? settings?.model ?? "";
|
||||
const thinking = preferences.thinking ?? settings?.thinking ?? "medium";
|
||||
|
||||
function update(patch: WorkspacePreference) {
|
||||
const next = workspacePreferences.save({ ...preferences, ...patch });
|
||||
setPreferences(next);
|
||||
}
|
||||
|
||||
function onModelChange(id: string) {
|
||||
@@ -185,7 +194,7 @@ export function ComposerFooter() {
|
||||
return (
|
||||
<div className="flex items-center justify-between gap-2 border-t border-border/60 px-3 py-1.5">
|
||||
<div className="flex items-center gap-2">
|
||||
<FooterSelect aria-label="Workspace" value={workspace} onChange={(v) => update({ workspace: v })}>
|
||||
<FooterSelect aria-label="Workspace" value={workspace} onChange={(v) => update({ workspaceId: v })}>
|
||||
{workspaces.length === 0 ? (
|
||||
<option value="">— workspace —</option>
|
||||
) : (
|
||||
|
||||
Reference in New Issue
Block a user