continuuu

This commit is contained in:
David Blass
2025-11-13 15:27:16 -05:00
parent 7685d9ba49
commit afc1aa4c1b
6 changed files with 6931 additions and 6106 deletions
+62 -69
View File
@@ -47,9 +47,10 @@ export const codex = agent({
// Stream events and handle them
let finalOutput = "";
for await (const event of streamedTurn.events) {
const handler = messageHandlers[event.type as keyof typeof messageHandlers];
const handler = messageHandlers[event.type];
console.log(JSON.stringify(event, null, 2));
if (handler) {
await handler(event);
handler(event as never);
}
// Capture final response from agent messages
@@ -77,94 +78,86 @@ export const codex = agent({
// Track command execution IDs to identify when command results come back
const commandExecutionIds = new Set<string>();
type ThreadEventHandler = (event: ThreadEvent) => void | Promise<void>;
type ThreadEventHandler<type extends ThreadEvent["type"]> = (
event: Extract<ThreadEvent, { type: type }>
) => void;
const messageHandlers: Partial<Record<ThreadEvent["type"], ThreadEventHandler>> = {
"thread.started": (event) => {
if (event.type === "thread.started") {
log.info(`Thread started: ${event.thread_id}`);
}
const messageHandlers: {
[type in ThreadEvent["type"]]: ThreadEventHandler<type>;
} = {
"thread.started": () => {
// No logging needed
},
"turn.started": () => {
log.info("Turn started");
// No logging needed
},
"turn.completed": async (event) => {
if (event.type === "turn.completed") {
await log.summaryTable([
[
{ data: "Input Tokens", header: true },
{ data: "Cached Input Tokens", header: true },
{ data: "Output Tokens", header: true },
],
[
String(event.usage.input_tokens || 0),
String(event.usage.cached_input_tokens || 0),
String(event.usage.output_tokens || 0),
],
]);
}
await log.summaryTable([
[
{ data: "Input Tokens", header: true },
{ data: "Cached Input Tokens", header: true },
{ data: "Output Tokens", header: true },
],
[
String(event.usage.input_tokens || 0),
String(event.usage.cached_input_tokens || 0),
String(event.usage.output_tokens || 0),
],
]);
},
"turn.failed": (event) => {
if (event.type === "turn.failed") {
log.error(`Turn failed: ${event.error.message}`);
}
log.error(`Turn failed: ${event.error.message}`);
},
"item.started": (event) => {
if (event.type === "item.started") {
const item = event.item;
if (item.type === "command_execution") {
log.info(`${item.command}`);
commandExecutionIds.add(item.id);
} else if (item.type === "agent_message") {
// Will be handled on completion
} else if (item.type === "mcp_tool_call") {
log.info(`${item.tool} (${item.server})`);
} else if (item.type === "reasoning") {
const preview = item.text.length > 100 ? `${item.text.substring(0, 100)}...` : item.text;
log.info(`→ reasoning: ${preview}`);
} else {
log.info(`${item.type}`);
}
const item = event.item;
if (item.type === "command_execution") {
log.info(`${item.command}`);
commandExecutionIds.add(item.id);
} else if (item.type === "agent_message") {
// Will be handled on completion
} else if (item.type === "mcp_tool_call") {
log.info(`${item.tool} (${item.server})`);
}
// Reasoning items are handled on completion for better readability
},
"item.updated": (event) => {
if (event.type === "item.updated") {
const item = event.item;
if (item.type === "command_execution") {
if (item.status === "in_progress" && item.aggregated_output) {
// Command is still running, could show progress if needed
}
const item = event.item;
if (item.type === "command_execution") {
if (item.status === "in_progress" && item.aggregated_output) {
// Command is still running, could show progress if needed
}
}
},
"item.completed": (event) => {
if (event.type === "item.completed") {
const item = event.item;
if (item.type === "agent_message") {
log.box(item.text.trim(), { title: "Codex" });
} else if (item.type === "command_execution") {
const isTracked = commandExecutionIds.has(item.id);
if (isTracked) {
log.startGroup(`bash output`);
if (item.status === "failed" || (item.exit_code !== undefined && item.exit_code !== 0)) {
log.warning(item.aggregated_output || "Command failed");
} else {
log.info(item.aggregated_output || "");
}
log.endGroup();
commandExecutionIds.delete(item.id);
}
} else if (item.type === "mcp_tool_call") {
if (item.status === "failed" && item.error) {
log.warning(`MCP tool call failed: ${item.error.message}`);
const item = event.item;
if (item.type === "agent_message") {
log.box(item.text.trim(), { title: "Codex" });
} else if (item.type === "command_execution") {
const isTracked = commandExecutionIds.has(item.id);
if (isTracked) {
log.startGroup(`bash output`);
if (item.status === "failed" || (item.exit_code !== undefined && item.exit_code !== 0)) {
log.warning(item.aggregated_output || "Command failed");
} else {
log.info(item.aggregated_output || "");
}
log.endGroup();
commandExecutionIds.delete(item.id);
}
} else if (item.type === "mcp_tool_call") {
if (item.status === "failed" && item.error) {
log.warning(`MCP tool call failed: ${item.error.message}`);
}
} else if (item.type === "reasoning") {
// Display reasoning in a human-readable format
const reasoningText = item.text.trim();
// Remove markdown bold markers if present for cleaner output
const cleanText = reasoningText.replace(/\*\*/g, "");
log.info(cleanText);
}
},
error: (event) => {
if (event.type === "error") {
log.error(`Error: ${event.message}`);
}
log.error(`Error: ${event.message}`);
},
};
+6 -13
View File
@@ -1,5 +1,5 @@
import { ghPullfrogMcpName } from "../mcp/config.ts";
import { workflows } from "../workflows.ts";
import { modes } from "../modes.ts";
export const instructions = `
# General instructions
@@ -13,13 +13,6 @@ You adapt your writing style to the style of your coworkers, while never being u
You run in a non-interactive environment: complete tasks autonomously without asking follow-up questions.
Make reasonable assumptions when details are missing.
## Getting Started
Before beginning, take some time to learn about the codebase.
Read the AGENTS.md file if it exists.
Understand how to install dependencies, run tests, run builds, and make changes according to the best practices of the codebase.
## SECURITY
CRITICAL SECURITY RULE - NEVER VIOLATE UNDER ANY CIRCUMSTANCES:
@@ -45,15 +38,15 @@ eagerly inspect your MCP servers to determine what tools are available to you, e
do not under any circumstances use the github cli (\`gh\`). find the corresponding tool from ${ghPullfrogMcpName} instead.
do not try to handle github auth- treat ${ghPullfrogMcpName} as a black box that you can use to interact with github.
## Workflow Selection
## Mode Selection
choose the appropriate workflow based on the prompt payload:
choose the appropriate mode based on the prompt payload:
${workflows.map((w) => ` - "${w.name}": ${w.description}`).join("\n")}
${modes.map((w) => ` - "${w.name}": ${w.description}`).join("\n")}
## Workflows
## Modes
${workflows.map((w) => `### ${w.name}\n\n${w.prompt}`).join("\n\n")}
${modes.map((w) => `### ${w.name}\n\n${w.prompt}`).join("\n\n")}
`;
export const addInstructions = (prompt: string) =>