opc-agent 1.3.2 → 2.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 (226) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +20 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +14 -0
  3. package/.github/PULL_REQUEST_TEMPLATE.md +13 -0
  4. package/.github/workflows/ci.yml +24 -0
  5. package/CHANGELOG.md +48 -63
  6. package/CONTRIBUTING.md +21 -60
  7. package/README.md +284 -348
  8. package/README.zh-CN.md +415 -415
  9. package/dist/channels/slack.js +93 -10
  10. package/dist/channels/telegram.d.ts +30 -9
  11. package/dist/channels/telegram.js +125 -33
  12. package/dist/channels/web.d.ts +10 -0
  13. package/dist/channels/web.js +33 -2
  14. package/dist/cli.js +667 -65
  15. package/dist/core/agent.d.ts +23 -0
  16. package/dist/core/agent.js +120 -3
  17. package/dist/core/runtime.d.ts +5 -0
  18. package/dist/core/runtime.js +71 -0
  19. package/dist/core/scheduler.d.ts +52 -0
  20. package/dist/core/scheduler.js +168 -0
  21. package/dist/core/subagent.d.ts +28 -0
  22. package/dist/core/subagent.js +65 -0
  23. package/dist/daemon.d.ts +3 -0
  24. package/dist/daemon.js +134 -0
  25. package/dist/deploy/hermes.js +22 -22
  26. package/dist/deploy/openclaw.js +31 -40
  27. package/dist/index.d.ts +10 -10
  28. package/dist/index.js +22 -15
  29. package/dist/providers/index.d.ts +6 -2
  30. package/dist/providers/index.js +22 -9
  31. package/dist/schema/oad.d.ts +180 -6
  32. package/dist/schema/oad.js +12 -1
  33. package/dist/skills/auto-learn.d.ts +28 -0
  34. package/dist/skills/auto-learn.js +257 -0
  35. package/dist/templates/code-reviewer.d.ts +0 -8
  36. package/dist/templates/code-reviewer.js +5 -9
  37. package/dist/templates/customer-service.d.ts +0 -8
  38. package/dist/templates/customer-service.js +2 -6
  39. package/dist/templates/data-analyst.d.ts +0 -8
  40. package/dist/templates/data-analyst.js +5 -9
  41. package/dist/templates/knowledge-base.d.ts +0 -8
  42. package/dist/templates/knowledge-base.js +2 -6
  43. package/dist/templates/sales-assistant.d.ts +0 -8
  44. package/dist/templates/sales-assistant.js +4 -8
  45. package/dist/templates/teacher.d.ts +0 -8
  46. package/dist/templates/teacher.js +6 -10
  47. package/dist/tools/builtin/datetime.d.ts +3 -0
  48. package/dist/tools/builtin/datetime.js +44 -0
  49. package/dist/tools/builtin/file.d.ts +3 -0
  50. package/dist/tools/builtin/file.js +151 -0
  51. package/dist/tools/builtin/index.d.ts +15 -0
  52. package/dist/tools/builtin/index.js +30 -0
  53. package/dist/tools/builtin/shell.d.ts +3 -0
  54. package/dist/tools/builtin/shell.js +43 -0
  55. package/dist/tools/builtin/web.d.ts +3 -0
  56. package/dist/tools/builtin/web.js +37 -0
  57. package/dist/tools/mcp-client.d.ts +24 -0
  58. package/dist/tools/mcp-client.js +119 -0
  59. package/dist/traces/index.d.ts +49 -0
  60. package/dist/traces/index.js +102 -0
  61. package/docs/.vitepress/config.ts +103 -103
  62. package/docs/api/cli.md +48 -48
  63. package/docs/api/oad-schema.md +64 -64
  64. package/docs/api/sdk.md +80 -80
  65. package/docs/guide/concepts.md +51 -51
  66. package/docs/guide/configuration.md +79 -79
  67. package/docs/guide/deployment.md +42 -42
  68. package/docs/guide/getting-started.md +44 -44
  69. package/docs/guide/templates.md +28 -28
  70. package/docs/guide/testing.md +84 -84
  71. package/docs/index.md +27 -27
  72. package/docs/zh/api/cli.md +54 -54
  73. package/docs/zh/api/oad-schema.md +87 -87
  74. package/docs/zh/api/sdk.md +102 -102
  75. package/docs/zh/guide/concepts.md +104 -104
  76. package/docs/zh/guide/configuration.md +135 -135
  77. package/docs/zh/guide/deployment.md +81 -81
  78. package/docs/zh/guide/getting-started.md +82 -82
  79. package/docs/zh/guide/templates.md +84 -84
  80. package/docs/zh/guide/testing.md +88 -88
  81. package/docs/zh/index.md +27 -27
  82. package/examples/README.md +22 -0
  83. package/examples/basic-agent.ts +90 -0
  84. package/examples/brain-integration.ts +71 -0
  85. package/examples/customer-service-demo/README.md +90 -90
  86. package/examples/customer-service-demo/oad.yaml +107 -107
  87. package/examples/multi-channel.ts +74 -0
  88. package/package.json +1 -1
  89. package/src/analytics/index.ts +66 -66
  90. package/src/channels/discord.ts +192 -192
  91. package/src/channels/email.ts +177 -177
  92. package/src/channels/feishu.ts +236 -236
  93. package/src/channels/index.ts +15 -15
  94. package/src/channels/slack.ts +217 -160
  95. package/src/channels/telegram.ts +155 -33
  96. package/src/channels/voice.ts +106 -106
  97. package/src/channels/web.ts +38 -2
  98. package/src/channels/webhook.ts +199 -199
  99. package/src/channels/websocket.ts +87 -87
  100. package/src/channels/wechat.ts +149 -149
  101. package/src/cli.ts +697 -63
  102. package/src/core/a2a.ts +143 -143
  103. package/src/core/agent.ts +146 -3
  104. package/src/core/analytics-engine.ts +186 -186
  105. package/src/core/auth.ts +57 -57
  106. package/src/core/cache.ts +141 -141
  107. package/src/core/compose.ts +77 -77
  108. package/src/core/config.ts +14 -14
  109. package/src/core/errors.ts +148 -148
  110. package/src/core/hitl.ts +138 -138
  111. package/src/core/logger.ts +57 -57
  112. package/src/core/orchestrator.ts +215 -215
  113. package/src/core/performance.ts +187 -187
  114. package/src/core/rate-limiter.ts +128 -128
  115. package/src/core/room.ts +109 -109
  116. package/src/core/runtime.ts +230 -152
  117. package/src/core/sandbox.ts +101 -101
  118. package/src/core/scheduler.ts +187 -0
  119. package/src/core/security.ts +171 -171
  120. package/src/core/subagent.ts +98 -0
  121. package/src/core/types.ts +68 -68
  122. package/src/core/versioning.ts +106 -106
  123. package/src/core/watch.ts +178 -178
  124. package/src/core/workflow.ts +235 -235
  125. package/src/daemon.ts +96 -0
  126. package/src/deploy/hermes.ts +156 -156
  127. package/src/deploy/openclaw.ts +190 -200
  128. package/src/i18n/index.ts +216 -216
  129. package/src/index.ts +14 -10
  130. package/src/memory/deepbrain.ts +108 -108
  131. package/src/memory/index.ts +34 -34
  132. package/src/plugins/index.ts +208 -208
  133. package/src/providers/index.ts +354 -331
  134. package/src/schema/oad.ts +14 -2
  135. package/src/skills/auto-learn.ts +262 -0
  136. package/src/skills/base.ts +16 -16
  137. package/src/skills/document.ts +100 -100
  138. package/src/skills/http.ts +35 -35
  139. package/src/skills/index.ts +27 -27
  140. package/src/skills/scheduler.ts +80 -80
  141. package/src/skills/webhook-trigger.ts +59 -59
  142. package/src/templates/code-reviewer.ts +30 -34
  143. package/src/templates/customer-service.ts +76 -80
  144. package/src/templates/data-analyst.ts +66 -70
  145. package/src/templates/executive-assistant.ts +71 -71
  146. package/src/templates/financial-advisor.ts +60 -60
  147. package/src/templates/knowledge-base.ts +27 -31
  148. package/src/templates/legal-assistant.ts +71 -71
  149. package/src/templates/sales-assistant.ts +75 -79
  150. package/src/templates/teacher.ts +75 -79
  151. package/src/testing/index.ts +181 -181
  152. package/src/tools/builtin/datetime.ts +41 -0
  153. package/src/tools/builtin/file.ts +107 -0
  154. package/src/tools/builtin/index.ts +28 -0
  155. package/src/tools/builtin/shell.ts +43 -0
  156. package/src/tools/builtin/web.ts +35 -0
  157. package/src/tools/calculator.ts +73 -73
  158. package/src/tools/datetime.ts +149 -149
  159. package/src/tools/json-transform.ts +187 -187
  160. package/src/tools/mcp-client.ts +131 -0
  161. package/src/tools/mcp.ts +76 -76
  162. package/src/tools/text-analysis.ts +116 -116
  163. package/src/traces/index.ts +132 -0
  164. package/templates/Dockerfile +15 -15
  165. package/templates/code-reviewer/README.md +27 -27
  166. package/templates/code-reviewer/oad.yaml +41 -41
  167. package/templates/customer-service/README.md +22 -22
  168. package/templates/customer-service/oad.yaml +36 -36
  169. package/templates/docker-compose.yml +21 -21
  170. package/templates/ecommerce-assistant/README.md +45 -45
  171. package/templates/ecommerce-assistant/oad.yaml +47 -47
  172. package/templates/knowledge-base/README.md +28 -28
  173. package/templates/knowledge-base/oad.yaml +38 -38
  174. package/templates/sales-assistant/README.md +26 -26
  175. package/templates/sales-assistant/oad.yaml +43 -43
  176. package/templates/tech-support/README.md +43 -43
  177. package/templates/tech-support/oad.yaml +45 -45
  178. package/test-agent/Dockerfile +9 -0
  179. package/test-agent/README.md +50 -0
  180. package/test-agent/agent.yaml +23 -0
  181. package/test-agent/docker-compose.yml +11 -0
  182. package/test-agent/oad.yaml +31 -0
  183. package/test-agent/package-lock.json +1492 -0
  184. package/test-agent/package.json +18 -0
  185. package/test-agent/src/index.ts +24 -0
  186. package/test-agent/src/skills/echo.ts +15 -0
  187. package/test-agent/tsconfig.json +25 -0
  188. package/tests/a2a.test.ts +66 -66
  189. package/tests/agent.test.ts +72 -72
  190. package/tests/analytics.test.ts +50 -50
  191. package/tests/auto-learn.test.ts +105 -0
  192. package/tests/builtin-tools.test.ts +83 -0
  193. package/tests/channel.test.ts +39 -39
  194. package/tests/cli.test.ts +46 -0
  195. package/tests/e2e.test.ts +134 -134
  196. package/tests/errors.test.ts +83 -83
  197. package/tests/hitl.test.ts +71 -71
  198. package/tests/i18n.test.ts +41 -41
  199. package/tests/mcp.test.ts +54 -54
  200. package/tests/oad.test.ts +68 -68
  201. package/tests/performance.test.ts +115 -115
  202. package/tests/plugin.test.ts +74 -74
  203. package/tests/room.test.ts +106 -106
  204. package/tests/runtime.test.ts +42 -42
  205. package/tests/sandbox.test.ts +46 -46
  206. package/tests/security.test.ts +60 -60
  207. package/tests/subagent.test.ts +130 -0
  208. package/tests/telegram-discord.test.ts +60 -0
  209. package/tests/templates.test.ts +77 -77
  210. package/tests/v070.test.ts +76 -76
  211. package/tests/versioning.test.ts +75 -75
  212. package/tests/voice.test.ts +61 -61
  213. package/tests/webhook.test.ts +29 -29
  214. package/tests/workflow.test.ts +143 -143
  215. package/tsconfig.json +19 -19
  216. package/vitest.config.ts +9 -9
  217. package/dist/core/dashboard.d.ts +0 -35
  218. package/dist/core/dashboard.js +0 -157
  219. package/dist/core/priority.d.ts +0 -52
  220. package/dist/core/priority.js +0 -102
  221. package/src/core/dashboard.ts +0 -219
  222. package/src/core/priority.ts +0 -140
  223. package/src/dtv/data.ts +0 -29
  224. package/src/dtv/trust.ts +0 -43
  225. package/src/dtv/value.ts +0 -47
  226. package/src/marketplace/index.ts +0 -223
@@ -1,4 +1,37 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
3
36
  exports.SlackChannel = void 0;
4
37
  const index_1 = require("./index");
@@ -37,9 +70,51 @@ class SlackChannel extends index_1.BaseChannel {
37
70
  }
38
71
  /** Start Events API HTTP server */
39
72
  async startEventsAPI() {
40
- // TODO: Implement with express or http
41
- // const port = this.config.port ?? 3001;
42
- // Listen for POST /slack/events and /slack/commands
73
+ const http = await Promise.resolve().then(() => __importStar(require('http')));
74
+ const port = this.config.port ?? 3001;
75
+ const server = http.createServer(async (req, res) => {
76
+ if (req.method !== 'POST') {
77
+ res.writeHead(404);
78
+ res.end();
79
+ return;
80
+ }
81
+ const chunks = [];
82
+ for await (const chunk of req)
83
+ chunks.push(chunk);
84
+ const body = JSON.parse(Buffer.concat(chunks).toString());
85
+ // URL verification challenge
86
+ if (body.type === 'url_verification') {
87
+ res.writeHead(200, { 'Content-Type': 'application/json' });
88
+ res.end(JSON.stringify({ challenge: body.challenge }));
89
+ return;
90
+ }
91
+ // Event callback
92
+ if (body.type === 'event_callback' && body.event) {
93
+ const event = body.event;
94
+ if (event.type === 'message' || event.type === 'app_mention') {
95
+ // Don't block the HTTP response
96
+ this.handleMessage(event).catch(() => { });
97
+ }
98
+ }
99
+ // Slash commands (form-urlencoded, but we handle JSON for simplicity)
100
+ if (req.url === '/slack/commands' && body.command) {
101
+ const reply = await this.handleSlashCommand({
102
+ command: body.command,
103
+ text: body.text ?? '',
104
+ userId: body.user_id,
105
+ channelId: body.channel_id,
106
+ triggerId: body.trigger_id,
107
+ });
108
+ res.writeHead(200, { 'Content-Type': 'application/json' });
109
+ res.end(JSON.stringify({ response_type: 'ephemeral', text: reply }));
110
+ return;
111
+ }
112
+ res.writeHead(200);
113
+ res.end('ok');
114
+ });
115
+ server.listen(port, () => {
116
+ console.log(`[SlackChannel] Events API listening on port ${port}`);
117
+ });
43
118
  }
44
119
  /** Handle incoming Slack message */
45
120
  async handleMessage(event) {
@@ -94,13 +169,21 @@ class SlackChannel extends index_1.BaseChannel {
94
169
  }
95
170
  /** Send a message to a Slack channel */
96
171
  async sendMessage(channel, text, threadTs) {
97
- // TODO: Implement with @slack/web-api
98
- // const { WebClient } = await import('@slack/web-api');
99
- // const client = new WebClient(this.config.botToken);
100
- // await client.chat.postMessage({ channel, text, thread_ts: threadTs });
101
- void channel;
102
- void text;
103
- void threadTs;
172
+ const body = { channel, text };
173
+ if (threadTs)
174
+ body.thread_ts = threadTs;
175
+ const res = await fetch('https://slack.com/api/chat.postMessage', {
176
+ method: 'POST',
177
+ headers: {
178
+ 'Authorization': `Bearer ${this.config.botToken}`,
179
+ 'Content-Type': 'application/json',
180
+ },
181
+ body: JSON.stringify(body),
182
+ });
183
+ const data = await res.json();
184
+ if (!data.ok) {
185
+ console.error(`[SlackChannel] chat.postMessage failed: ${data.error}`);
186
+ }
104
187
  }
105
188
  }
106
189
  exports.SlackChannel = SlackChannel;
@@ -1,21 +1,42 @@
1
1
  import { BaseChannel } from './index';
2
2
  /**
3
- * Telegram channel — basic webhook handler for Telegram Bot API.
4
- * Set TELEGRAM_BOT_TOKEN env var or pass in config.
3
+ * Telegram channel — supports both long-polling and webhook modes.
4
+ *
5
+ * Config:
6
+ * token: bot token (or TELEGRAM_BOT_TOKEN env var)
7
+ * mode: 'polling' | 'webhook' (default: 'polling')
8
+ * webhookUrl: required for webhook mode
9
+ * port: webhook server port (default: 3001)
10
+ *
11
+ * Polling mode requires no public URL — ideal for dev/local.
12
+ * Webhook mode is more efficient for production.
5
13
  */
14
+ export interface TelegramChannelConfig {
15
+ token?: string;
16
+ mode?: 'polling' | 'webhook';
17
+ webhookUrl?: string;
18
+ port?: number;
19
+ }
6
20
  export declare class TelegramChannel extends BaseChannel {
7
21
  readonly type = "telegram";
8
22
  private token;
23
+ private mode;
9
24
  private webhookUrl?;
10
- private server;
11
25
  private port;
12
- constructor(options?: {
13
- token?: string;
14
- webhookUrl?: string;
15
- port?: number;
16
- });
26
+ private offset;
27
+ private polling;
28
+ private server;
29
+ constructor(config?: TelegramChannelConfig);
17
30
  start(): Promise<void>;
18
31
  stop(): Promise<void>;
19
- private sendMessage;
32
+ private startPolling;
33
+ private poll;
34
+ private getUpdates;
35
+ private startWebhook;
36
+ private stopWebhook;
37
+ private processUpdate;
38
+ sendMessage(chatId: number | string, text: string): Promise<void>;
39
+ private apiCall;
40
+ private splitText;
20
41
  }
21
42
  //# sourceMappingURL=telegram.d.ts.map
@@ -35,58 +35,105 @@ var __importStar = (this && this.__importStar) || (function () {
35
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
36
  exports.TelegramChannel = void 0;
37
37
  const index_1 = require("./index");
38
- /**
39
- * Telegram channel — basic webhook handler for Telegram Bot API.
40
- * Set TELEGRAM_BOT_TOKEN env var or pass in config.
41
- */
42
38
  class TelegramChannel extends index_1.BaseChannel {
43
39
  type = 'telegram';
44
40
  token;
41
+ mode;
45
42
  webhookUrl;
46
- server = null;
47
43
  port;
48
- constructor(options = {}) {
44
+ // Polling state
45
+ offset = 0;
46
+ polling = false;
47
+ // Webhook state
48
+ server = null;
49
+ constructor(config = {}) {
49
50
  super();
50
- this.token = options.token ?? process.env.TELEGRAM_BOT_TOKEN ?? '';
51
- this.webhookUrl = options.webhookUrl;
52
- this.port = options.port ?? 3001;
51
+ this.token = config.token ?? process.env.TELEGRAM_BOT_TOKEN ?? '';
52
+ this.mode = config.mode ?? 'polling';
53
+ this.webhookUrl = config.webhookUrl;
54
+ this.port = config.port ?? 3001;
53
55
  }
54
56
  async start() {
55
57
  if (!this.token) {
56
58
  console.warn('[TelegramChannel] No bot token provided. Set TELEGRAM_BOT_TOKEN or pass token in config.');
57
59
  return;
58
60
  }
61
+ if (this.mode === 'webhook') {
62
+ await this.startWebhook();
63
+ }
64
+ else {
65
+ await this.startPolling();
66
+ }
67
+ }
68
+ async stop() {
69
+ if (this.mode === 'webhook') {
70
+ await this.stopWebhook();
71
+ }
72
+ else {
73
+ this.polling = false;
74
+ }
75
+ }
76
+ // ─── Polling Mode ────────────────────────────────────────
77
+ async startPolling() {
78
+ // Delete any existing webhook so polling works
79
+ await this.apiCall('deleteWebhook');
80
+ console.log(`[TelegramChannel] Started long-polling mode`);
81
+ this.polling = true;
82
+ this.poll();
83
+ }
84
+ async poll() {
85
+ while (this.polling) {
86
+ try {
87
+ const updates = await this.getUpdates();
88
+ for (const update of updates) {
89
+ await this.processUpdate(update);
90
+ }
91
+ }
92
+ catch (err) {
93
+ console.error('[TelegramChannel] Polling error:', err);
94
+ // Back off on error
95
+ if (this.polling) {
96
+ await new Promise((r) => setTimeout(r, 5000));
97
+ }
98
+ }
99
+ }
100
+ }
101
+ async getUpdates() {
102
+ const url = `https://api.telegram.org/bot${this.token}/getUpdates?offset=${this.offset}&timeout=30&allowed_updates=["message"]`;
103
+ const controller = new AbortController();
104
+ const timeout = setTimeout(() => controller.abort(), 40000); // 30s long-poll + 10s buffer
105
+ try {
106
+ const res = await fetch(url, { signal: controller.signal });
107
+ const data = (await res.json());
108
+ if (data.ok && data.result.length > 0) {
109
+ this.offset = data.result[data.result.length - 1].update_id + 1;
110
+ }
111
+ return data.result || [];
112
+ }
113
+ finally {
114
+ clearTimeout(timeout);
115
+ }
116
+ }
117
+ // ─── Webhook Mode ────────────────────────────────────────
118
+ async startWebhook() {
119
+ if (this.webhookUrl) {
120
+ await this.apiCall('setWebhook', { url: `${this.webhookUrl}/webhook/${this.token}` });
121
+ }
59
122
  const express = (await Promise.resolve().then(() => __importStar(require('express')))).default;
60
123
  const app = express();
61
124
  app.use(express.json());
62
125
  app.post(`/webhook/${this.token}`, async (req, res) => {
63
126
  try {
64
- const update = req.body;
65
- if (update.message?.text && this.handler) {
66
- const msg = {
67
- id: `tg_${update.message.message_id}`,
68
- role: 'user',
69
- content: update.message.text,
70
- timestamp: update.message.date * 1000,
71
- metadata: {
72
- sessionId: `tg_${update.message.chat.id}`,
73
- chatId: update.message.chat.id,
74
- userId: update.message.from?.id,
75
- platform: 'telegram',
76
- },
77
- };
78
- const response = await this.handler(msg);
79
- await this.sendMessage(update.message.chat.id, response.content);
80
- }
127
+ await this.processUpdate(req.body);
81
128
  res.json({ ok: true });
82
129
  }
83
130
  catch (err) {
84
- console.error('[TelegramChannel] Error handling update:', err);
131
+ console.error('[TelegramChannel] Webhook error:', err);
85
132
  res.status(500).json({ error: 'Internal error' });
86
133
  }
87
134
  });
88
135
  app.get('/health', (_req, res) => {
89
- res.json({ status: 'ok', channel: 'telegram' });
136
+ res.json({ status: 'ok', channel: 'telegram', mode: 'webhook' });
90
137
  });
91
138
  return new Promise((resolve) => {
92
139
  this.server = app.listen(this.port, () => {
@@ -95,25 +142,70 @@ class TelegramChannel extends index_1.BaseChannel {
95
142
  });
96
143
  });
97
144
  }
98
- async stop() {
145
+ async stopWebhook() {
99
146
  return new Promise((resolve, reject) => {
100
147
  if (!this.server)
101
148
  return resolve();
102
149
  this.server.close((err) => (err ? reject(err) : resolve()));
103
150
  });
104
151
  }
152
+ // ─── Shared ──────────────────────────────────────────────
153
+ async processUpdate(update) {
154
+ const message = update.message || update.edited_message;
155
+ if (!message?.text || !this.handler)
156
+ return;
157
+ const msg = {
158
+ id: `tg_${message.message_id}`,
159
+ role: 'user',
160
+ content: message.text,
161
+ timestamp: message.date * 1000,
162
+ metadata: {
163
+ sessionId: `tg_${message.chat.id}`,
164
+ chatId: message.chat.id,
165
+ userId: message.from?.id,
166
+ username: message.from?.username,
167
+ firstName: message.from?.first_name,
168
+ platform: 'telegram',
169
+ chatType: message.chat.type,
170
+ },
171
+ };
172
+ const response = await this.handler(msg);
173
+ await this.sendMessage(message.chat.id, response.content);
174
+ }
105
175
  async sendMessage(chatId, text) {
106
- const url = `https://api.telegram.org/bot${this.token}/sendMessage`;
176
+ // Telegram max message length is 4096
177
+ const chunks = this.splitText(text, 4096);
178
+ for (const chunk of chunks) {
179
+ await this.apiCall('sendMessage', {
180
+ chat_id: chatId,
181
+ text: chunk,
182
+ parse_mode: 'Markdown',
183
+ });
184
+ }
185
+ }
186
+ async apiCall(method, body) {
187
+ const url = `https://api.telegram.org/bot${this.token}/${method}`;
107
188
  try {
108
- await fetch(url, {
189
+ const res = await fetch(url, {
109
190
  method: 'POST',
110
191
  headers: { 'Content-Type': 'application/json' },
111
- body: JSON.stringify({ chat_id: chatId, text, parse_mode: 'Markdown' }),
192
+ body: body ? JSON.stringify(body) : undefined,
112
193
  });
194
+ return await res.json();
113
195
  }
114
196
  catch (err) {
115
- console.error('[TelegramChannel] Failed to send message:', err);
197
+ console.error(`[TelegramChannel] API call ${method} failed:`, err);
198
+ throw err;
199
+ }
200
+ }
201
+ splitText(text, maxLen) {
202
+ if (text.length <= maxLen)
203
+ return [text];
204
+ const parts = [];
205
+ for (let i = 0; i < text.length; i += maxLen) {
206
+ parts.push(text.slice(i, i + maxLen));
116
207
  }
208
+ return parts;
117
209
  }
118
210
  }
119
211
  exports.TelegramChannel = TelegramChannel;
@@ -9,6 +9,11 @@ export declare class WebChannel extends BaseChannel {
9
9
  private port;
10
10
  private streamHandler;
11
11
  private agentName;
12
+ private agentVersion;
13
+ private memoryType;
14
+ private skillNames;
15
+ private channelNames;
16
+ private analyticsProvider;
12
17
  private currentProvider;
13
18
  private stats;
14
19
  private eventHandlers;
@@ -23,6 +28,11 @@ export declare class WebChannel extends BaseChannel {
23
28
  trackSession(): void;
24
29
  constructor(port?: number, authConfig?: AuthConfig);
25
30
  setAgentName(name: string): void;
31
+ setAgentVersion(version: string): void;
32
+ setMemoryType(type: string): void;
33
+ setSkillNames(names: string[]): void;
34
+ setChannelNames(names: string[]): void;
35
+ setAnalyticsProvider(fn: () => any): void;
26
36
  onStreamMessage(handler: (msg: Message, res: Response) => Promise<void>): void;
27
37
  private setupRoutes;
28
38
  start(): Promise<void>;
@@ -286,6 +286,11 @@ class WebChannel extends index_1.BaseChannel {
286
286
  port;
287
287
  streamHandler = null;
288
288
  agentName = 'OPC Agent';
289
+ agentVersion = '1.0.0';
290
+ memoryType = 'in-memory';
291
+ skillNames = [];
292
+ channelNames = ['web'];
293
+ analyticsProvider = null;
289
294
  currentProvider = 'openai';
290
295
  stats = { sessions: 0, messages: 0, totalResponseMs: 0, tokenUsage: 0, knowledgeFiles: 0, startedAt: Date.now(), errors: 0 };
291
296
  eventHandlers = new Map();
@@ -326,6 +331,21 @@ class WebChannel extends index_1.BaseChannel {
326
331
  setAgentName(name) {
327
332
  this.agentName = name;
328
333
  }
334
+ setAgentVersion(version) {
335
+ this.agentVersion = version;
336
+ }
337
+ setMemoryType(type) {
338
+ this.memoryType = type;
339
+ }
340
+ setSkillNames(names) {
341
+ this.skillNames = names;
342
+ }
343
+ setChannelNames(names) {
344
+ this.channelNames = names;
345
+ }
346
+ setAnalyticsProvider(fn) {
347
+ this.analyticsProvider = fn;
348
+ }
329
349
  onStreamMessage(handler) {
330
350
  this.streamHandler = handler;
331
351
  }
@@ -334,7 +354,17 @@ class WebChannel extends index_1.BaseChannel {
334
354
  res.type('html').send(CHAT_HTML);
335
355
  });
336
356
  this.app.get('/health', (_req, res) => {
337
- res.json({ status: 'ok', timestamp: Date.now() });
357
+ res.json({
358
+ status: 'ok',
359
+ agent: this.agentName,
360
+ version: this.agentVersion,
361
+ uptime: Date.now() - this.stats.startedAt,
362
+ memory: this.memoryType,
363
+ skills: this.skillNames,
364
+ channels: this.channelNames,
365
+ analytics: this.analyticsProvider ? this.analyticsProvider() : null,
366
+ timestamp: Date.now(),
367
+ });
338
368
  });
339
369
  this.app.get('/api/info', (_req, res) => {
340
370
  res.json({ name: this.agentName });
@@ -408,7 +438,8 @@ class WebChannel extends index_1.BaseChannel {
408
438
  res.type('html').send(DASHBOARD_HTML);
409
439
  });
410
440
  this.app.get('/api/dashboard', (_req, res) => {
411
- res.json(this.stats);
441
+ const analytics = this.analyticsProvider ? this.analyticsProvider() : null;
442
+ res.json({ ...this.stats, analytics });
412
443
  });
413
444
  // --- Knowledge Base Upload ---
414
445
  this.app.post('/api/kb/upload', async (req, res) => {