fix(vscode): Change Health Check to Health API Endpoint and increase timeout (#268)
* Try fixing startup * Add OpenCode Version to debug
This commit is contained in:
@@ -415,6 +415,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
};
|
};
|
||||||
|
|
||||||
const probeTargets: Array<{ label: string; path: string; includeDirectory?: boolean; timeoutMs?: number }> = [
|
const probeTargets: Array<{ label: string; path: string; includeDirectory?: boolean; timeoutMs?: number }> = [
|
||||||
|
{ label: 'health', path: '/global/health', includeDirectory: false },
|
||||||
{ label: 'config', path: '/config', includeDirectory: true },
|
{ label: 'config', path: '/config', includeDirectory: true },
|
||||||
{ label: 'providers', path: '/config/providers', includeDirectory: true },
|
{ label: 'providers', path: '/config/providers', includeDirectory: true },
|
||||||
// Can be slower on large configs; keep the probe from producing false negatives.
|
// Can be slower on large configs; keep the probe from producing false negatives.
|
||||||
@@ -446,6 +447,7 @@ export async function activate(context: vscode.ExtensionContext) {
|
|||||||
const lines = [
|
const lines = [
|
||||||
`Time: ${new Date().toISOString()}`,
|
`Time: ${new Date().toISOString()}`,
|
||||||
`OpenChamber version: ${extensionVersion || '(unknown)'}`,
|
`OpenChamber version: ${extensionVersion || '(unknown)'}`,
|
||||||
|
`OpenCode Version: ${debug?.version ?? '(unknown)'}`,
|
||||||
`VS Code version: ${vscode.version}`,
|
`VS Code version: ${vscode.version}`,
|
||||||
`Platform: ${process.platform} ${process.arch}`,
|
`Platform: ${process.platform} ${process.arch}`,
|
||||||
`Workspace folders: ${workspaceFolders.length}${workspaceFolders.length ? ` (${workspaceFolders.join(', ')})` : ''}`,
|
`Workspace folders: ${workspaceFolders.length}${workspaceFolders.length ? ` (${workspaceFolders.join(', ')})` : ''}`,
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
import * as vscode from 'vscode';
|
import * as vscode from 'vscode';
|
||||||
import * as os from 'os';
|
import * as os from 'os';
|
||||||
import { execSync } from 'child_process';
|
import { execSync } from 'child_process';
|
||||||
import { createOpencodeServer } from '@opencode-ai/sdk/server';
|
import { createOpencodeServer } from '@opencode-ai/sdk/v2/server';
|
||||||
|
|
||||||
const READY_CHECK_TIMEOUT_MS = 30000;
|
const READY_CHECK_TIMEOUT_MS = 30000;
|
||||||
|
|
||||||
@@ -28,6 +28,7 @@ export type OpenCodeDebugInfo = {
|
|||||||
lastReadyElapsedMs: number | null;
|
lastReadyElapsedMs: number | null;
|
||||||
lastReadyAttempts: number | null;
|
lastReadyAttempts: number | null;
|
||||||
lastStartAttempts: number | null;
|
lastStartAttempts: number | null;
|
||||||
|
version: string | null;
|
||||||
};
|
};
|
||||||
|
|
||||||
export interface OpenCodeManager {
|
export interface OpenCodeManager {
|
||||||
@@ -53,8 +54,8 @@ function resolvePortFromUrl(url: string): number | null {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type ReadyResult =
|
type ReadyResult =
|
||||||
| { ok: true; baseUrl: string; elapsedMs: number; attempts: number }
|
| { ok: true; baseUrl: string; elapsedMs: number; attempts: number; version: string | null }
|
||||||
| { ok: false; elapsedMs: number; attempts: number };
|
| { ok: false; elapsedMs: number; attempts: number; version: null };
|
||||||
|
|
||||||
function normalizeBaseUrl(value: string): string {
|
function normalizeBaseUrl(value: string): string {
|
||||||
return value.replace(/\/+$/, '');
|
return value.replace(/\/+$/, '');
|
||||||
@@ -86,6 +87,7 @@ function getCandidateBaseUrls(serverUrl: string): string[] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function waitForReady(serverUrl: string, timeoutMs = 15000): Promise<ReadyResult> {
|
async function waitForReady(serverUrl: string, timeoutMs = 15000): Promise<ReadyResult> {
|
||||||
|
const outputChannel = vscode.window.createOutputChannel('OpenChamberManager');
|
||||||
const start = Date.now();
|
const start = Date.now();
|
||||||
const candidates = getCandidateBaseUrls(serverUrl);
|
const candidates = getCandidateBaseUrls(serverUrl);
|
||||||
let attempts = 0;
|
let attempts = 0;
|
||||||
@@ -98,16 +100,27 @@ async function waitForReady(serverUrl: string, timeoutMs = 15000): Promise<Ready
|
|||||||
const timeout = setTimeout(() => controller.abort(), 3000);
|
const timeout = setTimeout(() => controller.abort(), 3000);
|
||||||
|
|
||||||
// Keep using /config since the UI proxies to it (via /api -> strip prefix).
|
// Keep using /config since the UI proxies to it (via /api -> strip prefix).
|
||||||
const url = new URL(`${baseUrl}/config`);
|
const url = new URL(`${baseUrl}/global/health`);
|
||||||
const res = await fetch(url.toString(), {
|
const res = await fetch(url.toString(), {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: { Accept: 'application/json' },
|
headers: { Accept: 'application/json' },
|
||||||
signal: controller.signal,
|
signal: controller.signal,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
let body: { healthy?: boolean, version?: string } | null = null;
|
||||||
|
try {
|
||||||
|
body = (await res.json()) as { healthy?: boolean, version?: string };
|
||||||
|
} catch {
|
||||||
|
body = null;
|
||||||
|
}
|
||||||
|
|
||||||
clearTimeout(timeout);
|
clearTimeout(timeout);
|
||||||
if (res.ok) {
|
outputChannel?.appendLine(
|
||||||
return { ok: true, baseUrl, elapsedMs: Date.now() - start, attempts };
|
`Health check to ${url.toString()} returned ${res.status} with body: ${JSON.stringify(body)}`
|
||||||
|
);
|
||||||
|
|
||||||
|
if (res.ok && body?.healthy === true) {
|
||||||
|
return { ok: true, baseUrl, elapsedMs: Date.now() - start, attempts, version: body?.version ?? null };
|
||||||
}
|
}
|
||||||
} catch {
|
} catch {
|
||||||
// ignore
|
// ignore
|
||||||
@@ -117,7 +130,7 @@ async function waitForReady(serverUrl: string, timeoutMs = 15000): Promise<Ready
|
|||||||
await new Promise(r => setTimeout(r, 100));
|
await new Promise(r => setTimeout(r, 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
return { ok: false, elapsedMs: Date.now() - start, attempts };
|
return { ok: false, elapsedMs: Date.now() - start, attempts, version: null };
|
||||||
}
|
}
|
||||||
|
|
||||||
export function createOpenCodeManager(_context: vscode.ExtensionContext): OpenCodeManager {
|
export function createOpenCodeManager(_context: vscode.ExtensionContext): OpenCodeManager {
|
||||||
@@ -139,6 +152,7 @@ export function createOpenCodeManager(_context: vscode.ExtensionContext): OpenCo
|
|||||||
let lastReadyElapsedMs: number | null = null;
|
let lastReadyElapsedMs: number | null = null;
|
||||||
let lastReadyAttempts: number | null = null;
|
let lastReadyAttempts: number | null = null;
|
||||||
let lastStartAttempts: number | null = null;
|
let lastStartAttempts: number | null = null;
|
||||||
|
let version: string | null = null;
|
||||||
|
|
||||||
let detectedPort: number | null = null;
|
let detectedPort: number | null = null;
|
||||||
let cliMissing = false;
|
let cliMissing = false;
|
||||||
@@ -244,12 +258,13 @@ export function createOpenCodeManager(_context: vscode.ExtensionContext): OpenCo
|
|||||||
|
|
||||||
if (server && server.url) {
|
if (server && server.url) {
|
||||||
// Validate readiness for the current workspace context.
|
// Validate readiness for the current workspace context.
|
||||||
const ready = await waitForReady(server.url, 10000);
|
const ready = await waitForReady(server.url, READY_CHECK_TIMEOUT_MS);
|
||||||
lastReadyElapsedMs = ready.elapsedMs;
|
lastReadyElapsedMs = ready.elapsedMs;
|
||||||
lastReadyAttempts = ready.attempts;
|
lastReadyAttempts = ready.attempts;
|
||||||
if (ready.ok) {
|
if (ready.ok) {
|
||||||
managedApiUrlOverride = ready.baseUrl;
|
managedApiUrlOverride = ready.baseUrl;
|
||||||
detectedPort = resolvePortFromUrl(ready.baseUrl);
|
detectedPort = resolvePortFromUrl(ready.baseUrl);
|
||||||
|
version = ready.version;
|
||||||
setStatus('connected');
|
setStatus('connected');
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
@@ -322,6 +337,7 @@ export function createOpenCodeManager(_context: vscode.ExtensionContext): OpenCo
|
|||||||
|
|
||||||
managedApiUrlOverride = null;
|
managedApiUrlOverride = null;
|
||||||
detectedPort = null;
|
detectedPort = null;
|
||||||
|
version = null;
|
||||||
setStatus('disconnected');
|
setStatus('disconnected');
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -425,6 +441,7 @@ export function createOpenCodeManager(_context: vscode.ExtensionContext): OpenCo
|
|||||||
lastReadyElapsedMs,
|
lastReadyElapsedMs,
|
||||||
lastReadyAttempts,
|
lastReadyAttempts,
|
||||||
lastStartAttempts,
|
lastStartAttempts,
|
||||||
|
version,
|
||||||
}),
|
}),
|
||||||
onStatusChange(callback) {
|
onStatusChange(callback) {
|
||||||
listeners.add(callback);
|
listeners.add(callback);
|
||||||
|
|||||||
Reference in New Issue
Block a user