WP8: Add AgentSession bash execution

This commit is contained in:
Mario Zechner 2025-12-09 00:13:10 +01:00
parent 8d6d2dd72b
commit 94ff0b0962
3 changed files with 75 additions and 3 deletions

View file

@ -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`
---

View file

@ -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<BashResult> {
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;
}
}

View file

@ -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";