clawborrator-cli 0.0.33 → 0.0.35

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.
@@ -67760,43 +67760,73 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
67760
67760
  }
67761
67761
  }
67762
67762
  const wsUrl = cfg.hubUrl.replace(/^http/i, "ws") + "/cli";
67763
- const ws = new wrapper_default(wsUrl, {
67764
- headers: { Authorization: `Bearer ${cfg.pat}` }
67765
- });
67766
67763
  let mySubscription = false;
67767
67764
  const pendingPerms = [];
67768
- ws.on("open", () => {
67769
- say(`${DIM2}[${ts()}]${RESET2} connected to ${cfg.hubUrl}`);
67770
- const sub = { type: "subscribe", sessionId };
67771
- ws.send(JSON.stringify(sub));
67772
- });
67773
- ws.on("message", (data) => {
67774
- let msg;
67775
- try {
67776
- msg = JSON.parse(data.toString("utf8"));
67777
- } catch {
67778
- return;
67779
- }
67780
- if (msg.type === "permission_request") {
67781
- pendingPerms.push({ requestId: msg.requestId, tool: msg.tool, sessionId: msg.sessionId });
67782
- } else if (msg.type === "permission_resolved") {
67783
- const i = pendingPerms.findIndex((p) => p.requestId === msg.requestId);
67784
- if (i >= 0) pendingPerms.splice(i, 1);
67785
- }
67786
- printInbound(msg, myLogin);
67787
- if (msg.type === "subscribed") {
67788
- mySubscription = true;
67789
- say(`${DIM2}attached as ${BOLD2}${msg.role}${RESET2}${DIM2}. type for prompt \xB7 @other <text> to route \xB7 /m <text> for op-msg \xB7 /y /n on permissions \xB7 /q to quit${RESET2}`);
67790
- }
67791
- });
67792
- ws.on("close", (code, reason) => {
67793
- stopWorking();
67794
- say(`${DIM2}[${ts()}] disconnected (${code}${reason ? ": " + reason.toString() : ""})${RESET2}`);
67795
- process.exit(0);
67796
- });
67797
- ws.on("error", (err) => {
67798
- sayErr(`${RED}ws error: ${err.message}${RESET2}`);
67799
- });
67765
+ const BACKOFF = [1e3, 2e3, 5e3, 15e3, 3e4, 6e4];
67766
+ let ws;
67767
+ let stopRequested = false;
67768
+ let reconnectAttempt = 0;
67769
+ let reconnectTimer = null;
67770
+ function connect() {
67771
+ ws = new wrapper_default(wsUrl, { headers: { Authorization: `Bearer ${cfg.pat}` } });
67772
+ ws.on("open", () => {
67773
+ if (reconnectAttempt > 0) {
67774
+ say(`${DIM2}[${ts()}]${RESET2} ${AMBER}reconnected${RESET2} to ${cfg.hubUrl}`);
67775
+ } else {
67776
+ say(`${DIM2}[${ts()}]${RESET2} connected to ${cfg.hubUrl}`);
67777
+ }
67778
+ reconnectAttempt = 0;
67779
+ mySubscription = false;
67780
+ const sub = { type: "subscribe", sessionId };
67781
+ ws.send(JSON.stringify(sub));
67782
+ });
67783
+ ws.on("message", (data) => {
67784
+ let msg;
67785
+ try {
67786
+ msg = JSON.parse(data.toString("utf8"));
67787
+ } catch {
67788
+ return;
67789
+ }
67790
+ if (msg.type === "permission_request") {
67791
+ pendingPerms.push({ requestId: msg.requestId, tool: msg.tool, sessionId: msg.sessionId });
67792
+ } else if (msg.type === "permission_resolved") {
67793
+ const i = pendingPerms.findIndex((p) => p.requestId === msg.requestId);
67794
+ if (i >= 0) pendingPerms.splice(i, 1);
67795
+ }
67796
+ printInbound(msg, myLogin);
67797
+ if (msg.type === "subscribed") {
67798
+ mySubscription = true;
67799
+ say(`${DIM2}attached as ${BOLD2}${msg.role}${RESET2}${DIM2}. type for prompt \xB7 @other <text> to route \xB7 /m <text> for op-msg \xB7 /y /n on permissions \xB7 /q to quit${RESET2}`);
67800
+ }
67801
+ if (msg.type === "error" && (msg.code === "auth_failed" || msg.code === "token_revoked")) {
67802
+ stopRequested = true;
67803
+ }
67804
+ });
67805
+ ws.on("close", (code, reason) => {
67806
+ stopWorking();
67807
+ if (stopRequested || code === 1e3) {
67808
+ say(`${DIM2}[${ts()}] disconnected (${code}${reason && reason.length ? ": " + reason.toString() : ""})${RESET2}`);
67809
+ process.exit(0);
67810
+ }
67811
+ if (code === 1008) {
67812
+ sayErr(`${RED}disconnected (${code}): auth rejected \u2014 won't retry${RESET2}`);
67813
+ process.exit(2);
67814
+ }
67815
+ const delay = BACKOFF[Math.min(reconnectAttempt, BACKOFF.length - 1)];
67816
+ reconnectAttempt += 1;
67817
+ say(`${DIM2}[${ts()}] ${AMBER}disconnected${RESET2} (${code}${reason && reason.length ? ": " + reason.toString() : ""})${DIM2} \u2014 reconnecting in ${delay / 1e3}s (attempt ${reconnectAttempt})${RESET2}`);
67818
+ if (reconnectTimer) clearTimeout(reconnectTimer);
67819
+ reconnectTimer = setTimeout(() => {
67820
+ reconnectTimer = null;
67821
+ connect();
67822
+ }, delay);
67823
+ });
67824
+ ws.on("error", (err) => {
67825
+ if (ws.readyState === wrapper_default.CLOSING || ws.readyState === wrapper_default.CLOSED) return;
67826
+ sayErr(`${RED}ws error: ${err.message}${RESET2}`);
67827
+ });
67828
+ }
67829
+ connect();
67800
67830
  const rl = (0, import_node_readline2.createInterface)({
67801
67831
  input: process.stdin,
67802
67832
  output: process.stdout,
@@ -67813,6 +67843,11 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
67813
67843
  return;
67814
67844
  }
67815
67845
  if (text === "/q" || text === "/quit") {
67846
+ stopRequested = true;
67847
+ if (reconnectTimer) {
67848
+ clearTimeout(reconnectTimer);
67849
+ reconnectTimer = null;
67850
+ }
67816
67851
  ws.close(1e3, "user quit");
67817
67852
  return;
67818
67853
  }
@@ -67945,6 +67980,11 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
67945
67980
  startWorking();
67946
67981
  });
67947
67982
  process.on("SIGINT", () => {
67983
+ stopRequested = true;
67984
+ if (reconnectTimer) {
67985
+ clearTimeout(reconnectTimer);
67986
+ reconnectTimer = null;
67987
+ }
67948
67988
  ws.close(1e3, "sigint");
67949
67989
  });
67950
67990
  });
@@ -67973,6 +68013,12 @@ function printInbound(msg, myLogin) {
67973
68013
  say(`${DIM2}[${ts()}] presence: ${msg.attached.map((l) => "@" + l).join(", ") || "(empty)"}${RESET2}`);
67974
68014
  break;
67975
68015
  }
68016
+ case "channel_status": {
68017
+ const tag2 = msg.connected ? `${GREEN}\u25CF channel online${RESET2}` : `${RED}\u25CB channel offline${RESET2}`;
68018
+ say(`${DIM2}[${shortTs(msg.ts)}]${RESET2} ${tag2}`);
68019
+ if (!msg.connected) stopWorking();
68020
+ break;
68021
+ }
67976
68022
  case "ack":
67977
68023
  break;
67978
68024
  case "error":
@@ -68609,7 +68655,7 @@ var webhookCmd = new Command("webhook").description("manage webhook subscription
68609
68655
 
68610
68656
  // src/index.ts
68611
68657
  var program2 = new Command();
68612
- program2.name("claw").description("clawborrator CLI \u2014 control your Claude Code sessions from the terminal").version("0.0.33");
68658
+ program2.name("claw").description("clawborrator CLI \u2014 control your Claude Code sessions from the terminal").version("0.0.35");
68613
68659
  program2.addCommand(loginCmd);
68614
68660
  program2.addCommand(logoutCmd);
68615
68661
  program2.addCommand(whoamiCmd);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "clawborrator-cli",
3
- "version": "0.0.33",
3
+ "version": "0.0.35",
4
4
  "type": "module",
5
5
  "description": "claw — command-line client for clawborrator hub_v1. Manages PATs, channel tokens, sessions, cross-session routing, and webhooks; ships an inline TUI for live multi-operator session attach.",
6
6
  "license": "MIT",