golembot 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +191 -0
  3. package/dist/channel.d.ts +22 -0
  4. package/dist/channel.d.ts.map +1 -0
  5. package/dist/channel.js +14 -0
  6. package/dist/channel.js.map +1 -0
  7. package/dist/channels/dingtalk.d.ts +12 -0
  8. package/dist/channels/dingtalk.d.ts.map +1 -0
  9. package/dist/channels/dingtalk.js +66 -0
  10. package/dist/channels/dingtalk.js.map +1 -0
  11. package/dist/channels/feishu.d.ts +13 -0
  12. package/dist/channels/feishu.d.ts.map +1 -0
  13. package/dist/channels/feishu.js +73 -0
  14. package/dist/channels/feishu.js.map +1 -0
  15. package/dist/channels/wecom.d.ts +15 -0
  16. package/dist/channels/wecom.d.ts.map +1 -0
  17. package/dist/channels/wecom.js +152 -0
  18. package/dist/channels/wecom.js.map +1 -0
  19. package/dist/cli.d.ts +3 -0
  20. package/dist/cli.d.ts.map +1 -0
  21. package/dist/cli.js +303 -0
  22. package/dist/cli.js.map +1 -0
  23. package/dist/engine.d.ts +65 -0
  24. package/dist/engine.d.ts.map +1 -0
  25. package/dist/engine.js +747 -0
  26. package/dist/engine.js.map +1 -0
  27. package/dist/gateway.d.ts +11 -0
  28. package/dist/gateway.d.ts.map +1 -0
  29. package/dist/gateway.js +118 -0
  30. package/dist/gateway.js.map +1 -0
  31. package/dist/index.d.ts +26 -0
  32. package/dist/index.d.ts.map +1 -0
  33. package/dist/index.js +114 -0
  34. package/dist/index.js.map +1 -0
  35. package/dist/onboard.d.ts +7 -0
  36. package/dist/onboard.d.ts.map +1 -0
  37. package/dist/onboard.js +285 -0
  38. package/dist/onboard.js.map +1 -0
  39. package/dist/server.d.ts +10 -0
  40. package/dist/server.d.ts.map +1 -0
  41. package/dist/server.js +112 -0
  42. package/dist/server.js.map +1 -0
  43. package/dist/session.d.ts +4 -0
  44. package/dist/session.d.ts.map +1 -0
  45. package/dist/session.js +45 -0
  46. package/dist/session.js.map +1 -0
  47. package/dist/workspace.d.ts +52 -0
  48. package/dist/workspace.d.ts.map +1 -0
  49. package/dist/workspace.js +168 -0
  50. package/dist/workspace.js.map +1 -0
  51. package/package.json +91 -0
  52. package/skills/general/SKILL.md +63 -0
  53. package/skills/im-adapter/SKILL.md +48 -0
  54. package/templates/code-reviewer/README.md +14 -0
  55. package/templates/code-reviewer/golem.yaml +6 -0
  56. package/templates/code-reviewer/skills/code-review/SKILL.md +39 -0
  57. package/templates/customer-support/README.md +15 -0
  58. package/templates/customer-support/faq.md +10 -0
  59. package/templates/customer-support/golem.yaml +11 -0
  60. package/templates/customer-support/skills/faq-support/SKILL.md +34 -0
  61. package/templates/data-analyst/README.md +15 -0
  62. package/templates/data-analyst/golem.yaml +6 -0
  63. package/templates/data-analyst/skills/data-analysis/SKILL.md +45 -0
  64. package/templates/data-analyst/skills/data-analysis/calc.py +62 -0
  65. package/templates/meeting-notes/README.md +14 -0
  66. package/templates/meeting-notes/golem.yaml +6 -0
  67. package/templates/meeting-notes/skills/meeting/SKILL.md +51 -0
  68. package/templates/ops-assistant/README.md +16 -0
  69. package/templates/ops-assistant/golem.yaml +11 -0
  70. package/templates/ops-assistant/skills/ops/SKILL.md +29 -0
  71. package/templates/research/README.md +14 -0
  72. package/templates/research/golem.yaml +6 -0
  73. package/templates/research/skills/research/SKILL.md +56 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 GolemBot Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,191 @@
1
+ # GolemBot — Local-First AI Assistant Platform
2
+
3
+ > **Coding Agent = the soul, GolemBot = the body of clay.**
4
+ >
5
+ > Use the Coding Agents you already have (Cursor / Claude Code / OpenCode) as the brain — so they can do more than just chat, they can actually get things done.
6
+
7
+ GolemBot is a TypeScript library + CLI that wraps Coding Agent CLIs into a unified AI assistant engine. One command spins up an intelligent assistant connected to Feishu, DingTalk, or WeCom — running locally, fully transparent, and engine-swappable.
8
+
9
+ ## Features
10
+
11
+ - **Three Engines** — Cursor / Claude Code / OpenCode, switch with a single config line
12
+ - **Built-in IM Channels** — Native adapters for Feishu, DingTalk, and WeCom, no code required
13
+ - **Library First** — `createAssistant()` API embeds into any Node.js project
14
+ - **Directory = Assistant** — `ls` the directory to see what the assistant knows, what it can do, and what it has done
15
+ - **Skill = Capability** — Drop Markdown + scripts into the `skills/` directory, and the assistant gains new abilities automatically
16
+ - **Multi-User Isolation** — Routes by sessionKey, each user gets an independent session
17
+ - **HTTP Service** — Built-in SSE streaming API with Bearer token auth
18
+ - **Docker Deployment** — One-click deploy to the cloud
19
+
20
+ ## Quick Start
21
+
22
+ ```bash
23
+ # Install
24
+ npm install -g golembot
25
+
26
+ # Guided setup (recommended)
27
+ mkdir my-assistant && cd my-assistant
28
+ golembot onboard
29
+
30
+ # Or initialize manually
31
+ golembot init
32
+
33
+ # Start the gateway (IM channels + HTTP service)
34
+ golembot gateway
35
+ ```
36
+
37
+ Try it in 30 seconds:
38
+
39
+ ```bash
40
+ mkdir my-bot && cd my-bot
41
+ golembot init -e claude-code -n my-bot
42
+ golembot run
43
+ # > Write a Python script to calculate file sizes in the current directory
44
+ ```
45
+
46
+ ## Architecture
47
+
48
+ ```
49
+ Feishu / DingTalk / WeCom / HTTP API
50
+
51
+
52
+ ┌─────────────────────────┐
53
+ │ Gateway Service │
54
+ │ (Channel adapters + │
55
+ │ HTTP service) │
56
+ └────────────┬────────────┘
57
+
58
+ createAssistant()
59
+
60
+ ┌───────┼───────┐
61
+ ▼ ▼ ▼
62
+ Cursor Claude OpenCode
63
+ Code
64
+ ```
65
+
66
+ Core design: The Gateway is a long-running service that reuses the `createAssistant()` library API internally, with an IM channel adapter layer on top.
67
+
68
+ ## Engine Comparison
69
+
70
+ | | Cursor | Claude Code | OpenCode |
71
+ |---|---|---|---|
72
+ | Spawn Method | child_process.spawn | child_process.spawn | child_process.spawn |
73
+ | Skill Injection | `.cursor/skills/` | `.claude/skills/` + CLAUDE.md | `.opencode/skills/` + opencode.json |
74
+ | Session Resume | `--resume` | `--resume` | `--session` |
75
+ | API Key | CURSOR_API_KEY | ANTHROPIC_API_KEY | Depends on Provider |
76
+
77
+ The exposed `StreamEvent` interface is identical across engines — switching engines requires zero changes to your application code.
78
+
79
+ ## Usage
80
+
81
+ ### Option 1: CLI (fastest way to get started)
82
+
83
+ ```bash
84
+ golembot init # Initialize an assistant
85
+ golembot run # REPL conversation
86
+ golembot gateway # Start IM + HTTP service
87
+ golembot onboard # Guided setup
88
+ ```
89
+
90
+ ### Option 2: Library Import
91
+
92
+ ```typescript
93
+ import { createAssistant } from 'golembot';
94
+
95
+ const assistant = createAssistant({ dir: './my-agent' });
96
+
97
+ for await (const event of assistant.chat('Analyze the competitor data')) {
98
+ if (event.type === 'text') process.stdout.write(event.content);
99
+ }
100
+ ```
101
+
102
+ ### Option 3: Embed Anywhere
103
+
104
+ ```typescript
105
+ import { createAssistant } from 'golembot';
106
+ const bot = createAssistant({ dir: './slack-bot' });
107
+
108
+ slackApp.message(async ({ message, say }) => {
109
+ let reply = '';
110
+ for await (const event of bot.chat(message.text, {
111
+ sessionKey: `slack:${message.user}`,
112
+ })) {
113
+ if (event.type === 'text') reply += event.content;
114
+ }
115
+ await say(reply);
116
+ });
117
+ ```
118
+
119
+ ## Configuration
120
+
121
+ `golem.yaml` — the single config file for an assistant:
122
+
123
+ ```yaml
124
+ name: my-assistant
125
+ engine: claude-code
126
+ model: openrouter/anthropic/claude-sonnet-4
127
+
128
+ channels:
129
+ feishu:
130
+ appId: ${FEISHU_APP_ID}
131
+ appSecret: ${FEISHU_APP_SECRET}
132
+ dingtalk:
133
+ clientId: ${DINGTALK_CLIENT_ID}
134
+ clientSecret: ${DINGTALK_CLIENT_SECRET}
135
+
136
+ gateway:
137
+ port: 3000
138
+ token: ${GOLEM_TOKEN}
139
+ ```
140
+
141
+ Sensitive fields support `${ENV_VAR}` references to environment variables.
142
+
143
+ ## Skill System
144
+
145
+ A Skill is the unit of assistant capability — a directory containing `SKILL.md` (knowledge and instructions) and optional supporting files (scripts, templates, etc.).
146
+
147
+ ```
148
+ skills/
149
+ ├── general/ # General assistant (built-in)
150
+ │ └── SKILL.md
151
+ ├── im-adapter/ # IM reply conventions (built-in)
152
+ │ └── SKILL.md
153
+ └── my-custom-skill/ # Your own Skill
154
+ ├── SKILL.md
155
+ └── analyze.py
156
+ ```
157
+
158
+ Want to add a capability? Drop a folder into `skills/`. Want to remove one? Delete the folder. `ls skills/` is the complete list of what the assistant can do.
159
+
160
+ ## Docker Deployment
161
+
162
+ ```bash
163
+ # In the assistant directory
164
+ docker compose up -d
165
+ ```
166
+
167
+ Or use a Dockerfile:
168
+
169
+ ```dockerfile
170
+ FROM node:22-slim
171
+ RUN npm install -g golembot
172
+ WORKDIR /assistant
173
+ COPY . .
174
+ EXPOSE 3000
175
+ CMD ["golembot", "gateway"]
176
+ ```
177
+
178
+ ## Development
179
+
180
+ ```bash
181
+ git clone https://github.com/0xranx/golembot.git
182
+ cd golembot
183
+ pnpm install
184
+ pnpm run build
185
+ pnpm run test # Unit tests
186
+ pnpm run e2e:opencode # End-to-end tests (requires API Key)
187
+ ```
188
+
189
+ ## License
190
+
191
+ [MIT](LICENSE)
@@ -0,0 +1,22 @@
1
+ export interface ChannelMessage {
2
+ channelType: string;
3
+ senderId: string;
4
+ senderName?: string;
5
+ chatId: string;
6
+ chatType: 'dm' | 'group';
7
+ text: string;
8
+ raw: unknown;
9
+ }
10
+ export interface ChannelAdapter {
11
+ readonly name: string;
12
+ start(onMessage: (msg: ChannelMessage) => void): Promise<void>;
13
+ reply(msg: ChannelMessage, text: string): Promise<void>;
14
+ stop(): Promise<void>;
15
+ }
16
+ export declare function buildSessionKey(msg: ChannelMessage): string;
17
+ /**
18
+ * Strip @mention tags from the text, returning only the user's actual message.
19
+ * Handles common IM @mention formats: `@BotName`, `<at user_id="xxx">BotName</at>` etc.
20
+ */
21
+ export declare function stripMention(text: string): string;
22
+ //# sourceMappingURL=channel.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.d.ts","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,cAAc;IAC7B,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,EAAE,MAAM,CAAC;IACf,QAAQ,EAAE,IAAI,GAAG,OAAO,CAAC;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,EAAE,OAAO,CAAC;CACd;AAED,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,KAAK,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CACvB;AAED,wBAAgB,eAAe,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAE3D;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAKjD"}
@@ -0,0 +1,14 @@
1
+ export function buildSessionKey(msg) {
2
+ return `${msg.channelType}:${msg.chatId}:${msg.senderId}`;
3
+ }
4
+ /**
5
+ * Strip @mention tags from the text, returning only the user's actual message.
6
+ * Handles common IM @mention formats: `@BotName`, `<at user_id="xxx">BotName</at>` etc.
7
+ */
8
+ export function stripMention(text) {
9
+ return text
10
+ .replace(/<at[^>]*>.*?<\/at>/gi, '')
11
+ .replace(/@\S+/g, '')
12
+ .trim();
13
+ }
14
+ //# sourceMappingURL=channel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"channel.js","sourceRoot":"","sources":["../src/channel.ts"],"names":[],"mappings":"AAiBA,MAAM,UAAU,eAAe,CAAC,GAAmB;IACjD,OAAO,GAAG,GAAG,CAAC,WAAW,IAAI,GAAG,CAAC,MAAM,IAAI,GAAG,CAAC,QAAQ,EAAE,CAAC;AAC5D,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,YAAY,CAAC,IAAY;IACvC,OAAO,IAAI;SACR,OAAO,CAAC,sBAAsB,EAAE,EAAE,CAAC;SACnC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC;SACpB,IAAI,EAAE,CAAC;AACZ,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { ChannelAdapter, ChannelMessage } from '../channel.js';
2
+ import type { DingtalkChannelConfig } from '../workspace.js';
3
+ export declare class DingtalkAdapter implements ChannelAdapter {
4
+ readonly name = "dingtalk";
5
+ private config;
6
+ private dwClient;
7
+ constructor(config: DingtalkChannelConfig);
8
+ start(onMessage: (msg: ChannelMessage) => void): Promise<void>;
9
+ reply(msg: ChannelMessage, text: string): Promise<void>;
10
+ stop(): Promise<void>;
11
+ }
12
+ //# sourceMappingURL=dingtalk.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dingtalk.d.ts","sourceRoot":"","sources":["../../src/channels/dingtalk.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iBAAiB,CAAC;AAE7D,qBAAa,eAAgB,YAAW,cAAc;IACpD,QAAQ,CAAC,IAAI,cAAc;IAC3B,OAAO,CAAC,MAAM,CAAwB;IACtC,OAAO,CAAC,QAAQ,CAAM;gBAEV,MAAM,EAAE,qBAAqB;IAInC,KAAK,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA8C9D,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAuBvD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5B"}
@@ -0,0 +1,66 @@
1
+ export class DingtalkAdapter {
2
+ name = 'dingtalk';
3
+ config;
4
+ dwClient;
5
+ constructor(config) {
6
+ this.config = config;
7
+ }
8
+ async start(onMessage) {
9
+ let sdk;
10
+ try {
11
+ sdk = await import('dingtalk-stream');
12
+ }
13
+ catch {
14
+ throw new Error('DingTalk adapter requires dingtalk-stream. Install it: npm install dingtalk-stream');
15
+ }
16
+ const { DWClient, TOPIC_ROBOT } = sdk;
17
+ this.dwClient = new DWClient({
18
+ clientId: this.config.clientId,
19
+ clientSecret: this.config.clientSecret,
20
+ });
21
+ this.dwClient.registerCallbackListener(TOPIC_ROBOT, async (res) => {
22
+ const data = JSON.parse(res.data);
23
+ const text = data.text?.content?.trim() || '';
24
+ if (!text)
25
+ return;
26
+ const isGroup = data.conversationType === '2';
27
+ const channelMsg = {
28
+ channelType: 'dingtalk',
29
+ senderId: data.senderStaffId || data.senderId || '',
30
+ senderName: data.senderNick,
31
+ chatId: data.conversationId || '',
32
+ chatType: isGroup ? 'group' : 'dm',
33
+ text,
34
+ raw: { ...data, _sessionWebhook: data.sessionWebhook },
35
+ };
36
+ onMessage(channelMsg);
37
+ this.dwClient.socketCallBackResponse(res.headers.messageId, { status: 'SUCCESS' });
38
+ });
39
+ await this.dwClient.connect();
40
+ console.log(`[dingtalk] Stream connection established`);
41
+ }
42
+ async reply(msg, text) {
43
+ const raw = msg.raw;
44
+ const webhook = raw?._sessionWebhook;
45
+ if (!webhook)
46
+ return;
47
+ const body = {
48
+ msgtype: 'text',
49
+ text: { content: text },
50
+ };
51
+ const accessToken = await this.dwClient?.getAccessToken?.();
52
+ const headers = { 'Content-Type': 'application/json' };
53
+ if (accessToken) {
54
+ headers['x-acs-dingtalk-access-token'] = accessToken;
55
+ }
56
+ await fetch(webhook, {
57
+ method: 'POST',
58
+ headers,
59
+ body: JSON.stringify(body),
60
+ });
61
+ }
62
+ async stop() {
63
+ this.dwClient = null;
64
+ }
65
+ }
66
+ //# sourceMappingURL=dingtalk.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dingtalk.js","sourceRoot":"","sources":["../../src/channels/dingtalk.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ import type { ChannelAdapter, ChannelMessage } from '../channel.js';
2
+ import type { FeishuChannelConfig } from '../workspace.js';
3
+ export declare class FeishuAdapter implements ChannelAdapter {
4
+ readonly name = "feishu";
5
+ private config;
6
+ private client;
7
+ private wsClient;
8
+ constructor(config: FeishuChannelConfig);
9
+ start(onMessage: (msg: ChannelMessage) => void): Promise<void>;
10
+ reply(msg: ChannelMessage, text: string): Promise<void>;
11
+ stop(): Promise<void>;
12
+ }
13
+ //# sourceMappingURL=feishu.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feishu.d.ts","sourceRoot":"","sources":["../../src/channels/feishu.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAE3D,qBAAa,aAAc,YAAW,cAAc;IAClD,QAAQ,CAAC,IAAI,YAAY;IACzB,OAAO,CAAC,MAAM,CAAsB;IACpC,OAAO,CAAC,MAAM,CAAM;IACpB,OAAO,CAAC,QAAQ,CAAM;gBAEV,MAAM,EAAE,mBAAmB;IAIjC,KAAK,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IAuD9D,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAYvD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAM5B"}
@@ -0,0 +1,73 @@
1
+ export class FeishuAdapter {
2
+ name = 'feishu';
3
+ config;
4
+ client;
5
+ wsClient;
6
+ constructor(config) {
7
+ this.config = config;
8
+ }
9
+ async start(onMessage) {
10
+ let lark;
11
+ try {
12
+ lark = await import('@larksuiteoapi/node-sdk');
13
+ }
14
+ catch {
15
+ throw new Error('Feishu adapter requires @larksuiteoapi/node-sdk. Install it: npm install @larksuiteoapi/node-sdk');
16
+ }
17
+ const baseConfig = {
18
+ appId: this.config.appId,
19
+ appSecret: this.config.appSecret,
20
+ };
21
+ this.client = new lark.Client(baseConfig);
22
+ const eventDispatcher = new lark.EventDispatcher({}).register({
23
+ 'im.message.receive_v1': async (data) => {
24
+ const { message, sender } = data;
25
+ if (message.message_type !== 'text')
26
+ return;
27
+ let text = '';
28
+ try {
29
+ text = JSON.parse(message.content).text;
30
+ }
31
+ catch {
32
+ return;
33
+ }
34
+ const chatType = message.chat_type === 'p2p' ? 'dm' : 'group';
35
+ const channelMsg = {
36
+ channelType: 'feishu',
37
+ senderId: sender.sender_id?.open_id || sender.sender_id?.user_id || '',
38
+ senderName: sender.sender_id?.open_id,
39
+ chatId: message.chat_id,
40
+ chatType,
41
+ text,
42
+ raw: data,
43
+ };
44
+ onMessage(channelMsg);
45
+ },
46
+ });
47
+ this.wsClient = new lark.WSClient({
48
+ ...baseConfig,
49
+ loggerLevel: lark.LoggerLevel.info,
50
+ });
51
+ await this.wsClient.start({ eventDispatcher });
52
+ console.log(`[feishu] WebSocket connection established`);
53
+ }
54
+ async reply(msg, text) {
55
+ if (!this.client)
56
+ return;
57
+ await this.client.im.v1.message.create({
58
+ params: { receive_id_type: 'chat_id' },
59
+ data: {
60
+ receive_id: msg.chatId,
61
+ content: JSON.stringify({ text }),
62
+ msg_type: 'text',
63
+ },
64
+ });
65
+ }
66
+ async stop() {
67
+ // WSClient doesn't expose a clean close method in current SDK version;
68
+ // setting to null allows GC to collect.
69
+ this.wsClient = null;
70
+ this.client = null;
71
+ }
72
+ }
73
+ //# sourceMappingURL=feishu.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feishu.js","sourceRoot":"","sources":["../../src/channels/feishu.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { ChannelAdapter, ChannelMessage } from '../channel.js';
2
+ import type { WecomChannelConfig } from '../workspace.js';
3
+ export declare class WecomAdapter implements ChannelAdapter {
4
+ readonly name = "wecom";
5
+ private config;
6
+ private server;
7
+ private accessToken;
8
+ private tokenExpiresAt;
9
+ constructor(config: WecomChannelConfig);
10
+ private getAccessToken;
11
+ start(onMessage: (msg: ChannelMessage) => void): Promise<void>;
12
+ reply(msg: ChannelMessage, text: string): Promise<void>;
13
+ stop(): Promise<void>;
14
+ }
15
+ //# sourceMappingURL=wecom.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wecom.d.ts","sourceRoot":"","sources":["../../src/channels/wecom.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iBAAiB,CAAC;AAW1D,qBAAa,YAAa,YAAW,cAAc;IACjD,QAAQ,CAAC,IAAI,WAAW;IACxB,OAAO,CAAC,MAAM,CAAqB;IACnC,OAAO,CAAC,MAAM,CAAgD;IAC9D,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,cAAc,CAAa;gBAEvB,MAAM,EAAE,kBAAkB;YAIxB,cAAc;IAetB,KAAK,CAAC,SAAS,EAAE,CAAC,GAAG,EAAE,cAAc,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;IA2G9D,KAAK,CAAC,GAAG,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBvD,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;CAS5B"}
@@ -0,0 +1,152 @@
1
+ import { createServer } from 'node:http';
2
+ function readBody(req) {
3
+ return new Promise((resolve, reject) => {
4
+ const chunks = [];
5
+ req.on('data', (c) => chunks.push(c));
6
+ req.on('end', () => resolve(Buffer.concat(chunks).toString('utf-8')));
7
+ req.on('error', reject);
8
+ });
9
+ }
10
+ export class WecomAdapter {
11
+ name = 'wecom';
12
+ config;
13
+ server = null;
14
+ accessToken = '';
15
+ tokenExpiresAt = 0;
16
+ constructor(config) {
17
+ this.config = config;
18
+ }
19
+ async getAccessToken() {
20
+ if (this.accessToken && Date.now() < this.tokenExpiresAt) {
21
+ return this.accessToken;
22
+ }
23
+ const url = `https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=${this.config.corpId}&corpsecret=${this.config.secret}`;
24
+ const res = await fetch(url);
25
+ const data = await res.json();
26
+ if (data.errcode && data.errcode !== 0) {
27
+ throw new Error(`WeCom getAccessToken failed: ${data.errmsg}`);
28
+ }
29
+ this.accessToken = data.access_token;
30
+ this.tokenExpiresAt = Date.now() + (data.expires_in - 300) * 1000;
31
+ return this.accessToken;
32
+ }
33
+ async start(onMessage) {
34
+ let wecomCrypto;
35
+ let xml2js;
36
+ try {
37
+ wecomCrypto = await import('@wecom/crypto');
38
+ }
39
+ catch {
40
+ throw new Error('WeCom adapter requires @wecom/crypto. Install it: npm install @wecom/crypto');
41
+ }
42
+ try {
43
+ xml2js = await import('xml2js');
44
+ }
45
+ catch {
46
+ throw new Error('WeCom adapter requires xml2js. Install it: npm install xml2js');
47
+ }
48
+ const { getSignature, decrypt } = wecomCrypto;
49
+ this.server = createServer(async (req, res) => {
50
+ const url = new URL(req.url || '/', `http://${req.headers.host || 'localhost'}`);
51
+ if (!url.pathname.startsWith('/wecom')) {
52
+ res.writeHead(404);
53
+ res.end();
54
+ return;
55
+ }
56
+ const msgSignature = url.searchParams.get('msg_signature') || '';
57
+ const timestamp = url.searchParams.get('timestamp') || '';
58
+ const nonce = url.searchParams.get('nonce') || '';
59
+ if (req.method === 'GET') {
60
+ const echostr = url.searchParams.get('echostr') || '';
61
+ try {
62
+ const signature = getSignature(this.config.token, timestamp, nonce, echostr);
63
+ if (signature === msgSignature) {
64
+ const { message } = decrypt(this.config.encodingAESKey, echostr);
65
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
66
+ res.end(message);
67
+ }
68
+ else {
69
+ res.writeHead(403);
70
+ res.end('Signature mismatch');
71
+ }
72
+ }
73
+ catch {
74
+ res.writeHead(500);
75
+ res.end('Verification failed');
76
+ }
77
+ return;
78
+ }
79
+ if (req.method === 'POST') {
80
+ try {
81
+ const body = await readBody(req);
82
+ const parsed = await xml2js.parseStringPromise(body, { explicitArray: false });
83
+ const xmlRoot = parsed.xml;
84
+ const encryptedMsg = xmlRoot.Encrypt;
85
+ const signature = getSignature(this.config.token, timestamp, nonce, encryptedMsg);
86
+ if (signature !== msgSignature) {
87
+ res.writeHead(403);
88
+ res.end('Signature mismatch');
89
+ return;
90
+ }
91
+ const { message } = decrypt(this.config.encodingAESKey, encryptedMsg);
92
+ const msgParsed = await xml2js.parseStringPromise(message, { explicitArray: false });
93
+ const msgXml = msgParsed.xml;
94
+ if (msgXml.MsgType !== 'text') {
95
+ res.writeHead(200);
96
+ res.end('ok');
97
+ return;
98
+ }
99
+ const channelMsg = {
100
+ channelType: 'wecom',
101
+ senderId: msgXml.FromUserName || '',
102
+ chatId: msgXml.FromUserName || '',
103
+ chatType: 'dm',
104
+ text: msgXml.Content || '',
105
+ raw: msgXml,
106
+ };
107
+ onMessage(channelMsg);
108
+ res.writeHead(200);
109
+ res.end('ok');
110
+ }
111
+ catch (e) {
112
+ console.error('[wecom] Failed to process message:', e);
113
+ res.writeHead(500);
114
+ res.end('Internal error');
115
+ }
116
+ return;
117
+ }
118
+ res.writeHead(405);
119
+ res.end();
120
+ });
121
+ const port = 9000;
122
+ this.server.listen(port, () => {
123
+ console.log(`[wecom] Webhook server started on port ${port}, callback path: /wecom`);
124
+ });
125
+ }
126
+ async reply(msg, text) {
127
+ const token = await this.getAccessToken();
128
+ const url = `https://qyapi.weixin.qq.com/cgi-bin/message/send?access_token=${token}`;
129
+ const body = {
130
+ touser: msg.senderId,
131
+ msgtype: 'text',
132
+ agentid: Number(this.config.agentId),
133
+ text: { content: text },
134
+ };
135
+ await fetch(url, {
136
+ method: 'POST',
137
+ headers: { 'Content-Type': 'application/json' },
138
+ body: JSON.stringify(body),
139
+ });
140
+ }
141
+ async stop() {
142
+ return new Promise((resolve) => {
143
+ if (this.server) {
144
+ this.server.close(() => resolve());
145
+ }
146
+ else {
147
+ resolve();
148
+ }
149
+ });
150
+ }
151
+ }
152
+ //# sourceMappingURL=wecom.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wecom.js","sourceRoot":"","sources":["../../src/channels/wecom.ts"],"names":[],"mappings":"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"}
package/dist/cli.d.ts ADDED
@@ -0,0 +1,3 @@
1
+ #!/usr/bin/env node
2
+ export {};
3
+ //# sourceMappingURL=cli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}