@vicvic-im/agent-bot 0.0.0-stage → 0.1.1
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 +142 -2
- package/dist/agents/acp.d.ts +42 -0
- package/dist/agents/acp.d.ts.map +1 -0
- package/dist/agents/registry.d.ts +13 -0
- package/dist/agents/registry.d.ts.map +1 -0
- package/dist/agents/types.d.ts +72 -0
- package/dist/agents/types.d.ts.map +1 -0
- package/dist/chunk-QQ2NXJ3L.js +92 -0
- package/dist/chunk-QQ2NXJ3L.js.map +1 -0
- package/dist/chunk-SCVC76UL.js +1331 -0
- package/dist/chunk-SCVC76UL.js.map +1 -0
- package/dist/cli.cjs +1506 -0
- package/dist/cli.cjs.map +1 -0
- package/dist/cli.d.ts +3 -0
- package/dist/cli.d.ts.map +1 -0
- package/dist/cli.js +144 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/setup.d.ts +8 -0
- package/dist/commands/setup.d.ts.map +1 -0
- package/dist/config.d.ts +39 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/core/chunk.d.ts +10 -0
- package/dist/core/chunk.d.ts.map +1 -0
- package/dist/core/cli-path.d.ts +8 -0
- package/dist/core/cli-path.d.ts.map +1 -0
- package/dist/core/dispatcher.d.ts +18 -0
- package/dist/core/dispatcher.d.ts.map +1 -0
- package/dist/core/gate.d.ts +3 -0
- package/dist/core/gate.d.ts.map +1 -0
- package/dist/core/lock.d.ts +10 -0
- package/dist/core/lock.d.ts.map +1 -0
- package/dist/core/queue.d.ts +27 -0
- package/dist/core/queue.d.ts.map +1 -0
- package/dist/core/state.d.ts +22 -0
- package/dist/core/state.d.ts.map +1 -0
- package/dist/core/switch.d.ts +20 -0
- package/dist/core/switch.d.ts.map +1 -0
- package/dist/core/wire.d.ts +36 -0
- package/dist/core/wire.d.ts.map +1 -0
- package/dist/index.cjs +1464 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +13 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +77 -0
- package/dist/index.js.map +1 -0
- package/dist/server.cjs +1309 -0
- package/dist/server.cjs.map +1 -0
- package/dist/server.d.ts +9 -0
- package/dist/server.d.ts.map +1 -0
- package/dist/server.js +9 -0
- package/dist/server.js.map +1 -0
- package/dist/version.d.ts +3 -0
- package/dist/version.d.ts.map +1 -0
- package/package.json +47 -4
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/commands/setup.ts","../src/config.ts","../src/agents/registry.ts","../src/agents/acp.ts","../src/agents/types.ts","../src/core/queue.ts","../src/version.ts","../src/core/dispatcher.ts","../src/core/lock.ts","../src/core/state.ts","../src/core/wire.ts","../src/core/chunk.ts","../src/server.ts","../src/core/gate.ts","../src/core/switch.ts"],"sourcesContent":["export { ensureConfig, type SetupResult } from \"./commands/setup.js\";\nexport {\n CONFIG_FILENAME,\n DEFAULT_BASE_URL,\n DEFAULT_TIMEOUT_MS,\n GLOBAL_CONFIG_PATH,\n ConfigError,\n findConfigPath,\n loadConfig,\n normalizeConfig,\n saveConfig,\n type AgentConfig,\n type VbotConfig,\n} from \"./config.js\";\nexport {\n AGENTS,\n AGENT_NAMES,\n definitionOf,\n isAgentName,\n type AgentDefinition,\n} from \"./agents/registry.js\";\nexport { AcpAgent, AgentAbortError, AgentStartError } from \"./agents/acp.js\";\nexport {\n EMPTY_USAGE,\n type AgentBackend,\n type AgentCapabilities,\n type AgentEvent,\n type AgentName,\n type Usage,\n} from \"./agents/types.js\";\nexport { BotQueue, type QueueItem, type ReplyFn } from \"./core/queue.js\";\nexport { createDispatcher, HELP_TEXT, type Dispatch, type Runtime } from \"./core/dispatcher.js\";\nexport { acquireLock, LockError, releaseLock } from \"./core/lock.js\";\nexport {\n clearState,\n emptyState,\n loadState,\n saveState,\n statePath,\n tokenHash,\n type VbotState,\n} from \"./core/state.js\";\nexport { botUrl, VicvicWire } from \"./core/wire.js\";\nexport { MAX_MESSAGE_CHARS, splitMessage } from \"./core/chunk.js\";\nexport { runBot } from \"./server.js\";\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 { 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","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 { 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","/** 串行执行异步任务:用于让 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"],"mappings":"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","names":["import_node_fs","import_node_path","entry","pc","inquirer","resolve","entry","entry","import_node_fs","import_node_path","import_node_fs","import_node_os","import_node_path","trimTrailingSlash","WebSocket","resolve","import_node_path","switchAgent"]}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export { ensureConfig, type SetupResult } from "./commands/setup.js";
|
|
2
|
+
export { CONFIG_FILENAME, DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS, GLOBAL_CONFIG_PATH, ConfigError, findConfigPath, loadConfig, normalizeConfig, saveConfig, type AgentConfig, type VbotConfig, } from "./config.js";
|
|
3
|
+
export { AGENTS, AGENT_NAMES, definitionOf, isAgentName, type AgentDefinition, } from "./agents/registry.js";
|
|
4
|
+
export { AcpAgent, AgentAbortError, AgentStartError } from "./agents/acp.js";
|
|
5
|
+
export { EMPTY_USAGE, type AgentBackend, type AgentCapabilities, type AgentEvent, type AgentName, type Usage, } from "./agents/types.js";
|
|
6
|
+
export { BotQueue, type QueueItem, type ReplyFn } from "./core/queue.js";
|
|
7
|
+
export { createDispatcher, HELP_TEXT, type Dispatch, type Runtime } from "./core/dispatcher.js";
|
|
8
|
+
export { acquireLock, LockError, releaseLock } from "./core/lock.js";
|
|
9
|
+
export { clearState, emptyState, loadState, saveState, statePath, tokenHash, type VbotState, } from "./core/state.js";
|
|
10
|
+
export { botUrl, VicvicWire } from "./core/wire.js";
|
|
11
|
+
export { MAX_MESSAGE_CHARS, splitMessage } from "./core/chunk.js";
|
|
12
|
+
export { runBot } from "./server.js";
|
|
13
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,qBAAqB,CAAC;AACrE,OAAO,EACL,eAAe,EACf,gBAAgB,EAChB,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,cAAc,EACd,UAAU,EACV,eAAe,EACf,UAAU,EACV,KAAK,WAAW,EAChB,KAAK,UAAU,GAChB,MAAM,aAAa,CAAC;AACrB,OAAO,EACL,MAAM,EACN,WAAW,EACX,YAAY,EACZ,WAAW,EACX,KAAK,eAAe,GACrB,MAAM,sBAAsB,CAAC;AAC9B,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAC7E,OAAO,EACL,WAAW,EACX,KAAK,YAAY,EACjB,KAAK,iBAAiB,EACtB,KAAK,UAAU,EACf,KAAK,SAAS,EACd,KAAK,KAAK,GACX,MAAM,mBAAmB,CAAC;AAC3B,OAAO,EAAE,QAAQ,EAAE,KAAK,SAAS,EAAE,KAAK,OAAO,EAAE,MAAM,iBAAiB,CAAC;AACzE,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,KAAK,QAAQ,EAAE,KAAK,OAAO,EAAE,MAAM,sBAAsB,CAAC;AAChG,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AACrE,OAAO,EACL,UAAU,EACV,UAAU,EACV,SAAS,EACT,SAAS,EACT,SAAS,EACT,SAAS,EACT,KAAK,SAAS,GACf,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ensureConfig
|
|
3
|
+
} from "./chunk-QQ2NXJ3L.js";
|
|
4
|
+
import {
|
|
5
|
+
AGENTS,
|
|
6
|
+
AGENT_NAMES,
|
|
7
|
+
AcpAgent,
|
|
8
|
+
AgentAbortError,
|
|
9
|
+
AgentStartError,
|
|
10
|
+
BotQueue,
|
|
11
|
+
CONFIG_FILENAME,
|
|
12
|
+
ConfigError,
|
|
13
|
+
DEFAULT_BASE_URL,
|
|
14
|
+
DEFAULT_TIMEOUT_MS,
|
|
15
|
+
EMPTY_USAGE,
|
|
16
|
+
GLOBAL_CONFIG_PATH,
|
|
17
|
+
HELP_TEXT,
|
|
18
|
+
LockError,
|
|
19
|
+
MAX_MESSAGE_CHARS,
|
|
20
|
+
VicvicWire,
|
|
21
|
+
acquireLock,
|
|
22
|
+
botUrl,
|
|
23
|
+
clearState,
|
|
24
|
+
createDispatcher,
|
|
25
|
+
definitionOf,
|
|
26
|
+
emptyState,
|
|
27
|
+
findConfigPath,
|
|
28
|
+
isAgentName,
|
|
29
|
+
loadConfig,
|
|
30
|
+
loadState,
|
|
31
|
+
normalizeConfig,
|
|
32
|
+
releaseLock,
|
|
33
|
+
runBot,
|
|
34
|
+
saveConfig,
|
|
35
|
+
saveState,
|
|
36
|
+
splitMessage,
|
|
37
|
+
statePath,
|
|
38
|
+
tokenHash
|
|
39
|
+
} from "./chunk-SCVC76UL.js";
|
|
40
|
+
export {
|
|
41
|
+
AGENTS,
|
|
42
|
+
AGENT_NAMES,
|
|
43
|
+
AcpAgent,
|
|
44
|
+
AgentAbortError,
|
|
45
|
+
AgentStartError,
|
|
46
|
+
BotQueue,
|
|
47
|
+
CONFIG_FILENAME,
|
|
48
|
+
ConfigError,
|
|
49
|
+
DEFAULT_BASE_URL,
|
|
50
|
+
DEFAULT_TIMEOUT_MS,
|
|
51
|
+
EMPTY_USAGE,
|
|
52
|
+
GLOBAL_CONFIG_PATH,
|
|
53
|
+
HELP_TEXT,
|
|
54
|
+
LockError,
|
|
55
|
+
MAX_MESSAGE_CHARS,
|
|
56
|
+
VicvicWire,
|
|
57
|
+
acquireLock,
|
|
58
|
+
botUrl,
|
|
59
|
+
clearState,
|
|
60
|
+
createDispatcher,
|
|
61
|
+
definitionOf,
|
|
62
|
+
emptyState,
|
|
63
|
+
ensureConfig,
|
|
64
|
+
findConfigPath,
|
|
65
|
+
isAgentName,
|
|
66
|
+
loadConfig,
|
|
67
|
+
loadState,
|
|
68
|
+
normalizeConfig,
|
|
69
|
+
releaseLock,
|
|
70
|
+
runBot,
|
|
71
|
+
saveConfig,
|
|
72
|
+
saveState,
|
|
73
|
+
splitMessage,
|
|
74
|
+
statePath,
|
|
75
|
+
tokenHash
|
|
76
|
+
};
|
|
77
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|