fix(electrobun): session resume uses pending mode — user types prompt first, no empty string to SDK
This commit is contained in:
parent
31a3335651
commit
18b9c7c3b5
3 changed files with 49 additions and 6 deletions
|
|
@ -3,6 +3,7 @@
|
||||||
import ChatInput from "./ChatInput.svelte";
|
import ChatInput from "./ChatInput.svelte";
|
||||||
import SessionPicker from "./SessionPicker.svelte";
|
import SessionPicker from "./SessionPicker.svelte";
|
||||||
import type { AgentMessage, AgentStatus } from "./agent-store.svelte.ts";
|
import type { AgentMessage, AgentStatus } from "./agent-store.svelte.ts";
|
||||||
|
import { getPendingResume } from "./agent-store.svelte.ts";
|
||||||
import { t } from "./i18n.svelte.ts";
|
import { t } from "./i18n.svelte.ts";
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -55,6 +56,8 @@
|
||||||
return () => observer.disconnect();
|
return () => observer.disconnect();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
function getPendingResumeForProject() { return projectId ? getPendingResume(projectId) : undefined; }
|
||||||
|
|
||||||
function handleSend() {
|
function handleSend() {
|
||||||
const text = promptText.trim();
|
const text = promptText.trim();
|
||||||
if (!text) return;
|
if (!text) return;
|
||||||
|
|
@ -236,7 +239,7 @@
|
||||||
{model}
|
{model}
|
||||||
{provider}
|
{provider}
|
||||||
{contextPct}
|
{contextPct}
|
||||||
placeholder={t("agent.prompt.placeholder")}
|
placeholder={getPendingResumeForProject() ? 'Type to resume session...' : t("agent.prompt.placeholder")}
|
||||||
onSend={handleSend}
|
onSend={handleSend}
|
||||||
onInput={(v) => (promptText = v)}
|
onInput={(v) => (promptText = v)}
|
||||||
/>
|
/>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { onMount } from 'svelte';
|
import { onMount } from 'svelte';
|
||||||
import type { ClaudeSessionInfo } from './agent-store.svelte.ts';
|
import type { ClaudeSessionInfo } from './agent-store.svelte.ts';
|
||||||
import { listProjectSessions, resumeSession, continueLastSession, startAgent } from './agent-store.svelte.ts';
|
import { listProjectSessions, setPendingResume, getPendingResume, clearPendingResume } from './agent-store.svelte.ts';
|
||||||
import { t } from './i18n.svelte.ts';
|
import { t } from './i18n.svelte.ts';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -72,18 +72,21 @@
|
||||||
return s.length > max ? s.slice(0, max - 3) + '...' : s;
|
return s.length > max ? s.slice(0, max - 3) + '...' : s;
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleContinue() {
|
function handleContinue() {
|
||||||
open = false;
|
open = false;
|
||||||
await continueLastSession(projectId, provider, '', cwd);
|
setPendingResume(projectId, 'continue');
|
||||||
|
// User types their next prompt and hits Send — startAgent reads the pending resume
|
||||||
}
|
}
|
||||||
|
|
||||||
async function handleResume(sdkSessionId: string) {
|
function handleResume(sdkSessionId: string) {
|
||||||
open = false;
|
open = false;
|
||||||
await resumeSession(projectId, provider, sdkSessionId, '', cwd);
|
setPendingResume(projectId, 'resume', sdkSessionId);
|
||||||
|
// User types their next prompt and hits Send — startAgent reads the pending resume
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleNew() {
|
function handleNew() {
|
||||||
open = false;
|
open = false;
|
||||||
|
clearPendingResume(projectId);
|
||||||
onNewSession?.('');
|
onNewSession?.('');
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,33 @@ function validateExtraEnv(env: Record<string, string> | undefined): Record<strin
|
||||||
// Map projectId -> sessionId for lookup
|
// Map projectId -> sessionId for lookup
|
||||||
const projectSessionMap = new Map<string, string>();
|
const projectSessionMap = new Map<string, string>();
|
||||||
|
|
||||||
|
// 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<string, PendingResume>();
|
||||||
|
|
||||||
|
/** 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
|
// Map sessionId -> reactive session state
|
||||||
let sessions = $state<Record<string, AgentSession>>({});
|
let sessions = $state<Record<string, AgentSession>>({});
|
||||||
|
|
||||||
|
|
@ -522,6 +549,16 @@ async function _startAgentInner(
|
||||||
// If there's an existing done/error session for this project, clear it first
|
// If there's an existing done/error session for this project, clear it first
|
||||||
clearSession(projectId);
|
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()}`;
|
const sessionId = `${projectId}-${Date.now()}`;
|
||||||
|
|
||||||
// Read settings defaults if not explicitly provided (Fix #5)
|
// Read settings defaults if not explicitly provided (Fix #5)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue