Add ACP-backed role sessions

This commit is contained in:
zenord
2026-08-16 10:08:03 +08:00
parent d59c4a654f
commit a80fe68d57
34 changed files with 1683 additions and 887 deletions
+19 -50
View File
@@ -1,57 +1,26 @@
import { AgentRegistry } from "../agents/agent-registry.js";
import { SessionStore } from "./session-store.js";
import type { IncomingMessage } from "./types.js";
export type CommandKind = "help" | "roles" | "role" | "status" | "cancel" | "new";
export interface CommandResult {
handled: boolean;
text?: string;
export interface ParsedCommand {
kind: CommandKind;
argument?: string;
deprecatedAlias?: boolean;
}
export class CommandRouter {
constructor(
private readonly agents: AgentRegistry,
private readonly sessions: SessionStore
) {}
route(message: IncomingMessage, sessionId: string): CommandResult {
const text = message.text.trim();
if (!text.startsWith("/")) return { handled: false };
const [command, ...args] = text.split(/\s+/);
switch (command) {
case "/help":
return {
handled: true,
text: [
"Commands:",
"/help - show this help",
"/status - show gateway/session status",
"/agents - list available agents",
"/agent <name> - select an agent for this chat",
"/new - reset this chat session"
].join("\n")
};
case "/status": {
const session = this.sessions.getSession(sessionId);
return {
handled: true,
text: `OK\nplatform=${message.platform}\nchat=${message.chatId}\nagent=${session.selectedAgent || this.agents.defaultName()}`
};
}
case "/agents":
return { handled: true, text: `Available agents: ${this.agents.list().join(", ")}` };
case "/agent": {
const agentName = args[0];
if (!agentName) return { handled: true, text: "Usage: /agent <name>" };
if (!this.agents.has(agentName)) return { handled: true, text: `Unknown agent: ${agentName}` };
this.sessions.setSelectedAgent(sessionId, agentName);
return { handled: true, text: `Selected agent: ${agentName}` };
}
case "/new":
this.sessions.reset(sessionId);
return { handled: true, text: "Started a new session for this chat." };
default:
return { handled: false };
parse(text: string): ParsedCommand | undefined {
const trimmed = text.trim();
if (!trimmed.startsWith("/")) return undefined;
const [command, ...args] = trimmed.split(/\s+/);
switch (command.toLowerCase()) {
case "/help": return { kind: "help" };
case "/roles": return { kind: "roles" };
case "/role": return { kind: "role", argument: args[0] };
case "/status": return { kind: "status" };
case "/cancel": return { kind: "cancel" };
case "/new": return { kind: "new" };
case "/agents": return { kind: "roles", deprecatedAlias: true };
case "/agent": return { kind: "role", argument: args[0], deprecatedAlias: true };
default: return undefined;
}
}
}