@n1creator/openacp-cli 2026.712.10 → 2026.712.12

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
@@ -2276,18 +2276,17 @@ This file provides context for AI coding agents (Claude, Cursor, etc.) working o
2276
2276
 
2277
2277
  OpenACP is an open-source platform that bridges AI coding agents (Claude Code, Codex, etc.) to messaging platforms (Telegram, Discord, Slack) and custom UIs via the Agent Client Protocol (ACP). It features a microkernel plugin architecture where all features \u2014 adapters, services, commands \u2014 are plugins.
2278
2278
 
2279
- - **Website & Docs**: https://openacp.gitbook.io/docs
2279
+ - **Documentation**: https://github.com/an1creator/OpenACP/tree/main/docs/gitbook
2280
2280
  - **GitHub**: https://github.com/an1creator/OpenACP
2281
- - **Plugin Registry**: https://github.com/Open-ACP/plugin-registry
2282
2281
 
2283
2282
  Key documentation pages:
2284
- - [Getting Started](https://openacp.gitbook.io/docs/getting-started) \u2014 What is OpenACP, quickstart
2285
- - [Plugin Development](https://openacp.gitbook.io/docs/extending/building-plugins) \u2014 How to build plugins
2286
- - [Architecture](https://openacp.gitbook.io/docs/extending/architecture) \u2014 System design, plugin lifecycle
2287
- - [Dev Mode](https://openacp.gitbook.io/docs/extending/dev-mode) \u2014 Hot-reload development workflow
2288
- - [CLI Commands](https://openacp.gitbook.io/docs/api-reference/cli-commands) \u2014 Full CLI reference
2289
- - [Platform Setup](https://openacp.gitbook.io/docs/platform-setup) \u2014 Telegram, Discord, Slack guides
2290
- - [Configuration](https://openacp.gitbook.io/docs/self-hosting/configuration) \u2014 Config and settings reference
2283
+ - [Getting Started](https://github.com/an1creator/OpenACP/tree/main/docs/gitbook/getting-started) \u2014 What is OpenACP, quickstart
2284
+ - [Plugin Development](https://github.com/an1creator/OpenACP/blob/main/docs/gitbook/extending/getting-started-plugin.md) \u2014 How to build plugins
2285
+ - [Architecture](https://github.com/an1creator/OpenACP/tree/main/docs/gitbook/architecture) \u2014 System design, plugin lifecycle
2286
+ - [Dev Mode](https://github.com/an1creator/OpenACP/blob/main/docs/gitbook/extending/dev-mode.md) \u2014 Hot-reload development workflow
2287
+ - [CLI Commands](https://github.com/an1creator/OpenACP/blob/main/docs/gitbook/api-reference/cli-commands.md) \u2014 Full CLI reference
2288
+ - [Platform Setup](https://github.com/an1creator/OpenACP/tree/main/docs/gitbook/platform-setup) \u2014 Telegram, Discord, Slack guides
2289
+ - [Configuration](https://github.com/an1creator/OpenACP/blob/main/docs/gitbook/self-hosting/configuration.md) \u2014 Config and settings reference
2291
2290
 
2292
2291
  ## Project Overview
2293
2292
 
@@ -2876,16 +2875,16 @@ const ctx = createTestContext({
2876
2875
  \`\`\`bash
2877
2876
  openacp plugin install ${params.pluginName}
2878
2877
  \`\`\`
2879
- 5. Submit to the [OpenACP Plugin Registry](https://github.com/Open-ACP/plugin-registry) for discoverability.
2878
+ 5. Verify installation by the complete npm package name from a clean environment.
2880
2879
 
2881
2880
  ## Useful Links
2882
2881
 
2883
- - [Architecture: Plugin System](https://docs.openacp.dev/architecture/plugin-system)
2884
- - [Architecture: Writing Plugins](https://docs.openacp.dev/architecture/writing-plugins)
2885
- - [Architecture: Command System](https://docs.openacp.dev/architecture/command-system)
2886
- - [Plugin SDK Reference](https://docs.openacp.dev/extending/plugin-sdk-reference)
2887
- - [Getting Started: Your First Plugin](https://docs.openacp.dev/extending/getting-started-plugin)
2888
- - [Dev Mode](https://docs.openacp.dev/extending/dev-mode)
2882
+ - [Architecture: Plugin System](https://github.com/an1creator/OpenACP/blob/main/docs/gitbook/architecture/plugin-system.md)
2883
+ - [Architecture: Writing Plugins](https://github.com/an1creator/OpenACP/blob/main/docs/gitbook/architecture/writing-plugins.md)
2884
+ - [Architecture: Command System](https://github.com/an1creator/OpenACP/blob/main/docs/gitbook/architecture/command-system.md)
2885
+ - [Plugin SDK Reference](https://github.com/an1creator/OpenACP/blob/main/docs/gitbook/extending/plugin-sdk-reference.md)
2886
+ - [Getting Started: Your First Plugin](https://github.com/an1creator/OpenACP/blob/main/docs/gitbook/extending/getting-started-plugin.md)
2887
+ - [Dev Mode](https://github.com/an1creator/OpenACP/blob/main/docs/gitbook/extending/dev-mode.md)
2889
2888
  - [Contributing](https://github.com/an1creator/OpenACP/blob/main/CONTRIBUTING.md)
2890
2889
  `;
2891
2890
  }
@@ -16676,6 +16675,37 @@ var init_resume = __esm({
16676
16675
  }
16677
16676
  });
16678
16677
 
16678
+ // src/plugins/telegram/callback-navigation.ts
16679
+ function contextualCommandCallback(command2, target) {
16680
+ if (!command2.startsWith("/")) throw new Error("Telegram navigation commands must start with /");
16681
+ const data = target === "settings" ? `${SETTINGS_PREFIX}${command2}` : void 0;
16682
+ return data && Buffer.byteLength(data, "utf8") <= 64 ? data : void 0;
16683
+ }
16684
+ function settingsCommandCallback(command2) {
16685
+ const data = contextualCommandCallback(command2, "settings");
16686
+ if (!data) throw new Error("Telegram navigation callback exceeds 64 bytes");
16687
+ return data;
16688
+ }
16689
+ function decodeCommandCallback(data) {
16690
+ if (data.startsWith(SETTINGS_PREFIX)) {
16691
+ return { command: data.slice(SETTINGS_PREFIX.length), returnTarget: "settings" };
16692
+ }
16693
+ return { command: data.slice(2) };
16694
+ }
16695
+ function returnButton(target) {
16696
+ switch (target) {
16697
+ case "settings":
16698
+ return { text: "\u25C0\uFE0F Back to Settings", callback_data: "s:back:refresh" };
16699
+ }
16700
+ }
16701
+ var SETTINGS_PREFIX;
16702
+ var init_callback_navigation = __esm({
16703
+ "src/plugins/telegram/callback-navigation.ts"() {
16704
+ "use strict";
16705
+ SETTINGS_PREFIX = "c/@settings:";
16706
+ }
16707
+ });
16708
+
16679
16709
  // src/plugins/telegram/commands/menu.ts
16680
16710
  var menu_exports = {};
16681
16711
  __export(menu_exports, {
@@ -16788,6 +16818,7 @@ async function buildSettingsKeyboard(core) {
16788
16818
  kb.text(`${label}`, `s:input:${field.path}`).row();
16789
16819
  }
16790
16820
  }
16821
+ kb.text("\u{1F310} Proxy Management", settingsCommandCallback("/proxy")).row();
16791
16822
  kb.text("\u25C0\uFE0F Back to Menu", "s:back");
16792
16823
  return kb;
16793
16824
  }
@@ -16980,6 +17011,7 @@ var init_settings = __esm({
16980
17011
  "use strict";
16981
17012
  init_config_registry();
16982
17013
  init_log();
17014
+ init_callback_navigation();
16983
17015
  log21 = createChildLogger({ module: "telegram-settings" });
16984
17016
  }
16985
17017
  });
@@ -20790,6 +20822,9 @@ function stalePolicyResponse(reopen) {
20790
20822
  options: [{ label: "Refresh", command: reopen }, { label: "Proxy menu", command: "/proxy status" }]
20791
20823
  };
20792
20824
  }
20825
+ function proxyCapabilityError() {
20826
+ return { type: "error", message: PROXY_CAPABILITY_ERROR };
20827
+ }
20793
20828
  function registerProxyCommand(registry, _core) {
20794
20829
  const core = _core;
20795
20830
  registry.register({
@@ -20821,8 +20856,9 @@ function registerProxyCommand(registry, _core) {
20821
20856
  "wizard-auth",
20822
20857
  "wizard-review"
20823
20858
  ]);
20859
+ if (!await canManageProxy(core, args2)) return proxyCapabilityError();
20824
20860
  if (action && mutations.has(action) && !await canManageProxy(core, args2)) {
20825
- return { type: "error", message: "This action requires network:proxy:manage capability." };
20861
+ return proxyCapabilityError();
20826
20862
  }
20827
20863
  if (!action || action === "status") {
20828
20864
  return {
@@ -21306,10 +21342,14 @@ Credentials: ${profile.hasCredentials ? "configured" : "none"} \xB7 failClosed:
21306
21342
  async function canManageProxy(core, args2) {
21307
21343
  const identity = core.lifecycleManager?.serviceRegistry?.get("identity");
21308
21344
  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"));
21345
+ try {
21346
+ const user = await identity.getUserByIdentity(formatIdentityId(args2.channelId, args2.userId));
21347
+ return Boolean(user && hasIdentityCapability(user.role, "network:proxy:manage"));
21348
+ } catch {
21349
+ return false;
21350
+ }
21311
21351
  }
21312
- var DRAFT_TTL_MS, drafts;
21352
+ var DRAFT_TTL_MS, drafts, PROXY_CAPABILITY_ERROR;
21313
21353
  var init_proxy3 = __esm({
21314
21354
  "src/core/commands/proxy.ts"() {
21315
21355
  "use strict";
@@ -21319,6 +21359,7 @@ var init_proxy3 = __esm({
21319
21359
  init_proxy_service();
21320
21360
  DRAFT_TTL_MS = 10 * 6e4;
21321
21361
  drafts = /* @__PURE__ */ new Map();
21362
+ PROXY_CAPABILITY_ERROR = "Proxy management requires network:proxy:manage capability.";
21322
21363
  }
21323
21364
  });
21324
21365
 
@@ -21519,6 +21560,7 @@ var init_adapter2 = __esm({
21519
21560
  init_command_sync();
21520
21561
  init_command_ownership_store();
21521
21562
  init_instance_context();
21563
+ init_callback_navigation();
21522
21564
  log29 = createChildLogger({ module: "telegram" });
21523
21565
  HISTORICAL_OPENACP_COMMAND_NAMES = /* @__PURE__ */ new Set([
21524
21566
  ...STATIC_COMMANDS.map((command2) => command2.command),
@@ -21847,7 +21889,13 @@ var init_adapter2 = __esm({
21847
21889
  }
21848
21890
  });
21849
21891
  if (response.type !== "silent" && response.type !== "delegated") {
21850
- await this.renderCommandResponse(response, ctx.chat.id, topicIdForInput, String(ctx.from?.id));
21892
+ await this.renderCommandResponse(
21893
+ response,
21894
+ ctx.chat.id,
21895
+ topicIdForInput,
21896
+ String(ctx.from?.id),
21897
+ pending.returnTarget
21898
+ );
21851
21899
  }
21852
21900
  return;
21853
21901
  }
@@ -21930,7 +21978,8 @@ var init_adapter2 = __esm({
21930
21978
  return;
21931
21979
  }
21932
21980
  const data = ctx.callbackQuery.data;
21933
- const command2 = this.fromCallbackData(data);
21981
+ const callback = this.fromCallbackData(data);
21982
+ const command2 = callback.command;
21934
21983
  const registry = this.core.lifecycleManager?.serviceRegistry?.get(
21935
21984
  "command-registry"
21936
21985
  );
@@ -21959,16 +22008,23 @@ var init_adapter2 = __esm({
21959
22008
  await ctx.answerCallbackQuery();
21960
22009
  if (response.type !== "silent" && response.type !== "delegated") {
21961
22010
  if (response.type === "input") {
21962
- await this.renderCommandResponse(response, chatId, topicId, String(ctx.from?.id));
22011
+ await this.renderCommandResponse(
22012
+ response,
22013
+ chatId,
22014
+ topicId,
22015
+ String(ctx.from?.id),
22016
+ callback.returnTarget
22017
+ );
21963
22018
  return;
21964
22019
  }
21965
22020
  if (response.type === "menu") {
21966
22021
  const keyboard = response.options.map((opt) => [
21967
22022
  {
21968
22023
  text: `${opt.label}${opt.hint ? ` \u2014 ${opt.hint}` : ""}`,
21969
- callback_data: this.toCallbackData(opt.command)
22024
+ callback_data: this.toCallbackData(opt.command, callback.returnTarget)
21970
22025
  }
21971
22026
  ]);
22027
+ this.appendReturnButton(keyboard, callback.returnTarget);
21972
22028
  try {
21973
22029
  await ctx.editMessageText(response.title, {
21974
22030
  reply_markup: { inline_keyboard: keyboard }
@@ -21987,7 +22043,11 @@ var init_adapter2 = __esm({
21987
22043
  parseMode = "Markdown";
21988
22044
  }
21989
22045
  try {
21990
- await ctx.editMessageText(text5, { ...parseMode && { parse_mode: parseMode } });
22046
+ const returnMarkup = this.returnMarkup(callback.returnTarget);
22047
+ await ctx.editMessageText(text5, {
22048
+ ...parseMode && { parse_mode: parseMode },
22049
+ ...returnMarkup && { reply_markup: returnMarkup }
22050
+ });
21991
22051
  } catch {
21992
22052
  }
21993
22053
  }
@@ -22588,11 +22648,13 @@ System topics have been created. Tap${assistantTopicLink} to get started.`,
22588
22648
  log29.info("Telegram bot stopped");
22589
22649
  }
22590
22650
  // --- CommandRegistry response rendering ---
22591
- async renderCommandResponse(response, chatId, topicId, userId) {
22651
+ async renderCommandResponse(response, chatId, topicId, userId, returnTarget) {
22652
+ const returnMarkup = this.returnMarkup(returnTarget);
22592
22653
  switch (response.type) {
22593
22654
  case "text":
22594
22655
  await this.bot.api.sendMessage(chatId, response.text, {
22595
- message_thread_id: topicId
22656
+ message_thread_id: topicId,
22657
+ ...returnMarkup && { reply_markup: returnMarkup }
22596
22658
  });
22597
22659
  break;
22598
22660
  case "adaptive": {
@@ -22600,7 +22662,8 @@ System topics have been created. Tap${assistantTopicLink} to get started.`,
22600
22662
  const text5 = variant?.text ?? response.fallback;
22601
22663
  await this.bot.api.sendMessage(chatId, text5, {
22602
22664
  message_thread_id: topicId,
22603
- ...variant?.parse_mode && { parse_mode: variant.parse_mode }
22665
+ ...variant?.parse_mode && { parse_mode: variant.parse_mode },
22666
+ ...returnMarkup && { reply_markup: returnMarkup }
22604
22667
  });
22605
22668
  break;
22606
22669
  }
@@ -22608,16 +22671,17 @@ System topics have been created. Tap${assistantTopicLink} to get started.`,
22608
22671
  await this.bot.api.sendMessage(
22609
22672
  chatId,
22610
22673
  `\u26A0\uFE0F ${response.message}`,
22611
- { message_thread_id: topicId }
22674
+ { message_thread_id: topicId, ...returnMarkup && { reply_markup: returnMarkup } }
22612
22675
  );
22613
22676
  break;
22614
22677
  case "menu": {
22615
22678
  const keyboard = response.options.map((opt) => [
22616
22679
  {
22617
22680
  text: `${opt.label}${opt.hint ? ` \u2014 ${opt.hint}` : ""}`,
22618
- callback_data: this.toCallbackData(opt.command)
22681
+ callback_data: this.toCallbackData(opt.command, returnTarget)
22619
22682
  }
22620
22683
  ]);
22684
+ this.appendReturnButton(keyboard, returnTarget);
22621
22685
  await this.bot.api.sendMessage(chatId, response.title, {
22622
22686
  message_thread_id: topicId,
22623
22687
  reply_markup: { inline_keyboard: keyboard }
@@ -22631,7 +22695,8 @@ System topics have been created. Tap${assistantTopicLink} to get started.`,
22631
22695
  const text5 = `${response.title}
22632
22696
  ${lines.join("\n")}`;
22633
22697
  await this.bot.api.sendMessage(chatId, text5, {
22634
- message_thread_id: topicId
22698
+ message_thread_id: topicId,
22699
+ ...returnMarkup && { reply_markup: returnMarkup }
22635
22700
  });
22636
22701
  break;
22637
22702
  }
@@ -22640,16 +22705,17 @@ ${lines.join("\n")}`;
22640
22705
  [
22641
22706
  {
22642
22707
  text: "\u2705 Yes",
22643
- callback_data: this.toCallbackData(response.onYes)
22708
+ callback_data: this.toCallbackData(response.onYes, returnTarget)
22644
22709
  }
22645
22710
  ]
22646
22711
  ];
22647
22712
  if (response.onNo) {
22648
22713
  buttons[0].push({
22649
22714
  text: "\u274C No",
22650
- callback_data: this.toCallbackData(response.onNo)
22715
+ callback_data: this.toCallbackData(response.onNo, returnTarget)
22651
22716
  });
22652
22717
  }
22718
+ this.appendReturnButton(buttons, returnTarget);
22653
22719
  await this.bot.api.sendMessage(chatId, response.question, {
22654
22720
  message_thread_id: topicId,
22655
22721
  reply_markup: { inline_keyboard: buttons }
@@ -22658,7 +22724,10 @@ ${lines.join("\n")}`;
22658
22724
  }
22659
22725
  case "input": {
22660
22726
  if (!userId) {
22661
- await this.bot.api.sendMessage(chatId, response.fallback, { message_thread_id: topicId });
22727
+ await this.bot.api.sendMessage(chatId, response.fallback, {
22728
+ message_thread_id: topicId,
22729
+ ...returnMarkup && { reply_markup: returnMarkup }
22730
+ });
22662
22731
  break;
22663
22732
  }
22664
22733
  const key = `${chatId}:${userId}:${topicId ?? 0}`;
@@ -22680,7 +22749,8 @@ ${lines.join("\n")}`;
22680
22749
  sensitive: response.sensitive === true,
22681
22750
  fallback: response.fallback,
22682
22751
  expiresAt: Date.now() + (response.expiresInMs ?? 10 * 6e4),
22683
- promptMessageId: promptMessage.message_id
22752
+ promptMessageId: promptMessage.message_id,
22753
+ returnTarget
22684
22754
  });
22685
22755
  break;
22686
22756
  }
@@ -22688,11 +22758,15 @@ ${lines.join("\n")}`;
22688
22758
  break;
22689
22759
  }
22690
22760
  }
22691
- toCallbackData(command2) {
22761
+ toCallbackData(command2, returnTarget) {
22692
22762
  const data = `c/${command2}`;
22693
- if (data.length <= 64) return data;
22763
+ if (!returnTarget && Buffer.byteLength(data, "utf8") <= 64) return data;
22764
+ if (returnTarget) {
22765
+ const contextual = contextualCommandCallback(command2, returnTarget);
22766
+ if (contextual) return contextual;
22767
+ }
22694
22768
  const id = String(++this.callbackCounter);
22695
- this.callbackCache.set(id, command2);
22769
+ this.callbackCache.set(id, { command: command2, returnTarget });
22696
22770
  if (this.callbackCache.size > 1e3) {
22697
22771
  const first = this.callbackCache.keys().next().value;
22698
22772
  if (first) this.callbackCache.delete(first);
@@ -22701,9 +22775,15 @@ ${lines.join("\n")}`;
22701
22775
  }
22702
22776
  fromCallbackData(data) {
22703
22777
  if (data.startsWith("c/#")) {
22704
- return this.callbackCache.get(data.slice(3)) ?? data.slice(2);
22778
+ return this.callbackCache.get(data.slice(3)) ?? { command: data.slice(2) };
22705
22779
  }
22706
- return data.slice(2);
22780
+ return decodeCommandCallback(data);
22781
+ }
22782
+ returnMarkup(returnTarget) {
22783
+ return returnTarget ? { inline_keyboard: [[returnButton(returnTarget)]] } : void 0;
22784
+ }
22785
+ appendReturnButton(keyboard, returnTarget) {
22786
+ if (returnTarget) keyboard.push([returnButton(returnTarget)]);
22707
22787
  }
22708
22788
  setupRoutes() {
22709
22789
  this.bot.on("message:text", async (ctx) => {
@@ -31405,7 +31485,9 @@ function registerCoreMenuItems(registry) {
31405
31485
  label: "\u{1F310} Proxy Routing",
31406
31486
  priority: 32,
31407
31487
  group: "config",
31408
- action: { type: "command", command: "/proxy" }
31488
+ action: { type: "command", command: "/proxy" },
31489
+ // Keep already-sent m:core:proxy buttons valid while nesting new entry points under Settings.
31490
+ visible: () => false
31409
31491
  });
31410
31492
  registry.register({
31411
31493
  id: "core:restart",