ccpoke 1.4.2 → 1.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.
- package/README.en.md +26 -11
- package/README.md +26 -11
- package/dist/agent/agent-handler.d.ts +12 -0
- package/dist/agent/agent-handler.js +49 -0
- package/dist/agent/agent-handler.js.map +1 -0
- package/dist/agent/agent-registry.d.ts +9 -0
- package/dist/agent/agent-registry.js +24 -0
- package/dist/agent/agent-registry.js.map +1 -0
- package/dist/{hook/hook-installer.d.ts → agent/claude-code/claude-code-installer.d.ts} +2 -2
- package/dist/agent/claude-code/claude-code-installer.js +82 -0
- package/dist/agent/claude-code/claude-code-installer.js.map +1 -0
- package/dist/{monitor/transcript-parser.d.ts → agent/claude-code/claude-code-parser.d.ts} +6 -0
- package/dist/{monitor/transcript-parser.js → agent/claude-code/claude-code-parser.js} +10 -2
- package/dist/agent/claude-code/claude-code-parser.js.map +1 -0
- package/dist/agent/claude-code/claude-code-provider.d.ts +12 -0
- package/dist/agent/claude-code/claude-code-provider.js +72 -0
- package/dist/agent/claude-code/claude-code-provider.js.map +1 -0
- package/dist/agent/cursor/cursor-installer.d.ts +9 -0
- package/dist/agent/cursor/cursor-installer.js +89 -0
- package/dist/agent/cursor/cursor-installer.js.map +1 -0
- package/dist/agent/cursor/cursor-parser.d.ts +19 -0
- package/dist/agent/cursor/cursor-parser.js +61 -0
- package/dist/agent/cursor/cursor-parser.js.map +1 -0
- package/dist/agent/cursor/cursor-provider.d.ts +12 -0
- package/dist/agent/cursor/cursor-provider.js +72 -0
- package/dist/agent/cursor/cursor-provider.js.map +1 -0
- package/dist/agent/types.d.ts +27 -0
- package/dist/agent/types.js +11 -0
- package/dist/agent/types.js.map +1 -0
- package/dist/channel/telegram/telegram-channel.js +7 -90
- package/dist/channel/telegram/telegram-channel.js.map +1 -1
- package/dist/channel/types.d.ts +2 -0
- package/dist/commands/setup.js +83 -19
- package/dist/commands/setup.js.map +1 -1
- package/dist/commands/uninstall.js +12 -9
- package/dist/commands/uninstall.js.map +1 -1
- package/dist/config-manager.d.ts +2 -1
- package/dist/config-manager.js +21 -17
- package/dist/config-manager.js.map +1 -1
- package/dist/i18n/index.d.ts +7 -2
- package/dist/i18n/index.js +10 -5
- package/dist/i18n/index.js.map +1 -1
- package/dist/i18n/locales/en.js +11 -0
- package/dist/i18n/locales/en.js.map +1 -1
- package/dist/i18n/locales/vi.js +11 -0
- package/dist/i18n/locales/vi.js.map +1 -1
- package/dist/i18n/locales/zh.js +11 -0
- package/dist/i18n/locales/zh.js.map +1 -1
- package/dist/i18n/types.d.ts +11 -0
- package/dist/index.js +28 -8
- package/dist/index.js.map +1 -1
- package/dist/{hook/hook-server.d.ts → server/api-server.d.ts} +3 -3
- package/dist/{hook/hook-server.js → server/api-server.js} +6 -4
- package/dist/server/api-server.js.map +1 -0
- package/dist/utils/git-collector.js.map +1 -0
- package/dist/utils/markdown.d.ts +4 -0
- package/dist/utils/markdown.js +47 -0
- package/dist/utils/markdown.js.map +1 -0
- package/dist/utils/paths.d.ts +4 -1
- package/dist/utils/paths.js +5 -1
- package/dist/utils/paths.js.map +1 -1
- package/dist/utils/response-store.d.ts +2 -0
- package/dist/utils/response-store.js.map +1 -1
- package/dist/utils/stats-format.d.ts +3 -0
- package/dist/utils/stats-format.js +44 -0
- package/dist/utils/stats-format.js.map +1 -0
- package/package.json +4 -1
- package/dist/hook/hook-handler.d.ts +0 -10
- package/dist/hook/hook-handler.js +0 -76
- package/dist/hook/hook-handler.js.map +0 -1
- package/dist/hook/hook-installer.js +0 -110
- package/dist/hook/hook-installer.js.map +0 -1
- package/dist/hook/hook-server.js.map +0 -1
- package/dist/hook/response-store.d.ts +0 -8
- package/dist/hook/response-store.js +0 -18
- package/dist/monitor/git-collector.js.map +0 -1
- package/dist/monitor/transcript-parser.js.map +0 -1
- package/dist/setup.d.ts +0 -1
- package/dist/setup.js +0 -130
- package/dist/telegram/bot.d.ts +0 -20
- package/dist/telegram/bot.js +0 -130
- package/dist/telegram/message-formatter.d.ts +0 -18
- package/dist/telegram/message-formatter.js +0 -56
- package/dist/telegram/message-sender.d.ts +0 -2
- package/dist/telegram/message-sender.js +0 -76
- package/dist/utils/error-utils.d.ts +0 -1
- package/dist/utils/error-utils.js +0 -3
- /package/dist/{monitor → utils}/git-collector.d.ts +0 -0
- /package/dist/{monitor → utils}/git-collector.js +0 -0
package/README.en.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
# 🤖 ccpoke —
|
|
1
|
+
# 🤖 ccpoke — AI Agent ↔ Telegram Notification Bot
|
|
2
2
|
|
|
3
3
|
[Tiếng Việt](./README.md)
|
|
4
4
|
|
|
5
|
-
> Get Telegram notifications when Claude Code completes a response — with git diff, processing time, and result summary.
|
|
5
|
+
> Get Telegram notifications when your AI agent (Claude Code, Cursor, ...) completes a response — with git diff, processing time, and result summary.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## Problem
|
|
10
10
|
|
|
11
|
-
You're using Claude Code on your computer. You step away with your phone but have no idea if
|
|
11
|
+
You're using Claude Code or Cursor on your computer. You step away with your phone but have no idea if the AI agent is done yet or what files it changed.
|
|
12
12
|
|
|
13
|
-
**ccpoke** is a lightweight bridge between
|
|
13
|
+
**ccpoke** is a lightweight bridge between AI agents and Telegram — when any agent finishes, you get a notification right on your phone.
|
|
14
14
|
|
|
15
15
|
```
|
|
16
|
-
|
|
16
|
+
AI agent completes response
|
|
17
17
|
↓
|
|
18
18
|
Stop Hook triggers
|
|
19
19
|
↓
|
|
@@ -22,12 +22,22 @@ Claude Code completes response
|
|
|
22
22
|
Telegram notification 📱
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
## Supported Agents
|
|
26
|
+
|
|
27
|
+
| Agent | Status |
|
|
28
|
+
|-------|--------|
|
|
29
|
+
| Claude Code | ✅ Supported |
|
|
30
|
+
| Cursor | ✅ Supported |
|
|
31
|
+
|
|
32
|
+
Adding new agents is easy via the plugin architecture — contributions welcome!
|
|
33
|
+
|
|
25
34
|
## Features
|
|
26
35
|
|
|
27
|
-
-
|
|
36
|
+
- 🤖 **Multi-agent** — supports Claude Code, Cursor and more
|
|
37
|
+
- 🔔 **Auto notification** — AI agent finishes → Telegram notifies you instantly
|
|
28
38
|
- 📂 **Git diff included** — see changed files without opening your computer
|
|
29
|
-
- ⏱ **Processing time** — know how long
|
|
30
|
-
- 📝 **Response summary** — quick glance at what
|
|
39
|
+
- ⏱ **Processing time** — know how long the agent took
|
|
40
|
+
- 📝 **Response summary** — quick glance at what the agent replied
|
|
31
41
|
- 🔐 **User whitelist** — only authorized users can use the bot
|
|
32
42
|
- 📄 **Auto-split messages** — long responses are automatically paginated `[1/N]`
|
|
33
43
|
|
|
@@ -89,8 +99,12 @@ The setup wizard will guide you step by step:
|
|
|
89
99
|
│
|
|
90
100
|
◆ ✓ Connected! User ID: 123456789
|
|
91
101
|
│
|
|
102
|
+
◇ Select AI agents (space to toggle)
|
|
103
|
+
│ Claude Code, Cursor
|
|
104
|
+
│
|
|
92
105
|
◆ Config saved
|
|
93
|
-
◆ Hook installed
|
|
106
|
+
◆ Hook installed for Claude Code
|
|
107
|
+
◆ Hook installed for Cursor
|
|
94
108
|
◆ Chat ID registered
|
|
95
109
|
│
|
|
96
110
|
└ 🎉 Setup complete!
|
|
@@ -128,7 +142,7 @@ ccpoke
|
|
|
128
142
|
pnpm dev
|
|
129
143
|
```
|
|
130
144
|
|
|
131
|
-
Once running, use Claude Code as usual → notifications will arrive on Telegram.
|
|
145
|
+
Once running, use Claude Code / Cursor as usual → notifications will arrive on Telegram.
|
|
132
146
|
|
|
133
147
|
### Telegram Commands
|
|
134
148
|
|
|
@@ -163,7 +177,8 @@ ccpoke uninstall
|
|
|
163
177
|
```
|
|
164
178
|
┌ 🗑️ Uninstalling ccpoke
|
|
165
179
|
│
|
|
166
|
-
◆ Hook removed from
|
|
180
|
+
◆ Hook removed from Claude Code
|
|
181
|
+
◆ Hook removed from Cursor
|
|
167
182
|
◆ Removed ~/.ccpoke/ (config, state, hooks)
|
|
168
183
|
│
|
|
169
184
|
└ ccpoke uninstalled
|
package/README.md
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
# 🤖 ccpoke —
|
|
1
|
+
# 🤖 ccpoke — AI Agent ↔ Telegram Notification Bot
|
|
2
2
|
|
|
3
3
|
[English](./README.en.md)
|
|
4
4
|
|
|
5
|
-
> Nhận thông báo Telegram khi Claude Code hoàn thành response — kèm git diff, thời gian xử lý, và tóm tắt kết quả.
|
|
5
|
+
> Nhận thông báo Telegram khi AI agent (Claude Code, Cursor, ...) hoàn thành response — kèm git diff, thời gian xử lý, và tóm tắt kết quả.
|
|
6
6
|
|
|
7
7
|
---
|
|
8
8
|
|
|
9
9
|
## Vấn đề giải quyết
|
|
10
10
|
|
|
11
|
-
Bạn đang dùng Claude Code trên máy tính. Ra ngoài cầm điện thoại nhưng không biết
|
|
11
|
+
Bạn đang dùng Claude Code hoặc Cursor trên máy tính. Ra ngoài cầm điện thoại nhưng không biết AI agent đã xong chưa, thay đổi file nào.
|
|
12
12
|
|
|
13
|
-
**ccpoke** là cầu nối nhẹ giữa
|
|
13
|
+
**ccpoke** là cầu nối nhẹ giữa AI agents và Telegram — khi agent xong việc, bạn nhận notification ngay trên điện thoại.
|
|
14
14
|
|
|
15
15
|
```
|
|
16
|
-
|
|
16
|
+
AI agent xong response
|
|
17
17
|
↓
|
|
18
18
|
Stop Hook trigger
|
|
19
19
|
↓
|
|
@@ -22,12 +22,22 @@ Claude Code xong response
|
|
|
22
22
|
Telegram notification 📱
|
|
23
23
|
```
|
|
24
24
|
|
|
25
|
+
## Supported Agents
|
|
26
|
+
|
|
27
|
+
| Agent | Trạng thái |
|
|
28
|
+
|-------|-----------|
|
|
29
|
+
| Claude Code | ✅ Hỗ trợ |
|
|
30
|
+
| Cursor | ✅ Hỗ trợ |
|
|
31
|
+
|
|
32
|
+
Thêm agent mới qua kiến trúc plugin — contributions welcome!
|
|
33
|
+
|
|
25
34
|
## Tính năng
|
|
26
35
|
|
|
27
|
-
-
|
|
36
|
+
- 🤖 **Multi-agent** — hỗ trợ Claude Code, Cursor và mở rộng thêm
|
|
37
|
+
- 🔔 **Notification tự động** — AI agent xong → Telegram nhận tin ngay
|
|
28
38
|
- 📂 **Git diff kèm theo** — biết file nào thay đổi mà không cần mở máy tính
|
|
29
|
-
- ⏱ **Thời gian xử lý** — biết
|
|
30
|
-
- 📝 **Tóm tắt response** — xem nhanh
|
|
39
|
+
- ⏱ **Thời gian xử lý** — biết agent chạy bao lâu
|
|
40
|
+
- 📝 **Tóm tắt response** — xem nhanh agent trả lời gì
|
|
31
41
|
- 🔐 **Whitelist user** — chỉ user được phép mới dùng được bot
|
|
32
42
|
- 📄 **Auto-split message** — response dài tự động chia page `[1/N]`
|
|
33
43
|
|
|
@@ -89,8 +99,12 @@ Setup wizard sẽ hướng dẫn từng bước:
|
|
|
89
99
|
│
|
|
90
100
|
◆ ✓ Connected! User ID: 123456789
|
|
91
101
|
│
|
|
102
|
+
◇ Chọn AI agents (ấn cách để chọn)
|
|
103
|
+
│ Claude Code, Cursor
|
|
104
|
+
│
|
|
92
105
|
◆ Config saved
|
|
93
|
-
◆ Hook installed
|
|
106
|
+
◆ Hook installed for Claude Code
|
|
107
|
+
◆ Hook installed for Cursor
|
|
94
108
|
◆ Chat ID registered
|
|
95
109
|
│
|
|
96
110
|
└ 🎉 Setup complete!
|
|
@@ -128,7 +142,7 @@ ccpoke
|
|
|
128
142
|
pnpm dev
|
|
129
143
|
```
|
|
130
144
|
|
|
131
|
-
Bot chạy xong → dùng Claude Code bình thường → notification tự đến Telegram.
|
|
145
|
+
Bot chạy xong → dùng Claude Code / Cursor bình thường → notification tự đến Telegram.
|
|
132
146
|
|
|
133
147
|
### Telegram Commands
|
|
134
148
|
|
|
@@ -163,7 +177,8 @@ ccpoke uninstall
|
|
|
163
177
|
```
|
|
164
178
|
┌ 🗑️ Uninstalling ccpoke
|
|
165
179
|
│
|
|
166
|
-
◆ Hook removed from
|
|
180
|
+
◆ Hook removed from Claude Code
|
|
181
|
+
◆ Hook removed from Cursor
|
|
167
182
|
◆ Removed ~/.ccpoke/ (config, state, hooks)
|
|
168
183
|
│
|
|
169
184
|
└ ccpoke uninstalled
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentRegistry } from "./agent-registry.js";
|
|
2
|
+
import type { NotificationChannel } from "../channel/types.js";
|
|
3
|
+
import type { TunnelManager } from "../utils/tunnel.js";
|
|
4
|
+
export declare class AgentHandler {
|
|
5
|
+
private registry;
|
|
6
|
+
private channel;
|
|
7
|
+
private hookPort;
|
|
8
|
+
private tunnelManager;
|
|
9
|
+
constructor(registry: AgentRegistry, channel: NotificationChannel, hookPort: number, tunnelManager: TunnelManager);
|
|
10
|
+
handleStopEvent(agentName: string, rawEvent: unknown): Promise<void>;
|
|
11
|
+
private buildResponseUrl;
|
|
12
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { MINI_APP_BASE_URL } from "../utils/constants.js";
|
|
2
|
+
import { responseStore } from "../utils/response-store.js";
|
|
3
|
+
import { t } from "../i18n/index.js";
|
|
4
|
+
import { log, logError } from "../utils/log.js";
|
|
5
|
+
export class AgentHandler {
|
|
6
|
+
registry;
|
|
7
|
+
channel;
|
|
8
|
+
hookPort;
|
|
9
|
+
tunnelManager;
|
|
10
|
+
constructor(registry, channel, hookPort, tunnelManager) {
|
|
11
|
+
this.registry = registry;
|
|
12
|
+
this.channel = channel;
|
|
13
|
+
this.hookPort = hookPort;
|
|
14
|
+
this.tunnelManager = tunnelManager;
|
|
15
|
+
}
|
|
16
|
+
async handleStopEvent(agentName, rawEvent) {
|
|
17
|
+
const provider = this.registry.resolve(agentName);
|
|
18
|
+
if (!provider) {
|
|
19
|
+
log(t("agent.unknownAgent", { agent: agentName }));
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
if (provider.settleDelayMs > 0) {
|
|
23
|
+
await new Promise((resolve) => setTimeout(resolve, provider.settleDelayMs));
|
|
24
|
+
}
|
|
25
|
+
const result = provider.parseEvent(rawEvent);
|
|
26
|
+
const data = {
|
|
27
|
+
agent: provider.name,
|
|
28
|
+
agentDisplayName: provider.displayName,
|
|
29
|
+
...result,
|
|
30
|
+
};
|
|
31
|
+
const responseUrl = this.buildResponseUrl(data);
|
|
32
|
+
this.channel.sendNotification(data, responseUrl).catch((err) => {
|
|
33
|
+
logError(t("hook.notificationFailed"), err);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
buildResponseUrl(data) {
|
|
37
|
+
const id = responseStore.save(data);
|
|
38
|
+
const apiBase = this.tunnelManager.getPublicUrl() || `http://localhost:${this.hookPort}`;
|
|
39
|
+
const params = new URLSearchParams({
|
|
40
|
+
id,
|
|
41
|
+
api: apiBase,
|
|
42
|
+
p: data.projectName,
|
|
43
|
+
d: String(data.durationMs),
|
|
44
|
+
a: data.agent,
|
|
45
|
+
});
|
|
46
|
+
return `${MINI_APP_BASE_URL}/response/?${params.toString()}`;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
//# sourceMappingURL=agent-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-handler.js","sourceRoot":"","sources":["../../src/agent/agent-handler.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AAC1D,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAC3D,OAAO,EAAE,CAAC,EAAE,MAAM,kBAAkB,CAAC;AACrC,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD,MAAM,OAAO,YAAY;IAEb;IACA;IACA;IACA;IAJV,YACU,QAAuB,EACvB,OAA4B,EAC5B,QAAgB,EAChB,aAA4B;QAH5B,aAAQ,GAAR,QAAQ,CAAe;QACvB,YAAO,GAAP,OAAO,CAAqB;QAC5B,aAAQ,GAAR,QAAQ,CAAQ;QAChB,kBAAa,GAAb,aAAa,CAAe;IACnC,CAAC;IAEJ,KAAK,CAAC,eAAe,CAAC,SAAiB,EAAE,QAAiB;QACxD,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;QAClD,IAAI,CAAC,QAAQ,EAAE,CAAC;YACd,GAAG,CAAC,CAAC,CAAC,oBAAoB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CAAC,CAAC;YACnD,OAAO;QACT,CAAC;QAED,IAAI,QAAQ,CAAC,aAAa,GAAG,CAAC,EAAE,CAAC;YAC/B,MAAM,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,QAAQ,CAAC,aAAa,CAAC,CAAC,CAAC;QAC9E,CAAC;QAED,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC;QAE7C,MAAM,IAAI,GAAqB;YAC7B,KAAK,EAAE,QAAQ,CAAC,IAAI;YACpB,gBAAgB,EAAE,QAAQ,CAAC,WAAW;YACtC,GAAG,MAAM;SACV,CAAC;QAEF,MAAM,WAAW,GAAG,IAAI,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC;QAChD,IAAI,CAAC,OAAO,CAAC,gBAAgB,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC,KAAK,CAAC,CAAC,GAAY,EAAE,EAAE;YACtE,QAAQ,CAAC,CAAC,CAAC,yBAAyB,CAAC,EAAE,GAAG,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;IACL,CAAC;IAEO,gBAAgB,CAAC,IAAsB;QAC7C,MAAM,EAAE,GAAG,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAEpC,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,YAAY,EAAE,IAAI,oBAAoB,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzF,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC;YACjC,EAAE;YACF,GAAG,EAAE,OAAO;YACZ,CAAC,EAAE,IAAI,CAAC,WAAW;YACnB,CAAC,EAAE,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC;YAC1B,CAAC,EAAE,IAAI,CAAC,KAAK;SACd,CAAC,CAAC;QACH,OAAO,GAAG,iBAAiB,cAAc,MAAM,CAAC,QAAQ,EAAE,EAAE,CAAC;IAC/D,CAAC;CACF"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AgentProvider } from "./types.js";
|
|
2
|
+
export declare class AgentRegistry {
|
|
3
|
+
private providers;
|
|
4
|
+
register(provider: AgentProvider): void;
|
|
5
|
+
resolve(name: string): AgentProvider | undefined;
|
|
6
|
+
all(): AgentProvider[];
|
|
7
|
+
detectInstalled(): AgentProvider[];
|
|
8
|
+
}
|
|
9
|
+
export declare function createDefaultRegistry(): AgentRegistry;
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { ClaudeCodeProvider } from "./claude-code/claude-code-provider.js";
|
|
2
|
+
import { CursorProvider } from "./cursor/cursor-provider.js";
|
|
3
|
+
export class AgentRegistry {
|
|
4
|
+
providers = new Map();
|
|
5
|
+
register(provider) {
|
|
6
|
+
this.providers.set(provider.name, provider);
|
|
7
|
+
}
|
|
8
|
+
resolve(name) {
|
|
9
|
+
return this.providers.get(name);
|
|
10
|
+
}
|
|
11
|
+
all() {
|
|
12
|
+
return [...this.providers.values()];
|
|
13
|
+
}
|
|
14
|
+
detectInstalled() {
|
|
15
|
+
return this.all().filter((p) => p.detect());
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
export function createDefaultRegistry() {
|
|
19
|
+
const registry = new AgentRegistry();
|
|
20
|
+
registry.register(new ClaudeCodeProvider());
|
|
21
|
+
registry.register(new CursorProvider());
|
|
22
|
+
return registry;
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=agent-registry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"agent-registry.js","sourceRoot":"","sources":["../../src/agent/agent-registry.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE7D,MAAM,OAAO,aAAa;IAChB,SAAS,GAAG,IAAI,GAAG,EAAyB,CAAC;IAErD,QAAQ,CAAC,QAAuB;QAC9B,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,CAAC,IAAY;QAClB,OAAO,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IAClC,CAAC;IAED,GAAG;QACD,OAAO,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;IACtC,CAAC;IAED,eAAe;QACb,OAAO,IAAI,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IAC9C,CAAC;CACF;AAED,MAAM,UAAU,qBAAqB;IACnC,MAAM,QAAQ,GAAG,IAAI,aAAa,EAAE,CAAC;IACrC,QAAQ,CAAC,QAAQ,CAAC,IAAI,kBAAkB,EAAE,CAAC,CAAC;IAC5C,QAAQ,CAAC,QAAQ,CAAC,IAAI,cAAc,EAAE,CAAC,CAAC;IACxC,OAAO,QAAQ,CAAC;AAClB,CAAC"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
export declare class
|
|
1
|
+
export declare class ClaudeCodeInstaller {
|
|
2
2
|
static isInstalled(): boolean;
|
|
3
3
|
static install(hookPort: number, hookSecret: string): void;
|
|
4
4
|
static uninstall(): void;
|
|
5
|
-
private static
|
|
5
|
+
private static writeScript;
|
|
6
6
|
private static removeScript;
|
|
7
7
|
private static removeFromSettings;
|
|
8
8
|
private static readSettings;
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, unlinkSync } from "node:fs";
|
|
2
|
+
import { paths } from "../../utils/paths.js";
|
|
3
|
+
import { ApiRoute } from "../../utils/constants.js";
|
|
4
|
+
import { AgentName } from "../types.js";
|
|
5
|
+
function hasCcpokeHook(entries) {
|
|
6
|
+
return entries.some((entry) => entry.hooks?.some((h) => typeof h.command === "string" && h.command.includes("ccpoke")));
|
|
7
|
+
}
|
|
8
|
+
export class ClaudeCodeInstaller {
|
|
9
|
+
static isInstalled() {
|
|
10
|
+
try {
|
|
11
|
+
const settings = ClaudeCodeInstaller.readSettings();
|
|
12
|
+
return hasCcpokeHook(settings.hooks?.Stop ?? []);
|
|
13
|
+
}
|
|
14
|
+
catch {
|
|
15
|
+
return false;
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
static install(hookPort, hookSecret) {
|
|
19
|
+
const settings = ClaudeCodeInstaller.readSettings();
|
|
20
|
+
if (!settings.hooks)
|
|
21
|
+
settings.hooks = {};
|
|
22
|
+
const stopEntries = settings.hooks.Stop ?? [];
|
|
23
|
+
if (hasCcpokeHook(stopEntries))
|
|
24
|
+
return;
|
|
25
|
+
stopEntries.push({
|
|
26
|
+
hooks: [{ type: "command", command: paths.claudeCodeHookScript, timeout: 10 }],
|
|
27
|
+
});
|
|
28
|
+
settings.hooks.Stop = stopEntries;
|
|
29
|
+
mkdirSync(paths.claudeDir, { recursive: true });
|
|
30
|
+
writeFileSync(paths.claudeSettings, JSON.stringify(settings, null, 2));
|
|
31
|
+
ClaudeCodeInstaller.writeScript(hookPort, hookSecret);
|
|
32
|
+
}
|
|
33
|
+
static uninstall() {
|
|
34
|
+
ClaudeCodeInstaller.removeFromSettings();
|
|
35
|
+
ClaudeCodeInstaller.removeScript();
|
|
36
|
+
}
|
|
37
|
+
static writeScript(hookPort, hookSecret) {
|
|
38
|
+
mkdirSync(paths.hooksDir, { recursive: true });
|
|
39
|
+
const agentParam = `?agent=${AgentName.ClaudeCode}`;
|
|
40
|
+
const isWindows = process.platform === "win32";
|
|
41
|
+
const script = isWindows
|
|
42
|
+
? `@echo off\ncurl -s -X POST http://localhost:${hookPort}${ApiRoute.HookStop}${agentParam} -H "Content-Type: application/json" -H "X-CCPoke-Secret: ${hookSecret}" --data-binary @- > nul 2>&1\n`
|
|
43
|
+
: `#!/bin/bash\ncurl -s -X POST http://localhost:${hookPort}${ApiRoute.HookStop}${agentParam} \\\n -H "Content-Type: application/json" \\\n -H "X-CCPoke-Secret: ${hookSecret}" \\\n --data-binary @- > /dev/null 2>&1 || true\n`;
|
|
44
|
+
writeFileSync(paths.claudeCodeHookScript, script, { mode: isWindows ? 0o644 : 0o755 });
|
|
45
|
+
}
|
|
46
|
+
static removeScript() {
|
|
47
|
+
try {
|
|
48
|
+
unlinkSync(paths.claudeCodeHookScript);
|
|
49
|
+
}
|
|
50
|
+
catch {
|
|
51
|
+
// script file may not exist
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
static removeFromSettings() {
|
|
55
|
+
const settings = ClaudeCodeInstaller.readSettings();
|
|
56
|
+
if (!settings.hooks?.Stop)
|
|
57
|
+
return;
|
|
58
|
+
const filtered = settings.hooks.Stop.filter((entry) => !entry.hooks?.some((h) => typeof h.command === "string" && h.command.includes("ccpoke")));
|
|
59
|
+
if (filtered.length === 0) {
|
|
60
|
+
delete settings.hooks.Stop;
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
settings.hooks.Stop = filtered;
|
|
64
|
+
}
|
|
65
|
+
if (Object.keys(settings.hooks).length === 0) {
|
|
66
|
+
delete settings.hooks;
|
|
67
|
+
}
|
|
68
|
+
writeFileSync(paths.claudeSettings, JSON.stringify(settings, null, 2));
|
|
69
|
+
}
|
|
70
|
+
static readSettings() {
|
|
71
|
+
try {
|
|
72
|
+
return JSON.parse(readFileSync(paths.claudeSettings, "utf-8"));
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
const isFileNotFound = err instanceof Error && err.code === "ENOENT";
|
|
76
|
+
if (isFileNotFound)
|
|
77
|
+
return {};
|
|
78
|
+
throw err;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
//# sourceMappingURL=claude-code-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-installer.js","sourceRoot":"","sources":["../../../src/agent/claude-code/claude-code-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
export interface StopEvent {
|
|
2
|
+
session_id: string;
|
|
3
|
+
transcript_path: string;
|
|
4
|
+
cwd: string;
|
|
5
|
+
}
|
|
1
6
|
export interface TranscriptSummary {
|
|
2
7
|
lastAssistantMessage: string;
|
|
3
8
|
durationMs: number;
|
|
@@ -5,4 +10,5 @@ export interface TranscriptSummary {
|
|
|
5
10
|
outputTokens: number;
|
|
6
11
|
model: string;
|
|
7
12
|
}
|
|
13
|
+
export declare function isValidStopEvent(data: unknown): data is StopEvent;
|
|
8
14
|
export declare function parseTranscript(transcriptPath: string): TranscriptSummary;
|
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
import { readFileSync } from "node:fs";
|
|
2
|
-
import { expandHome } from "
|
|
2
|
+
import { expandHome } from "../../utils/paths.js";
|
|
3
|
+
export function isValidStopEvent(data) {
|
|
4
|
+
if (typeof data !== "object" || data === null)
|
|
5
|
+
return false;
|
|
6
|
+
const obj = data;
|
|
7
|
+
return (typeof obj.session_id === "string" &&
|
|
8
|
+
typeof obj.transcript_path === "string" &&
|
|
9
|
+
typeof obj.cwd === "string");
|
|
10
|
+
}
|
|
3
11
|
export function parseTranscript(transcriptPath) {
|
|
4
12
|
const expandedPath = expandHome(transcriptPath);
|
|
5
13
|
const raw = readFileSync(expandedPath, "utf-8");
|
|
@@ -70,4 +78,4 @@ function extractTextFromContent(parts) {
|
|
|
70
78
|
.map((p) => p.text)
|
|
71
79
|
.join("\n");
|
|
72
80
|
}
|
|
73
|
-
//# sourceMappingURL=
|
|
81
|
+
//# sourceMappingURL=claude-code-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-parser.js","sourceRoot":"","sources":["../../../src/agent/claude-code/claude-code-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { AgentProvider, AgentEventResult } from "../types.js";
|
|
2
|
+
export declare class ClaudeCodeProvider implements AgentProvider {
|
|
3
|
+
readonly name: "claude-code";
|
|
4
|
+
readonly displayName: string;
|
|
5
|
+
readonly settleDelayMs = 500;
|
|
6
|
+
detect(): boolean;
|
|
7
|
+
isHookInstalled(): boolean;
|
|
8
|
+
installHook(port: number, secret: string): void;
|
|
9
|
+
uninstallHook(): void;
|
|
10
|
+
parseEvent(raw: unknown): AgentEventResult;
|
|
11
|
+
private createFallbackResult;
|
|
12
|
+
}
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
import { existsSync } from "node:fs";
|
|
2
|
+
import { AgentName, AGENT_DISPLAY_NAMES } from "../types.js";
|
|
3
|
+
import { ClaudeCodeInstaller } from "./claude-code-installer.js";
|
|
4
|
+
import { isValidStopEvent, parseTranscript } from "./claude-code-parser.js";
|
|
5
|
+
import { collectGitChanges } from "../../utils/git-collector.js";
|
|
6
|
+
import { extractProjectName, paths } from "../../utils/paths.js";
|
|
7
|
+
import { DEFAULT_FALLBACK_DURATION_MS, TRANSCRIPT_SETTLE_DELAY_MS } from "../../utils/constants.js";
|
|
8
|
+
import { logError } from "../../utils/log.js";
|
|
9
|
+
import { t } from "../../i18n/index.js";
|
|
10
|
+
export class ClaudeCodeProvider {
|
|
11
|
+
name = AgentName.ClaudeCode;
|
|
12
|
+
displayName = AGENT_DISPLAY_NAMES[AgentName.ClaudeCode];
|
|
13
|
+
settleDelayMs = TRANSCRIPT_SETTLE_DELAY_MS;
|
|
14
|
+
detect() {
|
|
15
|
+
return existsSync(paths.claudeDir);
|
|
16
|
+
}
|
|
17
|
+
isHookInstalled() {
|
|
18
|
+
return ClaudeCodeInstaller.isInstalled();
|
|
19
|
+
}
|
|
20
|
+
installHook(port, secret) {
|
|
21
|
+
ClaudeCodeInstaller.install(port, secret);
|
|
22
|
+
}
|
|
23
|
+
uninstallHook() {
|
|
24
|
+
ClaudeCodeInstaller.uninstall();
|
|
25
|
+
}
|
|
26
|
+
parseEvent(raw) {
|
|
27
|
+
if (!isValidStopEvent(raw)) {
|
|
28
|
+
return this.createFallbackResult(raw);
|
|
29
|
+
}
|
|
30
|
+
let summary = {
|
|
31
|
+
lastAssistantMessage: "",
|
|
32
|
+
durationMs: 0,
|
|
33
|
+
inputTokens: 0,
|
|
34
|
+
outputTokens: 0,
|
|
35
|
+
model: "",
|
|
36
|
+
};
|
|
37
|
+
try {
|
|
38
|
+
summary = parseTranscript(raw.transcript_path);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
logError(t("hook.transcriptFailed"), err);
|
|
42
|
+
}
|
|
43
|
+
const gitChanges = collectGitChanges(raw.cwd);
|
|
44
|
+
let durationMs = Math.max(0, summary.durationMs);
|
|
45
|
+
if (durationMs === 0 && summary.lastAssistantMessage) {
|
|
46
|
+
durationMs = DEFAULT_FALLBACK_DURATION_MS;
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
projectName: extractProjectName(raw.cwd),
|
|
50
|
+
responseSummary: summary.lastAssistantMessage,
|
|
51
|
+
durationMs,
|
|
52
|
+
gitChanges,
|
|
53
|
+
inputTokens: summary.inputTokens,
|
|
54
|
+
outputTokens: summary.outputTokens,
|
|
55
|
+
model: summary.model,
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
createFallbackResult(raw) {
|
|
59
|
+
const obj = (typeof raw === "object" && raw !== null ? raw : {});
|
|
60
|
+
const cwd = typeof obj.cwd === "string" ? obj.cwd : process.cwd();
|
|
61
|
+
return {
|
|
62
|
+
projectName: extractProjectName(cwd),
|
|
63
|
+
responseSummary: "",
|
|
64
|
+
durationMs: 0,
|
|
65
|
+
gitChanges: collectGitChanges(cwd),
|
|
66
|
+
inputTokens: 0,
|
|
67
|
+
outputTokens: 0,
|
|
68
|
+
model: "",
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
//# sourceMappingURL=claude-code-provider.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"claude-code-provider.js","sourceRoot":"","sources":["../../../src/agent/claude-code/claude-code-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export declare class CursorInstaller {
|
|
2
|
+
static isInstalled(): boolean;
|
|
3
|
+
static install(hookPort: number, hookSecret: string): void;
|
|
4
|
+
static uninstall(): void;
|
|
5
|
+
private static writeScript;
|
|
6
|
+
private static removeScript;
|
|
7
|
+
private static removeFromHooksJson;
|
|
8
|
+
private static readConfig;
|
|
9
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { readFileSync, writeFileSync, mkdirSync, unlinkSync, existsSync } from "node:fs";
|
|
2
|
+
import { paths } from "../../utils/paths.js";
|
|
3
|
+
import { ApiRoute } from "../../utils/constants.js";
|
|
4
|
+
import { AgentName } from "../types.js";
|
|
5
|
+
function hasCcpokeHook(stopHooks) {
|
|
6
|
+
return stopHooks.some((entry) => typeof entry.command === "string" && entry.command.includes("ccpoke"));
|
|
7
|
+
}
|
|
8
|
+
export class CursorInstaller {
|
|
9
|
+
static isInstalled() {
|
|
10
|
+
try {
|
|
11
|
+
if (!existsSync(paths.cursorHooksJson))
|
|
12
|
+
return false;
|
|
13
|
+
const config = CursorInstaller.readConfig();
|
|
14
|
+
return hasCcpokeHook(config.hooks?.stop ?? []);
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
return false;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
static install(hookPort, hookSecret) {
|
|
21
|
+
mkdirSync(paths.cursorDir, { recursive: true });
|
|
22
|
+
const config = CursorInstaller.readConfig();
|
|
23
|
+
if (!config.hooks)
|
|
24
|
+
config.hooks = {};
|
|
25
|
+
const stopHooks = config.hooks.stop ?? [];
|
|
26
|
+
if (hasCcpokeHook(stopHooks))
|
|
27
|
+
return;
|
|
28
|
+
stopHooks.push({
|
|
29
|
+
command: paths.cursorHookScript,
|
|
30
|
+
timeout: 10,
|
|
31
|
+
});
|
|
32
|
+
config.hooks.stop = stopHooks;
|
|
33
|
+
if (!config.version)
|
|
34
|
+
config.version = 1;
|
|
35
|
+
writeFileSync(paths.cursorHooksJson, JSON.stringify(config, null, 2));
|
|
36
|
+
CursorInstaller.writeScript(hookPort, hookSecret);
|
|
37
|
+
}
|
|
38
|
+
static uninstall() {
|
|
39
|
+
CursorInstaller.removeFromHooksJson();
|
|
40
|
+
CursorInstaller.removeScript();
|
|
41
|
+
}
|
|
42
|
+
static writeScript(hookPort, hookSecret) {
|
|
43
|
+
mkdirSync(paths.hooksDir, { recursive: true });
|
|
44
|
+
const agentParam = `?agent=${AgentName.Cursor}`;
|
|
45
|
+
const isWindows = process.platform === "win32";
|
|
46
|
+
const script = isWindows
|
|
47
|
+
? `@echo off\ncurl -s -X POST http://localhost:${hookPort}${ApiRoute.HookStop}${agentParam} -H "Content-Type: application/json" -H "X-CCPoke-Secret: ${hookSecret}" --data-binary @- > nul 2>&1\n`
|
|
48
|
+
: `#!/bin/bash\ncurl -s -X POST http://localhost:${hookPort}${ApiRoute.HookStop}${agentParam} \\\n -H "Content-Type: application/json" \\\n -H "X-CCPoke-Secret: ${hookSecret}" \\\n --data-binary @- > /dev/null 2>&1 || true\n`;
|
|
49
|
+
writeFileSync(paths.cursorHookScript, script, { mode: isWindows ? 0o644 : 0o755 });
|
|
50
|
+
}
|
|
51
|
+
static removeScript() {
|
|
52
|
+
try {
|
|
53
|
+
unlinkSync(paths.cursorHookScript);
|
|
54
|
+
}
|
|
55
|
+
catch {
|
|
56
|
+
// script file may not exist
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
static removeFromHooksJson() {
|
|
60
|
+
if (!existsSync(paths.cursorHooksJson))
|
|
61
|
+
return;
|
|
62
|
+
const config = CursorInstaller.readConfig();
|
|
63
|
+
if (!config.hooks?.stop)
|
|
64
|
+
return;
|
|
65
|
+
const filtered = config.hooks.stop.filter((entry) => !(typeof entry.command === "string" && entry.command.includes("ccpoke")));
|
|
66
|
+
if (filtered.length === 0) {
|
|
67
|
+
delete config.hooks.stop;
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
config.hooks.stop = filtered;
|
|
71
|
+
}
|
|
72
|
+
if (Object.keys(config.hooks).length === 0) {
|
|
73
|
+
delete config.hooks;
|
|
74
|
+
}
|
|
75
|
+
writeFileSync(paths.cursorHooksJson, JSON.stringify(config, null, 2));
|
|
76
|
+
}
|
|
77
|
+
static readConfig() {
|
|
78
|
+
try {
|
|
79
|
+
return JSON.parse(readFileSync(paths.cursorHooksJson, "utf-8"));
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
const isFileNotFound = err instanceof Error && err.code === "ENOENT";
|
|
83
|
+
if (isFileNotFound)
|
|
84
|
+
return { version: 1, hooks: {} };
|
|
85
|
+
throw err;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
//# sourceMappingURL=cursor-installer.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cursor-installer.js","sourceRoot":"","sources":["../../../src/agent/cursor/cursor-installer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
export interface StopEvent {
|
|
2
|
+
conversationId: string;
|
|
3
|
+
model: string;
|
|
4
|
+
status: string;
|
|
5
|
+
transcriptPath: string;
|
|
6
|
+
cursorVersion: string;
|
|
7
|
+
cwd: string;
|
|
8
|
+
projectName: string;
|
|
9
|
+
}
|
|
10
|
+
export interface TranscriptSummary {
|
|
11
|
+
lastAssistantMessage: string;
|
|
12
|
+
durationMs: number;
|
|
13
|
+
inputTokens: number;
|
|
14
|
+
outputTokens: number;
|
|
15
|
+
model: string;
|
|
16
|
+
}
|
|
17
|
+
export declare function isValidStopEvent(data: unknown): data is Record<string, unknown>;
|
|
18
|
+
export declare function parseStopEvent(raw: Record<string, unknown>): StopEvent;
|
|
19
|
+
export declare function parseTranscript(transcriptPath: string): TranscriptSummary;
|