@openacp/cli 0.2.11 → 0.2.14
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 +25 -25
- package/dist/chunk-HTUZOMIT.js +421 -0
- package/dist/chunk-HTUZOMIT.js.map +1 -0
- package/dist/{chunk-I6KXISAR.js → chunk-TKOYKVXH.js} +384 -45
- package/dist/chunk-TKOYKVXH.js.map +1 -0
- package/dist/cli.js +2 -2
- package/dist/index.d.ts +124 -45
- package/dist/index.js +12 -2
- package/dist/{main-L5JD5STD.js → main-PB2TMO3M.js} +28 -18
- package/dist/main-PB2TMO3M.js.map +1 -0
- package/dist/{setup-2UVU4YYA.js → setup-4EBTX2NJ.js} +3 -32
- package/dist/{setup-2UVU4YYA.js.map → setup-4EBTX2NJ.js.map} +1 -1
- package/package.json +4 -1
- package/dist/chunk-I6KXISAR.js.map +0 -1
- package/dist/chunk-KADEDKIM.js +0 -220
- package/dist/chunk-KADEDKIM.js.map +0 -1
- package/dist/main-L5JD5STD.js.map +0 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
-
|
|
3
|
-
|
|
2
|
+
createChildLogger,
|
|
3
|
+
createSessionLogger
|
|
4
|
+
} from "./chunk-HTUZOMIT.js";
|
|
4
5
|
|
|
5
6
|
// src/core/streams.ts
|
|
6
7
|
function nodeToWebWritable(nodeStream) {
|
|
@@ -46,10 +47,12 @@ var StderrCapture = class {
|
|
|
46
47
|
|
|
47
48
|
// src/core/agent-instance.ts
|
|
48
49
|
import { spawn, execSync } from "child_process";
|
|
50
|
+
import { Transform } from "stream";
|
|
49
51
|
import fs from "fs";
|
|
50
52
|
import path from "path";
|
|
51
53
|
import { randomUUID } from "crypto";
|
|
52
54
|
import { ClientSideConnection, ndJsonStream } from "@agentclientprotocol/sdk";
|
|
55
|
+
var log = createChildLogger({ module: "agent-instance" });
|
|
53
56
|
function resolveAgentCommand(cmd) {
|
|
54
57
|
const packageDirs = [
|
|
55
58
|
path.resolve(process.cwd(), "node_modules", "@zed-industries", cmd, "dist", "index.js"),
|
|
@@ -103,7 +106,8 @@ var AgentInstance = class _AgentInstance {
|
|
|
103
106
|
static async spawn(agentDef, workingDirectory) {
|
|
104
107
|
const instance = new _AgentInstance(agentDef.name);
|
|
105
108
|
const resolved = resolveAgentCommand(agentDef.command);
|
|
106
|
-
log.debug(
|
|
109
|
+
log.debug({ agentName: agentDef.name, command: resolved.command, args: resolved.args }, "Spawning agent");
|
|
110
|
+
const spawnStart = Date.now();
|
|
107
111
|
instance.child = spawn(resolved.command, [...resolved.args, ...agentDef.args], {
|
|
108
112
|
stdio: ["pipe", "pipe", "pipe"],
|
|
109
113
|
cwd: workingDirectory,
|
|
@@ -119,8 +123,22 @@ var AgentInstance = class _AgentInstance {
|
|
|
119
123
|
instance.child.stderr.on("data", (chunk) => {
|
|
120
124
|
instance.stderrCapture.append(chunk.toString());
|
|
121
125
|
});
|
|
122
|
-
const
|
|
123
|
-
|
|
126
|
+
const stdinLogger = new Transform({
|
|
127
|
+
transform(chunk, _enc, cb) {
|
|
128
|
+
log.debug({ direction: "send", raw: chunk.toString().trimEnd() }, "ACP raw");
|
|
129
|
+
cb(null, chunk);
|
|
130
|
+
}
|
|
131
|
+
});
|
|
132
|
+
stdinLogger.pipe(instance.child.stdin);
|
|
133
|
+
const stdoutLogger = new Transform({
|
|
134
|
+
transform(chunk, _enc, cb) {
|
|
135
|
+
log.debug({ direction: "recv", raw: chunk.toString().trimEnd() }, "ACP raw");
|
|
136
|
+
cb(null, chunk);
|
|
137
|
+
}
|
|
138
|
+
});
|
|
139
|
+
instance.child.stdout.pipe(stdoutLogger);
|
|
140
|
+
const toAgent = nodeToWebWritable(stdinLogger);
|
|
141
|
+
const fromAgent = nodeToWebReadable(stdoutLogger);
|
|
124
142
|
const stream = ndJsonStream(toAgent, fromAgent);
|
|
125
143
|
instance.connection = new ClientSideConnection(
|
|
126
144
|
(_agent) => instance.createClient(_agent),
|
|
@@ -139,6 +157,7 @@ var AgentInstance = class _AgentInstance {
|
|
|
139
157
|
});
|
|
140
158
|
instance.sessionId = response.sessionId;
|
|
141
159
|
instance.child.on("exit", (code, signal) => {
|
|
160
|
+
log.info({ sessionId: instance.sessionId, exitCode: code, signal }, "Agent process exited");
|
|
142
161
|
if (code !== 0 && code !== null) {
|
|
143
162
|
const stderr = instance.stderrCapture.getLastLines();
|
|
144
163
|
instance.onSessionUpdate({
|
|
@@ -149,9 +168,9 @@ ${stderr}`
|
|
|
149
168
|
}
|
|
150
169
|
});
|
|
151
170
|
instance.connection.closed.then(() => {
|
|
152
|
-
log.debug("ACP connection closed
|
|
171
|
+
log.debug({ sessionId: instance.sessionId }, "ACP connection closed");
|
|
153
172
|
});
|
|
154
|
-
log.info(
|
|
173
|
+
log.info({ sessionId: response.sessionId, durationMs: Date.now() - spawnStart }, "Agent spawn complete");
|
|
155
174
|
return instance;
|
|
156
175
|
}
|
|
157
176
|
// createClient — implemented in Task 6b
|
|
@@ -366,6 +385,7 @@ var AgentManager = class {
|
|
|
366
385
|
|
|
367
386
|
// src/core/session.ts
|
|
368
387
|
import { nanoid } from "nanoid";
|
|
388
|
+
var moduleLog = createChildLogger({ module: "session" });
|
|
369
389
|
var Session = class {
|
|
370
390
|
id;
|
|
371
391
|
channelId;
|
|
@@ -381,17 +401,20 @@ var Session = class {
|
|
|
381
401
|
adapter;
|
|
382
402
|
// Set by wireSessionEvents for renaming
|
|
383
403
|
pendingPermission;
|
|
404
|
+
log;
|
|
384
405
|
constructor(opts) {
|
|
385
406
|
this.id = opts.id || nanoid(12);
|
|
386
407
|
this.channelId = opts.channelId;
|
|
387
408
|
this.agentName = opts.agentName;
|
|
388
409
|
this.workingDirectory = opts.workingDirectory;
|
|
389
410
|
this.agentInstance = opts.agentInstance;
|
|
411
|
+
this.log = createSessionLogger(this.id, moduleLog);
|
|
412
|
+
this.log.info({ agentName: this.agentName }, "Session created");
|
|
390
413
|
}
|
|
391
414
|
async enqueuePrompt(text) {
|
|
392
415
|
if (this.promptRunning) {
|
|
393
416
|
this.promptQueue.push(text);
|
|
394
|
-
log.debug(
|
|
417
|
+
this.log.debug({ queueDepth: this.promptQueue.length }, "Prompt queued");
|
|
395
418
|
return;
|
|
396
419
|
}
|
|
397
420
|
await this.runPrompt(text);
|
|
@@ -399,14 +422,17 @@ var Session = class {
|
|
|
399
422
|
async runPrompt(text) {
|
|
400
423
|
this.promptRunning = true;
|
|
401
424
|
this.status = "active";
|
|
425
|
+
const promptStart = Date.now();
|
|
426
|
+
this.log.debug("Prompt execution started");
|
|
402
427
|
try {
|
|
403
428
|
await this.agentInstance.prompt(text);
|
|
429
|
+
this.log.info({ durationMs: Date.now() - promptStart }, "Prompt execution completed");
|
|
404
430
|
if (!this.name) {
|
|
405
431
|
await this.autoName();
|
|
406
432
|
}
|
|
407
433
|
} catch (err) {
|
|
408
434
|
this.status = "error";
|
|
409
|
-
log.error(
|
|
435
|
+
this.log.error({ err }, "Prompt execution failed");
|
|
410
436
|
} finally {
|
|
411
437
|
this.promptRunning = false;
|
|
412
438
|
if (this.promptQueue.length > 0) {
|
|
@@ -428,6 +454,7 @@ var Session = class {
|
|
|
428
454
|
"Summarize this conversation in max 5 words for a topic title. Reply ONLY with the title, nothing else."
|
|
429
455
|
);
|
|
430
456
|
this.name = title.trim().slice(0, 50);
|
|
457
|
+
this.log.info({ name: this.name }, "Session auto-named");
|
|
431
458
|
if (this.adapter && this.name) {
|
|
432
459
|
await this.adapter.renameSessionThread(this.id, this.name);
|
|
433
460
|
}
|
|
@@ -437,11 +464,34 @@ var Session = class {
|
|
|
437
464
|
this.agentInstance.onSessionUpdate = prevHandler;
|
|
438
465
|
}
|
|
439
466
|
}
|
|
467
|
+
/** Fire-and-forget warm-up: primes model cache while user types their first message */
|
|
468
|
+
async warmup() {
|
|
469
|
+
this.promptRunning = true;
|
|
470
|
+
const prevHandler = this.agentInstance.onSessionUpdate;
|
|
471
|
+
this.agentInstance.onSessionUpdate = () => {
|
|
472
|
+
};
|
|
473
|
+
try {
|
|
474
|
+
const start = Date.now();
|
|
475
|
+
await this.agentInstance.prompt('Reply with only "ready".');
|
|
476
|
+
this.log.info({ durationMs: Date.now() - start }, "Warm-up complete");
|
|
477
|
+
} catch (err) {
|
|
478
|
+
this.log.error({ err }, "Warm-up failed");
|
|
479
|
+
} finally {
|
|
480
|
+
this.agentInstance.onSessionUpdate = prevHandler;
|
|
481
|
+
this.promptRunning = false;
|
|
482
|
+
if (this.promptQueue.length > 0) {
|
|
483
|
+
const next = this.promptQueue.shift();
|
|
484
|
+
await this.runPrompt(next);
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
}
|
|
440
488
|
async cancel() {
|
|
441
489
|
this.status = "cancelled";
|
|
490
|
+
this.log.info("Session cancelled");
|
|
442
491
|
await this.agentInstance.cancel();
|
|
443
492
|
}
|
|
444
493
|
async destroy() {
|
|
494
|
+
this.log.info("Session destroyed");
|
|
445
495
|
await this.agentInstance.destroy();
|
|
446
496
|
}
|
|
447
497
|
};
|
|
@@ -502,6 +552,7 @@ var NotificationManager = class {
|
|
|
502
552
|
};
|
|
503
553
|
|
|
504
554
|
// src/core/core.ts
|
|
555
|
+
var log2 = createChildLogger({ module: "core" });
|
|
505
556
|
var OpenACPCore = class {
|
|
506
557
|
configManager;
|
|
507
558
|
agentManager;
|
|
@@ -540,11 +591,16 @@ var OpenACPCore = class {
|
|
|
540
591
|
// --- Message Routing ---
|
|
541
592
|
async handleMessage(message) {
|
|
542
593
|
const config = this.configManager.get();
|
|
594
|
+
log2.debug({ channelId: message.channelId, threadId: message.threadId, userId: message.userId }, "Incoming message");
|
|
543
595
|
if (config.security.allowedUserIds.length > 0) {
|
|
544
|
-
if (!config.security.allowedUserIds.includes(message.userId))
|
|
596
|
+
if (!config.security.allowedUserIds.includes(message.userId)) {
|
|
597
|
+
log2.warn({ userId: message.userId }, "Rejected message from unauthorized user");
|
|
598
|
+
return;
|
|
599
|
+
}
|
|
545
600
|
}
|
|
546
601
|
const activeSessions = this.sessionManager.listSessions().filter((s) => s.status === "active" || s.status === "initializing");
|
|
547
602
|
if (activeSessions.length >= config.security.maxConcurrentSessions) {
|
|
603
|
+
log2.warn({ userId: message.userId, currentCount: activeSessions.length, max: config.security.maxConcurrentSessions }, "Session limit reached");
|
|
548
604
|
const adapter = this.adapters.get(message.channelId);
|
|
549
605
|
if (adapter) {
|
|
550
606
|
await adapter.sendMessage("system", {
|
|
@@ -561,6 +617,7 @@ var OpenACPCore = class {
|
|
|
561
617
|
async handleNewSession(channelId, agentName, workspacePath) {
|
|
562
618
|
const config = this.configManager.get();
|
|
563
619
|
const resolvedAgent = agentName || config.defaultAgent;
|
|
620
|
+
log2.info({ channelId, agentName: resolvedAgent }, "New session request");
|
|
564
621
|
const resolvedWorkspace = this.configManager.resolveWorkspace(
|
|
565
622
|
workspacePath || config.agents[resolvedAgent]?.workingDirectory
|
|
566
623
|
);
|
|
@@ -600,10 +657,6 @@ var OpenACPCore = class {
|
|
|
600
657
|
return { type: "plan", text: "", metadata: { entries: event.entries } };
|
|
601
658
|
case "usage":
|
|
602
659
|
return { type: "usage", text: "", metadata: { tokensUsed: event.tokensUsed, contextSize: event.contextSize, cost: event.cost } };
|
|
603
|
-
case "commands_update":
|
|
604
|
-
log.debug("Commands update:", event.commands);
|
|
605
|
-
return { type: "text", text: "" };
|
|
606
|
-
// no-op for now
|
|
607
660
|
default:
|
|
608
661
|
return { type: "text", text: "" };
|
|
609
662
|
}
|
|
@@ -623,6 +676,7 @@ var OpenACPCore = class {
|
|
|
623
676
|
break;
|
|
624
677
|
case "session_end":
|
|
625
678
|
session.status = "finished";
|
|
679
|
+
adapter.cleanupSkillCommands(session.id);
|
|
626
680
|
adapter.sendMessage(session.id, { type: "session_end", text: `Done (${event.reason})` });
|
|
627
681
|
this.notificationManager.notify(session.channelId, {
|
|
628
682
|
sessionId: session.id,
|
|
@@ -632,6 +686,7 @@ var OpenACPCore = class {
|
|
|
632
686
|
});
|
|
633
687
|
break;
|
|
634
688
|
case "error":
|
|
689
|
+
adapter.cleanupSkillCommands(session.id);
|
|
635
690
|
adapter.sendMessage(session.id, { type: "error", text: event.message });
|
|
636
691
|
this.notificationManager.notify(session.channelId, {
|
|
637
692
|
sessionId: session.id,
|
|
@@ -641,7 +696,8 @@ var OpenACPCore = class {
|
|
|
641
696
|
});
|
|
642
697
|
break;
|
|
643
698
|
case "commands_update":
|
|
644
|
-
|
|
699
|
+
log2.debug({ commands: event.commands }, "Commands available");
|
|
700
|
+
adapter.sendSkillCommands(session.id, event.commands);
|
|
645
701
|
break;
|
|
646
702
|
}
|
|
647
703
|
};
|
|
@@ -661,6 +717,11 @@ var ChannelAdapter = class {
|
|
|
661
717
|
this.core = core;
|
|
662
718
|
this.config = config;
|
|
663
719
|
}
|
|
720
|
+
// Skill commands — override in adapters that support dynamic commands
|
|
721
|
+
async sendSkillCommands(_sessionId, _commands) {
|
|
722
|
+
}
|
|
723
|
+
async cleanupSkillCommands(_sessionId) {
|
|
724
|
+
}
|
|
664
725
|
};
|
|
665
726
|
|
|
666
727
|
// src/adapters/telegram/adapter.ts
|
|
@@ -715,19 +776,19 @@ var KIND_ICON = {
|
|
|
715
776
|
move: "\u{1F4E6}",
|
|
716
777
|
other: "\u{1F6E0}\uFE0F"
|
|
717
778
|
};
|
|
718
|
-
function extractContentText(content) {
|
|
719
|
-
if (!content) return "";
|
|
779
|
+
function extractContentText(content, depth = 0) {
|
|
780
|
+
if (!content || depth > 5) return "";
|
|
720
781
|
if (typeof content === "string") return content;
|
|
721
782
|
if (Array.isArray(content)) {
|
|
722
|
-
return content.map((c) => extractContentText(c)).filter(Boolean).join("\n");
|
|
783
|
+
return content.map((c) => extractContentText(c, depth + 1)).filter(Boolean).join("\n");
|
|
723
784
|
}
|
|
724
785
|
if (typeof content === "object" && content !== null) {
|
|
725
786
|
const c = content;
|
|
726
787
|
if (c.type === "text" && typeof c.text === "string") return c.text;
|
|
727
788
|
if (typeof c.text === "string") return c.text;
|
|
728
789
|
if (typeof c.content === "string") return c.content;
|
|
729
|
-
if (c.input) return extractContentText(c.input);
|
|
730
|
-
if (c.output) return extractContentText(c.output);
|
|
790
|
+
if (c.input) return extractContentText(c.input, depth + 1);
|
|
791
|
+
if (c.output) return extractContentText(c.output, depth + 1);
|
|
731
792
|
const keys = Object.keys(c).filter((k) => k !== "type");
|
|
732
793
|
if (keys.length === 0) return "";
|
|
733
794
|
return JSON.stringify(c, null, 2);
|
|
@@ -937,6 +998,8 @@ function buildDeepLink(chatId, messageId) {
|
|
|
937
998
|
|
|
938
999
|
// src/adapters/telegram/commands.ts
|
|
939
1000
|
import { InlineKeyboard } from "grammy";
|
|
1001
|
+
import { nanoid as nanoid2 } from "nanoid";
|
|
1002
|
+
var log4 = createChildLogger({ module: "telegram-commands" });
|
|
940
1003
|
function setupCommands(bot, core, chatId) {
|
|
941
1004
|
bot.command("new", (ctx) => handleNew(ctx, core, chatId));
|
|
942
1005
|
bot.command("new_chat", (ctx) => handleNewChat(ctx, core, chatId));
|
|
@@ -949,6 +1012,35 @@ function setupCommands(bot, core, chatId) {
|
|
|
949
1012
|
function buildMenuKeyboard() {
|
|
950
1013
|
return new InlineKeyboard().text("\u{1F195} New Session", "m:new").text("\u{1F4AC} New Chat", "m:new_chat").row().text("\u26D4 Cancel", "m:cancel").text("\u{1F4CA} Status", "m:status").row().text("\u{1F916} Agents", "m:agents").text("\u2753 Help", "m:help");
|
|
951
1014
|
}
|
|
1015
|
+
function setupMenuCallbacks(bot, core, chatId) {
|
|
1016
|
+
bot.callbackQuery(/^m:/, async (ctx) => {
|
|
1017
|
+
const data = ctx.callbackQuery.data;
|
|
1018
|
+
try {
|
|
1019
|
+
await ctx.answerCallbackQuery();
|
|
1020
|
+
} catch {
|
|
1021
|
+
}
|
|
1022
|
+
switch (data) {
|
|
1023
|
+
case "m:new":
|
|
1024
|
+
await handleNew(ctx, core, chatId);
|
|
1025
|
+
break;
|
|
1026
|
+
case "m:new_chat":
|
|
1027
|
+
await handleNewChat(ctx, core, chatId);
|
|
1028
|
+
break;
|
|
1029
|
+
case "m:cancel":
|
|
1030
|
+
await handleCancel(ctx, core);
|
|
1031
|
+
break;
|
|
1032
|
+
case "m:status":
|
|
1033
|
+
await handleStatus(ctx, core);
|
|
1034
|
+
break;
|
|
1035
|
+
case "m:agents":
|
|
1036
|
+
await handleAgents(ctx, core);
|
|
1037
|
+
break;
|
|
1038
|
+
case "m:help":
|
|
1039
|
+
await handleHelp(ctx);
|
|
1040
|
+
break;
|
|
1041
|
+
}
|
|
1042
|
+
});
|
|
1043
|
+
}
|
|
952
1044
|
async function handleMenu(ctx) {
|
|
953
1045
|
await ctx.reply(`<b>OpenACP Menu</b>
|
|
954
1046
|
Choose an action:`, {
|
|
@@ -962,10 +1054,15 @@ async function handleNew(ctx, core, chatId) {
|
|
|
962
1054
|
const args = matchStr.split(" ").filter(Boolean);
|
|
963
1055
|
const agentName = args[0];
|
|
964
1056
|
const workspace = args[1];
|
|
1057
|
+
log4.info({ userId: ctx.from?.id, agentName }, "New session command");
|
|
965
1058
|
let threadId;
|
|
966
1059
|
try {
|
|
967
1060
|
const topicName = `\u{1F504} New Session`;
|
|
968
1061
|
threadId = await createSessionTopic(botFromCtx(ctx), chatId, topicName);
|
|
1062
|
+
await ctx.api.sendMessage(chatId, `\u23F3 Setting up session, please wait...`, {
|
|
1063
|
+
message_thread_id: threadId,
|
|
1064
|
+
parse_mode: "HTML"
|
|
1065
|
+
});
|
|
969
1066
|
const session = await core.handleNewSession(
|
|
970
1067
|
"telegram",
|
|
971
1068
|
agentName,
|
|
@@ -987,6 +1084,7 @@ async function handleNew(ctx, core, chatId) {
|
|
|
987
1084
|
parse_mode: "HTML"
|
|
988
1085
|
}
|
|
989
1086
|
);
|
|
1087
|
+
session.warmup().catch((err) => log4.error({ err }, "Warm-up error"));
|
|
990
1088
|
} catch (err) {
|
|
991
1089
|
if (threadId) {
|
|
992
1090
|
try {
|
|
@@ -1021,6 +1119,10 @@ async function handleNewChat(ctx, core, chatId) {
|
|
|
1021
1119
|
chatId,
|
|
1022
1120
|
topicName
|
|
1023
1121
|
);
|
|
1122
|
+
await ctx.api.sendMessage(chatId, `\u23F3 Setting up session, please wait...`, {
|
|
1123
|
+
message_thread_id: newThreadId,
|
|
1124
|
+
parse_mode: "HTML"
|
|
1125
|
+
});
|
|
1024
1126
|
session.threadId = String(newThreadId);
|
|
1025
1127
|
await ctx.api.sendMessage(
|
|
1026
1128
|
chatId,
|
|
@@ -1032,6 +1134,7 @@ async function handleNewChat(ctx, core, chatId) {
|
|
|
1032
1134
|
parse_mode: "HTML"
|
|
1033
1135
|
}
|
|
1034
1136
|
);
|
|
1137
|
+
session.warmup().catch((err) => log4.error({ err }, "Warm-up error"));
|
|
1035
1138
|
} catch (err) {
|
|
1036
1139
|
const message = err instanceof Error ? err.message : String(err);
|
|
1037
1140
|
await ctx.reply(`\u274C ${escapeHtml(message)}`, { parse_mode: "HTML" });
|
|
@@ -1045,6 +1148,7 @@ async function handleCancel(ctx, core) {
|
|
|
1045
1148
|
String(threadId)
|
|
1046
1149
|
);
|
|
1047
1150
|
if (session) {
|
|
1151
|
+
log4.info({ sessionId: session.id }, "Cancel session command");
|
|
1048
1152
|
await session.cancel();
|
|
1049
1153
|
await ctx.reply("\u26D4 Session cancelled.", { parse_mode: "HTML" });
|
|
1050
1154
|
}
|
|
@@ -1116,10 +1220,56 @@ Or just chat in the \u{1F916} Assistant topic for help!`,
|
|
|
1116
1220
|
function botFromCtx(ctx) {
|
|
1117
1221
|
return { api: ctx.api };
|
|
1118
1222
|
}
|
|
1223
|
+
var skillCallbackMap = /* @__PURE__ */ new Map();
|
|
1224
|
+
function buildSkillKeyboard(sessionId, commands) {
|
|
1225
|
+
const keyboard = new InlineKeyboard();
|
|
1226
|
+
const sorted = [...commands].sort((a, b) => a.name.localeCompare(b.name));
|
|
1227
|
+
for (let i = 0; i < sorted.length; i++) {
|
|
1228
|
+
const cmd = sorted[i];
|
|
1229
|
+
const key = nanoid2(8);
|
|
1230
|
+
skillCallbackMap.set(key, { sessionId, commandName: cmd.name });
|
|
1231
|
+
keyboard.text(`/${cmd.name}`, `s:${key}`);
|
|
1232
|
+
if (i % 2 === 1 && i < sorted.length - 1) {
|
|
1233
|
+
keyboard.row();
|
|
1234
|
+
}
|
|
1235
|
+
}
|
|
1236
|
+
return keyboard;
|
|
1237
|
+
}
|
|
1238
|
+
function clearSkillCallbacks(sessionId) {
|
|
1239
|
+
for (const [key, entry] of skillCallbackMap) {
|
|
1240
|
+
if (entry.sessionId === sessionId) {
|
|
1241
|
+
skillCallbackMap.delete(key);
|
|
1242
|
+
}
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
function setupSkillCallbacks(bot, core) {
|
|
1246
|
+
bot.callbackQuery(/^s:/, async (ctx) => {
|
|
1247
|
+
try {
|
|
1248
|
+
await ctx.answerCallbackQuery();
|
|
1249
|
+
} catch {
|
|
1250
|
+
}
|
|
1251
|
+
const key = ctx.callbackQuery.data.slice(2);
|
|
1252
|
+
const entry = skillCallbackMap.get(key);
|
|
1253
|
+
if (!entry) return;
|
|
1254
|
+
const session = core.sessionManager.getSession(entry.sessionId);
|
|
1255
|
+
if (!session || session.status !== "active") return;
|
|
1256
|
+
await session.enqueuePrompt(`/${entry.commandName}`);
|
|
1257
|
+
});
|
|
1258
|
+
}
|
|
1259
|
+
var STATIC_COMMANDS = [
|
|
1260
|
+
{ command: "new", description: "Create new session" },
|
|
1261
|
+
{ command: "new_chat", description: "New chat, same agent & workspace" },
|
|
1262
|
+
{ command: "cancel", description: "Cancel current session" },
|
|
1263
|
+
{ command: "status", description: "Show status" },
|
|
1264
|
+
{ command: "agents", description: "List available agents" },
|
|
1265
|
+
{ command: "help", description: "Help" },
|
|
1266
|
+
{ command: "menu", description: "Show menu" }
|
|
1267
|
+
];
|
|
1119
1268
|
|
|
1120
1269
|
// src/adapters/telegram/permissions.ts
|
|
1121
1270
|
import { InlineKeyboard as InlineKeyboard2 } from "grammy";
|
|
1122
|
-
import { nanoid as
|
|
1271
|
+
import { nanoid as nanoid3 } from "nanoid";
|
|
1272
|
+
var log5 = createChildLogger({ module: "telegram-permissions" });
|
|
1123
1273
|
var PermissionHandler = class {
|
|
1124
1274
|
constructor(bot, chatId, getSession, sendNotification) {
|
|
1125
1275
|
this.bot = bot;
|
|
@@ -1130,8 +1280,12 @@ var PermissionHandler = class {
|
|
|
1130
1280
|
pending = /* @__PURE__ */ new Map();
|
|
1131
1281
|
async sendPermissionRequest(session, request) {
|
|
1132
1282
|
const threadId = Number(session.threadId);
|
|
1133
|
-
const callbackKey =
|
|
1134
|
-
this.pending.set(callbackKey, {
|
|
1283
|
+
const callbackKey = nanoid3(8);
|
|
1284
|
+
this.pending.set(callbackKey, {
|
|
1285
|
+
sessionId: session.id,
|
|
1286
|
+
requestId: request.id,
|
|
1287
|
+
options: request.options.map((o) => ({ id: o.id, isAllow: o.isAllow }))
|
|
1288
|
+
});
|
|
1135
1289
|
const keyboard = new InlineKeyboard2();
|
|
1136
1290
|
for (const option of request.options) {
|
|
1137
1291
|
const emoji = option.isAllow ? "\u2705" : "\u274C";
|
|
@@ -1174,6 +1328,8 @@ ${escapeHtml(request.description)}`,
|
|
|
1174
1328
|
return;
|
|
1175
1329
|
}
|
|
1176
1330
|
const session = this.getSession(pending.sessionId);
|
|
1331
|
+
const isAllow = pending.options.find((o) => o.id === optionId)?.isAllow ?? false;
|
|
1332
|
+
log5.info({ requestId: pending.requestId, optionId, isAllow }, "Permission responded");
|
|
1177
1333
|
if (session?.pendingPermission?.requestId === pending.requestId) {
|
|
1178
1334
|
session.pendingPermission.resolve(optionId);
|
|
1179
1335
|
session.pendingPermission = void 0;
|
|
@@ -1240,6 +1396,7 @@ function redirectToAssistant(chatId, assistantTopicId) {
|
|
|
1240
1396
|
}
|
|
1241
1397
|
|
|
1242
1398
|
// src/adapters/telegram/adapter.ts
|
|
1399
|
+
var log6 = createChildLogger({ module: "telegram" });
|
|
1243
1400
|
var TelegramAdapter = class extends ChannelAdapter {
|
|
1244
1401
|
bot;
|
|
1245
1402
|
telegramConfig;
|
|
@@ -1250,6 +1407,8 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1250
1407
|
assistantSession = null;
|
|
1251
1408
|
notificationTopicId;
|
|
1252
1409
|
assistantTopicId;
|
|
1410
|
+
skillMessages = /* @__PURE__ */ new Map();
|
|
1411
|
+
// sessionId → pinned messageId
|
|
1253
1412
|
constructor(core, config) {
|
|
1254
1413
|
super(core, config);
|
|
1255
1414
|
this.telegramConfig = config;
|
|
@@ -1257,14 +1416,22 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1257
1416
|
async start() {
|
|
1258
1417
|
this.bot = new Bot(this.telegramConfig.botToken);
|
|
1259
1418
|
this.bot.catch((err) => {
|
|
1260
|
-
|
|
1419
|
+
const rootCause = err.error instanceof Error ? err.error : err;
|
|
1420
|
+
log6.error({ err: rootCause }, "Telegram bot error");
|
|
1261
1421
|
});
|
|
1262
1422
|
this.bot.api.config.use((prev, method, payload, signal) => {
|
|
1263
1423
|
if (method === "getUpdates") {
|
|
1264
|
-
|
|
1424
|
+
const p = payload;
|
|
1425
|
+
p.allowed_updates = p.allowed_updates ?? [
|
|
1426
|
+
"message",
|
|
1427
|
+
"callback_query"
|
|
1428
|
+
];
|
|
1265
1429
|
}
|
|
1266
1430
|
return prev(method, payload, signal);
|
|
1267
1431
|
});
|
|
1432
|
+
await this.bot.api.setMyCommands(STATIC_COMMANDS, {
|
|
1433
|
+
scope: { type: "chat", chat_id: this.telegramConfig.chatId }
|
|
1434
|
+
});
|
|
1268
1435
|
this.bot.use((ctx, next) => {
|
|
1269
1436
|
const chatId = ctx.chat?.id ?? ctx.callbackQuery?.message?.chat?.id;
|
|
1270
1437
|
if (chatId !== this.telegramConfig.chatId) return;
|
|
@@ -1288,12 +1455,25 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1288
1455
|
(sessionId) => this.core.sessionManager.getSession(sessionId),
|
|
1289
1456
|
(notification) => this.sendNotification(notification)
|
|
1290
1457
|
);
|
|
1458
|
+
setupSkillCallbacks(this.bot, this.core);
|
|
1459
|
+
setupMenuCallbacks(
|
|
1460
|
+
this.bot,
|
|
1461
|
+
this.core,
|
|
1462
|
+
this.telegramConfig.chatId
|
|
1463
|
+
);
|
|
1464
|
+
setupCommands(
|
|
1465
|
+
this.bot,
|
|
1466
|
+
this.core,
|
|
1467
|
+
this.telegramConfig.chatId
|
|
1468
|
+
);
|
|
1291
1469
|
this.permissionHandler.setupCallbackHandler();
|
|
1292
|
-
setupCommands(this.bot, this.core, this.telegramConfig.chatId);
|
|
1293
1470
|
this.setupRoutes();
|
|
1294
1471
|
this.bot.start({
|
|
1295
1472
|
allowed_updates: ["message", "callback_query"],
|
|
1296
|
-
onStart: () =>
|
|
1473
|
+
onStart: () => log6.info(
|
|
1474
|
+
{ chatId: this.telegramConfig.chatId },
|
|
1475
|
+
"Telegram bot started"
|
|
1476
|
+
)
|
|
1297
1477
|
});
|
|
1298
1478
|
try {
|
|
1299
1479
|
this.assistantSession = await spawnAssistant(
|
|
@@ -1302,7 +1482,28 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1302
1482
|
this.assistantTopicId
|
|
1303
1483
|
);
|
|
1304
1484
|
} catch (err) {
|
|
1305
|
-
|
|
1485
|
+
log6.error({ err }, "Failed to spawn assistant");
|
|
1486
|
+
}
|
|
1487
|
+
try {
|
|
1488
|
+
const config = this.core.configManager.get();
|
|
1489
|
+
const agents = this.core.agentManager.getAvailableAgents();
|
|
1490
|
+
const agentList = agents.map(
|
|
1491
|
+
(a) => `${escapeHtml(a.name)}${a.name === config.defaultAgent ? " (default)" : ""}`
|
|
1492
|
+
).join(", ");
|
|
1493
|
+
const workspace = escapeHtml(config.workspace.baseDir);
|
|
1494
|
+
const welcomeText = `\u{1F44B} <b>OpenACP Assistant</b> is online.
|
|
1495
|
+
|
|
1496
|
+
Available agents: ${agentList}
|
|
1497
|
+
Workspace: <code>${workspace}</code>
|
|
1498
|
+
|
|
1499
|
+
<b>Select an action:</b>`;
|
|
1500
|
+
await this.bot.api.sendMessage(this.telegramConfig.chatId, welcomeText, {
|
|
1501
|
+
message_thread_id: this.assistantTopicId,
|
|
1502
|
+
parse_mode: "HTML",
|
|
1503
|
+
reply_markup: buildMenuKeyboard()
|
|
1504
|
+
});
|
|
1505
|
+
} catch (err) {
|
|
1506
|
+
log6.warn({ err }, "Failed to send welcome message");
|
|
1306
1507
|
}
|
|
1307
1508
|
}
|
|
1308
1509
|
async stop() {
|
|
@@ -1310,32 +1511,43 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1310
1511
|
await this.assistantSession.destroy();
|
|
1311
1512
|
}
|
|
1312
1513
|
await this.bot.stop();
|
|
1514
|
+
log6.info("Telegram bot stopped");
|
|
1313
1515
|
}
|
|
1314
1516
|
setupRoutes() {
|
|
1315
1517
|
this.bot.on("message:text", async (ctx) => {
|
|
1316
1518
|
const threadId = ctx.message.message_thread_id;
|
|
1317
1519
|
if (!threadId) {
|
|
1318
|
-
const html = redirectToAssistant(
|
|
1520
|
+
const html = redirectToAssistant(
|
|
1521
|
+
this.telegramConfig.chatId,
|
|
1522
|
+
this.assistantTopicId
|
|
1523
|
+
);
|
|
1319
1524
|
await ctx.reply(html, { parse_mode: "HTML" });
|
|
1320
1525
|
return;
|
|
1321
1526
|
}
|
|
1322
1527
|
if (threadId === this.notificationTopicId) return;
|
|
1323
1528
|
if (threadId === this.assistantTopicId) {
|
|
1324
|
-
|
|
1529
|
+
ctx.replyWithChatAction("typing").catch(() => {
|
|
1530
|
+
});
|
|
1531
|
+
handleAssistantMessage(this.assistantSession, ctx.message.text).catch(
|
|
1532
|
+
(err) => log6.error({ err }, "Assistant error")
|
|
1533
|
+
);
|
|
1325
1534
|
return;
|
|
1326
1535
|
}
|
|
1327
|
-
|
|
1536
|
+
ctx.replyWithChatAction("typing").catch(() => {
|
|
1537
|
+
});
|
|
1328
1538
|
this.core.handleMessage({
|
|
1329
1539
|
channelId: "telegram",
|
|
1330
1540
|
threadId: String(threadId),
|
|
1331
1541
|
userId: String(ctx.from.id),
|
|
1332
1542
|
text: ctx.message.text
|
|
1333
|
-
}).catch((err) =>
|
|
1543
|
+
}).catch((err) => log6.error({ err }, "handleMessage error"));
|
|
1334
1544
|
});
|
|
1335
1545
|
}
|
|
1336
1546
|
// --- ChannelAdapter implementations ---
|
|
1337
1547
|
async sendMessage(sessionId, content) {
|
|
1338
|
-
const session = this.core.sessionManager.getSession(
|
|
1548
|
+
const session = this.core.sessionManager.getSession(
|
|
1549
|
+
sessionId
|
|
1550
|
+
);
|
|
1339
1551
|
if (!session) return;
|
|
1340
1552
|
const threadId = Number(session.threadId);
|
|
1341
1553
|
switch (content.type) {
|
|
@@ -1345,7 +1557,11 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1345
1557
|
case "text": {
|
|
1346
1558
|
let draft = this.sessionDrafts.get(sessionId);
|
|
1347
1559
|
if (!draft) {
|
|
1348
|
-
draft = new MessageDraft(
|
|
1560
|
+
draft = new MessageDraft(
|
|
1561
|
+
this.bot,
|
|
1562
|
+
this.telegramConfig.chatId,
|
|
1563
|
+
threadId
|
|
1564
|
+
);
|
|
1349
1565
|
this.sessionDrafts.set(sessionId, draft);
|
|
1350
1566
|
}
|
|
1351
1567
|
draft.append(content.text);
|
|
@@ -1357,19 +1573,31 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1357
1573
|
const msg = await this.bot.api.sendMessage(
|
|
1358
1574
|
this.telegramConfig.chatId,
|
|
1359
1575
|
formatToolCall(meta),
|
|
1360
|
-
{
|
|
1576
|
+
{
|
|
1577
|
+
message_thread_id: threadId,
|
|
1578
|
+
parse_mode: "HTML",
|
|
1579
|
+
disable_notification: true
|
|
1580
|
+
}
|
|
1361
1581
|
);
|
|
1362
1582
|
if (!this.toolCallMessages.has(sessionId)) {
|
|
1363
1583
|
this.toolCallMessages.set(sessionId, /* @__PURE__ */ new Map());
|
|
1364
1584
|
}
|
|
1365
|
-
this.toolCallMessages.get(sessionId).set(meta.id, {
|
|
1585
|
+
this.toolCallMessages.get(sessionId).set(meta.id, {
|
|
1586
|
+
msgId: msg.message_id,
|
|
1587
|
+
name: meta.name,
|
|
1588
|
+
kind: meta.kind
|
|
1589
|
+
});
|
|
1366
1590
|
break;
|
|
1367
1591
|
}
|
|
1368
1592
|
case "tool_update": {
|
|
1369
1593
|
const meta = content.metadata;
|
|
1370
1594
|
const toolState = this.toolCallMessages.get(sessionId)?.get(meta.id);
|
|
1371
1595
|
if (toolState) {
|
|
1372
|
-
const merged = {
|
|
1596
|
+
const merged = {
|
|
1597
|
+
...meta,
|
|
1598
|
+
name: meta.name || toolState.name,
|
|
1599
|
+
kind: meta.kind || toolState.kind
|
|
1600
|
+
};
|
|
1373
1601
|
try {
|
|
1374
1602
|
await this.bot.api.editMessageText(
|
|
1375
1603
|
this.telegramConfig.chatId,
|
|
@@ -1387,7 +1615,11 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1387
1615
|
await this.bot.api.sendMessage(
|
|
1388
1616
|
this.telegramConfig.chatId,
|
|
1389
1617
|
formatPlan(content.metadata),
|
|
1390
|
-
{
|
|
1618
|
+
{
|
|
1619
|
+
message_thread_id: threadId,
|
|
1620
|
+
parse_mode: "HTML",
|
|
1621
|
+
disable_notification: true
|
|
1622
|
+
}
|
|
1391
1623
|
);
|
|
1392
1624
|
break;
|
|
1393
1625
|
}
|
|
@@ -1395,7 +1627,11 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1395
1627
|
await this.bot.api.sendMessage(
|
|
1396
1628
|
this.telegramConfig.chatId,
|
|
1397
1629
|
formatUsage(content.metadata),
|
|
1398
|
-
{
|
|
1630
|
+
{
|
|
1631
|
+
message_thread_id: threadId,
|
|
1632
|
+
parse_mode: "HTML",
|
|
1633
|
+
disable_notification: true
|
|
1634
|
+
}
|
|
1399
1635
|
);
|
|
1400
1636
|
break;
|
|
1401
1637
|
}
|
|
@@ -1403,10 +1639,15 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1403
1639
|
await this.finalizeDraft(sessionId);
|
|
1404
1640
|
this.sessionDrafts.delete(sessionId);
|
|
1405
1641
|
this.toolCallMessages.delete(sessionId);
|
|
1642
|
+
await this.cleanupSkillCommands(sessionId);
|
|
1406
1643
|
await this.bot.api.sendMessage(
|
|
1407
1644
|
this.telegramConfig.chatId,
|
|
1408
1645
|
`\u2705 <b>Done</b>`,
|
|
1409
|
-
{
|
|
1646
|
+
{
|
|
1647
|
+
message_thread_id: threadId,
|
|
1648
|
+
parse_mode: "HTML",
|
|
1649
|
+
disable_notification: true
|
|
1650
|
+
}
|
|
1410
1651
|
);
|
|
1411
1652
|
break;
|
|
1412
1653
|
}
|
|
@@ -1415,18 +1656,29 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1415
1656
|
await this.bot.api.sendMessage(
|
|
1416
1657
|
this.telegramConfig.chatId,
|
|
1417
1658
|
`\u274C <b>Error:</b> ${escapeHtml(content.text)}`,
|
|
1418
|
-
{
|
|
1659
|
+
{
|
|
1660
|
+
message_thread_id: threadId,
|
|
1661
|
+
parse_mode: "HTML",
|
|
1662
|
+
disable_notification: true
|
|
1663
|
+
}
|
|
1419
1664
|
);
|
|
1420
1665
|
break;
|
|
1421
1666
|
}
|
|
1422
1667
|
}
|
|
1423
1668
|
}
|
|
1424
1669
|
async sendPermissionRequest(sessionId, request) {
|
|
1425
|
-
|
|
1670
|
+
log6.info({ sessionId, requestId: request.id }, "Permission request sent");
|
|
1671
|
+
const session = this.core.sessionManager.getSession(
|
|
1672
|
+
sessionId
|
|
1673
|
+
);
|
|
1426
1674
|
if (!session) return;
|
|
1427
1675
|
await this.permissionHandler.sendPermissionRequest(session, request);
|
|
1428
1676
|
}
|
|
1429
1677
|
async sendNotification(notification) {
|
|
1678
|
+
log6.info(
|
|
1679
|
+
{ sessionId: notification.sessionId, type: notification.type },
|
|
1680
|
+
"Notification sent"
|
|
1681
|
+
);
|
|
1430
1682
|
if (!this.notificationTopicId) return;
|
|
1431
1683
|
const emoji = {
|
|
1432
1684
|
completed: "\u2705",
|
|
@@ -1449,12 +1701,99 @@ var TelegramAdapter = class extends ChannelAdapter {
|
|
|
1449
1701
|
});
|
|
1450
1702
|
}
|
|
1451
1703
|
async createSessionThread(sessionId, name) {
|
|
1452
|
-
|
|
1704
|
+
log6.info({ sessionId, name }, "Session topic created");
|
|
1705
|
+
return String(
|
|
1706
|
+
await createSessionTopic(this.bot, this.telegramConfig.chatId, name)
|
|
1707
|
+
);
|
|
1453
1708
|
}
|
|
1454
1709
|
async renameSessionThread(sessionId, newName) {
|
|
1710
|
+
const session = this.core.sessionManager.getSession(
|
|
1711
|
+
sessionId
|
|
1712
|
+
);
|
|
1713
|
+
if (!session) return;
|
|
1714
|
+
await renameSessionTopic(
|
|
1715
|
+
this.bot,
|
|
1716
|
+
this.telegramConfig.chatId,
|
|
1717
|
+
Number(session.threadId),
|
|
1718
|
+
newName
|
|
1719
|
+
);
|
|
1720
|
+
}
|
|
1721
|
+
async sendSkillCommands(sessionId, commands) {
|
|
1455
1722
|
const session = this.core.sessionManager.getSession(sessionId);
|
|
1456
1723
|
if (!session) return;
|
|
1457
|
-
|
|
1724
|
+
const threadId = Number(session.threadId);
|
|
1725
|
+
if (!threadId) return;
|
|
1726
|
+
if (commands.length === 0) {
|
|
1727
|
+
await this.cleanupSkillCommands(sessionId);
|
|
1728
|
+
return;
|
|
1729
|
+
}
|
|
1730
|
+
clearSkillCallbacks(sessionId);
|
|
1731
|
+
const keyboard = buildSkillKeyboard(sessionId, commands);
|
|
1732
|
+
const text = "\u{1F6E0} <b>Available commands:</b>";
|
|
1733
|
+
const existingMsgId = this.skillMessages.get(sessionId);
|
|
1734
|
+
if (existingMsgId) {
|
|
1735
|
+
try {
|
|
1736
|
+
await this.bot.api.editMessageText(
|
|
1737
|
+
this.telegramConfig.chatId,
|
|
1738
|
+
existingMsgId,
|
|
1739
|
+
text,
|
|
1740
|
+
{ parse_mode: "HTML", reply_markup: keyboard }
|
|
1741
|
+
);
|
|
1742
|
+
return;
|
|
1743
|
+
} catch {
|
|
1744
|
+
}
|
|
1745
|
+
}
|
|
1746
|
+
try {
|
|
1747
|
+
const msg = await this.bot.api.sendMessage(
|
|
1748
|
+
this.telegramConfig.chatId,
|
|
1749
|
+
text,
|
|
1750
|
+
{
|
|
1751
|
+
message_thread_id: threadId,
|
|
1752
|
+
parse_mode: "HTML",
|
|
1753
|
+
reply_markup: keyboard,
|
|
1754
|
+
disable_notification: true
|
|
1755
|
+
}
|
|
1756
|
+
);
|
|
1757
|
+
this.skillMessages.set(sessionId, msg.message_id);
|
|
1758
|
+
await this.bot.api.pinChatMessage(this.telegramConfig.chatId, msg.message_id, {
|
|
1759
|
+
disable_notification: true
|
|
1760
|
+
});
|
|
1761
|
+
} catch (err) {
|
|
1762
|
+
log6.error({ err, sessionId }, "Failed to send skill commands");
|
|
1763
|
+
}
|
|
1764
|
+
await this.updateCommandAutocomplete(session.agentName, commands);
|
|
1765
|
+
}
|
|
1766
|
+
async cleanupSkillCommands(sessionId) {
|
|
1767
|
+
const msgId = this.skillMessages.get(sessionId);
|
|
1768
|
+
if (!msgId) return;
|
|
1769
|
+
try {
|
|
1770
|
+
await this.bot.api.editMessageText(
|
|
1771
|
+
this.telegramConfig.chatId,
|
|
1772
|
+
msgId,
|
|
1773
|
+
"\u{1F6E0} <i>Session ended</i>",
|
|
1774
|
+
{ parse_mode: "HTML" }
|
|
1775
|
+
);
|
|
1776
|
+
await this.bot.api.unpinChatMessage(this.telegramConfig.chatId, msgId);
|
|
1777
|
+
} catch {
|
|
1778
|
+
}
|
|
1779
|
+
this.skillMessages.delete(sessionId);
|
|
1780
|
+
clearSkillCallbacks(sessionId);
|
|
1781
|
+
}
|
|
1782
|
+
async updateCommandAutocomplete(agentName, skillCommands) {
|
|
1783
|
+
const prefix = `[${agentName}] `;
|
|
1784
|
+
const validSkills = skillCommands.map((c) => ({
|
|
1785
|
+
command: c.name.toLowerCase().replace(/[^a-z0-9_]/g, "_").slice(0, 32),
|
|
1786
|
+
description: (prefix + (c.description || c.name).replace(/\n/g, " ")).slice(0, 256)
|
|
1787
|
+
})).filter((c) => c.command.length > 0);
|
|
1788
|
+
const all = [...STATIC_COMMANDS, ...validSkills];
|
|
1789
|
+
try {
|
|
1790
|
+
await this.bot.api.setMyCommands(all, {
|
|
1791
|
+
scope: { type: "chat", chat_id: this.telegramConfig.chatId }
|
|
1792
|
+
});
|
|
1793
|
+
log6.info({ count: all.length, skills: validSkills.length }, "Updated command autocomplete");
|
|
1794
|
+
} catch (err) {
|
|
1795
|
+
log6.error({ err, commands: all }, "Failed to update command autocomplete");
|
|
1796
|
+
}
|
|
1458
1797
|
}
|
|
1459
1798
|
async finalizeDraft(sessionId) {
|
|
1460
1799
|
const draft = this.sessionDrafts.get(sessionId);
|
|
@@ -1478,4 +1817,4 @@ export {
|
|
|
1478
1817
|
ChannelAdapter,
|
|
1479
1818
|
TelegramAdapter
|
|
1480
1819
|
};
|
|
1481
|
-
//# sourceMappingURL=chunk-
|
|
1820
|
+
//# sourceMappingURL=chunk-TKOYKVXH.js.map
|