@0dai-dev/cli 2.5.0 → 2.6.0

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.
Files changed (2) hide show
  1. package/bin/0dai.js +58 -2
  2. package/package.json +1 -1
package/bin/0dai.js CHANGED
@@ -7,7 +7,7 @@ const fs = require("fs");
7
7
  const path = require("path");
8
8
  const os = require("os");
9
9
 
10
- const VERSION = "2.5.0";
10
+ const VERSION = "2.6.0";
11
11
  const API_URL = process.env.ODAI_API_URL || "https://api.0dai.dev";
12
12
  const T = process.stdout.isTTY ? "\x1b[38;2;45;212;168m" : ""; // teal
13
13
  const R = process.stdout.isTTY ? "\x1b[0m" : ""; // reset
@@ -892,6 +892,59 @@ function cmdSwarm(target, sub, args) {
892
892
  log(`task created: ${id} → ${forAgent}`);
893
893
  return;
894
894
  }
895
+ if (sub === "webhook") {
896
+ const webhooksFile = path.join(swarmDir, "webhooks.json");
897
+ const loadHooks = () => { try { return JSON.parse(fs.readFileSync(webhooksFile, "utf8")); } catch { return []; } };
898
+ const saveHooks = (h) => { fs.mkdirSync(swarmDir, { recursive: true }); fs.writeFileSync(webhooksFile, JSON.stringify(h, null, 2)); };
899
+ const action = args[2] || "";
900
+
901
+ if (action === "add") {
902
+ const url = args[3] || args.find((_, i) => args[i-1] === "--url");
903
+ const event = args.find((_, i) => args[i-1] === "--event") || "all";
904
+ const secret = args.find((_, i) => args[i-1] === "--secret") || "";
905
+ if (!url || !url.startsWith("http")) { log("Usage: 0dai swarm webhook add <url> [--event task_done|task_failed|all] [--secret TOKEN]"); return; }
906
+ const hooks = loadHooks();
907
+ if (hooks.find(h => h.url === url)) { log(`already registered: ${url}`); return; }
908
+ hooks.push({ url, event, secret: secret || undefined, added_at: new Date().toISOString() });
909
+ saveHooks(hooks);
910
+ log(`webhook added: ${url} (event: ${event})`);
911
+ return;
912
+ }
913
+ if (action === "list") {
914
+ const hooks = loadHooks();
915
+ if (hooks.length === 0) { log("no webhooks registered. Use: 0dai swarm webhook add <url>"); return; }
916
+ console.log(`\n ${T}Registered webhooks${R}\n`);
917
+ hooks.forEach((h, i) => {
918
+ console.log(` ${i+1}. ${h.url}`);
919
+ console.log(` ${D}event: ${h.event} added: ${h.added_at?.slice(0,10)}${R}`);
920
+ });
921
+ console.log();
922
+ return;
923
+ }
924
+ if (action === "remove") {
925
+ const url = args[3] || "";
926
+ if (!url) { log("Usage: 0dai swarm webhook remove <url>"); return; }
927
+ const hooks = loadHooks().filter(h => h.url !== url);
928
+ saveHooks(hooks);
929
+ log(`removed: ${url}`);
930
+ return;
931
+ }
932
+ if (action === "test") {
933
+ const url = args[3] || loadHooks()[0]?.url;
934
+ if (!url) { log("Usage: 0dai swarm webhook test <url>"); return; }
935
+ const payload = JSON.stringify({ event: "test", task_id: "test-ping", title: "Webhook test from 0dai", status: "done", timestamp: new Date().toISOString() });
936
+ const req = https.request(url, { method: "POST", headers: { "Content-Type": "application/json", "User-Agent": "0dai-swarm/1.0", "Content-Length": Buffer.byteLength(payload) } }, (res) => {
937
+ log(`test sent to ${url} → HTTP ${res.statusCode}`);
938
+ });
939
+ req.on("error", (e) => log(`test failed: ${e.message}`));
940
+ req.setTimeout(5000, () => { req.destroy(); log("test timed out"); });
941
+ req.write(payload);
942
+ req.end();
943
+ return;
944
+ }
945
+ console.log("Usage: 0dai swarm webhook [add|list|remove|test] <url> [--event all|task_done|task_failed] [--secret TOKEN]");
946
+ return;
947
+ }
895
948
  if (sub === "budget") {
896
949
  const budgetFile = path.join(swarmDir, "budget.json");
897
950
  if (!fs.existsSync(budgetFile)) { log("no budget data yet"); return; }
@@ -1000,7 +1053,10 @@ async function main() {
1000
1053
  console.log(" reflect Session reflection: delivered, delegation rate, blockers");
1001
1054
  console.log(" status Show maturity, swarm, session");
1002
1055
  console.log(" session save Save session for roaming");
1003
- console.log(" swarm status Task queue & delegation");
1056
+ console.log(" swarm status Task queue & delegation");
1057
+ console.log(" swarm webhook add Register webhook (fires on task done/failed)");
1058
+ console.log(" swarm webhook list Show registered webhooks");
1059
+ console.log(" swarm webhook test Send test ping to a webhook URL");
1004
1060
  console.log(" feedback push Send feedback to 0dai");
1005
1061
  console.log(" models Show model ratings (--fast/--balanced/--deep/--available)");
1006
1062
  console.log(" terminal Launch interactive agent session");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@0dai-dev/cli",
3
- "version": "2.5.0",
3
+ "version": "2.6.0",
4
4
  "description": "One config layer for 5 AI agent CLIs — Claude Code, Codex, OpenCode, Gemini, Aider",
5
5
  "bin": {
6
6
  "0dai": "./bin/0dai.js"