@n1creator/openacp-cli 2026.712.10 → 2026.712.11

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 CHANGED
@@ -227,9 +227,11 @@ not globally intercepted. Credentials live in a separate mode-0600 secret store
227
227
  and never appear in route files, agent definitions, status responses, or
228
228
  structured OpenACP logs.
229
229
 
230
- Manage routes from any connector with `/proxy`, from the CLI with
231
- `openacp proxy`, or through `/api/v1/proxy`. Channel changes are tested before
232
- they are saved. See [Scoped Proxy Routing](docs/gitbook/features/proxy-routing.md).
230
+ In Telegram, open **Settings Proxy Management** or use `/proxy` directly.
231
+ Both paths render the same connector-neutral proxy home; other adapters can use
232
+ that `/proxy` command model too. CLI and REST automation remain available through
233
+ `openacp proxy` and `/api/v1/proxy`. Channel changes are tested before they are
234
+ saved. See [Scoped Proxy Routing](docs/gitbook/features/proxy-routing.md).
233
235
 
234
236
  ### Operations
235
237
 
@@ -312,7 +314,8 @@ The protected JSON file supports a Quick URL mode: use either separate
312
314
  mutually exclusive. A URL must include an explicit port; credentials are parsed
313
315
  and stored separately, and the original URL is never persisted or returned.
314
316
 
315
- The connector-neutral `/proxy` interface now provides admin-only add/edit,
317
+ The connector-neutral `/proxy` interface requires `network:proxy:manage` before
318
+ showing status, profiles, routes, diagnostics, or tests. It provides add/edit,
316
319
  candidate test-before-save, credential clearing, paginated route controls, and
317
320
  atomic delete-with-reassignment. Telegram deletes credential replies before use;
318
321
  if that guarantee is unavailable, OpenACP refuses the value and directs the
package/dist/cli.js CHANGED
@@ -16676,6 +16676,37 @@ var init_resume = __esm({
16676
16676
  }
16677
16677
  });
16678
16678
 
16679
+ // src/plugins/telegram/callback-navigation.ts
16680
+ function contextualCommandCallback(command2, target) {
16681
+ if (!command2.startsWith("/")) throw new Error("Telegram navigation commands must start with /");
16682
+ const data = target === "settings" ? `${SETTINGS_PREFIX}${command2}` : void 0;
16683
+ return data && Buffer.byteLength(data, "utf8") <= 64 ? data : void 0;
16684
+ }
16685
+ function settingsCommandCallback(command2) {
16686
+ const data = contextualCommandCallback(command2, "settings");
16687
+ if (!data) throw new Error("Telegram navigation callback exceeds 64 bytes");
16688
+ return data;
16689
+ }
16690
+ function decodeCommandCallback(data) {
16691
+ if (data.startsWith(SETTINGS_PREFIX)) {
16692
+ return { command: data.slice(SETTINGS_PREFIX.length), returnTarget: "settings" };
16693
+ }
16694
+ return { command: data.slice(2) };
16695
+ }
16696
+ function returnButton(target) {
16697
+ switch (target) {
16698
+ case "settings":
16699
+ return { text: "\u25C0\uFE0F Back to Settings", callback_data: "s:back:refresh" };
16700
+ }
16701
+ }
16702
+ var SETTINGS_PREFIX;
16703
+ var init_callback_navigation = __esm({
16704
+ "src/plugins/telegram/callback-navigation.ts"() {
16705
+ "use strict";
16706
+ SETTINGS_PREFIX = "c/@settings:";
16707
+ }
16708
+ });
16709
+
16679
16710
  // src/plugins/telegram/commands/menu.ts
16680
16711
  var menu_exports = {};
16681
16712
  __export(menu_exports, {
@@ -16788,6 +16819,7 @@ async function buildSettingsKeyboard(core) {
16788
16819
  kb.text(`${label}`, `s:input:${field.path}`).row();
16789
16820
  }
16790
16821
  }
16822
+ kb.text("\u{1F310} Proxy Management", settingsCommandCallback("/proxy")).row();
16791
16823
  kb.text("\u25C0\uFE0F Back to Menu", "s:back");
16792
16824
  return kb;
16793
16825
  }
@@ -16980,6 +17012,7 @@ var init_settings = __esm({
16980
17012
  "use strict";
16981
17013
  init_config_registry();
16982
17014
  init_log();
17015
+ init_callback_navigation();
16983
17016
  log21 = createChildLogger({ module: "telegram-settings" });
16984
17017
  }
16985
17018
  });
@@ -20790,6 +20823,9 @@ function stalePolicyResponse(reopen) {
20790
20823
  options: [{ label: "Refresh", command: reopen }, { label: "Proxy menu", command: "/proxy status" }]
20791
20824
  };
20792
20825
  }
20826
+ function proxyCapabilityError() {
20827
+ return { type: "error", message: PROXY_CAPABILITY_ERROR };
20828
+ }
20793
20829
  function registerProxyCommand(registry, _core) {
20794
20830
  const core = _core;
20795
20831
  registry.register({
@@ -20821,8 +20857,9 @@ function registerProxyCommand(registry, _core) {
20821
20857
  "wizard-auth",
20822
20858
  "wizard-review"
20823
20859
  ]);
20860
+ if (!await canManageProxy(core, args2)) return proxyCapabilityError();
20824
20861
  if (action && mutations.has(action) && !await canManageProxy(core, args2)) {
20825
- return { type: "error", message: "This action requires network:proxy:manage capability." };
20862
+ return proxyCapabilityError();
20826
20863
  }
20827
20864
  if (!action || action === "status") {
20828
20865
  return {
@@ -21306,10 +21343,14 @@ Credentials: ${profile.hasCredentials ? "configured" : "none"} \xB7 failClosed:
21306
21343
  async function canManageProxy(core, args2) {
21307
21344
  const identity = core.lifecycleManager?.serviceRegistry?.get("identity");
21308
21345
  if (!identity) return false;
21309
- const user = await identity.getUserByIdentity(formatIdentityId(args2.channelId, args2.userId));
21310
- return Boolean(user && hasIdentityCapability(user.role, "network:proxy:manage"));
21346
+ try {
21347
+ const user = await identity.getUserByIdentity(formatIdentityId(args2.channelId, args2.userId));
21348
+ return Boolean(user && hasIdentityCapability(user.role, "network:proxy:manage"));
21349
+ } catch {
21350
+ return false;
21351
+ }
21311
21352
  }
21312
- var DRAFT_TTL_MS, drafts;
21353
+ var DRAFT_TTL_MS, drafts, PROXY_CAPABILITY_ERROR;
21313
21354
  var init_proxy3 = __esm({
21314
21355
  "src/core/commands/proxy.ts"() {
21315
21356
  "use strict";
@@ -21319,6 +21360,7 @@ var init_proxy3 = __esm({
21319
21360
  init_proxy_service();
21320
21361
  DRAFT_TTL_MS = 10 * 6e4;
21321
21362
  drafts = /* @__PURE__ */ new Map();
21363
+ PROXY_CAPABILITY_ERROR = "Proxy management requires network:proxy:manage capability.";
21322
21364
  }
21323
21365
  });
21324
21366
 
@@ -21519,6 +21561,7 @@ var init_adapter2 = __esm({
21519
21561
  init_command_sync();
21520
21562
  init_command_ownership_store();
21521
21563
  init_instance_context();
21564
+ init_callback_navigation();
21522
21565
  log29 = createChildLogger({ module: "telegram" });
21523
21566
  HISTORICAL_OPENACP_COMMAND_NAMES = /* @__PURE__ */ new Set([
21524
21567
  ...STATIC_COMMANDS.map((command2) => command2.command),
@@ -21847,7 +21890,13 @@ var init_adapter2 = __esm({
21847
21890
  }
21848
21891
  });
21849
21892
  if (response.type !== "silent" && response.type !== "delegated") {
21850
- await this.renderCommandResponse(response, ctx.chat.id, topicIdForInput, String(ctx.from?.id));
21893
+ await this.renderCommandResponse(
21894
+ response,
21895
+ ctx.chat.id,
21896
+ topicIdForInput,
21897
+ String(ctx.from?.id),
21898
+ pending.returnTarget
21899
+ );
21851
21900
  }
21852
21901
  return;
21853
21902
  }
@@ -21930,7 +21979,8 @@ var init_adapter2 = __esm({
21930
21979
  return;
21931
21980
  }
21932
21981
  const data = ctx.callbackQuery.data;
21933
- const command2 = this.fromCallbackData(data);
21982
+ const callback = this.fromCallbackData(data);
21983
+ const command2 = callback.command;
21934
21984
  const registry = this.core.lifecycleManager?.serviceRegistry?.get(
21935
21985
  "command-registry"
21936
21986
  );
@@ -21959,16 +22009,23 @@ var init_adapter2 = __esm({
21959
22009
  await ctx.answerCallbackQuery();
21960
22010
  if (response.type !== "silent" && response.type !== "delegated") {
21961
22011
  if (response.type === "input") {
21962
- await this.renderCommandResponse(response, chatId, topicId, String(ctx.from?.id));
22012
+ await this.renderCommandResponse(
22013
+ response,
22014
+ chatId,
22015
+ topicId,
22016
+ String(ctx.from?.id),
22017
+ callback.returnTarget
22018
+ );
21963
22019
  return;
21964
22020
  }
21965
22021
  if (response.type === "menu") {
21966
22022
  const keyboard = response.options.map((opt) => [
21967
22023
  {
21968
22024
  text: `${opt.label}${opt.hint ? ` \u2014 ${opt.hint}` : ""}`,
21969
- callback_data: this.toCallbackData(opt.command)
22025
+ callback_data: this.toCallbackData(opt.command, callback.returnTarget)
21970
22026
  }
21971
22027
  ]);
22028
+ this.appendReturnButton(keyboard, callback.returnTarget);
21972
22029
  try {
21973
22030
  await ctx.editMessageText(response.title, {
21974
22031
  reply_markup: { inline_keyboard: keyboard }
@@ -21987,7 +22044,11 @@ var init_adapter2 = __esm({
21987
22044
  parseMode = "Markdown";
21988
22045
  }
21989
22046
  try {
21990
- await ctx.editMessageText(text5, { ...parseMode && { parse_mode: parseMode } });
22047
+ const returnMarkup = this.returnMarkup(callback.returnTarget);
22048
+ await ctx.editMessageText(text5, {
22049
+ ...parseMode && { parse_mode: parseMode },
22050
+ ...returnMarkup && { reply_markup: returnMarkup }
22051
+ });
21991
22052
  } catch {
21992
22053
  }
21993
22054
  }
@@ -22588,11 +22649,13 @@ System topics have been created. Tap${assistantTopicLink} to get started.`,
22588
22649
  log29.info("Telegram bot stopped");
22589
22650
  }
22590
22651
  // --- CommandRegistry response rendering ---
22591
- async renderCommandResponse(response, chatId, topicId, userId) {
22652
+ async renderCommandResponse(response, chatId, topicId, userId, returnTarget) {
22653
+ const returnMarkup = this.returnMarkup(returnTarget);
22592
22654
  switch (response.type) {
22593
22655
  case "text":
22594
22656
  await this.bot.api.sendMessage(chatId, response.text, {
22595
- message_thread_id: topicId
22657
+ message_thread_id: topicId,
22658
+ ...returnMarkup && { reply_markup: returnMarkup }
22596
22659
  });
22597
22660
  break;
22598
22661
  case "adaptive": {
@@ -22600,7 +22663,8 @@ System topics have been created. Tap${assistantTopicLink} to get started.`,
22600
22663
  const text5 = variant?.text ?? response.fallback;
22601
22664
  await this.bot.api.sendMessage(chatId, text5, {
22602
22665
  message_thread_id: topicId,
22603
- ...variant?.parse_mode && { parse_mode: variant.parse_mode }
22666
+ ...variant?.parse_mode && { parse_mode: variant.parse_mode },
22667
+ ...returnMarkup && { reply_markup: returnMarkup }
22604
22668
  });
22605
22669
  break;
22606
22670
  }
@@ -22608,16 +22672,17 @@ System topics have been created. Tap${assistantTopicLink} to get started.`,
22608
22672
  await this.bot.api.sendMessage(
22609
22673
  chatId,
22610
22674
  `\u26A0\uFE0F ${response.message}`,
22611
- { message_thread_id: topicId }
22675
+ { message_thread_id: topicId, ...returnMarkup && { reply_markup: returnMarkup } }
22612
22676
  );
22613
22677
  break;
22614
22678
  case "menu": {
22615
22679
  const keyboard = response.options.map((opt) => [
22616
22680
  {
22617
22681
  text: `${opt.label}${opt.hint ? ` \u2014 ${opt.hint}` : ""}`,
22618
- callback_data: this.toCallbackData(opt.command)
22682
+ callback_data: this.toCallbackData(opt.command, returnTarget)
22619
22683
  }
22620
22684
  ]);
22685
+ this.appendReturnButton(keyboard, returnTarget);
22621
22686
  await this.bot.api.sendMessage(chatId, response.title, {
22622
22687
  message_thread_id: topicId,
22623
22688
  reply_markup: { inline_keyboard: keyboard }
@@ -22631,7 +22696,8 @@ System topics have been created. Tap${assistantTopicLink} to get started.`,
22631
22696
  const text5 = `${response.title}
22632
22697
  ${lines.join("\n")}`;
22633
22698
  await this.bot.api.sendMessage(chatId, text5, {
22634
- message_thread_id: topicId
22699
+ message_thread_id: topicId,
22700
+ ...returnMarkup && { reply_markup: returnMarkup }
22635
22701
  });
22636
22702
  break;
22637
22703
  }
@@ -22640,16 +22706,17 @@ ${lines.join("\n")}`;
22640
22706
  [
22641
22707
  {
22642
22708
  text: "\u2705 Yes",
22643
- callback_data: this.toCallbackData(response.onYes)
22709
+ callback_data: this.toCallbackData(response.onYes, returnTarget)
22644
22710
  }
22645
22711
  ]
22646
22712
  ];
22647
22713
  if (response.onNo) {
22648
22714
  buttons[0].push({
22649
22715
  text: "\u274C No",
22650
- callback_data: this.toCallbackData(response.onNo)
22716
+ callback_data: this.toCallbackData(response.onNo, returnTarget)
22651
22717
  });
22652
22718
  }
22719
+ this.appendReturnButton(buttons, returnTarget);
22653
22720
  await this.bot.api.sendMessage(chatId, response.question, {
22654
22721
  message_thread_id: topicId,
22655
22722
  reply_markup: { inline_keyboard: buttons }
@@ -22658,7 +22725,10 @@ ${lines.join("\n")}`;
22658
22725
  }
22659
22726
  case "input": {
22660
22727
  if (!userId) {
22661
- await this.bot.api.sendMessage(chatId, response.fallback, { message_thread_id: topicId });
22728
+ await this.bot.api.sendMessage(chatId, response.fallback, {
22729
+ message_thread_id: topicId,
22730
+ ...returnMarkup && { reply_markup: returnMarkup }
22731
+ });
22662
22732
  break;
22663
22733
  }
22664
22734
  const key = `${chatId}:${userId}:${topicId ?? 0}`;
@@ -22680,7 +22750,8 @@ ${lines.join("\n")}`;
22680
22750
  sensitive: response.sensitive === true,
22681
22751
  fallback: response.fallback,
22682
22752
  expiresAt: Date.now() + (response.expiresInMs ?? 10 * 6e4),
22683
- promptMessageId: promptMessage.message_id
22753
+ promptMessageId: promptMessage.message_id,
22754
+ returnTarget
22684
22755
  });
22685
22756
  break;
22686
22757
  }
@@ -22688,11 +22759,15 @@ ${lines.join("\n")}`;
22688
22759
  break;
22689
22760
  }
22690
22761
  }
22691
- toCallbackData(command2) {
22762
+ toCallbackData(command2, returnTarget) {
22692
22763
  const data = `c/${command2}`;
22693
- if (data.length <= 64) return data;
22764
+ if (!returnTarget && Buffer.byteLength(data, "utf8") <= 64) return data;
22765
+ if (returnTarget) {
22766
+ const contextual = contextualCommandCallback(command2, returnTarget);
22767
+ if (contextual) return contextual;
22768
+ }
22694
22769
  const id = String(++this.callbackCounter);
22695
- this.callbackCache.set(id, command2);
22770
+ this.callbackCache.set(id, { command: command2, returnTarget });
22696
22771
  if (this.callbackCache.size > 1e3) {
22697
22772
  const first = this.callbackCache.keys().next().value;
22698
22773
  if (first) this.callbackCache.delete(first);
@@ -22701,9 +22776,15 @@ ${lines.join("\n")}`;
22701
22776
  }
22702
22777
  fromCallbackData(data) {
22703
22778
  if (data.startsWith("c/#")) {
22704
- return this.callbackCache.get(data.slice(3)) ?? data.slice(2);
22779
+ return this.callbackCache.get(data.slice(3)) ?? { command: data.slice(2) };
22705
22780
  }
22706
- return data.slice(2);
22781
+ return decodeCommandCallback(data);
22782
+ }
22783
+ returnMarkup(returnTarget) {
22784
+ return returnTarget ? { inline_keyboard: [[returnButton(returnTarget)]] } : void 0;
22785
+ }
22786
+ appendReturnButton(keyboard, returnTarget) {
22787
+ if (returnTarget) keyboard.push([returnButton(returnTarget)]);
22707
22788
  }
22708
22789
  setupRoutes() {
22709
22790
  this.bot.on("message:text", async (ctx) => {
@@ -31405,7 +31486,9 @@ function registerCoreMenuItems(registry) {
31405
31486
  label: "\u{1F310} Proxy Routing",
31406
31487
  priority: 32,
31407
31488
  group: "config",
31408
- action: { type: "command", command: "/proxy" }
31489
+ action: { type: "command", command: "/proxy" },
31490
+ // Keep already-sent m:core:proxy buttons valid while nesting new entry points under Settings.
31491
+ visible: () => false
31409
31492
  });
31410
31493
  registry.register({
31411
31494
  id: "core:restart",