Fix remaining OpenCode review comments

This commit is contained in:
Konan69
2026-03-05 16:07:12 +01:00
parent 69c453b274
commit f4f9d6fd3f
4 changed files with 99 additions and 70 deletions

View File

@@ -141,38 +141,41 @@ export async function execute(ctx: AdapterExecutionContext): Promise<AdapterExec
} }
const instructionsFilePath = asString(config.instructionsFilePath, "").trim(); const instructionsFilePath = asString(config.instructionsFilePath, "").trim();
const instructionsDir = instructionsFilePath ? `${path.dirname(instructionsFilePath)}/` : ""; const resolvedInstructionsFilePath = instructionsFilePath
? path.resolve(cwd, instructionsFilePath)
: "";
const instructionsDir = resolvedInstructionsFilePath ? `${path.dirname(resolvedInstructionsFilePath)}/` : "";
let instructionsPrefix = ""; let instructionsPrefix = "";
if (instructionsFilePath) { if (resolvedInstructionsFilePath) {
try { try {
const instructionsContents = await fs.readFile(instructionsFilePath, "utf8"); const instructionsContents = await fs.readFile(resolvedInstructionsFilePath, "utf8");
instructionsPrefix = instructionsPrefix =
`${instructionsContents}\n\n` + `${instructionsContents}\n\n` +
`The above agent instructions were loaded from ${instructionsFilePath}. ` + `The above agent instructions were loaded from ${resolvedInstructionsFilePath}. ` +
`Resolve any relative file references from ${instructionsDir}.\n\n`; `Resolve any relative file references from ${instructionsDir}.\n\n`;
await onLog( await onLog(
"stderr", "stderr",
`[paperclip] Loaded agent instructions file: ${instructionsFilePath}\n`, `[paperclip] Loaded agent instructions file: ${resolvedInstructionsFilePath}\n`,
); );
} catch (err) { } catch (err) {
const reason = err instanceof Error ? err.message : String(err); const reason = err instanceof Error ? err.message : String(err);
await onLog( await onLog(
"stderr", "stderr",
`[paperclip] Warning: could not read agent instructions file "${instructionsFilePath}": ${reason}\n`, `[paperclip] Warning: could not read agent instructions file "${resolvedInstructionsFilePath}": ${reason}\n`,
); );
} }
} }
const commandNotes = (() => { const commandNotes = (() => {
if (!instructionsFilePath) return [] as string[]; if (!resolvedInstructionsFilePath) return [] as string[];
if (instructionsPrefix.length > 0) { if (instructionsPrefix.length > 0) {
return [ return [
`Loaded agent instructions from ${instructionsFilePath}`, `Loaded agent instructions from ${resolvedInstructionsFilePath}`,
`Prepended instructions + path directive to stdin prompt (relative references from ${instructionsDir}).`, `Prepended instructions + path directive to stdin prompt (relative references from ${instructionsDir}).`,
]; ];
} }
return [ return [
`Configured instructionsFilePath ${instructionsFilePath}, but file could not be read; continuing without injected instructions.`, `Configured instructionsFilePath ${resolvedInstructionsFilePath}, but file could not be read; continuing without injected instructions.`,
]; ];
})(); })();

View File

@@ -81,20 +81,30 @@ export async function testEnvironment(
} }
const runtimeEnv = normalizeEnv(ensurePathInEnv({ ...process.env, ...env })); const runtimeEnv = normalizeEnv(ensurePathInEnv({ ...process.env, ...env }));
try { const cwdInvalid = checks.some((check) => check.code === "opencode_cwd_invalid");
await ensureCommandResolvable(command, cwd, runtimeEnv); if (cwdInvalid) {
checks.push({ checks.push({
code: "opencode_command_resolvable", code: "opencode_command_skipped",
level: "info", level: "warn",
message: `Command is executable: ${command}`, message: "Skipped command check because working directory validation failed.",
});
} catch (err) {
checks.push({
code: "opencode_command_unresolvable",
level: "error",
message: err instanceof Error ? err.message : "Command is not executable",
detail: command, detail: command,
}); });
} else {
try {
await ensureCommandResolvable(command, cwd, runtimeEnv);
checks.push({
code: "opencode_command_resolvable",
level: "info",
message: `Command is executable: ${command}`,
});
} catch (err) {
checks.push({
code: "opencode_command_unresolvable",
level: "error",
message: err instanceof Error ? err.message : "Command is not executable",
detail: command,
});
}
} }
const canRunProbe = const canRunProbe =
@@ -174,61 +184,71 @@ export async function testEnvironment(
if (variant) args.push("--variant", variant); if (variant) args.push("--variant", variant);
if (extraArgs.length > 0) args.push(...extraArgs); if (extraArgs.length > 0) args.push(...extraArgs);
const probe = await runChildProcess( try {
`opencode-envtest-${Date.now()}-${Math.random().toString(16).slice(2)}`, const probe = await runChildProcess(
command, `opencode-envtest-${Date.now()}-${Math.random().toString(16).slice(2)}`,
args, command,
{ args,
cwd, {
env: runtimeEnv, cwd,
timeoutSec: 60, env: runtimeEnv,
graceSec: 5, timeoutSec: 60,
stdin: "Respond with hello.", graceSec: 5,
onLog: async () => {}, stdin: "Respond with hello.",
}, onLog: async () => {},
); },
);
const parsed = parseOpenCodeJsonl(probe.stdout); const parsed = parseOpenCodeJsonl(probe.stdout);
const detail = summarizeProbeDetail(probe.stdout, probe.stderr, parsed.errorMessage); const detail = summarizeProbeDetail(probe.stdout, probe.stderr, parsed.errorMessage);
const authEvidence = `${parsed.errorMessage ?? ""}\n${probe.stdout}\n${probe.stderr}`.trim(); const authEvidence = `${parsed.errorMessage ?? ""}\n${probe.stdout}\n${probe.stderr}`.trim();
if (probe.timedOut) { if (probe.timedOut) {
checks.push({ checks.push({
code: "opencode_hello_probe_timed_out", code: "opencode_hello_probe_timed_out",
level: "warn", level: "warn",
message: "OpenCode hello probe timed out.", message: "OpenCode hello probe timed out.",
hint: "Retry the probe. If this persists, run OpenCode manually in this working directory.", hint: "Retry the probe. If this persists, run OpenCode manually in this working directory.",
}); });
} else if ((probe.exitCode ?? 1) === 0 && !parsed.errorMessage) { } else if ((probe.exitCode ?? 1) === 0 && !parsed.errorMessage) {
const summary = parsed.summary.trim(); const summary = parsed.summary.trim();
const hasHello = /\bhello\b/i.test(summary); const hasHello = /\bhello\b/i.test(summary);
checks.push({ checks.push({
code: hasHello ? "opencode_hello_probe_passed" : "opencode_hello_probe_unexpected_output", code: hasHello ? "opencode_hello_probe_passed" : "opencode_hello_probe_unexpected_output",
level: hasHello ? "info" : "warn", level: hasHello ? "info" : "warn",
message: hasHello message: hasHello
? "OpenCode hello probe succeeded." ? "OpenCode hello probe succeeded."
: "OpenCode probe ran but did not return `hello` as expected.", : "OpenCode probe ran but did not return `hello` as expected.",
...(summary ? { detail: summary.replace(/\s+/g, " ").trim().slice(0, 240) } : {}), ...(summary ? { detail: summary.replace(/\s+/g, " ").trim().slice(0, 240) } : {}),
...(hasHello ...(hasHello
? {} ? {}
: { : {
hint: "Run `opencode run --format json` manually and prompt `Respond with hello` to inspect output.", hint: "Run `opencode run --format json` manually and prompt `Respond with hello` to inspect output.",
}), }),
}); });
} else if (OPENCODE_AUTH_REQUIRED_RE.test(authEvidence)) { } else if (OPENCODE_AUTH_REQUIRED_RE.test(authEvidence)) {
checks.push({ checks.push({
code: "opencode_hello_probe_auth_required", code: "opencode_hello_probe_auth_required",
level: "warn", level: "warn",
message: "OpenCode is installed, but provider authentication is not ready.", message: "OpenCode is installed, but provider authentication is not ready.",
...(detail ? { detail } : {}), ...(detail ? { detail } : {}),
hint: "Run `opencode auth login` or set provider credentials, then retry the probe.", hint: "Run `opencode auth login` or set provider credentials, then retry the probe.",
}); });
} else { } else {
checks.push({
code: "opencode_hello_probe_failed",
level: "error",
message: "OpenCode hello probe failed.",
...(detail ? { detail } : {}),
hint: "Run `opencode run --format json` manually in this working directory to debug.",
});
}
} catch (err) {
checks.push({ checks.push({
code: "opencode_hello_probe_failed", code: "opencode_hello_probe_failed",
level: "error", level: "error",
message: "OpenCode hello probe failed.", message: "OpenCode hello probe failed.",
...(detail ? { detail } : {}), detail: err instanceof Error ? err.message : String(err),
hint: "Run `opencode run --format json` manually in this working directory to debug.", hint: "Run `opencode run --format json` manually in this working directory to debug.",
}); });
} }

View File

@@ -149,6 +149,8 @@ export function OnboardingWizard() {
const { const {
data: adapterModels, data: adapterModels,
error: adapterModelsError, error: adapterModelsError,
isLoading: adapterModelsLoading,
isFetching: adapterModelsFetching,
} = useQuery({ } = useQuery({
queryKey: queryKey:
createdCompanyId createdCompanyId
@@ -332,6 +334,10 @@ export function OnboardingWizard() {
); );
return; return;
} }
if (adapterModelsLoading || adapterModelsFetching) {
setError("OpenCode models are still loading. Please wait and try again.");
return;
}
const discoveredModels = adapterModels ?? []; const discoveredModels = adapterModels ?? [];
if (!discoveredModels.some((entry) => entry.id === selectedModelId)) { if (!discoveredModels.some((entry) => entry.id === selectedModelId)) {
setError( setError(

View File

@@ -12,5 +12,5 @@ export function extractProviderIdWithFallback(modelId: string, fallback = "other
export function extractModelName(modelId: string): string { export function extractModelName(modelId: string): string {
const trimmed = modelId.trim(); const trimmed = modelId.trim();
if (!trimmed.includes("/")) return trimmed; if (!trimmed.includes("/")) return trimmed;
return trimmed.slice(trimmed.indexOf("/") + 1); return trimmed.slice(trimmed.indexOf("/") + 1).trim();
} }