tool call logging, centralized temp dir

This commit is contained in:
David Blass
2025-11-19 18:26:15 -05:00
parent 4b43b617f0
commit 7e0dcd5374
13 changed files with 781 additions and 354 deletions
+133 -46
View File
@@ -97759,10 +97759,6 @@ var schema = ark.schema;
var define2 = ark.define;
var declare = ark.declare;
// mcp/shared.ts
import { appendFileSync } from "node:fs";
import { join } from "node:path";
// node_modules/.pnpm/universal-user-agent@7.0.3/node_modules/universal-user-agent/index.js
function getUserAgent() {
if (typeof navigator === "object" && "userAgent" in navigator) {
@@ -101186,11 +101182,10 @@ var Octokit2 = Octokit.plugin(requestLog, legacyRestEndpointMethods, paginateRes
}
);
// utils/github.ts
var core2 = __toESM(require_core(), 1);
// utils/cli.ts
var core = __toESM(require_core(), 1);
import { appendFileSync, existsSync } from "node:fs";
import { join } from "node:path";
var isGitHubActions = !!process.env.GITHUB_ACTIONS;
var isDebugEnabled = process.env.LOG_LEVEL === "debug";
function startGroup2(name) {
@@ -101386,10 +101381,85 @@ var log = {
/**
* End a collapsed group
*/
endGroup: endGroup2
endGroup: endGroup2,
/**
* Log MCP tool call information to mcpLog.txt in the temp directory
*/
toolCall: ({
toolName,
request: request2,
result,
error: error41
}) => {
const logPath = getMcpLogPath();
const params = { toolName, request: request2 };
if (error41) {
params.error = error41;
} else if (result) {
params.result = result;
}
const logEntry = formatToolCall(params);
appendFileSync(logPath, logEntry, "utf-8");
}
};
function getMcpLogPath() {
const tempDir = process.env.PULLFROG_TEMP_DIR;
return join(tempDir, "mcpLog.txt");
}
function formatJsonValue(value2) {
const compact = JSON.stringify(value2);
return compact.length > 80 || compact.includes("\n") ? JSON.stringify(value2, null, 2) : compact;
}
function formatIndentedField(label, content) {
if (!content.includes("\n")) {
return ` ${label}: ${content}
`;
}
const lines = content.split("\n");
let formatted = ` ${label}: ${lines[0]}
`;
for (let i = 1; i < lines.length; i++) {
formatted += ` ${lines[i]}
`;
}
return formatted;
}
function formatToolInput(request2) {
const requestFormatted = formatJsonValue(request2);
if (requestFormatted === "{}") {
return "";
}
return formatIndentedField("input", requestFormatted);
}
function formatToolResult(result) {
try {
const parsed2 = JSON.parse(result);
const formatted = formatJsonValue(parsed2);
return formatIndentedField("result", formatted);
} catch {
return formatIndentedField("result", result);
}
}
function formatToolCall({
toolName,
request: request2,
result,
error: error41
}) {
let logEntry = `\u2192 ${toolName}
`;
logEntry += formatToolInput(request2);
if (error41) {
logEntry += formatIndentedField("error", error41);
} else if (result) {
logEntry += formatToolResult(result);
}
logEntry += "\n";
return logEntry;
}
// utils/github.ts
var core2 = __toESM(require_core(), 1);
function parseRepoContext() {
const githubRepo = process.env.GITHUB_REPOSITORY;
if (!githubRepo) {
@@ -101415,53 +101485,25 @@ var getMcpContext = cached2(() => {
})
};
});
function getLogPath() {
return join(process.cwd(), "log.txt");
}
function logToolCall({
toolName,
request: request2,
error: error41,
success
}) {
const logPath = getLogPath();
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
const requestStr = JSON.stringify(request2, null, 2);
let logEntry = `[${timestamp}] Tool: ${toolName}
Request: ${requestStr}
`;
if (error41) {
const errorMessage = error41 instanceof Error ? error41.message : String(error41);
const errorStack = error41 instanceof Error ? error41.stack : void 0;
logEntry += `Error: ${errorMessage}
`;
if (errorStack) {
logEntry += `Stack: ${errorStack}
`;
}
logEntry += `Status: FAILED
`;
} else if (success !== void 0) {
logEntry += `Status: ${success ? "SUCCESS" : "FAILED"}
`;
}
logEntry += `${"=".repeat(80)}
`;
appendFileSync(logPath, logEntry, "utf-8");
}
var tool = (toolDef) => {
const toolName = toolDef.name;
const originalExecute = toolDef.execute;
toolDef.execute = async (args2, context) => {
try {
logToolCall({ toolName, request: args2 });
const result = await originalExecute(args2, context);
const isError = result && typeof result === "object" && "isError" in result && result.isError === true;
logToolCall({ toolName, request: args2, success: !isError });
const resultData = result && typeof result === "object" && "content" in result ? result.content[0]?.text : void 0;
if (isError && resultData) {
log.toolCall({ toolName, request: args2, error: resultData });
} else if (resultData) {
log.toolCall({ toolName, request: args2, result: resultData });
} else {
log.toolCall({ toolName, request: args2 });
}
return result;
} catch (error41) {
logToolCall({ toolName, request: args2, error: error41 });
const errorMessage = error41 instanceof Error ? error41.message : String(error41);
log.toolCall({ toolName, request: args2, error: errorMessage });
throw error41;
}
};
@@ -101786,12 +101828,57 @@ var ReviewTool = tool({
})
});
// mcp/selectMode.ts
function getModes() {
const modesJson = process.env.PULLFROG_MODES;
if (modesJson) {
try {
return JSON.parse(modesJson);
} catch {
return [];
}
}
return [];
}
var SelectMode = type({
modeName: type.string.describe(
"the name of the mode to select (e.g., 'Plan', 'Build', 'Review', 'Prompt')"
)
});
var SelectModeTool = tool({
name: "select_mode",
description: "Select a mode and get its detailed prompt instructions. Call this first to determine which mode to use based on the request.",
parameters: SelectMode,
execute: contextualize(async ({ modeName }) => {
const allModes = getModes();
if (allModes.length === 0) {
return {
error: "No modes available. Modes must be provided via PULLFROG_MODES environment variable."
};
}
const selectedMode = allModes.find((m) => m.name.toLowerCase() === modeName.toLowerCase());
if (!selectedMode) {
const availableModes = allModes.map((m) => m.name).join(", ");
return {
error: `Mode "${modeName}" not found. Available modes: ${availableModes}`,
availableModes: allModes.map((m) => ({ name: m.name, description: m.description }))
};
}
return {
modeName: selectedMode.name,
description: selectedMode.description,
prompt: selectedMode.prompt
};
})
});
// mcp/server.ts
var server = new FastMCP({
name: "gh-pullfrog",
version: "0.0.1"
});
addTools(server, [
SelectModeTool,
CreateCommentTool,
EditCommentTool,
CreateWorkingCommentTool,