Fix opencode things

This commit is contained in:
Colin McDonnell
2025-12-16 22:39:10 -08:00
parent 6be94d53ab
commit 54d43164b5
+67 -62
View File
@@ -11,14 +11,6 @@ import {
setupProcessAgentEnv, setupProcessAgentEnv,
} from "./shared.ts"; } from "./shared.ts";
// import { createOpencode } from "@opencode-ai/sdk"
// const { client } = await createOpencode({
// config: {
// ''
// }
// })
// opencode cli event types inferred from json output format // opencode cli event types inferred from json output format
interface OpenCodeInitEvent { interface OpenCodeInitEvent {
type: "init"; type: "init";
@@ -87,16 +79,33 @@ interface OpenCodeStepFinishEvent {
interface OpenCodeToolUseEvent { interface OpenCodeToolUseEvent {
type: "tool_use"; type: "tool_use";
timestamp?: string; timestamp?: number;
tool_name?: string; sessionID?: string;
tool_id?: string; part?: {
parameters?: unknown; id?: string;
callID?: string;
tool?: string;
state?: {
status?: string;
input?: unknown;
output?: string;
};
};
[key: string]: unknown; [key: string]: unknown;
} }
interface OpenCodeToolResultEvent { interface OpenCodeToolResultEvent {
type: "tool_result"; type: "tool_result";
timestamp?: string; timestamp?: number;
sessionID?: string;
part?: {
callID?: string;
state?: {
status?: string;
output?: string;
};
};
// fallback fields for older format
tool_id?: string; tool_id?: string;
status?: "success" | "error"; status?: "success" | "error";
output?: string; output?: string;
@@ -155,6 +164,7 @@ const messageHandlers = {
log.info( log.info(
`🔵 OpenCode init: session_id=${event.session_id || "unknown"}, model=${event.model || "unknown"}` `🔵 OpenCode init: session_id=${event.session_id || "unknown"}, model=${event.model || "unknown"}`
); );
log.info(`🔵 OpenCode init event (full): ${JSON.stringify(event)}`);
finalOutput = ""; finalOutput = "";
accumulatedTokens = { input: 0, output: 0 }; accumulatedTokens = { input: 0, output: 0 };
tokensLogged = false; tokensLogged = false;
@@ -186,9 +196,6 @@ const messageHandlers = {
// log from text events only to avoid duplicates // log from text events only to avoid duplicates
if (event.part?.text?.trim()) { if (event.part?.text?.trim()) {
const message = event.part.text.trim(); const message = event.part.text.trim();
log.info(
`📝 OpenCode text output: ${message.substring(0, 200)}${message.length > 200 ? "..." : ""}`
);
log.box(message, { title: "OpenCode" }); log.box(message, { title: "OpenCode" });
finalOutput = message; finalOutput = message;
} }
@@ -221,45 +228,46 @@ const messageHandlers = {
} }
}, },
tool_use: (event: OpenCodeToolUseEvent) => { tool_use: (event: OpenCodeToolUseEvent) => {
if (event.tool_name && event.tool_id) { const toolName = event.part?.tool;
toolCallTimings.set(event.tool_id, Date.now()); const toolId = event.part?.callID;
const paramsStr = event.parameters const parameters = event.part?.state?.input;
? JSON.stringify(event.parameters).substring(0, 500) const status = event.part?.state?.status;
: "{}"; const output = event.part?.state?.output;
const stepContext = currentStepId
? ` (step=${currentStepType || "unknown"}, stepId=${currentStepId.substring(0, 20)}...)`
: "";
log.info(`🔧 OpenCode tool_use: ${event.tool_name}${stepContext}, id=${event.tool_id}`);
log.info(` Parameters: ${paramsStr}${paramsStr.length >= 500 ? "..." : ""}`);
if (toolName && toolId) {
// track tool call in current step // track tool call in current step
if (stepHistory.length > 0) { if (stepHistory.length > 0) {
stepHistory[stepHistory.length - 1].toolCalls.push(event.tool_name); stepHistory[stepHistory.length - 1].toolCalls.push(toolName);
} }
log.toolCall({ log.toolCall({
toolName: event.tool_name, toolName,
input: event.parameters || {}, input: parameters || {},
}); });
// if tool already completed (status in same event), log output
if (status === "completed" && output) {
log.debug(` output: ${output}`);
}
} }
}, },
tool_result: (event: OpenCodeToolResultEvent) => { tool_result: (event: OpenCodeToolResultEvent) => {
if (event.tool_id) { // handle both new part structure and legacy flat structure
const toolStartTime = toolCallTimings.get(event.tool_id); const toolId = event.part?.callID || event.tool_id;
const status = event.part?.state?.status || event.status || "unknown";
const output = event.part?.state?.output || event.output;
if (toolId) {
const toolStartTime = toolCallTimings.get(toolId);
if (toolStartTime) { if (toolStartTime) {
const toolDuration = Date.now() - toolStartTime; const toolDuration = Date.now() - toolStartTime;
toolCallTimings.delete(event.tool_id); toolCallTimings.delete(toolId);
const status = event.status || "unknown";
const stepContext = currentStepId ? ` (step=${currentStepType || "unknown"})` : ""; const stepContext = currentStepId ? ` (step=${currentStepType || "unknown"})` : "";
const outputPreview =
typeof event.output === "string"
? event.output.substring(0, 500)
: JSON.stringify(event.output).substring(0, 500);
log.info( log.info(
`🔧 OpenCode tool_result${stepContext}: id=${event.tool_id}, status=${status}, duration=${toolDuration}ms` `🔧 OpenCode tool_result${stepContext}: id=${toolId}, status=${status}, duration=${toolDuration}ms`
); );
if (outputPreview && outputPreview !== "{}" && outputPreview !== "null") { if (output) {
log.info(` Output: ${outputPreview}${outputPreview.length >= 500 ? "..." : ""}`); log.debug(` output: ${typeof output === "string" ? output : JSON.stringify(output)}`);
} }
if (toolDuration > 5000) { if (toolDuration > 5000) {
log.warning( log.warning(
@@ -268,9 +276,8 @@ const messageHandlers = {
} }
} }
} }
if (event.status === "error") { if (status === "error") {
const errorMsg = const errorMsg = typeof output === "string" ? output : JSON.stringify(output);
typeof event.output === "string" ? event.output : JSON.stringify(event.output);
log.warning(`❌ Tool call failed: ${errorMsg}`); log.warning(`❌ Tool call failed: ${errorMsg}`);
} }
}, },
@@ -362,6 +369,14 @@ export const opencode = agent({
log.info(`🚀 Starting OpenCode CLI: ${cliPath} ${args.join(" ")}`); log.info(`🚀 Starting OpenCode CLI: ${cliPath} ${args.join(" ")}`);
log.info(`📁 Working directory: ${repoDir}`); log.info(`📁 Working directory: ${repoDir}`);
log.info(`🏠 HOME env var: ${env.HOME}`);
log.info(`📋 Config directory: ${join(env.HOME!, ".config", "opencode")}`);
// log key env vars (not values for security)
const envKeys = Object.keys(env).filter(
(k) => !k.includes("KEY") && !k.includes("TOKEN") && !k.includes("SECRET")
);
log.info(`🔑 Environment keys (non-sensitive): ${envKeys.join(", ")}`);
const startTime = Date.now(); const startTime = Date.now();
let lastActivityTime = startTime; let lastActivityTime = startTime;
let eventCount = 0; let eventCount = 0;
@@ -375,7 +390,7 @@ export const opencode = agent({
timeout: 600000, // 10 minutes timeout to prevent infinite hangs timeout: 600000, // 10 minutes timeout to prevent infinite hangs
stdio: ["ignore", "pipe", "pipe"], stdio: ["ignore", "pipe", "pipe"],
onStdout: async (chunk) => { onStdout: async (chunk) => {
log.debug(`[opencode stdout] ${chunk}`); log.debug(JSON.stringify(JSON.parse(chunk), null, 2));
const text = chunk.toString(); const text = chunk.toString();
output += text; output += text;
@@ -406,23 +421,10 @@ export const opencode = agent({
if (handler) { if (handler) {
await handler(event as never); await handler(event as never);
} else { } else {
// log unhandled event types for visibility (but don't spam) // log unhandled event types for visibility
if ( log.info(
event.type && `📋 OpenCode event (unhandled): type=${event.type}, data=${JSON.stringify(event).substring(0, 500)}`
![ );
"init",
"message",
"text",
"step_start",
"step_finish",
"tool_use",
"tool_result",
"result",
"error",
].includes(event.type)
) {
log.debug(`📋 OpenCode event (unhandled): type=${event.type}`);
}
} }
} catch { } catch {
// non-JSON lines are ignored // non-JSON lines are ignored
@@ -430,6 +432,7 @@ export const opencode = agent({
} }
}, },
onStderr: (chunk) => { onStderr: (chunk) => {
log.debug(JSON.stringify(JSON.parse(chunk), null, 2));
const trimmed = chunk.trim(); const trimmed = chunk.trim();
if (trimmed) { if (trimmed) {
log.warning(trimmed); log.warning(trimmed);
@@ -517,8 +520,10 @@ function configureOpenCodeMcpServers({
config.mcp = opencodeMcpServers; config.mcp = opencodeMcpServers;
writeFileSync(configPath, JSON.stringify(config, null, 2), "utf-8"); const configJson = JSON.stringify(config, null, 2);
writeFileSync(configPath, configJson, "utf-8");
log.info(`MCP config written to ${configPath}`); log.info(`MCP config written to ${configPath}`);
log.info(`MCP config contents:\n${configJson}`);
} }
/** /**