From 18b9c7c3b58ea460bfa2c7e2b3cca84c5d4e36c2 Mon Sep 17 00:00:00 2001 From: Hibryda Date: Fri, 27 Mar 2026 03:35:02 +0100 Subject: [PATCH] =?UTF-8?q?fix(electrobun):=20session=20resume=20uses=20pe?= =?UTF-8?q?nding=20mode=20=E2=80=94=20user=20types=20prompt=20first,=20no?= =?UTF-8?q?=20empty=20string=20to=20SDK?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ui-electrobun/src/mainview/AgentPane.svelte | 5 ++- .../src/mainview/SessionPicker.svelte | 13 ++++--- .../src/mainview/agent-store.svelte.ts | 37 +++++++++++++++++++ 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/ui-electrobun/src/mainview/AgentPane.svelte b/ui-electrobun/src/mainview/AgentPane.svelte index a22c1eb..8992352 100644 --- a/ui-electrobun/src/mainview/AgentPane.svelte +++ b/ui-electrobun/src/mainview/AgentPane.svelte @@ -3,6 +3,7 @@ import ChatInput from "./ChatInput.svelte"; import SessionPicker from "./SessionPicker.svelte"; import type { AgentMessage, AgentStatus } from "./agent-store.svelte.ts"; + import { getPendingResume } from "./agent-store.svelte.ts"; import { t } from "./i18n.svelte.ts"; interface Props { @@ -55,6 +56,8 @@ return () => observer.disconnect(); }); + function getPendingResumeForProject() { return projectId ? getPendingResume(projectId) : undefined; } + function handleSend() { const text = promptText.trim(); if (!text) return; @@ -236,7 +239,7 @@ {model} {provider} {contextPct} - placeholder={t("agent.prompt.placeholder")} + placeholder={getPendingResumeForProject() ? 'Type to resume session...' : t("agent.prompt.placeholder")} onSend={handleSend} onInput={(v) => (promptText = v)} /> diff --git a/ui-electrobun/src/mainview/SessionPicker.svelte b/ui-electrobun/src/mainview/SessionPicker.svelte index b6da90e..3558900 100644 --- a/ui-electrobun/src/mainview/SessionPicker.svelte +++ b/ui-electrobun/src/mainview/SessionPicker.svelte @@ -1,7 +1,7 @@ diff --git a/ui-electrobun/src/mainview/agent-store.svelte.ts b/ui-electrobun/src/mainview/agent-store.svelte.ts index ae62a88..9764fb8 100644 --- a/ui-electrobun/src/mainview/agent-store.svelte.ts +++ b/ui-electrobun/src/mainview/agent-store.svelte.ts @@ -127,6 +127,33 @@ function validateExtraEnv(env: Record | undefined): Record sessionId for lookup const projectSessionMap = new Map(); +// Pending resume: when the user selects a session to resume, we store the +// resume options here. The next startAgent() call reads and clears them. +// This avoids sending an empty prompt — the user types their message first. +interface PendingResume { + mode: 'continue' | 'resume'; + sdkSessionId?: string; +} +const pendingResumes = new Map(); + +/** Set a pending resume for a project — next startAgent will use these options. */ +export function setPendingResume(projectId: string, mode: 'continue' | 'resume', sdkSessionId?: string): void { + pendingResumes.set(projectId, { mode, sdkSessionId }); + bump(); +} + +/** Check if a project has a pending resume. */ +export function getPendingResume(projectId: string): PendingResume | undefined { + void _v; + return pendingResumes.get(projectId); +} + +/** Clear pending resume (called after startAgent consumes it). */ +export function clearPendingResume(projectId: string): void { + pendingResumes.delete(projectId); + bump(); +} + // Map sessionId -> reactive session state let sessions = $state>({}); @@ -522,6 +549,16 @@ async function _startAgentInner( // If there's an existing done/error session for this project, clear it first clearSession(projectId); + // Check for pending resume (user selected a session in the picker) + const pending = pendingResumes.get(projectId); + if (pending) { + pendingResumes.delete(projectId); + if (!options.resumeMode) { + options.resumeMode = pending.mode; + options.resumeSessionId = pending.sdkSessionId; + } + } + const sessionId = `${projectId}-${Date.now()}`; // Read settings defaults if not explicitly provided (Fix #5)