@alfe.ai/openclaw-telegram 0.0.1

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.
@@ -0,0 +1,503 @@
1
+ const require_telegram_bridge = require("./telegram-bridge.cjs");
2
+ let node_path = require("node:path");
3
+ let node_module = require("node:module");
4
+ let node_os = require("node:os");
5
+ let _alfe_ai_agent_api_client = require("@alfe.ai/agent-api-client");
6
+ let _alfe_ai_config = require("@alfe.ai/config");
7
+ let _alfe_ai_openclaw_plugin_kit = require("@alfe.ai/openclaw-plugin-kit");
8
+ //#region src/plugin.ts
9
+ const pkg = (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href)("../package.json");
10
+ const RETRY_MS = 3e4;
11
+ const DELIVERY_RETRY_MS = 5e3;
12
+ const IDENTITY_RETRY_MS = 3e4;
13
+ const MAX_IDENTITY_ATTEMPTS = 5;
14
+ const MAX_AGENT_ID_CHARS = 256;
15
+ const SAFE_AGENT_ID = /^[A-Za-z0-9_-]+$/u;
16
+ var TelegramLocalRuntime = class {
17
+ bridge = null;
18
+ retryTimer = null;
19
+ running = false;
20
+ generation = 0;
21
+ dispatch = null;
22
+ pluginRuntime = null;
23
+ pluginConfig = {};
24
+ logger = null;
25
+ deliveryQueuesByChat = /* @__PURE__ */ new Map();
26
+ dispatchedDeliveryIds = /* @__PURE__ */ new Map();
27
+ queued = /* @__PURE__ */ new Set();
28
+ blockedChats = /* @__PURE__ */ new Set();
29
+ constructor(agentId, stateDir) {
30
+ this.agentId = agentId;
31
+ this.stateDir = stateDir;
32
+ }
33
+ configure(api) {
34
+ this.logger = api.logger;
35
+ this.pluginRuntime = api.runtime ?? null;
36
+ try {
37
+ this.pluginConfig = api.runtime?.config.loadConfig() ?? {};
38
+ } catch {
39
+ this.pluginConfig = {};
40
+ api.logger.warn("OpenClaw config could not be loaded; Telegram tools remain available");
41
+ }
42
+ this.dispatch = (0, _alfe_ai_openclaw_plugin_kit.resolveOpenClawSdk)(api.logger, { unresolvableNote: "OpenClaw inbound SDK unavailable — Telegram deliveries will retry locally" });
43
+ }
44
+ async start() {
45
+ if (this.running) return;
46
+ this.running = true;
47
+ const generation = ++this.generation;
48
+ await this.connect(generation);
49
+ }
50
+ async stop() {
51
+ this.running = false;
52
+ this.generation += 1;
53
+ if (this.retryTimer) {
54
+ clearTimeout(this.retryTimer);
55
+ this.retryTimer = null;
56
+ }
57
+ const bridge = this.bridge;
58
+ this.bridge = null;
59
+ await bridge?.stop();
60
+ }
61
+ async status() {
62
+ const bridge = this.bridge;
63
+ if (!bridge?.isReady()) return {
64
+ authorized: false,
65
+ state: "setup_required",
66
+ deliveryMode: "read_only",
67
+ action: `Run \`${loginCommand(this.agentId)}\` in a terminal on the agent machine.`
68
+ };
69
+ return bridge.request("status");
70
+ }
71
+ async request(method, params = {}) {
72
+ const bridge = this.bridge;
73
+ if (!bridge?.isReady()) throw (0, _alfe_ai_openclaw_plugin_kit.publicToolError)(`Telegram is not logged in on this agent. Run \`${loginCommand(this.agentId)}\` in a terminal on the agent machine.`);
74
+ try {
75
+ const result = await bridge.request(method, params);
76
+ const chatId = typeof params.chatId === "string" ? params.chatId : null;
77
+ if (chatId && method === "subscribe") this.blockedChats.delete(chatId);
78
+ if (chatId && method === "unsubscribe") {
79
+ this.blockedChats.add(chatId);
80
+ for (const [deliveryId, dispatchedChatId] of this.dispatchedDeliveryIds) if (dispatchedChatId === chatId) this.dispatchedDeliveryIds.delete(deliveryId);
81
+ }
82
+ return result;
83
+ } catch (error) {
84
+ if (error instanceof require_telegram_bridge.TelegramBridgeUnavailable) throw (0, _alfe_ai_openclaw_plugin_kit.publicToolError)("Telegram is temporarily unavailable on this agent. Check `telegram_status` and retry.");
85
+ throw error;
86
+ }
87
+ }
88
+ async connect(generation) {
89
+ if (!this.isCurrentGeneration(generation) || this.bridge) return;
90
+ const logger = this.logger;
91
+ if (!logger) return;
92
+ const bridge = new require_telegram_bridge.TelegramBridge({
93
+ logger,
94
+ stateDir: this.stateDir,
95
+ onEvent: (event) => {
96
+ this.enqueue(event);
97
+ },
98
+ onExit: () => {
99
+ if (this.bridge === bridge) this.bridge = null;
100
+ this.scheduleRetry(generation);
101
+ }
102
+ });
103
+ this.bridge = bridge;
104
+ try {
105
+ await bridge.start();
106
+ if (!this.isCurrentGeneration(generation)) {
107
+ await bridge.stop();
108
+ if (this.bridge === bridge) this.bridge = null;
109
+ return;
110
+ }
111
+ logger.info("Telegram local user-session listener connected");
112
+ } catch {
113
+ await bridge.stop().catch(() => void 0);
114
+ if (this.bridge === bridge) this.bridge = null;
115
+ logger.info(`Telegram local session is not ready; run \`${loginCommand(this.agentId)}\` on the agent machine`);
116
+ this.scheduleRetry(generation);
117
+ }
118
+ }
119
+ scheduleRetry(generation) {
120
+ if (!this.running || generation !== this.generation || this.retryTimer) return;
121
+ this.retryTimer = setTimeout(() => {
122
+ this.retryTimer = null;
123
+ this.connect(generation);
124
+ }, RETRY_MS);
125
+ this.retryTimer.unref();
126
+ }
127
+ enqueue(event) {
128
+ if (this.queued.has(event.deliveryId) || this.blockedChats.has(event.chatId)) return;
129
+ this.queued.add(event.deliveryId);
130
+ const current = (this.deliveryQueuesByChat.get(event.chatId) ?? Promise.resolve()).then(() => this.deliverUntilAccepted(event)).catch(() => void 0).finally(() => {
131
+ this.queued.delete(event.deliveryId);
132
+ if (this.deliveryQueuesByChat.get(event.chatId) === current) this.deliveryQueuesByChat.delete(event.chatId);
133
+ });
134
+ this.deliveryQueuesByChat.set(event.chatId, current);
135
+ }
136
+ async deliverUntilAccepted(event) {
137
+ while (this.running && !this.blockedChats.has(event.chatId)) {
138
+ const dispatch = this.dispatch;
139
+ const runtime = this.pluginRuntime;
140
+ const bridge = this.bridge;
141
+ if (!dispatch || !runtime || !bridge?.isReady()) {
142
+ await delay(DELIVERY_RETRY_MS);
143
+ continue;
144
+ }
145
+ const outcome = { accepted: true };
146
+ try {
147
+ if (!this.dispatchedDeliveryIds.has(event.deliveryId)) {
148
+ await dispatch({
149
+ cfg: this.pluginConfig,
150
+ runtime,
151
+ channel: "telegram",
152
+ channelLabel: "Telegram",
153
+ accountId: `local-user-session:${this.agentId}`,
154
+ peer: {
155
+ kind: event.chatKind === "private" ? "direct" : "group",
156
+ id: event.chatId
157
+ },
158
+ senderId: event.senderId,
159
+ senderAddress: event.senderUsername ? `telegram:@${event.senderUsername}` : `telegram:${event.senderId}`,
160
+ recipientAddress: `telegram:${event.chatId}`,
161
+ conversationLabel: `Telegram · ${event.chatTitle}`,
162
+ rawBody: event.text,
163
+ messageId: `${this.agentId}:${event.deliveryId}`,
164
+ timestamp: Date.parse(event.timestamp),
165
+ extraContext: { telegram: {
166
+ chatId: event.chatId,
167
+ chatTitle: event.chatTitle,
168
+ chatKind: event.chatKind,
169
+ senderName: event.senderName,
170
+ readOnly: true
171
+ } },
172
+ deliver: () => Promise.resolve(),
173
+ onRecordError: () => {
174
+ outcome.accepted = false;
175
+ this.logger?.warn("Telegram inbound record was rejected; retaining local delivery");
176
+ },
177
+ onDispatchError: () => {
178
+ outcome.accepted = false;
179
+ this.logger?.warn("Telegram inbound dispatch failed; retaining local delivery");
180
+ }
181
+ });
182
+ if (!outcome.accepted) throw new Error("dispatch_rejected");
183
+ this.dispatchedDeliveryIds.set(event.deliveryId, event.chatId);
184
+ }
185
+ await bridge.request("ack", { deliveryId: event.deliveryId });
186
+ this.dispatchedDeliveryIds.delete(event.deliveryId);
187
+ return;
188
+ } catch {
189
+ this.logger?.warn("Telegram inbound delivery will retry");
190
+ await delay(DELIVERY_RETRY_MS);
191
+ }
192
+ }
193
+ }
194
+ isCurrentGeneration(generation) {
195
+ return this.running && generation === this.generation;
196
+ }
197
+ };
198
+ const runtimesByAgent = /* @__PURE__ */ new Map();
199
+ const bindingsByRuntime = /* @__PURE__ */ new Map();
200
+ var TelegramActivationBinding = class TelegramActivationBinding {
201
+ runtime = null;
202
+ agentId = null;
203
+ activationKey = null;
204
+ ownsStart = false;
205
+ stopped = true;
206
+ lifecycleGeneration = 0;
207
+ resolvingIdentityGeneration = null;
208
+ identityAttempts = 0;
209
+ identityRetryTimer = null;
210
+ async start(api) {
211
+ const retryCycleExhausted = !this.runtime && this.identityAttempts >= MAX_IDENTITY_ATTEMPTS;
212
+ if (!this.stopped && !retryCycleExhausted && (this.runtime || this.resolvingIdentityGeneration === this.lifecycleGeneration || this.identityRetryTimer)) return;
213
+ if (this.stopped || retryCycleExhausted) {
214
+ this.identityAttempts = 0;
215
+ this.lifecycleGeneration += 1;
216
+ }
217
+ this.stopped = false;
218
+ await this.resolveIdentityAndStart(api, this.lifecycleGeneration);
219
+ }
220
+ async resolveIdentityAndStart(api, generation) {
221
+ if (this.stopped || generation !== this.lifecycleGeneration || this.runtime || this.resolvingIdentityGeneration === generation) return;
222
+ this.resolvingIdentityGeneration = generation;
223
+ this.identityAttempts += 1;
224
+ let agentId;
225
+ try {
226
+ const config = (0, _alfe_ai_config.resolveConfig)();
227
+ agentId = requireAgentId((await new _alfe_ai_agent_api_client.AgentApiClient({
228
+ apiKey: config.apiKey,
229
+ apiUrl: config.apiUrl
230
+ }).whoami()).agentId);
231
+ } catch {
232
+ if (this.resolvingIdentityGeneration === generation) this.resolvingIdentityGeneration = null;
233
+ if (generation !== this.lifecycleGeneration) return;
234
+ api.logger.error(this.identityAttempts < MAX_IDENTITY_ATTEMPTS ? "Telegram could not resolve this agent identity; local session startup will retry" : "Telegram could not resolve this agent identity after bounded retries; local session startup is disabled");
235
+ this.scheduleIdentityRetry(api, generation);
236
+ return;
237
+ }
238
+ if (this.resolvingIdentityGeneration === generation) this.resolvingIdentityGeneration = null;
239
+ if (generation !== this.lifecycleGeneration) return;
240
+ const stateDir = telegramStateDir(agentId);
241
+ let runtime = runtimesByAgent.get(agentId);
242
+ if (!runtime) {
243
+ runtime = new TelegramLocalRuntime(agentId, stateDir);
244
+ runtimesByAgent.set(agentId, runtime);
245
+ }
246
+ const activationKey = (0, _alfe_ai_openclaw_plugin_kit.getActivationKey)(`telegram-local-user-session-${agentId}`);
247
+ const ownsStart = (0, _alfe_ai_openclaw_plugin_kit.guardedStart)(activationKey, api.logger, async () => {
248
+ runtime.configure(api);
249
+ await runtime.start();
250
+ });
251
+ this.attachRuntime(runtime, agentId, activationKey, ownsStart);
252
+ }
253
+ async stop() {
254
+ this.stopped = true;
255
+ this.lifecycleGeneration += 1;
256
+ this.resolvingIdentityGeneration = null;
257
+ if (this.identityRetryTimer) {
258
+ clearTimeout(this.identityRetryTimer);
259
+ this.identityRetryTimer = null;
260
+ }
261
+ const runtime = this.runtime;
262
+ const agentId = this.agentId;
263
+ const activationKey = this.activationKey;
264
+ const ownsStart = this.ownsStart;
265
+ this.detachRuntime(runtime);
266
+ if (!ownsStart) return;
267
+ if (runtime) TelegramActivationBinding.invalidateRuntimeBindings(runtime);
268
+ try {
269
+ await runtime?.stop();
270
+ } finally {
271
+ if (agentId && runtimesByAgent.get(agentId) === runtime) runtimesByAgent.delete(agentId);
272
+ if (activationKey) (0, _alfe_ai_openclaw_plugin_kit.resetActivation)(activationKey);
273
+ if (runtime) TelegramActivationBinding.invalidateRuntimeBindings(runtime);
274
+ }
275
+ }
276
+ attachRuntime(runtime, agentId, activationKey, ownsStart) {
277
+ this.runtime = runtime;
278
+ this.agentId = agentId;
279
+ this.activationKey = activationKey;
280
+ this.ownsStart = ownsStart;
281
+ let bindings = bindingsByRuntime.get(runtime);
282
+ if (!bindings) {
283
+ bindings = /* @__PURE__ */ new Set();
284
+ bindingsByRuntime.set(runtime, bindings);
285
+ }
286
+ bindings.add(this);
287
+ }
288
+ detachRuntime(runtime) {
289
+ if (runtime && this.runtime !== runtime) return;
290
+ const attachedRuntime = this.runtime;
291
+ this.runtime = null;
292
+ this.agentId = null;
293
+ this.activationKey = null;
294
+ this.ownsStart = false;
295
+ if (!attachedRuntime) return;
296
+ const bindings = bindingsByRuntime.get(attachedRuntime);
297
+ bindings?.delete(this);
298
+ if (bindings?.size === 0) bindingsByRuntime.delete(attachedRuntime);
299
+ }
300
+ static invalidateRuntimeBindings(runtime) {
301
+ const bindings = bindingsByRuntime.get(runtime);
302
+ if (!bindings) return;
303
+ for (const binding of [...bindings]) binding.detachRuntime(runtime);
304
+ }
305
+ scheduleIdentityRetry(api, generation) {
306
+ if (this.stopped || generation !== this.lifecycleGeneration || this.runtime || this.identityRetryTimer || this.identityAttempts >= MAX_IDENTITY_ATTEMPTS) return;
307
+ this.identityRetryTimer = setTimeout(() => {
308
+ this.identityRetryTimer = null;
309
+ this.resolveIdentityAndStart(api, generation);
310
+ }, IDENTITY_RETRY_MS);
311
+ this.identityRetryTimer.unref();
312
+ }
313
+ status() {
314
+ if (this.runtime) return this.runtime.status();
315
+ return Promise.resolve({
316
+ authorized: false,
317
+ state: "identity_required",
318
+ deliveryMode: "read_only",
319
+ action: "Wait for the local Telegram service to resolve this agent identity, then retry."
320
+ });
321
+ }
322
+ request(method, params = {}) {
323
+ if (!this.runtime) throw (0, _alfe_ai_openclaw_plugin_kit.publicToolError)("Telegram is still resolving this agent identity. Retry telegram_status shortly.");
324
+ return this.runtime.request(method, params);
325
+ }
326
+ };
327
+ const bindingsByApi = /* @__PURE__ */ new WeakMap();
328
+ const plugin = {
329
+ id: "@alfe.ai/openclaw-telegram",
330
+ name: "Telegram (local user session)",
331
+ description: "Explicit local Telegram chat subscriptions through a machine-held MTProto session",
332
+ version: pkg.version,
333
+ activate(api) {
334
+ (0, _alfe_ai_agent_api_client.installToolErrorCapture)(api, { plugin: "openclaw-telegram" });
335
+ const binding = new TelegramActivationBinding();
336
+ bindingsByApi.set(api, binding);
337
+ for (const tool of createTools(binding)) api.registerTool(tool);
338
+ api.registerService({
339
+ id: "telegram-local-user-session",
340
+ start: async () => {
341
+ await binding.start(api);
342
+ },
343
+ stop: async () => {
344
+ await binding.stop();
345
+ }
346
+ });
347
+ api.logger.info("Registered 5 local Telegram tools");
348
+ },
349
+ async deactivate(api) {
350
+ const binding = bindingsByApi.get(api);
351
+ bindingsByApi.delete(api);
352
+ await binding?.stop();
353
+ api.logger.info("Telegram local user-session plugin deactivated");
354
+ }
355
+ };
356
+ function createTools(binding) {
357
+ return [
358
+ (0, _alfe_ai_openclaw_plugin_kit.defineTool)({
359
+ name: "telegram_status",
360
+ description: "Check whether the local Telegram user session is authorized and show subscription/delivery counts.",
361
+ parameters: emptyObjectSchema(),
362
+ handler: () => binding.status()
363
+ }),
364
+ (0, _alfe_ai_openclaw_plugin_kit.defineTool)({
365
+ name: "telegram_list_chats",
366
+ description: "List chats visible to the locally signed-in Telegram account. Use the returned chatId with telegram_subscribe.",
367
+ parameters: {
368
+ type: "object",
369
+ additionalProperties: false,
370
+ properties: {
371
+ offset: {
372
+ type: "integer",
373
+ minimum: 0,
374
+ maximum: 5e3
375
+ },
376
+ limit: {
377
+ type: "integer",
378
+ minimum: 1,
379
+ maximum: 100
380
+ },
381
+ query: {
382
+ type: "string",
383
+ maxLength: 128
384
+ },
385
+ kinds: {
386
+ type: "array",
387
+ maxItems: 3,
388
+ uniqueItems: true,
389
+ items: {
390
+ type: "string",
391
+ enum: [
392
+ "private",
393
+ "group",
394
+ "channel"
395
+ ]
396
+ }
397
+ }
398
+ }
399
+ },
400
+ handler: (params) => binding.request("list_dialogs", normalizeListParams(params))
401
+ }),
402
+ (0, _alfe_ai_openclaw_plugin_kit.defineTool)({
403
+ name: "telegram_list_subscriptions",
404
+ description: "List the Telegram chats whose new text messages currently trigger local agent turns, with pagination.",
405
+ parameters: paginationSchema(),
406
+ handler: (params) => binding.request("list_subscriptions", normalizePagination(params))
407
+ }),
408
+ (0, _alfe_ai_openclaw_plugin_kit.defineTool)({
409
+ name: "telegram_subscribe",
410
+ description: "Subscribe locally to one Telegram chat by chatId. Only do this with the user’s explicit permission and where message processing is allowed.",
411
+ parameters: chatIdSchema(),
412
+ handler: (params) => binding.request("subscribe", { chatId: requireChatId(params) })
413
+ }),
414
+ (0, _alfe_ai_openclaw_plugin_kit.defineTool)({
415
+ name: "telegram_unsubscribe",
416
+ description: "Stop local processing of new messages from one subscribed Telegram chat.",
417
+ parameters: chatIdSchema(),
418
+ handler: (params) => binding.request("unsubscribe", { chatId: requireChatId(params) })
419
+ })
420
+ ];
421
+ }
422
+ function telegramStateDir(agentId, home = (0, node_os.homedir)()) {
423
+ return (0, node_path.join)(home, ".alfe", "agents", requireAgentId(agentId), "telegram");
424
+ }
425
+ function loginCommand(agentId) {
426
+ return `npx -y @alfe.ai/openclaw-telegram@${pkg.version} login --agent-id ${requireAgentId(agentId)}`;
427
+ }
428
+ function requireAgentId(value) {
429
+ if (typeof value !== "string" || value.length === 0 || value.length > MAX_AGENT_ID_CHARS || !SAFE_AGENT_ID.test(value)) throw new Error("Invalid local agent identity");
430
+ return value;
431
+ }
432
+ function emptyObjectSchema() {
433
+ return {
434
+ type: "object",
435
+ additionalProperties: false,
436
+ properties: {}
437
+ };
438
+ }
439
+ function chatIdSchema() {
440
+ return {
441
+ type: "object",
442
+ additionalProperties: false,
443
+ required: ["chatId"],
444
+ properties: { chatId: {
445
+ type: "string",
446
+ minLength: 1,
447
+ maxLength: 128,
448
+ pattern: "^-?[0-9]+$"
449
+ } }
450
+ };
451
+ }
452
+ function paginationSchema() {
453
+ return {
454
+ type: "object",
455
+ additionalProperties: false,
456
+ properties: {
457
+ offset: {
458
+ type: "integer",
459
+ minimum: 0,
460
+ maximum: 5e3
461
+ },
462
+ limit: {
463
+ type: "integer",
464
+ minimum: 1,
465
+ maximum: 100
466
+ }
467
+ }
468
+ };
469
+ }
470
+ function requireChatId(params) {
471
+ const value = params.chatId;
472
+ if (typeof value !== "string" || !/^-?[0-9]+$/.test(value) || value.length > 128) throw (0, _alfe_ai_openclaw_plugin_kit.publicToolError)("chatId must be a Telegram numeric chat ID returned by telegram_list_chats.");
473
+ return value;
474
+ }
475
+ function normalizeListParams(params) {
476
+ const normalized = normalizePagination(params);
477
+ if (params.query !== void 0) {
478
+ if (typeof params.query !== "string" || params.query.length > 128) throw (0, _alfe_ai_openclaw_plugin_kit.publicToolError)("query must be a string of at most 128 characters.");
479
+ normalized.query = params.query;
480
+ }
481
+ if (params.kinds !== void 0) {
482
+ if (!Array.isArray(params.kinds) || params.kinds.some((kind) => kind !== "private" && kind !== "group" && kind !== "channel")) throw (0, _alfe_ai_openclaw_plugin_kit.publicToolError)("kinds may contain only private, group, or channel.");
483
+ normalized.kinds = [...new Set(params.kinds)];
484
+ }
485
+ return normalized;
486
+ }
487
+ function normalizePagination(params) {
488
+ const normalized = {};
489
+ if (params.offset !== void 0) normalized.offset = requireInteger(params.offset, 0, 5e3, "offset");
490
+ if (params.limit !== void 0) normalized.limit = requireInteger(params.limit, 1, 100, "limit");
491
+ return normalized;
492
+ }
493
+ function requireInteger(value, minimum, maximum, name) {
494
+ if (typeof value !== "number" || !Number.isInteger(value) || value < minimum || value > maximum) throw (0, _alfe_ai_openclaw_plugin_kit.publicToolError)(`${name} must be an integer from ${String(minimum)} to ${String(maximum)}.`);
495
+ return value;
496
+ }
497
+ async function delay(milliseconds) {
498
+ await new Promise((resolve) => {
499
+ setTimeout(resolve, milliseconds).unref();
500
+ });
501
+ }
502
+ //#endregion
503
+ module.exports = plugin;
@@ -0,0 +1,58 @@
1
+ import { r as TelegramBridgeLogger } from "./telegram-bridge.cjs";
2
+
3
+ //#region ../openclaw-plugin-kit/dist/index.d.ts
4
+
5
+ //# sourceMappingURL=types.d.ts.map
6
+ //#endregion
7
+ //#region src/tools.d.ts
8
+ /** Shape returned to OpenClaw from a tool `execute`. */
9
+ interface ToolResult {
10
+ content: {
11
+ type: "text";
12
+ text: string;
13
+ }[];
14
+ details: unknown;
15
+ isError?: boolean;
16
+ }
17
+ interface ToolDef<TParameters = unknown> {
18
+ name: string;
19
+ description: string;
20
+ label: string;
21
+ parameters: TParameters;
22
+ execute: (toolCallId: string, params: Record<string, unknown>) => Promise<ToolResult>;
23
+ }
24
+ /** Deliberately model-safe validation/usage failure. Other exceptions stay private. */
25
+ //#endregion
26
+ //#region src/plugin.d.ts
27
+ interface PluginRuntime {
28
+ config: {
29
+ loadConfig(): Record<string, unknown>;
30
+ };
31
+ channel: unknown;
32
+ }
33
+ interface PluginServiceContext {
34
+ logger: PluginLogger;
35
+ stateDir: string;
36
+ config: Record<string, unknown>;
37
+ }
38
+ type PluginLogger = TelegramBridgeLogger;
39
+ interface PluginApi {
40
+ logger: PluginLogger;
41
+ runtime?: PluginRuntime;
42
+ registerTool(tool: ToolDef): void;
43
+ registerService(service: {
44
+ id: string;
45
+ start(ctx: PluginServiceContext): void | Promise<void>;
46
+ stop?(ctx: PluginServiceContext): void | Promise<void>;
47
+ }): void;
48
+ }
49
+ declare const plugin: {
50
+ id: string;
51
+ name: string;
52
+ description: string;
53
+ version: string;
54
+ activate(api: PluginApi): void;
55
+ deactivate(api: PluginApi): Promise<void>;
56
+ };
57
+ //#endregion
58
+ export { plugin as default };
@@ -0,0 +1,58 @@
1
+ import { r as TelegramBridgeLogger } from "./telegram-bridge.js";
2
+
3
+ //#region ../openclaw-plugin-kit/dist/index.d.ts
4
+
5
+ //# sourceMappingURL=types.d.ts.map
6
+ //#endregion
7
+ //#region src/tools.d.ts
8
+ /** Shape returned to OpenClaw from a tool `execute`. */
9
+ interface ToolResult {
10
+ content: {
11
+ type: "text";
12
+ text: string;
13
+ }[];
14
+ details: unknown;
15
+ isError?: boolean;
16
+ }
17
+ interface ToolDef<TParameters = unknown> {
18
+ name: string;
19
+ description: string;
20
+ label: string;
21
+ parameters: TParameters;
22
+ execute: (toolCallId: string, params: Record<string, unknown>) => Promise<ToolResult>;
23
+ }
24
+ /** Deliberately model-safe validation/usage failure. Other exceptions stay private. */
25
+ //#endregion
26
+ //#region src/plugin.d.ts
27
+ interface PluginRuntime {
28
+ config: {
29
+ loadConfig(): Record<string, unknown>;
30
+ };
31
+ channel: unknown;
32
+ }
33
+ interface PluginServiceContext {
34
+ logger: PluginLogger;
35
+ stateDir: string;
36
+ config: Record<string, unknown>;
37
+ }
38
+ type PluginLogger = TelegramBridgeLogger;
39
+ interface PluginApi {
40
+ logger: PluginLogger;
41
+ runtime?: PluginRuntime;
42
+ registerTool(tool: ToolDef): void;
43
+ registerService(service: {
44
+ id: string;
45
+ start(ctx: PluginServiceContext): void | Promise<void>;
46
+ stop?(ctx: PluginServiceContext): void | Promise<void>;
47
+ }): void;
48
+ }
49
+ declare const plugin: {
50
+ id: string;
51
+ name: string;
52
+ description: string;
53
+ version: string;
54
+ activate(api: PluginApi): void;
55
+ deactivate(api: PluginApi): Promise<void>;
56
+ };
57
+ //#endregion
58
+ export { plugin as default };