@openacp/cli 0.4.10 → 0.5.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 (82) hide show
  1. package/README.md +57 -4
  2. package/dist/agent-catalog-4IAJ7HEG.js +10 -0
  3. package/dist/agent-registry-B5YAMA4T.js +8 -0
  4. package/dist/agent-store-ZBXGOFPH.js +8 -0
  5. package/dist/api-client-UN7BXQOQ.js +11 -0
  6. package/dist/{autostart-DZ3MHHMM.js → autostart-K73RQZVV.js} +3 -3
  7. package/dist/chunk-5HGXUCMX.js +83 -0
  8. package/dist/chunk-5HGXUCMX.js.map +1 -0
  9. package/dist/{chunk-UAUTLC4E.js → chunk-D73LCTPF.js} +75 -37
  10. package/dist/chunk-D73LCTPF.js.map +1 -0
  11. package/dist/{chunk-LYKCQTH5.js → chunk-ESOPMQAY.js} +5 -1
  12. package/dist/chunk-ESOPMQAY.js.map +1 -0
  13. package/dist/{chunk-KPI4HGJC.js → chunk-FWN3UIRT.js} +1631 -970
  14. package/dist/chunk-FWN3UIRT.js.map +1 -0
  15. package/dist/chunk-IRGYTNLP.js +650 -0
  16. package/dist/chunk-IRGYTNLP.js.map +1 -0
  17. package/dist/{chunk-ZRFBLD3W.js → chunk-JRF4G4X7.js} +71 -25
  18. package/dist/chunk-JRF4G4X7.js.map +1 -0
  19. package/dist/{chunk-6MJLVZXV.js → chunk-LAFKARV3.js} +58 -21
  20. package/dist/{chunk-6MJLVZXV.js.map → chunk-LAFKARV3.js.map} +1 -1
  21. package/dist/chunk-NAMYZIS5.js +1 -0
  22. package/dist/{chunk-HZD3CGPK.js → chunk-NDR5JCS7.js} +3 -3
  23. package/dist/chunk-OORPX73T.js +30 -0
  24. package/dist/chunk-OORPX73T.js.map +1 -0
  25. package/dist/{chunk-V3BA2MJ6.js → chunk-RF3DUYFO.js} +2 -2
  26. package/dist/chunk-S3DRLJPM.js +422 -0
  27. package/dist/chunk-S3DRLJPM.js.map +1 -0
  28. package/dist/chunk-UG6X672R.js +90 -0
  29. package/dist/chunk-UG6X672R.js.map +1 -0
  30. package/dist/{chunk-C6YIUTGR.js → chunk-VBEWSWVL.js} +2 -2
  31. package/dist/{chunk-MRKYJ422.js → chunk-X6LLG7XN.js} +2 -2
  32. package/dist/chunk-XJJ7LPXP.js +85 -0
  33. package/dist/chunk-XJJ7LPXP.js.map +1 -0
  34. package/dist/chunk-Z46LGZ7R.js +110 -0
  35. package/dist/chunk-Z46LGZ7R.js.map +1 -0
  36. package/dist/cli.js +313 -52
  37. package/dist/cli.js.map +1 -1
  38. package/dist/{config-H2DSEHNW.js → config-PCPIBPUA.js} +3 -3
  39. package/dist/config-editor-5L7AJ5AF.js +12 -0
  40. package/dist/config-editor-5L7AJ5AF.js.map +1 -0
  41. package/dist/config-registry-SNKA2EH2.js +17 -0
  42. package/dist/config-registry-SNKA2EH2.js.map +1 -0
  43. package/dist/{daemon-VF6HJQXD.js → daemon-JZLFRUW6.js} +4 -4
  44. package/dist/daemon-JZLFRUW6.js.map +1 -0
  45. package/dist/data/registry-snapshot.json +876 -0
  46. package/dist/doctor-N2HKKUUQ.js +9 -0
  47. package/dist/doctor-N2HKKUUQ.js.map +1 -0
  48. package/dist/index.d.ts +212 -43
  49. package/dist/index.js +43 -14
  50. package/dist/install-cloudflared-BTGUD7SW.js +8 -0
  51. package/dist/install-cloudflared-BTGUD7SW.js.map +1 -0
  52. package/dist/log-SPS2S6FO.js +19 -0
  53. package/dist/log-SPS2S6FO.js.map +1 -0
  54. package/dist/{main-G6XDM7EZ.js → main-37GLOJ7G.js} +21 -15
  55. package/dist/{main-G6XDM7EZ.js.map → main-37GLOJ7G.js.map} +1 -1
  56. package/dist/menu-6RCPBVGQ.js +15 -0
  57. package/dist/menu-6RCPBVGQ.js.map +1 -0
  58. package/dist/{setup-FCVL75K6.js → setup-QAS3QW3M.js} +5 -4
  59. package/dist/setup-QAS3QW3M.js.map +1 -0
  60. package/dist/{tunnel-service-DASSH7OA.js → tunnel-service-LEVPLXAZ.js} +3 -3
  61. package/package.json +10 -2
  62. package/dist/agent-registry-7HC6D4CH.js +0 -7
  63. package/dist/chunk-KPI4HGJC.js.map +0 -1
  64. package/dist/chunk-LYKCQTH5.js.map +0 -1
  65. package/dist/chunk-UAUTLC4E.js.map +0 -1
  66. package/dist/chunk-VA2M52CM.js +0 -15
  67. package/dist/chunk-VA2M52CM.js.map +0 -1
  68. package/dist/chunk-ZRFBLD3W.js.map +0 -1
  69. package/dist/config-editor-SKS4LJLT.js +0 -11
  70. package/dist/install-cloudflared-ILUXKLAC.js +0 -8
  71. /package/dist/{agent-registry-7HC6D4CH.js.map → agent-catalog-4IAJ7HEG.js.map} +0 -0
  72. /package/dist/{autostart-DZ3MHHMM.js.map → agent-registry-B5YAMA4T.js.map} +0 -0
  73. /package/dist/{config-H2DSEHNW.js.map → agent-store-ZBXGOFPH.js.map} +0 -0
  74. /package/dist/{config-editor-SKS4LJLT.js.map → api-client-UN7BXQOQ.js.map} +0 -0
  75. /package/dist/{daemon-VF6HJQXD.js.map → autostart-K73RQZVV.js.map} +0 -0
  76. /package/dist/{install-cloudflared-ILUXKLAC.js.map → chunk-NAMYZIS5.js.map} +0 -0
  77. /package/dist/{chunk-HZD3CGPK.js.map → chunk-NDR5JCS7.js.map} +0 -0
  78. /package/dist/{chunk-V3BA2MJ6.js.map → chunk-RF3DUYFO.js.map} +0 -0
  79. /package/dist/{chunk-C6YIUTGR.js.map → chunk-VBEWSWVL.js.map} +0 -0
  80. /package/dist/{chunk-MRKYJ422.js.map → chunk-X6LLG7XN.js.map} +0 -0
  81. /package/dist/{setup-FCVL75K6.js.map → config-PCPIBPUA.js.map} +0 -0
  82. /package/dist/{tunnel-service-DASSH7OA.js.map → tunnel-service-LEVPLXAZ.js.map} +0 -0
package/README.md CHANGED
@@ -6,9 +6,11 @@
6
6
 
7
7
  One message, any channel, any agent.
8
8
 
9
- [![License: AGPL-3.0](https://img.shields.io/badge/License-AGPL--3.0-blue.svg)](LICENSE)
9
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
10
10
  [![Node.js >= 20](https://img.shields.io/badge/Node.js-%3E%3D%2020-green.svg)](https://nodejs.org/)
11
11
  [![ACP Protocol](https://img.shields.io/badge/Protocol-ACP-purple.svg)](https://agentclientprotocol.org/)
12
+ [![npm](https://img.shields.io/npm/v/@openacp/cli.svg)](https://www.npmjs.com/package/@openacp/cli)
13
+ [![Twitter Follow](https://img.shields.io/twitter/follow/Open_ACP?style=social)](https://x.com/Open_ACP)
12
14
 
13
15
  [Getting Started](docs/guide/getting-started.md) | [Usage](docs/guide/usage.md) | [Configuration](docs/guide/configuration.md) | [Tunnel](docs/guide/tunnel.md) | [Plugins](docs/guide/plugins.md) | [Development](docs/guide/development.md)
14
16
 
@@ -32,9 +34,47 @@ ACP Protocol (JSON-RPC / stdio) Tunnel Service
32
34
  AI Agent (Claude Code, Codex, ...) File/Diff Viewer
33
35
  ```
34
36
 
37
+ ## Screenshots
38
+
39
+ <div align="center">
40
+ <table>
41
+ <tr>
42
+ <td align="center"><img src="docs/images/menu.png" width="250" /><br /><b>Control Panel</b><br />Manage sessions, agents, and settings</td>
43
+ <td align="center"><img src="docs/images/agent-working.png" width="250" /><br /><b>Agent at Work</b><br />Plans, reads files, writes code</td>
44
+ </tr>
45
+ <tr>
46
+ <td align="center"><img src="docs/images/tool-calls.png" width="250" /><br /><b>Real-time Tool Calls</b><br />See every action the agent takes</td>
47
+ <td align="center"><img src="docs/images/skills.png" width="250" /><br /><b>Agent Skills</b><br />Brainstorming, TDD, debugging & more</td>
48
+ </tr>
49
+ </table>
50
+ </div>
51
+
52
+ ## Supported Agents
53
+
54
+ OpenACP follows the [Agent Client Protocol (ACP)](https://agentclientprotocol.com/) standard — an open protocol for connecting AI coding agents to client applications. Agent definitions are loaded from the [official ACP Registry](https://agentclientprotocol.com/get-started/registry) via CDN ([`registry.json`](https://cdn.agentclientprotocol.com/registry/v1/latest/registry.json)), so new agents are available as soon as they're registered.
55
+
56
+ | Agent | Distribution | Description |
57
+ |-------|-------------|-------------|
58
+ | [Claude Agent](https://github.com/anthropics/claude-code) | npx | Anthropic's Claude coding agent |
59
+ | [Gemini CLI](https://github.com/google-gemini/gemini-cli) | npx | Google's official CLI for Gemini |
60
+ | [Codex CLI](https://github.com/openai/codex) | npx | OpenAI's coding assistant |
61
+ | [GitHub Copilot](https://github.com/github/copilot-cli) | npx | GitHub's AI pair programmer |
62
+ | [Cursor](https://www.cursor.com/) | binary | Cursor's coding agent |
63
+ | [Cline](https://github.com/cline/cline) | npx | Autonomous coding agent with file editing, commands, and browser |
64
+ | [goose](https://github.com/block/goose) | binary | Open source AI agent for engineering tasks |
65
+ | [Amp](https://github.com/tao12345666333/amp-acp) | binary | The frontier coding agent |
66
+ | [Auggie CLI](https://www.augmentcode.com/) | npx | Augment Code's agent with industry-leading context engine |
67
+ | [Junie](https://www.jetbrains.com/) | binary | AI coding agent by JetBrains |
68
+ | [Kilo](https://github.com/kilocode/kilo) | npx | The open source coding agent |
69
+ | [Qwen Code](https://github.com/QwenLM/qwen-code) | npx | Alibaba's Qwen coding assistant |
70
+ | [crow-cli](https://github.com/crowdecode/crow-cli) | uvx | Minimal ACP native coding agent |
71
+ | ...and more | | [See full registry →](https://agentclientprotocol.com/get-started/registry) |
72
+
73
+ > **28+ agents supported** — any agent registered in the ACP Registry works out of the box. Install with `openacp agents install <name>` or browse from Telegram with `/agents`.
74
+
35
75
  ## Features
36
76
 
37
- - **Multi-agent** — Claude Code, Codex, or any ACP-compatible agent
77
+ - **Multi-agent** — Claude Code, Codex, Gemini, Cursor, and [28+ ACP-compatible agents](#supported-agents)
38
78
  - **Telegram** — Forum topics, real-time streaming, permission buttons, skill commands
39
79
  - **Tunnel & file viewer** — Public file/diff viewer via Cloudflare, ngrok, bore, or Tailscale
40
80
  - **Session persistence** — Resume sessions across restarts
@@ -87,6 +127,14 @@ openacp logs
87
127
  ### Other CLI commands
88
128
 
89
129
  ```bash
130
+ # Agent management
131
+ openacp agents # List all agents (installed + available)
132
+ openacp agents install <name> # Install an agent from the ACP Registry
133
+ openacp agents uninstall <name> # Remove an installed agent
134
+ openacp agents info <name> # Show agent details & dependencies
135
+ openacp agents refresh # Force-refresh the registry
136
+
137
+ # System
90
138
  openacp config # Show current config
91
139
  openacp reset # Re-run the setup wizard
92
140
  openacp update # Update to latest version
@@ -105,7 +153,8 @@ Once OpenACP is running, control it from Telegram:
105
153
  | `/newchat` | New session, same agent & workspace |
106
154
  | `/cancel` | Cancel current session |
107
155
  | `/status` | Show session or system status |
108
- | `/agents` | List available agents |
156
+ | `/agents` | Browse & install agents from ACP Registry |
157
+ | `/install <name>` | Install an agent directly |
109
158
 
110
159
  Each session gets its own forum topic. The agent streams responses in real time, shows tool calls, and asks for permission when needed.
111
160
 
@@ -150,6 +199,10 @@ Sessions are not locked after transfer — you can continue from either side.
150
199
 
151
200
  See [development guide](docs/guide/development.md).
152
201
 
202
+ ## Follow Us
203
+
204
+ [![Twitter Follow](https://img.shields.io/twitter/follow/Open_ACP?style=social)](https://x.com/Open_ACP)
205
+
153
206
  ## License
154
207
 
155
- [AGPL-3.0](LICENSE)
208
+ [MIT](LICENSE)
@@ -0,0 +1,10 @@
1
+ import {
2
+ AgentCatalog
3
+ } from "./chunk-S3DRLJPM.js";
4
+ import "./chunk-5HGXUCMX.js";
5
+ import "./chunk-XJJ7LPXP.js";
6
+ import "./chunk-ESOPMQAY.js";
7
+ export {
8
+ AgentCatalog
9
+ };
10
+ //# sourceMappingURL=agent-catalog-4IAJ7HEG.js.map
@@ -0,0 +1,8 @@
1
+ import "./chunk-NAMYZIS5.js";
2
+ import {
3
+ getAgentCapabilities
4
+ } from "./chunk-XJJ7LPXP.js";
5
+ export {
6
+ getAgentCapabilities
7
+ };
8
+ //# sourceMappingURL=agent-registry-B5YAMA4T.js.map
@@ -0,0 +1,8 @@
1
+ import {
2
+ AgentStore
3
+ } from "./chunk-5HGXUCMX.js";
4
+ import "./chunk-ESOPMQAY.js";
5
+ export {
6
+ AgentStore
7
+ };
8
+ //# sourceMappingURL=agent-store-ZBXGOFPH.js.map
@@ -0,0 +1,11 @@
1
+ import {
2
+ apiCall,
3
+ readApiPort,
4
+ removeStalePortFile
5
+ } from "./chunk-OORPX73T.js";
6
+ export {
7
+ apiCall,
8
+ readApiPort,
9
+ removeStalePortFile
10
+ };
11
+ //# sourceMappingURL=api-client-UN7BXQOQ.js.map
@@ -5,8 +5,8 @@ import {
5
5
  isAutoStartInstalled,
6
6
  isAutoStartSupported,
7
7
  uninstallAutoStart
8
- } from "./chunk-MRKYJ422.js";
9
- import "./chunk-LYKCQTH5.js";
8
+ } from "./chunk-X6LLG7XN.js";
9
+ import "./chunk-ESOPMQAY.js";
10
10
  export {
11
11
  generateLaunchdPlist,
12
12
  generateSystemdUnit,
@@ -15,4 +15,4 @@ export {
15
15
  isAutoStartSupported,
16
16
  uninstallAutoStart
17
17
  };
18
- //# sourceMappingURL=autostart-DZ3MHHMM.js.map
18
+ //# sourceMappingURL=autostart-K73RQZVV.js.map
@@ -0,0 +1,83 @@
1
+ import {
2
+ createChildLogger
3
+ } from "./chunk-ESOPMQAY.js";
4
+
5
+ // src/core/agent-store.ts
6
+ import * as fs from "fs";
7
+ import * as path from "path";
8
+ import * as os from "os";
9
+ import { z } from "zod";
10
+ var log = createChildLogger({ module: "agent-store" });
11
+ var InstalledAgentSchema = z.object({
12
+ registryId: z.string().nullable(),
13
+ name: z.string(),
14
+ version: z.string(),
15
+ distribution: z.enum(["npx", "uvx", "binary", "custom"]),
16
+ command: z.string(),
17
+ args: z.array(z.string()).default([]),
18
+ env: z.record(z.string(), z.string()).default({}),
19
+ workingDirectory: z.string().optional(),
20
+ installedAt: z.string(),
21
+ binaryPath: z.string().nullable().default(null)
22
+ });
23
+ var AgentStoreSchema = z.object({
24
+ version: z.number().default(1),
25
+ installed: z.record(z.string(), InstalledAgentSchema).default({})
26
+ });
27
+ var AgentStore = class {
28
+ data = { version: 1, installed: {} };
29
+ filePath;
30
+ constructor(filePath) {
31
+ this.filePath = filePath ?? path.join(os.homedir(), ".openacp", "agents.json");
32
+ }
33
+ load() {
34
+ fs.mkdirSync(path.dirname(this.filePath), { recursive: true });
35
+ if (!fs.existsSync(this.filePath)) {
36
+ this.data = { version: 1, installed: {} };
37
+ return;
38
+ }
39
+ try {
40
+ const raw = JSON.parse(fs.readFileSync(this.filePath, "utf-8"));
41
+ const result = AgentStoreSchema.safeParse(raw);
42
+ if (result.success) {
43
+ this.data = result.data;
44
+ } else {
45
+ log.warn({ errors: result.error.issues }, "Invalid agents.json, starting fresh");
46
+ this.data = { version: 1, installed: {} };
47
+ }
48
+ } catch (err) {
49
+ log.warn({ err }, "Failed to read agents.json, starting fresh");
50
+ this.data = { version: 1, installed: {} };
51
+ }
52
+ }
53
+ exists() {
54
+ return fs.existsSync(this.filePath);
55
+ }
56
+ getInstalled() {
57
+ return this.data.installed;
58
+ }
59
+ getAgent(key) {
60
+ return this.data.installed[key];
61
+ }
62
+ addAgent(key, agent) {
63
+ this.data.installed[key] = agent;
64
+ this.save();
65
+ }
66
+ removeAgent(key) {
67
+ delete this.data.installed[key];
68
+ this.save();
69
+ }
70
+ hasAgent(key) {
71
+ return key in this.data.installed;
72
+ }
73
+ save() {
74
+ const tmpPath = this.filePath + ".tmp";
75
+ fs.writeFileSync(tmpPath, JSON.stringify(this.data, null, 2));
76
+ fs.renameSync(tmpPath, this.filePath);
77
+ }
78
+ };
79
+
80
+ export {
81
+ AgentStore
82
+ };
83
+ //# sourceMappingURL=chunk-5HGXUCMX.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/agent-store.ts"],"sourcesContent":["import * as fs from \"node:fs\";\nimport * as path from \"node:path\";\nimport * as os from \"node:os\";\nimport { z } from \"zod\";\nimport type { InstalledAgent } from \"./types.js\";\nimport { createChildLogger } from \"./log.js\";\n\nconst log = createChildLogger({ module: \"agent-store\" });\n\nconst InstalledAgentSchema = z.object({\n registryId: z.string().nullable(),\n name: z.string(),\n version: z.string(),\n distribution: z.enum([\"npx\", \"uvx\", \"binary\", \"custom\"]),\n command: z.string(),\n args: z.array(z.string()).default([]),\n env: z.record(z.string(), z.string()).default({}),\n workingDirectory: z.string().optional(),\n installedAt: z.string(),\n binaryPath: z.string().nullable().default(null),\n});\n\nconst AgentStoreSchema = z.object({\n version: z.number().default(1),\n installed: z.record(z.string(), InstalledAgentSchema).default({}),\n});\n\ntype AgentStoreData = z.infer<typeof AgentStoreSchema>;\n\nexport class AgentStore {\n private data: AgentStoreData = { version: 1, installed: {} };\n private filePath: string;\n\n constructor(filePath?: string) {\n this.filePath = filePath ?? path.join(os.homedir(), \".openacp\", \"agents.json\");\n }\n\n load(): void {\n fs.mkdirSync(path.dirname(this.filePath), { recursive: true });\n\n if (!fs.existsSync(this.filePath)) {\n this.data = { version: 1, installed: {} };\n return;\n }\n\n try {\n const raw = JSON.parse(fs.readFileSync(this.filePath, \"utf-8\") as string);\n const result = AgentStoreSchema.safeParse(raw);\n if (result.success) {\n this.data = result.data;\n } else {\n log.warn({ errors: result.error.issues }, \"Invalid agents.json, starting fresh\");\n this.data = { version: 1, installed: {} };\n }\n } catch (err) {\n log.warn({ err }, \"Failed to read agents.json, starting fresh\");\n this.data = { version: 1, installed: {} };\n }\n }\n\n exists(): boolean {\n return fs.existsSync(this.filePath);\n }\n\n getInstalled(): Record<string, InstalledAgent> {\n return this.data.installed;\n }\n\n getAgent(key: string): InstalledAgent | undefined {\n return this.data.installed[key];\n }\n\n addAgent(key: string, agent: InstalledAgent): void {\n this.data.installed[key] = agent;\n this.save();\n }\n\n removeAgent(key: string): void {\n delete this.data.installed[key];\n this.save();\n }\n\n hasAgent(key: string): boolean {\n return key in this.data.installed;\n }\n\n private save(): void {\n const tmpPath = this.filePath + \".tmp\";\n fs.writeFileSync(tmpPath, JSON.stringify(this.data, null, 2));\n fs.renameSync(tmpPath, this.filePath);\n }\n}\n"],"mappings":";;;;;AAAA,YAAY,QAAQ;AACpB,YAAY,UAAU;AACtB,YAAY,QAAQ;AACpB,SAAS,SAAS;AAIlB,IAAM,MAAM,kBAAkB,EAAE,QAAQ,cAAc,CAAC;AAEvD,IAAM,uBAAuB,EAAE,OAAO;AAAA,EACpC,YAAY,EAAE,OAAO,EAAE,SAAS;AAAA,EAChC,MAAM,EAAE,OAAO;AAAA,EACf,SAAS,EAAE,OAAO;AAAA,EAClB,cAAc,EAAE,KAAK,CAAC,OAAO,OAAO,UAAU,QAAQ,CAAC;AAAA,EACvD,SAAS,EAAE,OAAO;AAAA,EAClB,MAAM,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EACpC,KAAK,EAAE,OAAO,EAAE,OAAO,GAAG,EAAE,OAAO,CAAC,EAAE,QAAQ,CAAC,CAAC;AAAA,EAChD,kBAAkB,EAAE,OAAO,EAAE,SAAS;AAAA,EACtC,aAAa,EAAE,OAAO;AAAA,EACtB,YAAY,EAAE,OAAO,EAAE,SAAS,EAAE,QAAQ,IAAI;AAChD,CAAC;AAED,IAAM,mBAAmB,EAAE,OAAO;AAAA,EAChC,SAAS,EAAE,OAAO,EAAE,QAAQ,CAAC;AAAA,EAC7B,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,oBAAoB,EAAE,QAAQ,CAAC,CAAC;AAClE,CAAC;AAIM,IAAM,aAAN,MAAiB;AAAA,EACd,OAAuB,EAAE,SAAS,GAAG,WAAW,CAAC,EAAE;AAAA,EACnD;AAAA,EAER,YAAY,UAAmB;AAC7B,SAAK,WAAW,YAAiB,UAAQ,WAAQ,GAAG,YAAY,aAAa;AAAA,EAC/E;AAAA,EAEA,OAAa;AACX,IAAG,aAAe,aAAQ,KAAK,QAAQ,GAAG,EAAE,WAAW,KAAK,CAAC;AAE7D,QAAI,CAAI,cAAW,KAAK,QAAQ,GAAG;AACjC,WAAK,OAAO,EAAE,SAAS,GAAG,WAAW,CAAC,EAAE;AACxC;AAAA,IACF;AAEA,QAAI;AACF,YAAM,MAAM,KAAK,MAAS,gBAAa,KAAK,UAAU,OAAO,CAAW;AACxE,YAAM,SAAS,iBAAiB,UAAU,GAAG;AAC7C,UAAI,OAAO,SAAS;AAClB,aAAK,OAAO,OAAO;AAAA,MACrB,OAAO;AACL,YAAI,KAAK,EAAE,QAAQ,OAAO,MAAM,OAAO,GAAG,qCAAqC;AAC/E,aAAK,OAAO,EAAE,SAAS,GAAG,WAAW,CAAC,EAAE;AAAA,MAC1C;AAAA,IACF,SAAS,KAAK;AACZ,UAAI,KAAK,EAAE,IAAI,GAAG,4CAA4C;AAC9D,WAAK,OAAO,EAAE,SAAS,GAAG,WAAW,CAAC,EAAE;AAAA,IAC1C;AAAA,EACF;AAAA,EAEA,SAAkB;AAChB,WAAU,cAAW,KAAK,QAAQ;AAAA,EACpC;AAAA,EAEA,eAA+C;AAC7C,WAAO,KAAK,KAAK;AAAA,EACnB;AAAA,EAEA,SAAS,KAAyC;AAChD,WAAO,KAAK,KAAK,UAAU,GAAG;AAAA,EAChC;AAAA,EAEA,SAAS,KAAa,OAA6B;AACjD,SAAK,KAAK,UAAU,GAAG,IAAI;AAC3B,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,YAAY,KAAmB;AAC7B,WAAO,KAAK,KAAK,UAAU,GAAG;AAC9B,SAAK,KAAK;AAAA,EACZ;AAAA,EAEA,SAAS,KAAsB;AAC7B,WAAO,OAAO,KAAK,KAAK;AAAA,EAC1B;AAAA,EAEQ,OAAa;AACnB,UAAM,UAAU,KAAK,WAAW;AAChC,IAAG,iBAAc,SAAS,KAAK,UAAU,KAAK,MAAM,MAAM,CAAC,CAAC;AAC5D,IAAG,cAAW,SAAS,KAAK,QAAQ;AAAA,EACtC;AACF;","names":[]}
@@ -1,11 +1,12 @@
1
+ import {
2
+ commandExists
3
+ } from "./chunk-XJJ7LPXP.js";
1
4
  import {
2
5
  expandHome
3
- } from "./chunk-ZRFBLD3W.js";
6
+ } from "./chunk-JRF4G4X7.js";
4
7
 
5
8
  // src/core/setup.ts
6
9
  import { execFileSync } from "child_process";
7
- import * as fs from "fs";
8
- import * as path from "path";
9
10
  import { input, select } from "@inquirer/prompts";
10
11
  var c = {
11
12
  reset: "\x1B[0m",
@@ -217,22 +218,6 @@ var KNOWN_AGENTS = [
217
218
  { name: "claude", commands: ["claude-agent-acp"] },
218
219
  { name: "codex", commands: ["codex"] }
219
220
  ];
220
- function commandExists(cmd) {
221
- try {
222
- execFileSync("which", [cmd], { stdio: "pipe" });
223
- return true;
224
- } catch {
225
- }
226
- let dir = process.cwd();
227
- while (true) {
228
- const binPath = path.join(dir, "node_modules", ".bin", cmd);
229
- if (fs.existsSync(binPath)) return true;
230
- const parent = path.dirname(dir);
231
- if (parent === dir) break;
232
- dir = parent;
233
- }
234
- return false;
235
- }
236
221
  async function detectAgents() {
237
222
  const found = [];
238
223
  for (const agent of KNOWN_AGENTS) {
@@ -324,20 +309,73 @@ async function setupTelegram() {
324
309
  };
325
310
  }
326
311
  async function setupAgents() {
327
- const detected = await detectAgents();
328
- const agents = {};
329
- agents["claude"] = { command: "claude-agent-acp", args: [], env: {} };
330
- for (const agent of detected) {
331
- if (agent.name !== "claude") {
332
- agents[agent.name] = { command: agent.command, args: [], env: {} };
312
+ const { AgentCatalog } = await import("./agent-catalog-4IAJ7HEG.js");
313
+ const { select: select2, checkbox } = await import("@inquirer/prompts");
314
+ const catalog = new AgentCatalog();
315
+ catalog.load();
316
+ console.log(dim(" Checking available agents..."));
317
+ await catalog.refreshRegistryIfStale();
318
+ if (!catalog.getInstalledAgent("claude")) {
319
+ const claudeRegistry = catalog.findRegistryAgent("claude-acp");
320
+ if (claudeRegistry) {
321
+ await catalog.install("claude-acp");
322
+ } else {
323
+ const { AgentStore } = await import("./agent-store-ZBXGOFPH.js");
324
+ const store = new AgentStore();
325
+ store.load();
326
+ store.addAgent("claude", {
327
+ registryId: "claude-acp",
328
+ name: "Claude Agent",
329
+ version: "bundled",
330
+ distribution: "npx",
331
+ command: "npx",
332
+ args: ["@zed-industries/claude-agent-acp"],
333
+ env: {},
334
+ installedAt: (/* @__PURE__ */ new Date()).toISOString(),
335
+ binaryPath: null
336
+ });
333
337
  }
334
338
  }
335
- const defaultAgent = Object.keys(agents)[0];
336
- const agentCmd = agents[defaultAgent].command;
337
- console.log(
338
- ok(`Agent: ${c.bold}${defaultAgent}${c.reset}${c.green} (${agentCmd})`)
339
- );
340
- return { agents, defaultAgent };
339
+ console.log(ok("Claude Agent ready"));
340
+ const available = catalog.getAvailable();
341
+ const installable = available.filter((a) => !a.installed && a.available);
342
+ if (installable.length > 0) {
343
+ const choices = installable.slice(0, 10).map((a) => ({
344
+ name: `${a.name} (${a.distribution})`,
345
+ value: a.key,
346
+ checked: false
347
+ }));
348
+ const selected = await checkbox({
349
+ message: "Install additional agents? (Space to select, Enter to continue)",
350
+ choices
351
+ });
352
+ for (const key of selected) {
353
+ const regAgent = catalog.findRegistryAgent(key);
354
+ if (regAgent) {
355
+ process.stdout.write(` Installing ${regAgent.name}... `);
356
+ const result = await catalog.install(key);
357
+ if (result.ok) {
358
+ console.log(ok("done"));
359
+ } else {
360
+ console.log(warn(`skipped: ${result.error}`));
361
+ }
362
+ }
363
+ }
364
+ }
365
+ const installedAgents = Object.keys(catalog.getInstalledEntries());
366
+ let defaultAgent = "claude";
367
+ if (installedAgents.length > 1) {
368
+ defaultAgent = await select2({
369
+ message: "Which agent should be the default?",
370
+ choices: installedAgents.map((key) => {
371
+ const agent = catalog.getInstalledAgent(key);
372
+ return { name: `${agent.name} (${key})`, value: key };
373
+ }),
374
+ default: "claude"
375
+ });
376
+ }
377
+ console.log(ok(`Default agent: ${c.bold}${defaultAgent}${c.reset}`));
378
+ return { defaultAgent };
341
379
  }
342
380
  async function setupWorkspace() {
343
381
  console.log(step(2, "Workspace"));
@@ -370,7 +408,7 @@ async function setupRunMode() {
370
408
  ]
371
409
  });
372
410
  if (mode === "daemon") {
373
- const { installAutoStart, isAutoStartSupported } = await import("./autostart-DZ3MHHMM.js");
411
+ const { installAutoStart, isAutoStartSupported } = await import("./autostart-K73RQZVV.js");
374
412
  const autoStart = isAutoStartSupported();
375
413
  if (autoStart) {
376
414
  const result = installAutoStart(expandHome("~/.openacp/logs"));
@@ -395,8 +433,8 @@ async function runSetup(configManager) {
395
433
  printWelcomeBanner();
396
434
  try {
397
435
  const telegram = await setupTelegram();
398
- const { agents, defaultAgent } = await setupAgents();
399
- if (agents["claude"]) {
436
+ const { defaultAgent } = await setupAgents();
437
+ {
400
438
  const { confirm } = await import("@inquirer/prompts");
401
439
  const installClaude = await confirm({
402
440
  message: "Install session transfer for Claude? (enables /openacp:handoff in your terminal)",
@@ -428,7 +466,7 @@ async function runSetup(configManager) {
428
466
  };
429
467
  const config = {
430
468
  channels: { telegram },
431
- agents,
469
+ agents: {},
432
470
  defaultAgent,
433
471
  workspace,
434
472
  security,
@@ -471,7 +509,7 @@ async function runSetup(configManager) {
471
509
  if (config.tunnel.enabled && config.tunnel.provider === "cloudflare") {
472
510
  console.log(dim(" Ensuring cloudflared is installed..."));
473
511
  try {
474
- const { ensureCloudflared } = await import("./install-cloudflared-ILUXKLAC.js");
512
+ const { ensureCloudflared } = await import("./install-cloudflared-BTGUD7SW.js");
475
513
  const binPath = await ensureCloudflared();
476
514
  console.log(ok(`cloudflared ready at ${dim(binPath)}`));
477
515
  } catch (err) {
@@ -506,4 +544,4 @@ export {
506
544
  setupRunMode,
507
545
  runSetup
508
546
  };
509
- //# sourceMappingURL=chunk-UAUTLC4E.js.map
547
+ //# sourceMappingURL=chunk-D73LCTPF.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/setup.ts"],"sourcesContent":["import { execFileSync } from \"node:child_process\";\nimport { input, select } from \"@inquirer/prompts\";\nimport type { Config, ConfigManager } from \"./config.js\";\nimport { expandHome } from \"./config.js\";\nimport { commandExists } from \"./agent-dependencies.js\";\n\n// --- ANSI colors ---\n\nconst c = {\n reset: \"\\x1b[0m\",\n bold: \"\\x1b[1m\",\n dim: \"\\x1b[2m\",\n green: \"\\x1b[32m\",\n yellow: \"\\x1b[33m\",\n red: \"\\x1b[31m\",\n cyan: \"\\x1b[36m\",\n white: \"\\x1b[37m\",\n};\n\nconst ok = (msg: string) =>\n `${c.green}${c.bold}✓${c.reset} ${c.green}${msg}${c.reset}`;\nconst warn = (msg: string) => `${c.yellow}⚠ ${msg}${c.reset}`;\nconst fail = (msg: string) => `${c.red}✗ ${msg}${c.reset}`;\nconst step = (n: number, title: string) =>\n `\\n${c.cyan}${c.bold}[${n}/3]${c.reset} ${c.bold}${title}${c.reset}\\n`;\nconst dim = (msg: string) => `${c.dim}${msg}${c.reset}`;\n\n// --- Telegram validation ---\n\nexport async function validateBotToken(\n token: string,\n): Promise<\n | { ok: true; botName: string; botUsername: string }\n | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const data = (await res.json()) as {\n ok: boolean;\n result?: { first_name: string; username: string };\n description?: string;\n };\n if (data.ok && data.result) {\n return {\n ok: true,\n botName: data.result.first_name,\n botUsername: data.result.username,\n };\n }\n return { ok: false, error: data.description || \"Invalid token\" };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\nexport async function validateChatId(\n token: string,\n chatId: number,\n): Promise<\n { ok: true; title: string; isForum: boolean } | { ok: false; error: string }\n> {\n try {\n const res = await fetch(`https://api.telegram.org/bot${token}/getChat`, {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId }),\n });\n const data = (await res.json()) as {\n ok: boolean;\n result?: { title: string; type: string; is_forum?: boolean };\n description?: string;\n };\n if (!data.ok || !data.result) {\n return { ok: false, error: data.description || \"Invalid chat ID\" };\n }\n if (data.result.type !== \"supergroup\") {\n return {\n ok: false,\n error: `Chat is \"${data.result.type}\", must be a supergroup`,\n };\n }\n return {\n ok: true,\n title: data.result.title,\n isForum: data.result.is_forum === true,\n };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\nexport async function validateBotAdmin(\n token: string,\n chatId: number,\n): Promise<{ ok: true } | { ok: false; error: string }> {\n try {\n // Get bot's own user ID\n const meRes = await fetch(`https://api.telegram.org/bot${token}/getMe`);\n const meData = (await meRes.json()) as {\n ok: boolean;\n result?: { id: number };\n };\n if (!meData.ok || !meData.result) {\n return { ok: false, error: \"Could not retrieve bot info\" };\n }\n\n const res = await fetch(\n `https://api.telegram.org/bot${token}/getChatMember`,\n {\n method: \"POST\",\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({ chat_id: chatId, user_id: meData.result.id }),\n },\n );\n const data = (await res.json()) as {\n ok: boolean;\n result?: { status: string };\n description?: string;\n };\n if (!data.ok || !data.result) {\n return {\n ok: false,\n error: data.description || \"Could not check bot membership\",\n };\n }\n\n const { status } = data.result;\n if (status === \"administrator\" || status === \"creator\") {\n return { ok: true };\n }\n return {\n ok: false,\n error: `Bot is \"${status}\" in this group. It must be an admin. Please promote the bot to admin in group settings.`,\n };\n } catch (err) {\n return { ok: false, error: (err as Error).message };\n }\n}\n\n// --- Chat ID auto-detection ---\n\nfunction promptManualChatId(): Promise<number> {\n return input({\n message: \"Supergroup chat ID (e.g. -1001234567890):\",\n validate: (val) => {\n const n = Number(val.trim());\n if (isNaN(n) || !Number.isInteger(n)) return \"Chat ID must be an integer\";\n return true;\n },\n }).then((val) => Number(val.trim()));\n}\n\nasync function detectChatId(token: string): Promise<number> {\n // Clear old updates\n let lastUpdateId = 0;\n try {\n const clearRes = await fetch(\n `https://api.telegram.org/bot${token}/getUpdates?offset=-1`,\n );\n const clearData = (await clearRes.json()) as {\n ok: boolean;\n result?: Array<{ update_id: number }>;\n };\n if (clearData.ok && clearData.result?.length) {\n lastUpdateId = clearData.result[clearData.result.length - 1].update_id;\n }\n } catch {\n // ignore\n }\n\n console.log(\"\");\n console.log(` ${c.bold}If you don't have a supergroup yet:${c.reset}`);\n console.log(dim(\" 1. Open Telegram → New Group → add your bot\"));\n console.log(dim(\" 2. Group Settings → convert to Supergroup\"));\n console.log(dim(\" 3. Enable Topics in group settings\"));\n console.log(\"\");\n console.log(` ${c.bold}Then send \"hi\" in the group.${c.reset}`);\n console.log(\n dim(\n ` Listening... press ${c.reset}${c.yellow}m${c.reset}${c.dim} to enter ID manually`,\n ),\n );\n console.log(\"\");\n\n const MAX_ATTEMPTS = 120;\n const POLL_INTERVAL = 1000;\n\n // Listen for 'm' keypress to switch to manual\n let cancelled = false;\n const onKeypress = (data: Buffer) => {\n const key = data.toString();\n if (key === \"m\" || key === \"M\") {\n cancelled = true;\n }\n };\n if (process.stdin.isTTY) {\n process.stdin.setRawMode(true);\n process.stdin.resume();\n process.stdin.on(\"data\", onKeypress);\n }\n\n const cleanup = () => {\n if (process.stdin.isTTY) {\n process.stdin.removeListener(\"data\", onKeypress);\n process.stdin.setRawMode(false);\n process.stdin.pause();\n }\n };\n\n try {\n for (let i = 0; i < MAX_ATTEMPTS; i++) {\n if (cancelled) {\n cleanup();\n return promptManualChatId();\n }\n\n try {\n const offset = lastUpdateId ? lastUpdateId + 1 : 0;\n const res = await fetch(\n `https://api.telegram.org/bot${token}/getUpdates?offset=${offset}&timeout=1`,\n );\n const data = (await res.json()) as {\n ok: boolean;\n result?: Array<{\n update_id: number;\n message?: {\n chat: { id: number; title?: string; type: string };\n };\n my_chat_member?: {\n chat: { id: number; title?: string; type: string };\n };\n }>;\n };\n\n if (!data.ok || !data.result?.length) {\n await new Promise((r) => setTimeout(r, POLL_INTERVAL));\n continue;\n }\n\n const groups = new Map<number, string>();\n for (const update of data.result) {\n lastUpdateId = update.update_id;\n const chat = update.message?.chat ?? update.my_chat_member?.chat;\n if (chat && (chat.type === \"supergroup\" || chat.type === \"group\")) {\n groups.set(chat.id, chat.title ?? String(chat.id));\n }\n }\n\n if (groups.size === 1) {\n const [id, title] = [...groups.entries()][0];\n console.log(\n ok(`Group detected: ${c.bold}${title}${c.reset}${c.green} (${id})`),\n );\n cleanup();\n return id;\n }\n\n if (groups.size > 1) {\n cleanup();\n const choices = [...groups.entries()].map(([id, title]) => ({\n name: `${title} (${id})`,\n value: id,\n }));\n return select({\n message: \"Multiple groups found. Pick one:\",\n choices,\n });\n }\n } catch {\n // Network error, retry\n }\n await new Promise((r) => setTimeout(r, POLL_INTERVAL));\n }\n\n console.log(warn(\"Timed out waiting for messages.\"));\n cleanup();\n return promptManualChatId();\n } catch (err) {\n cleanup();\n throw err;\n }\n}\n\n// --- Agent detection ---\n\nconst KNOWN_AGENTS: Array<{ name: string; commands: string[] }> = [\n // claude-agent-acp is bundled as a dependency — no detection needed, but\n // kept here so detectAgents() still returns it for display purposes.\n { name: \"claude\", commands: [\"claude-agent-acp\"] },\n { name: \"codex\", commands: [\"codex\"] },\n];\n\nexport async function detectAgents(): Promise<\n Array<{ name: string; command: string }>\n> {\n const found: Array<{ name: string; command: string }> = [];\n for (const agent of KNOWN_AGENTS) {\n // Find all available commands for this agent (PATH + node_modules/.bin)\n const available: string[] = [];\n for (const cmd of agent.commands) {\n if (commandExists(cmd)) {\n available.push(cmd);\n }\n }\n if (available.length > 0) {\n // Prefer claude-agent-acp over claude/claude-code (priority order)\n found.push({ name: agent.name, command: available[0] });\n }\n }\n return found;\n}\n\nexport async function validateAgentCommand(command: string): Promise<boolean> {\n try {\n execFileSync(\"which\", [command], { stdio: \"pipe\" });\n return true;\n } catch {\n return false;\n }\n}\n\n// --- Setup steps ---\n\nexport async function setupTelegram(): Promise<Config[\"channels\"][string]> {\n console.log(step(1, \"Telegram Bot\"));\n\n let botToken = \"\";\n\n while (true) {\n botToken = await input({\n message: \"Bot token (from @BotFather):\",\n validate: (val) => val.trim().length > 0 || \"Token cannot be empty\",\n });\n botToken = botToken.trim();\n\n const result = await validateBotToken(botToken);\n if (result.ok) {\n console.log(ok(`Connected to @${result.botUsername}`));\n break;\n }\n console.log(fail(result.error));\n const action = await select({\n message: \"What to do?\",\n choices: [\n { name: \"Re-enter token\", value: \"retry\" },\n { name: \"Use as-is (skip validation)\", value: \"skip\" },\n ],\n });\n if (action === \"skip\") break;\n }\n\n let chatId: number;\n\n while (true) {\n chatId = await detectChatId(botToken);\n\n // Validate bot can access this chat and it's a supergroup\n const chatResult = await validateChatId(botToken, chatId);\n if (!chatResult.ok) {\n console.log(fail(chatResult.error));\n console.log(\"\");\n console.log(` ${c.bold}How to fix:${c.reset}`);\n console.log(dim(\" 1. Make sure the bot is added to the group\"));\n console.log(dim(\" 2. The group must be a Supergroup (Group Settings → convert)\"));\n console.log(dim(\" 3. Send a message in the group after adding the bot\"));\n console.log(\"\");\n await input({ message: \"Press Enter to try again...\" });\n continue;\n }\n console.log(\n ok(\n `Group: ${c.bold}${chatResult.title}${c.reset}${c.green}${chatResult.isForum ? \" (Topics enabled)\" : \"\"}`,\n ),\n );\n\n // Check bot has admin privileges\n const adminResult = await validateBotAdmin(botToken, chatId);\n if (!adminResult.ok) {\n console.log(fail(adminResult.error));\n console.log(\"\");\n console.log(` ${c.bold}How to fix:${c.reset}`);\n console.log(dim(\" 1. Open the group in Telegram\"));\n console.log(dim(\" 2. Go to Group Settings → Administrators\"));\n console.log(dim(\" 3. Add the bot as an administrator\"));\n console.log(\"\");\n await input({ message: \"Press Enter to check again...\" });\n continue;\n }\n console.log(ok(\"Bot has admin privileges\"));\n break;\n }\n\n return {\n enabled: true,\n botToken,\n chatId,\n notificationTopicId: null,\n assistantTopicId: null,\n };\n}\n\nexport async function setupAgents(): Promise<{\n defaultAgent: string;\n}> {\n const { AgentCatalog } = await import(\"./agent-catalog.js\");\n const { select, checkbox } = await import(\"@inquirer/prompts\");\n\n const catalog = new AgentCatalog();\n catalog.load();\n\n console.log(dim(\" Checking available agents...\"));\n await catalog.refreshRegistryIfStale();\n\n // Claude is always pre-installed (bundled dependency)\n if (!catalog.getInstalledAgent(\"claude\")) {\n const claudeRegistry = catalog.findRegistryAgent(\"claude-acp\");\n if (claudeRegistry) {\n await catalog.install(\"claude-acp\");\n } else {\n // Fallback: register bundled claude-agent-acp directly\n const { AgentStore } = await import(\"./agent-store.js\");\n const store = new AgentStore();\n store.load();\n store.addAgent(\"claude\", {\n registryId: \"claude-acp\",\n name: \"Claude Agent\",\n version: \"bundled\",\n distribution: \"npx\",\n command: \"npx\",\n args: [\"@zed-industries/claude-agent-acp\"],\n env: {},\n installedAt: new Date().toISOString(),\n binaryPath: null,\n });\n }\n }\n console.log(ok(\"Claude Agent ready\"));\n\n const available = catalog.getAvailable();\n const installable = available.filter((a) => !a.installed && a.available);\n\n // Offer additional agents\n if (installable.length > 0) {\n const choices = installable.slice(0, 10).map((a) => ({\n name: `${a.name} (${a.distribution})`,\n value: a.key,\n checked: false,\n }));\n\n const selected = await checkbox({\n message: \"Install additional agents? (Space to select, Enter to continue)\",\n choices,\n });\n\n for (const key of selected) {\n const regAgent = catalog.findRegistryAgent(key);\n if (regAgent) {\n process.stdout.write(` Installing ${regAgent.name}... `);\n const result = await catalog.install(key);\n if (result.ok) {\n console.log(ok(\"done\"));\n } else {\n console.log(warn(`skipped: ${result.error}`));\n }\n }\n }\n }\n\n // Choose default agent\n const installedAgents = Object.keys(catalog.getInstalledEntries());\n let defaultAgent = \"claude\";\n\n if (installedAgents.length > 1) {\n defaultAgent = await select({\n message: \"Which agent should be the default?\",\n choices: installedAgents.map((key) => {\n const agent = catalog.getInstalledAgent(key)!;\n return { name: `${agent.name} (${key})`, value: key };\n }),\n default: \"claude\",\n });\n }\n\n console.log(ok(`Default agent: ${c.bold}${defaultAgent}${c.reset}`));\n return { defaultAgent };\n}\n\nexport async function setupWorkspace(): Promise<{ baseDir: string }> {\n console.log(step(2, \"Workspace\"));\n\n const baseDir = await input({\n message: \"Base directory for workspaces:\",\n default: \"~/openacp-workspace\",\n validate: (val) => val.trim().length > 0 || \"Path cannot be empty\",\n });\n\n return { baseDir: baseDir.trim().replace(/^['\"]|['\"]$/g, \"\") };\n}\n\nexport async function setupRunMode(): Promise<{ runMode: 'foreground' | 'daemon'; autoStart: boolean }> {\n console.log(step(3, 'Run Mode'))\n\n // Don't show daemon option on Windows\n if (process.platform === 'win32') {\n console.log(dim(' (Daemon mode not available on Windows)'))\n return { runMode: 'foreground', autoStart: false }\n }\n\n const mode = await select({\n message: 'How would you like to run OpenACP?',\n choices: [\n {\n name: 'Background (daemon)',\n value: 'daemon' as const,\n description: 'Runs silently, auto-starts on boot. Manage with: openacp status | stop | logs',\n },\n {\n name: 'Foreground (terminal)',\n value: 'foreground' as const,\n description: 'Runs in current terminal session. Start with: openacp',\n },\n ],\n })\n\n if (mode === 'daemon') {\n const { installAutoStart, isAutoStartSupported } = await import('./autostart.js')\n const autoStart = isAutoStartSupported()\n if (autoStart) {\n const result = installAutoStart(expandHome('~/.openacp/logs'))\n if (result.success) {\n console.log(ok('Auto-start on boot enabled'))\n } else {\n console.log(warn(`Auto-start failed: ${result.error}`))\n }\n }\n return { runMode: 'daemon', autoStart }\n }\n\n return { runMode: 'foreground', autoStart: false }\n}\n\n// --- Orchestrator ---\n\nfunction printWelcomeBanner(): void {\n console.log(`\n${c.cyan}${c.bold} ╔══════════════════════════════╗\n ║ Welcome to OpenACP ║\n ╚══════════════════════════════╝${c.reset}\n`);\n}\n\nexport async function runSetup(configManager: ConfigManager): Promise<boolean> {\n printWelcomeBanner();\n\n try {\n const telegram = await setupTelegram();\n const { defaultAgent } = await setupAgents();\n\n // Offer Claude CLI integration\n {\n const { confirm } = await import(\"@inquirer/prompts\");\n const installClaude = await confirm({\n message: \"Install session transfer for Claude? (enables /openacp:handoff in your terminal)\",\n default: true,\n });\n\n if (installClaude) {\n try {\n const { getIntegration } = await import(\"../cli/integrate.js\");\n const integration = getIntegration(\"claude\");\n if (integration) {\n for (const item of integration.items) {\n const result = await item.install();\n for (const log of result.logs) console.log(` ${log}`);\n }\n }\n console.log(\"Claude CLI integration installed.\\n\");\n } catch (err) {\n console.log(`Could not install Claude CLI integration: ${err instanceof Error ? err.message : err}`);\n console.log(\" You can install it later with: openacp integrate claude\\n\");\n }\n }\n }\n\n const workspace = await setupWorkspace();\n const { runMode, autoStart } = await setupRunMode();\n const security = {\n allowedUserIds: [] as string[],\n maxConcurrentSessions: 20,\n sessionTimeoutMinutes: 60,\n };\n\n const config: Config = {\n channels: { telegram },\n agents: {},\n defaultAgent,\n workspace,\n security,\n logging: {\n level: \"info\",\n logDir: \"~/.openacp/logs\",\n maxFileSize: \"10m\",\n maxFiles: 7,\n sessionLogRetentionDays: 30,\n },\n runMode,\n autoStart,\n api: {\n port: 21420,\n host: '127.0.0.1',\n },\n sessionStore: { ttlDays: 30 },\n tunnel: {\n enabled: true,\n port: 3100,\n provider: \"cloudflare\",\n options: {},\n storeTtlMinutes: 60,\n auth: { enabled: false },\n },\n integrations: {},\n };\n\n try {\n await configManager.writeNew(config);\n } catch (writeErr) {\n console.log(\n fail(`Could not save config: ${(writeErr as Error).message}`),\n );\n return false;\n }\n\n console.log(\"\");\n console.log(\n ok(`Config saved to ${c.bold}${configManager.getConfigPath()}`),\n );\n\n // Pre-download cloudflared if tunnel enabled\n if (config.tunnel.enabled && config.tunnel.provider === \"cloudflare\") {\n console.log(dim(\" Ensuring cloudflared is installed...\"));\n try {\n const { ensureCloudflared } = await import(\n \"../tunnel/providers/install-cloudflared.js\"\n );\n const binPath = await ensureCloudflared();\n console.log(ok(`cloudflared ready at ${dim(binPath)}`));\n } catch (err) {\n console.log(\n warn(\n `Could not install cloudflared: ${(err as Error).message}. Tunnel may not work.`,\n ),\n );\n }\n }\n\n console.log(ok(\"Starting OpenACP...\"));\n console.log(\"\");\n\n return true;\n } catch (err) {\n if ((err as Error).name === \"ExitPromptError\") {\n console.log(dim(\"\\nSetup cancelled.\"));\n return false;\n }\n throw err;\n }\n}\n"],"mappings":"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","names":["select"]}
@@ -94,6 +94,9 @@ function initLogger(config) {
94
94
  Object.assign(log, wrapVariadic(rootLogger));
95
95
  return rootLogger;
96
96
  }
97
+ function setLogLevel(level) {
98
+ rootLogger.level = level;
99
+ }
97
100
  function createChildLogger(context) {
98
101
  return new Proxy({}, {
99
102
  get(_target, prop, receiver) {
@@ -189,9 +192,10 @@ async function cleanupOldSessionLogs(retentionDays) {
189
192
  export {
190
193
  log,
191
194
  initLogger,
195
+ setLogLevel,
192
196
  createChildLogger,
193
197
  createSessionLogger,
194
198
  shutdownLogger,
195
199
  cleanupOldSessionLogs
196
200
  };
197
- //# sourceMappingURL=chunk-LYKCQTH5.js.map
201
+ //# sourceMappingURL=chunk-ESOPMQAY.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/core/log.ts"],"sourcesContent":["import pino from 'pino'\nimport fs from 'node:fs'\nimport path from 'node:path'\nimport os from 'node:os'\nimport type { LoggingConfig } from './config.js'\n\nexport type Logger = pino.Logger\n\n// --- Default console-only logger (pre-init) ---\nlet rootLogger: pino.Logger = pino({\n level: 'debug',\n transport: { target: 'pino-pretty', options: { colorize: true, translateTime: 'SYS:standard' } },\n})\nlet initialized = false\nlet logDir: string | undefined\nlet currentTransport: ReturnType<typeof pino.transport> | undefined\n\nfunction expandHome(p: string): string {\n return p.startsWith('~') ? path.join(os.homedir(), p.slice(1)) : p\n}\n\n// --- Variadic wrapper for backward compatibility ---\nfunction wrapVariadic(logger: pino.Logger) {\n return {\n info: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.info(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.info(args.map(String).join(' '))\n }\n },\n warn: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.warn(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.warn(args.map(String).join(' '))\n }\n },\n error: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.error(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.error(args.map(String).join(' '))\n }\n },\n debug: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.debug(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.debug(args.map(String).join(' '))\n }\n },\n fatal: (...args: unknown[]) => {\n if (args.length === 0) return\n if (typeof args[0] === 'object' && args[0] !== null && !(args[0] instanceof Error)) {\n logger.fatal(args[0] as object, args.slice(1).join(' '))\n } else {\n logger.fatal(args.map(String).join(' '))\n }\n },\n child: (bindings: pino.Bindings) => logger.child(bindings),\n }\n}\n\nexport const log = wrapVariadic(rootLogger)\n\n// --- Public API ---\n\nexport function initLogger(config: LoggingConfig): Logger {\n if (initialized) return rootLogger\n\n const resolvedLogDir = expandHome(config.logDir)\n logDir = resolvedLogDir\n\n try {\n fs.mkdirSync(resolvedLogDir, { recursive: true })\n fs.mkdirSync(path.join(resolvedLogDir, 'sessions'), { recursive: true })\n } catch (err) {\n console.error(`[WARN] Failed to create log directory ${resolvedLogDir}, falling back to console-only:`, err)\n return rootLogger\n }\n\n const transports = pino.transport({\n targets: [\n {\n target: 'pino-pretty',\n options: { colorize: true, translateTime: 'SYS:standard' },\n level: config.level,\n },\n {\n target: 'pino-roll',\n options: {\n file: path.join(resolvedLogDir, 'openacp.log'),\n size: config.maxFileSize,\n limit: { count: config.maxFiles },\n },\n level: config.level,\n },\n ],\n })\n\n currentTransport = transports\n rootLogger = pino({ level: config.level }, transports)\n initialized = true\n\n // Update the default log wrapper to use the new root logger\n Object.assign(log, wrapVariadic(rootLogger))\n\n return rootLogger\n}\n\n/** Change log level at runtime. Pino transport targets respect parent level changes automatically. */\nexport function setLogLevel(level: string): void {\n rootLogger.level = level\n}\n\nexport function createChildLogger(context: { module: string; [key: string]: unknown }): Logger {\n // Return a proxy that always delegates to the current rootLogger.\n // This ensures child loggers created at module-level (before initLogger)\n // pick up the initialized logger with pino-pretty transport.\n return new Proxy({} as Logger, {\n get(_target, prop, receiver) {\n const child = rootLogger.child(context)\n const value = Reflect.get(child, prop, receiver)\n return typeof value === 'function' ? value.bind(child) : value\n },\n })\n}\n\nexport function createSessionLogger(sessionId: string, parentLogger: Logger): Logger {\n const sessionLogDir = logDir ? path.join(logDir, 'sessions') : undefined\n if (!sessionLogDir) {\n return parentLogger.child({ sessionId })\n }\n\n try {\n const sessionLogPath = path.join(sessionLogDir, `${sessionId}.log`)\n const dest = pino.destination(sessionLogPath)\n const sessionFileLogger = pino({ level: parentLogger.level }, dest).child({ sessionId })\n\n // Create a logger that writes to both parent (combined) and session file\n const combinedChild = parentLogger.child({ sessionId })\n const originalInfo = combinedChild.info.bind(combinedChild)\n const originalWarn = combinedChild.warn.bind(combinedChild)\n const originalError = combinedChild.error.bind(combinedChild)\n const originalDebug = combinedChild.debug.bind(combinedChild)\n const originalFatal = combinedChild.fatal.bind(combinedChild)\n\n // Proxy log methods to write to both destinations\n combinedChild.info = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.info(objOrMsg, ...rest)\n return originalInfo(objOrMsg, ...rest)\n }) as any\n combinedChild.warn = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.warn(objOrMsg, ...rest)\n return originalWarn(objOrMsg, ...rest)\n }) as any\n combinedChild.error = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.error(objOrMsg, ...rest)\n return originalError(objOrMsg, ...rest)\n }) as any\n combinedChild.debug = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.debug(objOrMsg, ...rest)\n return originalDebug(objOrMsg, ...rest)\n }) as any\n combinedChild.fatal = ((objOrMsg: any, ...rest: any[]) => {\n sessionFileLogger.fatal(objOrMsg, ...rest)\n return originalFatal(objOrMsg, ...rest)\n }) as any\n\n // Store dest for cleanup\n ;(combinedChild as any).__sessionDest = dest\n\n return combinedChild\n } catch (err) {\n // Graceful degradation: session file failed, just use combined log\n parentLogger.warn({ sessionId, err }, 'Failed to create session log file, using combined log only')\n return parentLogger.child({ sessionId })\n }\n}\n\nexport async function shutdownLogger(): Promise<void> {\n if (!initialized) return\n\n const transport = currentTransport\n\n // Reset state immediately so re-init is possible\n rootLogger = pino({ level: 'debug' })\n Object.assign(log, wrapVariadic(rootLogger))\n currentTransport = undefined\n logDir = undefined\n initialized = false\n\n if (transport) {\n await new Promise<void>((resolve) => {\n const timeout = setTimeout(resolve, 3000)\n transport.on('close', () => {\n clearTimeout(timeout)\n resolve()\n })\n transport.end()\n })\n }\n}\n\nexport async function cleanupOldSessionLogs(retentionDays: number): Promise<void> {\n if (!logDir) return\n\n const sessionsDir = path.join(logDir, 'sessions')\n try {\n const files = await fs.promises.readdir(sessionsDir)\n const cutoff = Date.now() - retentionDays * 24 * 60 * 60 * 1000\n\n for (const file of files) {\n try {\n const filePath = path.join(sessionsDir, file)\n const stat = await fs.promises.stat(filePath)\n if (stat.mtimeMs < cutoff) {\n await fs.promises.unlink(filePath)\n rootLogger.debug({ file }, 'Deleted old session log')\n }\n } catch (err) {\n rootLogger.warn({ file, err }, 'Failed to delete old session log')\n }\n }\n } catch {\n // Sessions directory doesn't exist — no-op\n }\n}\n"],"mappings":"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","names":[]}