mirror of
https://github.com/getcompanion-ai/co-mono.git
synced 2026-04-19 20:00:41 +00:00
feat(coding-agent): add user_bash event and theme API extensions
- user_bash event for intercepting ! and !! commands (#528) - Extensions can return { operations } or { result } to redirect/replace - executeBashWithOperations() for custom BashOperations execution - session.recordBashResult() for extensions handling bash themselves - Theme API: getAllThemes(), getTheme(), setTheme() on ctx.ui - mac-system-theme.ts example: sync with macOS dark/light mode - Updated ssh.ts to use user_bash event
This commit is contained in:
parent
16e142ef7d
commit
121823c74d
14 changed files with 405 additions and 36 deletions
|
|
@ -24,7 +24,7 @@ import type {
|
|||
import type { AssistantMessage, ImageContent, Message, Model, TextContent } from "@mariozechner/pi-ai";
|
||||
import { isContextOverflow, modelsAreEqual, supportsXhigh } from "@mariozechner/pi-ai";
|
||||
import { getAuthPath } from "../config.js";
|
||||
import { type BashResult, executeBash as executeBashCommand } from "./bash-executor.js";
|
||||
import { type BashResult, executeBash as executeBashCommand, executeBashWithOperations } from "./bash-executor.js";
|
||||
import {
|
||||
type CompactionResult,
|
||||
calculateContextTokens,
|
||||
|
|
@ -50,6 +50,7 @@ import type { ModelRegistry } from "./model-registry.js";
|
|||
import { expandPromptTemplate, type PromptTemplate } from "./prompt-templates.js";
|
||||
import type { BranchSummaryEntry, CompactionEntry, NewSessionOptions, SessionManager } from "./session-manager.js";
|
||||
import type { SettingsManager, SkillsSettings } from "./settings-manager.js";
|
||||
import type { BashOperations } from "./tools/bash.js";
|
||||
|
||||
/** Session-specific events that extend the core AgentEvent */
|
||||
export type AgentSessionEvent =
|
||||
|
|
@ -1617,51 +1618,63 @@ export class AgentSession {
|
|||
* @param command The bash command to execute
|
||||
* @param onChunk Optional streaming callback for output
|
||||
* @param options.excludeFromContext If true, command output won't be sent to LLM (!! prefix)
|
||||
* @param options.operations Custom BashOperations for remote execution
|
||||
*/
|
||||
async executeBash(
|
||||
command: string,
|
||||
onChunk?: (chunk: string) => void,
|
||||
options?: { excludeFromContext?: boolean },
|
||||
options?: { excludeFromContext?: boolean; operations?: BashOperations },
|
||||
): 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(),
|
||||
excludeFromContext: options?.excludeFromContext,
|
||||
};
|
||||
|
||||
// If agent is streaming, defer adding to avoid breaking tool_use/tool_result ordering
|
||||
if (this.isStreaming) {
|
||||
// Queue for later - will be flushed on agent_end
|
||||
this._pendingBashMessages.push(bashMessage);
|
||||
} else {
|
||||
// Add to agent state immediately
|
||||
this.agent.appendMessage(bashMessage);
|
||||
|
||||
// Save to session
|
||||
this.sessionManager.appendMessage(bashMessage);
|
||||
}
|
||||
const result = options?.operations
|
||||
? await executeBashWithOperations(command, process.cwd(), options.operations, {
|
||||
onChunk,
|
||||
signal: this._bashAbortController.signal,
|
||||
})
|
||||
: await executeBashCommand(command, {
|
||||
onChunk,
|
||||
signal: this._bashAbortController.signal,
|
||||
});
|
||||
|
||||
this.recordBashResult(command, result, options);
|
||||
return result;
|
||||
} finally {
|
||||
this._bashAbortController = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Record a bash execution result in session history.
|
||||
* Used by executeBash and by extensions that handle bash execution themselves.
|
||||
*/
|
||||
recordBashResult(command: string, result: BashResult, options?: { excludeFromContext?: boolean }): void {
|
||||
const bashMessage: BashExecutionMessage = {
|
||||
role: "bashExecution",
|
||||
command,
|
||||
output: result.output,
|
||||
exitCode: result.exitCode,
|
||||
cancelled: result.cancelled,
|
||||
truncated: result.truncated,
|
||||
fullOutputPath: result.fullOutputPath,
|
||||
timestamp: Date.now(),
|
||||
excludeFromContext: options?.excludeFromContext,
|
||||
};
|
||||
|
||||
// If agent is streaming, defer adding to avoid breaking tool_use/tool_result ordering
|
||||
if (this.isStreaming) {
|
||||
// Queue for later - will be flushed on agent_end
|
||||
this._pendingBashMessages.push(bashMessage);
|
||||
} else {
|
||||
// Add to agent state immediately
|
||||
this.agent.appendMessage(bashMessage);
|
||||
|
||||
// Save to session
|
||||
this.sessionManager.appendMessage(bashMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Cancel running bash command.
|
||||
*/
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue