diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 3bffd4e81..631024028 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -43,3 +43,6 @@ export type { SessionManagerDeps } from "./session-manager.js"; // Lifecycle manager — state machine + reaction engine export { createLifecycleManager } from "./lifecycle-manager.js"; export type { LifecycleManagerDeps } from "./lifecycle-manager.js"; + +// Shared utilities +export { shellEscape } from "./utils.js"; diff --git a/packages/core/src/utils.ts b/packages/core/src/utils.ts new file mode 100644 index 000000000..7724829d9 --- /dev/null +++ b/packages/core/src/utils.ts @@ -0,0 +1,13 @@ +/** + * Shared utility functions for agent-orchestrator plugins. + */ + +/** + * POSIX-safe shell escaping: wraps value in single quotes, + * escaping any embedded single quotes as '\\'' . + * + * Safe for use in both `sh -c` and `execFile` contexts. + */ +export function shellEscape(arg: string): string { + return "'" + arg.replace(/'/g, "'\\''") + "'"; +} diff --git a/packages/plugins/agent-aider/src/index.ts b/packages/plugins/agent-aider/src/index.ts index 207fd46b9..64d4619fe 100644 --- a/packages/plugins/agent-aider/src/index.ts +++ b/packages/plugins/agent-aider/src/index.ts @@ -1,11 +1,12 @@ -import type { - Agent, - AgentIntrospection, - AgentLaunchConfig, - ActivityState, - PluginModule, - RuntimeHandle, - Session, +import { + shellEscape, + type Agent, + type AgentIntrospection, + type AgentLaunchConfig, + type ActivityState, + type PluginModule, + type RuntimeHandle, + type Session, } from "@agent-orchestrator/core"; import { execFile } from "node:child_process"; import { promisify } from "node:util"; @@ -27,14 +28,6 @@ export const manifest = { // Agent Implementation // ============================================================================= -/** - * POSIX-safe shell escaping: wraps value in single quotes, - * escaping any embedded single quotes as '\'' . - */ -function shellEscape(arg: string): string { - return "'" + arg.replace(/'/g, "'\\''") + "'"; -} - function createAiderAgent(): Agent { return { name: "aider", diff --git a/packages/plugins/agent-claude-code/src/index.ts b/packages/plugins/agent-claude-code/src/index.ts index 08c100296..34b528750 100644 --- a/packages/plugins/agent-claude-code/src/index.ts +++ b/packages/plugins/agent-claude-code/src/index.ts @@ -1,12 +1,13 @@ -import type { - Agent, - AgentIntrospection, - AgentLaunchConfig, - ActivityState, - CostEstimate, - PluginModule, - RuntimeHandle, - Session, +import { + shellEscape, + type Agent, + type AgentIntrospection, + type AgentLaunchConfig, + type ActivityState, + type CostEstimate, + type PluginModule, + type RuntimeHandle, + type Session, } from "@agent-orchestrator/core"; import { execFile } from "node:child_process"; import { readdir, readFile, stat } from "node:fs/promises"; @@ -197,18 +198,6 @@ function extractCost(lines: JsonlLine[]): CostEstimate | undefined { return { inputTokens, outputTokens, estimatedCostUsd: totalCost }; } -// ============================================================================= -// Shell Escaping -// ============================================================================= - -/** - * POSIX-safe shell escaping: wraps value in single quotes, - * escaping any embedded single quotes as '\'' . - */ -function shellEscape(arg: string): string { - return "'" + arg.replace(/'/g, "'\\''") + "'"; -} - // ============================================================================= // Activity Detection Patterns // ============================================================================= diff --git a/packages/plugins/agent-codex/src/index.ts b/packages/plugins/agent-codex/src/index.ts index 6a2bc4c51..5a0a38a76 100644 --- a/packages/plugins/agent-codex/src/index.ts +++ b/packages/plugins/agent-codex/src/index.ts @@ -1,11 +1,12 @@ -import type { - Agent, - AgentIntrospection, - AgentLaunchConfig, - ActivityState, - PluginModule, - RuntimeHandle, - Session, +import { + shellEscape, + type Agent, + type AgentIntrospection, + type AgentLaunchConfig, + type ActivityState, + type PluginModule, + type RuntimeHandle, + type Session, } from "@agent-orchestrator/core"; import { execFile } from "node:child_process"; import { promisify } from "node:util"; @@ -27,14 +28,6 @@ export const manifest = { // Agent Implementation // ============================================================================= -/** - * POSIX-safe shell escaping: wraps value in single quotes, - * escaping any embedded single quotes as '\'' . - */ -function shellEscape(arg: string): string { - return "'" + arg.replace(/'/g, "'\\''") + "'"; -} - function createCodexAgent(): Agent { return { name: "codex",