adaptoclaw 1.0.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 (123) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +3 -0
  3. package/dist/channels/amocrm.d.ts +20 -0
  4. package/dist/channels/amocrm.d.ts.map +1 -0
  5. package/dist/channels/amocrm.js +233 -0
  6. package/dist/channels/amocrm.js.map +1 -0
  7. package/dist/channels/factory.d.ts +24 -0
  8. package/dist/channels/factory.d.ts.map +1 -0
  9. package/dist/channels/factory.js +41 -0
  10. package/dist/channels/factory.js.map +1 -0
  11. package/dist/channels/telegram.d.ts +28 -0
  12. package/dist/channels/telegram.d.ts.map +1 -0
  13. package/dist/channels/telegram.js +432 -0
  14. package/dist/channels/telegram.js.map +1 -0
  15. package/dist/channels/whatsapp.d.ts +88 -0
  16. package/dist/channels/whatsapp.d.ts.map +1 -0
  17. package/dist/channels/whatsapp.js +502 -0
  18. package/dist/channels/whatsapp.js.map +1 -0
  19. package/dist/config-types.d.ts +43 -0
  20. package/dist/config-types.d.ts.map +1 -0
  21. package/dist/config-types.js +2 -0
  22. package/dist/config-types.js.map +1 -0
  23. package/dist/config.d.ts +32 -0
  24. package/dist/config.d.ts.map +1 -0
  25. package/dist/config.js +71 -0
  26. package/dist/config.js.map +1 -0
  27. package/dist/container-runner.d.ts +47 -0
  28. package/dist/container-runner.d.ts.map +1 -0
  29. package/dist/container-runner.js +494 -0
  30. package/dist/container-runner.js.map +1 -0
  31. package/dist/container-runtime.d.ts +13 -0
  32. package/dist/container-runtime.d.ts.map +1 -0
  33. package/dist/container-runtime.js +90 -0
  34. package/dist/container-runtime.js.map +1 -0
  35. package/dist/core/engine.d.ts +64 -0
  36. package/dist/core/engine.d.ts.map +1 -0
  37. package/dist/core/engine.js +782 -0
  38. package/dist/core/engine.js.map +1 -0
  39. package/dist/create.d.ts +4 -0
  40. package/dist/create.d.ts.map +1 -0
  41. package/dist/create.js +5 -0
  42. package/dist/create.js.map +1 -0
  43. package/dist/db.d.ts +67 -0
  44. package/dist/db.d.ts.map +1 -0
  45. package/dist/db.js +454 -0
  46. package/dist/db.js.map +1 -0
  47. package/dist/env.d.ts +8 -0
  48. package/dist/env.d.ts.map +1 -0
  49. package/dist/env.js +40 -0
  50. package/dist/env.js.map +1 -0
  51. package/dist/group-folder.d.ts +5 -0
  52. package/dist/group-folder.d.ts.map +1 -0
  53. package/dist/group-folder.js +44 -0
  54. package/dist/group-folder.js.map +1 -0
  55. package/dist/group-queue.d.ts +52 -0
  56. package/dist/group-queue.d.ts.map +1 -0
  57. package/dist/group-queue.js +321 -0
  58. package/dist/group-queue.js.map +1 -0
  59. package/dist/health.d.ts +5 -0
  60. package/dist/health.d.ts.map +1 -0
  61. package/dist/health.js +70 -0
  62. package/dist/health.js.map +1 -0
  63. package/dist/hooks/runner.d.ts +13 -0
  64. package/dist/hooks/runner.d.ts.map +1 -0
  65. package/dist/hooks/runner.js +42 -0
  66. package/dist/hooks/runner.js.map +1 -0
  67. package/dist/hooks/types.d.ts +33 -0
  68. package/dist/hooks/types.d.ts.map +1 -0
  69. package/dist/hooks/types.js +2 -0
  70. package/dist/hooks/types.js.map +1 -0
  71. package/dist/index.d.ts +10 -0
  72. package/dist/index.d.ts.map +1 -0
  73. package/dist/index.js +38 -0
  74. package/dist/index.js.map +1 -0
  75. package/dist/ipc.d.ts +36 -0
  76. package/dist/ipc.d.ts.map +1 -0
  77. package/dist/ipc.js +441 -0
  78. package/dist/ipc.js.map +1 -0
  79. package/dist/logger.d.ts +3 -0
  80. package/dist/logger.d.ts.map +1 -0
  81. package/dist/logger.js +14 -0
  82. package/dist/logger.js.map +1 -0
  83. package/dist/media-cleanup.d.ts +2 -0
  84. package/dist/media-cleanup.d.ts.map +1 -0
  85. package/dist/media-cleanup.js +51 -0
  86. package/dist/media-cleanup.js.map +1 -0
  87. package/dist/media.d.ts +2 -0
  88. package/dist/media.d.ts.map +1 -0
  89. package/dist/media.js +22 -0
  90. package/dist/media.js.map +1 -0
  91. package/dist/mount-security.d.ts +34 -0
  92. package/dist/mount-security.d.ts.map +1 -0
  93. package/dist/mount-security.js +321 -0
  94. package/dist/mount-security.js.map +1 -0
  95. package/dist/rate-limiter.d.ts +10 -0
  96. package/dist/rate-limiter.d.ts.map +1 -0
  97. package/dist/rate-limiter.js +31 -0
  98. package/dist/rate-limiter.js.map +1 -0
  99. package/dist/router.d.ts +11 -0
  100. package/dist/router.d.ts.map +1 -0
  101. package/dist/router.js +79 -0
  102. package/dist/router.js.map +1 -0
  103. package/dist/rqlite.d.ts +36 -0
  104. package/dist/rqlite.d.ts.map +1 -0
  105. package/dist/rqlite.js +98 -0
  106. package/dist/rqlite.js.map +1 -0
  107. package/dist/runtime-config.d.ts +9 -0
  108. package/dist/runtime-config.d.ts.map +1 -0
  109. package/dist/runtime-config.js +14 -0
  110. package/dist/runtime-config.js.map +1 -0
  111. package/dist/task-scheduler.d.ts +14 -0
  112. package/dist/task-scheduler.d.ts.map +1 -0
  113. package/dist/task-scheduler.js +189 -0
  114. package/dist/task-scheduler.js.map +1 -0
  115. package/dist/types.d.ts +96 -0
  116. package/dist/types.d.ts.map +1 -0
  117. package/dist/types.js +2 -0
  118. package/dist/types.js.map +1 -0
  119. package/dist/whatsapp-auth.d.ts +2 -0
  120. package/dist/whatsapp-auth.d.ts.map +1 -0
  121. package/dist/whatsapp-auth.js +141 -0
  122. package/dist/whatsapp-auth.js.map +1 -0
  123. package/package.json +58 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Gavriel
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,3 @@
1
+ # adaptoclaw
2
+
3
+ AI assistant framework. See [docs/plans/](docs/plans/) for architecture.
@@ -0,0 +1,20 @@
1
+ import { Channel, OnChatMetadata, OnInboundMessage, RegisteredGroup } from '../types.js';
2
+ export interface AmoCrmChannelOpts {
3
+ onMessage: OnInboundMessage;
4
+ onChatMetadata: OnChatMetadata;
5
+ registeredGroups: () => Record<string, RegisteredGroup>;
6
+ registerGroup: (jid: string, group: RegisteredGroup) => Promise<void>;
7
+ }
8
+ export declare class AmoCrmChannel implements Channel {
9
+ name: string;
10
+ private server;
11
+ private opts;
12
+ constructor(opts: AmoCrmChannelOpts);
13
+ connect(): Promise<void>;
14
+ private handleWebhook;
15
+ sendMessage(jid: string, text: string): Promise<void>;
16
+ isConnected(): boolean;
17
+ ownsJid(jid: string): boolean;
18
+ disconnect(): Promise<void>;
19
+ }
20
+ //# sourceMappingURL=amocrm.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"amocrm.d.ts","sourceRoot":"","sources":["../../src/channels/amocrm.ts"],"names":[],"mappings":"AAiBA,OAAO,EACL,OAAO,EAEP,cAAc,EACd,gBAAgB,EAChB,eAAe,EAChB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,iBAAiB;IAChC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;IACxD,aAAa,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,eAAe,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;CACvE;AA4FD,qBAAa,aAAc,YAAW,OAAO;IAC3C,IAAI,SAAY;IAEhB,OAAO,CAAC,MAAM,CAA4B;IAC1C,OAAO,CAAC,IAAI,CAAoB;gBAEpB,IAAI,EAAE,iBAAiB;IAI7B,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAsC9B,OAAO,CAAC,aAAa;IAoDf,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+D3D,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIvB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;CAWlC"}
@@ -0,0 +1,233 @@
1
+ import fs from 'fs';
2
+ import http from 'http';
3
+ import path from 'path';
4
+ import { parse as parseQs } from 'querystring';
5
+ import { AMOCRM_BASE_URL, AMOCRM_GROUP_FOLDER, AMOCRM_LIVE_LEADS, AMOCRM_RESPONSE_FIELD_ID, AMOCRM_SALESBOT_ID, AMOCRM_WEBHOOK_PORT, DATA_DIR, GROUPS_DIR, TRIGGER_PATTERN, } from '../config.js';
6
+ import { logger } from '../logger.js';
7
+ /** Read the AmoCRM access token from the group folder. */
8
+ function readToken() {
9
+ const tokenPath = path.join(GROUPS_DIR, AMOCRM_GROUP_FOLDER, 'amocrm-token.txt');
10
+ try {
11
+ return fs.readFileSync(tokenPath, 'utf-8').trim();
12
+ }
13
+ catch {
14
+ logger.error({ tokenPath }, 'Failed to read AmoCRM token');
15
+ return '';
16
+ }
17
+ }
18
+ async function amoFetch(urlPath, init) {
19
+ const token = readToken();
20
+ if (!token)
21
+ throw new Error('AmoCRM token not available');
22
+ const res = await fetch(`${AMOCRM_BASE_URL}${urlPath}`, {
23
+ ...init,
24
+ headers: {
25
+ Authorization: `Bearer ${token}`,
26
+ 'Content-Type': 'application/json',
27
+ ...init?.headers,
28
+ },
29
+ });
30
+ if (!res.ok) {
31
+ const body = await res.text();
32
+ throw new Error(`AmoCRM ${res.status}: ${body}`);
33
+ }
34
+ // Some endpoints return empty body (204, or 200 with no content)
35
+ const text = await res.text();
36
+ if (!text)
37
+ return null;
38
+ try {
39
+ return JSON.parse(text);
40
+ }
41
+ catch {
42
+ return null;
43
+ }
44
+ }
45
+ function parseWebhookBody(body) {
46
+ const parsed = parseQs(body);
47
+ const messages = [];
48
+ // Collect all message[add][N] entries
49
+ // Keys look like: message[add][0][text], message[add][0][author][name]
50
+ const addEntries = {};
51
+ for (const [key, val] of Object.entries(parsed)) {
52
+ const m = key.match(/^message\[add\]\[(\d+)\]\[(.+)\]$/);
53
+ if (!m)
54
+ continue;
55
+ const idx = m[1];
56
+ const field = m[2]; // e.g. "text", "author][name", "type"
57
+ if (!addEntries[idx])
58
+ addEntries[idx] = {};
59
+ addEntries[idx][field] = String(val);
60
+ }
61
+ for (const entry of Object.values(addEntries)) {
62
+ messages.push({
63
+ type: entry['type'] || '',
64
+ text: entry['text'] || '',
65
+ leadId: entry['entity_id'] || '',
66
+ contactId: entry['contact_id'] || '',
67
+ // author][name comes from message[add][0][author][name] parsed by regex
68
+ authorName: entry['author][name'] || entry['author[name]'] || 'Unknown',
69
+ origin: entry['origin'] || '',
70
+ talkId: entry['talk_id'] || '',
71
+ });
72
+ }
73
+ return messages;
74
+ }
75
+ export class AmoCrmChannel {
76
+ name = 'amocrm';
77
+ server = null;
78
+ opts;
79
+ constructor(opts) {
80
+ this.opts = opts;
81
+ }
82
+ async connect() {
83
+ return new Promise((resolve) => {
84
+ this.server = http.createServer((req, res) => {
85
+ // Health check
86
+ if (req.method === 'GET') {
87
+ res.writeHead(200, { 'Content-Type': 'text/plain' });
88
+ res.end('amocrm webhook alive');
89
+ return;
90
+ }
91
+ if (req.method !== 'POST') {
92
+ res.writeHead(405);
93
+ res.end();
94
+ return;
95
+ }
96
+ let body = '';
97
+ req.on('data', (chunk) => { body += chunk; });
98
+ req.on('end', () => {
99
+ res.writeHead(200);
100
+ res.end('ok');
101
+ try {
102
+ this.handleWebhook(body);
103
+ }
104
+ catch (err) {
105
+ logger.error({ err }, 'Error handling AmoCRM webhook');
106
+ }
107
+ });
108
+ });
109
+ this.server.listen(AMOCRM_WEBHOOK_PORT, () => {
110
+ logger.info({ port: AMOCRM_WEBHOOK_PORT }, 'AmoCRM webhook server started');
111
+ console.log(`\n AmoCRM webhook: http://localhost:${AMOCRM_WEBHOOK_PORT}`);
112
+ resolve();
113
+ });
114
+ });
115
+ }
116
+ handleWebhook(body) {
117
+ const messages = parseWebhookBody(body);
118
+ for (const msg of messages) {
119
+ // Only process incoming messages (from client, not bot)
120
+ if (msg.type !== 'incoming') {
121
+ logger.debug({ type: msg.type }, 'Skipping non-incoming AmoCRM message');
122
+ continue;
123
+ }
124
+ if (!msg.leadId) {
125
+ logger.warn('AmoCRM message without lead_id, skipping');
126
+ continue;
127
+ }
128
+ const chatJid = `amo:${msg.leadId}`;
129
+ const timestamp = new Date().toISOString();
130
+ // Auto-register new leads
131
+ const groups = this.opts.registeredGroups();
132
+ if (!groups[chatJid]) {
133
+ const groupName = `AmoCRM Lead ${msg.leadId}`;
134
+ this.opts.registerGroup(chatJid, {
135
+ name: groupName,
136
+ folder: AMOCRM_GROUP_FOLDER,
137
+ trigger: TRIGGER_PATTERN.source,
138
+ added_at: timestamp,
139
+ requiresTrigger: false,
140
+ });
141
+ logger.info({ jid: chatJid, lead: msg.leadId }, 'Auto-registered AmoCRM lead');
142
+ }
143
+ this.opts.onChatMetadata(chatJid, timestamp, `Lead ${msg.leadId}`, 'amocrm', false);
144
+ const newMessage = {
145
+ id: `amo-${msg.leadId}-${Date.now()}`,
146
+ chat_jid: chatJid,
147
+ sender: msg.contactId || msg.leadId,
148
+ sender_name: msg.authorName,
149
+ content: msg.text,
150
+ timestamp,
151
+ is_from_me: false,
152
+ };
153
+ this.opts.onMessage(chatJid, newMessage);
154
+ logger.info({ leadId: msg.leadId, author: msg.authorName, origin: msg.origin, text: msg.text.slice(0, 200) }, 'AmoCRM incoming message');
155
+ }
156
+ }
157
+ async sendMessage(jid, text) {
158
+ const leadId = jid.replace(/^amo:/, '');
159
+ const isLive = AMOCRM_LIVE_LEADS.has(leadId);
160
+ // Always log locally
161
+ const logPath = path.join(DATA_DIR, 'amocrm-dryrun.jsonl');
162
+ const entry = { leadId, text, ts: new Date().toISOString(), live: isLive };
163
+ fs.appendFileSync(logPath, JSON.stringify(entry) + '\n');
164
+ if (!isLive) {
165
+ // DRY_RUN: only add note to lead in AmoCRM for visibility
166
+ logger.info({ leadId }, '[DRY_RUN] AmoCRM response logged');
167
+ try {
168
+ await amoFetch(`/api/v4/leads/${leadId}/notes`, {
169
+ method: 'POST',
170
+ body: JSON.stringify([{
171
+ note_type: 'common',
172
+ params: { text: `[DRY_RUN] AI: ${text}` },
173
+ }]),
174
+ });
175
+ }
176
+ catch (err) {
177
+ logger.error({ err, leadId }, 'Failed to add DRY_RUN note');
178
+ }
179
+ return;
180
+ }
181
+ // LIVE: send response to client via Salesbot
182
+ try {
183
+ // 1. Write response to the AI Response field
184
+ await amoFetch(`/api/v4/leads/${leadId}`, {
185
+ method: 'PATCH',
186
+ body: JSON.stringify({
187
+ custom_fields_values: [{
188
+ field_id: AMOCRM_RESPONSE_FIELD_ID,
189
+ values: [{ value: text }],
190
+ }],
191
+ }),
192
+ });
193
+ // 2. Run Salesbot to deliver the message
194
+ await amoFetch(`/api/v4/bots/${AMOCRM_SALESBOT_ID}/run`, {
195
+ method: 'POST',
196
+ body: JSON.stringify([{
197
+ entity_id: parseInt(leadId, 10),
198
+ entity_type: 'leads',
199
+ }]),
200
+ });
201
+ // 3. Log response as a note
202
+ await amoFetch(`/api/v4/leads/${leadId}/notes`, {
203
+ method: 'POST',
204
+ body: JSON.stringify([{
205
+ note_type: 'common',
206
+ params: { text: `AI: ${text}` },
207
+ }]),
208
+ });
209
+ logger.info({ leadId }, 'AmoCRM response sent via Salesbot');
210
+ }
211
+ catch (err) {
212
+ logger.error({ err, leadId }, 'Failed to send AmoCRM response');
213
+ }
214
+ }
215
+ isConnected() {
216
+ return this.server !== null;
217
+ }
218
+ ownsJid(jid) {
219
+ return jid.startsWith('amo:');
220
+ }
221
+ async disconnect() {
222
+ if (this.server) {
223
+ return new Promise((resolve) => {
224
+ this.server.close(() => {
225
+ this.server = null;
226
+ logger.info('AmoCRM webhook server stopped');
227
+ resolve();
228
+ });
229
+ });
230
+ }
231
+ }
232
+ }
233
+ //# sourceMappingURL=amocrm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"amocrm.js","sourceRoot":"","sources":["../../src/channels/amocrm.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { ChannelFactory } from '../config-types.js';
2
+ export interface WhatsAppOptions {
3
+ autoRegister?: boolean;
4
+ listenOnly?: boolean;
5
+ phoneNumber?: string;
6
+ hasOwnNumber?: boolean;
7
+ }
8
+ export declare function whatsapp(opts?: WhatsAppOptions): ChannelFactory;
9
+ export interface TelegramOptions {
10
+ token: string;
11
+ only?: boolean;
12
+ }
13
+ export declare function telegram(opts: TelegramOptions): ChannelFactory;
14
+ export interface AmoCrmOptions {
15
+ baseUrl: string;
16
+ webhookPort?: number;
17
+ salesbotId?: number;
18
+ responseFieldId?: number;
19
+ groupFolder?: string;
20
+ liveLeads?: string[];
21
+ enabled?: boolean;
22
+ }
23
+ export declare function amocrm(opts: AmoCrmOptions): ChannelFactory;
24
+ //# sourceMappingURL=factory.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../../src/channels/factory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAe,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAOjE,MAAM,WAAW,eAAe;IAC9B,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,YAAY,CAAC,EAAE,OAAO,CAAC;CACxB;AAED,wBAAgB,QAAQ,CAAC,IAAI,GAAE,eAAoB,GAAG,cAAc,CAWnE;AAID,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,OAAO,CAAC;CAChB;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,cAAc,CAW9D;AAID,MAAM,WAAW,aAAa;IAC5B,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,aAAa,GAAG,cAAc,CAY1D"}
@@ -0,0 +1,41 @@
1
+ import { WhatsAppChannel } from './whatsapp.js';
2
+ import { TelegramChannel } from './telegram.js';
3
+ import { AmoCrmChannel } from './amocrm.js';
4
+ export function whatsapp(opts = {}) {
5
+ return {
6
+ name: 'whatsapp',
7
+ create(deps) {
8
+ return new WhatsAppChannel({
9
+ onMessage: deps.onMessage,
10
+ onChatMetadata: deps.onChatMetadata,
11
+ registeredGroups: deps.registeredGroups,
12
+ });
13
+ },
14
+ };
15
+ }
16
+ export function telegram(opts) {
17
+ return {
18
+ name: 'telegram',
19
+ create(deps) {
20
+ return new TelegramChannel(opts.token, {
21
+ onMessage: deps.onMessage,
22
+ onChatMetadata: deps.onChatMetadata,
23
+ registeredGroups: deps.registeredGroups,
24
+ });
25
+ },
26
+ };
27
+ }
28
+ export function amocrm(opts) {
29
+ return {
30
+ name: 'amocrm',
31
+ create(deps) {
32
+ return new AmoCrmChannel({
33
+ onMessage: deps.onMessage,
34
+ onChatMetadata: deps.onChatMetadata,
35
+ registeredGroups: deps.registeredGroups,
36
+ registerGroup: deps.registerGroup,
37
+ });
38
+ },
39
+ };
40
+ }
41
+ //# sourceMappingURL=factory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"factory.js","sourceRoot":"","sources":["../../src/channels/factory.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;AAChD,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAW5C,MAAM,UAAU,QAAQ,CAAC,OAAwB,EAAE;IACjD,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,MAAM,CAAC,IAAiB;YACtB,OAAO,IAAI,eAAe,CAAC;gBACzB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,cAAc,EAAE,IAAI,CAAC,cAAc;gBACnC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;aACxC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC;AASD,MAAM,UAAU,QAAQ,CAAC,IAAqB;IAC5C,OAAO;QACL,IAAI,EAAE,UAAU;QAChB,MAAM,CAAC,IAAiB;YACtB,OAAO,IAAI,eAAe,CAAC,IAAI,CAAC,KAAK,EAAE;gBACrC,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,cAAc,EAAE,IAAI,CAAC,cAAc;gBACnC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;aACxC,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC;AAcD,MAAM,UAAU,MAAM,CAAC,IAAmB;IACxC,OAAO;QACL,IAAI,EAAE,QAAQ;QACd,MAAM,CAAC,IAAiB;YACtB,OAAO,IAAI,aAAa,CAAC;gBACvB,SAAS,EAAE,IAAI,CAAC,SAAS;gBACzB,cAAc,EAAE,IAAI,CAAC,cAAc;gBACnC,gBAAgB,EAAE,IAAI,CAAC,gBAAgB;gBACvC,aAAa,EAAE,IAAI,CAAC,aAA6F;aAClH,CAAC,CAAC;QACL,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,28 @@
1
+ import { Channel, OnChatMetadata, OnInboundMessage, RegisteredGroup } from '../types.js';
2
+ export interface TelegramChannelOpts {
3
+ onMessage: OnInboundMessage;
4
+ onChatMetadata: OnChatMetadata;
5
+ registeredGroups: () => Record<string, RegisteredGroup>;
6
+ }
7
+ /** Convert markdown to Telegram-compatible HTML. */
8
+ export declare function toTelegramHtml(text: string): string;
9
+ export type PairingHandler = (phoneNumber: string, onCode: (code: string) => void) => void;
10
+ export declare class TelegramChannel implements Channel {
11
+ name: string;
12
+ private bot;
13
+ private opts;
14
+ private botToken;
15
+ private pairingHandler;
16
+ private pendingPairingPhone;
17
+ constructor(botToken: string, opts: TelegramChannelOpts);
18
+ /** Set handler for WhatsApp pairing requests from /linkwhatsapp command */
19
+ onWhatsAppPairing(handler: PairingHandler): void;
20
+ connect(): Promise<void>;
21
+ sendMessage(jid: string, text: string): Promise<void>;
22
+ sendMedia(jid: string, filePath: string, caption?: string, mimeType?: string): Promise<void>;
23
+ isConnected(): boolean;
24
+ ownsJid(jid: string): boolean;
25
+ disconnect(): Promise<void>;
26
+ setTyping(jid: string, isTyping: boolean): Promise<void>;
27
+ }
28
+ //# sourceMappingURL=telegram.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"telegram.d.ts","sourceRoot":"","sources":["../../src/channels/telegram.ts"],"names":[],"mappings":"AAQA,OAAO,EACL,OAAO,EAEP,cAAc,EACd,gBAAgB,EAChB,eAAe,EAChB,MAAM,aAAa,CAAC;AAErB,MAAM,WAAW,mBAAmB;IAClC,SAAS,EAAE,gBAAgB,CAAC;IAC5B,cAAc,EAAE,cAAc,CAAC;IAC/B,gBAAgB,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,eAAe,CAAC,CAAC;CACzD;AAED,oDAAoD;AACpD,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnD;AAED,MAAM,MAAM,cAAc,GAAG,CAAC,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,KAAK,IAAI,CAAC;AAE3F,qBAAa,eAAgB,YAAW,OAAO;IAC7C,IAAI,SAAc;IAElB,OAAO,CAAC,GAAG,CAAoB;IAC/B,OAAO,CAAC,IAAI,CAAsB;IAClC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,cAAc,CAA+B;IACrD,OAAO,CAAC,mBAAmB,CAAkC;gBAEjD,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,mBAAmB;IAKvD,2EAA2E;IAC3E,iBAAiB,CAAC,OAAO,EAAE,cAAc,GAAG,IAAI;IAI1C,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;IAsXxB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAkCrD,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BlG,WAAW,IAAI,OAAO;IAItB,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO;IAIvB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAQ3B,SAAS,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;CAS/D"}