@openacp/cli 2026.41.1 → 2026.41.2

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/dist/index.js CHANGED
@@ -2032,6 +2032,7 @@ async function createApiServer(options) {
2032
2032
  return { port: Number(url.port), host: url.hostname };
2033
2033
  } catch (err) {
2034
2034
  if (err?.code === "EADDRINUSE" && attempt < maxRetries && port < 65535) {
2035
+ console.log(`[api-server] Port ${port} in use, trying ${port + 1}...`);
2035
2036
  port++;
2036
2037
  continue;
2037
2038
  }
@@ -3549,14 +3550,6 @@ ${stderr}`
3549
3550
  };
3550
3551
  break;
3551
3552
  }
3552
- case "current_mode_update": {
3553
- const cm = update;
3554
- event = {
3555
- type: "current_mode_update",
3556
- modeId: cm.currentModeId
3557
- };
3558
- break;
3559
- }
3560
3553
  case "config_option_update": {
3561
3554
  const co = update;
3562
3555
  event = {
@@ -3574,10 +3567,10 @@ ${stderr}`
3574
3567
  break;
3575
3568
  }
3576
3569
  // NOTE: model_update is NOT a session update type in the ACP SDK schema.
3577
- // Model changes are applied via the unstable_setSessionModel() method and
3578
- // the response is synchronous — the SDK does not push a model_update
3579
- // notification to the client. Therefore AgentEvent "model_update" cannot
3580
- // originate from sessionUpdate and must be emitted by callers of setModel()
3570
+ // Model changes are applied via setSessionConfigOption() and the response
3571
+ // is synchronous — the SDK does not push a model_update notification to
3572
+ // the client. Therefore AgentEvent "model_update" cannot originate from
3573
+ // sessionUpdate and must be emitted by callers of setConfigOption()
3581
3574
  // if they need to propagate the change downstream.
3582
3575
  default:
3583
3576
  return;
@@ -3659,9 +3652,6 @@ ${stderr}`
3659
3652
  };
3660
3653
  }
3661
3654
  // ── New ACP methods ──────────────────────────────────────────────────
3662
- async setMode(modeId) {
3663
- await this.connection.setSessionMode({ sessionId: this.sessionId, modeId });
3664
- }
3665
3655
  async setConfigOption(configId, value) {
3666
3656
  return await this.connection.setSessionConfigOption({
3667
3657
  sessionId: this.sessionId,
@@ -3669,12 +3659,6 @@ ${stderr}`
3669
3659
  ...value
3670
3660
  });
3671
3661
  }
3672
- async setModel(modelId) {
3673
- await this.connection.unstable_setSessionModel({
3674
- sessionId: this.sessionId,
3675
- modelId
3676
- });
3677
- }
3678
3662
  async listSessions(cwd, cursor) {
3679
3663
  return await this.connection.listSessions({
3680
3664
  cwd: cwd ?? null,
@@ -3946,12 +3930,8 @@ var Session = class extends TypedEmitter {
3946
3930
  name;
3947
3931
  createdAt = /* @__PURE__ */ new Date();
3948
3932
  voiceMode = "off";
3949
- dangerousMode = false;
3950
- currentMode;
3951
- availableModes = [];
3952
3933
  configOptions = [];
3953
- currentModel;
3954
- availableModels = [];
3934
+ clientOverrides = {};
3955
3935
  agentCapabilities;
3956
3936
  archiving = false;
3957
3937
  promptCount = 0;
@@ -4245,34 +4225,28 @@ ${result.text}` : result.text;
4245
4225
  }
4246
4226
  }
4247
4227
  // --- ACP Mode / Config / Model State ---
4248
- setInitialAcpState(state) {
4249
- if (state.modes) {
4250
- this.currentMode = state.modes.currentModeId;
4251
- this.availableModes = state.modes.availableModes;
4252
- }
4253
- if (state.configOptions) {
4254
- this.configOptions = state.configOptions;
4255
- }
4256
- if (state.models) {
4257
- this.currentModel = state.models.currentModelId;
4258
- this.availableModels = state.models.availableModels;
4259
- }
4260
- if (state.agentCapabilities) {
4261
- this.agentCapabilities = state.agentCapabilities;
4262
- }
4228
+ setInitialConfigOptions(options) {
4229
+ this.configOptions = options ?? [];
4230
+ }
4231
+ setAgentCapabilities(caps) {
4232
+ this.agentCapabilities = caps;
4233
+ }
4234
+ getConfigOption(id) {
4235
+ return this.configOptions.find((o) => o.id === id);
4236
+ }
4237
+ getConfigByCategory(category) {
4238
+ return this.configOptions.find((o) => o.category === category);
4239
+ }
4240
+ getConfigValue(id) {
4241
+ const option = this.getConfigOption(id);
4242
+ if (!option) return void 0;
4243
+ return String(option.currentValue);
4263
4244
  }
4264
4245
  /** Set session name explicitly and emit 'named' event */
4265
4246
  setName(name) {
4266
4247
  this.name = name;
4267
4248
  this.emit("named", name);
4268
4249
  }
4269
- async updateMode(modeId) {
4270
- if (this.middlewareChain) {
4271
- const result = await this.middlewareChain.execute("mode:beforeChange", { sessionId: this.id, fromMode: this.currentMode, toMode: modeId }, async (p) => p);
4272
- if (!result) return;
4273
- }
4274
- this.currentMode = modeId;
4275
- }
4276
4250
  async updateConfigOptions(options) {
4277
4251
  if (this.middlewareChain) {
4278
4252
  const result = await this.middlewareChain.execute("config:beforeChange", { sessionId: this.id, configId: "options", oldValue: this.configOptions, newValue: options }, async (p) => p);
@@ -4280,21 +4254,10 @@ ${result.text}` : result.text;
4280
4254
  }
4281
4255
  this.configOptions = options;
4282
4256
  }
4283
- async updateModel(modelId) {
4284
- if (this.middlewareChain) {
4285
- const result = await this.middlewareChain.execute("model:beforeChange", { sessionId: this.id, fromModel: this.currentModel, toModel: modelId }, async (p) => p);
4286
- if (!result) return;
4287
- }
4288
- this.currentModel = modelId;
4289
- }
4290
4257
  /** Snapshot of current ACP state for persistence */
4291
4258
  toAcpStateSnapshot() {
4292
4259
  return {
4293
- currentMode: this.currentMode,
4294
- availableModes: this.availableModes.length > 0 ? this.availableModes : void 0,
4295
4260
  configOptions: this.configOptions.length > 0 ? this.configOptions : void 0,
4296
- currentModel: this.currentModel,
4297
- availableModels: this.availableModels.length > 0 ? this.availableModels : void 0,
4298
4261
  agentCapabilities: this.agentCapabilities
4299
4262
  };
4300
4263
  }
@@ -4344,10 +4307,6 @@ ${result.text}` : result.text;
4344
4307
  this.agentSessionId = newAgent.sessionId;
4345
4308
  this.promptCount = 0;
4346
4309
  this.agentCapabilities = void 0;
4347
- this.currentMode = void 0;
4348
- this.availableModes = [];
4349
- this.currentModel = void 0;
4350
- this.availableModels = [];
4351
4310
  this.configOptions = [];
4352
4311
  this.log.info({ from: this.agentSwitchHistory.at(-1).agentName, to: agentName }, "Agent switched");
4353
4312
  }
@@ -4608,24 +4567,12 @@ var MessageTransformer = class {
4608
4567
  text: `Session updated: ${event.title ?? ""}`.trim(),
4609
4568
  metadata: { title: event.title, updatedAt: event.updatedAt }
4610
4569
  };
4611
- case "current_mode_update":
4612
- return {
4613
- type: "mode_change",
4614
- text: `Mode: ${event.modeId}`,
4615
- metadata: { modeId: event.modeId }
4616
- };
4617
4570
  case "config_option_update":
4618
4571
  return {
4619
4572
  type: "config_update",
4620
4573
  text: "Config updated",
4621
4574
  metadata: { options: event.options }
4622
4575
  };
4623
- case "model_update":
4624
- return {
4625
- type: "model_update",
4626
- text: `Model: ${event.modelId}`,
4627
- metadata: { modelId: event.modelId }
4628
- };
4629
4576
  case "user_message_chunk":
4630
4577
  return {
4631
4578
  type: "user_replay",
@@ -4774,7 +4721,7 @@ var SessionManager = class {
4774
4721
  createdAt: session.createdAt.toISOString(),
4775
4722
  lastActiveAt: (/* @__PURE__ */ new Date()).toISOString(),
4776
4723
  name: session.name,
4777
- dangerousMode: false,
4724
+ clientOverrides: {},
4778
4725
  platform: {}
4779
4726
  });
4780
4727
  }
@@ -4906,6 +4853,15 @@ var SessionManager = class {
4906
4853
 
4907
4854
  // src/core/sessions/session-bridge.ts
4908
4855
  init_log();
4856
+
4857
+ // src/core/utils/bypass-detection.ts
4858
+ var BYPASS_KEYWORDS = ["bypass", "dangerous", "skip", "dontask", "dont_ask", "auto_accept"];
4859
+ function isPermissionBypass(value) {
4860
+ const lower = value.toLowerCase();
4861
+ return BYPASS_KEYWORDS.some((kw) => lower.includes(kw));
4862
+ }
4863
+
4864
+ // src/core/sessions/session-bridge.ts
4909
4865
  var log6 = createChildLogger({ module: "session-bridge" });
4910
4866
  var SessionBridge = class {
4911
4867
  constructor(session, adapter, deps) {
@@ -5111,24 +5067,12 @@ var SessionBridge = class {
5111
5067
  outgoing = this.deps.messageTransformer.transform(event);
5112
5068
  this.sendMessage(this.session.id, outgoing);
5113
5069
  break;
5114
- case "current_mode_update":
5115
- this.session.updateMode(event.modeId);
5116
- this.persistAcpState();
5117
- outgoing = this.deps.messageTransformer.transform(event);
5118
- this.sendMessage(this.session.id, outgoing);
5119
- break;
5120
5070
  case "config_option_update":
5121
5071
  this.session.updateConfigOptions(event.options);
5122
5072
  this.persistAcpState();
5123
5073
  outgoing = this.deps.messageTransformer.transform(event);
5124
5074
  this.sendMessage(this.session.id, outgoing);
5125
5075
  break;
5126
- case "model_update":
5127
- this.session.updateModel(event.modelId);
5128
- this.persistAcpState();
5129
- outgoing = this.deps.messageTransformer.transform(event);
5130
- this.sendMessage(this.session.id, outgoing);
5131
- break;
5132
5076
  case "user_message_chunk":
5133
5077
  outgoing = this.deps.messageTransformer.transform(event);
5134
5078
  this.sendMessage(this.session.id, outgoing);
@@ -5148,7 +5092,7 @@ var SessionBridge = class {
5148
5092
  });
5149
5093
  return outgoing;
5150
5094
  }
5151
- /** Persist current ACP state (mode, config, model) to session store as cache */
5095
+ /** Persist current ACP state (configOptions, agentCapabilities) to session store as cache */
5152
5096
  persistAcpState() {
5153
5097
  this.deps.sessionManager.patchRecord(this.session.id, {
5154
5098
  acpState: this.session.toAcpStateSnapshot()
@@ -5203,12 +5147,17 @@ var SessionBridge = class {
5203
5147
  return allowOption.id;
5204
5148
  }
5205
5149
  }
5206
- if (this.session.dangerousMode) {
5150
+ const modeOption = this.session.getConfigByCategory("mode");
5151
+ const isAgentBypass = modeOption && isPermissionBypass(
5152
+ typeof modeOption.currentValue === "string" ? modeOption.currentValue : ""
5153
+ );
5154
+ const isClientBypass = this.session.clientOverrides.bypassPermissions;
5155
+ if (isAgentBypass || isClientBypass) {
5207
5156
  const allowOption = permReq.options.find((o) => o.isAllow);
5208
5157
  if (allowOption) {
5209
5158
  log6.info(
5210
- { sessionId: this.session.id, requestId: permReq.id, optionId: allowOption.id },
5211
- "Dangerous mode: auto-approving permission"
5159
+ { sessionId: this.session.id, requestId: permReq.id, optionId: allowOption.id, agentBypass: !!isAgentBypass, clientBypass: !!isClientBypass },
5160
+ "Bypass mode: auto-approving permission"
5212
5161
  );
5213
5162
  if (mw) {
5214
5163
  mw.execute("permission:afterResolve", {
@@ -5406,16 +5355,14 @@ var SessionFactory = class {
5406
5355
  }
5407
5356
  const resp = agentInstance.initialSessionResponse;
5408
5357
  if (resp) {
5409
- session.setInitialAcpState({
5410
- modes: resp.modes ?? null,
5411
- configOptions: resp.configOptions ?? null,
5412
- models: resp.models ?? null,
5413
- agentCapabilities: agentInstance.agentCapabilities ?? null
5414
- });
5358
+ if (resp.configOptions) {
5359
+ session.setInitialConfigOptions(resp.configOptions);
5360
+ }
5361
+ if (agentInstance.agentCapabilities) {
5362
+ session.setAgentCapabilities(agentInstance.agentCapabilities);
5363
+ }
5415
5364
  } else if (agentInstance.agentCapabilities) {
5416
- session.setInitialAcpState({
5417
- agentCapabilities: agentInstance.agentCapabilities
5418
- });
5365
+ session.setAgentCapabilities(agentInstance.agentCapabilities);
5419
5366
  }
5420
5367
  this.sessionManager.registerSession(session);
5421
5368
  this.eventBus.emit("session:created", {
@@ -5465,18 +5412,21 @@ var SessionFactory = class {
5465
5412
  threadId
5466
5413
  });
5467
5414
  session.activate();
5468
- session.dangerousMode = record.dangerousMode ?? false;
5415
+ if (record.clientOverrides) {
5416
+ session.clientOverrides = record.clientOverrides;
5417
+ } else if (record.dangerousMode) {
5418
+ session.clientOverrides = { bypassPermissions: true };
5419
+ }
5469
5420
  if (record.firstAgent) session.firstAgent = record.firstAgent;
5470
5421
  if (record.agentSwitchHistory) session.agentSwitchHistory = record.agentSwitchHistory;
5471
5422
  if (record.currentPromptCount != null) session.promptCount = record.currentPromptCount;
5472
5423
  if (record.acpState) {
5473
- const s = record.acpState;
5474
- session.setInitialAcpState({
5475
- modes: s.currentMode && s.availableModes ? { currentModeId: s.currentMode, availableModes: s.availableModes } : null,
5476
- configOptions: s.configOptions ?? null,
5477
- models: s.currentModel && s.availableModels ? { currentModelId: s.currentModel, availableModels: s.availableModels } : null,
5478
- agentCapabilities: s.agentCapabilities ?? null
5479
- });
5424
+ if (record.acpState.configOptions) {
5425
+ session.setInitialConfigOptions(record.acpState.configOptions);
5426
+ }
5427
+ if (record.acpState.agentCapabilities) {
5428
+ session.setAgentCapabilities(record.acpState.agentCapabilities);
5429
+ }
5480
5430
  }
5481
5431
  log7.info({ sessionId: session.id, threadId }, "Lazy resume successful");
5482
5432
  return session;
@@ -7111,6 +7061,7 @@ var LifecycleManager = class {
7111
7061
  } catch (err) {
7112
7062
  this._failed.add(plugin.name);
7113
7063
  ctx.cleanup();
7064
+ console.error(`[lifecycle] Plugin ${plugin.name} setup() FAILED:`, err);
7114
7065
  this.getPluginLogger(plugin.name).error(`setup() failed: ${err}`);
7115
7066
  this.eventBus?.emit("plugin:failed", { name: plugin.name, error: String(err) });
7116
7067
  }
@@ -7384,6 +7335,13 @@ var OpenACPCore = class {
7384
7335
  { channelId: message.channelId, threadId: message.threadId },
7385
7336
  "No session found for thread (in-memory miss + lazy resume returned null)"
7386
7337
  );
7338
+ const adapter = this.adapters.get(message.channelId);
7339
+ if (adapter) {
7340
+ await adapter.sendMessage(message.threadId, {
7341
+ type: "error",
7342
+ text: "\u26A0\uFE0F No active session in this topic. Use /new to start one."
7343
+ });
7344
+ }
7387
7345
  return;
7388
7346
  }
7389
7347
  this.sessionManager.patchRecord(session.id, {
@@ -11128,8 +11086,12 @@ var SendQueue = class {
11128
11086
  const result = await item.fn();
11129
11087
  item.resolve(result);
11130
11088
  } catch (err) {
11131
- this.config.onError?.(err instanceof Error ? err : new Error(String(err)));
11132
- item.reject(err);
11089
+ if (err instanceof Error && "description" in err && typeof err.description === "string" && err.description.includes("message is not modified")) {
11090
+ item.resolve(void 0);
11091
+ } else {
11092
+ this.config.onError?.(err instanceof Error ? err : new Error(String(err)));
11093
+ item.reject(err);
11094
+ }
11133
11095
  } finally {
11134
11096
  const now = Date.now();
11135
11097
  this.lastExec = now;
@@ -12385,14 +12347,15 @@ function setupDangerousModeCallbacks(bot, core) {
12385
12347
  const sessionId = ctx.callbackQuery.data.slice(2);
12386
12348
  const session = core.sessionManager.getSession(sessionId);
12387
12349
  if (session) {
12388
- session.dangerousMode = !session.dangerousMode;
12350
+ const newDangerousMode2 = !session.clientOverrides.bypassPermissions;
12351
+ session.clientOverrides.bypassPermissions = newDangerousMode2;
12389
12352
  log18.info(
12390
- { sessionId, dangerousMode: session.dangerousMode },
12353
+ { sessionId, dangerousMode: newDangerousMode2 },
12391
12354
  "Dangerous mode toggled via button"
12392
12355
  );
12393
- core.sessionManager.patchRecord(sessionId, { dangerousMode: session.dangerousMode }).catch(() => {
12356
+ core.sessionManager.patchRecord(sessionId, { clientOverrides: session.clientOverrides }).catch(() => {
12394
12357
  });
12395
- const toastText2 = session.dangerousMode ? "\u2620\uFE0F Dangerous mode enabled \u2014 permissions auto-approved" : "\u{1F510} Dangerous mode disabled \u2014 permissions shown normally";
12358
+ const toastText2 = newDangerousMode2 ? "\u2620\uFE0F Dangerous mode enabled \u2014 permissions auto-approved" : "\u{1F510} Dangerous mode disabled \u2014 permissions shown normally";
12396
12359
  try {
12397
12360
  await ctx.answerCallbackQuery({ text: toastText2 });
12398
12361
  } catch {
@@ -12401,7 +12364,7 @@ function setupDangerousModeCallbacks(bot, core) {
12401
12364
  await ctx.editMessageReplyMarkup({
12402
12365
  reply_markup: buildSessionControlKeyboard(
12403
12366
  sessionId,
12404
- session.dangerousMode,
12367
+ newDangerousMode2,
12405
12368
  session.voiceMode === "on"
12406
12369
  )
12407
12370
  });
@@ -12419,8 +12382,8 @@ function setupDangerousModeCallbacks(bot, core) {
12419
12382
  }
12420
12383
  return;
12421
12384
  }
12422
- const newDangerousMode = !(record.dangerousMode ?? false);
12423
- core.sessionManager.patchRecord(sessionId, { dangerousMode: newDangerousMode }).catch(() => {
12385
+ const newDangerousMode = !(record.clientOverrides?.bypassPermissions ?? record.dangerousMode ?? false);
12386
+ core.sessionManager.patchRecord(sessionId, { clientOverrides: { bypassPermissions: newDangerousMode } }).catch(() => {
12424
12387
  });
12425
12388
  log18.info(
12426
12389
  { sessionId, dangerousMode: newDangerousMode },
@@ -12451,19 +12414,19 @@ async function handleEnableDangerous(ctx, core) {
12451
12414
  });
12452
12415
  return;
12453
12416
  }
12454
- const session = core.sessionManager.getSessionByThread(
12417
+ const session = await core.getOrResumeSession(
12455
12418
  "telegram",
12456
12419
  String(threadId)
12457
12420
  );
12458
12421
  if (session) {
12459
- if (session.dangerousMode) {
12422
+ if (session.clientOverrides.bypassPermissions) {
12460
12423
  await ctx.reply("\u2620\uFE0F Dangerous mode is already enabled.", {
12461
12424
  parse_mode: "HTML"
12462
12425
  });
12463
12426
  return;
12464
12427
  }
12465
- session.dangerousMode = true;
12466
- core.sessionManager.patchRecord(session.id, { dangerousMode: true }).catch(() => {
12428
+ session.clientOverrides.bypassPermissions = true;
12429
+ core.sessionManager.patchRecord(session.id, { clientOverrides: session.clientOverrides }).catch(() => {
12467
12430
  });
12468
12431
  } else {
12469
12432
  const record = core.sessionManager.getRecordByThread(
@@ -12476,13 +12439,13 @@ async function handleEnableDangerous(ctx, core) {
12476
12439
  });
12477
12440
  return;
12478
12441
  }
12479
- if (record.dangerousMode) {
12442
+ if (record.clientOverrides?.bypassPermissions ?? record.dangerousMode) {
12480
12443
  await ctx.reply("\u2620\uFE0F Dangerous mode is already enabled.", {
12481
12444
  parse_mode: "HTML"
12482
12445
  });
12483
12446
  return;
12484
12447
  }
12485
- core.sessionManager.patchRecord(record.sessionId, { dangerousMode: true }).catch(() => {
12448
+ core.sessionManager.patchRecord(record.sessionId, { clientOverrides: { bypassPermissions: true } }).catch(() => {
12486
12449
  });
12487
12450
  }
12488
12451
  await ctx.reply(
@@ -12502,19 +12465,19 @@ async function handleDisableDangerous(ctx, core) {
12502
12465
  });
12503
12466
  return;
12504
12467
  }
12505
- const session = core.sessionManager.getSessionByThread(
12468
+ const session = await core.getOrResumeSession(
12506
12469
  "telegram",
12507
12470
  String(threadId)
12508
12471
  );
12509
12472
  if (session) {
12510
- if (!session.dangerousMode) {
12473
+ if (!session.clientOverrides.bypassPermissions) {
12511
12474
  await ctx.reply("\u{1F510} Dangerous mode is already disabled.", {
12512
12475
  parse_mode: "HTML"
12513
12476
  });
12514
12477
  return;
12515
12478
  }
12516
- session.dangerousMode = false;
12517
- core.sessionManager.patchRecord(session.id, { dangerousMode: false }).catch(() => {
12479
+ session.clientOverrides.bypassPermissions = false;
12480
+ core.sessionManager.patchRecord(session.id, { clientOverrides: session.clientOverrides }).catch(() => {
12518
12481
  });
12519
12482
  } else {
12520
12483
  const record = core.sessionManager.getRecordByThread(
@@ -12527,13 +12490,13 @@ async function handleDisableDangerous(ctx, core) {
12527
12490
  });
12528
12491
  return;
12529
12492
  }
12530
- if (!record.dangerousMode) {
12493
+ if (!(record.clientOverrides?.bypassPermissions ?? record.dangerousMode)) {
12531
12494
  await ctx.reply("\u{1F510} Dangerous mode is already disabled.", {
12532
12495
  parse_mode: "HTML"
12533
12496
  });
12534
12497
  return;
12535
12498
  }
12536
- core.sessionManager.patchRecord(record.sessionId, { dangerousMode: false }).catch(() => {
12499
+ core.sessionManager.patchRecord(record.sessionId, { clientOverrides: { bypassPermissions: false } }).catch(() => {
12537
12500
  });
12538
12501
  }
12539
12502
  await ctx.reply(
@@ -12583,7 +12546,7 @@ function setupTTSCallbacks(bot, core) {
12583
12546
  await ctx.editMessageReplyMarkup({
12584
12547
  reply_markup: buildSessionControlKeyboard(
12585
12548
  sessionId,
12586
- session.dangerousMode,
12549
+ session.clientOverrides.bypassPermissions ?? false,
12587
12550
  newMode === "on"
12588
12551
  )
12589
12552
  });
@@ -12652,7 +12615,7 @@ async function handleOutputMode(ctx, core) {
12652
12615
  await ctx.reply("\u26A0\uFE0F This command must be used in a session topic.", { parse_mode: "HTML" });
12653
12616
  return;
12654
12617
  }
12655
- const session = core.sessionManager.getSessionByThread(
12618
+ const session = await core.getOrResumeSession(
12656
12619
  "telegram",
12657
12620
  String(threadId)
12658
12621
  );
@@ -12949,7 +12912,7 @@ async function handleNewChat(ctx, core, chatId) {
12949
12912
  );
12950
12913
  return;
12951
12914
  }
12952
- const currentSession = core.sessionManager.getSessionByThread(
12915
+ const currentSession = await core.getOrResumeSession(
12953
12916
  "telegram",
12954
12917
  String(threadId)
12955
12918
  );
@@ -13218,7 +13181,7 @@ async function handleCancel(ctx, core, assistant) {
13218
13181
  async function handleStatus(ctx, core) {
13219
13182
  const threadId = ctx.message?.message_thread_id;
13220
13183
  if (threadId) {
13221
- const session = core.sessionManager.getSessionByThread(
13184
+ const session = await core.getOrResumeSession(
13222
13185
  "telegram",
13223
13186
  String(threadId)
13224
13187
  );
@@ -15714,6 +15677,7 @@ var MessageDraft = class {
15714
15677
  flushTimer;
15715
15678
  flushPromise = Promise.resolve();
15716
15679
  lastSentBuffer = "";
15680
+ lastSentHtml = "";
15717
15681
  displayTruncated = false;
15718
15682
  tracer;
15719
15683
  append(text3) {
@@ -15773,6 +15737,8 @@ var MessageDraft = class {
15773
15737
  this.firstFlushPending = false;
15774
15738
  }
15775
15739
  } else {
15740
+ if (html === this.lastSentHtml) return;
15741
+ this.lastSentHtml = html;
15776
15742
  try {
15777
15743
  const result = await this.sendQueue.enqueue(
15778
15744
  () => this.bot.api.editMessageText(this.chatId, this.messageId, html, {
@@ -16340,10 +16306,10 @@ var TelegramAdapter = class extends MessagingAdapter {
16340
16306
  const chatId = ctx.chat.id;
16341
16307
  const topicId = ctx.message.message_thread_id;
16342
16308
  try {
16343
- const sessionId = topicId != null ? this.core.sessionManager.getSessionByThread(
16309
+ const sessionId = topicId != null ? (await this.core.getOrResumeSession(
16344
16310
  "telegram",
16345
16311
  String(topicId)
16346
- )?.id ?? null : null;
16312
+ ))?.id ?? null : null;
16347
16313
  const response = await registry.execute(text3, {
16348
16314
  raw: "",
16349
16315
  sessionId,
@@ -16379,10 +16345,10 @@ var TelegramAdapter = class extends MessagingAdapter {
16379
16345
  const chatId = ctx.chat.id;
16380
16346
  const topicId = ctx.callbackQuery.message?.message_thread_id;
16381
16347
  try {
16382
- const sessionId = topicId != null ? this.core.sessionManager.getSessionByThread(
16348
+ const sessionId = topicId != null ? (await this.core.getOrResumeSession(
16383
16349
  "telegram",
16384
16350
  String(topicId)
16385
- )?.id ?? null : null;
16351
+ ))?.id ?? null : null;
16386
16352
  const response = await registry.execute(command, {
16387
16353
  raw: "",
16388
16354
  sessionId,
@@ -16464,7 +16430,7 @@ var TelegramAdapter = class extends MessagingAdapter {
16464
16430
  });
16465
16431
  return;
16466
16432
  }
16467
- const session = this.core.sessionManager.getSessionByThread(
16433
+ const session = await this.core.getOrResumeSession(
16468
16434
  "telegram",
16469
16435
  String(threadId)
16470
16436
  );
@@ -16736,10 +16702,10 @@ ${lines.join("\n")}`;
16736
16702
  );
16737
16703
  return;
16738
16704
  }
16739
- const sessionId = this.core.sessionManager.getSessionByThread(
16705
+ const sessionId = (await this.core.getOrResumeSession(
16740
16706
  "telegram",
16741
16707
  String(threadId)
16742
- )?.id;
16708
+ ))?.id;
16743
16709
  if (sessionId) {
16744
16710
  this.getTracer(sessionId)?.log("telegram", { action: "incoming:message", sessionId, userId: String(ctx.from?.id), text: ctx.message?.text });
16745
16711
  await this.draftManager.finalize(sessionId, this.assistantSession?.id);
@@ -17227,11 +17193,11 @@ Task completed.
17227
17193
  if (!threadId) return;
17228
17194
  await this.skillManager.send(sessionId, threadId, commands);
17229
17195
  }
17230
- resolveSessionId(threadId) {
17231
- return this.core.sessionManager.getSessionByThread(
17196
+ async resolveSessionId(threadId) {
17197
+ return (await this.core.getOrResumeSession(
17232
17198
  "telegram",
17233
17199
  String(threadId)
17234
- )?.id;
17200
+ ))?.id;
17235
17201
  }
17236
17202
  async downloadTelegramFile(fileId) {
17237
17203
  try {
@@ -17252,7 +17218,7 @@ Task completed.
17252
17218
  if (!downloaded) return;
17253
17219
  let buffer = downloaded.buffer;
17254
17220
  let originalFilePath;
17255
- const sessionId = this.resolveSessionId(threadId) || "unknown";
17221
+ const sessionId = await this.resolveSessionId(threadId) || "unknown";
17256
17222
  if (convertOggToWav) {
17257
17223
  const oggAtt = await this.fileService.saveFile(
17258
17224
  sessionId,
@@ -17287,7 +17253,7 @@ Task completed.
17287
17253
  }
17288
17254
  return;
17289
17255
  }
17290
- const sid = this.resolveSessionId(threadId);
17256
+ const sid = await this.resolveSessionId(threadId);
17291
17257
  if (sid) await this.draftManager.finalize(sid, this.assistantSession?.id);
17292
17258
  this.core.handleMessage({
17293
17259
  channelId: "telegram",