@cmdop/bot 2026.2.26 → 2026.2.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +6 -0
- package/dist/index.cjs +281 -170
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +100 -63
- package/dist/index.d.ts +100 -63
- package/dist/index.js +281 -170
- package/dist/index.js.map +1 -1
- package/package.json +5 -3
package/README.md
CHANGED
|
@@ -279,6 +279,12 @@ All errors extend `BotError` and expose a `code` string:
|
|
|
279
279
|
- `@cmdop/node` (peer dependency, installed automatically)
|
|
280
280
|
- Platform libraries are **optional peer dependencies** — install only what you use
|
|
281
281
|
|
|
282
|
+
## Links
|
|
283
|
+
|
|
284
|
+
- [Homepage](https://cmdop.com/sdk/python/bot)
|
|
285
|
+
- [Documentation](https://cmdop.com/docs/sdk/node/bot)
|
|
286
|
+
- [npm](https://www.npmjs.com/package/@cmdop/bot)
|
|
287
|
+
|
|
282
288
|
## License
|
|
283
289
|
|
|
284
290
|
MIT
|
package/dist/index.cjs
CHANGED
|
@@ -5,6 +5,7 @@ var grammy = require('grammy');
|
|
|
5
5
|
var discord_js = require('discord.js');
|
|
6
6
|
var bolt = require('@slack/bolt');
|
|
7
7
|
var node = require('@cmdop/node');
|
|
8
|
+
var consola = require('consola');
|
|
8
9
|
|
|
9
10
|
var __create = Object.create;
|
|
10
11
|
var __defProp = Object.defineProperty;
|
|
@@ -161,6 +162,95 @@ var init_errors = __esm({
|
|
|
161
162
|
}
|
|
162
163
|
});
|
|
163
164
|
|
|
165
|
+
// src/models/command.ts
|
|
166
|
+
var command_exports = {};
|
|
167
|
+
__export(command_exports, {
|
|
168
|
+
ParsedCommandSchema: () => exports.ParsedCommandSchema,
|
|
169
|
+
parseCommand: () => parseCommand
|
|
170
|
+
});
|
|
171
|
+
function parseCommand(text) {
|
|
172
|
+
const trimmed = text.trim();
|
|
173
|
+
const match = /^[/!](\w+)(?:\s+(.*))?$/s.exec(trimmed);
|
|
174
|
+
if (!match) return null;
|
|
175
|
+
const name = (match[1] ?? "").toLowerCase();
|
|
176
|
+
const rest = (match[2] ?? "").trim();
|
|
177
|
+
const args = rest ? rest.split(/\s+/) : [];
|
|
178
|
+
return exports.ParsedCommandSchema.parse({ name, args, rawText: trimmed });
|
|
179
|
+
}
|
|
180
|
+
exports.ParsedCommandSchema = void 0;
|
|
181
|
+
var init_command = __esm({
|
|
182
|
+
"src/models/command.ts"() {
|
|
183
|
+
exports.ParsedCommandSchema = v4.z.object({
|
|
184
|
+
name: v4.z.string().min(1),
|
|
185
|
+
args: v4.z.array(v4.z.string()),
|
|
186
|
+
rawText: v4.z.string()
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// src/core/base-channel.ts
|
|
192
|
+
exports.BaseChannel = void 0;
|
|
193
|
+
var init_base_channel = __esm({
|
|
194
|
+
"src/core/base-channel.ts"() {
|
|
195
|
+
init_command();
|
|
196
|
+
init_errors();
|
|
197
|
+
exports.BaseChannel = class {
|
|
198
|
+
constructor(id, name, permissions, dispatcher, logger) {
|
|
199
|
+
this.id = id;
|
|
200
|
+
this.name = name;
|
|
201
|
+
this.permissions = permissions;
|
|
202
|
+
this.dispatcher = dispatcher;
|
|
203
|
+
this.logger = logger;
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* Process an incoming message: parse command → check permission → dispatch → send result.
|
|
207
|
+
* Plain text (non-command) is routed to the agent handler automatically.
|
|
208
|
+
* Channels call this from their platform event handler.
|
|
209
|
+
*/
|
|
210
|
+
async processMessage(msg) {
|
|
211
|
+
const parsed = parseCommand(msg.text);
|
|
212
|
+
const ctx = parsed ? {
|
|
213
|
+
userId: msg.userId,
|
|
214
|
+
command: parsed.name,
|
|
215
|
+
args: parsed.args,
|
|
216
|
+
channelId: msg.channelId,
|
|
217
|
+
message: msg
|
|
218
|
+
} : {
|
|
219
|
+
userId: msg.userId,
|
|
220
|
+
command: "agent",
|
|
221
|
+
args: [msg.text],
|
|
222
|
+
channelId: msg.channelId,
|
|
223
|
+
message: msg
|
|
224
|
+
};
|
|
225
|
+
let result;
|
|
226
|
+
try {
|
|
227
|
+
result = await this.dispatcher.dispatch(ctx);
|
|
228
|
+
} catch (err2) {
|
|
229
|
+
const botErr = err2 instanceof exports.BotError ? err2 : new exports.BotError("Unexpected error", { cause: err2 instanceof Error ? err2 : void 0 });
|
|
230
|
+
result = { ok: false, error: botErr };
|
|
231
|
+
}
|
|
232
|
+
if (result.ok) {
|
|
233
|
+
await this.send(msg.userId, result.value);
|
|
234
|
+
} else {
|
|
235
|
+
await this.send(msg.userId, {
|
|
236
|
+
type: "error",
|
|
237
|
+
message: this.formatErrorMessage(result.error)
|
|
238
|
+
});
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
formatErrorMessage(error) {
|
|
242
|
+
if (error instanceof exports.CommandNotFoundError) {
|
|
243
|
+
return `Unknown command. Type /help for available commands.`;
|
|
244
|
+
}
|
|
245
|
+
return error.message;
|
|
246
|
+
}
|
|
247
|
+
logEvent(event, meta = {}) {
|
|
248
|
+
this.logger.info(`[${this.name}] ${event}`, { channel: this.id, ...meta });
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
}
|
|
252
|
+
});
|
|
253
|
+
|
|
164
254
|
// ../../node_modules/.pnpm/bottleneck@2.19.5/node_modules/bottleneck/lib/parser.js
|
|
165
255
|
var require_parser = __commonJS({
|
|
166
256
|
"../../node_modules/.pnpm/bottleneck@2.19.5/node_modules/bottleneck/lib/parser.js"(exports2) {
|
|
@@ -3011,9 +3101,9 @@ var require_lib = __commonJS({
|
|
|
3011
3101
|
}
|
|
3012
3102
|
});
|
|
3013
3103
|
|
|
3014
|
-
// ../../node_modules/.pnpm/@grammyjs+transformer-throttler@1.2.1_grammy@1.40.
|
|
3104
|
+
// ../../node_modules/.pnpm/@grammyjs+transformer-throttler@1.2.1_grammy@1.40.1/node_modules/@grammyjs/transformer-throttler/dist/deps.node.js
|
|
3015
3105
|
var require_deps_node = __commonJS({
|
|
3016
|
-
"../../node_modules/.pnpm/@grammyjs+transformer-throttler@1.2.1_grammy@1.40.
|
|
3106
|
+
"../../node_modules/.pnpm/@grammyjs+transformer-throttler@1.2.1_grammy@1.40.1/node_modules/@grammyjs/transformer-throttler/dist/deps.node.js"(exports2) {
|
|
3017
3107
|
var __importDefault = exports2 && exports2.__importDefault || function(mod2) {
|
|
3018
3108
|
return mod2 && mod2.__esModule ? mod2 : { "default": mod2 };
|
|
3019
3109
|
};
|
|
@@ -3026,9 +3116,9 @@ var require_deps_node = __commonJS({
|
|
|
3026
3116
|
}
|
|
3027
3117
|
});
|
|
3028
3118
|
|
|
3029
|
-
// ../../node_modules/.pnpm/@grammyjs+transformer-throttler@1.2.1_grammy@1.40.
|
|
3119
|
+
// ../../node_modules/.pnpm/@grammyjs+transformer-throttler@1.2.1_grammy@1.40.1/node_modules/@grammyjs/transformer-throttler/dist/mod.js
|
|
3030
3120
|
var require_mod = __commonJS({
|
|
3031
|
-
"../../node_modules/.pnpm/@grammyjs+transformer-throttler@1.2.1_grammy@1.40.
|
|
3121
|
+
"../../node_modules/.pnpm/@grammyjs+transformer-throttler@1.2.1_grammy@1.40.1/node_modules/@grammyjs/transformer-throttler/dist/mod.js"(exports2) {
|
|
3032
3122
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
3033
3123
|
exports2.bypassThrottler = exports2.apiThrottler = exports2.BottleneckStrategy = void 0;
|
|
3034
3124
|
var deps_node_js_1 = require_deps_node();
|
|
@@ -3091,90 +3181,10 @@ var require_mod = __commonJS({
|
|
|
3091
3181
|
}
|
|
3092
3182
|
});
|
|
3093
3183
|
|
|
3094
|
-
// src/models/command.ts
|
|
3095
|
-
var command_exports = {};
|
|
3096
|
-
__export(command_exports, {
|
|
3097
|
-
ParsedCommandSchema: () => exports.ParsedCommandSchema,
|
|
3098
|
-
parseCommand: () => parseCommand
|
|
3099
|
-
});
|
|
3100
|
-
function parseCommand(text) {
|
|
3101
|
-
const trimmed = text.trim();
|
|
3102
|
-
const match = /^[/!](\w+)(?:\s+(.*))?$/s.exec(trimmed);
|
|
3103
|
-
if (!match) return null;
|
|
3104
|
-
const name = (match[1] ?? "").toLowerCase();
|
|
3105
|
-
const rest = (match[2] ?? "").trim();
|
|
3106
|
-
const args = rest ? rest.split(/\s+/) : [];
|
|
3107
|
-
return exports.ParsedCommandSchema.parse({ name, args, rawText: trimmed });
|
|
3108
|
-
}
|
|
3109
|
-
exports.ParsedCommandSchema = void 0;
|
|
3110
|
-
var init_command = __esm({
|
|
3111
|
-
"src/models/command.ts"() {
|
|
3112
|
-
exports.ParsedCommandSchema = v4.z.object({
|
|
3113
|
-
name: v4.z.string().min(1),
|
|
3114
|
-
args: v4.z.array(v4.z.string()),
|
|
3115
|
-
rawText: v4.z.string()
|
|
3116
|
-
});
|
|
3117
|
-
}
|
|
3118
|
-
});
|
|
3119
|
-
|
|
3120
|
-
// src/core/base-channel.ts
|
|
3121
|
-
exports.BaseChannel = void 0;
|
|
3122
|
-
var init_base_channel = __esm({
|
|
3123
|
-
"src/core/base-channel.ts"() {
|
|
3124
|
-
init_command();
|
|
3125
|
-
init_errors();
|
|
3126
|
-
exports.BaseChannel = class {
|
|
3127
|
-
constructor(id, name, permissions, dispatcher, logger) {
|
|
3128
|
-
this.id = id;
|
|
3129
|
-
this.name = name;
|
|
3130
|
-
this.permissions = permissions;
|
|
3131
|
-
this.dispatcher = dispatcher;
|
|
3132
|
-
this.logger = logger;
|
|
3133
|
-
}
|
|
3134
|
-
/**
|
|
3135
|
-
* Process an incoming message: parse command → check permission → dispatch → send result.
|
|
3136
|
-
* Channels call this from their platform event handler.
|
|
3137
|
-
*/
|
|
3138
|
-
async processMessage(msg) {
|
|
3139
|
-
const parsed = parseCommand(msg.text);
|
|
3140
|
-
if (!parsed) return;
|
|
3141
|
-
const ctx = {
|
|
3142
|
-
userId: msg.userId,
|
|
3143
|
-
command: parsed.name,
|
|
3144
|
-
args: parsed.args,
|
|
3145
|
-
channelId: msg.channelId,
|
|
3146
|
-
message: msg
|
|
3147
|
-
};
|
|
3148
|
-
let result;
|
|
3149
|
-
try {
|
|
3150
|
-
result = await this.dispatcher.dispatch(ctx);
|
|
3151
|
-
} catch (err2) {
|
|
3152
|
-
const botErr = err2 instanceof exports.BotError ? err2 : new exports.BotError("Unexpected error", { cause: err2 instanceof Error ? err2 : void 0 });
|
|
3153
|
-
result = { ok: false, error: botErr };
|
|
3154
|
-
}
|
|
3155
|
-
if (result.ok) {
|
|
3156
|
-
await this.send(msg.userId, result.value);
|
|
3157
|
-
} else {
|
|
3158
|
-
await this.send(msg.userId, {
|
|
3159
|
-
type: "error",
|
|
3160
|
-
message: this.formatErrorMessage(result.error)
|
|
3161
|
-
});
|
|
3162
|
-
}
|
|
3163
|
-
}
|
|
3164
|
-
formatErrorMessage(error) {
|
|
3165
|
-
if (error instanceof exports.CommandNotFoundError) {
|
|
3166
|
-
return `Unknown command. Type /help for available commands.`;
|
|
3167
|
-
}
|
|
3168
|
-
return error.message;
|
|
3169
|
-
}
|
|
3170
|
-
logEvent(event, meta = {}) {
|
|
3171
|
-
this.logger.info(`[${this.name}] ${event}`, { channel: this.id, ...meta });
|
|
3172
|
-
}
|
|
3173
|
-
};
|
|
3174
|
-
}
|
|
3175
|
-
});
|
|
3176
|
-
|
|
3177
3184
|
// src/channels/telegram/formatter.ts
|
|
3185
|
+
function escapeHtml(text) {
|
|
3186
|
+
return text.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
3187
|
+
}
|
|
3178
3188
|
function formatBytes(bytes) {
|
|
3179
3189
|
if (bytes < 1024) return `${bytes}B`;
|
|
3180
3190
|
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}K`;
|
|
@@ -3244,6 +3254,51 @@ ${this.formatText(error.message)}`;
|
|
|
3244
3254
|
const sizeStr = size !== void 0 && !isDir ? ` \\(${this.formatText(formatBytes(size))}\\)` : "";
|
|
3245
3255
|
return `${icon} \`${this.escapeInline(name)}\`${sizeStr}`;
|
|
3246
3256
|
}
|
|
3257
|
+
// ─── HTML formatting (preferred — avoids MarkdownV2 escaping hell) ────────
|
|
3258
|
+
/**
|
|
3259
|
+
* Escape HTML special chars, then convert basic markdown to HTML tags.
|
|
3260
|
+
* Handles: **bold**, `code`, ```code blocks```, _italic_
|
|
3261
|
+
*/
|
|
3262
|
+
formatTextHtml(text) {
|
|
3263
|
+
let html = escapeHtml(text);
|
|
3264
|
+
html = html.replace(/```(\w*)\n([\s\S]*?)```/g, (_m, lang, code) => {
|
|
3265
|
+
const cls = lang ? ` class="language-${lang}"` : "";
|
|
3266
|
+
return `<pre><code${cls}>${code}</code></pre>`;
|
|
3267
|
+
});
|
|
3268
|
+
html = html.replace(/`([^`]+)`/g, "<code>$1</code>");
|
|
3269
|
+
html = html.replace(/\*\*(.+?)\*\*/g, "<b>$1</b>");
|
|
3270
|
+
html = html.replace(/__(.+?)__/g, "<b>$1</b>");
|
|
3271
|
+
html = html.replace(/(?<!\w)\*([^*]+?)\*(?!\w)/g, "<i>$1</i>");
|
|
3272
|
+
html = html.replace(/(?<!\w)_([^_]+?)_(?!\w)/g, "<i>$1</i>");
|
|
3273
|
+
return html;
|
|
3274
|
+
}
|
|
3275
|
+
/**
|
|
3276
|
+
* Format code block as HTML <pre>.
|
|
3277
|
+
*/
|
|
3278
|
+
formatCodeHtml(code, language) {
|
|
3279
|
+
const escaped = escapeHtml(code);
|
|
3280
|
+
const cls = language ? ` class="language-${language}"` : "";
|
|
3281
|
+
const wrapped = `<pre><code${cls}>${escaped}</code></pre>`;
|
|
3282
|
+
if (wrapped.length <= TELEGRAM_MAX_MESSAGE_LENGTH) return wrapped;
|
|
3283
|
+
const overhead = 40 + (language?.length ?? 0);
|
|
3284
|
+
const maxCode = TELEGRAM_MAX_MESSAGE_LENGTH - overhead;
|
|
3285
|
+
return `<pre><code${cls}>${escaped.slice(0, maxCode)}
|
|
3286
|
+
\u2026(truncated)</code></pre>`;
|
|
3287
|
+
}
|
|
3288
|
+
/**
|
|
3289
|
+
* Format error message as HTML.
|
|
3290
|
+
*/
|
|
3291
|
+
formatErrorHtml(message) {
|
|
3292
|
+
return `\u274C <b>Error:</b> ${escapeHtml(message)}`;
|
|
3293
|
+
}
|
|
3294
|
+
/**
|
|
3295
|
+
* Format file entry as HTML.
|
|
3296
|
+
*/
|
|
3297
|
+
formatFileEntryHtml(name, isDir, size) {
|
|
3298
|
+
const icon = isDir ? "\u{1F4C1}" : "\u{1F4C4}";
|
|
3299
|
+
const sizeStr = size !== void 0 && !isDir ? ` (${formatBytes(size)})` : "";
|
|
3300
|
+
return `${icon} <code>${escapeHtml(name)}</code>${sizeStr}`;
|
|
3301
|
+
}
|
|
3247
3302
|
// Escape text that appears inside inline code (backtick context)
|
|
3248
3303
|
escapeInline(text) {
|
|
3249
3304
|
return text.replace(/`/g, "'");
|
|
@@ -3282,8 +3337,18 @@ var init_channel = __esm({
|
|
|
3282
3337
|
bot.on("message:text", async (ctx) => {
|
|
3283
3338
|
const msg = this.normalizeContext(ctx);
|
|
3284
3339
|
if (!msg) return;
|
|
3285
|
-
|
|
3286
|
-
|
|
3340
|
+
const typingInterval = setInterval(() => {
|
|
3341
|
+
ctx.api.sendChatAction(ctx.chat.id, "typing").catch(() => {
|
|
3342
|
+
});
|
|
3343
|
+
}, 4e3);
|
|
3344
|
+
await ctx.api.sendChatAction(ctx.chat.id, "typing").catch(() => {
|
|
3345
|
+
});
|
|
3346
|
+
try {
|
|
3347
|
+
for (const h3 of this.messageHandlers) await h3(msg);
|
|
3348
|
+
await this.processMessage(msg);
|
|
3349
|
+
} finally {
|
|
3350
|
+
clearInterval(typingInterval);
|
|
3351
|
+
}
|
|
3287
3352
|
});
|
|
3288
3353
|
bot.on("callback_query:data", async (ctx) => {
|
|
3289
3354
|
await ctx.answerCallbackQuery();
|
|
@@ -3331,20 +3396,18 @@ var init_channel = __esm({
|
|
|
3331
3396
|
try {
|
|
3332
3397
|
switch (message.type) {
|
|
3333
3398
|
case "text": {
|
|
3334
|
-
const text = this.truncate(this.formatter.
|
|
3335
|
-
await this.bot.api.sendMessage(chatId, text, { parse_mode: "
|
|
3399
|
+
const text = this.truncate(this.formatter.formatTextHtml(message.text));
|
|
3400
|
+
await this.bot.api.sendMessage(chatId, text, { parse_mode: "HTML" });
|
|
3336
3401
|
break;
|
|
3337
3402
|
}
|
|
3338
3403
|
case "code": {
|
|
3339
|
-
const code = this.formatter.
|
|
3340
|
-
await this.bot.api.sendMessage(chatId, code, { parse_mode: "
|
|
3404
|
+
const code = this.formatter.formatCodeHtml(message.code, message.language);
|
|
3405
|
+
await this.bot.api.sendMessage(chatId, code, { parse_mode: "HTML" });
|
|
3341
3406
|
break;
|
|
3342
3407
|
}
|
|
3343
3408
|
case "error": {
|
|
3344
|
-
const errText = this.formatter.
|
|
3345
|
-
|
|
3346
|
-
);
|
|
3347
|
-
await this.bot.api.sendMessage(chatId, errText, { parse_mode: "MarkdownV2" });
|
|
3409
|
+
const errText = this.formatter.formatErrorHtml(message.message);
|
|
3410
|
+
await this.bot.api.sendMessage(chatId, errText, { parse_mode: "HTML" });
|
|
3348
3411
|
break;
|
|
3349
3412
|
}
|
|
3350
3413
|
}
|
|
@@ -3371,7 +3434,7 @@ var init_channel = __esm({
|
|
|
3371
3434
|
}
|
|
3372
3435
|
truncate(text) {
|
|
3373
3436
|
if (text.length <= this.maxLength) return text;
|
|
3374
|
-
return text.slice(0, this.maxLength - 20) + "\n
|
|
3437
|
+
return text.slice(0, this.maxLength - 20) + "\n... <i>(truncated)</i>";
|
|
3375
3438
|
}
|
|
3376
3439
|
};
|
|
3377
3440
|
}
|
|
@@ -16580,21 +16643,34 @@ var PermissionManager = class {
|
|
|
16580
16643
|
return this.identityMap;
|
|
16581
16644
|
}
|
|
16582
16645
|
};
|
|
16583
|
-
|
|
16584
|
-
|
|
16585
|
-
|
|
16646
|
+
var CONSOLA_LEVELS = {
|
|
16647
|
+
debug: 4,
|
|
16648
|
+
info: 3,
|
|
16649
|
+
warn: 2,
|
|
16650
|
+
error: 1
|
|
16651
|
+
};
|
|
16586
16652
|
function createLogger(level = "info") {
|
|
16587
|
-
const
|
|
16588
|
-
|
|
16589
|
-
|
|
16590
|
-
|
|
16591
|
-
|
|
16592
|
-
|
|
16653
|
+
const consola$1 = consola.createConsola({
|
|
16654
|
+
level: CONSOLA_LEVELS[level],
|
|
16655
|
+
formatOptions: {
|
|
16656
|
+
date: true,
|
|
16657
|
+
colors: true
|
|
16658
|
+
}
|
|
16659
|
+
}).withTag("bot");
|
|
16593
16660
|
return {
|
|
16594
|
-
|
|
16595
|
-
|
|
16596
|
-
|
|
16597
|
-
|
|
16661
|
+
consola: consola$1,
|
|
16662
|
+
debug(msg, meta) {
|
|
16663
|
+
meta ? consola$1.debug(msg, meta) : consola$1.debug(msg);
|
|
16664
|
+
},
|
|
16665
|
+
info(msg, meta) {
|
|
16666
|
+
meta ? consola$1.info(msg, meta) : consola$1.info(msg);
|
|
16667
|
+
},
|
|
16668
|
+
warn(msg, meta) {
|
|
16669
|
+
meta ? consola$1.warn(msg, meta) : consola$1.warn(msg);
|
|
16670
|
+
},
|
|
16671
|
+
error(msg, meta) {
|
|
16672
|
+
meta ? consola$1.error(msg, meta) : consola$1.error(msg);
|
|
16673
|
+
}
|
|
16598
16674
|
};
|
|
16599
16675
|
}
|
|
16600
16676
|
|
|
@@ -16701,7 +16777,21 @@ var AgentHandler = class extends BaseHandler {
|
|
|
16701
16777
|
const text = result.text.length > this.maxOutput ? result.text.slice(0, this.maxOutput) + "\n...(truncated)" : result.text;
|
|
16702
16778
|
return ok({ type: "text", text });
|
|
16703
16779
|
} catch (e3) {
|
|
16704
|
-
|
|
16780
|
+
const errMsg = e3 instanceof Error ? e3.message : String(e3);
|
|
16781
|
+
this.logger.error("Agent execution failed", { error: errMsg });
|
|
16782
|
+
if (errMsg.includes("session_id") || errMsg.includes("No active session")) {
|
|
16783
|
+
return err(new exports.CMDOPError("Machine is offline or CMDOP agent is not running.\nhttps://cmdop.com/downloads/"));
|
|
16784
|
+
}
|
|
16785
|
+
if (errMsg.includes("context canceled") || errMsg.includes("CANCELLED")) {
|
|
16786
|
+
return err(new exports.CMDOPError("Request was interrupted. Please try again."));
|
|
16787
|
+
}
|
|
16788
|
+
if (errMsg.includes("DEADLINE_EXCEEDED") || errMsg.includes("timeout")) {
|
|
16789
|
+
return err(new exports.CMDOPError("Request timed out. The task may be too complex \u2014 try a simpler prompt."));
|
|
16790
|
+
}
|
|
16791
|
+
if (errMsg.includes("UNAVAILABLE") || errMsg.includes("Connection refused")) {
|
|
16792
|
+
return err(new exports.CMDOPError("Server unavailable. Check your connection and try again."));
|
|
16793
|
+
}
|
|
16794
|
+
return err(new exports.CMDOPError(`Agent error: ${errMsg}`, e3 instanceof Error ? e3 : void 0));
|
|
16705
16795
|
}
|
|
16706
16796
|
}
|
|
16707
16797
|
};
|
|
@@ -16822,6 +16912,63 @@ function loadSettings(env = process.env) {
|
|
|
16822
16912
|
return result.data;
|
|
16823
16913
|
}
|
|
16824
16914
|
|
|
16915
|
+
// src/channels/demo/channel.ts
|
|
16916
|
+
init_base_channel();
|
|
16917
|
+
var DemoChannel = class extends exports.BaseChannel {
|
|
16918
|
+
messageHandlers = [];
|
|
16919
|
+
onOutput;
|
|
16920
|
+
constructor(permissions, dispatcher, logger, options2 = {}) {
|
|
16921
|
+
super("demo", "Demo", permissions, dispatcher, logger);
|
|
16922
|
+
this.onOutput = options2.onOutput ?? ((text) => process.stdout.write(text + "\n"));
|
|
16923
|
+
}
|
|
16924
|
+
async start() {
|
|
16925
|
+
this.logEvent("started");
|
|
16926
|
+
}
|
|
16927
|
+
async stop() {
|
|
16928
|
+
this.messageHandlers = [];
|
|
16929
|
+
this.logEvent("stopped");
|
|
16930
|
+
}
|
|
16931
|
+
send(_userId, message) {
|
|
16932
|
+
const text = formatOutgoing(message);
|
|
16933
|
+
this.onOutput(text, message);
|
|
16934
|
+
return Promise.resolve();
|
|
16935
|
+
}
|
|
16936
|
+
onMessage(handler) {
|
|
16937
|
+
this.messageHandlers.push(handler);
|
|
16938
|
+
}
|
|
16939
|
+
/**
|
|
16940
|
+
* Inject a message as if it came from a real platform user.
|
|
16941
|
+
* Primarily used in tests and CLI demos.
|
|
16942
|
+
*/
|
|
16943
|
+
async injectMessage(input) {
|
|
16944
|
+
const msg = {
|
|
16945
|
+
id: `demo-${Date.now()}`,
|
|
16946
|
+
userId: input.userId ?? "demo-user",
|
|
16947
|
+
channelId: this.id,
|
|
16948
|
+
text: input.text,
|
|
16949
|
+
timestamp: /* @__PURE__ */ new Date(),
|
|
16950
|
+
attachments: []
|
|
16951
|
+
};
|
|
16952
|
+
for (const handler of this.messageHandlers) {
|
|
16953
|
+
await handler(msg);
|
|
16954
|
+
}
|
|
16955
|
+
await this.processMessage(msg);
|
|
16956
|
+
}
|
|
16957
|
+
};
|
|
16958
|
+
function formatOutgoing(message) {
|
|
16959
|
+
switch (message.type) {
|
|
16960
|
+
case "text":
|
|
16961
|
+
return message.text;
|
|
16962
|
+
case "code":
|
|
16963
|
+
return `\`\`\`${message.language ?? ""}
|
|
16964
|
+
${message.code}
|
|
16965
|
+
\`\`\``;
|
|
16966
|
+
case "error":
|
|
16967
|
+
return `\u274C ${message.message}${message.hint ? `
|
|
16968
|
+
\u{1F4A1} ${message.hint}` : ""}`;
|
|
16969
|
+
}
|
|
16970
|
+
}
|
|
16971
|
+
|
|
16825
16972
|
// src/hub.ts
|
|
16826
16973
|
var IntegrationHub = class _IntegrationHub {
|
|
16827
16974
|
constructor(_client, _logger, _settings, permissions, dispatcher, channelStartMode) {
|
|
@@ -16847,11 +16994,12 @@ var IntegrationHub = class _IntegrationHub {
|
|
|
16847
16994
|
Object.assign(settings2, options2.settings ?? {});
|
|
16848
16995
|
if (options2.defaultMachine) settings2.defaultMachine = options2.defaultMachine;
|
|
16849
16996
|
const logger = options2.logger ?? createLogger(settings2.logLevel);
|
|
16850
|
-
const client = options2.apiKey ?
|
|
16997
|
+
const client = options2.apiKey ? node.CMDOPClient.remote(options2.apiKey) : node.CMDOPClient.local();
|
|
16851
16998
|
const store = options2.permissionStore ?? new InMemoryPermissionStore();
|
|
16852
16999
|
const identityMap = new IdentityMap();
|
|
16853
17000
|
const permissions = new PermissionManager(store, {
|
|
16854
17001
|
adminUsers: [...options2.adminUsers ?? [], ...settings2.allowedUsers],
|
|
17002
|
+
defaultLevel: options2.defaultPermission,
|
|
16855
17003
|
identityMap
|
|
16856
17004
|
});
|
|
16857
17005
|
const dispatcher = new MessageDispatcher(permissions, logger);
|
|
@@ -16898,6 +17046,15 @@ var IntegrationHub = class _IntegrationHub {
|
|
|
16898
17046
|
const channel = new SlackChannel2(options2, this._permissions, this._dispatcher, this._logger);
|
|
16899
17047
|
return this.registerChannel(channel);
|
|
16900
17048
|
}
|
|
17049
|
+
/**
|
|
17050
|
+
* Create and register a DemoChannel for CLI testing.
|
|
17051
|
+
* No external dependencies — messages are injected via the returned channel's `injectMessage()`.
|
|
17052
|
+
*/
|
|
17053
|
+
addDemo(options2) {
|
|
17054
|
+
const channel = new DemoChannel(this._permissions, this._dispatcher, this._logger, options2);
|
|
17055
|
+
this.registerChannel(channel);
|
|
17056
|
+
return channel;
|
|
17057
|
+
}
|
|
16901
17058
|
registerHandler(handler) {
|
|
16902
17059
|
this._dispatcher.register(handler);
|
|
16903
17060
|
return this;
|
|
@@ -16906,6 +17063,17 @@ var IntegrationHub = class _IntegrationHub {
|
|
|
16906
17063
|
async start() {
|
|
16907
17064
|
if (this.started) return;
|
|
16908
17065
|
this.started = true;
|
|
17066
|
+
if (this._settings.defaultMachine) {
|
|
17067
|
+
try {
|
|
17068
|
+
await this._client.setMachine(this._settings.defaultMachine);
|
|
17069
|
+
this._logger.info("Machine routing initialized", { machine: this._settings.defaultMachine });
|
|
17070
|
+
} catch (err2) {
|
|
17071
|
+
this._logger.error("Failed to initialize machine routing", {
|
|
17072
|
+
machine: this._settings.defaultMachine,
|
|
17073
|
+
err: err2 instanceof Error ? err2.message : String(err2)
|
|
17074
|
+
});
|
|
17075
|
+
}
|
|
17076
|
+
}
|
|
16909
17077
|
if (this.channelStartMode === "strict") {
|
|
16910
17078
|
await Promise.all([...this.channels.values()].map(async (ch) => {
|
|
16911
17079
|
await ch.start();
|
|
@@ -17168,63 +17336,6 @@ var SlackStream = class _SlackStream {
|
|
|
17168
17336
|
}
|
|
17169
17337
|
};
|
|
17170
17338
|
|
|
17171
|
-
// src/channels/demo/channel.ts
|
|
17172
|
-
init_base_channel();
|
|
17173
|
-
var DemoChannel = class extends exports.BaseChannel {
|
|
17174
|
-
messageHandlers = [];
|
|
17175
|
-
onOutput;
|
|
17176
|
-
constructor(permissions, dispatcher, logger, options2 = {}) {
|
|
17177
|
-
super("demo", "Demo", permissions, dispatcher, logger);
|
|
17178
|
-
this.onOutput = options2.onOutput ?? ((text) => process.stdout.write(text + "\n"));
|
|
17179
|
-
}
|
|
17180
|
-
async start() {
|
|
17181
|
-
this.logEvent("started");
|
|
17182
|
-
}
|
|
17183
|
-
async stop() {
|
|
17184
|
-
this.messageHandlers = [];
|
|
17185
|
-
this.logEvent("stopped");
|
|
17186
|
-
}
|
|
17187
|
-
send(_userId, message) {
|
|
17188
|
-
const text = formatOutgoing(message);
|
|
17189
|
-
this.onOutput(text, message);
|
|
17190
|
-
return Promise.resolve();
|
|
17191
|
-
}
|
|
17192
|
-
onMessage(handler) {
|
|
17193
|
-
this.messageHandlers.push(handler);
|
|
17194
|
-
}
|
|
17195
|
-
/**
|
|
17196
|
-
* Inject a message as if it came from a real platform user.
|
|
17197
|
-
* Primarily used in tests and CLI demos.
|
|
17198
|
-
*/
|
|
17199
|
-
async injectMessage(input) {
|
|
17200
|
-
const msg = {
|
|
17201
|
-
id: `demo-${Date.now()}`,
|
|
17202
|
-
userId: input.userId ?? "demo-user",
|
|
17203
|
-
channelId: this.id,
|
|
17204
|
-
text: input.text,
|
|
17205
|
-
timestamp: /* @__PURE__ */ new Date(),
|
|
17206
|
-
attachments: []
|
|
17207
|
-
};
|
|
17208
|
-
for (const handler of this.messageHandlers) {
|
|
17209
|
-
await handler(msg);
|
|
17210
|
-
}
|
|
17211
|
-
await this.processMessage(msg);
|
|
17212
|
-
}
|
|
17213
|
-
};
|
|
17214
|
-
function formatOutgoing(message) {
|
|
17215
|
-
switch (message.type) {
|
|
17216
|
-
case "text":
|
|
17217
|
-
return message.text;
|
|
17218
|
-
case "code":
|
|
17219
|
-
return `\`\`\`${message.language ?? ""}
|
|
17220
|
-
${message.code}
|
|
17221
|
-
\`\`\``;
|
|
17222
|
-
case "error":
|
|
17223
|
-
return `\u274C ${message.message}${message.hint ? `
|
|
17224
|
-
\u{1F4A1} ${message.hint}` : ""}`;
|
|
17225
|
-
}
|
|
17226
|
-
}
|
|
17227
|
-
|
|
17228
17339
|
// src/channels/telegram/index.ts
|
|
17229
17340
|
init_channel();
|
|
17230
17341
|
init_formatter();
|