feat(vscode): implement API and session readiness checks before message handling
This commit is contained in:
@@ -10,6 +10,37 @@ const AUTO_DELETE_DEFAULT_DAYS = 30;
|
|||||||
const AUTO_DELETE_KEEP_RECENT = 5;
|
const AUTO_DELETE_KEEP_RECENT = 5;
|
||||||
const AUTO_DELETE_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
const AUTO_DELETE_INTERVAL_MS = 24 * 60 * 60 * 1000;
|
||||||
|
|
||||||
|
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
|
||||||
|
|
||||||
|
const waitForApiReady = async (client: OpencodeClient, attempts = 10, delayMs = 500): Promise<boolean> => {
|
||||||
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
||||||
|
try {
|
||||||
|
await client.session.list({ query: { directory: getWorkspaceFolder() } });
|
||||||
|
return true;
|
||||||
|
} catch {
|
||||||
|
await sleep(delayMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
const waitForSessionReady = async (client: OpencodeClient, sessionId: string, attempts = 10, delayMs = 500): Promise<boolean> => {
|
||||||
|
for (let attempt = 0; attempt < attempts; attempt += 1) {
|
||||||
|
try {
|
||||||
|
const response = await client.session.get({
|
||||||
|
path: { id: sessionId },
|
||||||
|
query: { directory: getWorkspaceFolder() },
|
||||||
|
});
|
||||||
|
if (response.data) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
await sleep(delayMs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
let autoDeleteRunning = false;
|
let autoDeleteRunning = false;
|
||||||
|
|
||||||
const getLastActivity = (session: Session): number => {
|
const getLastActivity = (session: Session): number => {
|
||||||
@@ -247,9 +278,18 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|||||||
if (!client) return null;
|
if (!client) return null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const apiReady = await waitForApiReady(client);
|
||||||
|
if (!apiReady) {
|
||||||
|
throw new Error('OpenCode API not ready');
|
||||||
|
}
|
||||||
|
|
||||||
const response = await client.session.create({ query: { directory: getWorkspaceFolder() }, body: {} });
|
const response = await client.session.create({ query: { directory: getWorkspaceFolder() }, body: {} });
|
||||||
const session = response.data;
|
const session = response.data;
|
||||||
if (!session) throw new Error('No session returned');
|
if (!session) throw new Error('No session returned');
|
||||||
|
const sessionReady = await waitForSessionReady(client, session.id);
|
||||||
|
if (!sessionReady) {
|
||||||
|
console.warn('Session created but not ready yet; continuing');
|
||||||
|
}
|
||||||
await get().loadSessions();
|
await get().loadSessions();
|
||||||
set({ currentSessionId: session.id });
|
set({ currentSessionId: session.id });
|
||||||
return session.id;
|
return session.id;
|
||||||
@@ -295,6 +335,16 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|||||||
set({ isSending: true, streamingSessionId: currentSessionId });
|
set({ isSending: true, streamingSessionId: currentSessionId });
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const apiReady = await waitForApiReady(client);
|
||||||
|
if (!apiReady) {
|
||||||
|
throw new Error('OpenCode API not ready');
|
||||||
|
}
|
||||||
|
|
||||||
|
const sessionReady = await waitForSessionReady(client, currentSessionId);
|
||||||
|
if (!sessionReady) {
|
||||||
|
console.warn('Session not ready yet; attempting to prompt anyway');
|
||||||
|
}
|
||||||
|
|
||||||
// Add user message optimistically
|
// Add user message optimistically
|
||||||
const messageId = `temp-${Date.now()}`;
|
const messageId = `temp-${Date.now()}`;
|
||||||
const partId = `part-${messageId}`;
|
const partId = `part-${messageId}`;
|
||||||
@@ -320,8 +370,7 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|||||||
newMessages.set(currentSessionId, [...currentMessages, userMessage]);
|
newMessages.set(currentSessionId, [...currentMessages, userMessage]);
|
||||||
set({ messages: newMessages });
|
set({ messages: newMessages });
|
||||||
|
|
||||||
// Send message via session.prompt
|
const sendPrompt = () => client.session.prompt({
|
||||||
await client.session.prompt({
|
|
||||||
path: { id: currentSessionId },
|
path: { id: currentSessionId },
|
||||||
query: { directory: getWorkspaceFolder() },
|
query: { directory: getWorkspaceFolder() },
|
||||||
body: {
|
body: {
|
||||||
@@ -329,6 +378,17 @@ export const useChatStore = create<ChatState>((set, get) => ({
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
try {
|
||||||
|
await sendPrompt();
|
||||||
|
} catch (error) {
|
||||||
|
const recovered = await waitForSessionReady(client, currentSessionId, 6, 500);
|
||||||
|
if (recovered) {
|
||||||
|
await sendPrompt();
|
||||||
|
} else {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Reload messages to get the actual response
|
// Reload messages to get the actual response
|
||||||
await get().loadMessages(currentSessionId);
|
await get().loadMessages(currentSessionId);
|
||||||
await get().loadSessions(); // Update session title if changed
|
await get().loadSessions(); // Update session title if changed
|
||||||
|
|||||||
Reference in New Issue
Block a user