@vicvic-im/agent-bot 0.0.0-stage → 0.1.0

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.
Files changed (52) hide show
  1. package/README.md +142 -2
  2. package/dist/agents/acp.d.ts +42 -0
  3. package/dist/agents/acp.d.ts.map +1 -0
  4. package/dist/agents/registry.d.ts +13 -0
  5. package/dist/agents/registry.d.ts.map +1 -0
  6. package/dist/agents/types.d.ts +72 -0
  7. package/dist/agents/types.d.ts.map +1 -0
  8. package/dist/chunk-DMDFB2QE.js +1331 -0
  9. package/dist/chunk-DMDFB2QE.js.map +1 -0
  10. package/dist/chunk-FYLVJB7J.js +92 -0
  11. package/dist/chunk-FYLVJB7J.js.map +1 -0
  12. package/dist/cli.cjs +1499 -0
  13. package/dist/cli.cjs.map +1 -0
  14. package/dist/cli.d.ts +3 -0
  15. package/dist/cli.d.ts.map +1 -0
  16. package/dist/cli.js +135 -0
  17. package/dist/cli.js.map +1 -0
  18. package/dist/commands/setup.d.ts +8 -0
  19. package/dist/commands/setup.d.ts.map +1 -0
  20. package/dist/config.d.ts +39 -0
  21. package/dist/config.d.ts.map +1 -0
  22. package/dist/core/chunk.d.ts +10 -0
  23. package/dist/core/chunk.d.ts.map +1 -0
  24. package/dist/core/dispatcher.d.ts +18 -0
  25. package/dist/core/dispatcher.d.ts.map +1 -0
  26. package/dist/core/gate.d.ts +3 -0
  27. package/dist/core/gate.d.ts.map +1 -0
  28. package/dist/core/lock.d.ts +10 -0
  29. package/dist/core/lock.d.ts.map +1 -0
  30. package/dist/core/queue.d.ts +27 -0
  31. package/dist/core/queue.d.ts.map +1 -0
  32. package/dist/core/state.d.ts +22 -0
  33. package/dist/core/state.d.ts.map +1 -0
  34. package/dist/core/switch.d.ts +20 -0
  35. package/dist/core/switch.d.ts.map +1 -0
  36. package/dist/core/wire.d.ts +36 -0
  37. package/dist/core/wire.d.ts.map +1 -0
  38. package/dist/index.cjs +1464 -0
  39. package/dist/index.cjs.map +1 -0
  40. package/dist/index.d.ts +13 -0
  41. package/dist/index.d.ts.map +1 -0
  42. package/dist/index.js +77 -0
  43. package/dist/index.js.map +1 -0
  44. package/dist/server.cjs +1309 -0
  45. package/dist/server.cjs.map +1 -0
  46. package/dist/server.d.ts +9 -0
  47. package/dist/server.d.ts.map +1 -0
  48. package/dist/server.js +9 -0
  49. package/dist/server.js.map +1 -0
  50. package/dist/version.d.ts +3 -0
  51. package/dist/version.d.ts.map +1 -0
  52. package/package.json +47 -4
package/README.md CHANGED
@@ -1,3 +1,143 @@
1
- # Temporary Holding Version
1
+ # @vicvic-im/agent-bot
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Connect a local coding agent to [vicvic.im](https://vicvic.im) as an AI contact. Supports **Claude Code**, **Codex**, **OpenCode**, and **Pi** through the [Agent Client Protocol](https://agentclientprotocol.com) (ACP).
4
+
5
+ This is the multi-agent successor to `@ccbot/cli`. It reuses the same vicvic.im bot WebSocket protocol, so the server needs no changes.
6
+
7
+ ## Requirements
8
+
9
+ - Node.js >= 20
10
+ - One of the supported agents installed and authenticated **on the same machine**:
11
+
12
+ | Agent | Command prerequisite |
13
+ | ----------- | ---------------------------------------- |
14
+ | Claude Code | `claude login` or `ANTHROPIC_AUTH_TOKEN` |
15
+ | Codex | `codex login` |
16
+ | OpenCode | OpenCode >= 1.19, provider configured |
17
+ | Pi | Pi installed and authenticated |
18
+
19
+ ACP adapters are pinned in code:
20
+
21
+ - `@agentclientprotocol/claude-agent-acp@0.100.0`
22
+ - `@agentclientprotocol/codex-acp@2.5.0`
23
+ - `opencode acp` (OpenCode >= 1.19)
24
+ - `pi-acp@0.0.34` (third-party adapter)
25
+
26
+ `npx` based adapters are downloaded on first run; pre-install them globally if your network is slow.
27
+
28
+ Verified ACP capabilities (2026-11-05, local):
29
+
30
+ | Agent | resume | load | model option | usage cost | Notes |
31
+ | ----------- | ------ | ---- | ------------ | ---------- | ------------------------------------------------------- |
32
+ | Claude Code | ✅ | ✅ | ✅ | ✅ | ~13s cold start |
33
+ | Codex | ✅ | ✅ | ✅ | ❌ | ~100s cold start |
34
+ | OpenCode | ✅ | ✅ | ✅ | ✅ | set a working model; the free default may hit its limit |
35
+ | Pi | ❌ | ✅ | ✅ | ❌ | uses `session/load`; may include a context preamble |
36
+
37
+ ## Install
38
+
39
+ ```bash
40
+ npm i -g @vicvic-im/agent-bot
41
+ ```
42
+
43
+ ## Quick start
44
+
45
+ 1. Create an AI Bot in vicvic.im and copy its pairing token.
46
+ 2. In the project directory you want the agent to work in:
47
+
48
+ ```bash
49
+ vbot start
50
+ ```
51
+
52
+ 3. The first run asks for the agent, work directory, timeout, server URL, and token, then writes `vbot.json`.
53
+ 4. Send a message to the bot from vicvic.im.
54
+
55
+ With `pm2` installed, `vbot start` runs in the background. Without pm2, or with `--foreground`, it runs in the current terminal.
56
+
57
+ ## Commands
58
+
59
+ ```bash
60
+ vbot start [--foreground] [-c <config>]
61
+ vbot stop [-c <config>]
62
+ vbot restart [-c <config>]
63
+ vbot status [-c <config>]
64
+ vbot logs [-c <config>]
65
+ vbot delete [-c <config>]
66
+ ```
67
+
68
+ Chat commands:
69
+
70
+ | Command | Description |
71
+ | --------------- | ---------------------------------------------------- |
72
+ | `/new` | Drop the ACP session and start a new conversation |
73
+ | `/stop` | Cancel the current run and clear the queue |
74
+ | `/status` | Show agent, session, cwd, queue, usage, capabilities |
75
+ | `/agent [name]` | List or switch the agent backend |
76
+ | `/model [name]` | Show or switch the model (if the agent exposes it) |
77
+ | `/cost` | Show context usage and optional cost |
78
+ | `/help` | Show commands |
79
+
80
+ Unknown `/commands` are forwarded to the agent as prompts.
81
+
82
+ ## Configuration
83
+
84
+ `vbot.json` in the current directory, or `~/.vbot/config.json` as a fallback:
85
+
86
+ ```json
87
+ {
88
+ "provider": "vicvic",
89
+ "vicvic": {
90
+ "baseUrl": "https://api.vicvic.im",
91
+ "token": "ccbotpk_xxx"
92
+ },
93
+ "agent": {
94
+ "name": "codex",
95
+ "cwd": "/Users/me/project",
96
+ "model": null
97
+ },
98
+ "timeoutMs": 3600000,
99
+ "logPrompt": false
100
+ }
101
+ ```
102
+
103
+ - `agent.command` / `agent.args` are optional overrides. When omitted, the pinned command from the registry is used.
104
+ - `agent.cwd` must be an absolute existing directory.
105
+ - `VBOT_TOKEN` overrides `vicvic.token`, which is useful for CI or secret managers.
106
+ - `logPrompt` defaults to `false`; prompts are not printed to logs.
107
+
108
+ Session state is stored in `~/.vbot/state/<sha256(token)[:16]>.json`. State contains no message text and no token.
109
+
110
+ ## Security
111
+
112
+ `vbot` runs the agent with **your local user permissions** and automatically approves every ACP permission request. There is no interactive approval mode. Only run it in a directory you trust, and review what the agent is allowed to access.
113
+
114
+ The pairing token is a long-lived credential. Do not commit `vbot.json`; the file is written with mode `0600` but may still be copied by backup tools.
115
+
116
+ ## Differences from `@ccbot/cli`
117
+
118
+ - Multi-agent through ACP instead of Claude-only SDK.
119
+ - Session state is persisted; restarting `vbot` can resume the ACP session when the backend supports it.
120
+ - `/cost` reports ACP `usage_update` values (`used` / `size` / optional `cost`), not Claude's dollar cost.
121
+ - New config file (`vbot.json`) and pm2 process names (`vbot-*`); it does not read or migrate `ccbot.json`.
122
+ - The App's onboarding still says `npm i -g @ccbot/cli`; this is a known gap for now.
123
+
124
+ ## Known limitations
125
+
126
+ - No streaming/progress messages yet: only `Processing...` and the final reply.
127
+ - Text only. Image and file messages are not supported by the vicvic.im bot conversation.
128
+ - The server's offline notice still mentions `ccbot` (the server is unchanged in this phase).
129
+ - Windows is not officially verified; the adapters and pm2 may need extra setup.
130
+ - Chat CLI messages are English, matching the existing `@ccbot/cli` developer tooling; App UI i18n is unaffected.
131
+
132
+ ## Development
133
+
134
+ ```bash
135
+ pnpm --filter @vicvic-im/agent-bot build
136
+ pnpm --filter @vicvic-im/agent-bot test
137
+ pnpm --filter @vicvic-im/agent-bot lint
138
+
139
+ # probe ACP capabilities of all four backends
140
+ pnpm --filter @vicvic-im/agent-bot exec tsx scripts/probe.ts
141
+ ```
142
+
143
+ See `docs/prds/agent-bot-cli.md` for the full design.
@@ -0,0 +1,42 @@
1
+ import type { AgentBackend, AgentCapabilities, AgentName, AgentRunRequest, AgentRunResult } from "./types.js";
2
+ import type { AgentConfig } from "../config.js";
3
+ export declare class AgentAbortError extends Error {
4
+ constructor();
5
+ }
6
+ export declare class AgentStartError extends Error {
7
+ readonly stderr: string;
8
+ constructor(message: string, stderr: string);
9
+ }
10
+ /** 通过 ACP stdio 驱动单个 coding agent 子进程。 */
11
+ export declare class AcpAgent implements AgentBackend {
12
+ readonly name: AgentName;
13
+ private readonly config;
14
+ private child;
15
+ private connection;
16
+ private ctx;
17
+ private startPromise;
18
+ private session;
19
+ private configOptions;
20
+ private initCaps;
21
+ private turn;
22
+ private stderr;
23
+ private sawUsageCost;
24
+ private pendingModel;
25
+ constructor(name: AgentName, config: AgentConfig);
26
+ capabilities(): AgentCapabilities;
27
+ sessionId(): string | null;
28
+ resetSession(): void;
29
+ start(): Promise<void>;
30
+ private doStart;
31
+ private ensureSession;
32
+ run(request: AgentRunRequest): Promise<AgentRunResult>;
33
+ cancel(): Promise<void>;
34
+ setModel(model: string): Promise<boolean>;
35
+ close(): Promise<void>;
36
+ private handleUpdate;
37
+ private dispatchUpdate;
38
+ private applyContentChunk;
39
+ private applyToolUpdate;
40
+ private applyUsage;
41
+ }
42
+ //# sourceMappingURL=acp.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"acp.d.ts","sourceRoot":"","sources":["../../src/agents/acp.ts"],"names":[],"mappings":"AAWA,OAAO,KAAK,EACV,YAAY,EACZ,iBAAiB,EACjB,SAAS,EACT,eAAe,EACf,cAAc,EAEf,MAAM,YAAY,CAAC;AAGpB,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,qBAAa,eAAgB,SAAQ,KAAK;;CAKzC;AAED,qBAAa,eAAgB,SAAQ,KAAK;IAGtC,QAAQ,CAAC,MAAM,EAAE,MAAM;gBADvB,OAAO,EAAE,MAAM,EACN,MAAM,EAAE,MAAM;CAK1B;AAWD,0CAA0C;AAC1C,qBAAa,QAAS,YAAW,YAAY;IAczC,QAAQ,CAAC,IAAI,EAAE,SAAS;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM;IAdzB,OAAO,CAAC,KAAK,CAA6B;IAC1C,OAAO,CAAC,UAAU,CAAqC;IACvD,OAAO,CAAC,GAAG,CAAkC;IAC7C,OAAO,CAAC,YAAY,CAA8B;IAClD,OAAO,CAAC,OAAO,CAAuB;IACtC,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,QAAQ,CAAmC;IACnD,OAAO,CAAC,IAAI,CAAqB;IACjC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,YAAY,CAAuB;gBAGhC,IAAI,EAAE,SAAS,EACP,MAAM,EAAE,WAAW;IAGtC,YAAY,IAAI,iBAAiB;IASjC,SAAS,IAAI,MAAM,GAAG,IAAI;IAI1B,YAAY,IAAI,IAAI;IAId,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;YASd,OAAO;YA8EP,aAAa;IA+CrB,GAAG,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC;IAkEtD,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IASvB,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAkBzC,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAyB5B,OAAO,CAAC,YAAY;IAOpB,OAAO,CAAC,cAAc;IAyBtB,OAAO,CAAC,iBAAiB;IAMzB,OAAO,CAAC,eAAe;IAQvB,OAAO,CAAC,UAAU;CAWnB"}
@@ -0,0 +1,13 @@
1
+ import type { AgentCommand, AgentName } from "./types.js";
2
+ export interface AgentDefinition {
3
+ name: AgentName;
4
+ label: string;
5
+ command: AgentCommand;
6
+ /** 需要用户自行完成的认证前置。 */
7
+ authHint: string;
8
+ }
9
+ export declare const AGENTS: Record<AgentName, AgentDefinition>;
10
+ export declare const AGENT_NAMES: AgentName[];
11
+ export declare function isAgentName(value: string): value is AgentName;
12
+ export declare function definitionOf(name: AgentName): AgentDefinition;
13
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../src/agents/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAI1D,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,SAAS,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,YAAY,CAAC;IACtB,qBAAqB;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED,eAAO,MAAM,MAAM,EAAE,MAAM,CAAC,SAAS,EAAE,eAAe,CAqCrD,CAAC;AAEF,eAAO,MAAM,WAAW,EAA0B,SAAS,EAAE,CAAC;AAE9D,wBAAgB,WAAW,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,IAAI,SAAS,CAE7D;AAED,wBAAgB,YAAY,CAAC,IAAI,EAAE,SAAS,GAAG,eAAe,CAE7D"}
@@ -0,0 +1,72 @@
1
+ export type AgentName = "claude" | "codex" | "opencode" | "pi";
2
+ export interface AgentCommand {
3
+ command: string;
4
+ args: string[];
5
+ }
6
+ export interface Usage {
7
+ /** 当前上下文 token 数(ACP v1 usage_update.used)。 */
8
+ used: number;
9
+ /** 上下文窗口大小(ACP v1 usage_update.size)。 */
10
+ size: number;
11
+ /** 累计成本,单位由 agent 决定;不提供时为 null。 */
12
+ cost: {
13
+ amount: number;
14
+ currency: string;
15
+ } | null;
16
+ }
17
+ export declare const EMPTY_USAGE: Usage;
18
+ export type AgentEvent = {
19
+ type: "text";
20
+ text: string;
21
+ } | {
22
+ type: "thought";
23
+ text: string;
24
+ } | {
25
+ type: "tool";
26
+ name: string;
27
+ status: string;
28
+ } | {
29
+ type: "usage";
30
+ usage: Usage;
31
+ };
32
+ export interface AgentRunRequest {
33
+ prompt: string;
34
+ /** 已保存的 ACP session id;为空或后端不支持 resume 时新建。 */
35
+ sessionId?: string;
36
+ cwd: string;
37
+ model?: string | null;
38
+ signal: AbortSignal;
39
+ onEvent?: (event: AgentEvent) => void;
40
+ }
41
+ export interface AgentRunResult {
42
+ text: string;
43
+ sessionId: string;
44
+ usage: Usage;
45
+ /** true 表示本次是新会话(用于提示用户上下文已重置)。 */
46
+ newSession: boolean;
47
+ }
48
+ export interface AgentCapabilities {
49
+ resume: boolean;
50
+ load: boolean;
51
+ setConfigOption: boolean;
52
+ usageCost: boolean;
53
+ }
54
+ export interface AgentBackend {
55
+ readonly name: AgentName;
56
+ /** 启动子进程并完成 initialize;可重复调用(已启动则直接返回)。 */
57
+ start(): Promise<void>;
58
+ /** 运行一轮 prompt。内部负责 session 新建/恢复。 */
59
+ run(request: AgentRunRequest): Promise<AgentRunResult>;
60
+ /** 取消当前 prompt。 */
61
+ cancel(): Promise<void>;
62
+ /** 切换模型;返回 false 表示当前后端不支持。 */
63
+ setModel(model: string): Promise<boolean>;
64
+ /** 丢弃当前 ACP session;下一次 run 会新建会话。 */
65
+ resetSession(): void;
66
+ /** 关闭子进程并清理资源。 */
67
+ close(): Promise<void>;
68
+ capabilities(): AgentCapabilities;
69
+ /** 当前 ACP session id(可能为空)。 */
70
+ sessionId(): string | null;
71
+ }
72
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/agents/types.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,SAAS,GAAG,QAAQ,GAAG,OAAO,GAAG,UAAU,GAAG,IAAI,CAAC;AAE/D,MAAM,WAAW,YAAY;IAC3B,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB;AAED,MAAM,WAAW,KAAK;IACpB,+CAA+C;IAC/C,IAAI,EAAE,MAAM,CAAC;IACb,yCAAyC;IACzC,IAAI,EAAE,MAAM,CAAC;IACb,oCAAoC;IACpC,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAC;CACnD;AAED,eAAO,MAAM,WAAW,EAAE,KAAwC,CAAC;AAEnE,MAAM,MAAM,UAAU,GAClB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACjC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,KAAK,EAAE,KAAK,CAAA;CAAE,CAAC;AAEpC,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,+CAA+C;IAC/C,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,WAAW,CAAC;IACpB,OAAO,CAAC,EAAE,CAAC,KAAK,EAAE,UAAU,KAAK,IAAI,CAAC;CACvC;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,EAAE,MAAM,CAAC;IAClB,KAAK,EAAE,KAAK,CAAC;IACb,mCAAmC;IACnC,UAAU,EAAE,OAAO,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,OAAO,CAAC;IAChB,IAAI,EAAE,OAAO,CAAC;IACd,eAAe,EAAE,OAAO,CAAC;IACzB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,2CAA2C;IAC3C,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,sCAAsC;IACtC,GAAG,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAAC;IACvD,mBAAmB;IACnB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB,+BAA+B;IAC/B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAC1C,sCAAsC;IACtC,YAAY,IAAI,IAAI,CAAC;IACrB,kBAAkB;IAClB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,YAAY,IAAI,iBAAiB,CAAC;IAClC,+BAA+B;IAC/B,SAAS,IAAI,MAAM,GAAG,IAAI,CAAC;CAC5B"}