From 94ff0b0962c79925a79f57023fc80aadabea963d Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Tue, 9 Dec 2025 00:13:10 +0100 Subject: [PATCH] WP8: Add AgentSession bash execution --- packages/coding-agent/docs/refactor.md | 4 +- .../coding-agent/src/core/agent-session.ts | 65 +++++++++++++++++++ packages/coding-agent/src/core/index.ts | 9 ++- 3 files changed, 75 insertions(+), 3 deletions(-) diff --git a/packages/coding-agent/docs/refactor.md b/packages/coding-agent/docs/refactor.md index 5194e32f..4f7ce79e 100644 --- a/packages/coding-agent/docs/refactor.md +++ b/packages/coding-agent/docs/refactor.md @@ -888,8 +888,8 @@ get isBashRunning(): boolean { **Verification:** 1. `npm run check` passes -- [ ] Add bash execution methods using bash-executor module -- [ ] Verify with `npm run check` +- [x] Add bash execution methods using bash-executor module +- [x] Verify with `npm run check` --- diff --git a/packages/coding-agent/src/core/agent-session.ts b/packages/coding-agent/src/core/agent-session.ts index 6846dbfa..8d60b905 100644 --- a/packages/coding-agent/src/core/agent-session.ts +++ b/packages/coding-agent/src/core/agent-session.ts @@ -17,10 +17,12 @@ import type { Agent, AgentEvent, AgentState, AppMessage, Attachment, ThinkingLev import type { AssistantMessage, Model } from "@mariozechner/pi-ai"; import { calculateContextTokens, compact, shouldCompact } from "../compaction.js"; import { getModelsPath } from "../config.js"; +import type { BashExecutionMessage } from "../messages.js"; import { getApiKeyForModel, getAvailableModels } from "../model-config.js"; import { loadSessionFromEntries, type SessionManager } from "../session-manager.js"; import type { SettingsManager } from "../settings-manager.js"; import { expandSlashCommand, type FileSlashCommand } from "../slash-commands.js"; +import { type BashResult, executeBash as executeBashCommand } from "./bash-executor.js"; /** Listener function for agent events */ export type AgentEventListener = (event: AgentEvent) => void; @@ -83,6 +85,9 @@ export class AgentSession { // Compaction state private _compactionAbortController: AbortController | null = null; + // Bash execution state + private _bashAbortController: AbortController | null = null; + constructor(config: AgentSessionConfig) { this.agent = config.agent; this.sessionManager = config.sessionManager; @@ -616,4 +621,64 @@ export class AgentSession { get autoCompactionEnabled(): boolean { return this.settingsManager.getCompactionEnabled(); } + + // ========================================================================= + // Bash Execution + // ========================================================================= + + /** + * Execute a bash command. + * Adds result to agent context and session. + * @param command The bash command to execute + * @param onChunk Optional streaming callback for output + */ + async executeBash(command: string, onChunk?: (chunk: string) => void): Promise { + this._bashAbortController = new AbortController(); + + try { + const result = await executeBashCommand(command, { + onChunk, + signal: this._bashAbortController.signal, + }); + + // Create and save message + const bashMessage: BashExecutionMessage = { + role: "bashExecution", + command, + output: result.output, + exitCode: result.exitCode, + cancelled: result.cancelled, + truncated: result.truncated, + fullOutputPath: result.fullOutputPath, + timestamp: Date.now(), + }; + + // Add to agent state + this.agent.appendMessage(bashMessage); + + // Save to session + this.sessionManager.saveMessage(bashMessage); + + // Initialize session if needed + if (this.sessionManager.shouldInitializeSession(this.agent.state.messages)) { + this.sessionManager.startSession(this.agent.state); + } + + return result; + } finally { + this._bashAbortController = null; + } + } + + /** + * Cancel running bash command. + */ + abortBash(): void { + this._bashAbortController?.abort(); + } + + /** Whether a bash command is currently running */ + get isBashRunning(): boolean { + return this._bashAbortController !== null; + } } diff --git a/packages/coding-agent/src/core/index.ts b/packages/coding-agent/src/core/index.ts index 82f4cb2a..ca42285d 100644 --- a/packages/coding-agent/src/core/index.ts +++ b/packages/coding-agent/src/core/index.ts @@ -2,5 +2,12 @@ * Core modules shared between all run modes. */ -export { AgentSession, type AgentSessionConfig } from "./agent-session.js"; +export { + type AgentEventListener, + AgentSession, + type AgentSessionConfig, + type CompactionResult, + type ModelCycleResult, + type PromptOptions, +} from "./agent-session.js"; export { type BashExecutorOptions, type BashResult, executeBash } from "./bash-executor.js";