@openacp/cli 2026.331.2 → 2026.331.3

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/cli.js CHANGED
@@ -3929,7 +3929,7 @@ function initLogger(config) {
3929
3929
  target: "pino-pretty",
3930
3930
  options: {
3931
3931
  colorize: true,
3932
- translateTime: "HH:mm:ss",
3932
+ translateTime: "SYS:HH:MM:ss",
3933
3933
  ignore: "pid,hostname",
3934
3934
  singleLine: true
3935
3935
  },
@@ -4964,7 +4964,7 @@ var init_tunnel_registry = __esm({
4964
4964
  this.providerOptions = opts.providerOptions ?? {};
4965
4965
  this.registryPath = opts.registryPath ?? path16.join(os9.homedir(), ".openacp", "tunnels.json");
4966
4966
  }
4967
- async add(port, opts) {
4967
+ async add(port, opts, _autoRetry = true) {
4968
4968
  if (this.entries.has(port)) {
4969
4969
  const existing = this.entries.get(port);
4970
4970
  if (existing.entry.status === "active" || existing.entry.status === "starting") {
@@ -5018,6 +5018,15 @@ var init_tunnel_registry = __esm({
5018
5018
  entry.status = "failed";
5019
5019
  log7.error({ port, err: err.message }, "Tunnel failed to start");
5020
5020
  this.scheduleSave();
5021
+ const live = this.entries.get(port);
5022
+ if (_autoRetry && live && !this.shuttingDown && live.entry.retryCount < MAX_RETRIES) {
5023
+ const delay = BASE_RETRY_DELAY_MS * Math.pow(2, live.entry.retryCount);
5024
+ log7.warn(
5025
+ { port, retry: live.entry.retryCount + 1, maxRetries: MAX_RETRIES, delayMs: delay },
5026
+ "Scheduling retry after initial start failure"
5027
+ );
5028
+ live.retryTimer = setTimeout(() => this.retry(port, opts), delay);
5029
+ }
5021
5030
  throw err;
5022
5031
  });
5023
5032
  this.entries.set(port, { entry, process: provider, spawnPromise, retryTimer: null });
@@ -5034,7 +5043,7 @@ var init_tunnel_registry = __esm({
5034
5043
  if (live.retryTimer) clearTimeout(live.retryTimer);
5035
5044
  this.entries.delete(port);
5036
5045
  try {
5037
- const entry = await this.add(port, opts);
5046
+ const entry = await this.add(port, opts, false);
5038
5047
  entry.retryCount = retryCount;
5039
5048
  } catch (err) {
5040
5049
  log7.error({ port, err: err.message, retry: retryCount }, "Tunnel retry failed");
@@ -15237,27 +15246,28 @@ var init_adapter = __esm({
15237
15246
  }
15238
15247
  return prev(method, payload, signal);
15239
15248
  });
15240
- await this.bot.api.setMyCommands(STATIC_COMMANDS, {
15241
- scope: { type: "chat", chat_id: this.telegramConfig.chatId }
15242
- });
15249
+ this.registerCommandsWithRetry();
15243
15250
  this.bot.use((ctx, next) => {
15244
15251
  const chatId = ctx.chat?.id ?? ctx.callbackQuery?.message?.chat?.id;
15245
15252
  if (chatId !== this.telegramConfig.chatId) return;
15246
15253
  return next();
15247
15254
  });
15248
- const topics = await ensureTopics(
15249
- this.bot,
15250
- this.telegramConfig.chatId,
15251
- this.telegramConfig,
15252
- async (updates) => {
15253
- if (this.saveTopicIds) {
15254
- await this.saveTopicIds(updates);
15255
- } else {
15256
- await this.core.configManager.save({
15257
- channels: { telegram: updates }
15258
- });
15255
+ const topics = await this.retryWithBackoff(
15256
+ () => ensureTopics(
15257
+ this.bot,
15258
+ this.telegramConfig.chatId,
15259
+ this.telegramConfig,
15260
+ async (updates) => {
15261
+ if (this.saveTopicIds) {
15262
+ await this.saveTopicIds(updates);
15263
+ } else {
15264
+ await this.core.configManager.save({
15265
+ channels: { telegram: updates }
15266
+ });
15267
+ }
15259
15268
  }
15260
- }
15269
+ ),
15270
+ "ensureTopics"
15261
15271
  );
15262
15272
  this.notificationTopicId = topics.notificationTopicId;
15263
15273
  this.assistantTopicId = topics.assistantTopicId;
@@ -15505,6 +15515,40 @@ var init_adapter = __esm({
15505
15515
  });
15506
15516
  }
15507
15517
  }
15518
+ /**
15519
+ * Retry an async operation with exponential backoff.
15520
+ * Used for Telegram API calls that may fail due to transient network issues.
15521
+ */
15522
+ async retryWithBackoff(fn, label, maxRetries = 5, baseDelayMs = 2e3) {
15523
+ for (let attempt = 1; attempt <= maxRetries; attempt++) {
15524
+ try {
15525
+ return await fn();
15526
+ } catch (err) {
15527
+ if (attempt === maxRetries) throw err;
15528
+ const delay = baseDelayMs * Math.pow(2, attempt - 1);
15529
+ log26.warn(
15530
+ { err, attempt, maxRetries, delayMs: delay, operation: label },
15531
+ `${label} failed, retrying in ${delay}ms`
15532
+ );
15533
+ await new Promise((r) => setTimeout(r, delay));
15534
+ }
15535
+ }
15536
+ throw new Error("unreachable");
15537
+ }
15538
+ /**
15539
+ * Register Telegram commands in the background with retries.
15540
+ * Non-critical — bot works fine without autocomplete commands.
15541
+ */
15542
+ registerCommandsWithRetry() {
15543
+ this.retryWithBackoff(
15544
+ () => this.bot.api.setMyCommands(STATIC_COMMANDS, {
15545
+ scope: { type: "chat", chat_id: this.telegramConfig.chatId }
15546
+ }),
15547
+ "setMyCommands"
15548
+ ).catch((err) => {
15549
+ log26.warn({ err }, "Failed to register Telegram commands after retries (non-critical)");
15550
+ });
15551
+ }
15508
15552
  async stop() {
15509
15553
  for (const tracker of this.sessionTrackers.values()) {
15510
15554
  tracker.destroy();
@@ -23097,8 +23141,19 @@ var init_core = __esm({
23097
23141
  this.agentCatalog.refreshRegistryIfStale().catch((err) => {
23098
23142
  log37.warn({ err }, "Background registry refresh failed");
23099
23143
  });
23100
- for (const adapter of this.adapters.values()) {
23101
- await adapter.start();
23144
+ const failures = [];
23145
+ for (const [name, adapter] of this.adapters.entries()) {
23146
+ try {
23147
+ await adapter.start();
23148
+ } catch (err) {
23149
+ log37.error({ err, adapter: name }, `Adapter "${name}" failed to start`);
23150
+ failures.push({ name, error: err });
23151
+ }
23152
+ }
23153
+ if (failures.length > 0 && failures.length === this.adapters.size) {
23154
+ throw new Error(
23155
+ `All adapters failed to start: ${failures.map((f) => f.name).join(", ")}`
23156
+ );
23102
23157
  }
23103
23158
  }
23104
23159
  async stop() {