paperclip-plugin-telegram 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.
- package/README.md +116 -0
- package/dist/acp-bridge.d.ts +12 -0
- package/dist/acp-bridge.js +166 -0
- package/dist/acp-bridge.js.map +1 -0
- package/dist/commands.d.ts +10 -0
- package/dist/commands.js +212 -0
- package/dist/commands.js.map +1 -0
- package/dist/constants.d.ts +24 -0
- package/dist/constants.js +25 -0
- package/dist/constants.js.map +1 -0
- package/dist/formatters.d.ts +13 -0
- package/dist/formatters.js +130 -0
- package/dist/formatters.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/manifest.d.ts +3 -0
- package/dist/manifest.js +125 -0
- package/dist/manifest.js.map +1 -0
- package/dist/telegram-api.d.ts +28 -0
- package/dist/telegram-api.js +147 -0
- package/dist/telegram-api.js.map +1 -0
- package/dist/worker.d.ts +1 -0
- package/dist/worker.js +300 -0
- package/dist/worker.js.map +1 -0
- package/package.json +33 -0
package/README.md
ADDED
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# paperclip-plugin-telegram
|
|
2
|
+
|
|
3
|
+
Bidirectional Telegram integration for [Paperclip](https://github.com/paperclipai/paperclip). Push agent notifications to Telegram, receive bot commands, approve requests with inline buttons, and route forum topics to projects.
|
|
4
|
+
|
|
5
|
+
Built on the Paperclip plugin SDK and the domain event bridge ([PR #909](https://github.com/paperclipai/paperclip/pull/909)).
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Push notifications** on issue created, issue done, approval requested, agent error, run lifecycle
|
|
10
|
+
- **Bot commands**: `/status`, `/issues`, `/agents`, `/approve`, `/help`, `/connect`
|
|
11
|
+
- **Inline buttons** for approve/reject on approval notifications
|
|
12
|
+
- **Inbound routing**: reply to a notification in Telegram and it becomes an issue comment in Paperclip
|
|
13
|
+
- **Per-company chat routing** with `/connect` command
|
|
14
|
+
- **Forum topic routing**: map Telegram topics to Paperclip projects
|
|
15
|
+
- **Daily digest**: scheduled summary of agent activity
|
|
16
|
+
- **MarkdownV2 formatting** with automatic plain text fallback
|
|
17
|
+
|
|
18
|
+
## Setup
|
|
19
|
+
|
|
20
|
+
### 1. Create a Telegram bot
|
|
21
|
+
|
|
22
|
+
1. Open Telegram and chat with [@BotFather](https://t.me/BotFather)
|
|
23
|
+
2. Run `/newbot` and follow the prompts
|
|
24
|
+
3. Save the bot token
|
|
25
|
+
|
|
26
|
+
### 2. Get your chat ID
|
|
27
|
+
|
|
28
|
+
Send a message to your bot, then run:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
curl "https://api.telegram.org/bot<YOUR_TOKEN>/getUpdates"
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Find the `chat.id` field in the response. For groups, the ID is a negative number.
|
|
35
|
+
|
|
36
|
+
### 3. Install the plugin
|
|
37
|
+
|
|
38
|
+
```bash
|
|
39
|
+
# From your Paperclip directory
|
|
40
|
+
pnpm paperclipai plugin install /path/to/paperclip-plugin-telegram
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
### 4. Configure
|
|
44
|
+
|
|
45
|
+
In your Paperclip instance settings, configure:
|
|
46
|
+
|
|
47
|
+
| Setting | Required | Description |
|
|
48
|
+
|---------|----------|-------------|
|
|
49
|
+
| `telegramBotTokenRef` | Yes | Secret reference to your bot token |
|
|
50
|
+
| `defaultChatId` | Yes | Chat ID for notifications |
|
|
51
|
+
| `approvalsChatId` | No | Separate chat for approvals |
|
|
52
|
+
| `errorsChatId` | No | Separate chat for errors |
|
|
53
|
+
| `enableCommands` | No | Enable bot commands (default: true) |
|
|
54
|
+
| `enableInbound` | No | Route Telegram replies to issues (default: true) |
|
|
55
|
+
| `dailyDigestEnabled` | No | Send daily activity summary |
|
|
56
|
+
| `topicRouting` | No | Map forum topics to projects |
|
|
57
|
+
|
|
58
|
+
### 5. Add bot to group (optional)
|
|
59
|
+
|
|
60
|
+
If using a group chat:
|
|
61
|
+
1. Add the bot to your Telegram group
|
|
62
|
+
2. Disable privacy mode via BotFather (`/setprivacy` -> Disable) if you want the bot to see all messages
|
|
63
|
+
3. Run `/connect <company-name>` in the group
|
|
64
|
+
|
|
65
|
+
## How it works
|
|
66
|
+
|
|
67
|
+
### Notifications (outbound)
|
|
68
|
+
|
|
69
|
+
When Paperclip events fire (issue created, approval needed, agent error), the plugin formats them as Telegram messages with MarkdownV2 and sends to the configured chat.
|
|
70
|
+
|
|
71
|
+
Approval notifications include inline Approve/Reject buttons. Clicking a button calls the Paperclip API directly and updates the message to show the resolution.
|
|
72
|
+
|
|
73
|
+
### Commands (inbound)
|
|
74
|
+
|
|
75
|
+
The bot registers commands with Telegram's command menu. Users can interact with Paperclip directly:
|
|
76
|
+
|
|
77
|
+
- `/status` - overview of agents and tasks
|
|
78
|
+
- `/issues` - list open issues
|
|
79
|
+
- `/agents` - list agents with status
|
|
80
|
+
- `/approve <id>` - approve a pending request
|
|
81
|
+
- `/connect <company>` - link this chat to a Paperclip company
|
|
82
|
+
|
|
83
|
+
### Reply routing
|
|
84
|
+
|
|
85
|
+
When a user replies to a bot notification, the plugin looks up which Paperclip entity that notification was about and posts the reply as an issue comment. This turns Telegram threads into a natural conversation interface for Paperclip issues.
|
|
86
|
+
|
|
87
|
+
## Comparison with PR #407
|
|
88
|
+
|
|
89
|
+
| Feature | PR #407 | This plugin |
|
|
90
|
+
|---------|---------|-------------|
|
|
91
|
+
| Push notifications | Yes | Yes |
|
|
92
|
+
| Receive messages | No | Yes |
|
|
93
|
+
| Bot commands | No | /status, /issues, /agents, /approve |
|
|
94
|
+
| Inline buttons | No | Approve/reject on approvals |
|
|
95
|
+
| Reply routing | No | Replies become issue comments |
|
|
96
|
+
| Topic routing | No | Forum topic = project |
|
|
97
|
+
| Daily digest | No | Yes |
|
|
98
|
+
| Architecture | Monorepo example | Standalone npm package |
|
|
99
|
+
|
|
100
|
+
## Development
|
|
101
|
+
|
|
102
|
+
```bash
|
|
103
|
+
pnpm install
|
|
104
|
+
pnpm build
|
|
105
|
+
pnpm typecheck
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
## License
|
|
109
|
+
|
|
110
|
+
MIT
|
|
111
|
+
|
|
112
|
+
## Credits
|
|
113
|
+
|
|
114
|
+
This contribution was developed with AI assistance (Claude Code).
|
|
115
|
+
|
|
116
|
+
Inspired by [OpenClaw's Telegram integration](https://github.com/openclaw/openclaw) (grammY, bidirectional messaging, inline buttons) and adapted for the Paperclip plugin SDK.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PluginContext } from "@paperclipai/plugin-sdk";
|
|
2
|
+
type AcpOutputEvent = {
|
|
3
|
+
sessionId: string;
|
|
4
|
+
chatId: string;
|
|
5
|
+
threadId: number;
|
|
6
|
+
text: string;
|
|
7
|
+
done?: boolean;
|
|
8
|
+
};
|
|
9
|
+
export declare function handleAcpCommand(ctx: PluginContext, token: string, chatId: string, args: string, messageThreadId?: number): Promise<void>;
|
|
10
|
+
export declare function routeMessageToAcp(ctx: PluginContext, chatId: string, threadId: number, text: string): Promise<boolean>;
|
|
11
|
+
export declare function handleAcpOutput(ctx: PluginContext, token: string, event: AcpOutputEvent): Promise<void>;
|
|
12
|
+
export {};
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { sendMessage, escapeMarkdownV2, sendChatAction } from "./telegram-api.js";
|
|
2
|
+
export async function handleAcpCommand(ctx, token, chatId, args, messageThreadId) {
|
|
3
|
+
const parts = args.trim().split(/\s+/);
|
|
4
|
+
const subcommand = parts[0]?.toLowerCase() ?? "";
|
|
5
|
+
switch (subcommand) {
|
|
6
|
+
case "spawn":
|
|
7
|
+
await handleAcpSpawn(ctx, token, chatId, parts.slice(1).join(" "), messageThreadId);
|
|
8
|
+
break;
|
|
9
|
+
case "status":
|
|
10
|
+
await handleAcpStatus(ctx, token, chatId, messageThreadId);
|
|
11
|
+
break;
|
|
12
|
+
case "cancel":
|
|
13
|
+
await handleAcpCancel(ctx, token, chatId, messageThreadId);
|
|
14
|
+
break;
|
|
15
|
+
case "close":
|
|
16
|
+
await handleAcpClose(ctx, token, chatId, messageThreadId);
|
|
17
|
+
break;
|
|
18
|
+
default:
|
|
19
|
+
await sendMessage(ctx, token, chatId, [
|
|
20
|
+
escapeMarkdownV2("🔌") + " *ACP Commands*",
|
|
21
|
+
"",
|
|
22
|
+
`/acp spawn <agent\\-name> \\- ${escapeMarkdownV2("Start a coding agent session in this thread")}`,
|
|
23
|
+
`/acp status \\- ${escapeMarkdownV2("Show current ACP session status")}`,
|
|
24
|
+
`/acp cancel \\- ${escapeMarkdownV2("Cancel the running agent task")}`,
|
|
25
|
+
`/acp close \\- ${escapeMarkdownV2("End the ACP session and unbind this thread")}`,
|
|
26
|
+
].join("\n"), { parseMode: "MarkdownV2", messageThreadId });
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async function handleAcpSpawn(ctx, token, chatId, agentName, messageThreadId) {
|
|
30
|
+
if (!agentName.trim()) {
|
|
31
|
+
await sendMessage(ctx, token, chatId, "Usage: /acp spawn <agent-name>", {
|
|
32
|
+
messageThreadId,
|
|
33
|
+
});
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
if (!messageThreadId) {
|
|
37
|
+
await sendMessage(ctx, token, chatId, "ACP sessions must be started inside a topic thread.", { messageThreadId });
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
const existingBinding = await getAcpBinding(ctx, chatId, messageThreadId);
|
|
41
|
+
if (existingBinding) {
|
|
42
|
+
await sendMessage(ctx, token, chatId, `This thread already has an ACP session: \`${escapeMarkdownV2(existingBinding.sessionId)}\``, { parseMode: "MarkdownV2", messageThreadId });
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
await sendChatAction(ctx, token, chatId);
|
|
46
|
+
const sessionId = `acp_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
47
|
+
await ctx.state.set({ scopeKind: "instance", stateKey: `acp_${chatId}_${messageThreadId}` }, { sessionId, agentName: agentName.trim(), boundAt: new Date().toISOString() });
|
|
48
|
+
await ctx.events.emit("acp-message", "", {
|
|
49
|
+
type: "spawn",
|
|
50
|
+
sessionId,
|
|
51
|
+
agentName: agentName.trim(),
|
|
52
|
+
chatId,
|
|
53
|
+
threadId: messageThreadId,
|
|
54
|
+
});
|
|
55
|
+
await sendMessage(ctx, token, chatId, [
|
|
56
|
+
escapeMarkdownV2("🔌") + " *ACP Session Started*",
|
|
57
|
+
"",
|
|
58
|
+
`Agent: *${escapeMarkdownV2(agentName.trim())}*`,
|
|
59
|
+
`Session: \`${escapeMarkdownV2(sessionId)}\``,
|
|
60
|
+
"",
|
|
61
|
+
escapeMarkdownV2("Send messages in this thread to interact with the agent."),
|
|
62
|
+
].join("\n"), { parseMode: "MarkdownV2", messageThreadId });
|
|
63
|
+
ctx.logger.info("ACP session spawned", { sessionId, agentName: agentName.trim(), chatId, threadId: messageThreadId });
|
|
64
|
+
}
|
|
65
|
+
async function handleAcpStatus(ctx, token, chatId, messageThreadId) {
|
|
66
|
+
if (!messageThreadId) {
|
|
67
|
+
await sendMessage(ctx, token, chatId, "Run /acp status inside a thread with an active session.", {
|
|
68
|
+
messageThreadId,
|
|
69
|
+
});
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
const binding = await getAcpBinding(ctx, chatId, messageThreadId);
|
|
73
|
+
if (!binding) {
|
|
74
|
+
await sendMessage(ctx, token, chatId, "No ACP session bound to this thread.", {
|
|
75
|
+
messageThreadId,
|
|
76
|
+
});
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
await sendMessage(ctx, token, chatId, [
|
|
80
|
+
escapeMarkdownV2("🔌") + " *ACP Session*",
|
|
81
|
+
"",
|
|
82
|
+
`Agent: *${escapeMarkdownV2(binding.agentName)}*`,
|
|
83
|
+
`Session: \`${escapeMarkdownV2(binding.sessionId)}\``,
|
|
84
|
+
`Started: ${escapeMarkdownV2(binding.boundAt)}`,
|
|
85
|
+
].join("\n"), { parseMode: "MarkdownV2", messageThreadId });
|
|
86
|
+
}
|
|
87
|
+
async function handleAcpCancel(ctx, token, chatId, messageThreadId) {
|
|
88
|
+
if (!messageThreadId) {
|
|
89
|
+
await sendMessage(ctx, token, chatId, "Run /acp cancel inside a thread with an active session.", {
|
|
90
|
+
messageThreadId,
|
|
91
|
+
});
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
const binding = await getAcpBinding(ctx, chatId, messageThreadId);
|
|
95
|
+
if (!binding) {
|
|
96
|
+
await sendMessage(ctx, token, chatId, "No ACP session bound to this thread.", {
|
|
97
|
+
messageThreadId,
|
|
98
|
+
});
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
await ctx.events.emit("acp-message", "", {
|
|
102
|
+
type: "cancel",
|
|
103
|
+
sessionId: binding.sessionId,
|
|
104
|
+
chatId,
|
|
105
|
+
threadId: messageThreadId,
|
|
106
|
+
});
|
|
107
|
+
await sendMessage(ctx, token, chatId, `${escapeMarkdownV2("⏹")} Cancellation requested for session \`${escapeMarkdownV2(binding.sessionId)}\``, { parseMode: "MarkdownV2", messageThreadId });
|
|
108
|
+
ctx.logger.info("ACP cancel requested", { sessionId: binding.sessionId, chatId, threadId: messageThreadId });
|
|
109
|
+
}
|
|
110
|
+
async function handleAcpClose(ctx, token, chatId, messageThreadId) {
|
|
111
|
+
if (!messageThreadId) {
|
|
112
|
+
await sendMessage(ctx, token, chatId, "Run /acp close inside a thread with an active session.", {
|
|
113
|
+
messageThreadId,
|
|
114
|
+
});
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
const binding = await getAcpBinding(ctx, chatId, messageThreadId);
|
|
118
|
+
if (!binding) {
|
|
119
|
+
await sendMessage(ctx, token, chatId, "No ACP session bound to this thread.", {
|
|
120
|
+
messageThreadId,
|
|
121
|
+
});
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
await ctx.events.emit("acp-message", "", {
|
|
125
|
+
type: "close",
|
|
126
|
+
sessionId: binding.sessionId,
|
|
127
|
+
chatId,
|
|
128
|
+
threadId: messageThreadId,
|
|
129
|
+
});
|
|
130
|
+
await ctx.state.set({ scopeKind: "instance", stateKey: `acp_${chatId}_${messageThreadId}` }, null);
|
|
131
|
+
await sendMessage(ctx, token, chatId, `${escapeMarkdownV2("🔌")} ACP session \`${escapeMarkdownV2(binding.sessionId)}\` closed\\.`, { parseMode: "MarkdownV2", messageThreadId });
|
|
132
|
+
ctx.logger.info("ACP session closed", { sessionId: binding.sessionId, chatId, threadId: messageThreadId });
|
|
133
|
+
}
|
|
134
|
+
export async function routeMessageToAcp(ctx, chatId, threadId, text) {
|
|
135
|
+
const binding = await getAcpBinding(ctx, chatId, threadId);
|
|
136
|
+
if (!binding)
|
|
137
|
+
return false;
|
|
138
|
+
await ctx.events.emit("acp-message", "", {
|
|
139
|
+
type: "message",
|
|
140
|
+
sessionId: binding.sessionId,
|
|
141
|
+
chatId,
|
|
142
|
+
threadId,
|
|
143
|
+
text,
|
|
144
|
+
});
|
|
145
|
+
ctx.logger.info("Routed message to ACP session", { sessionId: binding.sessionId, chatId, threadId });
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
export async function handleAcpOutput(ctx, token, event) {
|
|
149
|
+
const { chatId, threadId, text, done } = event;
|
|
150
|
+
const prefix = done
|
|
151
|
+
? escapeMarkdownV2("✅")
|
|
152
|
+
: escapeMarkdownV2("🤖");
|
|
153
|
+
const formatted = `${prefix} ${escapeMarkdownV2(text)}`;
|
|
154
|
+
await sendMessage(ctx, token, chatId, formatted, {
|
|
155
|
+
parseMode: "MarkdownV2",
|
|
156
|
+
messageThreadId: threadId,
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
async function getAcpBinding(ctx, chatId, threadId) {
|
|
160
|
+
const binding = await ctx.state.get({
|
|
161
|
+
scopeKind: "instance",
|
|
162
|
+
stateKey: `acp_${chatId}_${threadId}`,
|
|
163
|
+
});
|
|
164
|
+
return binding;
|
|
165
|
+
}
|
|
166
|
+
//# sourceMappingURL=acp-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"acp-bridge.js","sourceRoot":"","sources":["../src/acp-bridge.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PluginContext } from "@paperclipai/plugin-sdk";
|
|
2
|
+
type BotCommand = {
|
|
3
|
+
command: string;
|
|
4
|
+
description: string;
|
|
5
|
+
};
|
|
6
|
+
export declare const BOT_COMMANDS: BotCommand[];
|
|
7
|
+
export declare function handleCommand(ctx: PluginContext, token: string, chatId: string, command: string, args: string, messageThreadId?: number, baseUrl?: string): Promise<void>;
|
|
8
|
+
export declare function handleConnectTopic(ctx: PluginContext, token: string, chatId: string, args: string, messageThreadId?: number): Promise<void>;
|
|
9
|
+
export declare function getTopicForProject(ctx: PluginContext, chatId: string, projectName?: string): Promise<number | undefined>;
|
|
10
|
+
export {};
|
package/dist/commands.js
ADDED
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
import { sendMessage, escapeMarkdownV2, sendChatAction } from "./telegram-api.js";
|
|
2
|
+
import { METRIC_NAMES } from "./constants.js";
|
|
3
|
+
import { handleAcpCommand } from "./acp-bridge.js";
|
|
4
|
+
export const BOT_COMMANDS = [
|
|
5
|
+
{ command: "status", description: "Company health: active agents, open issues" },
|
|
6
|
+
{ command: "issues", description: "List open issues (optionally by project)" },
|
|
7
|
+
{ command: "agents", description: "List agents with current status" },
|
|
8
|
+
{ command: "approve", description: "Approve a pending request by ID" },
|
|
9
|
+
{ command: "help", description: "Show available commands" },
|
|
10
|
+
{ command: "acp", description: "Manage ACP coding agent sessions (spawn, status, cancel, close)" },
|
|
11
|
+
];
|
|
12
|
+
export async function handleCommand(ctx, token, chatId, command, args, messageThreadId, baseUrl) {
|
|
13
|
+
await ctx.metrics.write(METRIC_NAMES.commandsHandled, 1);
|
|
14
|
+
switch (command) {
|
|
15
|
+
case "status":
|
|
16
|
+
await handleStatus(ctx, token, chatId, messageThreadId);
|
|
17
|
+
break;
|
|
18
|
+
case "issues":
|
|
19
|
+
await handleIssues(ctx, token, chatId, args, messageThreadId);
|
|
20
|
+
break;
|
|
21
|
+
case "agents":
|
|
22
|
+
await handleAgents(ctx, token, chatId, messageThreadId);
|
|
23
|
+
break;
|
|
24
|
+
case "approve":
|
|
25
|
+
await handleApprove(ctx, token, chatId, args, messageThreadId, baseUrl);
|
|
26
|
+
break;
|
|
27
|
+
case "help":
|
|
28
|
+
await handleHelp(ctx, token, chatId, messageThreadId);
|
|
29
|
+
break;
|
|
30
|
+
case "connect":
|
|
31
|
+
await handleConnect(ctx, token, chatId, args, messageThreadId);
|
|
32
|
+
break;
|
|
33
|
+
case "connect-topic":
|
|
34
|
+
await handleConnectTopic(ctx, token, chatId, args, messageThreadId);
|
|
35
|
+
break;
|
|
36
|
+
case "acp":
|
|
37
|
+
await handleAcpCommand(ctx, token, chatId, args, messageThreadId);
|
|
38
|
+
break;
|
|
39
|
+
default:
|
|
40
|
+
await sendMessage(ctx, token, chatId, `Unknown command: /${command}. Try /help`, {
|
|
41
|
+
messageThreadId,
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
async function handleStatus(ctx, token, chatId, messageThreadId) {
|
|
46
|
+
await sendChatAction(ctx, token, chatId);
|
|
47
|
+
try {
|
|
48
|
+
const companyId = await resolveCompanyId(ctx, chatId);
|
|
49
|
+
const agents = await ctx.agents.list({ companyId });
|
|
50
|
+
const activeAgents = agents.filter((a) => a.status === "active");
|
|
51
|
+
const issues = await ctx.issues.list({ companyId, limit: 10 });
|
|
52
|
+
const doneIssues = issues.filter((i) => i.status === "done");
|
|
53
|
+
const lines = [
|
|
54
|
+
escapeMarkdownV2("📊") + " *Paperclip Status*",
|
|
55
|
+
"",
|
|
56
|
+
`${escapeMarkdownV2("🤖")} Active agents: *${activeAgents.length}*/${escapeMarkdownV2(String(agents.length))}`,
|
|
57
|
+
`${escapeMarkdownV2("📋")} Recent issues: *${escapeMarkdownV2(String(issues.length))}* \\(${escapeMarkdownV2(String(doneIssues.length))} done\\)`,
|
|
58
|
+
];
|
|
59
|
+
await sendMessage(ctx, token, chatId, lines.join("\n"), {
|
|
60
|
+
parseMode: "MarkdownV2",
|
|
61
|
+
messageThreadId,
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
await sendMessage(ctx, token, chatId, escapeMarkdownV2("📊") + " *Paperclip Status*\n\n" + escapeMarkdownV2("Could not fetch status. Make sure this chat is linked to a company with /connect."), {
|
|
66
|
+
parseMode: "MarkdownV2",
|
|
67
|
+
messageThreadId,
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
async function handleIssues(ctx, token, chatId, projectFilter, messageThreadId) {
|
|
72
|
+
await sendChatAction(ctx, token, chatId);
|
|
73
|
+
try {
|
|
74
|
+
const companyId = await resolveCompanyId(ctx, chatId);
|
|
75
|
+
const issues = await ctx.issues.list({ companyId, limit: 10 });
|
|
76
|
+
const filtered = projectFilter
|
|
77
|
+
? issues.filter((i) => {
|
|
78
|
+
const projName = i.project?.name ?? "";
|
|
79
|
+
return projName.toLowerCase().includes(projectFilter.toLowerCase());
|
|
80
|
+
})
|
|
81
|
+
: issues;
|
|
82
|
+
if (filtered.length === 0) {
|
|
83
|
+
const filter = projectFilter ? ` for project "${projectFilter}"` : "";
|
|
84
|
+
await sendMessage(ctx, token, chatId, `No issues found${filter}.`, { messageThreadId });
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
const statusEmoji = { done: "✅", todo: "📋", in_progress: "🔄", backlog: "📥" };
|
|
88
|
+
const lines = [escapeMarkdownV2("📋") + " *Open Issues*", ""];
|
|
89
|
+
for (const issue of filtered) {
|
|
90
|
+
const emoji = statusEmoji[issue.status] ?? "📋";
|
|
91
|
+
const id = issue.identifier ?? issue.id;
|
|
92
|
+
lines.push(`${escapeMarkdownV2(emoji)} ${escapeMarkdownV2(id)} \\- ${escapeMarkdownV2(issue.title)}`);
|
|
93
|
+
}
|
|
94
|
+
await sendMessage(ctx, token, chatId, lines.join("\n"), {
|
|
95
|
+
parseMode: "MarkdownV2",
|
|
96
|
+
messageThreadId,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
const filter = projectFilter ? ` for project "${projectFilter}"` : "";
|
|
101
|
+
await sendMessage(ctx, token, chatId, `Could not fetch issues${filter}. Make sure this chat is linked with /connect.`, { messageThreadId });
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
async function handleAgents(ctx, token, chatId, messageThreadId) {
|
|
105
|
+
await sendChatAction(ctx, token, chatId);
|
|
106
|
+
try {
|
|
107
|
+
const companyId = await resolveCompanyId(ctx, chatId);
|
|
108
|
+
const agents = await ctx.agents.list({ companyId });
|
|
109
|
+
if (agents.length === 0) {
|
|
110
|
+
await sendMessage(ctx, token, chatId, "No agents found.", { messageThreadId });
|
|
111
|
+
return;
|
|
112
|
+
}
|
|
113
|
+
const statusEmoji = { active: "🟢", error: "🔴", paused: "🟡", idle: "⚪", running: "🔵" };
|
|
114
|
+
const lines = [escapeMarkdownV2("🤖") + " *Agents*", ""];
|
|
115
|
+
for (const agent of agents) {
|
|
116
|
+
const emoji = statusEmoji[agent.status] ?? "⚪";
|
|
117
|
+
lines.push(`${escapeMarkdownV2(emoji)} *${escapeMarkdownV2(agent.name)}* \\- ${escapeMarkdownV2(agent.status)}`);
|
|
118
|
+
}
|
|
119
|
+
await sendMessage(ctx, token, chatId, lines.join("\n"), {
|
|
120
|
+
parseMode: "MarkdownV2",
|
|
121
|
+
messageThreadId,
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
catch {
|
|
125
|
+
await sendMessage(ctx, token, chatId, "Could not fetch agents. Make sure this chat is linked with /connect.", { messageThreadId });
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async function handleApprove(ctx, token, chatId, approvalId, messageThreadId, baseUrl = "http://localhost:3100") {
|
|
129
|
+
if (!approvalId.trim()) {
|
|
130
|
+
await sendMessage(ctx, token, chatId, "Usage: /approve <approval-id>", {
|
|
131
|
+
messageThreadId,
|
|
132
|
+
});
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
await ctx.http.fetch(`${baseUrl}/api/approvals/${approvalId.trim()}/approve`, {
|
|
137
|
+
method: "POST",
|
|
138
|
+
headers: { "Content-Type": "application/json" },
|
|
139
|
+
body: JSON.stringify({ decidedByUserId: `telegram:${chatId}` }),
|
|
140
|
+
});
|
|
141
|
+
await sendMessage(ctx, token, chatId, `${escapeMarkdownV2("✅")} *Approved*: \`${escapeMarkdownV2(approvalId.trim())}\``, { parseMode: "MarkdownV2", messageThreadId });
|
|
142
|
+
}
|
|
143
|
+
catch (err) {
|
|
144
|
+
await sendMessage(ctx, token, chatId, `Failed to approve ${approvalId}: ${err instanceof Error ? err.message : String(err)}`, { messageThreadId });
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
async function handleHelp(ctx, token, chatId, messageThreadId) {
|
|
148
|
+
const lines = [
|
|
149
|
+
escapeMarkdownV2("📎") + " *Paperclip Bot Commands*",
|
|
150
|
+
"",
|
|
151
|
+
...BOT_COMMANDS.map((cmd) => `/${escapeMarkdownV2(cmd.command)} \\- ${escapeMarkdownV2(cmd.description)}`),
|
|
152
|
+
"",
|
|
153
|
+
`/${escapeMarkdownV2("connect")} \\- ${escapeMarkdownV2("Link this chat to a Paperclip company")}`,
|
|
154
|
+
`/${escapeMarkdownV2("connect-topic")} \\- ${escapeMarkdownV2("Map a project to a forum topic")}`,
|
|
155
|
+
];
|
|
156
|
+
await sendMessage(ctx, token, chatId, lines.join("\n"), {
|
|
157
|
+
parseMode: "MarkdownV2",
|
|
158
|
+
messageThreadId,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
async function handleConnect(ctx, token, chatId, companyName, messageThreadId) {
|
|
162
|
+
if (!companyName.trim()) {
|
|
163
|
+
await sendMessage(ctx, token, chatId, "Usage: /connect <company-name>", {
|
|
164
|
+
messageThreadId,
|
|
165
|
+
});
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
await ctx.state.set({ scopeKind: "instance", stateKey: `chat_${chatId}` }, { companyName: companyName.trim(), linkedAt: new Date().toISOString() });
|
|
169
|
+
await sendMessage(ctx, token, chatId, `${escapeMarkdownV2("🔗")} ${escapeMarkdownV2("Linked this chat to company:")} *${escapeMarkdownV2(companyName.trim())}*`, { parseMode: "MarkdownV2", messageThreadId });
|
|
170
|
+
ctx.logger.info("Chat linked to company", { chatId, companyName: companyName.trim() });
|
|
171
|
+
}
|
|
172
|
+
export async function handleConnectTopic(ctx, token, chatId, args, messageThreadId) {
|
|
173
|
+
const parts = args.trim().split(/\s+/);
|
|
174
|
+
if (parts.length < 2) {
|
|
175
|
+
await sendMessage(ctx, token, chatId, "Usage: /connect\\-topic <project\\-name> <topic\\-id>", {
|
|
176
|
+
parseMode: "MarkdownV2",
|
|
177
|
+
messageThreadId,
|
|
178
|
+
});
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
const topicId = parts.pop();
|
|
182
|
+
const projectName = parts.join(" ");
|
|
183
|
+
const existing = (await ctx.state.get({
|
|
184
|
+
scopeKind: "instance",
|
|
185
|
+
stateKey: `topic-map-${chatId}`,
|
|
186
|
+
}));
|
|
187
|
+
const topicMap = existing ?? {};
|
|
188
|
+
topicMap[projectName] = topicId;
|
|
189
|
+
await ctx.state.set({ scopeKind: "instance", stateKey: `topic-map-${chatId}` }, topicMap);
|
|
190
|
+
await sendMessage(ctx, token, chatId, `${escapeMarkdownV2("🔗")} ${escapeMarkdownV2(`Mapped project "${projectName}" to topic ${topicId}`)}`, { parseMode: "MarkdownV2", messageThreadId });
|
|
191
|
+
ctx.logger.info("Topic mapped", { chatId, projectName, topicId });
|
|
192
|
+
}
|
|
193
|
+
export async function getTopicForProject(ctx, chatId, projectName) {
|
|
194
|
+
if (!projectName)
|
|
195
|
+
return undefined;
|
|
196
|
+
const topicMap = (await ctx.state.get({
|
|
197
|
+
scopeKind: "instance",
|
|
198
|
+
stateKey: `topic-map-${chatId}`,
|
|
199
|
+
}));
|
|
200
|
+
if (!topicMap)
|
|
201
|
+
return undefined;
|
|
202
|
+
const topicId = topicMap[projectName];
|
|
203
|
+
return topicId ? Number(topicId) : undefined;
|
|
204
|
+
}
|
|
205
|
+
async function resolveCompanyId(ctx, chatId) {
|
|
206
|
+
const mapping = await ctx.state.get({
|
|
207
|
+
scopeKind: "instance",
|
|
208
|
+
stateKey: `chat_${chatId}`,
|
|
209
|
+
});
|
|
210
|
+
return mapping?.companyName ?? chatId;
|
|
211
|
+
}
|
|
212
|
+
//# sourceMappingURL=commands.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"commands.js","sourceRoot":"","sources":["../src/commands.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export declare const PLUGIN_ID = "paperclip-plugin-telegram";
|
|
2
|
+
export declare const PLUGIN_VERSION = "0.1.0";
|
|
3
|
+
export declare const DEFAULT_CONFIG: {
|
|
4
|
+
readonly telegramBotTokenRef: "";
|
|
5
|
+
readonly defaultChatId: "";
|
|
6
|
+
readonly approvalsChatId: "";
|
|
7
|
+
readonly errorsChatId: "";
|
|
8
|
+
readonly paperclipBaseUrl: "http://localhost:3100";
|
|
9
|
+
readonly notifyOnIssueCreated: true;
|
|
10
|
+
readonly notifyOnIssueDone: true;
|
|
11
|
+
readonly notifyOnApprovalCreated: true;
|
|
12
|
+
readonly notifyOnAgentError: true;
|
|
13
|
+
readonly enableCommands: true;
|
|
14
|
+
readonly enableInbound: true;
|
|
15
|
+
readonly dailyDigestEnabled: false;
|
|
16
|
+
readonly dailyDigestTime: "09:00";
|
|
17
|
+
readonly topicRouting: false;
|
|
18
|
+
};
|
|
19
|
+
export declare const METRIC_NAMES: {
|
|
20
|
+
readonly sent: "telegram_notifications_sent";
|
|
21
|
+
readonly failed: "telegram_notification_failures";
|
|
22
|
+
readonly commandsHandled: "telegram_commands_handled";
|
|
23
|
+
readonly inboundRouted: "telegram_inbound_routed";
|
|
24
|
+
};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const PLUGIN_ID = "paperclip-plugin-telegram";
|
|
2
|
+
export const PLUGIN_VERSION = "0.1.0";
|
|
3
|
+
export const DEFAULT_CONFIG = {
|
|
4
|
+
telegramBotTokenRef: "",
|
|
5
|
+
defaultChatId: "",
|
|
6
|
+
approvalsChatId: "",
|
|
7
|
+
errorsChatId: "",
|
|
8
|
+
paperclipBaseUrl: "http://localhost:3100",
|
|
9
|
+
notifyOnIssueCreated: true,
|
|
10
|
+
notifyOnIssueDone: true,
|
|
11
|
+
notifyOnApprovalCreated: true,
|
|
12
|
+
notifyOnAgentError: true,
|
|
13
|
+
enableCommands: true,
|
|
14
|
+
enableInbound: true,
|
|
15
|
+
dailyDigestEnabled: false,
|
|
16
|
+
dailyDigestTime: "09:00",
|
|
17
|
+
topicRouting: false,
|
|
18
|
+
};
|
|
19
|
+
export const METRIC_NAMES = {
|
|
20
|
+
sent: "telegram_notifications_sent",
|
|
21
|
+
failed: "telegram_notification_failures",
|
|
22
|
+
commandsHandled: "telegram_commands_handled",
|
|
23
|
+
inboundRouted: "telegram_inbound_routed",
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../src/constants.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,SAAS,GAAG,2BAA2B,CAAC;AACrD,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC,MAAM,CAAC,MAAM,cAAc,GAAG;IAC5B,mBAAmB,EAAE,EAAE;IACvB,aAAa,EAAE,EAAE;IACjB,eAAe,EAAE,EAAE;IACnB,YAAY,EAAE,EAAE;IAChB,gBAAgB,EAAE,uBAAuB;IACzC,oBAAoB,EAAE,IAAI;IAC1B,iBAAiB,EAAE,IAAI;IACvB,uBAAuB,EAAE,IAAI;IAC7B,kBAAkB,EAAE,IAAI;IACxB,cAAc,EAAE,IAAI;IACpB,aAAa,EAAE,IAAI;IACnB,kBAAkB,EAAE,KAAK;IACzB,eAAe,EAAE,OAAO;IACxB,YAAY,EAAE,KAAK;CACX,CAAC;AAEX,MAAM,CAAC,MAAM,YAAY,GAAG;IAC1B,IAAI,EAAE,6BAA6B;IACnC,MAAM,EAAE,gCAAgC;IACxC,eAAe,EAAE,2BAA2B;IAC5C,aAAa,EAAE,yBAAyB;CAChC,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { PluginEvent } from "@paperclipai/plugin-sdk";
|
|
2
|
+
import type { SendMessageOptions } from "./telegram-api.js";
|
|
3
|
+
type FormattedMessage = {
|
|
4
|
+
text: string;
|
|
5
|
+
options: SendMessageOptions;
|
|
6
|
+
};
|
|
7
|
+
export declare function formatIssueCreated(event: PluginEvent): FormattedMessage;
|
|
8
|
+
export declare function formatIssueDone(event: PluginEvent): FormattedMessage;
|
|
9
|
+
export declare function formatApprovalCreated(event: PluginEvent): FormattedMessage;
|
|
10
|
+
export declare function formatAgentError(event: PluginEvent): FormattedMessage;
|
|
11
|
+
export declare function formatAgentRunStarted(event: PluginEvent): FormattedMessage;
|
|
12
|
+
export declare function formatAgentRunFinished(event: PluginEvent): FormattedMessage;
|
|
13
|
+
export {};
|