/** * Command Handler - Parses and executes commands * * Handles command execution using the unified command system. */ import type { MessageBus } from '../../infra/bus/index.js'; import type { Config } from '../../config/schema.js'; import type { SessionConfigStore, SessionStore } from '../../session/index.js'; import type { ThinkLevel } from '../transcript/thinking-types.js'; import type { CompactionResult } from '../memory/compaction.js'; import { type BtwQueryOptions, type CommandStreamEvent } from '../../chat-commands/index.js'; import type { WorkflowRunServiceLike } from '../../workflows/service/workflow-run-service.types.js'; import type { SkillInstallToolOptions, SkillInstallToolResult } from '../tools/skill-install-tool.js'; export interface CommandContext { sessionKey: string; channel: string; chatId: string; senderId: string; isGroup: boolean; /** From inbound message metadata (thread/account, etc.) for continuation routing. */ inboundMetadata?: Record; } export interface CommandHandlerConfig { config: Config; bus: MessageBus; sessionStore: SessionStore; sessionConfigStore?: SessionConfigStore; /** After /think persists, sync pi-agent */ applySessionThinkingLevel?: (sessionKey: string, level: ThinkLevel) => void; getCurrentModel: () => string; switchModelForSession: (sessionKey: string, modelId: string) => Promise; /** Drop in-memory agent after session file is cleared (e.g. /new) */ invalidateAgentSession?: (sessionKey: string) => void; /** Reset session in place (archive transcript, new session id; preserve overrides) */ resetSession?: (sessionKey: string) => Promise<{ sessionId: string; previousSessionId: string; } | null>; /** Cancel streaming preview + in-flight LLM work for this session (e.g. /abort) */ abortSessionTurn?: (sessionKey: string) => Promise; /** Reload skills from disk and refresh active agent prompts. */ reloadSkills?: () => void | Promise; /** Install a managed skill from an explicit source and refresh active agent prompts. */ installSkillFromSource?: (opts: SkillInstallToolOptions) => Promise; compactSession?: (sessionKey: string, options?: { instructions?: string; force?: boolean; }) => Promise; btwQuery?: (sessionKey: string, question: string, options?: BtwQueryOptions) => Promise<{ text: string; error?: string; }>; getSessionContextReport?: (sessionKey: string, mode: 'list' | 'detail' | 'json') => Promise; getWorkflowRunService?: () => WorkflowRunServiceLike | undefined; } export declare class CommandHandler { private config; private bus; private sessionStore; private sessionConfigStore?; private applySessionThinkingLevel?; private getCurrentModel; private switchModelForSession; private invalidateAgentSession?; private abortSessionTurn?; private reloadSkills?; private installSkillFromSource?; private compactSession?; private btwQuery?; private getSessionContextReport?; private resetSession?; private getWorkflowRunService?; constructor(handlerConfig: CommandHandlerConfig); /** Replace config reference after hot reload or gateway PATCH so commands see current defaults. */ updateAgentConfig(config: Config): void; /** * Build the unified command context shared by all execute paths. * When `recorder` is set, every reply text is also captured (for realtime / CLI aggregation). */ private buildCommandContext; /** * Execute a command using the unified command system */ executeCommand(commandName: string, args: string, context: CommandContext): Promise; /** * Run command and return all user-visible text (ctx.reply + result.content) for realtime/CLI. * Same bus side effects as {@link executeCommand}. */ executeCommandAndAggregateReply(commandName: string, args: string, context: CommandContext, options?: { emitEvent?: (event: CommandStreamEvent) => void | Promise; }): Promise<{ handled: boolean; aggregatedText: string; metadata?: Record; }>; }