@cmdop/bot 2026.2.28 → 2026.3.101

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
@@ -1,6 +1,6 @@
1
1
  # @cmdop/bot
2
2
 
3
- Multi-channel bot framework for [CMDOP](https://cmdop.com) — run `/exec`, `/agent`, and `/files` commands from Telegram, Discord, and Slack.
3
+ Multi-channel bot framework for [CMDOP](https://cmdop.com) — run `/exec`, `/agent`, `/skills`, and `/files` commands from Telegram, Discord, and Slack.
4
4
 
5
5
  ```
6
6
  pnpm add @cmdop/bot
@@ -19,7 +19,7 @@ await hub.addTelegram({ token: process.env.TELEGRAM_TOKEN });
19
19
  await hub.start();
20
20
  ```
21
21
 
22
- That's it. Your bot now responds to `/exec`, `/agent`, `/files`, and `/help`.
22
+ That's it. Your bot now responds to `/exec`, `/agent`, `/skills`, `/files`, and `/help`.
23
23
 
24
24
  ---
25
25
 
@@ -76,6 +76,7 @@ Requires Socket Mode enabled in your Slack app settings. See [examples/slack.ts]
76
76
  |---------|-------|-------------------|
77
77
  | `/exec` | `/exec <shell command>` | `EXECUTE` |
78
78
  | `/agent` | `/agent <prompt>` | `EXECUTE` |
79
+ | `/skills` | `/skills list \| show <name> \| run <name> <prompt>` | `EXECUTE` |
79
80
  | `/files` | `/files [read] <path>` | `READ` |
80
81
  | `/help` | `/help` | none |
81
82
 
@@ -102,7 +103,7 @@ Permission levels (ordered, each includes all levels below):
102
103
  |-------|--------|
103
104
  | `NONE` | No commands (only `/help`) |
104
105
  | `READ` | `/files` |
105
- | `EXECUTE` | `/exec`, `/agent` |
106
+ | `EXECUTE` | `/exec`, `/agent`, `/skills` |
106
107
  | `FILES` | _(reserved for future write operations)_ |
107
108
  | `ADMIN` | All commands |
108
109
 
@@ -282,7 +283,7 @@ All errors extend `BotError` and expose a `code` string:
282
283
  ## Links
283
284
 
284
285
  - [Homepage](https://cmdop.com/sdk/python/bot)
285
- - [Documentation](https://cmdop.com/docs/sdk/node/bot)
286
+ - [Documentation](https://cmdop.com/docs/sdk/node-bot)
286
287
  - [npm](https://www.npmjs.com/package/@cmdop/bot)
287
288
 
288
289
  ## License
package/dist/index.cjs CHANGED
@@ -16356,7 +16356,7 @@ var init_channel3 = __esm({
16356
16356
  { title: "Get help", message: "/help" }
16357
16357
  ]
16358
16358
  });
16359
- await say("Hello! Use `/exec`, `/agent`, `/files`, or `/help`.");
16359
+ await say("Hello! Use `/exec`, `/agent`, `/skills`, `/files`, or `/help`.");
16360
16360
  },
16361
16361
  threadContextChanged: async ({ saveThreadContext }) => {
16362
16362
  await saveThreadContext();
@@ -16888,6 +16888,103 @@ ${lines.join("\n\n")}`;
16888
16888
  }
16889
16889
  };
16890
16890
 
16891
+ // src/handlers/skills.ts
16892
+ init_errors();
16893
+ var SkillsHandler = class extends BaseHandler {
16894
+ name = "skills";
16895
+ description = "List, show, or run skills on the remote machine";
16896
+ usage = "/skills list | /skills show <name> | /skills run <name> <prompt>";
16897
+ requiredPermission = "EXECUTE";
16898
+ maxOutput;
16899
+ constructor(client, logger, config = {}) {
16900
+ super(client, logger);
16901
+ this.maxOutput = config.maxOutputLength ?? 4e3;
16902
+ }
16903
+ async handle(ctx) {
16904
+ const subcommand = ctx.args[0]?.toLowerCase();
16905
+ if (!subcommand) {
16906
+ return err(new exports.CommandArgsError("skills", "Subcommand required. Usage: /skills list | /skills show <name> | /skills run <name> <prompt>"));
16907
+ }
16908
+ try {
16909
+ if (ctx.machine) {
16910
+ await this.client.skills.setMachine(ctx.machine);
16911
+ }
16912
+ switch (subcommand) {
16913
+ case "list":
16914
+ return await this.handleList();
16915
+ case "show":
16916
+ return await this.handleShow(ctx);
16917
+ case "run":
16918
+ return await this.handleRun(ctx);
16919
+ default:
16920
+ return err(new exports.CommandArgsError("skills", `Unknown subcommand "${subcommand}". Usage: /skills list | /skills show <name> | /skills run <name> <prompt>`));
16921
+ }
16922
+ } catch (e3) {
16923
+ const errMsg = e3 instanceof Error ? e3.message : String(e3);
16924
+ this.logger.error("Skills operation failed", { error: errMsg });
16925
+ if (errMsg.includes("session_id") || errMsg.includes("No active session")) {
16926
+ return err(new exports.CMDOPError("Machine is offline or CMDOP agent is not running.\nhttps://cmdop.com/downloads/"));
16927
+ }
16928
+ if (errMsg.includes("DEADLINE_EXCEEDED") || errMsg.includes("timeout")) {
16929
+ return err(new exports.CMDOPError("Request timed out. The skill may be too complex \u2014 try a simpler prompt."));
16930
+ }
16931
+ if (errMsg.includes("UNAVAILABLE") || errMsg.includes("Connection refused")) {
16932
+ return err(new exports.CMDOPError("Server unavailable. Check your connection and try again."));
16933
+ }
16934
+ return err(new exports.CMDOPError(`Skills error: ${errMsg}`, e3 instanceof Error ? e3 : void 0));
16935
+ }
16936
+ }
16937
+ async handleList() {
16938
+ const skills = await this.client.skills.list();
16939
+ if (skills.length === 0) {
16940
+ return ok({ type: "text", text: "No skills installed." });
16941
+ }
16942
+ const lines = skills.map(
16943
+ (s4) => s4.description ? `${s4.name} \u2014 ${s4.description}` : s4.name
16944
+ );
16945
+ return ok({ type: "text", text: lines.join("\n") });
16946
+ }
16947
+ async handleShow(ctx) {
16948
+ const name = ctx.args[1];
16949
+ if (!name) {
16950
+ return err(new exports.CommandArgsError("skills", "Skill name required. Usage: /skills show <name>"));
16951
+ }
16952
+ const detail = await this.client.skills.show(name);
16953
+ if (!detail.found) {
16954
+ return err(new exports.CMDOPError(detail.error ?? `Skill "${name}" not found`));
16955
+ }
16956
+ const parts = [];
16957
+ if (detail.info) {
16958
+ parts.push(`Skill: ${detail.info.name}`);
16959
+ if (detail.info.description) parts.push(`Description: ${detail.info.description}`);
16960
+ if (detail.info.author) parts.push(`Author: ${detail.info.author}`);
16961
+ if (detail.info.version) parts.push(`Version: ${detail.info.version}`);
16962
+ if (detail.info.origin) parts.push(`Origin: ${detail.info.origin}`);
16963
+ }
16964
+ if (detail.source) parts.push(`Source: ${detail.source}`);
16965
+ if (detail.content) {
16966
+ const preview = detail.content.length > this.maxOutput ? detail.content.slice(0, this.maxOutput) + "\n...(truncated)" : detail.content;
16967
+ parts.push(`
16968
+ System prompt:
16969
+ ${preview}`);
16970
+ }
16971
+ return ok({ type: "code", code: parts.join("\n") });
16972
+ }
16973
+ async handleRun(ctx) {
16974
+ const name = ctx.args[1];
16975
+ if (!name) {
16976
+ return err(new exports.CommandArgsError("skills", "Skill name and prompt required. Usage: /skills run <name> <prompt>"));
16977
+ }
16978
+ const prompt = ctx.args.slice(2).join(" ").trim();
16979
+ if (!prompt) {
16980
+ return err(new exports.CommandArgsError("skills", "Prompt required. Usage: /skills run <name> <prompt>"));
16981
+ }
16982
+ const result = await this.client.skills.run(name, prompt);
16983
+ const code = result.text.length > this.maxOutput ? result.text.slice(0, this.maxOutput) + "\n...(truncated)" : result.text;
16984
+ return ok({ type: "code", code });
16985
+ }
16986
+ };
16987
+
16891
16988
  // src/config.ts
16892
16989
  init_errors();
16893
16990
  var BotSettingsSchema = v4.z.object({
@@ -17007,6 +17104,7 @@ var IntegrationHub = class _IntegrationHub {
17007
17104
  const hub = new _IntegrationHub(client, logger, settings2, permissions, dispatcher, mode);
17008
17105
  hub.registerHandler(new TerminalHandler(client, logger, { maxOutputLength: settings2.maxOutputLength }));
17009
17106
  hub.registerHandler(new AgentHandler(client, logger, { maxOutputLength: settings2.maxOutputLength }));
17107
+ hub.registerHandler(new SkillsHandler(client, logger, { maxOutputLength: settings2.maxOutputLength }));
17010
17108
  hub.registerHandler(new FilesHandler(client, logger));
17011
17109
  hub.registerHandler(new HelpHandler(client, logger, {
17012
17110
  getCommands: () => dispatcher.getCommandList()