@openacp/cli 0.2.16 → 0.2.18

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.
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  createChildLogger,
3
3
  createSessionLogger
4
- } from "./chunk-HTUZOMIT.js";
4
+ } from "./chunk-ZATQZUJT.js";
5
5
 
6
6
  // src/core/streams.ts
7
7
  function nodeToWebWritable(nodeStream) {
@@ -55,7 +55,14 @@ import { ClientSideConnection, ndJsonStream } from "@agentclientprotocol/sdk";
55
55
  var log = createChildLogger({ module: "agent-instance" });
56
56
  function resolveAgentCommand(cmd) {
57
57
  const packageDirs = [
58
- path.resolve(process.cwd(), "node_modules", "@zed-industries", cmd, "dist", "index.js"),
58
+ path.resolve(
59
+ process.cwd(),
60
+ "node_modules",
61
+ "@zed-industries",
62
+ cmd,
63
+ "dist",
64
+ "index.js"
65
+ ),
59
66
  path.resolve(process.cwd(), "node_modules", cmd, "dist", "index.js")
60
67
  ];
61
68
  for (const jsPath of packageDirs) {
@@ -103,19 +110,33 @@ var AgentInstance = class _AgentInstance {
103
110
  constructor(agentName) {
104
111
  this.agentName = agentName;
105
112
  }
106
- static async spawn(agentDef, workingDirectory) {
113
+ static async spawnSubprocess(agentDef, workingDirectory) {
107
114
  const instance = new _AgentInstance(agentDef.name);
108
115
  const resolved = resolveAgentCommand(agentDef.command);
109
- log.debug({ agentName: agentDef.name, command: resolved.command, args: resolved.args }, "Spawning agent");
110
- const spawnStart = Date.now();
111
- instance.child = spawn(resolved.command, [...resolved.args, ...agentDef.args], {
112
- stdio: ["pipe", "pipe", "pipe"],
113
- cwd: workingDirectory,
114
- env: { ...process.env, ...agentDef.env }
115
- });
116
+ log.debug(
117
+ {
118
+ agentName: agentDef.name,
119
+ command: resolved.command,
120
+ args: resolved.args
121
+ },
122
+ "Resolved agent command"
123
+ );
124
+ instance.child = spawn(
125
+ resolved.command,
126
+ [...resolved.args, ...agentDef.args],
127
+ {
128
+ stdio: ["pipe", "pipe", "pipe"],
129
+ cwd: workingDirectory,
130
+ env: { ...process.env, ...agentDef.env }
131
+ }
132
+ );
116
133
  await new Promise((resolve, reject) => {
117
134
  instance.child.on("error", (err) => {
118
- reject(new Error(`Failed to spawn agent "${agentDef.name}": ${err.message}. Is "${agentDef.command}" installed?`));
135
+ reject(
136
+ new Error(
137
+ `Failed to spawn agent "${agentDef.name}": ${err.message}. Is "${agentDef.command}" installed?`
138
+ )
139
+ );
119
140
  });
120
141
  instance.child.on("spawn", () => resolve());
121
142
  });
@@ -125,14 +146,20 @@ var AgentInstance = class _AgentInstance {
125
146
  });
126
147
  const stdinLogger = new Transform({
127
148
  transform(chunk, _enc, cb) {
128
- log.debug({ direction: "send", raw: chunk.toString().trimEnd() }, "ACP raw");
149
+ log.debug(
150
+ { direction: "send", raw: chunk.toString().trimEnd() },
151
+ "ACP raw"
152
+ );
129
153
  cb(null, chunk);
130
154
  }
131
155
  });
132
156
  stdinLogger.pipe(instance.child.stdin);
133
157
  const stdoutLogger = new Transform({
134
158
  transform(chunk, _enc, cb) {
135
- log.debug({ direction: "recv", raw: chunk.toString().trimEnd() }, "ACP raw");
159
+ log.debug(
160
+ { direction: "recv", raw: chunk.toString().trimEnd() },
161
+ "ACP raw"
162
+ );
136
163
  cb(null, chunk);
137
164
  }
138
165
  });
@@ -151,26 +178,82 @@ var AgentInstance = class _AgentInstance {
151
178
  terminal: true
152
179
  }
153
180
  });
154
- const response = await instance.connection.newSession({
155
- cwd: workingDirectory,
156
- mcpServers: []
157
- });
158
- instance.sessionId = response.sessionId;
159
- instance.child.on("exit", (code, signal) => {
160
- log.info({ sessionId: instance.sessionId, exitCode: code, signal }, "Agent process exited");
181
+ return instance;
182
+ }
183
+ setupCrashDetection() {
184
+ this.child.on("exit", (code, signal) => {
185
+ log.info(
186
+ { sessionId: this.sessionId, exitCode: code, signal },
187
+ "Agent process exited"
188
+ );
161
189
  if (code !== 0 && code !== null) {
162
- const stderr = instance.stderrCapture.getLastLines();
163
- instance.onSessionUpdate({
190
+ const stderr = this.stderrCapture.getLastLines();
191
+ this.onSessionUpdate({
164
192
  type: "error",
165
193
  message: `Agent crashed (exit code ${code})
166
194
  ${stderr}`
167
195
  });
168
196
  }
169
197
  });
170
- instance.connection.closed.then(() => {
171
- log.debug({ sessionId: instance.sessionId }, "ACP connection closed");
198
+ this.connection.closed.then(() => {
199
+ log.debug({ sessionId: this.sessionId }, "ACP connection closed");
172
200
  });
173
- log.info({ sessionId: response.sessionId, durationMs: Date.now() - spawnStart }, "Agent spawn complete");
201
+ }
202
+ static async spawn(agentDef, workingDirectory) {
203
+ log.debug(
204
+ { agentName: agentDef.name, command: agentDef.command },
205
+ "Spawning agent"
206
+ );
207
+ const spawnStart = Date.now();
208
+ const instance = await _AgentInstance.spawnSubprocess(
209
+ agentDef,
210
+ workingDirectory
211
+ );
212
+ const response = await instance.connection.newSession({
213
+ cwd: workingDirectory,
214
+ mcpServers: []
215
+ });
216
+ instance.sessionId = response.sessionId;
217
+ instance.setupCrashDetection();
218
+ log.info(
219
+ { sessionId: response.sessionId, durationMs: Date.now() - spawnStart },
220
+ "Agent spawn complete"
221
+ );
222
+ return instance;
223
+ }
224
+ static async resume(agentDef, workingDirectory, agentSessionId) {
225
+ log.debug({ agentName: agentDef.name, agentSessionId }, "Resuming agent");
226
+ const spawnStart = Date.now();
227
+ const instance = await _AgentInstance.spawnSubprocess(
228
+ agentDef,
229
+ workingDirectory
230
+ );
231
+ try {
232
+ const response = await instance.connection.unstable_resumeSession({
233
+ sessionId: agentSessionId,
234
+ cwd: workingDirectory
235
+ });
236
+ instance.sessionId = response.sessionId;
237
+ log.info(
238
+ { sessionId: response.sessionId, durationMs: Date.now() - spawnStart },
239
+ "Agent resume complete"
240
+ );
241
+ } catch (err) {
242
+ log.warn(
243
+ { err, agentSessionId },
244
+ "Resume failed, falling back to new session"
245
+ );
246
+ const response = await instance.connection.newSession({
247
+ cwd: workingDirectory,
248
+ mcpServers: []
249
+ });
250
+ instance.sessionId = response.sessionId;
251
+ log.info(
252
+ { sessionId: response.sessionId, durationMs: Date.now() - spawnStart },
253
+ "Agent fallback spawn complete"
254
+ );
255
+ }
256
+ instance.setupCrashDetection();
174
257
  return instance;
175
258
  }
176
259
  // createClient — implemented in Task 6b
@@ -223,7 +306,10 @@ ${stderr}`
223
306
  };
224
307
  break;
225
308
  case "available_commands_update":
226
- event = { type: "commands_update", commands: update.availableCommands };
309
+ event = {
310
+ type: "commands_update",
311
+ commands: update.availableCommands
312
+ };
227
313
  break;
228
314
  default:
229
315
  return;
@@ -286,8 +372,14 @@ ${stderr}`
286
372
  state.output = state.output.slice(excess);
287
373
  }
288
374
  };
289
- childProcess.stdout?.on("data", (chunk) => appendOutput(chunk.toString()));
290
- childProcess.stderr?.on("data", (chunk) => appendOutput(chunk.toString()));
375
+ childProcess.stdout?.on(
376
+ "data",
377
+ (chunk) => appendOutput(chunk.toString())
378
+ );
379
+ childProcess.stderr?.on(
380
+ "data",
381
+ (chunk) => appendOutput(chunk.toString())
382
+ );
291
383
  childProcess.on("exit", (code, signal) => {
292
384
  state.exitStatus = { exitCode: code, signal };
293
385
  });
@@ -301,7 +393,10 @@ ${stderr}`
301
393
  return {
302
394
  output: state.output,
303
395
  truncated: false,
304
- exitStatus: state.exitStatus ? { exitCode: state.exitStatus.exitCode, signal: state.exitStatus.signal } : void 0
396
+ exitStatus: state.exitStatus ? {
397
+ exitCode: state.exitStatus.exitCode,
398
+ signal: state.exitStatus.signal
399
+ } : void 0
305
400
  };
306
401
  },
307
402
  async waitForTerminalExit(params) {
@@ -310,7 +405,10 @@ ${stderr}`
310
405
  throw new Error(`Terminal not found: ${params.terminalId}`);
311
406
  }
312
407
  if (state.exitStatus !== null) {
313
- return { exitCode: state.exitStatus.exitCode, signal: state.exitStatus.signal };
408
+ return {
409
+ exitCode: state.exitStatus.exitCode,
410
+ signal: state.exitStatus.signal
411
+ };
314
412
  }
315
413
  return new Promise((resolve) => {
316
414
  state.process.on("exit", (code, signal) => {
@@ -381,6 +479,11 @@ var AgentManager = class {
381
479
  if (!agentDef) throw new Error(`Agent "${agentName}" not found in config`);
382
480
  return AgentInstance.spawn(agentDef, workingDirectory);
383
481
  }
482
+ async resume(agentName, workingDirectory, agentSessionId) {
483
+ const agentDef = this.getAgent(agentName);
484
+ if (!agentDef) throw new Error(`Agent "${agentName}" not found in config`);
485
+ return AgentInstance.resume(agentDef, workingDirectory, agentSessionId);
486
+ }
384
487
  };
385
488
 
386
489
  // src/core/session.ts
@@ -393,6 +496,7 @@ var Session = class {
393
496
  agentName;
394
497
  workingDirectory;
395
498
  agentInstance;
499
+ agentSessionId = "";
396
500
  status = "initializing";
397
501
  name;
398
502
  promptQueue = [];
@@ -426,7 +530,10 @@ var Session = class {
426
530
  this.log.debug("Prompt execution started");
427
531
  try {
428
532
  await this.agentInstance.prompt(text);
429
- this.log.info({ durationMs: Date.now() - promptStart }, "Prompt execution completed");
533
+ this.log.info(
534
+ { durationMs: Date.now() - promptStart },
535
+ "Prompt execution completed"
536
+ );
430
537
  if (!this.name) {
431
538
  await this.autoName();
432
539
  }
@@ -499,10 +606,34 @@ var Session = class {
499
606
  // src/core/session-manager.ts
500
607
  var SessionManager = class {
501
608
  sessions = /* @__PURE__ */ new Map();
609
+ store;
610
+ constructor(store = null) {
611
+ this.store = store;
612
+ }
502
613
  async createSession(channelId, agentName, workingDirectory, agentManager) {
503
614
  const agentInstance = await agentManager.spawn(agentName, workingDirectory);
504
- const session = new Session({ channelId, agentName, workingDirectory, agentInstance });
615
+ const session = new Session({
616
+ channelId,
617
+ agentName,
618
+ workingDirectory,
619
+ agentInstance
620
+ });
505
621
  this.sessions.set(session.id, session);
622
+ session.agentSessionId = session.agentInstance.sessionId;
623
+ if (this.store) {
624
+ await this.store.save({
625
+ sessionId: session.id,
626
+ agentSessionId: session.agentInstance.sessionId,
627
+ agentName: session.agentName,
628
+ workingDir: session.workingDirectory,
629
+ channelId,
630
+ status: session.status,
631
+ createdAt: session.createdAt.toISOString(),
632
+ lastActiveAt: (/* @__PURE__ */ new Date()).toISOString(),
633
+ name: session.name,
634
+ platform: {}
635
+ });
636
+ }
506
637
  return session;
507
638
  }
508
639
  getSession(sessionId) {
@@ -516,9 +647,44 @@ var SessionManager = class {
516
647
  }
517
648
  return void 0;
518
649
  }
650
+ registerSession(session) {
651
+ this.sessions.set(session.id, session);
652
+ }
653
+ async updateSessionPlatform(sessionId, platform) {
654
+ if (!this.store) return;
655
+ const record = this.store.get(sessionId);
656
+ if (record) {
657
+ await this.store.save({ ...record, platform });
658
+ }
659
+ }
660
+ async updateSessionActivity(sessionId) {
661
+ if (!this.store) return;
662
+ const record = this.store.get(sessionId);
663
+ if (record) {
664
+ await this.store.save({
665
+ ...record,
666
+ lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
667
+ });
668
+ }
669
+ }
670
+ async updateSessionStatus(sessionId, status) {
671
+ if (!this.store) return;
672
+ const record = this.store.get(sessionId);
673
+ if (record) {
674
+ await this.store.save({ ...record, status });
675
+ }
676
+ }
519
677
  async cancelSession(sessionId) {
520
678
  const session = this.sessions.get(sessionId);
521
- if (session) await session.cancel();
679
+ if (session) {
680
+ await session.cancel();
681
+ if (this.store) {
682
+ const record = this.store.get(sessionId);
683
+ if (record) {
684
+ await this.store.save({ ...record, status: "cancelled" });
685
+ }
686
+ }
687
+ }
522
688
  }
523
689
  listSessions(channelId) {
524
690
  const all = Array.from(this.sessions.values());
@@ -526,6 +692,14 @@ var SessionManager = class {
526
692
  return all;
527
693
  }
528
694
  async destroyAll() {
695
+ if (this.store) {
696
+ for (const session of this.sessions.values()) {
697
+ const record = this.store.get(session.id);
698
+ if (record) {
699
+ await this.store.save({ ...record, status: "finished" });
700
+ }
701
+ }
702
+ }
529
703
  for (const session of this.sessions.values()) {
530
704
  await session.destroy();
531
705
  }
@@ -552,18 +726,218 @@ var NotificationManager = class {
552
726
  };
553
727
 
554
728
  // src/core/core.ts
555
- var log2 = createChildLogger({ module: "core" });
729
+ import path3 from "path";
730
+ import os from "os";
731
+
732
+ // src/core/session-store.ts
733
+ import fs2 from "fs";
734
+ import path2 from "path";
735
+ var log2 = createChildLogger({ module: "session-store" });
736
+ var DEBOUNCE_MS = 2e3;
737
+ var JsonFileSessionStore = class {
738
+ records = /* @__PURE__ */ new Map();
739
+ filePath;
740
+ ttlDays;
741
+ debounceTimer = null;
742
+ cleanupInterval = null;
743
+ flushHandler = null;
744
+ constructor(filePath, ttlDays) {
745
+ this.filePath = filePath;
746
+ this.ttlDays = ttlDays;
747
+ this.load();
748
+ this.cleanup();
749
+ this.cleanupInterval = setInterval(
750
+ () => this.cleanup(),
751
+ 24 * 60 * 60 * 1e3
752
+ );
753
+ this.flushHandler = () => this.flushSync();
754
+ process.on("SIGTERM", this.flushHandler);
755
+ process.on("SIGINT", this.flushHandler);
756
+ process.on("exit", this.flushHandler);
757
+ }
758
+ async save(record) {
759
+ this.records.set(record.sessionId, { ...record });
760
+ this.scheduleDiskWrite();
761
+ }
762
+ get(sessionId) {
763
+ return this.records.get(sessionId);
764
+ }
765
+ findByPlatform(channelId, predicate) {
766
+ for (const record of this.records.values()) {
767
+ if (record.channelId === channelId && predicate(record.platform)) {
768
+ return record;
769
+ }
770
+ }
771
+ return void 0;
772
+ }
773
+ list(channelId) {
774
+ const all = [...this.records.values()];
775
+ if (channelId) return all.filter((r) => r.channelId === channelId);
776
+ return all;
777
+ }
778
+ async remove(sessionId) {
779
+ this.records.delete(sessionId);
780
+ this.scheduleDiskWrite();
781
+ }
782
+ flushSync() {
783
+ if (this.debounceTimer) {
784
+ clearTimeout(this.debounceTimer);
785
+ this.debounceTimer = null;
786
+ }
787
+ const data = {
788
+ version: 1,
789
+ sessions: Object.fromEntries(this.records)
790
+ };
791
+ const dir = path2.dirname(this.filePath);
792
+ if (!fs2.existsSync(dir)) fs2.mkdirSync(dir, { recursive: true });
793
+ fs2.writeFileSync(this.filePath, JSON.stringify(data, null, 2));
794
+ }
795
+ destroy() {
796
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
797
+ if (this.cleanupInterval) clearInterval(this.cleanupInterval);
798
+ if (this.flushHandler) {
799
+ process.removeListener("SIGTERM", this.flushHandler);
800
+ process.removeListener("SIGINT", this.flushHandler);
801
+ process.removeListener("exit", this.flushHandler);
802
+ this.flushHandler = null;
803
+ }
804
+ }
805
+ load() {
806
+ if (!fs2.existsSync(this.filePath)) return;
807
+ try {
808
+ const raw = JSON.parse(
809
+ fs2.readFileSync(this.filePath, "utf-8")
810
+ );
811
+ if (raw.version !== 1) {
812
+ log2.warn(
813
+ { version: raw.version },
814
+ "Unknown session store version, skipping load"
815
+ );
816
+ return;
817
+ }
818
+ for (const [id, record] of Object.entries(raw.sessions)) {
819
+ this.records.set(id, record);
820
+ }
821
+ log2.info({ count: this.records.size }, "Loaded session records");
822
+ } catch (err) {
823
+ log2.error({ err }, "Failed to load session store");
824
+ }
825
+ }
826
+ cleanup() {
827
+ const cutoff = Date.now() - this.ttlDays * 24 * 60 * 60 * 1e3;
828
+ let removed = 0;
829
+ for (const [id, record] of this.records) {
830
+ if (record.status === "active" || record.status === "initializing")
831
+ continue;
832
+ const lastActive = new Date(record.lastActiveAt).getTime();
833
+ if (lastActive < cutoff) {
834
+ this.records.delete(id);
835
+ removed++;
836
+ }
837
+ }
838
+ if (removed > 0) {
839
+ log2.info({ removed }, "Cleaned up expired session records");
840
+ this.scheduleDiskWrite();
841
+ }
842
+ }
843
+ scheduleDiskWrite() {
844
+ if (this.debounceTimer) clearTimeout(this.debounceTimer);
845
+ this.debounceTimer = setTimeout(() => {
846
+ this.flushSync();
847
+ }, DEBOUNCE_MS);
848
+ }
849
+ };
850
+
851
+ // src/tunnel/extract-file-info.ts
852
+ function extractFileInfo(name, kind, content) {
853
+ if (!content) return null;
854
+ if (kind && !["read", "edit", "write"].includes(kind)) return null;
855
+ const info = parseContent(content);
856
+ if (!info) return null;
857
+ if (!info.filePath) {
858
+ const pathMatch = name.match(/(?:Read|Edit|Write|View)\s+(.+)/i);
859
+ if (pathMatch) info.filePath = pathMatch[1].trim();
860
+ }
861
+ if (!info.filePath || !info.content) return null;
862
+ return info;
863
+ }
864
+ function parseContent(content) {
865
+ if (typeof content === "string") {
866
+ return { content };
867
+ }
868
+ if (Array.isArray(content)) {
869
+ for (const block of content) {
870
+ const result = parseContent(block);
871
+ if (result?.content || result?.filePath) return result;
872
+ }
873
+ return null;
874
+ }
875
+ if (typeof content === "object" && content !== null) {
876
+ const c = content;
877
+ if (c.type === "diff" && typeof c.path === "string") {
878
+ const newText = c.newText;
879
+ const oldText = c.oldText;
880
+ if (newText) {
881
+ return {
882
+ filePath: c.path,
883
+ content: newText,
884
+ oldContent: oldText ?? void 0
885
+ };
886
+ }
887
+ }
888
+ if (c.type === "content" && c.content) {
889
+ return parseContent(c.content);
890
+ }
891
+ if (c.type === "text" && typeof c.text === "string") {
892
+ return { content: c.text, filePath: c.filePath };
893
+ }
894
+ if (typeof c.text === "string") {
895
+ return { content: c.text, filePath: c.filePath };
896
+ }
897
+ if (typeof c.file_path === "string" || typeof c.filePath === "string" || typeof c.path === "string") {
898
+ const filePath = c.file_path || c.filePath || c.path;
899
+ const fileContent = c.content || c.text || c.output || c.newText;
900
+ if (typeof fileContent === "string") {
901
+ return {
902
+ filePath,
903
+ content: fileContent,
904
+ oldContent: c.old_content || c.oldText
905
+ };
906
+ }
907
+ }
908
+ if (c.input) {
909
+ const result = parseContent(c.input);
910
+ if (result) return result;
911
+ }
912
+ if (c.output) {
913
+ const result = parseContent(c.output);
914
+ if (result) return result;
915
+ }
916
+ }
917
+ return null;
918
+ }
919
+
920
+ // src/core/core.ts
921
+ var log3 = createChildLogger({ module: "core" });
556
922
  var OpenACPCore = class {
557
923
  configManager;
558
924
  agentManager;
559
925
  sessionManager;
560
926
  notificationManager;
561
927
  adapters = /* @__PURE__ */ new Map();
928
+ tunnelService;
929
+ sessionStore = null;
930
+ resumeLocks = /* @__PURE__ */ new Map();
562
931
  constructor(configManager) {
563
932
  this.configManager = configManager;
564
933
  const config = configManager.get();
565
934
  this.agentManager = new AgentManager(config);
566
- this.sessionManager = new SessionManager();
935
+ const storePath = path3.join(os.homedir(), ".openacp", "sessions.json");
936
+ this.sessionStore = new JsonFileSessionStore(
937
+ storePath,
938
+ config.sessionStore.ttlDays
939
+ );
940
+ this.sessionManager = new SessionManager(this.sessionStore);
567
941
  this.notificationManager = new NotificationManager(this.adapters);
568
942
  }
569
943
  registerAdapter(name, adapter) {
@@ -591,16 +965,33 @@ var OpenACPCore = class {
591
965
  // --- Message Routing ---
592
966
  async handleMessage(message) {
593
967
  const config = this.configManager.get();
594
- log2.debug({ channelId: message.channelId, threadId: message.threadId, userId: message.userId }, "Incoming message");
968
+ log3.debug(
969
+ {
970
+ channelId: message.channelId,
971
+ threadId: message.threadId,
972
+ userId: message.userId
973
+ },
974
+ "Incoming message"
975
+ );
595
976
  if (config.security.allowedUserIds.length > 0) {
596
977
  if (!config.security.allowedUserIds.includes(message.userId)) {
597
- log2.warn({ userId: message.userId }, "Rejected message from unauthorized user");
978
+ log3.warn(
979
+ { userId: message.userId },
980
+ "Rejected message from unauthorized user"
981
+ );
598
982
  return;
599
983
  }
600
984
  }
601
985
  const activeSessions = this.sessionManager.listSessions().filter((s) => s.status === "active" || s.status === "initializing");
602
986
  if (activeSessions.length >= config.security.maxConcurrentSessions) {
603
- log2.warn({ userId: message.userId, currentCount: activeSessions.length, max: config.security.maxConcurrentSessions }, "Session limit reached");
987
+ log3.warn(
988
+ {
989
+ userId: message.userId,
990
+ currentCount: activeSessions.length,
991
+ max: config.security.maxConcurrentSessions
992
+ },
993
+ "Session limit reached"
994
+ );
604
995
  const adapter = this.adapters.get(message.channelId);
605
996
  if (adapter) {
606
997
  await adapter.sendMessage("system", {
@@ -610,14 +1001,21 @@ var OpenACPCore = class {
610
1001
  }
611
1002
  return;
612
1003
  }
613
- const session = this.sessionManager.getSessionByThread(message.channelId, message.threadId);
1004
+ let session = this.sessionManager.getSessionByThread(
1005
+ message.channelId,
1006
+ message.threadId
1007
+ );
1008
+ if (!session) {
1009
+ session = await this.lazyResume(message) ?? void 0;
1010
+ }
614
1011
  if (!session) return;
1012
+ this.sessionManager.updateSessionActivity(session.id);
615
1013
  await session.enqueuePrompt(message.text);
616
1014
  }
617
1015
  async handleNewSession(channelId, agentName, workspacePath) {
618
1016
  const config = this.configManager.get();
619
1017
  const resolvedAgent = agentName || config.defaultAgent;
620
- log2.info({ channelId, agentName: resolvedAgent }, "New session request");
1018
+ log3.info({ channelId, agentName: resolvedAgent }, "New session request");
621
1019
  const resolvedWorkspace = this.configManager.resolveWorkspace(
622
1020
  workspacePath || config.agents[resolvedAgent]?.workingDirectory
623
1021
  );
@@ -634,7 +1032,10 @@ var OpenACPCore = class {
634
1032
  return session;
635
1033
  }
636
1034
  async handleNewChat(channelId, currentThreadId) {
637
- const currentSession = this.sessionManager.getSessionByThread(channelId, currentThreadId);
1035
+ const currentSession = this.sessionManager.getSessionByThread(
1036
+ channelId,
1037
+ currentThreadId
1038
+ );
638
1039
  if (!currentSession) return null;
639
1040
  return this.handleNewSession(
640
1041
  channelId,
@@ -642,25 +1043,148 @@ var OpenACPCore = class {
642
1043
  currentSession.workingDirectory
643
1044
  );
644
1045
  }
1046
+ // --- Lazy Resume ---
1047
+ async lazyResume(message) {
1048
+ const store = this.sessionStore;
1049
+ if (!store) return null;
1050
+ const lockKey = `${message.channelId}:${message.threadId}`;
1051
+ const existing = this.resumeLocks.get(lockKey);
1052
+ if (existing) return existing;
1053
+ const record = store.findByPlatform(
1054
+ message.channelId,
1055
+ (p) => String(p.topicId) === message.threadId
1056
+ );
1057
+ if (!record) return null;
1058
+ if (record.status === "cancelled" || record.status === "error") return null;
1059
+ const resumePromise = (async () => {
1060
+ try {
1061
+ const agentInstance = await this.agentManager.resume(
1062
+ record.agentName,
1063
+ record.workingDir,
1064
+ record.agentSessionId
1065
+ );
1066
+ const session = new Session({
1067
+ id: record.sessionId,
1068
+ channelId: record.channelId,
1069
+ agentName: record.agentName,
1070
+ workingDirectory: record.workingDir,
1071
+ agentInstance
1072
+ });
1073
+ session.threadId = message.threadId;
1074
+ session.agentSessionId = agentInstance.sessionId;
1075
+ session.status = "active";
1076
+ session.name = record.name;
1077
+ this.sessionManager.registerSession(session);
1078
+ const adapter = this.adapters.get(message.channelId);
1079
+ if (adapter) {
1080
+ this.wireSessionEvents(session, adapter);
1081
+ }
1082
+ await store.save({
1083
+ ...record,
1084
+ agentSessionId: agentInstance.sessionId,
1085
+ status: "active",
1086
+ lastActiveAt: (/* @__PURE__ */ new Date()).toISOString()
1087
+ });
1088
+ log3.info(
1089
+ { sessionId: session.id, threadId: message.threadId },
1090
+ "Lazy resume successful"
1091
+ );
1092
+ return session;
1093
+ } catch (err) {
1094
+ log3.error({ err, record }, "Lazy resume failed");
1095
+ return null;
1096
+ } finally {
1097
+ this.resumeLocks.delete(lockKey);
1098
+ }
1099
+ })();
1100
+ this.resumeLocks.set(lockKey, resumePromise);
1101
+ return resumePromise;
1102
+ }
645
1103
  // --- Event Wiring ---
646
- toOutgoingMessage(event) {
1104
+ toOutgoingMessage(event, session) {
647
1105
  switch (event.type) {
648
1106
  case "text":
649
1107
  return { type: "text", text: event.content };
650
1108
  case "thought":
651
1109
  return { type: "thought", text: event.content };
652
- case "tool_call":
653
- return { type: "tool_call", text: event.name, metadata: { id: event.id, kind: event.kind, status: event.status, content: event.content, locations: event.locations } };
654
- case "tool_update":
655
- return { type: "tool_update", text: "", metadata: { id: event.id, status: event.status, content: event.content } };
1110
+ case "tool_call": {
1111
+ const metadata = {
1112
+ id: event.id,
1113
+ kind: event.kind,
1114
+ status: event.status,
1115
+ content: event.content,
1116
+ locations: event.locations
1117
+ };
1118
+ this.enrichWithViewerLinks(event, metadata, session);
1119
+ return { type: "tool_call", text: event.name, metadata };
1120
+ }
1121
+ case "tool_update": {
1122
+ const metadata = {
1123
+ id: event.id,
1124
+ status: event.status,
1125
+ content: event.content
1126
+ };
1127
+ this.enrichWithViewerLinks(event, metadata, session);
1128
+ return { type: "tool_update", text: "", metadata };
1129
+ }
656
1130
  case "plan":
657
1131
  return { type: "plan", text: "", metadata: { entries: event.entries } };
658
1132
  case "usage":
659
- return { type: "usage", text: "", metadata: { tokensUsed: event.tokensUsed, contextSize: event.contextSize, cost: event.cost } };
1133
+ return {
1134
+ type: "usage",
1135
+ text: "",
1136
+ metadata: {
1137
+ tokensUsed: event.tokensUsed,
1138
+ contextSize: event.contextSize,
1139
+ cost: event.cost
1140
+ }
1141
+ };
660
1142
  default:
661
1143
  return { type: "text", text: "" };
662
1144
  }
663
1145
  }
1146
+ enrichWithViewerLinks(event, metadata, session) {
1147
+ if (!this.tunnelService || !session) return;
1148
+ const name = "name" in event ? event.name || "" : "";
1149
+ const kind = "kind" in event ? event.kind : void 0;
1150
+ log3.debug(
1151
+ { name, kind, status: event.status, hasContent: !!event.content },
1152
+ "enrichWithViewerLinks: inspecting event"
1153
+ );
1154
+ const fileInfo = extractFileInfo(name, kind, event.content);
1155
+ if (!fileInfo) return;
1156
+ log3.info(
1157
+ {
1158
+ name,
1159
+ kind,
1160
+ filePath: fileInfo.filePath,
1161
+ hasOldContent: !!fileInfo.oldContent
1162
+ },
1163
+ "enrichWithViewerLinks: extracted file info"
1164
+ );
1165
+ const store = this.tunnelService.getStore();
1166
+ const viewerLinks = {};
1167
+ if (fileInfo.oldContent) {
1168
+ const id2 = store.storeDiff(
1169
+ session.id,
1170
+ fileInfo.filePath,
1171
+ fileInfo.oldContent,
1172
+ fileInfo.content,
1173
+ session.workingDirectory
1174
+ );
1175
+ if (id2) viewerLinks.diff = this.tunnelService.diffUrl(id2);
1176
+ }
1177
+ const id = store.storeFile(
1178
+ session.id,
1179
+ fileInfo.filePath,
1180
+ fileInfo.content,
1181
+ session.workingDirectory
1182
+ );
1183
+ if (id) viewerLinks.file = this.tunnelService.fileUrl(id);
1184
+ if (Object.keys(viewerLinks).length > 0) {
1185
+ metadata.viewerLinks = viewerLinks;
1186
+ }
1187
+ }
664
1188
  // Public — adapters call this for assistant session wiring
665
1189
  wireSessionEvents(session, adapter) {
666
1190
  session.adapter = adapter;
@@ -672,12 +1196,19 @@ var OpenACPCore = class {
672
1196
  case "tool_update":
673
1197
  case "plan":
674
1198
  case "usage":
675
- adapter.sendMessage(session.id, this.toOutgoingMessage(event));
1199
+ adapter.sendMessage(
1200
+ session.id,
1201
+ this.toOutgoingMessage(event, session)
1202
+ );
676
1203
  break;
677
1204
  case "session_end":
678
1205
  session.status = "finished";
1206
+ this.sessionManager.updateSessionStatus(session.id, "finished");
679
1207
  adapter.cleanupSkillCommands(session.id);
680
- adapter.sendMessage(session.id, { type: "session_end", text: `Done (${event.reason})` });
1208
+ adapter.sendMessage(session.id, {
1209
+ type: "session_end",
1210
+ text: `Done (${event.reason})`
1211
+ });
681
1212
  this.notificationManager.notify(session.channelId, {
682
1213
  sessionId: session.id,
683
1214
  sessionName: session.name,
@@ -686,8 +1217,12 @@ var OpenACPCore = class {
686
1217
  });
687
1218
  break;
688
1219
  case "error":
1220
+ this.sessionManager.updateSessionStatus(session.id, "error");
689
1221
  adapter.cleanupSkillCommands(session.id);
690
- adapter.sendMessage(session.id, { type: "error", text: event.message });
1222
+ adapter.sendMessage(session.id, {
1223
+ type: "error",
1224
+ text: event.message
1225
+ });
691
1226
  this.notificationManager.notify(session.channelId, {
692
1227
  sessionId: session.id,
693
1228
  sessionName: session.name,
@@ -696,7 +1231,7 @@ var OpenACPCore = class {
696
1231
  });
697
1232
  break;
698
1233
  case "commands_update":
699
- log2.debug({ commands: event.commands }, "Commands available");
1234
+ log3.debug({ commands: event.commands }, "Commands available");
700
1235
  adapter.sendSkillCommands(session.id, event.commands);
701
1236
  break;
702
1237
  }
@@ -808,6 +1343,7 @@ function formatToolCall(tool) {
808
1343
  text += `
809
1344
  <pre>${escapeHtml(truncateContent(details))}</pre>`;
810
1345
  }
1346
+ text += formatViewerLinks(tool.viewerLinks);
811
1347
  return text;
812
1348
  }
813
1349
  function formatToolUpdate(update) {
@@ -820,6 +1356,16 @@ function formatToolUpdate(update) {
820
1356
  text += `
821
1357
  <pre>${escapeHtml(truncateContent(details))}</pre>`;
822
1358
  }
1359
+ text += formatViewerLinks(update.viewerLinks);
1360
+ return text;
1361
+ }
1362
+ function formatViewerLinks(links) {
1363
+ if (!links) return "";
1364
+ let text = "";
1365
+ if (links.file) text += `
1366
+ \u{1F4C4} <a href="${escapeHtml(links.file)}">View file</a>`;
1367
+ if (links.diff) text += `
1368
+ \u{1F4DD} <a href="${escapeHtml(links.diff)}">View diff</a>`;
823
1369
  return text;
824
1370
  }
825
1371
  function formatPlan(plan) {
@@ -999,7 +1545,7 @@ function buildDeepLink(chatId, messageId) {
999
1545
  // src/adapters/telegram/commands.ts
1000
1546
  import { InlineKeyboard } from "grammy";
1001
1547
  import { nanoid as nanoid2 } from "nanoid";
1002
- var log4 = createChildLogger({ module: "telegram-commands" });
1548
+ var log5 = createChildLogger({ module: "telegram-commands" });
1003
1549
  function setupCommands(bot, core, chatId) {
1004
1550
  bot.command("new", (ctx) => handleNew(ctx, core, chatId));
1005
1551
  bot.command("new_chat", (ctx) => handleNewChat(ctx, core, chatId));
@@ -1054,7 +1600,7 @@ async function handleNew(ctx, core, chatId) {
1054
1600
  const args = matchStr.split(" ").filter(Boolean);
1055
1601
  const agentName = args[0];
1056
1602
  const workspace = args[1];
1057
- log4.info({ userId: ctx.from?.id, agentName }, "New session command");
1603
+ log5.info({ userId: ctx.from?.id, agentName }, "New session command");
1058
1604
  let threadId;
1059
1605
  try {
1060
1606
  const topicName = `\u{1F504} New Session`;
@@ -1069,6 +1615,9 @@ async function handleNew(ctx, core, chatId) {
1069
1615
  workspace
1070
1616
  );
1071
1617
  session.threadId = String(threadId);
1618
+ await core.sessionManager.updateSessionPlatform(session.id, {
1619
+ topicId: threadId
1620
+ });
1072
1621
  const finalName = `\u{1F504} ${session.agentName} \u2014 New Session`;
1073
1622
  try {
1074
1623
  await ctx.api.editForumTopic(chatId, threadId, { name: finalName });
@@ -1084,7 +1633,7 @@ async function handleNew(ctx, core, chatId) {
1084
1633
  parse_mode: "HTML"
1085
1634
  }
1086
1635
  );
1087
- session.warmup().catch((err) => log4.error({ err }, "Warm-up error"));
1636
+ session.warmup().catch((err) => log5.error({ err }, "Warm-up error"));
1088
1637
  } catch (err) {
1089
1638
  if (threadId) {
1090
1639
  try {
@@ -1124,6 +1673,9 @@ async function handleNewChat(ctx, core, chatId) {
1124
1673
  parse_mode: "HTML"
1125
1674
  });
1126
1675
  session.threadId = String(newThreadId);
1676
+ await core.sessionManager.updateSessionPlatform(session.id, {
1677
+ topicId: newThreadId
1678
+ });
1127
1679
  await ctx.api.sendMessage(
1128
1680
  chatId,
1129
1681
  `\u2705 New chat (same agent &amp; workspace)
@@ -1134,7 +1686,7 @@ async function handleNewChat(ctx, core, chatId) {
1134
1686
  parse_mode: "HTML"
1135
1687
  }
1136
1688
  );
1137
- session.warmup().catch((err) => log4.error({ err }, "Warm-up error"));
1689
+ session.warmup().catch((err) => log5.error({ err }, "Warm-up error"));
1138
1690
  } catch (err) {
1139
1691
  const message = err instanceof Error ? err.message : String(err);
1140
1692
  await ctx.reply(`\u274C ${escapeHtml(message)}`, { parse_mode: "HTML" });
@@ -1148,7 +1700,7 @@ async function handleCancel(ctx, core) {
1148
1700
  String(threadId)
1149
1701
  );
1150
1702
  if (session) {
1151
- log4.info({ sessionId: session.id }, "Cancel session command");
1703
+ log5.info({ sessionId: session.id }, "Cancel session command");
1152
1704
  await session.cancel();
1153
1705
  await ctx.reply("\u26D4 Session cancelled.", { parse_mode: "HTML" });
1154
1706
  }
@@ -1269,7 +1821,7 @@ var STATIC_COMMANDS = [
1269
1821
  // src/adapters/telegram/permissions.ts
1270
1822
  import { InlineKeyboard as InlineKeyboard2 } from "grammy";
1271
1823
  import { nanoid as nanoid3 } from "nanoid";
1272
- var log5 = createChildLogger({ module: "telegram-permissions" });
1824
+ var log6 = createChildLogger({ module: "telegram-permissions" });
1273
1825
  var PermissionHandler = class {
1274
1826
  constructor(bot, chatId, getSession, sendNotification) {
1275
1827
  this.bot = bot;
@@ -1329,7 +1881,7 @@ ${escapeHtml(request.description)}`,
1329
1881
  }
1330
1882
  const session = this.getSession(pending.sessionId);
1331
1883
  const isAllow = pending.options.find((o) => o.id === optionId)?.isAllow ?? false;
1332
- log5.info({ requestId: pending.requestId, optionId, isAllow }, "Permission responded");
1884
+ log6.info({ requestId: pending.requestId, optionId, isAllow }, "Permission responded");
1333
1885
  if (session?.pendingPermission?.requestId === pending.requestId) {
1334
1886
  session.pendingPermission.resolve(optionId);
1335
1887
  session.pendingPermission = void 0;
@@ -1396,7 +1948,7 @@ function redirectToAssistant(chatId, assistantTopicId) {
1396
1948
  }
1397
1949
 
1398
1950
  // src/adapters/telegram/adapter.ts
1399
- var log6 = createChildLogger({ module: "telegram" });
1951
+ var log7 = createChildLogger({ module: "telegram" });
1400
1952
  var TelegramAdapter = class extends ChannelAdapter {
1401
1953
  bot;
1402
1954
  telegramConfig;
@@ -1414,10 +1966,10 @@ var TelegramAdapter = class extends ChannelAdapter {
1414
1966
  this.telegramConfig = config;
1415
1967
  }
1416
1968
  async start() {
1417
- this.bot = new Bot(this.telegramConfig.botToken);
1969
+ this.bot = new Bot(this.telegramConfig.botToken, { client: { fetch } });
1418
1970
  this.bot.catch((err) => {
1419
1971
  const rootCause = err.error instanceof Error ? err.error : err;
1420
- log6.error({ err: rootCause }, "Telegram bot error");
1972
+ log7.error({ err: rootCause }, "Telegram bot error");
1421
1973
  });
1422
1974
  this.bot.api.config.use((prev, method, payload, signal) => {
1423
1975
  if (method === "getUpdates") {
@@ -1470,7 +2022,7 @@ var TelegramAdapter = class extends ChannelAdapter {
1470
2022
  this.setupRoutes();
1471
2023
  this.bot.start({
1472
2024
  allowed_updates: ["message", "callback_query"],
1473
- onStart: () => log6.info(
2025
+ onStart: () => log7.info(
1474
2026
  { chatId: this.telegramConfig.chatId },
1475
2027
  "Telegram bot started"
1476
2028
  )
@@ -1482,7 +2034,7 @@ var TelegramAdapter = class extends ChannelAdapter {
1482
2034
  this.assistantTopicId
1483
2035
  );
1484
2036
  } catch (err) {
1485
- log6.error({ err }, "Failed to spawn assistant");
2037
+ log7.error({ err }, "Failed to spawn assistant");
1486
2038
  }
1487
2039
  try {
1488
2040
  const config = this.core.configManager.get();
@@ -1503,7 +2055,7 @@ Workspace: <code>${workspace}</code>
1503
2055
  reply_markup: buildMenuKeyboard()
1504
2056
  });
1505
2057
  } catch (err) {
1506
- log6.warn({ err }, "Failed to send welcome message");
2058
+ log7.warn({ err }, "Failed to send welcome message");
1507
2059
  }
1508
2060
  }
1509
2061
  async stop() {
@@ -1511,7 +2063,7 @@ Workspace: <code>${workspace}</code>
1511
2063
  await this.assistantSession.destroy();
1512
2064
  }
1513
2065
  await this.bot.stop();
1514
- log6.info("Telegram bot stopped");
2066
+ log7.info("Telegram bot stopped");
1515
2067
  }
1516
2068
  setupRoutes() {
1517
2069
  this.bot.on("message:text", async (ctx) => {
@@ -1529,7 +2081,7 @@ Workspace: <code>${workspace}</code>
1529
2081
  ctx.replyWithChatAction("typing").catch(() => {
1530
2082
  });
1531
2083
  handleAssistantMessage(this.assistantSession, ctx.message.text).catch(
1532
- (err) => log6.error({ err }, "Assistant error")
2084
+ (err) => log7.error({ err }, "Assistant error")
1533
2085
  );
1534
2086
  return;
1535
2087
  }
@@ -1540,7 +2092,7 @@ Workspace: <code>${workspace}</code>
1540
2092
  threadId: String(threadId),
1541
2093
  userId: String(ctx.from.id),
1542
2094
  text: ctx.message.text
1543
- }).catch((err) => log6.error({ err }, "handleMessage error"));
2095
+ }).catch((err) => log7.error({ err }, "handleMessage error"));
1544
2096
  });
1545
2097
  }
1546
2098
  // --- ChannelAdapter implementations ---
@@ -1585,7 +2137,8 @@ Workspace: <code>${workspace}</code>
1585
2137
  this.toolCallMessages.get(sessionId).set(meta.id, {
1586
2138
  msgId: msg.message_id,
1587
2139
  name: meta.name,
1588
- kind: meta.kind
2140
+ kind: meta.kind,
2141
+ viewerLinks: meta.viewerLinks
1589
2142
  });
1590
2143
  break;
1591
2144
  }
@@ -1593,10 +2146,13 @@ Workspace: <code>${workspace}</code>
1593
2146
  const meta = content.metadata;
1594
2147
  const toolState = this.toolCallMessages.get(sessionId)?.get(meta.id);
1595
2148
  if (toolState) {
2149
+ const viewerLinks = meta.viewerLinks || toolState.viewerLinks;
2150
+ if (meta.viewerLinks) toolState.viewerLinks = meta.viewerLinks;
1596
2151
  const merged = {
1597
2152
  ...meta,
1598
2153
  name: meta.name || toolState.name,
1599
- kind: meta.kind || toolState.kind
2154
+ kind: meta.kind || toolState.kind,
2155
+ viewerLinks
1600
2156
  };
1601
2157
  try {
1602
2158
  await this.bot.api.editMessageText(
@@ -1614,7 +2170,9 @@ Workspace: <code>${workspace}</code>
1614
2170
  await this.finalizeDraft(sessionId);
1615
2171
  await this.bot.api.sendMessage(
1616
2172
  this.telegramConfig.chatId,
1617
- formatPlan(content.metadata),
2173
+ formatPlan(
2174
+ content.metadata
2175
+ ),
1618
2176
  {
1619
2177
  message_thread_id: threadId,
1620
2178
  parse_mode: "HTML",
@@ -1626,7 +2184,9 @@ Workspace: <code>${workspace}</code>
1626
2184
  case "usage": {
1627
2185
  await this.bot.api.sendMessage(
1628
2186
  this.telegramConfig.chatId,
1629
- formatUsage(content.metadata),
2187
+ formatUsage(
2188
+ content.metadata
2189
+ ),
1630
2190
  {
1631
2191
  message_thread_id: threadId,
1632
2192
  parse_mode: "HTML",
@@ -1667,7 +2227,7 @@ Workspace: <code>${workspace}</code>
1667
2227
  }
1668
2228
  }
1669
2229
  async sendPermissionRequest(sessionId, request) {
1670
- log6.info({ sessionId, requestId: request.id }, "Permission request sent");
2230
+ log7.info({ sessionId, requestId: request.id }, "Permission request sent");
1671
2231
  const session = this.core.sessionManager.getSession(
1672
2232
  sessionId
1673
2233
  );
@@ -1675,7 +2235,7 @@ Workspace: <code>${workspace}</code>
1675
2235
  await this.permissionHandler.sendPermissionRequest(session, request);
1676
2236
  }
1677
2237
  async sendNotification(notification) {
1678
- log6.info(
2238
+ log7.info(
1679
2239
  { sessionId: notification.sessionId, type: notification.type },
1680
2240
  "Notification sent"
1681
2241
  );
@@ -1701,7 +2261,7 @@ Workspace: <code>${workspace}</code>
1701
2261
  });
1702
2262
  }
1703
2263
  async createSessionThread(sessionId, name) {
1704
- log6.info({ sessionId, name }, "Session topic created");
2264
+ log7.info({ sessionId, name }, "Session topic created");
1705
2265
  return String(
1706
2266
  await createSessionTopic(this.bot, this.telegramConfig.chatId, name)
1707
2267
  );
@@ -1719,7 +2279,9 @@ Workspace: <code>${workspace}</code>
1719
2279
  );
1720
2280
  }
1721
2281
  async sendSkillCommands(sessionId, commands) {
1722
- const session = this.core.sessionManager.getSession(sessionId);
2282
+ const session = this.core.sessionManager.getSession(
2283
+ sessionId
2284
+ );
1723
2285
  if (!session) return;
1724
2286
  const threadId = Number(session.threadId);
1725
2287
  if (!threadId) return;
@@ -1755,11 +2317,15 @@ Workspace: <code>${workspace}</code>
1755
2317
  }
1756
2318
  );
1757
2319
  this.skillMessages.set(sessionId, msg.message_id);
1758
- await this.bot.api.pinChatMessage(this.telegramConfig.chatId, msg.message_id, {
1759
- disable_notification: true
1760
- });
2320
+ await this.bot.api.pinChatMessage(
2321
+ this.telegramConfig.chatId,
2322
+ msg.message_id,
2323
+ {
2324
+ disable_notification: true
2325
+ }
2326
+ );
1761
2327
  } catch (err) {
1762
- log6.error({ err, sessionId }, "Failed to send skill commands");
2328
+ log7.error({ err, sessionId }, "Failed to send skill commands");
1763
2329
  }
1764
2330
  await this.updateCommandAutocomplete(session.agentName, commands);
1765
2331
  }
@@ -1790,9 +2356,15 @@ Workspace: <code>${workspace}</code>
1790
2356
  await this.bot.api.setMyCommands(all, {
1791
2357
  scope: { type: "chat", chat_id: this.telegramConfig.chatId }
1792
2358
  });
1793
- log6.info({ count: all.length, skills: validSkills.length }, "Updated command autocomplete");
2359
+ log7.info(
2360
+ { count: all.length, skills: validSkills.length },
2361
+ "Updated command autocomplete"
2362
+ );
1794
2363
  } catch (err) {
1795
- log6.error({ err, commands: all }, "Failed to update command autocomplete");
2364
+ log7.error(
2365
+ { err, commands: all },
2366
+ "Failed to update command autocomplete"
2367
+ );
1796
2368
  }
1797
2369
  }
1798
2370
  async finalizeDraft(sessionId) {
@@ -1817,4 +2389,4 @@ export {
1817
2389
  ChannelAdapter,
1818
2390
  TelegramAdapter
1819
2391
  };
1820
- //# sourceMappingURL=chunk-TKOYKVXH.js.map
2392
+ //# sourceMappingURL=chunk-HTXK4NLG.js.map