@vicvic-im/agent-bot 0.1.1 → 0.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +9 -3
- package/dist/agents/acp.d.ts +2 -1
- package/dist/agents/acp.d.ts.map +1 -1
- package/dist/agents/types.d.ts +16 -0
- package/dist/agents/types.d.ts.map +1 -1
- package/dist/bin-server.cjs +1422 -0
- package/dist/bin-server.cjs.map +1 -0
- package/dist/bin-server.d.ts +2 -0
- package/dist/bin-server.d.ts.map +1 -0
- package/dist/bin-server.js +19 -0
- package/dist/bin-server.js.map +1 -0
- package/dist/{chunk-QQ2NXJ3L.js → chunk-CDBYOHVL.js} +2 -2
- package/dist/{chunk-SCVC76UL.js → chunk-ELLWQDOY.js} +217 -105
- package/dist/chunk-ELLWQDOY.js.map +1 -0
- package/dist/cli.cjs +246 -119
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +32 -17
- package/dist/cli.js.map +1 -1
- package/dist/core/dispatcher.d.ts +3 -1
- package/dist/core/dispatcher.d.ts.map +1 -1
- package/dist/core/pm2.d.ts +7 -0
- package/dist/core/pm2.d.ts.map +1 -0
- package/dist/index.cjs +210 -98
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +2 -2
- package/dist/server.cjs +210 -96
- package/dist/server.cjs.map +1 -1
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +1 -1
- package/dist/version.d.ts +1 -1
- package/package.json +10 -10
- package/dist/chunk-SCVC76UL.js.map +0 -1
- /package/dist/{chunk-QQ2NXJ3L.js.map → chunk-CDBYOHVL.js.map} +0 -0
package/dist/cli.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/commands/setup.ts","../src/config.ts","../src/agents/registry.ts","../src/core/cli-path.ts","../src/server.ts","../src/agents/acp.ts","../src/agents/types.ts","../src/core/queue.ts","../src/version.ts","../src/core/dispatcher.ts","../src/core/gate.ts","../src/core/switch.ts","../src/core/lock.ts","../src/core/state.ts","../src/core/wire.ts","../src/core/chunk.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { execFileSync } from \"node:child_process\";\nimport { basename, resolve } from \"node:path\";\nimport { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { ensureConfig } from \"./commands/setup.js\";\nimport { findConfigPath, loadConfig } from \"./config.js\";\nimport { readPackageVersion, resolveServerEntry } from \"./core/cli-path.js\";\nimport { runBot } from \"./server.js\";\n\ninterface GlobalOptions {\n config?: string;\n}\n\nfunction processName(cwd: string): string {\n return `vbot-${basename(resolve(cwd)).replace(/[^a-zA-Z0-9._-]+/g, \"-\")}`;\n}\n\n// pm2 是可选的外部工具。通过固定的 /usr/bin/env 调用,避免把任意 PATH 条目当作可执行文件;\n// Windows 一期不承诺后台模式,检测失败时退回前台运行。\nconst ENV_BIN = \"/usr/bin/env\";\n\nfunction hasPm2(): boolean {\n try {\n execFileSync(ENV_BIN, [\"pm2\", \"--version\"], { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n}\n\nfunction pm2(args: string[], capture = false): string {\n return execFileSync(ENV_BIN, [\"pm2\", ...args], {\n stdio: capture ? \"pipe\" : \"inherit\",\n encoding: \"utf8\",\n });\n}\n\nfunction resolveName(configPath?: string): string {\n const path = findConfigPath(configPath);\n if (!path) return \"vbot\";\n try {\n const { config } = loadConfig(path);\n return processName(config.agent.cwd);\n } catch {\n return \"vbot\";\n }\n}\n\nfunction cliPath(): string {\n const path = process.argv[1];\n if (!path) throw new Error(\"Cannot resolve vbot entry; run the installed binary.\");\n return path;\n}\n\nconst program = new Command();\nprogram\n .name(\"vbot\")\n .description(\"Connect local coding agents to vicvic.im\")\n .version(readPackageVersion(cliPath()));\n\nprogram\n .command(\"start\")\n .description(\"Start vbot (prompts for config on first run)\")\n .option(\"--foreground\", \"run in the foreground instead of pm2\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action(async (options: GlobalOptions & { foreground?: boolean }) => {\n const { path } = await ensureConfig(options.config);\n if (options.foreground || !hasPm2()) {\n if (!options.foreground) {\n console.log(\n pc.yellow(\"pm2 not found; running in the foreground. Install pm2 for background mode.\")\n );\n }\n await runBot(path);\n return;\n }\n const name = resolveName(path);\n try {\n pm2([\"describe\", name], true);\n pm2([\"restart\", name, \"--update-env\"]);\n } catch {\n pm2([\n \"start\",\n resolveServerEntry(cliPath()),\n \"--name\",\n name,\n \"--stop-exit-codes\",\n \"2\",\n \"--log-date-format\",\n \"YYYY-MM-DD HH:mm:ss\",\n \"--\",\n path,\n ]);\n }\n pm2([\"save\"], true);\n console.log(pc.green(`✔ ${name} started. Use \"vbot logs\" to view output.`));\n });\n\nprogram\n .command(\"stop\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action((options: GlobalOptions) => {\n try {\n pm2([\"stop\", resolveName(options.config)]);\n } catch {\n console.error(pc.red(\"Failed to stop vbot. Is it running?\"));\n }\n });\n\nprogram\n .command(\"restart\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action((options: GlobalOptions) => {\n try {\n pm2([\"restart\", resolveName(options.config), \"--update-env\"]);\n } catch {\n console.error(pc.red('Failed to restart vbot. Try \"vbot start\".'));\n }\n });\n\nprogram\n .command(\"status\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action((options: GlobalOptions) => {\n try {\n pm2([\"describe\", resolveName(options.config)]);\n } catch {\n console.log(pc.yellow(\"vbot is not running.\"));\n }\n });\n\nprogram\n .command(\"logs\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action((options: GlobalOptions) => {\n try {\n pm2([\"logs\", resolveName(options.config), \"--lines\", \"50\"]);\n } catch {\n console.error(\"Failed to show logs. Is pm2 installed?\");\n }\n });\n\nprogram\n .command(\"delete\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action((options: GlobalOptions) => {\n try {\n pm2([\"delete\", resolveName(options.config)]);\n } catch {\n console.error(\"Failed to delete vbot process.\");\n }\n });\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n console.error(pc.red(error instanceof Error ? error.message : String(error)));\n process.exitCode = 1;\n});\n","import { existsSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport inquirer from \"inquirer\";\nimport pc from \"picocolors\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_TIMEOUT_MS,\n findConfigPath,\n loadConfig,\n normalizeConfig,\n saveConfig,\n type VbotConfig,\n} from \"../config.js\";\nimport { AGENTS, AGENT_NAMES, isAgentName } from \"../agents/registry.js\";\n\nexport interface SetupResult {\n config: VbotConfig;\n path: string;\n}\n\n/** 已有配置直接用;否则运行首次向导并写入当前目录 vbot.json。 */\nexport async function ensureConfig(explicit?: string): Promise<SetupResult> {\n let found: string | undefined;\n if (explicit) {\n const explicitPath = resolve(explicit);\n found = existsSync(explicitPath) ? explicitPath : undefined;\n } else {\n found = findConfigPath();\n }\n if (found) return loadConfig(found);\n\n const target = resolve(explicit ?? \"vbot.json\");\n console.log(pc.yellow(\"vbot.json not found, starting setup...\\n\"));\n\n const answers = await inquirer.prompt<{\n agent: string;\n cwd: string;\n timeoutMs: number;\n logPrompt: boolean;\n baseUrl: string;\n token: string;\n }>([\n {\n type: \"list\",\n name: \"agent\",\n message: \"Agent backend:\",\n choices: AGENT_NAMES.map((name) => ({\n name: `${name} (${AGENTS[name].label})`,\n value: name,\n })),\n },\n {\n type: \"input\",\n name: \"cwd\",\n message: \"Work directory:\",\n default: process.cwd(),\n validate: (value: string) => (value.trim() ? true : \"Work directory is required\"),\n },\n {\n type: \"number\",\n name: \"timeoutMs\",\n message: \"Timeout in ms:\",\n default: DEFAULT_TIMEOUT_MS,\n },\n {\n type: \"confirm\",\n name: \"logPrompt\",\n message: \"Log prompt content? (not recommended)\",\n default: false,\n },\n {\n type: \"input\",\n name: \"baseUrl\",\n message: \"vicvic.im server URL:\",\n default: DEFAULT_BASE_URL,\n },\n {\n type: \"password\",\n name: \"token\",\n message: \"Bot pairing token:\",\n validate: (value: string) => (value.trim() ? true : \"Pairing token is required\"),\n },\n ]);\n\n const agentName = answers.agent;\n if (!isAgentName(agentName)) throw new Error(`Invalid agent: ${agentName}`);\n\n const config = normalizeConfig(\n {\n provider: \"vicvic\",\n vicvic: { baseUrl: answers.baseUrl.trim() || DEFAULT_BASE_URL, token: answers.token.trim() },\n agent: { name: agentName, cwd: answers.cwd.trim() },\n timeoutMs: answers.timeoutMs,\n logPrompt: answers.logPrompt,\n },\n resolve(dirname(target))\n );\n\n saveConfig(config, target);\n console.log(pc.green(`✔ Config saved to ${target}\\n`));\n return { config, path: target };\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { isAgentName } from \"./agents/registry.js\";\nimport type { AgentName } from \"./agents/types.js\";\n\nexport const CONFIG_FILENAME = \"vbot.json\";\nexport const GLOBAL_CONFIG_DIR = join(homedir(), \".vbot\");\nexport const GLOBAL_CONFIG_PATH = join(GLOBAL_CONFIG_DIR, \"config.json\");\nexport const DEFAULT_BASE_URL = \"https://api.vicvic.im\";\nexport const DEFAULT_TIMEOUT_MS = 3_600_000;\n\nexport interface AgentConfig {\n name: AgentName;\n /** 可选覆盖;缺省由 registry 注入固定版本的默认命令。 */\n command?: string;\n args?: string[];\n cwd: string;\n model?: string | null;\n env?: Record<string, string>;\n}\n\nexport interface VbotConfig {\n provider: \"vicvic\";\n vicvic: {\n baseUrl: string;\n token: string;\n };\n agent: AgentConfig;\n timeoutMs: number;\n logPrompt: boolean;\n}\n\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigError\";\n }\n}\n\nfunction readJson(path: string): unknown {\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as unknown;\n } catch (error) {\n throw new ConfigError(\n `Failed to read config ${path}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\nfunction asRecord(value: unknown, field: string): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new ConfigError(`Invalid \"${field}\" in vbot.json: expected an object`);\n }\n return value as Record<string, unknown>;\n}\n\nfunction asString(value: unknown, field: string): string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new ConfigError(`Invalid \"${field}\" in vbot.json: expected a non-empty string`);\n }\n return value.trim();\n}\n\nfunction optionalString(value: unknown, field: string): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value !== \"string\") {\n throw new ConfigError(`Invalid \"${field}\" in vbot.json: expected a string`);\n }\n return value.trim() || undefined;\n}\n\nfunction trimTrailingSlash(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end -= 1;\n return value.slice(0, end);\n}\n\nfunction parseEnv(value: unknown): Record<string, string> | undefined {\n if (value === undefined || value === null) return undefined;\n const record = asRecord(value, \"agent.env\");\n const env: Record<string, string> = {};\n for (const [key, entry] of Object.entries(record)) {\n if (typeof entry !== \"string\") {\n throw new ConfigError(`Invalid \"agent.env.${key}\": expected a string`);\n }\n env[key] = entry;\n }\n return env;\n}\n\nfunction parseProvider(root: Record<string, unknown>): \"vicvic\" {\n const provider = optionalString(root.provider, \"provider\") ?? \"vicvic\";\n if (provider !== \"vicvic\") {\n throw new ConfigError(`Unsupported provider \"${provider}\"; only \"vicvic\" is supported`);\n }\n return \"vicvic\";\n}\n\nfunction parseVicvic(\n root: Record<string, unknown>,\n env: NodeJS.ProcessEnv\n): { baseUrl: string; token: string } {\n const vicvic = asRecord(root.vicvic, \"vicvic\");\n const baseUrl = trimTrailingSlash(\n optionalString(vicvic.baseUrl, \"vicvic.baseUrl\") ?? DEFAULT_BASE_URL\n );\n const token = env.VBOT_TOKEN?.trim() || optionalString(vicvic.token, \"vicvic.token\");\n if (!token) {\n throw new ConfigError(\n 'Missing \"vicvic.token\"; set it in vbot.json or the VBOT_TOKEN environment variable'\n );\n }\n return { baseUrl, token };\n}\n\nfunction parseAgent(root: Record<string, unknown>, configDir: string): AgentConfig {\n const agentRaw = asRecord(root.agent, \"agent\");\n const agentName = asString(agentRaw.name, \"agent.name\");\n if (!isAgentName(agentName)) {\n throw new ConfigError(\n `Invalid \"agent.name\" \"${agentName}\"; expected one of claude, codex, opencode, pi`\n );\n }\n\n const cwdValue = asString(agentRaw.cwd, \"agent.cwd\");\n const cwd = isAbsolute(cwdValue) ? cwdValue : resolve(configDir, cwdValue);\n if (!existsSync(cwd)) {\n throw new ConfigError(`\"agent.cwd\" does not exist: ${cwd}`);\n }\n\n const argsRaw = agentRaw.args;\n if (argsRaw !== undefined && !Array.isArray(argsRaw)) {\n throw new ConfigError('Invalid \"agent.args\": expected an array of strings');\n }\n\n return {\n name: agentName,\n command: optionalString(agentRaw.command, \"agent.command\"),\n args: Array.isArray(argsRaw) ? argsRaw.map((entry) => String(entry)) : undefined,\n cwd,\n model: optionalString(agentRaw.model, \"agent.model\") ?? null,\n env: parseEnv(agentRaw.env),\n };\n}\n\nfunction parseTimeout(root: Record<string, unknown>): number {\n const value = typeof root.timeoutMs === \"number\" ? root.timeoutMs : DEFAULT_TIMEOUT_MS;\n if (!Number.isFinite(value) || value < 1000 || value > 86_400_000) {\n throw new ConfigError('Invalid \"timeoutMs\": expected a number between 1000 and 86400000');\n }\n return value;\n}\n\n/** 校验并规范化第三方 JSON;不读取文件,便于单测。 */\nexport function normalizeConfig(\n raw: unknown,\n configDir: string,\n env: NodeJS.ProcessEnv = process.env\n): VbotConfig {\n const root = asRecord(raw, \"root\");\n return {\n provider: parseProvider(root),\n vicvic: parseVicvic(root, env),\n agent: parseAgent(root, configDir),\n timeoutMs: parseTimeout(root),\n logPrompt: root.logPrompt === true,\n };\n}\n\n/** 配置查找顺序:显式路径 > 当前目录 vbot.json > ~/.vbot/config.json。 */\nexport function findConfigPath(explicit?: string): string | undefined {\n if (explicit) {\n const path = resolve(explicit);\n if (!existsSync(path)) throw new ConfigError(`Config file not found: ${path}`);\n return path;\n }\n const local = resolve(process.cwd(), CONFIG_FILENAME);\n if (existsSync(local)) return local;\n if (existsSync(GLOBAL_CONFIG_PATH)) return GLOBAL_CONFIG_PATH;\n return undefined;\n}\n\nexport function loadConfig(explicit?: string): { config: VbotConfig; path: string } {\n const path = findConfigPath(explicit);\n if (!path) {\n throw new ConfigError(\n `No vbot.json found in ${process.cwd()} or ${GLOBAL_CONFIG_PATH}. Run \"vbot start\" to create one.`\n );\n }\n const config = normalizeConfig(readJson(path), dirname(path));\n return { config, path };\n}\n\n/** 原子写入;token 在文件中,权限收紧到 0600。 */\nexport function saveConfig(config: VbotConfig, path: string): void {\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true });\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 });\n renameSync(tmp, path);\n try {\n chmodSync(path, 0o600);\n } catch {\n // Windows 等平台可能不支持 chmod;忽略即可。\n }\n}\n","import type { AgentCommand, AgentName } from \"./types.js\";\n\n// 四个后端的默认启动命令。适配器版本固定,避免 latest 漂移导致行为变化。\n// 升级流程:单独验证 -> 更新本表与 README -> 提交。\nexport interface AgentDefinition {\n name: AgentName;\n label: string;\n command: AgentCommand;\n /** 需要用户自行完成的认证前置。 */\n authHint: string;\n}\n\nexport const AGENTS: Record<AgentName, AgentDefinition> = {\n claude: {\n name: \"claude\",\n label: \"Claude Code\",\n command: {\n command: \"npx\",\n args: [\"-y\", \"@agentclientprotocol/claude-agent-acp@0.100.0\"],\n },\n authHint: \"Run `claude login` (or configure ANTHROPIC_AUTH_TOKEN) before using vbot.\",\n },\n codex: {\n name: \"codex\",\n label: \"Codex CLI\",\n command: {\n command: \"npx\",\n args: [\"-y\", \"@agentclientprotocol/codex-acp@2.5.0\"],\n },\n authHint: \"Run `codex login` before using vbot.\",\n },\n opencode: {\n name: \"opencode\",\n label: \"OpenCode\",\n command: {\n command: \"opencode\",\n args: [\"acp\"],\n },\n authHint: \"OpenCode >= 1.19 is required; configure a provider/model in OpenCode first.\",\n },\n pi: {\n name: \"pi\",\n label: \"Pi\",\n command: {\n command: \"npx\",\n args: [\"-y\", \"--package=pi-acp@0.0.34\", \"--\", \"pi-acp\"],\n },\n authHint: \"Install and authenticate Pi (`pi` CLI) before using vbot.\",\n },\n};\n\nexport const AGENT_NAMES = Object.keys(AGENTS) as AgentName[];\n\nexport function isAgentName(value: string): value is AgentName {\n return (AGENT_NAMES as string[]).includes(value);\n}\n\nexport function definitionOf(name: AgentName): AgentDefinition {\n return AGENTS[name];\n}\n","import { existsSync, readFileSync, realpathSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * 全局安装时 argv[1] 是 bin 目录的符号链接(如 ~/.nvm/.../bin/vbot),\n * 必须 realpath 后定位包内同目录的 server.js;直接 dirname(argv[1]) 会指向 bin 目录。\n */\nexport function resolveServerEntry(cliPath: string): string {\n const real = realpathSync(cliPath);\n const candidate = join(dirname(real), \"server.js\");\n if (!existsSync(candidate)) {\n throw new Error(`Server bundle not found at ${candidate}. Reinstall @vicvic-im/agent-bot.`);\n }\n return candidate;\n}\n\n/** 从真实 dist/cli.js 位置向上读取包版本,避免符号链接导致读错 package.json。 */\nexport function readPackageVersion(cliPath: string): string {\n try {\n const raw = readFileSync(join(dirname(realpathSync(cliPath)), \"..\", \"package.json\"), \"utf8\");\n return (JSON.parse(raw) as { version?: string }).version ?? \"0.1.0\";\n } catch {\n return \"0.1.0\";\n }\n}\n","import { resolve } from \"node:path\";\nimport { ConfigError, loadConfig, saveConfig, type VbotConfig } from \"./config.js\";\nimport { AcpAgent, AgentAbortError, AgentStartError } from \"./agents/acp.js\";\nimport { AGENTS } from \"./agents/registry.js\";\nimport type { AgentBackend, AgentEvent, AgentName } from \"./agents/types.js\";\nimport { BotQueue, type QueueItem } from \"./core/queue.js\";\nimport { createDispatcher, type Runtime } from \"./core/dispatcher.js\";\nimport { createGate } from \"./core/gate.js\";\nimport { switchAgent } from \"./core/switch.js\";\nimport { acquireLock, LockError } from \"./core/lock.js\";\nimport { emptyState, loadState, saveState, type VbotState } from \"./core/state.js\";\nimport { VicvicWire } from \"./core/wire.js\";\nimport { splitMessage } from \"./core/chunk.js\";\n\ninterface BotContext {\n config: VbotConfig;\n configPath: string;\n state: VbotState;\n getAgent(): AgentBackend;\n setAgent(agent: AgentBackend): void;\n getQueue(): BotQueue;\n saveState(): void;\n saveConfig(): void;\n}\n\nexport interface BotHandle {\n finished: Promise<void>;\n stop(): Promise<void>;\n}\n\nfunction replySafe(reply: (text: string) => Promise<void>, text: string): void {\n reply(text).catch((error) => console.error(\"[server] reply failed:\", error));\n}\n\nfunction logAgentEvent(event: AgentEvent): void {\n if (event.type === \"tool\") {\n console.log(`[agent] tool ${event.name} (${event.status})`);\n } else if (event.type === \"usage\") {\n const cost = event.usage.cost ? ` ${event.usage.cost.amount} ${event.usage.cost.currency}` : \"\";\n console.log(`[agent] usage ${event.usage.used}/${event.usage.size}${cost}`);\n } else if (event.type === \"thought\") {\n console.log(`[agent] thought: ${event.text.slice(0, 80)}`);\n }\n}\n\n/** 启动 bot 运行循环;返回可停止的句柄,供 CLI 与测试使用。 */\nexport async function startBot(configPath: string): Promise<BotHandle> {\n const { config } = loadConfig(configPath);\n const token = config.vicvic.token;\n const release = acquireLock(token);\n\n const state = loadState(token) ?? emptyState(token, config.agent.name, config.agent.cwd);\n state.agent = config.agent.name;\n state.cwd = config.agent.cwd;\n\n let agent: AgentBackend = new AcpAgent(config.agent.name, config.agent);\n const gate = createGate();\n let switching = false;\n const holder: { queue: BotQueue | null } = { queue: null };\n const ctx: BotContext = {\n config,\n configPath,\n state,\n getAgent: () => agent,\n setAgent: (next) => {\n agent = next;\n },\n getQueue: () => {\n if (!holder.queue) throw new Error(\"queue is not initialized\");\n return holder.queue;\n },\n saveState: () => {\n state.lastUsedAt = new Date().toISOString();\n saveState(state);\n },\n saveConfig: () => saveConfig(config, configPath),\n };\n holder.queue = new BotQueue((item, signal) => gate(() => processPrompt(ctx, item, signal)));\n\n const runtime = createRuntime(ctx, (name) => {\n if (switching) return Promise.reject(new Error(\"Agent switch already in progress.\"));\n switching = true;\n return gate(() => switchAgent(ctx, name)).finally(() => {\n switching = false;\n });\n });\n const dispatch = createDispatcher(runtime);\n\n let notifySignal: () => void = () => undefined;\n const wire = new VicvicWire({\n baseUrl: config.vicvic.baseUrl,\n token,\n handlers: {\n onPrompt: (text, _msgUid, reply) => {\n if (config.logPrompt) console.log(`[vicvic] prompt: ${text.slice(0, 100)}...`);\n else console.log(\"[vicvic] prompt\");\n dispatch(text, reply);\n },\n onFatal: (error) => {\n console.error(`[vicvic] fatal: ${error.message}`);\n // 2 表示不可恢复的配置错误;pm2 以 --stop-exit-codes 2 避免无限重启。\n process.exitCode = 2;\n notifySignal();\n },\n },\n });\n\n const lifecycle = setupLifecycle(wire, () => agent, release);\n notifySignal = lifecycle.onSignal;\n announce(config);\n wire.start();\n\n return { finished: lifecycle.finished, stop: lifecycle.stop };\n}\n\ninterface Lifecycle {\n finished: Promise<void>;\n onSignal: () => void;\n stop: () => Promise<void>;\n}\n\nfunction setupLifecycle(\n getWire: VicvicWire,\n getAgent: () => AgentBackend,\n release: () => void\n): Lifecycle {\n let finish: () => void = () => undefined;\n const finished = new Promise<void>((resolveFinished) => {\n finish = resolveFinished;\n });\n let stopped = false;\n const onSignal = () => {\n console.log(\"[vbot] shutting down\");\n stop().catch((error) => console.error(\"[server] shutdown failed:\", error));\n };\n const stop = async (): Promise<void> => {\n if (stopped) return;\n stopped = true;\n getWire.stop();\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n await getAgent()\n .close()\n .catch(() => undefined);\n release();\n finish();\n };\n process.once(\"SIGINT\", onSignal);\n process.once(\"SIGTERM\", onSignal);\n return { finished, onSignal, stop };\n}\n\nfunction announce(config: VbotConfig): void {\n console.warn(\n `vbot runs ${config.agent.name} with your local user permissions and auto-approves permission requests.\\n` +\n \"Only use it in a directory you trust. Authentication must be completed in the agent CLI beforehand.\"\n );\n console.log(AGENTS[config.agent.name].authHint);\n console.log(`vbot starting. agent=${config.agent.name} cwd=${config.agent.cwd}`);\n}\n\n/** 运行直到 SIGINT / SIGTERM 或致命错误。 */\nexport async function runBot(configPath: string): Promise<void> {\n const bot = await startBot(configPath);\n await bot.finished;\n}\n\nfunction createRuntime(\n ctx: BotContext,\n switchAgent: (name: AgentName) => Promise<string>\n): Runtime {\n return {\n config: () => ctx.config,\n agent: () => ctx.getAgent(),\n queue: () => ctx.getQueue(),\n state: () => ctx.state,\n saveState: () => ctx.saveState(),\n saveConfig: () => ctx.saveConfig(),\n switchAgent,\n };\n}\n\nasync function processPrompt(ctx: BotContext, item: QueueItem, signal: AbortSignal): Promise<void> {\n replySafe(item.reply, \"Processing...\");\n\n const controller = new AbortController();\n let timedOut = false;\n const onAbort = () => controller.abort();\n signal.addEventListener(\"abort\", onAbort, { once: true });\n const timer = setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, ctx.config.timeoutMs);\n\n try {\n const result = await ctx.getAgent().run({\n prompt: item.text,\n sessionId: ctx.state.acpSessionId ?? undefined,\n cwd: ctx.config.agent.cwd,\n model: ctx.config.agent.model,\n signal: controller.signal,\n onEvent: ctx.config.logPrompt ? logAgentEvent : undefined,\n });\n\n ctx.state.acpSessionId = result.sessionId;\n ctx.state.usage = result.usage;\n ctx.saveState();\n\n for (const chunk of splitMessage(result.text || \"(no output)\")) {\n await item.reply(chunk);\n }\n } catch (error) {\n if (error instanceof AgentAbortError) {\n if (timedOut)\n replySafe(item.reply, \"Execution timeout, please retry or simplify your request.\");\n else if (!signal.aborted) replySafe(item.reply, \"Request aborted.\");\n return;\n }\n replyError(item.reply, error);\n } finally {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", onAbort);\n }\n}\n\nfunction replyError(reply: (text: string) => Promise<void>, error: unknown): void {\n if (error instanceof AgentStartError) {\n console.error(`[server] agent start failed: ${error.message}\\n${error.stderr}`);\n replySafe(reply, `Error: ${error.message}`);\n return;\n }\n console.error(\"[server] agent run failed:\", error);\n replySafe(reply, `Error: ${error instanceof Error ? error.message : String(error)}`);\n}\n\n// pm2 直接执行 dist/server.js:argv[1] 是 server.js,argv[2] 是配置路径。\nconst entry = process.argv[1] ?? \"\";\nif (/(^|[\\\\/])server\\.(js|cjs|ts)$/.test(entry)) {\n const configPath = process.argv[2];\n if (!configPath) {\n console.error(\"Usage: server.js <config-path>\");\n process.exit(1);\n }\n runBot(resolve(configPath)).catch((error: unknown) => {\n console.error(error instanceof Error ? error.message : String(error));\n // 配置错误 / 双实例锁属于不可恢复的启动错误;pm2 以 --stop-exit-codes 2 避免循环重启。\n const expected = error instanceof ConfigError || error instanceof LockError;\n process.exit(expected ? 2 : 1);\n });\n}\n","import { spawn, type ChildProcess } from \"node:child_process\";\nimport { Readable, Writable } from \"node:stream\";\nimport * as acp from \"@agentclientprotocol/sdk\";\nimport type {\n AgentCapabilities as AcpAgentCapabilities,\n ContentChunk,\n SessionConfigOption,\n SessionNotification,\n SessionUpdate,\n ToolCallUpdate,\n} from \"@agentclientprotocol/sdk\";\nimport type {\n AgentBackend,\n AgentCapabilities,\n AgentName,\n AgentRunRequest,\n AgentRunResult,\n Usage,\n} from \"./types.js\";\nimport { EMPTY_USAGE } from \"./types.js\";\nimport { definitionOf } from \"./registry.js\";\nimport type { AgentConfig } from \"../config.js\";\n\nexport class AgentAbortError extends Error {\n constructor() {\n super(\"Aborted\");\n this.name = \"AbortError\";\n }\n}\n\nexport class AgentStartError extends Error {\n constructor(\n message: string,\n readonly stderr: string\n ) {\n super(message);\n this.name = \"AgentStartError\";\n }\n}\n\ninterface Turn {\n text: string;\n usage: Usage;\n sawCost: boolean;\n onEvent?: (event: unknown) => void;\n}\n\nconst STDERR_LIMIT = 4_000;\n\n/** 通过 ACP stdio 驱动单个 coding agent 子进程。 */\nexport class AcpAgent implements AgentBackend {\n private child: ChildProcess | null = null;\n private connection: acp.ClientConnection | null = null;\n private ctx: acp.ClientContext | null = null;\n private startPromise: Promise<void> | null = null;\n private session: string | null = null;\n private configOptions: SessionConfigOption[] = [];\n private initCaps: AcpAgentCapabilities | undefined;\n private turn: Turn | null = null;\n private stderr = \"\";\n private sawUsageCost = false;\n private pendingModel: string | null = null;\n\n constructor(\n readonly name: AgentName,\n private readonly config: AgentConfig\n ) {}\n\n capabilities(): AgentCapabilities {\n return {\n resume: Boolean(this.initCaps?.sessionCapabilities?.resume),\n load: Boolean(this.initCaps?.loadSession),\n setConfigOption: this.configOptions.length > 0,\n usageCost: this.sawUsageCost,\n };\n }\n\n sessionId(): string | null {\n return this.session;\n }\n\n resetSession(): void {\n this.session = null;\n }\n\n async start(): Promise<void> {\n if (this.connection) return;\n if (this.startPromise) return this.startPromise;\n this.startPromise = this.doStart().finally(() => {\n this.startPromise = null;\n });\n return this.startPromise;\n }\n\n private async doStart(): Promise<void> {\n const definition = definitionOf(this.name);\n const command = this.config.command ?? definition.command.command;\n const args = this.config.args ?? definition.command.args;\n\n const child = spawn(command, args, {\n cwd: this.config.cwd,\n env: { ...process.env, ...this.config.env },\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n this.child = child;\n this.stderr = \"\";\n\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n this.stderr = `${this.stderr}${chunk.toString()}`.slice(-STDERR_LIMIT);\n if (this.stderr.length > 0) {\n console.error(`[${this.name}] ${chunk.toString().trimEnd()}`);\n }\n });\n\n child.on(\"exit\", (code, signal) => {\n if (this.child === child) {\n this.connection = null;\n this.ctx = null;\n this.child = null;\n }\n if (code !== 0 && signal !== \"SIGTERM\") {\n console.error(`[${this.name}] exited with code ${code ?? \"?\"} signal ${signal ?? \"-\"}`);\n }\n });\n\n if (!child.stdout || !child.stdin) {\n child.kill();\n throw new AgentStartError(\n `Failed to start ${this.name}: stdio pipes are unavailable`,\n this.stderr\n );\n }\n\n const input = Writable.toWeb(child.stdin) as unknown as WritableStream<Uint8Array>;\n const output = Readable.toWeb(child.stdout) as unknown as ReadableStream<Uint8Array>;\n const stream = acp.ndJsonStream(input, output);\n\n const app = acp.client({ name: \"vbot\" });\n app.onRequest(acp.methods.client.session.requestPermission, ({ params }) => {\n const options = params.options;\n const chosen =\n options.find((option) => option.kind === \"allow_always\") ??\n options.find((option) => option.kind === \"allow_once\");\n if (!chosen) {\n return { outcome: { outcome: \"cancelled\" as const } };\n }\n return { outcome: { outcome: \"selected\" as const, optionId: chosen.optionId } };\n });\n app.onNotification(acp.methods.client.session.update, ({ params }) => {\n this.handleUpdate(params);\n });\n\n const connection = app.connect(stream);\n this.connection = connection;\n this.ctx = connection.agent;\n\n try {\n const init = await this.ctx.request(acp.methods.agent.initialize, {\n protocolVersion: 1,\n clientCapabilities: {},\n clientInfo: { name: \"vbot\", version: \"0.1.0\" },\n });\n this.initCaps = init.agentCapabilities;\n } catch (error) {\n await this.close();\n throw new AgentStartError(\n `Failed to initialize ${this.name}: ${error instanceof Error ? error.message : String(error)}`,\n this.stderr\n );\n }\n }\n\n private async ensureSession(\n savedSessionId?: string\n ): Promise<{ sessionId: string; isNew: boolean }> {\n if (!this.ctx) throw new Error(`${this.name} is not started`);\n if (this.session) return { sessionId: this.session, isNew: false };\n\n if (savedSessionId) {\n const caps = this.initCaps;\n try {\n if (caps?.sessionCapabilities?.resume) {\n const resumed = await this.ctx.request(acp.methods.agent.session.resume, {\n sessionId: savedSessionId,\n cwd: this.config.cwd,\n mcpServers: [],\n });\n this.configOptions = resumed.configOptions ?? [];\n this.session = savedSessionId;\n return { sessionId: savedSessionId, isNew: false };\n }\n if (caps?.loadSession) {\n const loaded = await this.ctx.request(acp.methods.agent.session.load, {\n sessionId: savedSessionId,\n cwd: this.config.cwd,\n mcpServers: [],\n });\n this.configOptions = loaded.configOptions ?? [];\n this.session = savedSessionId;\n return { sessionId: savedSessionId, isNew: false };\n }\n } catch (error) {\n console.warn(\n `[${this.name}] failed to resume session ${savedSessionId}, starting a new one: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n const created = await this.ctx.request(acp.methods.agent.session.new, {\n cwd: this.config.cwd,\n mcpServers: [],\n });\n this.session = created.sessionId;\n this.configOptions = created.configOptions ?? [];\n return { sessionId: created.sessionId, isNew: true };\n }\n\n async run(request: AgentRunRequest): Promise<AgentRunResult> {\n await this.start();\n const opened = await this.ensureSession(request.sessionId);\n\n const model = request.model ?? this.pendingModel;\n if (model) {\n await this.setModel(model).catch(() => false);\n }\n\n const turn: Turn = {\n text: \"\",\n usage: { ...EMPTY_USAGE },\n sawCost: false,\n onEvent: request.onEvent as ((event: unknown) => void) | undefined,\n };\n this.turn = turn;\n\n const aborted = new Promise<never>((_, reject) => {\n if (request.signal.aborted) {\n reject(new AgentAbortError());\n return;\n }\n request.signal.addEventListener(\"abort\", () => reject(new AgentAbortError()), { once: true });\n });\n const onAbort = () => this.cancel().catch(() => undefined);\n if (request.signal.aborted) onAbort();\n else request.signal.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n if (!this.ctx) throw new Error(`${this.name} is not started`);\n const pending = this.ctx.request(\n acp.methods.agent.session.prompt,\n {\n sessionId: opened.sessionId,\n prompt: [{ type: \"text\", text: request.prompt }],\n },\n { cancellationSignal: request.signal, stopWaitingOnCancel: true }\n );\n // 如果 abort 先到,避免 prompt 后续 rejection 变成 unhandled。\n pending.catch(() => undefined);\n const response = await Promise.race([pending, aborted]);\n\n // 让同一连接上的 session/update 通知先处理完,再读取累计文本。\n await new Promise<void>((resolve) => setImmediate(resolve));\n\n if (response.stopReason === \"cancelled\" || request.signal.aborted) {\n throw new AgentAbortError();\n }\n\n return {\n text: turn.text,\n sessionId: opened.sessionId,\n usage: turn.usage,\n newSession: opened.isNew,\n };\n } catch (error) {\n if (request.signal.aborted || (error instanceof Error && error.name === \"AbortError\")) {\n throw new AgentAbortError();\n }\n throw error;\n } finally {\n request.signal.removeEventListener(\"abort\", onAbort);\n this.turn = null;\n }\n }\n\n async cancel(): Promise<void> {\n if (!this.ctx || !this.session) return;\n try {\n await this.ctx.notify(acp.methods.agent.session.cancel, { sessionId: this.session });\n } catch {\n // 连接已断开时忽略;子进程退出会由下一次 run 重新拉起。\n }\n }\n\n async setModel(model: string): Promise<boolean> {\n if (!this.ctx || !this.session) {\n this.pendingModel = model;\n return true;\n }\n const option = this.configOptions.find(\n (entry) => entry.type === \"select\" && (entry.id === \"model\" || entry.category === \"model\")\n );\n if (!option) return false;\n await this.ctx.request(acp.methods.agent.session.setConfigOption, {\n sessionId: this.session,\n configId: option.id,\n value: model,\n });\n this.pendingModel = null;\n return true;\n }\n\n async close(): Promise<void> {\n const child = this.child;\n const connection = this.connection;\n this.child = null;\n this.connection = null;\n this.ctx = null;\n this.session = null;\n this.configOptions = [];\n this.pendingModel = null;\n this.turn = null;\n try {\n connection?.close();\n } catch {\n // 已关闭\n }\n if (!child || child.exitCode !== null) return;\n const exited = new Promise<void>((resolve) => {\n child.once(\"exit\", () => resolve());\n });\n child.kill(\"SIGTERM\");\n const timer = setTimeout(() => child.kill(\"SIGKILL\"), 3_000);\n await exited;\n clearTimeout(timer);\n }\n\n private handleUpdate(notification: SessionNotification): void {\n if (notification.sessionId !== this.session) return;\n const turn = this.turn;\n if (!turn) return;\n this.dispatchUpdate(notification.update, turn);\n }\n\n private dispatchUpdate(update: SessionUpdate, turn: Turn): void {\n switch (update.sessionUpdate) {\n case \"agent_message_chunk\":\n this.applyContentChunk(update as ContentChunk, turn, \"text\");\n break;\n case \"agent_thought_chunk\":\n this.applyContentChunk(update as ContentChunk, turn, \"thought\");\n break;\n case \"tool_call\":\n turn.onEvent?.({ type: \"tool\", name: update.title, status: update.status ?? \"pending\" });\n break;\n case \"tool_call_update\":\n this.applyToolUpdate(update as ToolCallUpdate, turn);\n break;\n case \"usage_update\":\n this.applyUsage(update, turn);\n break;\n case \"config_option_update\":\n this.configOptions = update.configOptions;\n break;\n default:\n break;\n }\n }\n\n private applyContentChunk(chunk: ContentChunk, turn: Turn, kind: \"text\" | \"thought\"): void {\n if (chunk.content.type !== \"text\") return;\n if (kind === \"text\") turn.text += chunk.content.text;\n turn.onEvent?.({ type: kind, text: chunk.content.text });\n }\n\n private applyToolUpdate(tool: ToolCallUpdate, turn: Turn): void {\n turn.onEvent?.({\n type: \"tool\",\n name: tool.title ?? tool.toolCallId,\n status: tool.status ?? \"pending\",\n });\n }\n\n private applyUsage(\n update: Extract<SessionUpdate, { sessionUpdate: \"usage_update\" }>,\n turn: Turn\n ): void {\n turn.usage = { used: update.used, size: update.size, cost: update.cost ?? null };\n if (update.cost) {\n turn.sawCost = true;\n this.sawUsageCost = true;\n }\n turn.onEvent?.({ type: \"usage\", usage: turn.usage });\n }\n}\n","// Agent 后端抽象。四个后端都通过 ACP 驱动,差异只体现在启动命令与能力探测上。\n\nexport type AgentName = \"claude\" | \"codex\" | \"opencode\" | \"pi\";\n\nexport interface AgentCommand {\n command: string;\n args: string[];\n}\n\nexport interface Usage {\n /** 当前上下文 token 数(ACP v1 usage_update.used)。 */\n used: number;\n /** 上下文窗口大小(ACP v1 usage_update.size)。 */\n size: number;\n /** 累计成本,单位由 agent 决定;不提供时为 null。 */\n cost: { amount: number; currency: string } | null;\n}\n\nexport const EMPTY_USAGE: Usage = { used: 0, size: 0, cost: null };\n\nexport type AgentEvent =\n | { type: \"text\"; text: string }\n | { type: \"thought\"; text: string }\n | { type: \"tool\"; name: string; status: string }\n | { type: \"usage\"; usage: Usage };\n\nexport interface AgentRunRequest {\n prompt: string;\n /** 已保存的 ACP session id;为空或后端不支持 resume 时新建。 */\n sessionId?: string;\n cwd: string;\n model?: string | null;\n signal: AbortSignal;\n onEvent?: (event: AgentEvent) => void;\n}\n\nexport interface AgentRunResult {\n text: string;\n sessionId: string;\n usage: Usage;\n /** true 表示本次是新会话(用于提示用户上下文已重置)。 */\n newSession: boolean;\n}\n\nexport interface AgentCapabilities {\n resume: boolean;\n load: boolean;\n setConfigOption: boolean;\n usageCost: boolean;\n}\n\nexport interface AgentBackend {\n readonly name: AgentName;\n /** 启动子进程并完成 initialize;可重复调用(已启动则直接返回)。 */\n start(): Promise<void>;\n /** 运行一轮 prompt。内部负责 session 新建/恢复。 */\n run(request: AgentRunRequest): Promise<AgentRunResult>;\n /** 取消当前 prompt。 */\n cancel(): Promise<void>;\n /** 切换模型;返回 false 表示当前后端不支持。 */\n setModel(model: string): Promise<boolean>;\n /** 丢弃当前 ACP session;下一次 run 会新建会话。 */\n resetSession(): void;\n /** 关闭子进程并清理资源。 */\n close(): Promise<void>;\n capabilities(): AgentCapabilities;\n /** 当前 ACP session id(可能为空)。 */\n sessionId(): string | null;\n}\n","export type ReplyFn = (text: string) => Promise<void>;\n\nexport interface QueueItem {\n text: string;\n msgUid?: string;\n reply: ReplyFn;\n}\n\nexport type Processor = (item: QueueItem, signal: AbortSignal) => Promise<void>;\n\nexport interface QueueStatus {\n busy: boolean;\n queued: number;\n current: string | null;\n}\n\n/** 单 bot 串行队列:同一时间只跑一轮 agent,其余排队。 */\nexport class BotQueue {\n private readonly items: QueueItem[] = [];\n private running = false;\n private controller: AbortController | null = null;\n private currentText: string | null = null;\n\n constructor(private readonly processor: Processor) {}\n\n async enqueue(item: QueueItem): Promise<void> {\n if (this.running) {\n const ahead = this.items.length + 1;\n this.items.push(item);\n await item.reply(`Queued — ${ahead} message(s) ahead of you`);\n return;\n }\n this.running = true;\n this.items.push(item);\n try {\n await this.drain();\n } finally {\n this.running = false;\n this.controller = null;\n this.currentText = null;\n }\n }\n\n /** 中止当前任务并清空队列;返回是否有任务被中止。 */\n stop(): boolean {\n const wasBusy = this.running;\n this.controller?.abort();\n this.controller = null;\n this.items.length = 0;\n return wasBusy;\n }\n\n status(): QueueStatus {\n return { busy: this.running, queued: this.items.length, current: this.currentText };\n }\n\n private async drain(): Promise<void> {\n while (this.items.length > 0) {\n const item = this.items.shift();\n if (!item) break;\n this.controller = new AbortController();\n this.currentText = item.text;\n try {\n await this.processor(item, this.controller.signal);\n } catch (error) {\n console.error(\"[queue] processor error:\", error);\n await item\n .reply(`Error: ${error instanceof Error ? error.message : String(error)}`)\n .catch(() => undefined);\n } finally {\n this.controller = null;\n this.currentText = null;\n }\n }\n }\n}\n","/** 与 package.json 的 version 保持一致;发布时同步更新。 */\nexport const VBOT_VERSION = \"0.1.1\";\n","import { AGENTS, AGENT_NAMES, isAgentName } from \"../agents/registry.js\";\nimport type { AgentBackend, AgentCapabilities, AgentName } from \"../agents/types.js\";\nimport type { VbotConfig } from \"../config.js\";\nimport type { BotQueue } from \"./queue.js\";\nimport type { VbotState } from \"./state.js\";\nimport { VBOT_VERSION } from \"../version.js\";\n\nexport const HELP_TEXT = `Available commands:\n/new — Start a new session\n/stop — Abort the current request\n/status — Show agent, session and queue status\n/agent [name] — Show or switch agent backend\n/model [name] — Show or switch model\n/cost — Show context usage and cost\n/version — Show vbot version\n/help — Show this help\n\nOther /commands are sent to the agent as prompts.`;\n\nexport interface Runtime {\n config(): VbotConfig;\n agent(): AgentBackend;\n queue(): BotQueue;\n state(): VbotState;\n saveState(): void;\n saveConfig(): void;\n /** 切换后端;返回给用户的提示。失败时抛错。 */\n switchAgent(name: AgentName): Promise<string>;\n}\n\nexport type Dispatch = (text: string, reply: (text: string) => Promise<void>) => void;\n\ntype Send = (message: string) => void;\n\nexport function createDispatcher(runtime: Runtime): Dispatch {\n return (text, reply) => {\n const send: Send = (message) => {\n reply(message).catch((error) => console.error(\"[dispatch] reply failed:\", error));\n };\n\n const prompt = text.startsWith(\"/\") ? handleSlashCommand(runtime, text, send) : text;\n if (prompt === null) return;\n\n runtime\n .queue()\n .enqueue({ text: prompt, reply })\n .catch((error) => {\n console.error(\"[dispatch] enqueue failed:\", error);\n send(\"System error, please try again later.\");\n });\n };\n}\n\n/** 返回要转发给 agent 的 prompt;返回 null 表示命令已被处理。 */\nfunction handleSlashCommand(runtime: Runtime, text: string, send: Send): string | null {\n const [rawCommand, ...args] = text.split(/\\s+/);\n switch (rawCommand.toLowerCase()) {\n case \"/new\":\n handleNew(runtime, send);\n return null;\n case \"/stop\":\n handleStop(runtime, send);\n return null;\n case \"/status\":\n send(statusText(runtime));\n return null;\n case \"/agent\":\n handleAgent(runtime, args, send);\n return null;\n case \"/model\":\n handleModel(runtime, args, send);\n return null;\n case \"/cost\":\n send(costText(runtime));\n return null;\n case \"/help\":\n send(HELP_TEXT);\n return null;\n case \"/version\":\n send(`vbot v${VBOT_VERSION}`);\n return null;\n default:\n // 未识别的 /command 去掉斜杠后作为 prompt 转发(与 ccbot 行为一致)。\n return text.slice(1);\n }\n}\n\nfunction handleNew(runtime: Runtime, send: Send): void {\n runtime.agent().resetSession();\n const state = runtime.state();\n state.acpSessionId = null;\n state.usage = { used: 0, size: 0, cost: null };\n runtime.saveState();\n send(\"Session reset. Starting a new conversation.\");\n}\n\nfunction handleStop(runtime: Runtime, send: Send): void {\n const queue = runtime.queue();\n const queued = queue.status().queued;\n if (!queue.stop()) {\n send(\"No running request to stop.\");\n return;\n }\n send(\n queued > 0\n ? `Current request aborted. ${queued} queued message(s) discarded.`\n : \"Current request aborted.\"\n );\n}\n\nfunction handleAgent(runtime: Runtime, args: string[], send: Send): void {\n const name = args.join(\" \").trim();\n if (!name) {\n const current = runtime.config().agent.name;\n const list = AGENT_NAMES.map((entry) => `${entry === current ? \"*\" : \" \"} ${entry}`).join(\"\\n\");\n send(`Current agent: ${current}\\nAvailable agents:\\n${list}`);\n return;\n }\n if (!isAgentName(name)) {\n send(`Unknown agent \"${name}\". Available: ${AGENT_NAMES.join(\", \")}`);\n return;\n }\n if (runtime.queue().status().busy) {\n send(\"Cannot switch agent while a request is running. Use /stop first.\");\n return;\n }\n send(`Switching to ${name}...`);\n runtime\n .switchAgent(name)\n .then((message) => send(message))\n .catch((error: unknown) =>\n send(`Error: ${error instanceof Error ? error.message : String(error)}`)\n );\n}\n\nfunction handleModel(runtime: Runtime, args: string[], send: Send): void {\n const model = args.join(\" \").trim();\n if (!model) {\n send(`Current model: ${runtime.config().agent.model ?? \"default\"}`);\n return;\n }\n const config = runtime.config();\n const hadSession = runtime.agent().sessionId() !== null;\n config.agent.model = model;\n runtime.saveConfig();\n runtime\n .agent()\n .setModel(model)\n .then((supported) => {\n if (!supported) {\n send(\n `Model saved: ${model}. This agent does not expose a runtime model option; it will be used on the next session if supported.`\n );\n return;\n }\n send(\n hadSession\n ? `Model switched to: ${model}`\n : `Model set to: ${model}. It will apply when the session starts.`\n );\n })\n .catch((error: unknown) =>\n send(`Error: ${error instanceof Error ? error.message : String(error)}`)\n );\n}\n\nfunction statusText(runtime: Runtime): string {\n const config = runtime.config();\n const agent = runtime.agent();\n const state = runtime.state();\n const queue = runtime.queue().status();\n const lines = [\n `Agent: ${config.agent.name} (${AGENTS[config.agent.name].label})`,\n `Session: ${agent.sessionId() ?? \"none\"}`,\n `Work dir: ${config.agent.cwd}`,\n `Model: ${config.agent.model ?? \"default\"}`,\n `Status: ${queue.busy ? \"busy\" : \"idle\"}`,\n `Queue: ${queue.queued}`,\n `Usage: ${state.usage.used}/${state.usage.size} tokens`,\n `Capabilities: ${capabilitiesText(agent.capabilities())}`,\n ];\n return lines.join(\"\\n\");\n}\n\nfunction costText(runtime: Runtime): string {\n const usage = runtime.state().usage;\n const context = `Context: ${usage.used}/${usage.size} tokens`;\n if (!usage.cost) {\n return `${context}\\nCost: this agent does not report cost.`;\n }\n return `${context}\\nCost: ${usage.cost.amount} ${usage.cost.currency}`;\n}\n\nfunction capabilitiesText(caps: AgentCapabilities): string {\n const enabled = [\n caps.resume ? \"resume\" : null,\n caps.load ? \"load\" : null,\n caps.setConfigOption ? \"model\" : null,\n caps.usageCost ? \"cost\" : null,\n ].filter(Boolean);\n return enabled.length > 0 ? enabled.join(\", \") : \"basic\";\n}\n","/** 串行执行异步任务:用于让 prompt 与 /agent 切换互斥,避免切换期间中断进行中的请求。 */\nexport function createGate() {\n let tail: Promise<unknown> = Promise.resolve();\n return function run<T>(task: () => Promise<T>): Promise<T> {\n const result = tail.then(task, task);\n tail = result.then(\n () => undefined,\n () => undefined\n );\n return result;\n };\n}\n","import { AcpAgent } from \"../agents/acp.js\";\nimport { AGENTS } from \"../agents/registry.js\";\nimport { EMPTY_USAGE, type AgentBackend, type AgentName } from \"../agents/types.js\";\nimport type { AgentConfig, VbotConfig } from \"../config.js\";\nimport type { VbotState } from \"./state.js\";\n\nexport interface SwitchContext {\n config: VbotConfig;\n state: VbotState;\n getAgent(): AgentBackend;\n setAgent(agent: AgentBackend): void;\n saveConfig(): void;\n saveState(): void;\n /** 测试注入;默认创建 AcpAgent。 */\n createAgent?(name: AgentName, config: AgentConfig): AgentBackend;\n}\n\n/**\n * 切换到另一个 agent 后端。\n * 先启动新实例并切换引用,再关闭旧实例:避免关闭旧进程时中断新请求。\n * 调用方负责用 gate 串行化,保证切换期间没有 prompt 在跑。\n */\nexport async function switchAgent(ctx: SwitchContext, name: AgentName): Promise<string> {\n const previous = ctx.getAgent();\n const nextConfig: AgentConfig = {\n ...ctx.config.agent,\n name,\n command: undefined,\n args: undefined,\n model: null,\n };\n const next = ctx.createAgent ? ctx.createAgent(name, nextConfig) : new AcpAgent(name, nextConfig);\n await next.start();\n ctx.setAgent(next);\n\n ctx.config.agent = nextConfig;\n ctx.state.agent = name;\n ctx.state.acpSessionId = null;\n ctx.state.usage = { ...EMPTY_USAGE };\n ctx.saveConfig();\n ctx.saveState();\n\n await previous.close().catch(() => undefined);\n return `Switched to ${name} (${AGENTS[name].label}). A new session will start.`;\n}\n","import {\n closeSync,\n existsSync,\n mkdirSync,\n openSync,\n readFileSync,\n unlinkSync,\n writeSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { stateDir, tokenHash } from \"./state.js\";\n\nexport class LockError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"LockError\";\n }\n}\n\nconst lockPath = (token: string) => join(stateDir(), `${tokenHash(token)}.lock`);\n\nfunction readPid(path: string): number | null {\n try {\n const pid = Number.parseInt(readFileSync(path, \"utf8\").trim(), 10);\n return Number.isFinite(pid) && pid > 0 ? pid : null;\n } catch {\n return null;\n }\n}\n\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 同一 token 只允许一个 vbot 实例。服务端按 botId 只保留最后一个 WS 连接,\n * 多开会互相顶掉;这里用本地文件锁提前拒绝。\n */\nexport function acquireLock(token: string): () => void {\n mkdirSync(stateDir(), { recursive: true });\n const path = lockPath(token);\n\n for (let attempt = 0; attempt < 2; attempt += 1) {\n try {\n const fd = openSync(path, \"wx\");\n writeSync(fd, String(process.pid));\n closeSync(fd);\n return () => releaseLock(token);\n } catch (error) {\n if (!(error instanceof Error) || !(\"code\" in error) || error.code !== \"EEXIST\") {\n throw error;\n }\n const pid = readPid(path);\n if (pid && isAlive(pid)) {\n throw new LockError(`This bot is already running in another vbot process (pid ${pid}).`);\n }\n // 残留锁:上一个进程异常退出。删除后重试一次。\n try {\n unlinkSync(path);\n } catch {\n // 忽略并发删除失败,下一轮会重新判断。\n }\n }\n }\n\n throw new LockError(\"Failed to acquire vbot lock; please retry.\");\n}\n\nexport function releaseLock(token: string): void {\n const path = lockPath(token);\n if (!existsSync(path)) return;\n const pid = readPid(path);\n if (pid !== process.pid) return;\n try {\n unlinkSync(path);\n } catch {\n // 进程退出阶段清理失败不阻塞。\n }\n}\n","import { createHash } from \"node:crypto\";\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { EMPTY_USAGE, type AgentName, type Usage } from \"../agents/types.js\";\n\n/** vbot 的本地数据目录;测试通过 VBOT_HOME 指向临时目录。 */\nexport function vbotHome(): string {\n return process.env.VBOT_HOME?.trim() || join(homedir(), \".vbot\");\n}\n\nexport function stateDir(): string {\n return join(vbotHome(), \"state\");\n}\n\nexport interface VbotState {\n tokenHash: string;\n agent: AgentName;\n acpSessionId: string | null;\n cwd: string;\n createdAt: string;\n lastUsedAt: string;\n usage: Usage;\n}\n\n/** token 的 SHA-256 前 16 位:不落明文 token,且一个 token 稳定对应一个状态文件。 */\nexport function tokenHash(token: string): string {\n return createHash(\"sha256\").update(token).digest(\"hex\").slice(0, 16);\n}\n\nexport function statePath(token: string): string {\n return join(stateDir(), `${tokenHash(token)}.json`);\n}\n\nexport function emptyState(token: string, agent: AgentName, cwd: string): VbotState {\n const now = new Date().toISOString();\n return {\n tokenHash: tokenHash(token),\n agent,\n acpSessionId: null,\n cwd,\n createdAt: now,\n lastUsedAt: now,\n usage: { ...EMPTY_USAGE },\n };\n}\n\nexport function loadState(token: string): VbotState | null {\n const path = statePath(token);\n if (!existsSync(path)) return null;\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as Partial<VbotState>;\n if (typeof parsed.acpSessionId !== \"string\" && parsed.acpSessionId !== null) return null;\n if (typeof parsed.agent !== \"string\") return null;\n return {\n tokenHash: tokenHash(token),\n agent: parsed.agent as AgentName,\n acpSessionId: parsed.acpSessionId ?? null,\n cwd: typeof parsed.cwd === \"string\" ? parsed.cwd : process.cwd(),\n createdAt: typeof parsed.createdAt === \"string\" ? parsed.createdAt : new Date().toISOString(),\n lastUsedAt:\n typeof parsed.lastUsedAt === \"string\" ? parsed.lastUsedAt : new Date().toISOString(),\n usage:\n parsed.usage && typeof parsed.usage === \"object\"\n ? { ...EMPTY_USAGE, ...parsed.usage }\n : { ...EMPTY_USAGE },\n };\n } catch {\n // 损坏的状态文件按不存在处理,避免阻塞启动。\n return null;\n }\n}\n\n/** 原子写入状态文件;失败时抛错由调用方决定是否降级。 */\nexport function saveState(state: VbotState): void {\n const dir = stateDir();\n mkdirSync(dir, { recursive: true });\n const path = join(dir, `${state.tokenHash}.json`);\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, `${JSON.stringify(state, null, 2)}\\n`, { mode: 0o600 });\n renameSync(tmp, path);\n}\n\nexport function clearState(token: string): void {\n const path = statePath(token);\n if (existsSync(path)) {\n try {\n unlinkSync(path);\n } catch {\n // 清理失败不影响 /new,下一次写入会覆盖。\n }\n }\n}\n","import WebSocket from \"ws\";\n\nexport interface WireHandlers {\n onPrompt: (\n text: string,\n msgUid: string | undefined,\n reply: (text: string) => Promise<void>\n ) => void;\n onReady?: () => void;\n onDisconnected?: () => void;\n onFatal?: (error: Error) => void;\n}\n\nexport interface WireOptions {\n baseUrl: string;\n token: string;\n handlers: WireHandlers;\n}\n\nconst RECONNECT_BASE_MS = 1_000;\nconst RECONNECT_MAX_MS = 30_000;\nconst HEARTBEAT_MS = 30_000;\nconst INVALID_TOKEN_CODE = 4001;\n\ninterface ServerFrame {\n type?: string;\n msgUid?: string;\n text?: string;\n}\n\nfunction trimTrailingSlash(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end -= 1;\n return value.slice(0, end);\n}\n\n/** vicvic.im bot WS 地址;http(s) 自动改写为 ws(s)。 */\nexport function botUrl(baseUrl: string, token: string): string {\n const wsBase = trimTrailingSlash(baseUrl.replace(/^http/, \"ws\"));\n return `${wsBase}/bot/connect?token=${encodeURIComponent(token)}`;\n}\n\n/**\n * 与 app-server 的 bot 通道。协议与 ccbot 完全一致:\n * server -> {type:\"ready\"} / {type:\"prompt\", msgUid, text}\n * client -> {type:\"reply\", msgUid, text}\n */\nexport class VicvicWire {\n private socket: WebSocket | null = null;\n private stopped = false;\n private attempt = 0;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private heartbeatTimer: NodeJS.Timeout | null = null;\n\n constructor(private readonly options: WireOptions) {}\n\n start(): void {\n this.stopped = false;\n this.connect();\n }\n\n stop(): void {\n this.stopped = true;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.clearHeartbeat();\n this.socket?.close();\n this.socket = null;\n }\n\n /** 发送回复;socket 不可用时 reject,由调用方决定是否记录日志。 */\n async reply(msgUid: string | undefined, text: string): Promise<void> {\n const socket = this.socket;\n if (!socket || socket.readyState !== WebSocket.OPEN) {\n throw new Error(\"Bot connection is not open\");\n }\n await new Promise<void>((resolve, reject) => {\n socket.send(JSON.stringify({ type: \"reply\", msgUid, text }), (error) => {\n if (error) reject(error);\n else resolve();\n });\n });\n }\n\n private connect(): void {\n if (this.stopped) return;\n const url = botUrl(this.options.baseUrl, this.options.token);\n const socket = new WebSocket(url);\n this.socket = socket;\n\n socket.on(\"open\", () => {\n this.attempt = 0;\n this.startHeartbeat();\n console.log(\"[vicvic] connected\");\n });\n\n socket.on(\"message\", (raw) => {\n let frame: ServerFrame;\n try {\n frame = JSON.parse(String(raw)) as ServerFrame;\n } catch {\n return; // 非 JSON 帧直接忽略\n }\n if (frame.type === \"ready\") {\n console.log(\"[vicvic] ready\");\n this.options.handlers.onReady?.();\n return;\n }\n if (frame.type === \"prompt\" && typeof frame.text === \"string\" && frame.text.length > 0) {\n this.options.handlers.onPrompt(frame.text, frame.msgUid, (text) =>\n this.reply(frame.msgUid, text)\n );\n }\n });\n\n socket.on(\"close\", (code, reason) => {\n this.clearHeartbeat();\n if (this.socket === socket) this.socket = null;\n if (code === INVALID_TOKEN_CODE) {\n this.stopped = true;\n this.options.handlers.onFatal?.(\n new Error(`Invalid bot token (${reason.toString() || \"4001\"}).`)\n );\n return;\n }\n console.log(\"[vicvic] disconnected\");\n this.options.handlers.onDisconnected?.();\n this.scheduleReconnect();\n });\n\n socket.on(\"error\", (error: Error) => {\n console.error(\"[vicvic] ws error:\", error.message); // close 随后触发重连\n });\n }\n\n private scheduleReconnect(): void {\n if (this.stopped || this.reconnectTimer) return;\n const delay = Math.min(RECONNECT_BASE_MS * 2 ** this.attempt, RECONNECT_MAX_MS);\n this.attempt += 1;\n console.log(`[vicvic] reconnecting in ${Math.round(delay / 1000)}s`);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, delay);\n }\n\n private startHeartbeat(): void {\n this.clearHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n try {\n this.socket?.ping();\n } catch {\n // close 事件负责重连\n }\n }, HEARTBEAT_MS);\n }\n\n private clearHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n}\n","/** 单条 IM 消息的分段上限;E2E 实测腾讯云 IM 上限后再回填方案文档。 */\nexport const MAX_MESSAGE_CHARS = 4000;\n\nfunction isLowSurrogate(code: number): boolean {\n return code >= 0xdc00 && code <= 0xdfff;\n}\n\nfunction fenceCount(text: string): number {\n return (text.match(/```/g) ?? []).length;\n}\n\nfunction avoidSurrogateSplit(text: string, cut: number, start: number): number {\n return cut > start && isLowSurrogate(text.charCodeAt(cut)) ? cut - 1 : cut;\n}\n\nfunction preferNewline(text: string, start: number, cut: number, max: number): number {\n const newline = text.lastIndexOf(\"\\n\", cut);\n return newline >= start + Math.floor(max / 2) ? newline + 1 : cut;\n}\n\nfunction avoidFenceSplit(text: string, start: number, cut: number, max: number): number {\n if (fenceCount(text.slice(start, cut)) % 2 === 0) return cut;\n const fenceStart = text.lastIndexOf(\"```\", cut);\n return fenceStart >= start + Math.floor(max / 4) ? fenceStart : cut;\n}\n\n/** 在 [start, start+max] 内找一个尽量安全的切点。 */\nfunction findCut(text: string, start: number, max: number): number {\n const hardCut = Math.min(start + max, text.length);\n let cut = avoidSurrogateSplit(text, hardCut, start);\n cut = preferNewline(text, start, cut, max);\n cut = avoidFenceSplit(text, start, cut, max);\n return cut > start ? cut : hardCut;\n}\n\n/**\n * 把长文本切成适合单条 IM 消息的段:\n * - 优先在切点前的换行处断开;\n * - 不切断 UTF-16 代理对;\n * - 尽量不把一段切在未闭合的代码块内部(找不到安全切点时退化为硬切)。\n */\nexport function splitMessage(text: string, max: number = MAX_MESSAGE_CHARS): string[] {\n if (!text) return [];\n if (max < 2) throw new Error(\"max must be >= 2\");\n\n const chunks: string[] = [];\n let start = 0;\n\n while (start < text.length) {\n if (text.length - start <= max) {\n chunks.push(text.slice(start));\n break;\n }\n const cut = findCut(text, start, max);\n const chunk = text.slice(start, cut);\n if (chunk.trim().length > 0) chunks.push(chunk);\n start = cut;\n }\n\n return chunks;\n}\n"],"mappings":"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","names":["import_node_child_process","import_node_path","import_picocolors","import_node_fs","import_node_path","entry","pc","inquirer","import_node_fs","import_node_path","cliPath","import_node_path","resolve","entry","entry","import_node_fs","import_node_path","import_node_fs","import_node_os","import_node_path","trimTrailingSlash","WebSocket","resolve","switchAgent","pc"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/commands/setup.ts","../src/config.ts","../src/agents/registry.ts","../src/core/cli-path.ts","../src/core/pm2.ts","../src/agents/acp.ts","../src/agents/types.ts","../src/version.ts","../src/core/queue.ts","../src/core/dispatcher.ts","../src/core/gate.ts","../src/core/switch.ts","../src/core/lock.ts","../src/core/state.ts","../src/core/wire.ts","../src/core/chunk.ts","../src/server.ts"],"sourcesContent":["#!/usr/bin/env node\nimport { execFileSync } from \"node:child_process\";\nimport { basename, resolve } from \"node:path\";\nimport { Command } from \"commander\";\nimport pc from \"picocolors\";\nimport { ensureConfig } from \"./commands/setup.js\";\nimport { findConfigPath, loadConfig } from \"./config.js\";\nimport { readPackageVersion, resolveServerEntry } from \"./core/cli-path.js\";\nimport { ensurePm2, hasPm2 } from \"./core/pm2.js\";\nimport { runBot } from \"./server.js\";\n\ninterface GlobalOptions {\n config?: string;\n}\n\nfunction processName(cwd: string): string {\n return `vbot-${basename(resolve(cwd)).replace(/[^a-zA-Z0-9._-]+/g, \"-\")}`;\n}\n\n// pm2 是可选的外部工具。通过固定的 /usr/bin/env 调用,避免把任意 PATH 条目当作可执行文件;\n// Windows 一期不承诺后台模式,检测失败时退回前台运行。\nconst ENV_BIN = \"/usr/bin/env\";\n\nfunction pm2(args: string[], capture = false): string {\n return execFileSync(ENV_BIN, [\"pm2\", ...args], {\n stdio: capture ? \"pipe\" : \"inherit\",\n encoding: \"utf8\",\n });\n}\n\nfunction resolveName(configPath?: string): string {\n const path = findConfigPath(configPath);\n if (!path) return \"vbot\";\n try {\n const { config } = loadConfig(path);\n return processName(config.agent.cwd);\n } catch {\n return \"vbot\";\n }\n}\n\nfunction cliPath(): string {\n const path = process.argv[1];\n if (!path) throw new Error(\"Cannot resolve vbot entry; run the installed binary.\");\n return path;\n}\n\nconst program = new Command();\nprogram\n .name(\"vbot\")\n .description(\"Connect local coding agents to vicvic.im\")\n .version(readPackageVersion(cliPath()));\n\nprogram\n .command(\"start\")\n .description(\"Start vbot (prompts for config on first run)\")\n .option(\"--foreground\", \"run in the foreground instead of pm2\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action(async (options: GlobalOptions & { foreground?: boolean }) => {\n const { path } = await ensureConfig(options.config);\n if (options.foreground) {\n await runBot(path);\n return;\n }\n if (!hasPm2()) console.log(pc.yellow(\"pm2 not found, installing globally...\"));\n if (!ensurePm2()) {\n console.error(pc.red(\"Failed to install pm2. Please install manually: npm i -g pm2\"));\n console.log(pc.yellow(\"Running in the foreground instead.\"));\n await runBot(path);\n return;\n }\n const name = resolveName(path);\n try {\n pm2([\"describe\", name], true);\n pm2([\"restart\", name, \"--update-env\"]);\n } catch {\n pm2([\n \"start\",\n resolveServerEntry(cliPath()),\n \"--name\",\n name,\n \"--stop-exit-codes\",\n \"2\",\n \"--log-date-format\",\n \"YYYY-MM-DD HH:mm:ss\",\n \"--\",\n path,\n ]);\n }\n pm2([\"save\"], true);\n console.log(pc.green(`✔ ${name} started. Use \"vbot logs\" to view output.`));\n });\n\nprogram\n .command(\"stop\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action((options: GlobalOptions) => {\n try {\n pm2([\"stop\", resolveName(options.config)]);\n } catch {\n console.error(pc.red(\"Failed to stop vbot. Is it running?\"));\n }\n });\n\nprogram\n .command(\"restart\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action((options: GlobalOptions) => {\n try {\n pm2([\"restart\", resolveName(options.config), \"--update-env\"]);\n } catch {\n console.error(pc.red('Failed to restart vbot. Try \"vbot start\".'));\n }\n });\n\nprogram\n .command(\"status\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action((options: GlobalOptions) => {\n try {\n pm2([\"describe\", resolveName(options.config)]);\n } catch {\n console.log(pc.yellow(\"vbot is not running.\"));\n }\n });\n\nprogram\n .command(\"logs\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action((options: GlobalOptions) => {\n try {\n pm2([\"logs\", resolveName(options.config), \"--lines\", \"50\"]);\n } catch {\n console.error(\"Failed to show logs. Is pm2 installed?\");\n }\n });\n\nprogram\n .command(\"delete\")\n .option(\"-c, --config <path>\", \"config file path\")\n .action((options: GlobalOptions) => {\n try {\n pm2([\"delete\", resolveName(options.config)]);\n } catch {\n console.error(\"Failed to delete vbot process.\");\n }\n });\n\nprogram.parseAsync(process.argv).catch((error: unknown) => {\n console.error(pc.red(error instanceof Error ? error.message : String(error)));\n process.exitCode = 1;\n});\n","import { existsSync } from \"node:fs\";\nimport { dirname, resolve } from \"node:path\";\nimport inquirer from \"inquirer\";\nimport pc from \"picocolors\";\nimport {\n DEFAULT_BASE_URL,\n DEFAULT_TIMEOUT_MS,\n findConfigPath,\n loadConfig,\n normalizeConfig,\n saveConfig,\n type VbotConfig,\n} from \"../config.js\";\nimport { AGENTS, AGENT_NAMES, isAgentName } from \"../agents/registry.js\";\n\nexport interface SetupResult {\n config: VbotConfig;\n path: string;\n}\n\n/** 已有配置直接用;否则运行首次向导并写入当前目录 vbot.json。 */\nexport async function ensureConfig(explicit?: string): Promise<SetupResult> {\n let found: string | undefined;\n if (explicit) {\n const explicitPath = resolve(explicit);\n found = existsSync(explicitPath) ? explicitPath : undefined;\n } else {\n found = findConfigPath();\n }\n if (found) return loadConfig(found);\n\n const target = resolve(explicit ?? \"vbot.json\");\n console.log(pc.yellow(\"vbot.json not found, starting setup...\\n\"));\n\n const answers = await inquirer.prompt<{\n agent: string;\n cwd: string;\n timeoutMs: number;\n logPrompt: boolean;\n baseUrl: string;\n token: string;\n }>([\n {\n type: \"list\",\n name: \"agent\",\n message: \"Agent backend:\",\n choices: AGENT_NAMES.map((name) => ({\n name: `${name} (${AGENTS[name].label})`,\n value: name,\n })),\n },\n {\n type: \"input\",\n name: \"cwd\",\n message: \"Work directory:\",\n default: process.cwd(),\n validate: (value: string) => (value.trim() ? true : \"Work directory is required\"),\n },\n {\n type: \"number\",\n name: \"timeoutMs\",\n message: \"Timeout in ms:\",\n default: DEFAULT_TIMEOUT_MS,\n },\n {\n type: \"confirm\",\n name: \"logPrompt\",\n message: \"Log prompt content? (not recommended)\",\n default: false,\n },\n {\n type: \"input\",\n name: \"baseUrl\",\n message: \"vicvic.im server URL:\",\n default: DEFAULT_BASE_URL,\n },\n {\n type: \"password\",\n name: \"token\",\n message: \"Bot pairing token:\",\n validate: (value: string) => (value.trim() ? true : \"Pairing token is required\"),\n },\n ]);\n\n const agentName = answers.agent;\n if (!isAgentName(agentName)) throw new Error(`Invalid agent: ${agentName}`);\n\n const config = normalizeConfig(\n {\n provider: \"vicvic\",\n vicvic: { baseUrl: answers.baseUrl.trim() || DEFAULT_BASE_URL, token: answers.token.trim() },\n agent: { name: agentName, cwd: answers.cwd.trim() },\n timeoutMs: answers.timeoutMs,\n logPrompt: answers.logPrompt,\n },\n resolve(dirname(target))\n );\n\n saveConfig(config, target);\n console.log(pc.green(`✔ Config saved to ${target}\\n`));\n return { config, path: target };\n}\n","import { chmodSync, existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { dirname, isAbsolute, join, resolve } from \"node:path\";\nimport { isAgentName } from \"./agents/registry.js\";\nimport type { AgentName } from \"./agents/types.js\";\n\nexport const CONFIG_FILENAME = \"vbot.json\";\nexport const GLOBAL_CONFIG_DIR = join(homedir(), \".vbot\");\nexport const GLOBAL_CONFIG_PATH = join(GLOBAL_CONFIG_DIR, \"config.json\");\nexport const DEFAULT_BASE_URL = \"https://api.vicvic.im\";\nexport const DEFAULT_TIMEOUT_MS = 3_600_000;\n\nexport interface AgentConfig {\n name: AgentName;\n /** 可选覆盖;缺省由 registry 注入固定版本的默认命令。 */\n command?: string;\n args?: string[];\n cwd: string;\n model?: string | null;\n env?: Record<string, string>;\n}\n\nexport interface VbotConfig {\n provider: \"vicvic\";\n vicvic: {\n baseUrl: string;\n token: string;\n };\n agent: AgentConfig;\n timeoutMs: number;\n logPrompt: boolean;\n}\n\nexport class ConfigError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigError\";\n }\n}\n\nfunction readJson(path: string): unknown {\n try {\n return JSON.parse(readFileSync(path, \"utf8\")) as unknown;\n } catch (error) {\n throw new ConfigError(\n `Failed to read config ${path}: ${error instanceof Error ? error.message : String(error)}`\n );\n }\n}\n\nfunction asRecord(value: unknown, field: string): Record<string, unknown> {\n if (!value || typeof value !== \"object\" || Array.isArray(value)) {\n throw new ConfigError(`Invalid \"${field}\" in vbot.json: expected an object`);\n }\n return value as Record<string, unknown>;\n}\n\nfunction asString(value: unknown, field: string): string {\n if (typeof value !== \"string\" || value.trim().length === 0) {\n throw new ConfigError(`Invalid \"${field}\" in vbot.json: expected a non-empty string`);\n }\n return value.trim();\n}\n\nfunction optionalString(value: unknown, field: string): string | undefined {\n if (value === undefined || value === null) return undefined;\n if (typeof value !== \"string\") {\n throw new ConfigError(`Invalid \"${field}\" in vbot.json: expected a string`);\n }\n return value.trim() || undefined;\n}\n\nfunction trimTrailingSlash(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end -= 1;\n return value.slice(0, end);\n}\n\nfunction parseEnv(value: unknown): Record<string, string> | undefined {\n if (value === undefined || value === null) return undefined;\n const record = asRecord(value, \"agent.env\");\n const env: Record<string, string> = {};\n for (const [key, entry] of Object.entries(record)) {\n if (typeof entry !== \"string\") {\n throw new ConfigError(`Invalid \"agent.env.${key}\": expected a string`);\n }\n env[key] = entry;\n }\n return env;\n}\n\nfunction parseProvider(root: Record<string, unknown>): \"vicvic\" {\n const provider = optionalString(root.provider, \"provider\") ?? \"vicvic\";\n if (provider !== \"vicvic\") {\n throw new ConfigError(`Unsupported provider \"${provider}\"; only \"vicvic\" is supported`);\n }\n return \"vicvic\";\n}\n\nfunction parseVicvic(\n root: Record<string, unknown>,\n env: NodeJS.ProcessEnv\n): { baseUrl: string; token: string } {\n const vicvic = asRecord(root.vicvic, \"vicvic\");\n const baseUrl = trimTrailingSlash(\n optionalString(vicvic.baseUrl, \"vicvic.baseUrl\") ?? DEFAULT_BASE_URL\n );\n const token = env.VBOT_TOKEN?.trim() || optionalString(vicvic.token, \"vicvic.token\");\n if (!token) {\n throw new ConfigError(\n 'Missing \"vicvic.token\"; set it in vbot.json or the VBOT_TOKEN environment variable'\n );\n }\n return { baseUrl, token };\n}\n\nfunction parseAgent(root: Record<string, unknown>, configDir: string): AgentConfig {\n const agentRaw = asRecord(root.agent, \"agent\");\n const agentName = asString(agentRaw.name, \"agent.name\");\n if (!isAgentName(agentName)) {\n throw new ConfigError(\n `Invalid \"agent.name\" \"${agentName}\"; expected one of claude, codex, opencode, pi`\n );\n }\n\n const cwdValue = asString(agentRaw.cwd, \"agent.cwd\");\n const cwd = isAbsolute(cwdValue) ? cwdValue : resolve(configDir, cwdValue);\n if (!existsSync(cwd)) {\n throw new ConfigError(`\"agent.cwd\" does not exist: ${cwd}`);\n }\n\n const argsRaw = agentRaw.args;\n if (argsRaw !== undefined && !Array.isArray(argsRaw)) {\n throw new ConfigError('Invalid \"agent.args\": expected an array of strings');\n }\n\n return {\n name: agentName,\n command: optionalString(agentRaw.command, \"agent.command\"),\n args: Array.isArray(argsRaw) ? argsRaw.map((entry) => String(entry)) : undefined,\n cwd,\n model: optionalString(agentRaw.model, \"agent.model\") ?? null,\n env: parseEnv(agentRaw.env),\n };\n}\n\nfunction parseTimeout(root: Record<string, unknown>): number {\n const value = typeof root.timeoutMs === \"number\" ? root.timeoutMs : DEFAULT_TIMEOUT_MS;\n if (!Number.isFinite(value) || value < 1000 || value > 86_400_000) {\n throw new ConfigError('Invalid \"timeoutMs\": expected a number between 1000 and 86400000');\n }\n return value;\n}\n\n/** 校验并规范化第三方 JSON;不读取文件,便于单测。 */\nexport function normalizeConfig(\n raw: unknown,\n configDir: string,\n env: NodeJS.ProcessEnv = process.env\n): VbotConfig {\n const root = asRecord(raw, \"root\");\n return {\n provider: parseProvider(root),\n vicvic: parseVicvic(root, env),\n agent: parseAgent(root, configDir),\n timeoutMs: parseTimeout(root),\n logPrompt: root.logPrompt === true,\n };\n}\n\n/** 配置查找顺序:显式路径 > 当前目录 vbot.json > ~/.vbot/config.json。 */\nexport function findConfigPath(explicit?: string): string | undefined {\n if (explicit) {\n const path = resolve(explicit);\n if (!existsSync(path)) throw new ConfigError(`Config file not found: ${path}`);\n return path;\n }\n const local = resolve(process.cwd(), CONFIG_FILENAME);\n if (existsSync(local)) return local;\n if (existsSync(GLOBAL_CONFIG_PATH)) return GLOBAL_CONFIG_PATH;\n return undefined;\n}\n\nexport function loadConfig(explicit?: string): { config: VbotConfig; path: string } {\n const path = findConfigPath(explicit);\n if (!path) {\n throw new ConfigError(\n `No vbot.json found in ${process.cwd()} or ${GLOBAL_CONFIG_PATH}. Run \"vbot start\" to create one.`\n );\n }\n const config = normalizeConfig(readJson(path), dirname(path));\n return { config, path };\n}\n\n/** 原子写入;token 在文件中,权限收紧到 0600。 */\nexport function saveConfig(config: VbotConfig, path: string): void {\n const dir = dirname(path);\n mkdirSync(dir, { recursive: true });\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, `${JSON.stringify(config, null, 2)}\\n`, { mode: 0o600 });\n renameSync(tmp, path);\n try {\n chmodSync(path, 0o600);\n } catch {\n // Windows 等平台可能不支持 chmod;忽略即可。\n }\n}\n","import type { AgentCommand, AgentName } from \"./types.js\";\n\n// 四个后端的默认启动命令。适配器版本固定,避免 latest 漂移导致行为变化。\n// 升级流程:单独验证 -> 更新本表与 README -> 提交。\nexport interface AgentDefinition {\n name: AgentName;\n label: string;\n command: AgentCommand;\n /** 需要用户自行完成的认证前置。 */\n authHint: string;\n}\n\nexport const AGENTS: Record<AgentName, AgentDefinition> = {\n claude: {\n name: \"claude\",\n label: \"Claude Code\",\n command: {\n command: \"npx\",\n args: [\"-y\", \"@agentclientprotocol/claude-agent-acp@0.100.0\"],\n },\n authHint: \"Run `claude login` (or configure ANTHROPIC_AUTH_TOKEN) before using vbot.\",\n },\n codex: {\n name: \"codex\",\n label: \"Codex CLI\",\n command: {\n command: \"npx\",\n args: [\"-y\", \"@agentclientprotocol/codex-acp@2.5.0\"],\n },\n authHint: \"Run `codex login` before using vbot.\",\n },\n opencode: {\n name: \"opencode\",\n label: \"OpenCode\",\n command: {\n command: \"opencode\",\n args: [\"acp\"],\n },\n authHint: \"OpenCode >= 1.19 is required; configure a provider/model in OpenCode first.\",\n },\n pi: {\n name: \"pi\",\n label: \"Pi\",\n command: {\n command: \"npx\",\n args: [\"-y\", \"--package=pi-acp@0.0.34\", \"--\", \"pi-acp\"],\n },\n authHint: \"Install and authenticate Pi (`pi` CLI) before using vbot.\",\n },\n};\n\nexport const AGENT_NAMES = Object.keys(AGENTS) as AgentName[];\n\nexport function isAgentName(value: string): value is AgentName {\n return (AGENT_NAMES as string[]).includes(value);\n}\n\nexport function definitionOf(name: AgentName): AgentDefinition {\n return AGENTS[name];\n}\n","import { existsSync, readFileSync, realpathSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\n\n/**\n * 全局安装时 argv[1] 是 bin 目录的符号链接(如 ~/.nvm/.../bin/vbot),\n * 必须 realpath 后定位包内同目录的 server.js;直接 dirname(argv[1]) 会指向 bin 目录。\n */\nexport function resolveServerEntry(cliPath: string): string {\n const real = realpathSync(cliPath);\n const candidate = join(dirname(real), \"bin-server.js\");\n if (!existsSync(candidate)) {\n throw new Error(`Server bundle not found at ${candidate}. Reinstall @vicvic-im/agent-bot.`);\n }\n return candidate;\n}\n\n/** 从真实 dist/cli.js 位置向上读取包版本,避免符号链接导致读错 package.json。 */\nexport function readPackageVersion(cliPath: string): string {\n try {\n const raw = readFileSync(join(dirname(realpathSync(cliPath)), \"..\", \"package.json\"), \"utf8\");\n return (JSON.parse(raw) as { version?: string }).version ?? \"0.1.0\";\n } catch {\n return \"0.1.0\";\n }\n}\n","import { execFileSync } from \"node:child_process\";\n\n// pm2 是可选的外部工具。通过固定的 /usr/bin/env 调用,避免把任意 PATH 条目当作可执行文件。\nconst ENV_BIN = \"/usr/bin/env\";\n\ntype Exec = typeof execFileSync;\n\nexport function hasPm2(exec: Exec = execFileSync): boolean {\n try {\n exec(ENV_BIN, [\"pm2\", \"--version\"], { stdio: \"ignore\" });\n return true;\n } catch {\n return false;\n }\n}\n\n/** 与 ccbot 一致:pm2 缺失时自动全局安装;安装失败返回 false,由调用方退前台。 */\nexport function ensurePm2(exec: Exec = execFileSync): boolean {\n if (hasPm2(exec)) return true;\n try {\n exec(ENV_BIN, [\"npm\", \"i\", \"-g\", \"pm2\"], { stdio: \"inherit\" });\n return hasPm2(exec);\n } catch {\n return false;\n }\n}\n","import { spawn, type ChildProcess } from \"node:child_process\";\nimport { Readable, Writable } from \"node:stream\";\nimport * as acp from \"@agentclientprotocol/sdk\";\nimport type {\n AgentCapabilities as AcpAgentCapabilities,\n ContentChunk,\n SessionConfigOption,\n SessionConfigSelectOptions,\n SessionNotification,\n SessionUpdate,\n ToolCallUpdate,\n} from \"@agentclientprotocol/sdk\";\nimport type {\n AgentBackend,\n AgentCapabilities,\n AgentModelOption,\n AgentModelState,\n AgentName,\n AgentRunRequest,\n AgentRunResult,\n Usage,\n} from \"./types.js\";\nimport { EMPTY_USAGE } from \"./types.js\";\nimport { definitionOf } from \"./registry.js\";\nimport { VBOT_VERSION } from \"../version.js\";\nimport type { AgentConfig } from \"../config.js\";\n\nexport class AgentAbortError extends Error {\n constructor() {\n super(\"Aborted\");\n this.name = \"AbortError\";\n }\n}\n\nexport class AgentStartError extends Error {\n constructor(\n message: string,\n readonly stderr: string\n ) {\n super(message);\n this.name = \"AgentStartError\";\n }\n}\n\ninterface Turn {\n text: string;\n usage: Usage;\n sawCost: boolean;\n onEvent?: (event: unknown) => void;\n}\n\nconst STDERR_LIMIT = 4_000;\n\n/** 拍平 ACP 的 select 选项(兼容分组的 options)。 */\nfunction flattenSelectOptions(options: SessionConfigSelectOptions): AgentModelOption[] {\n return options.flatMap((entry) =>\n \"group\" in entry\n ? entry.options.map((option) => ({ value: option.value, label: option.name }))\n : [{ value: entry.value, label: entry.name }]\n );\n}\n\n/** 命中模型配置项:优先语义分类 category=model,回退 id=model。 */\nfunction isModelOption(option: SessionConfigOption): boolean {\n return option.type === \"select\" && (option.category === \"model\" || option.id === \"model\");\n}\n\n/** 通过 ACP stdio 驱动单个 coding agent 子进程。 */\nexport class AcpAgent implements AgentBackend {\n private child: ChildProcess | null = null;\n private connection: acp.ClientConnection | null = null;\n private ctx: acp.ClientContext | null = null;\n private startPromise: Promise<void> | null = null;\n private session: string | null = null;\n private configOptions: SessionConfigOption[] = [];\n private initCaps: AcpAgentCapabilities | undefined;\n private turn: Turn | null = null;\n private stderr = \"\";\n private sawUsageCost = false;\n private pendingModel: string | null = null;\n\n constructor(\n readonly name: AgentName,\n private readonly config: AgentConfig\n ) {}\n\n capabilities(): AgentCapabilities {\n return {\n resume: Boolean(this.initCaps?.sessionCapabilities?.resume),\n load: Boolean(this.initCaps?.loadSession),\n setConfigOption: this.configOptions.length > 0,\n usageCost: this.sawUsageCost,\n };\n }\n\n sessionId(): string | null {\n return this.session;\n }\n\n currentModel(): AgentModelState | null {\n const option = this.configOptions.find(isModelOption);\n if (!option || option.type !== \"select\") return null;\n const value = String(option.currentValue);\n const options = flattenSelectOptions(option.options);\n const label = options.find((entry) => entry.value === value)?.label ?? value;\n return { value, label, options };\n }\n\n resetSession(): void {\n this.session = null;\n }\n\n async start(): Promise<void> {\n if (this.connection) return;\n if (this.startPromise) return this.startPromise;\n this.startPromise = this.doStart().finally(() => {\n this.startPromise = null;\n });\n return this.startPromise;\n }\n\n private async doStart(): Promise<void> {\n const definition = definitionOf(this.name);\n const command = this.config.command ?? definition.command.command;\n const args = this.config.args ?? definition.command.args;\n\n const child = spawn(command, args, {\n cwd: this.config.cwd,\n env: { ...process.env, ...this.config.env },\n stdio: [\"pipe\", \"pipe\", \"pipe\"],\n });\n this.child = child;\n this.stderr = \"\";\n\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n this.stderr = `${this.stderr}${chunk.toString()}`.slice(-STDERR_LIMIT);\n if (this.stderr.length > 0) {\n console.error(`[${this.name}] ${chunk.toString().trimEnd()}`);\n }\n });\n\n child.on(\"exit\", (code, signal) => {\n if (this.child === child) {\n this.connection = null;\n this.ctx = null;\n this.child = null;\n }\n if (code !== 0 && signal !== \"SIGTERM\") {\n console.error(`[${this.name}] exited with code ${code ?? \"?\"} signal ${signal ?? \"-\"}`);\n }\n });\n\n if (!child.stdout || !child.stdin) {\n child.kill();\n throw new AgentStartError(\n `Failed to start ${this.name}: stdio pipes are unavailable`,\n this.stderr\n );\n }\n\n const input = Writable.toWeb(child.stdin) as unknown as WritableStream<Uint8Array>;\n const output = Readable.toWeb(child.stdout) as unknown as ReadableStream<Uint8Array>;\n const stream = acp.ndJsonStream(input, output);\n\n const app = acp.client({ name: \"vbot\" });\n app.onRequest(acp.methods.client.session.requestPermission, ({ params }) => {\n const options = params.options;\n const chosen =\n options.find((option) => option.kind === \"allow_always\") ??\n options.find((option) => option.kind === \"allow_once\");\n if (!chosen) {\n return { outcome: { outcome: \"cancelled\" as const } };\n }\n return { outcome: { outcome: \"selected\" as const, optionId: chosen.optionId } };\n });\n app.onNotification(acp.methods.client.session.update, ({ params }) => {\n this.handleUpdate(params);\n });\n\n const connection = app.connect(stream);\n this.connection = connection;\n this.ctx = connection.agent;\n\n try {\n const init = await this.ctx.request(acp.methods.agent.initialize, {\n protocolVersion: 1,\n clientCapabilities: {},\n clientInfo: { name: \"vbot\", version: VBOT_VERSION },\n });\n this.initCaps = init.agentCapabilities;\n } catch (error) {\n await this.close();\n throw new AgentStartError(\n `Failed to initialize ${this.name}: ${error instanceof Error ? error.message : String(error)}`,\n this.stderr\n );\n }\n }\n\n private async ensureSession(\n savedSessionId?: string\n ): Promise<{ sessionId: string; isNew: boolean }> {\n if (!this.ctx) throw new Error(`${this.name} is not started`);\n if (this.session) return { sessionId: this.session, isNew: false };\n\n if (savedSessionId) {\n const caps = this.initCaps;\n try {\n if (caps?.sessionCapabilities?.resume) {\n const resumed = await this.ctx.request(acp.methods.agent.session.resume, {\n sessionId: savedSessionId,\n cwd: this.config.cwd,\n mcpServers: [],\n });\n this.configOptions = resumed.configOptions ?? [];\n this.session = savedSessionId;\n return { sessionId: savedSessionId, isNew: false };\n }\n if (caps?.loadSession) {\n const loaded = await this.ctx.request(acp.methods.agent.session.load, {\n sessionId: savedSessionId,\n cwd: this.config.cwd,\n mcpServers: [],\n });\n this.configOptions = loaded.configOptions ?? [];\n this.session = savedSessionId;\n return { sessionId: savedSessionId, isNew: false };\n }\n } catch (error) {\n console.warn(\n `[${this.name}] failed to resume session ${savedSessionId}, starting a new one: ${\n error instanceof Error ? error.message : String(error)\n }`\n );\n }\n }\n\n const created = await this.ctx.request(acp.methods.agent.session.new, {\n cwd: this.config.cwd,\n mcpServers: [],\n });\n this.session = created.sessionId;\n this.configOptions = created.configOptions ?? [];\n return { sessionId: created.sessionId, isNew: true };\n }\n\n async run(request: AgentRunRequest): Promise<AgentRunResult> {\n await this.start();\n const opened = await this.ensureSession(request.sessionId);\n\n const model = request.model ?? this.pendingModel;\n if (model) {\n await this.setModel(model).catch(() => false);\n }\n\n const turn: Turn = {\n text: \"\",\n usage: { ...EMPTY_USAGE },\n sawCost: false,\n onEvent: request.onEvent as ((event: unknown) => void) | undefined,\n };\n this.turn = turn;\n\n const aborted = new Promise<never>((_, reject) => {\n if (request.signal.aborted) {\n reject(new AgentAbortError());\n return;\n }\n request.signal.addEventListener(\"abort\", () => reject(new AgentAbortError()), { once: true });\n });\n const onAbort = () => this.cancel().catch(() => undefined);\n if (request.signal.aborted) onAbort();\n else request.signal.addEventListener(\"abort\", onAbort, { once: true });\n\n try {\n if (!this.ctx) throw new Error(`${this.name} is not started`);\n const pending = this.ctx.request(\n acp.methods.agent.session.prompt,\n {\n sessionId: opened.sessionId,\n prompt: [{ type: \"text\", text: request.prompt }],\n },\n { cancellationSignal: request.signal, stopWaitingOnCancel: true }\n );\n // 如果 abort 先到,避免 prompt 后续 rejection 变成 unhandled。\n pending.catch(() => undefined);\n const response = await Promise.race([pending, aborted]);\n\n // 让同一连接上的 session/update 通知先处理完,再读取累计文本。\n await new Promise<void>((resolve) => setImmediate(resolve));\n\n if (response.stopReason === \"cancelled\" || request.signal.aborted) {\n throw new AgentAbortError();\n }\n\n return {\n text: turn.text,\n sessionId: opened.sessionId,\n usage: turn.usage,\n newSession: opened.isNew,\n };\n } catch (error) {\n if (request.signal.aborted || (error instanceof Error && error.name === \"AbortError\")) {\n throw new AgentAbortError();\n }\n throw error;\n } finally {\n request.signal.removeEventListener(\"abort\", onAbort);\n this.turn = null;\n }\n }\n\n async cancel(): Promise<void> {\n if (!this.ctx || !this.session) return;\n try {\n await this.ctx.notify(acp.methods.agent.session.cancel, { sessionId: this.session });\n } catch {\n // 连接已断开时忽略;子进程退出会由下一次 run 重新拉起。\n }\n }\n\n async setModel(model: string): Promise<boolean> {\n if (!this.ctx || !this.session) {\n this.pendingModel = model;\n return true;\n }\n const option = this.configOptions.find(isModelOption);\n if (!option) return false;\n const response = await this.ctx.request(acp.methods.agent.session.setConfigOption, {\n sessionId: this.session,\n configId: option.id,\n value: model,\n });\n // 服务端会回传最新 configOptions;不覆盖会导致 /model 立即读回旧值。\n // 空数组不作覆盖:部分后端在 set_config_option 里不回传完整选项表,覆盖会让当前模型丢失。\n if (response?.configOptions?.length) this.configOptions = response.configOptions;\n this.pendingModel = null;\n return true;\n }\n\n async close(): Promise<void> {\n const child = this.child;\n const connection = this.connection;\n this.child = null;\n this.connection = null;\n this.ctx = null;\n this.session = null;\n this.configOptions = [];\n this.pendingModel = null;\n this.turn = null;\n try {\n connection?.close();\n } catch {\n // 已关闭\n }\n if (!child || child.exitCode !== null) return;\n const exited = new Promise<void>((resolve) => {\n child.once(\"exit\", () => resolve());\n });\n child.kill(\"SIGTERM\");\n const timer = setTimeout(() => child.kill(\"SIGKILL\"), 3_000);\n await exited;\n clearTimeout(timer);\n }\n\n private handleUpdate(notification: SessionNotification): void {\n if (notification.sessionId !== this.session) return;\n const turn = this.turn;\n if (!turn) return;\n this.dispatchUpdate(notification.update, turn);\n }\n\n private dispatchUpdate(update: SessionUpdate, turn: Turn): void {\n switch (update.sessionUpdate) {\n case \"agent_message_chunk\":\n this.applyContentChunk(update as ContentChunk, turn, \"text\");\n break;\n case \"agent_thought_chunk\":\n this.applyContentChunk(update as ContentChunk, turn, \"thought\");\n break;\n case \"tool_call\":\n turn.onEvent?.({ type: \"tool\", name: update.title, status: update.status ?? \"pending\" });\n break;\n case \"tool_call_update\":\n this.applyToolUpdate(update as ToolCallUpdate, turn);\n break;\n case \"usage_update\":\n this.applyUsage(update, turn);\n break;\n case \"config_option_update\":\n this.configOptions = update.configOptions;\n break;\n default:\n break;\n }\n }\n\n private applyContentChunk(chunk: ContentChunk, turn: Turn, kind: \"text\" | \"thought\"): void {\n if (chunk.content.type !== \"text\") return;\n if (kind === \"text\") turn.text += chunk.content.text;\n turn.onEvent?.({ type: kind, text: chunk.content.text });\n }\n\n private applyToolUpdate(tool: ToolCallUpdate, turn: Turn): void {\n turn.onEvent?.({\n type: \"tool\",\n name: tool.title ?? tool.toolCallId,\n status: tool.status ?? \"pending\",\n });\n }\n\n private applyUsage(\n update: Extract<SessionUpdate, { sessionUpdate: \"usage_update\" }>,\n turn: Turn\n ): void {\n turn.usage = { used: update.used, size: update.size, cost: update.cost ?? null };\n if (update.cost) {\n turn.sawCost = true;\n this.sawUsageCost = true;\n }\n turn.onEvent?.({ type: \"usage\", usage: turn.usage });\n }\n}\n","// Agent 后端抽象。四个后端都通过 ACP 驱动,差异只体现在启动命令与能力探测上。\n\nexport type AgentName = \"claude\" | \"codex\" | \"opencode\" | \"pi\";\n\nexport interface AgentCommand {\n command: string;\n args: string[];\n}\n\nexport interface Usage {\n /** 当前上下文 token 数(ACP v1 usage_update.used)。 */\n used: number;\n /** 上下文窗口大小(ACP v1 usage_update.size)。 */\n size: number;\n /** 累计成本,单位由 agent 决定;不提供时为 null。 */\n cost: { amount: number; currency: string } | null;\n}\n\nexport const EMPTY_USAGE: Usage = { used: 0, size: 0, cost: null };\n\nexport type AgentEvent =\n | { type: \"text\"; text: string }\n | { type: \"thought\"; text: string }\n | { type: \"tool\"; name: string; status: string }\n | { type: \"usage\"; usage: Usage };\n\nexport interface AgentRunRequest {\n prompt: string;\n /** 已保存的 ACP session id;为空或后端不支持 resume 时新建。 */\n sessionId?: string;\n cwd: string;\n model?: string | null;\n signal: AbortSignal;\n onEvent?: (event: AgentEvent) => void;\n}\n\nexport interface AgentRunResult {\n text: string;\n sessionId: string;\n usage: Usage;\n /** true 表示本次是新会话(用于提示用户上下文已重置)。 */\n newSession: boolean;\n}\n\n/** 一个可选的模型(ACP session config 的 select 值)。 */\nexport interface AgentModelOption {\n value: string;\n label: string;\n}\n\n/** 当前模型状态,从 ACP session config 推导;未建立会话时为 null。 */\nexport interface AgentModelState {\n /** 当前生效模型的 ACP 值(/model 切换时使用)。 */\n value: string;\n /** 当前生效模型的可读名(优先 option.name,回退 value)。 */\n label: string;\n /** 可选模型列表;后端不暴露时为空数组。 */\n options: AgentModelOption[];\n}\n\nexport interface AgentCapabilities {\n resume: boolean;\n load: boolean;\n setConfigOption: boolean;\n usageCost: boolean;\n}\n\nexport interface AgentBackend {\n readonly name: AgentName;\n /** 启动子进程并完成 initialize;可重复调用(已启动则直接返回)。 */\n start(): Promise<void>;\n /** 运行一轮 prompt。内部负责 session 新建/恢复。 */\n run(request: AgentRunRequest): Promise<AgentRunResult>;\n /** 取消当前 prompt。 */\n cancel(): Promise<void>;\n /** 切换模型;返回 false 表示当前后端不支持。 */\n setModel(model: string): Promise<boolean>;\n /** 丢弃当前 ACP session;下一次 run 会新建会话。 */\n resetSession(): void;\n /** 关闭子进程并清理资源。 */\n close(): Promise<void>;\n capabilities(): AgentCapabilities;\n /** 当前 ACP session id(可能为空)。 */\n sessionId(): string | null;\n /** 当前模型;后端未暴露模型配置项或会话未建立时返回 null。 */\n currentModel(): AgentModelState | null;\n}\n","/** 与 package.json 的 version 保持一致;发布时同步更新。 */\nexport const VBOT_VERSION = \"0.1.3\";\n","export type ReplyFn = (text: string) => Promise<void>;\n\nexport interface QueueItem {\n text: string;\n msgUid?: string;\n reply: ReplyFn;\n}\n\nexport type Processor = (item: QueueItem, signal: AbortSignal) => Promise<void>;\n\nexport interface QueueStatus {\n busy: boolean;\n queued: number;\n current: string | null;\n}\n\n/** 单 bot 串行队列:同一时间只跑一轮 agent,其余排队。 */\nexport class BotQueue {\n private readonly items: QueueItem[] = [];\n private running = false;\n private controller: AbortController | null = null;\n private currentText: string | null = null;\n\n constructor(private readonly processor: Processor) {}\n\n async enqueue(item: QueueItem): Promise<void> {\n if (this.running) {\n const ahead = this.items.length + 1;\n this.items.push(item);\n await item.reply(`Queued — ${ahead} message(s) ahead of you`);\n return;\n }\n this.running = true;\n this.items.push(item);\n try {\n await this.drain();\n } finally {\n this.running = false;\n this.controller = null;\n this.currentText = null;\n }\n }\n\n /** 中止当前任务并清空队列;返回是否有任务被中止。 */\n stop(): boolean {\n const wasBusy = this.running;\n this.controller?.abort();\n this.controller = null;\n this.items.length = 0;\n return wasBusy;\n }\n\n status(): QueueStatus {\n return { busy: this.running, queued: this.items.length, current: this.currentText };\n }\n\n private async drain(): Promise<void> {\n while (this.items.length > 0) {\n const item = this.items.shift();\n if (!item) break;\n this.controller = new AbortController();\n this.currentText = item.text;\n try {\n await this.processor(item, this.controller.signal);\n } catch (error) {\n console.error(\"[queue] processor error:\", error);\n await item\n .reply(`Error: ${error instanceof Error ? error.message : String(error)}`)\n .catch(() => undefined);\n } finally {\n this.controller = null;\n this.currentText = null;\n }\n }\n }\n}\n","import { homedir } from \"node:os\";\nimport { AGENTS, AGENT_NAMES, isAgentName } from \"../agents/registry.js\";\nimport type { AgentBackend, AgentCapabilities, AgentName } from \"../agents/types.js\";\nimport type { VbotConfig } from \"../config.js\";\nimport type { BotQueue } from \"./queue.js\";\nimport type { VbotState } from \"./state.js\";\nimport { VBOT_VERSION } from \"../version.js\";\n\n// 命令输出统一走 GFM 表格:Web 端 react-markdown + remark-gfm、RN 端 markdown-body 都已渲染 table。\n// /status 额外保留「首行摘要」,因为会话列表预览与推送只取消息首行。\nconst HELP_ROWS: ReadonlyArray<readonly [string, string]> = [\n [\"/new\", \"Start a new session\"],\n [\"/stop\", \"Abort the current request\"],\n [\"/status\", \"Show agent, session and queue status\"],\n [\"/agent [name]\", \"Show or switch agent backend\"],\n [\"/model [name]\", \"Show or switch model\"],\n [\"/cost\", \"Show context usage and cost\"],\n [\"/version\", \"Show vbot version\"],\n [\"/help\", \"Show this help\"],\n];\n\nconst HELP_FOOTER = \"Other /commands are sent to the agent as prompts.\";\nconst NEW_BUSY_TEXT = \"Cannot reset the session while a request is running. Use /stop first.\";\nconst MODEL_BUSY_TEXT = \"Cannot switch model while a request is running. Use /stop first.\";\n\nexport const HELP_TEXT = [\n table(\n [\"Command\", \"Description\"],\n HELP_ROWS.map(([command, description]) => [command, description])\n ),\n \"\",\n HELP_FOOTER,\n].join(\"\\n\");\n\nexport interface Runtime {\n config(): VbotConfig;\n agent(): AgentBackend;\n queue(): BotQueue;\n state(): VbotState;\n saveState(): void;\n saveConfig(): void;\n /** 串行化对 agent 内部状态的写操作(复用 server 的 gate,避免与进行中的 turn 竞争)。 */\n serialize<T>(task: () => Promise<T>): Promise<T>;\n /** 切换后端;返回给用户的提示。失败时抛错。 */\n switchAgent(name: AgentName): Promise<string>;\n}\n\nexport type Dispatch = (text: string, reply: (text: string) => Promise<void>) => void;\n\ntype Send = (message: string) => void;\n\nexport function createDispatcher(runtime: Runtime): Dispatch {\n return (text, reply) => {\n const send: Send = (message) => {\n reply(message).catch((error) => console.error(\"[dispatch] reply failed:\", error));\n };\n\n const prompt = text.startsWith(\"/\") ? handleSlashCommand(runtime, text, send) : text;\n if (prompt === null) return;\n\n runtime\n .queue()\n .enqueue({ text: prompt, reply })\n .catch((error) => {\n console.error(\"[dispatch] enqueue failed:\", error);\n send(\"System error, please try again later.\");\n });\n };\n}\n\n/** 转义单元格:竖线会破坏表格,换行会破坏行结构。 */\nfunction escapeCell(value: string): string {\n return value.replace(/\\|/g, \"\\\\|\").replace(/\\r?\\n/g, \" \");\n}\n\n/** 生成 GFM 表格;列数为 0 时返回空串(调用方自行处理)。 */\nfunction table(headers: string[], rows: ReadonlyArray<ReadonlyArray<string>>): string {\n const head = `| ${headers.map(escapeCell).join(\" | \")} |`;\n const separator = `| ${headers.map(() => \"---\").join(\" | \")} |`;\n const body = rows.map((row) => `| ${row.map(escapeCell).join(\" | \")} |`);\n return [head, separator, ...body].join(\"\\n\");\n}\n\nfunction formatNumber(value: number): string {\n if (!Number.isFinite(value)) return String(value);\n const negative = value < 0;\n const digits = Math.abs(Math.trunc(value)).toString();\n let out = \"\";\n for (let i = 0; i < digits.length; i += 1) {\n if (i > 0 && (digits.length - i) % 3 === 0) out += \",\";\n out += digits[i];\n }\n return negative ? \"-\" + out : out;\n}\n\nfunction percentOf(used: number, size: number): string | null {\n if (size <= 0) return null;\n return `${((used / size) * 100).toFixed(1)}%`;\n}\n\nfunction usageText(runtime: Runtime): string {\n const { used, size } = runtime.state().usage;\n if (size <= 0) return \"not reported\";\n const base = `${formatNumber(used)} / ${formatNumber(size)}`;\n const percent = percentOf(used, size);\n return percent ? `${base} (${percent})` : base;\n}\n\n/** 把家目录前缀缩成 ~,避免长路径把表格撑爆。 */\nfunction compactPath(path: string): string {\n const home = homedir();\n if (!home) return path;\n if (path === home) return \"~\";\n const prefix = home + \"/\";\n if (path.startsWith(prefix)) return \"~\" + path.slice(home.length);\n return path;\n}\n\nfunction modelText(runtime: Runtime): string {\n const current = runtime.agent().currentModel();\n if (current) return current.label;\n const configured = runtime.config().agent.model;\n if (configured) return `${configured} (configured, not applied yet)`;\n return \"unknown (session not started)\";\n}\n\n/** 返回要转发给 agent 的 prompt;返回 null 表示命令已被处理。 */\nfunction handleSlashCommand(runtime: Runtime, text: string, send: Send): string | null {\n const [rawCommand, ...args] = text.split(/\\s+/);\n switch (rawCommand.toLowerCase()) {\n case \"/new\":\n void handleNew(runtime, send);\n return null;\n case \"/stop\":\n handleStop(runtime, send);\n return null;\n case \"/status\":\n send(statusText(runtime));\n return null;\n case \"/agent\":\n handleAgent(runtime, args, send);\n return null;\n case \"/model\":\n void handleModel(runtime, args, send);\n return null;\n case \"/cost\":\n send(costText(runtime));\n return null;\n case \"/help\":\n send(HELP_TEXT);\n return null;\n case \"/version\":\n send(`vbot v${VBOT_VERSION}`);\n return null;\n default:\n // 未识别的 /command 去掉斜杠后作为 prompt 转发(与 ccbot 行为一致)。\n return text.slice(1);\n }\n}\n\nasync function handleNew(runtime: Runtime, send: Send): Promise<void> {\n // 运行中重置会让当轮流式更新因 sessionId 不匹配被丢弃,回复退化成 (no output);\n // 且 processPrompt 结束后会把旧 sessionId 写回 state。这里直接拒绝,与 /agent 行为一致。\n if (runtime.queue().status().busy) {\n send(NEW_BUSY_TEXT);\n return;\n }\n await runtime.serialize(async () => {\n runtime.agent().resetSession();\n const state = runtime.state();\n state.acpSessionId = null;\n state.usage = { used: 0, size: 0, cost: null };\n runtime.saveState();\n });\n send(\"Session reset. Starting a new conversation.\");\n}\n\nfunction handleStop(runtime: Runtime, send: Send): void {\n const queue = runtime.queue();\n const queued = queue.status().queued;\n if (!queue.stop()) {\n send(\"No running request to stop.\");\n return;\n }\n send(\n queued > 0\n ? `Current request aborted. ${queued} queued message(s) discarded.`\n : \"Current request aborted.\"\n );\n}\n\nfunction handleAgent(runtime: Runtime, args: string[], send: Send): void {\n const name = args.join(\" \").trim();\n const current = runtime.config().agent.name;\n if (!name) {\n send(\n table(\n [\"Agent\", \"Backend\", \"\"],\n AGENT_NAMES.map((entry) => [\n entry,\n AGENTS[entry].label,\n entry === current ? \"← current\" : \"\",\n ])\n )\n );\n return;\n }\n if (!isAgentName(name)) {\n send(`Unknown agent \"${name}\". Available: ${AGENT_NAMES.join(\", \")}`);\n return;\n }\n if (runtime.queue().status().busy) {\n send(\"Cannot switch agent while a request is running. Use /stop first.\");\n return;\n }\n send(`Switching to ${name}...`);\n runtime\n .switchAgent(name)\n .then((message) => send(message))\n .catch((error: unknown) =>\n send(`Error: ${error instanceof Error ? error.message : String(error)}`)\n );\n}\n\nasync function handleModel(runtime: Runtime, args: string[], send: Send): Promise<void> {\n const model = args.join(\" \").trim();\n if (!model) {\n send(modelReport(runtime));\n return;\n }\n // 运行中改模型会与进行中的 turn 竞争(config_option_update 与 prompt 交错),\n // 与 /new 同策略:忙时拒绝,空闲时再进 gate 串行执行。\n if (runtime.queue().status().busy) {\n send(MODEL_BUSY_TEXT);\n return;\n }\n const config = runtime.config();\n const hadSession = runtime.agent().sessionId() !== null;\n const supported = await runtime.serialize(async () => {\n const accepted = await runtime.agent().setModel(model);\n config.agent.model = model;\n runtime.saveConfig();\n return accepted;\n });\n const applied = runtime.agent().currentModel()?.label ?? model;\n if (!supported) {\n send(\n `Model saved: ${model}. This agent does not expose a runtime model option; it will be used on the next session if supported.`\n );\n return;\n }\n send(\n hadSession\n ? `Model switched to: ${applied}`\n : `Model set to: ${applied}. It will apply when the session starts.`\n );\n}\n\n/** 无参 /model:显示 ACP 当前模型与可选模型列表。 */\nfunction modelReport(runtime: Runtime): string {\n const current = runtime.agent().currentModel();\n if (!current) {\n const configured = runtime.config().agent.model;\n const hint = configured\n ? `Configured: ${configured}\\n\\nThe agent has not reported a model yet; it becomes visible after the first message.`\n : \"This agent does not expose a runtime model option, or the session has not started.\";\n return `Current: unknown\\n\\n${hint}`;\n }\n const lines = [`Current: ${current.label}`];\n if (current.options.length > 0) {\n lines.push(\n \"\",\n table(\n [\"Model\", \"\"],\n current.options.map((option) => [\n option.label,\n option.value === current.value ? \"← current\" : \"\",\n ])\n )\n );\n }\n lines.push(\"\", \"Switch: /model <name>\");\n return lines.join(\"\\n\");\n}\n\nfunction statusText(runtime: Runtime): string {\n const config = runtime.config();\n const agent = runtime.agent();\n const state = runtime.state();\n const queue = runtime.queue().status();\n const { used, size } = state.usage;\n\n const summary = [\n `**${config.agent.name}**`,\n queue.busy ? \"busy\" : \"idle\",\n size > 0 ? `${formatNumber(used)} / ${formatNumber(size)}` : null,\n ]\n .filter(Boolean)\n .join(\" · \");\n\n const rows: string[][] = [\n [\"Agent\", `${config.agent.name} (${AGENTS[config.agent.name].label})`],\n [\"Session\", agent.sessionId() ?? \"none\"],\n [\"Work dir\", compactPath(config.agent.cwd)],\n [\"Model\", modelText(runtime)],\n [\"Status\", queue.busy ? \"busy\" : \"idle\"],\n [\"Queue\", String(queue.queued)],\n [\"Usage\", usageText(runtime)],\n [\"Capabilities\", capabilitiesText(agent.capabilities())],\n ];\n\n return [summary, \"\", table([\"Field\", \"Value\"], rows)].join(\"\\n\");\n}\n\nfunction costText(runtime: Runtime): string {\n const usage = runtime.state().usage;\n const cost = usage.cost\n ? `${usage.cost.amount} ${usage.cost.currency}`\n : \"not reported by this agent\";\n return table(\n [\"Field\", \"Value\"],\n [\n [\"Context\", usageText(runtime)],\n [\"Cost\", cost],\n ]\n );\n}\n\nfunction capabilitiesText(caps: AgentCapabilities): string {\n const enabled = [\n caps.resume ? \"resume\" : null,\n caps.load ? \"load\" : null,\n caps.setConfigOption ? \"model\" : null,\n caps.usageCost ? \"cost\" : null,\n ].filter(Boolean);\n return enabled.length > 0 ? enabled.join(\", \") : \"basic\";\n}\n","/** 串行执行异步任务:用于让 prompt 与 /agent 切换互斥,避免切换期间中断进行中的请求。 */\nexport function createGate() {\n let tail: Promise<unknown> = Promise.resolve();\n return function run<T>(task: () => Promise<T>): Promise<T> {\n const result = tail.then(task, task);\n tail = result.then(\n () => undefined,\n () => undefined\n );\n return result;\n };\n}\n","import { AcpAgent } from \"../agents/acp.js\";\nimport { AGENTS } from \"../agents/registry.js\";\nimport { EMPTY_USAGE, type AgentBackend, type AgentName } from \"../agents/types.js\";\nimport type { AgentConfig, VbotConfig } from \"../config.js\";\nimport type { VbotState } from \"./state.js\";\n\nexport interface SwitchContext {\n config: VbotConfig;\n state: VbotState;\n getAgent(): AgentBackend;\n setAgent(agent: AgentBackend): void;\n saveConfig(): void;\n saveState(): void;\n /** 测试注入;默认创建 AcpAgent。 */\n createAgent?(name: AgentName, config: AgentConfig): AgentBackend;\n}\n\n/**\n * 切换到另一个 agent 后端。\n * 先启动新实例并切换引用,再关闭旧实例:避免关闭旧进程时中断新请求。\n * 调用方负责用 gate 串行化,保证切换期间没有 prompt 在跑。\n */\nexport async function switchAgent(ctx: SwitchContext, name: AgentName): Promise<string> {\n const previous = ctx.getAgent();\n const nextConfig: AgentConfig = {\n ...ctx.config.agent,\n name,\n command: undefined,\n args: undefined,\n model: null,\n };\n const next = ctx.createAgent ? ctx.createAgent(name, nextConfig) : new AcpAgent(name, nextConfig);\n await next.start();\n ctx.setAgent(next);\n\n ctx.config.agent = nextConfig;\n ctx.state.agent = name;\n ctx.state.acpSessionId = null;\n ctx.state.usage = { ...EMPTY_USAGE };\n ctx.saveConfig();\n ctx.saveState();\n\n await previous.close().catch(() => undefined);\n return `Switched to ${name} (${AGENTS[name].label}). A new session will start.`;\n}\n","import {\n closeSync,\n existsSync,\n mkdirSync,\n openSync,\n readFileSync,\n unlinkSync,\n writeSync,\n} from \"node:fs\";\nimport { join } from \"node:path\";\nimport { stateDir, tokenHash } from \"./state.js\";\n\nexport class LockError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"LockError\";\n }\n}\n\nconst lockPath = (token: string) => join(stateDir(), `${tokenHash(token)}.lock`);\n\nfunction readPid(path: string): number | null {\n try {\n const pid = Number.parseInt(readFileSync(path, \"utf8\").trim(), 10);\n return Number.isFinite(pid) && pid > 0 ? pid : null;\n } catch {\n return null;\n }\n}\n\nfunction isAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\n/**\n * 同一 token 只允许一个 vbot 实例。服务端按 botId 只保留最后一个 WS 连接,\n * 多开会互相顶掉;这里用本地文件锁提前拒绝。\n */\nexport function acquireLock(token: string): () => void {\n mkdirSync(stateDir(), { recursive: true });\n const path = lockPath(token);\n\n for (let attempt = 0; attempt < 2; attempt += 1) {\n try {\n const fd = openSync(path, \"wx\");\n writeSync(fd, String(process.pid));\n closeSync(fd);\n return () => releaseLock(token);\n } catch (error) {\n if (!(error instanceof Error) || !(\"code\" in error) || error.code !== \"EEXIST\") {\n throw error;\n }\n const pid = readPid(path);\n if (pid && isAlive(pid)) {\n throw new LockError(`This bot is already running in another vbot process (pid ${pid}).`);\n }\n // 残留锁:上一个进程异常退出。删除后重试一次。\n try {\n unlinkSync(path);\n } catch {\n // 忽略并发删除失败,下一轮会重新判断。\n }\n }\n }\n\n throw new LockError(\"Failed to acquire vbot lock; please retry.\");\n}\n\nexport function releaseLock(token: string): void {\n const path = lockPath(token);\n if (!existsSync(path)) return;\n const pid = readPid(path);\n if (pid !== process.pid) return;\n try {\n unlinkSync(path);\n } catch {\n // 进程退出阶段清理失败不阻塞。\n }\n}\n","import { createHash } from \"node:crypto\";\nimport {\n existsSync,\n mkdirSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { EMPTY_USAGE, type AgentName, type Usage } from \"../agents/types.js\";\n\n/** vbot 的本地数据目录;测试通过 VBOT_HOME 指向临时目录。 */\nexport function vbotHome(): string {\n return process.env.VBOT_HOME?.trim() || join(homedir(), \".vbot\");\n}\n\nexport function stateDir(): string {\n return join(vbotHome(), \"state\");\n}\n\nexport interface VbotState {\n tokenHash: string;\n agent: AgentName;\n acpSessionId: string | null;\n cwd: string;\n createdAt: string;\n lastUsedAt: string;\n usage: Usage;\n}\n\n/** token 的 SHA-256 前 16 位:不落明文 token,且一个 token 稳定对应一个状态文件。 */\nexport function tokenHash(token: string): string {\n return createHash(\"sha256\").update(token).digest(\"hex\").slice(0, 16);\n}\n\nexport function statePath(token: string): string {\n return join(stateDir(), `${tokenHash(token)}.json`);\n}\n\nexport function emptyState(token: string, agent: AgentName, cwd: string): VbotState {\n const now = new Date().toISOString();\n return {\n tokenHash: tokenHash(token),\n agent,\n acpSessionId: null,\n cwd,\n createdAt: now,\n lastUsedAt: now,\n usage: { ...EMPTY_USAGE },\n };\n}\n\nexport function loadState(token: string): VbotState | null {\n const path = statePath(token);\n if (!existsSync(path)) return null;\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as Partial<VbotState>;\n if (typeof parsed.acpSessionId !== \"string\" && parsed.acpSessionId !== null) return null;\n if (typeof parsed.agent !== \"string\") return null;\n return {\n tokenHash: tokenHash(token),\n agent: parsed.agent as AgentName,\n acpSessionId: parsed.acpSessionId ?? null,\n cwd: typeof parsed.cwd === \"string\" ? parsed.cwd : process.cwd(),\n createdAt: typeof parsed.createdAt === \"string\" ? parsed.createdAt : new Date().toISOString(),\n lastUsedAt:\n typeof parsed.lastUsedAt === \"string\" ? parsed.lastUsedAt : new Date().toISOString(),\n usage:\n parsed.usage && typeof parsed.usage === \"object\"\n ? { ...EMPTY_USAGE, ...parsed.usage }\n : { ...EMPTY_USAGE },\n };\n } catch {\n // 损坏的状态文件按不存在处理,避免阻塞启动。\n return null;\n }\n}\n\n/** 原子写入状态文件;失败时抛错由调用方决定是否降级。 */\nexport function saveState(state: VbotState): void {\n const dir = stateDir();\n mkdirSync(dir, { recursive: true });\n const path = join(dir, `${state.tokenHash}.json`);\n const tmp = `${path}.${process.pid}.tmp`;\n writeFileSync(tmp, `${JSON.stringify(state, null, 2)}\\n`, { mode: 0o600 });\n renameSync(tmp, path);\n}\n\nexport function clearState(token: string): void {\n const path = statePath(token);\n if (existsSync(path)) {\n try {\n unlinkSync(path);\n } catch {\n // 清理失败不影响 /new,下一次写入会覆盖。\n }\n }\n}\n","import WebSocket from \"ws\";\n\nexport interface WireHandlers {\n onPrompt: (\n text: string,\n msgUid: string | undefined,\n reply: (text: string) => Promise<void>\n ) => void;\n onReady?: () => void;\n onDisconnected?: () => void;\n onFatal?: (error: Error) => void;\n}\n\nexport interface WireOptions {\n baseUrl: string;\n token: string;\n handlers: WireHandlers;\n}\n\nconst RECONNECT_BASE_MS = 1_000;\nconst RECONNECT_MAX_MS = 30_000;\nconst HEARTBEAT_MS = 30_000;\nconst INVALID_TOKEN_CODE = 4001;\n\ninterface ServerFrame {\n type?: string;\n msgUid?: string;\n text?: string;\n}\n\nfunction trimTrailingSlash(value: string): string {\n let end = value.length;\n while (end > 0 && value[end - 1] === \"/\") end -= 1;\n return value.slice(0, end);\n}\n\n/** vicvic.im bot WS 地址;http(s) 自动改写为 ws(s)。 */\nexport function botUrl(baseUrl: string, token: string): string {\n const wsBase = trimTrailingSlash(baseUrl.replace(/^http/, \"ws\"));\n return `${wsBase}/bot/connect?token=${encodeURIComponent(token)}`;\n}\n\n/**\n * 与 app-server 的 bot 通道。协议与 ccbot 完全一致:\n * server -> {type:\"ready\"} / {type:\"prompt\", msgUid, text}\n * client -> {type:\"reply\", msgUid, text}\n */\nexport class VicvicWire {\n private socket: WebSocket | null = null;\n private stopped = false;\n private attempt = 0;\n private reconnectTimer: NodeJS.Timeout | null = null;\n private heartbeatTimer: NodeJS.Timeout | null = null;\n\n constructor(private readonly options: WireOptions) {}\n\n start(): void {\n this.stopped = false;\n this.connect();\n }\n\n stop(): void {\n this.stopped = true;\n if (this.reconnectTimer) {\n clearTimeout(this.reconnectTimer);\n this.reconnectTimer = null;\n }\n this.clearHeartbeat();\n this.socket?.close();\n this.socket = null;\n }\n\n /** 发送回复;socket 不可用时 reject,由调用方决定是否记录日志。 */\n async reply(msgUid: string | undefined, text: string): Promise<void> {\n const socket = this.socket;\n if (!socket || socket.readyState !== WebSocket.OPEN) {\n throw new Error(\"Bot connection is not open\");\n }\n await new Promise<void>((resolve, reject) => {\n socket.send(JSON.stringify({ type: \"reply\", msgUid, text }), (error) => {\n if (error) reject(error);\n else resolve();\n });\n });\n }\n\n private connect(): void {\n if (this.stopped) return;\n const url = botUrl(this.options.baseUrl, this.options.token);\n const socket = new WebSocket(url);\n this.socket = socket;\n\n socket.on(\"open\", () => {\n this.attempt = 0;\n this.startHeartbeat();\n console.log(\"[vicvic] connected\");\n });\n\n socket.on(\"message\", (raw) => {\n let frame: ServerFrame;\n try {\n frame = JSON.parse(String(raw)) as ServerFrame;\n } catch {\n return; // 非 JSON 帧直接忽略\n }\n if (frame.type === \"ready\") {\n console.log(\"[vicvic] ready\");\n this.options.handlers.onReady?.();\n return;\n }\n if (frame.type === \"prompt\" && typeof frame.text === \"string\" && frame.text.length > 0) {\n this.options.handlers.onPrompt(frame.text, frame.msgUid, (text) =>\n this.reply(frame.msgUid, text)\n );\n }\n });\n\n socket.on(\"close\", (code, reason) => {\n this.clearHeartbeat();\n if (this.socket === socket) this.socket = null;\n if (code === INVALID_TOKEN_CODE) {\n this.stopped = true;\n this.options.handlers.onFatal?.(\n new Error(`Invalid bot token (${reason.toString() || \"4001\"}).`)\n );\n return;\n }\n console.log(\"[vicvic] disconnected\");\n this.options.handlers.onDisconnected?.();\n this.scheduleReconnect();\n });\n\n socket.on(\"error\", (error: Error) => {\n console.error(\"[vicvic] ws error:\", error.message); // close 随后触发重连\n });\n }\n\n private scheduleReconnect(): void {\n if (this.stopped || this.reconnectTimer) return;\n const delay = Math.min(RECONNECT_BASE_MS * 2 ** this.attempt, RECONNECT_MAX_MS);\n this.attempt += 1;\n console.log(`[vicvic] reconnecting in ${Math.round(delay / 1000)}s`);\n this.reconnectTimer = setTimeout(() => {\n this.reconnectTimer = null;\n this.connect();\n }, delay);\n }\n\n private startHeartbeat(): void {\n this.clearHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n try {\n this.socket?.ping();\n } catch {\n // close 事件负责重连\n }\n }, HEARTBEAT_MS);\n }\n\n private clearHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n}\n","/** 单条 IM 消息的分段上限;E2E 实测腾讯云 IM 上限后再回填方案文档。 */\nexport const MAX_MESSAGE_CHARS = 4000;\n\nfunction isLowSurrogate(code: number): boolean {\n return code >= 0xdc00 && code <= 0xdfff;\n}\n\nfunction fenceCount(text: string): number {\n return (text.match(/```/g) ?? []).length;\n}\n\nfunction avoidSurrogateSplit(text: string, cut: number, start: number): number {\n return cut > start && isLowSurrogate(text.charCodeAt(cut)) ? cut - 1 : cut;\n}\n\nfunction preferNewline(text: string, start: number, cut: number, max: number): number {\n const newline = text.lastIndexOf(\"\\n\", cut);\n return newline >= start + Math.floor(max / 2) ? newline + 1 : cut;\n}\n\nfunction avoidFenceSplit(text: string, start: number, cut: number, max: number): number {\n if (fenceCount(text.slice(start, cut)) % 2 === 0) return cut;\n const fenceStart = text.lastIndexOf(\"```\", cut);\n return fenceStart >= start + Math.floor(max / 4) ? fenceStart : cut;\n}\n\n/** 在 [start, start+max] 内找一个尽量安全的切点。 */\nfunction findCut(text: string, start: number, max: number): number {\n const hardCut = Math.min(start + max, text.length);\n let cut = avoidSurrogateSplit(text, hardCut, start);\n cut = preferNewline(text, start, cut, max);\n cut = avoidFenceSplit(text, start, cut, max);\n return cut > start ? cut : hardCut;\n}\n\n/**\n * 把长文本切成适合单条 IM 消息的段:\n * - 优先在切点前的换行处断开;\n * - 不切断 UTF-16 代理对;\n * - 尽量不把一段切在未闭合的代码块内部(找不到安全切点时退化为硬切)。\n */\nexport function splitMessage(text: string, max: number = MAX_MESSAGE_CHARS): string[] {\n if (!text) return [];\n if (max < 2) throw new Error(\"max must be >= 2\");\n\n const chunks: string[] = [];\n let start = 0;\n\n while (start < text.length) {\n if (text.length - start <= max) {\n chunks.push(text.slice(start));\n break;\n }\n const cut = findCut(text, start, max);\n const chunk = text.slice(start, cut);\n if (chunk.trim().length > 0) chunks.push(chunk);\n start = cut;\n }\n\n return chunks;\n}\n","import { loadConfig, saveConfig, type VbotConfig } from \"./config.js\";\nimport { AcpAgent, AgentAbortError, AgentStartError } from \"./agents/acp.js\";\nimport { AGENTS } from \"./agents/registry.js\";\nimport type { AgentBackend, AgentEvent, AgentName } from \"./agents/types.js\";\nimport { BotQueue, type QueueItem } from \"./core/queue.js\";\nimport { createDispatcher, type Runtime } from \"./core/dispatcher.js\";\nimport { createGate } from \"./core/gate.js\";\nimport { switchAgent } from \"./core/switch.js\";\nimport { acquireLock } from \"./core/lock.js\";\nimport { emptyState, loadState, saveState, type VbotState } from \"./core/state.js\";\nimport { VicvicWire } from \"./core/wire.js\";\nimport { splitMessage } from \"./core/chunk.js\";\n\ninterface BotContext {\n config: VbotConfig;\n configPath: string;\n state: VbotState;\n getAgent(): AgentBackend;\n setAgent(agent: AgentBackend): void;\n getQueue(): BotQueue;\n saveState(): void;\n saveConfig(): void;\n}\n\nexport interface BotHandle {\n finished: Promise<void>;\n stop(): Promise<void>;\n}\n\nfunction replySafe(reply: (text: string) => Promise<void>, text: string): void {\n reply(text).catch((error) => console.error(\"[server] reply failed:\", error));\n}\n\nfunction logAgentEvent(event: AgentEvent): void {\n if (event.type === \"tool\") {\n console.log(`[agent] tool ${event.name} (${event.status})`);\n } else if (event.type === \"usage\") {\n const cost = event.usage.cost ? ` ${event.usage.cost.amount} ${event.usage.cost.currency}` : \"\";\n console.log(`[agent] usage ${event.usage.used}/${event.usage.size}${cost}`);\n } else if (event.type === \"thought\") {\n console.log(`[agent] thought: ${event.text.slice(0, 80)}`);\n }\n}\n\n/** 启动 bot 运行循环;返回可停止的句柄,供 CLI 与测试使用。 */\nexport async function startBot(configPath: string): Promise<BotHandle> {\n const { config } = loadConfig(configPath);\n const token = config.vicvic.token;\n const release = acquireLock(token);\n\n const state = loadState(token) ?? emptyState(token, config.agent.name, config.agent.cwd);\n state.agent = config.agent.name;\n state.cwd = config.agent.cwd;\n\n let agent: AgentBackend = new AcpAgent(config.agent.name, config.agent);\n const gate = createGate();\n let switching = false;\n const holder: { queue: BotQueue | null } = { queue: null };\n const ctx: BotContext = {\n config,\n configPath,\n state,\n getAgent: () => agent,\n setAgent: (next) => {\n agent = next;\n },\n getQueue: () => {\n if (!holder.queue) throw new Error(\"queue is not initialized\");\n return holder.queue;\n },\n saveState: () => {\n state.lastUsedAt = new Date().toISOString();\n saveState(state);\n },\n saveConfig: () => saveConfig(config, configPath),\n };\n holder.queue = new BotQueue((item, signal) => gate(() => processPrompt(ctx, item, signal)));\n\n const runtime = createRuntime(\n ctx,\n (task) => gate(task),\n (name) => {\n if (switching) return Promise.reject(new Error(\"Agent switch already in progress.\"));\n switching = true;\n return gate(() => switchAgent(ctx, name)).finally(() => {\n switching = false;\n });\n }\n );\n const dispatch = createDispatcher(runtime);\n\n let notifySignal: () => void = () => undefined;\n const wire = new VicvicWire({\n baseUrl: config.vicvic.baseUrl,\n token,\n handlers: {\n onPrompt: (text, _msgUid, reply) => {\n if (config.logPrompt) console.log(`[vicvic] prompt: ${text.slice(0, 100)}...`);\n else console.log(\"[vicvic] prompt\");\n dispatch(text, reply);\n },\n onFatal: (error) => {\n console.error(`[vicvic] fatal: ${error.message}`);\n // 2 表示不可恢复的配置错误;pm2 以 --stop-exit-codes 2 避免无限重启。\n process.exitCode = 2;\n notifySignal();\n },\n },\n });\n\n const lifecycle = setupLifecycle(wire, () => agent, release);\n notifySignal = lifecycle.onSignal;\n announce(config);\n wire.start();\n\n return { finished: lifecycle.finished, stop: lifecycle.stop };\n}\n\ninterface Lifecycle {\n finished: Promise<void>;\n onSignal: () => void;\n stop: () => Promise<void>;\n}\n\nfunction setupLifecycle(\n getWire: VicvicWire,\n getAgent: () => AgentBackend,\n release: () => void\n): Lifecycle {\n let finish: () => void = () => undefined;\n const finished = new Promise<void>((resolveFinished) => {\n finish = resolveFinished;\n });\n let stopped = false;\n const onSignal = () => {\n console.log(\"[vbot] shutting down\");\n stop().catch((error) => console.error(\"[server] shutdown failed:\", error));\n };\n const stop = async (): Promise<void> => {\n if (stopped) return;\n stopped = true;\n getWire.stop();\n process.off(\"SIGINT\", onSignal);\n process.off(\"SIGTERM\", onSignal);\n await getAgent()\n .close()\n .catch(() => undefined);\n release();\n finish();\n };\n process.once(\"SIGINT\", onSignal);\n process.once(\"SIGTERM\", onSignal);\n return { finished, onSignal, stop };\n}\n\nfunction announce(config: VbotConfig): void {\n console.warn(\n `vbot runs ${config.agent.name} with your local user permissions and auto-approves permission requests.\\n` +\n \"Only use it in a directory you trust. Authentication must be completed in the agent CLI beforehand.\"\n );\n console.log(AGENTS[config.agent.name].authHint);\n console.log(`vbot starting. agent=${config.agent.name} cwd=${config.agent.cwd}`);\n}\n\n/** 运行直到 SIGINT / SIGTERM 或致命错误。 */\nexport async function runBot(configPath: string): Promise<void> {\n const bot = await startBot(configPath);\n await bot.finished;\n}\n\nfunction createRuntime(\n ctx: BotContext,\n gate: <T>(task: () => Promise<T>) => Promise<T>,\n switchAgent: (name: AgentName) => Promise<string>\n): Runtime {\n return {\n config: () => ctx.config,\n agent: () => ctx.getAgent(),\n queue: () => ctx.getQueue(),\n state: () => ctx.state,\n saveState: () => ctx.saveState(),\n saveConfig: () => ctx.saveConfig(),\n serialize: (task) => gate(task),\n switchAgent,\n };\n}\n\nasync function processPrompt(ctx: BotContext, item: QueueItem, signal: AbortSignal): Promise<void> {\n replySafe(item.reply, \"Processing...\");\n\n const controller = new AbortController();\n let timedOut = false;\n const onAbort = () => controller.abort();\n signal.addEventListener(\"abort\", onAbort, { once: true });\n const timer = setTimeout(() => {\n timedOut = true;\n controller.abort();\n }, ctx.config.timeoutMs);\n\n try {\n const result = await ctx.getAgent().run({\n prompt: item.text,\n sessionId: ctx.state.acpSessionId ?? undefined,\n cwd: ctx.config.agent.cwd,\n model: ctx.config.agent.model,\n signal: controller.signal,\n onEvent: ctx.config.logPrompt ? logAgentEvent : undefined,\n });\n\n ctx.state.acpSessionId = result.sessionId;\n ctx.state.usage = result.usage;\n ctx.saveState();\n\n for (const chunk of splitMessage(result.text || \"(no output)\")) {\n await item.reply(chunk);\n }\n } catch (error) {\n if (error instanceof AgentAbortError) {\n if (timedOut)\n replySafe(item.reply, \"Execution timeout, please retry or simplify your request.\");\n else if (!signal.aborted) replySafe(item.reply, \"Request aborted.\");\n return;\n }\n replyError(item.reply, error);\n } finally {\n clearTimeout(timer);\n signal.removeEventListener(\"abort\", onAbort);\n }\n}\n\nfunction replyError(reply: (text: string) => Promise<void>, error: unknown): void {\n if (error instanceof AgentStartError) {\n console.error(`[server] agent start failed: ${error.message}\\n${error.stderr}`);\n replySafe(reply, `Error: ${error.message}`);\n return;\n }\n console.error(\"[server] agent run failed:\", error);\n replySafe(reply, `Error: ${error instanceof Error ? error.message : String(error)}`);\n}\n"],"mappings":"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","names":["import_node_child_process","import_node_path","import_picocolors","import_node_fs","import_node_path","pc","inquirer","import_node_fs","import_node_path","cliPath","import_node_child_process","resolve","import_node_os","import_node_fs","import_node_path","import_node_fs","import_node_os","import_node_path","trimTrailingSlash","WebSocket","resolve","switchAgent","ENV_BIN","pc"]}
|
package/dist/cli.js
CHANGED
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
ensureConfig
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-CDBYOHVL.js";
|
|
5
5
|
import {
|
|
6
6
|
findConfigPath,
|
|
7
7
|
loadConfig,
|
|
8
8
|
runBot
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-ELLWQDOY.js";
|
|
10
10
|
|
|
11
11
|
// src/cli.ts
|
|
12
|
-
import { execFileSync } from "child_process";
|
|
12
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
13
13
|
import { basename, resolve } from "path";
|
|
14
14
|
import { Command } from "commander";
|
|
15
15
|
import pc from "picocolors";
|
|
@@ -19,7 +19,7 @@ import { existsSync, readFileSync, realpathSync } from "fs";
|
|
|
19
19
|
import { dirname, join } from "path";
|
|
20
20
|
function resolveServerEntry(cliPath2) {
|
|
21
21
|
const real = realpathSync(cliPath2);
|
|
22
|
-
const candidate = join(dirname(real), "server.js");
|
|
22
|
+
const candidate = join(dirname(real), "bin-server.js");
|
|
23
23
|
if (!existsSync(candidate)) {
|
|
24
24
|
throw new Error(`Server bundle not found at ${candidate}. Reinstall @vicvic-im/agent-bot.`);
|
|
25
25
|
}
|
|
@@ -34,21 +34,34 @@ function readPackageVersion(cliPath2) {
|
|
|
34
34
|
}
|
|
35
35
|
}
|
|
36
36
|
|
|
37
|
-
// src/
|
|
38
|
-
|
|
39
|
-
return `vbot-${basename(resolve(cwd)).replace(/[^a-zA-Z0-9._-]+/g, "-")}`;
|
|
40
|
-
}
|
|
37
|
+
// src/core/pm2.ts
|
|
38
|
+
import { execFileSync } from "child_process";
|
|
41
39
|
var ENV_BIN = "/usr/bin/env";
|
|
42
|
-
function hasPm2() {
|
|
40
|
+
function hasPm2(exec = execFileSync) {
|
|
43
41
|
try {
|
|
44
|
-
|
|
42
|
+
exec(ENV_BIN, ["pm2", "--version"], { stdio: "ignore" });
|
|
45
43
|
return true;
|
|
46
44
|
} catch {
|
|
47
45
|
return false;
|
|
48
46
|
}
|
|
49
47
|
}
|
|
48
|
+
function ensurePm2(exec = execFileSync) {
|
|
49
|
+
if (hasPm2(exec)) return true;
|
|
50
|
+
try {
|
|
51
|
+
exec(ENV_BIN, ["npm", "i", "-g", "pm2"], { stdio: "inherit" });
|
|
52
|
+
return hasPm2(exec);
|
|
53
|
+
} catch {
|
|
54
|
+
return false;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// src/cli.ts
|
|
59
|
+
function processName(cwd) {
|
|
60
|
+
return `vbot-${basename(resolve(cwd)).replace(/[^a-zA-Z0-9._-]+/g, "-")}`;
|
|
61
|
+
}
|
|
62
|
+
var ENV_BIN2 = "/usr/bin/env";
|
|
50
63
|
function pm2(args, capture = false) {
|
|
51
|
-
return
|
|
64
|
+
return execFileSync2(ENV_BIN2, ["pm2", ...args], {
|
|
52
65
|
stdio: capture ? "pipe" : "inherit",
|
|
53
66
|
encoding: "utf8"
|
|
54
67
|
});
|
|
@@ -72,12 +85,14 @@ var program = new Command();
|
|
|
72
85
|
program.name("vbot").description("Connect local coding agents to vicvic.im").version(readPackageVersion(cliPath()));
|
|
73
86
|
program.command("start").description("Start vbot (prompts for config on first run)").option("--foreground", "run in the foreground instead of pm2").option("-c, --config <path>", "config file path").action(async (options) => {
|
|
74
87
|
const { path } = await ensureConfig(options.config);
|
|
75
|
-
if (options.foreground
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
88
|
+
if (options.foreground) {
|
|
89
|
+
await runBot(path);
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
92
|
+
if (!hasPm2()) console.log(pc.yellow("pm2 not found, installing globally..."));
|
|
93
|
+
if (!ensurePm2()) {
|
|
94
|
+
console.error(pc.red("Failed to install pm2. Please install manually: npm i -g pm2"));
|
|
95
|
+
console.log(pc.yellow("Running in the foreground instead."));
|
|
81
96
|
await runBot(path);
|
|
82
97
|
return;
|
|
83
98
|
}
|