diff --git a/entry b/entry index 098efa7..e109205 100755 --- a/entry +++ b/entry @@ -135589,6 +135589,7 @@ var Effort = type.enumerated("mini", "auto", "max"); // utils/log.ts var core = __toESM(require_core(), 1); var import_table = __toESM(require_src(), 1); +import { AsyncLocalStorage } from "node:async_hooks"; // utils/globals.ts import { existsSync } from "node:fs"; @@ -135597,6 +135598,23 @@ var isGitHubActions = !!process.env.GITHUB_ACTIONS; var isInsideDocker = existsSync("/.dockerenv"); // utils/log.ts +var logContext = new AsyncLocalStorage(); +var MAGENTA = "\x1B[35m"; +var RESET = "\x1B[0m"; +function withLogPrefix(prefix, fn2) { + return logContext.run({ prefix }, fn2); +} +function prefixLines(message) { + const ctx = logContext.getStore(); + if (!ctx) return message; + const colored = `${MAGENTA}${ctx.prefix}${RESET} `; + return message.split("\n").map((line) => `${colored}${line}`).join("\n"); +} +function prefixPlain(name) { + const ctx = logContext.getStore(); + if (!ctx) return name; + return `${ctx.prefix} ${name}`; +} var isRunnerDebugEnabled = () => core.isDebug(); var isLocalDebugEnabled = () => process.env.LOG_LEVEL === "debug" || process.env.ACTIONS_STEP_DEBUG === "true"; var isDebugEnabled = () => isLocalDebugEnabled() || isRunnerDebugEnabled(); @@ -135612,10 +135630,11 @@ ${arg.stack}`; }).join(" "); } function startGroup2(name) { + const prefixed = prefixPlain(name); if (isGitHubActions) { - core.startGroup(name); + core.startGroup(prefixed); } else { - console.group(name); + console.group(prefixed); } } function endGroup2() { @@ -135688,7 +135707,7 @@ function boxString(text, options) { } function box(text, options) { const boxContent = boxString(text, options); - core.info(boxContent); + core.info(prefixLines(boxContent)); } async function writeSummary(text) { if (!isGitHubActions) return; @@ -135708,42 +135727,42 @@ function printTable(rows, options) { ); const formatted = (0, import_table.table)(tableData); if (title) { - core.info(` -${title}`); + core.info(prefixLines(` +${title}`)); } - core.info(` + core.info(prefixLines(` ${formatted} -`); +`)); } function separator(length = 50) { const separatorText = "\u2500".repeat(length); - core.info(separatorText); + core.info(prefixLines(separatorText)); } var log = { /** Print info message */ info: (...args2) => { - core.info(`${ts()}${formatArgs(args2)}`); + core.info(prefixLines(`${ts()}${formatArgs(args2)}`)); }, /** Print a warning message. Use only for warnings that should be displayed in the job summary. */ warning: (...args2) => { - core.warning(`${ts()}${formatArgs(args2)}`); + core.warning(prefixLines(`${ts()}${formatArgs(args2)}`)); }, /** Print an error message. Use only for errors that should be displayed in the job summary. */ error: (...args2) => { - core.error(`${ts()}${formatArgs(args2)}`); + core.error(prefixLines(`${ts()}${formatArgs(args2)}`)); }, /** Print success message */ success: (...args2) => { - core.info(`${ts()}\xBB ${formatArgs(args2)}`); + core.info(prefixLines(`${ts()}\xBB ${formatArgs(args2)}`)); }, /** Print debug message (only when debug mode is enabled) */ debug: (...args2) => { if (isRunnerDebugEnabled()) { - core.debug(formatArgs(args2)); + core.debug(prefixLines(formatArgs(args2))); return; } if (isLocalDebugEnabled()) { - core.info(`${ts()}[DEBUG] ${formatArgs(args2)}`); + core.info(prefixLines(`${ts()}[DEBUG] ${formatArgs(args2)}`)); } }, /** Print a formatted box with text */ @@ -136443,41 +136462,43 @@ ${params.instructions}`; }; } async function runSubagent(params) { - params.subagent.keepAliveInterval = setInterval(markActivity, 3e4); - const mcpServer = await startSubagentMcpServer({ - ctx: params.ctx, - subagentId: params.subagent.id - }); - const subagentTmpdir = join(params.ctx.tmpdir, params.subagent.id); - mkdirSync(subagentTmpdir, { recursive: true }); - try { - const subagentPayload = { ...params.ctx.payload, effort: params.effort }; - const subagentInstructions = buildSubagentInstructions({ + return withLogPrefix(`[${params.subagent.label}]`, async () => { + params.subagent.keepAliveInterval = setInterval(markActivity, 3e4); + const mcpServer = await startSubagentMcpServer({ ctx: params.ctx, - label: params.subagent.label, - instructions: params.instructions + subagentId: params.subagent.id }); - const result = await params.ctx.agent.run({ - payload: subagentPayload, - mcpServerUrl: mcpServer.url, - tmpdir: subagentTmpdir, - instructions: subagentInstructions - }); - params.subagent.usage = result.usage; - writeFileSync(params.subagent.stdoutFilePath, result.output ?? "", "utf-8"); - completeSubagent({ ctx: params.ctx, subagent: params.subagent, success: result.success }); - return { success: result.success, error: result.error }; - } catch (err) { - const errorMessage = err instanceof Error ? err.message : String(err); + const subagentTmpdir = join(params.ctx.tmpdir, params.subagent.id); + mkdirSync(subagentTmpdir, { recursive: true }); try { - writeFileSync(params.subagent.stdoutFilePath, "", "utf-8"); - } catch { + const subagentPayload = { ...params.ctx.payload, effort: params.effort }; + const subagentInstructions = buildSubagentInstructions({ + ctx: params.ctx, + label: params.subagent.label, + instructions: params.instructions + }); + const result = await params.ctx.agent.run({ + payload: subagentPayload, + mcpServerUrl: mcpServer.url, + tmpdir: subagentTmpdir, + instructions: subagentInstructions + }); + params.subagent.usage = result.usage; + writeFileSync(params.subagent.stdoutFilePath, result.output ?? "", "utf-8"); + completeSubagent({ ctx: params.ctx, subagent: params.subagent, success: result.success }); + return { success: result.success, error: result.error }; + } catch (err) { + const errorMessage = err instanceof Error ? err.message : String(err); + try { + writeFileSync(params.subagent.stdoutFilePath, "", "utf-8"); + } catch { + } + completeSubagent({ ctx: params.ctx, subagent: params.subagent, success: false }); + return { success: false, error: errorMessage }; + } finally { + await mcpServer.stop(); } - completeSubagent({ ctx: params.ctx, subagent: params.subagent, success: false }); - return { success: false, error: errorMessage }; - } finally { - await mcpServer.stop(); - } + }); } // mcp/askQuestion.ts diff --git a/get-installation-token/entry b/get-installation-token/entry index 8abf8ed..a6c6070 100755 --- a/get-installation-token/entry +++ b/get-installation-token/entry @@ -25507,6 +25507,7 @@ var core3 = __toESM(require_core(), 1); // utils/log.ts var core = __toESM(require_core(), 1); var import_table = __toESM(require_src(), 1); +import { AsyncLocalStorage } from "node:async_hooks"; // utils/globals.ts import { existsSync } from "node:fs"; @@ -25515,6 +25516,20 @@ var isGitHubActions = !!process.env.GITHUB_ACTIONS; var isInsideDocker = existsSync("/.dockerenv"); // utils/log.ts +var logContext = new AsyncLocalStorage(); +var MAGENTA = "\x1B[35m"; +var RESET = "\x1B[0m"; +function prefixLines(message) { + const ctx = logContext.getStore(); + if (!ctx) return message; + const colored = `${MAGENTA}${ctx.prefix}${RESET} `; + return message.split("\n").map((line) => `${colored}${line}`).join("\n"); +} +function prefixPlain(name) { + const ctx = logContext.getStore(); + if (!ctx) return name; + return `${ctx.prefix} ${name}`; +} var isRunnerDebugEnabled = () => core.isDebug(); var isLocalDebugEnabled = () => process.env.LOG_LEVEL === "debug" || process.env.ACTIONS_STEP_DEBUG === "true"; var isDebugEnabled = () => isLocalDebugEnabled() || isRunnerDebugEnabled(); @@ -25530,10 +25545,11 @@ ${arg.stack}`; }).join(" "); } function startGroup2(name) { + const prefixed = prefixPlain(name); if (isGitHubActions) { - core.startGroup(name); + core.startGroup(prefixed); } else { - console.group(name); + console.group(prefixed); } } function endGroup2() { @@ -25606,7 +25622,7 @@ function boxString(text, options) { } function box(text, options) { const boxContent = boxString(text, options); - core.info(boxContent); + core.info(prefixLines(boxContent)); } function printTable(rows, options) { const { title } = options || {}; @@ -25620,42 +25636,42 @@ function printTable(rows, options) { ); const formatted = (0, import_table.table)(tableData); if (title) { - core.info(` -${title}`); + core.info(prefixLines(` +${title}`)); } - core.info(` + core.info(prefixLines(` ${formatted} -`); +`)); } function separator(length = 50) { const separatorText = "\u2500".repeat(length); - core.info(separatorText); + core.info(prefixLines(separatorText)); } var log = { /** Print info message */ info: (...args) => { - core.info(`${ts()}${formatArgs(args)}`); + core.info(prefixLines(`${ts()}${formatArgs(args)}`)); }, /** Print a warning message. Use only for warnings that should be displayed in the job summary. */ warning: (...args) => { - core.warning(`${ts()}${formatArgs(args)}`); + core.warning(prefixLines(`${ts()}${formatArgs(args)}`)); }, /** Print an error message. Use only for errors that should be displayed in the job summary. */ error: (...args) => { - core.error(`${ts()}${formatArgs(args)}`); + core.error(prefixLines(`${ts()}${formatArgs(args)}`)); }, /** Print success message */ success: (...args) => { - core.info(`${ts()}\xBB ${formatArgs(args)}`); + core.info(prefixLines(`${ts()}\xBB ${formatArgs(args)}`)); }, /** Print debug message (only when debug mode is enabled) */ debug: (...args) => { if (isRunnerDebugEnabled()) { - core.debug(formatArgs(args)); + core.debug(prefixLines(formatArgs(args))); return; } if (isLocalDebugEnabled()) { - core.info(`${ts()}[DEBUG] ${formatArgs(args)}`); + core.info(prefixLines(`${ts()}[DEBUG] ${formatArgs(args)}`)); } }, /** Print a formatted box with text */ diff --git a/mcp/subagent.ts b/mcp/subagent.ts index 6bb0ed9..2fa0e92 100644 --- a/mcp/subagent.ts +++ b/mcp/subagent.ts @@ -6,6 +6,7 @@ import type { Effort } from "../external.ts"; import { ghPullfrogMcpName } from "../external.ts"; import { markActivity } from "../utils/activity.ts"; import type { ResolvedInstructions } from "../utils/instructions.ts"; +import { withLogPrefix } from "../utils/log.ts"; import { type SubagentState, startSubagentMcpServer, type ToolContext } from "./server.ts"; type CreateSubagentParams = { @@ -132,41 +133,43 @@ type RunSubagentResult = { }; export async function runSubagent(params: RunSubagentParams): Promise { - params.subagent.keepAliveInterval = setInterval(markActivity, 30_000); - const mcpServer = await startSubagentMcpServer({ - ctx: params.ctx, - subagentId: params.subagent.id, - }); - // each subagent gets its own tmpdir so parallel agents don't clobber config files - const subagentTmpdir = join(params.ctx.tmpdir, params.subagent.id); - mkdirSync(subagentTmpdir, { recursive: true }); - try { - const subagentPayload = { ...params.ctx.payload, effort: params.effort }; - const subagentInstructions = buildSubagentInstructions({ + return withLogPrefix(`[${params.subagent.label}]`, async () => { + params.subagent.keepAliveInterval = setInterval(markActivity, 30_000); + const mcpServer = await startSubagentMcpServer({ ctx: params.ctx, - label: params.subagent.label, - instructions: params.instructions, + subagentId: params.subagent.id, }); - const result = await params.ctx.agent.run({ - payload: subagentPayload, - mcpServerUrl: mcpServer.url, - tmpdir: subagentTmpdir, - instructions: subagentInstructions, - }); - params.subagent.usage = result.usage; - writeFileSync(params.subagent.stdoutFilePath, result.output ?? "", "utf-8"); - completeSubagent({ ctx: params.ctx, subagent: params.subagent, success: result.success }); - return { success: result.success, error: result.error }; - } catch (err) { - const errorMessage = err instanceof Error ? err.message : String(err); + // each subagent gets its own tmpdir so parallel agents don't clobber config files + const subagentTmpdir = join(params.ctx.tmpdir, params.subagent.id); + mkdirSync(subagentTmpdir, { recursive: true }); try { - writeFileSync(params.subagent.stdoutFilePath, "", "utf-8"); - } catch { - // best-effort + const subagentPayload = { ...params.ctx.payload, effort: params.effort }; + const subagentInstructions = buildSubagentInstructions({ + ctx: params.ctx, + label: params.subagent.label, + instructions: params.instructions, + }); + const result = await params.ctx.agent.run({ + payload: subagentPayload, + mcpServerUrl: mcpServer.url, + tmpdir: subagentTmpdir, + instructions: subagentInstructions, + }); + params.subagent.usage = result.usage; + writeFileSync(params.subagent.stdoutFilePath, result.output ?? "", "utf-8"); + completeSubagent({ ctx: params.ctx, subagent: params.subagent, success: result.success }); + return { success: result.success, error: result.error }; + } catch (err) { + const errorMessage = err instanceof Error ? err.message : String(err); + try { + writeFileSync(params.subagent.stdoutFilePath, "", "utf-8"); + } catch { + // best-effort + } + completeSubagent({ ctx: params.ctx, subagent: params.subagent, success: false }); + return { success: false, error: errorMessage }; + } finally { + await mcpServer.stop(); } - completeSubagent({ ctx: params.ctx, subagent: params.subagent, success: false }); - return { success: false, error: errorMessage }; - } finally { - await mcpServer.stop(); - } + }); } diff --git a/post b/post index e474e97..e5edd39 100755 --- a/post +++ b/post @@ -28846,6 +28846,7 @@ var require_semver2 = __commonJS({ // utils/log.ts var core = __toESM(require_core(), 1); var import_table = __toESM(require_src(), 1); +import { AsyncLocalStorage } from "node:async_hooks"; // utils/globals.ts import { existsSync } from "node:fs"; @@ -28854,6 +28855,20 @@ var isGitHubActions = !!process.env.GITHUB_ACTIONS; var isInsideDocker = existsSync("/.dockerenv"); // utils/log.ts +var logContext = new AsyncLocalStorage(); +var MAGENTA = "\x1B[35m"; +var RESET = "\x1B[0m"; +function prefixLines(message) { + const ctx = logContext.getStore(); + if (!ctx) return message; + const colored = `${MAGENTA}${ctx.prefix}${RESET} `; + return message.split("\n").map((line) => `${colored}${line}`).join("\n"); +} +function prefixPlain(name) { + const ctx = logContext.getStore(); + if (!ctx) return name; + return `${ctx.prefix} ${name}`; +} var isRunnerDebugEnabled = () => core.isDebug(); var isLocalDebugEnabled = () => process.env.LOG_LEVEL === "debug" || process.env.ACTIONS_STEP_DEBUG === "true"; var isDebugEnabled = () => isLocalDebugEnabled() || isRunnerDebugEnabled(); @@ -28869,10 +28884,11 @@ ${arg.stack}`; }).join(" "); } function startGroup2(name) { + const prefixed = prefixPlain(name); if (isGitHubActions) { - core.startGroup(name); + core.startGroup(prefixed); } else { - console.group(name); + console.group(prefixed); } } function endGroup2() { @@ -28945,7 +28961,7 @@ function boxString(text, options) { } function box(text, options) { const boxContent = boxString(text, options); - core.info(boxContent); + core.info(prefixLines(boxContent)); } function printTable(rows, options) { const { title } = options || {}; @@ -28959,42 +28975,42 @@ function printTable(rows, options) { ); const formatted = (0, import_table.table)(tableData); if (title) { - core.info(` -${title}`); + core.info(prefixLines(` +${title}`)); } - core.info(` + core.info(prefixLines(` ${formatted} -`); +`)); } function separator(length = 50) { const separatorText = "\u2500".repeat(length); - core.info(separatorText); + core.info(prefixLines(separatorText)); } var log = { /** Print info message */ info: (...args2) => { - core.info(`${ts()}${formatArgs(args2)}`); + core.info(prefixLines(`${ts()}${formatArgs(args2)}`)); }, /** Print a warning message. Use only for warnings that should be displayed in the job summary. */ warning: (...args2) => { - core.warning(`${ts()}${formatArgs(args2)}`); + core.warning(prefixLines(`${ts()}${formatArgs(args2)}`)); }, /** Print an error message. Use only for errors that should be displayed in the job summary. */ error: (...args2) => { - core.error(`${ts()}${formatArgs(args2)}`); + core.error(prefixLines(`${ts()}${formatArgs(args2)}`)); }, /** Print success message */ success: (...args2) => { - core.info(`${ts()}\xBB ${formatArgs(args2)}`); + core.info(prefixLines(`${ts()}\xBB ${formatArgs(args2)}`)); }, /** Print debug message (only when debug mode is enabled) */ debug: (...args2) => { if (isRunnerDebugEnabled()) { - core.debug(formatArgs(args2)); + core.debug(prefixLines(formatArgs(args2))); return; } if (isLocalDebugEnabled()) { - core.info(`${ts()}[DEBUG] ${formatArgs(args2)}`); + core.info(prefixLines(`${ts()}[DEBUG] ${formatArgs(args2)}`)); } }, /** Print a formatted box with text */ diff --git a/utils/log.ts b/utils/log.ts index 8ce9f21..dbdccf3 100644 --- a/utils/log.ts +++ b/utils/log.ts @@ -2,11 +2,43 @@ * Logging utilities that work well in both local and GitHub Actions environments */ +import { AsyncLocalStorage } from "node:async_hooks"; import * as core from "@actions/core"; import { table } from "table"; import type { AgentUsage } from "../agents/shared.ts"; import { isGitHubActions, isInsideDocker } from "./globals.ts"; +// --- subagent log prefix via AsyncLocalStorage --- + +type LogContext = { prefix: string }; + +const logContext = new AsyncLocalStorage(); + +const MAGENTA = "\x1b[35m"; +const RESET = "\x1b[0m"; + +/** run `fn` with every log line prefixed by `prefix` (e.g. "[task-label]") in magenta */ +export function withLogPrefix(prefix: string, fn: () => Promise): Promise { + return logContext.run({ prefix }, fn); +} + +function prefixLines(message: string): string { + const ctx = logContext.getStore(); + if (!ctx) return message; + const colored = `${MAGENTA}${ctx.prefix}${RESET} `; + return message + .split("\n") + .map((line) => `${colored}${line}`) + .join("\n"); +} + +/** plain-text prefix (no ANSI) for GitHub Actions group names */ +function prefixPlain(name: string): string { + const ctx = logContext.getStore(); + if (!ctx) return name; + return `${ctx.prefix} ${name}`; +} + const isRunnerDebugEnabled = () => core.isDebug(); const isLocalDebugEnabled = () => @@ -36,10 +68,11 @@ function formatArgs(args: unknown[]): string { * Start a collapsed group (GitHub Actions) or regular group (local) */ function startGroup(name: string): void { + const prefixed = prefixPlain(name); if (isGitHubActions) { - core.startGroup(name); + core.startGroup(prefixed); } else { - console.group(name); + console.group(prefixed); } } @@ -153,7 +186,7 @@ function box( } ): void { const boxContent = boxString(text, options); - core.info(boxContent); + core.info(prefixLines(boxContent)); } /** @@ -200,9 +233,9 @@ function printTable( const formatted = table(tableData); if (title) { - core.info(`\n${title}`); + core.info(prefixLines(`\n${title}`)); } - core.info(`\n${formatted}\n`); + core.info(prefixLines(`\n${formatted}\n`)); } /** @@ -210,7 +243,7 @@ function printTable( */ function separator(length: number = 50): void { const separatorText = "─".repeat(length); - core.info(separatorText); + core.info(prefixLines(separatorText)); } /** @@ -219,32 +252,32 @@ function separator(length: number = 50): void { export const log = { /** Print info message */ info: (...args: unknown[]): void => { - core.info(`${ts()}${formatArgs(args)}`); + core.info(prefixLines(`${ts()}${formatArgs(args)}`)); }, /** Print a warning message. Use only for warnings that should be displayed in the job summary. */ warning: (...args: unknown[]): void => { - core.warning(`${ts()}${formatArgs(args)}`); + core.warning(prefixLines(`${ts()}${formatArgs(args)}`)); }, /** Print an error message. Use only for errors that should be displayed in the job summary. */ error: (...args: unknown[]): void => { - core.error(`${ts()}${formatArgs(args)}`); + core.error(prefixLines(`${ts()}${formatArgs(args)}`)); }, /** Print success message */ success: (...args: unknown[]): void => { - core.info(`${ts()}» ${formatArgs(args)}`); + core.info(prefixLines(`${ts()}» ${formatArgs(args)}`)); }, /** Print debug message (only when debug mode is enabled) */ debug: (...args: unknown[]): void => { if (isRunnerDebugEnabled()) { - core.debug(formatArgs(args)); + core.debug(prefixLines(formatArgs(args))); return; } if (isLocalDebugEnabled()) { - core.info(`${ts()}[DEBUG] ${formatArgs(args)}`); + core.info(prefixLines(`${ts()}[DEBUG] ${formatArgs(args)}`)); } },