clawborrator-cli 0.0.50 → 0.0.52
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-bundled/claw.cjs +43 -20
- package/package.json +1 -1
package/dist-bundled/claw.cjs
CHANGED
|
@@ -67615,23 +67615,30 @@ var AmbiguousError = class extends Error {
|
|
|
67615
67615
|
}
|
|
67616
67616
|
code = "CLW_AMBIGUOUS";
|
|
67617
67617
|
};
|
|
67618
|
-
async function pickCandidate(input, candidates) {
|
|
67618
|
+
async function pickCandidate(input, candidates, opts = {}) {
|
|
67619
67619
|
if (candidates.length === 1) return candidates[0];
|
|
67620
67620
|
const live = candidates.filter((c) => c.connected);
|
|
67621
|
-
|
|
67622
|
-
|
|
67621
|
+
let promptSet;
|
|
67622
|
+
if (opts.destructive) {
|
|
67623
|
+
if (candidates.length <= 1) return candidates[0];
|
|
67624
|
+
promptSet = candidates;
|
|
67625
|
+
} else {
|
|
67626
|
+
if (live.length <= 1) return live[0] ?? candidates[0];
|
|
67627
|
+
promptSet = live;
|
|
67623
67628
|
}
|
|
67624
67629
|
if (!process.stdin.isTTY || !process.stderr.isTTY) {
|
|
67625
|
-
throw new AmbiguousError(
|
|
67630
|
+
throw new AmbiguousError(promptSet, input);
|
|
67626
67631
|
}
|
|
67627
67632
|
process.stderr.write(`${BOLD}'${input}' is ambiguous \u2014 pick a session:${RESET}
|
|
67628
67633
|
`);
|
|
67629
|
-
for (let i = 0; i <
|
|
67630
|
-
const c =
|
|
67634
|
+
for (let i = 0; i < promptSet.length; i++) {
|
|
67635
|
+
const c = promptSet[i];
|
|
67631
67636
|
const qualified = c.routingName ? `@${c.startedByLogin}/${c.routingName.replace(/^@/, "")}` : `(no routing name)`;
|
|
67637
|
+
const status = c.connected ? `${BOLD}\u25CF online${RESET}` : `${DIM}\u25CB offline${RESET}`;
|
|
67632
67638
|
const cwd = c.cwd ? ` ${DIM}${c.cwd}${RESET}` : "";
|
|
67633
67639
|
const host = c.host ? ` ${DIM}${c.host}${RESET}` : "";
|
|
67634
|
-
|
|
67640
|
+
const seen = c.lastSeenAt ? ` ${DIM}last seen ${c.lastSeenAt}${RESET}` : "";
|
|
67641
|
+
process.stderr.write(` ${BOLD}${i + 1}${RESET}. ${qualified} ${status}${host}${cwd}${seen}
|
|
67635
67642
|
`);
|
|
67636
67643
|
process.stderr.write(` ${DIM}id ${c.id}${RESET}
|
|
67637
67644
|
`);
|
|
@@ -67640,7 +67647,7 @@ async function pickCandidate(input, candidates) {
|
|
|
67640
67647
|
`);
|
|
67641
67648
|
const rl = (0, import_node_readline.createInterface)({ input: process.stdin, output: process.stderr });
|
|
67642
67649
|
const answer = await new Promise((resolve3) => {
|
|
67643
|
-
rl.question(`pick [1-${
|
|
67650
|
+
rl.question(`pick [1-${promptSet.length}]: `, resolve3);
|
|
67644
67651
|
});
|
|
67645
67652
|
rl.close();
|
|
67646
67653
|
const trimmed = answer.trim().toLowerCase();
|
|
@@ -67648,10 +67655,10 @@ async function pickCandidate(input, candidates) {
|
|
|
67648
67655
|
throw new Error("cancelled");
|
|
67649
67656
|
}
|
|
67650
67657
|
const idx = parseInt(trimmed, 10);
|
|
67651
|
-
if (!Number.isInteger(idx) || idx < 1 || idx >
|
|
67658
|
+
if (!Number.isInteger(idx) || idx < 1 || idx > promptSet.length) {
|
|
67652
67659
|
throw new Error(`invalid selection '${answer}'`);
|
|
67653
67660
|
}
|
|
67654
|
-
return
|
|
67661
|
+
return promptSet[idx - 1];
|
|
67655
67662
|
}
|
|
67656
67663
|
|
|
67657
67664
|
// src/commands/session-attach.ts
|
|
@@ -67830,7 +67837,7 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
|
|
|
67830
67837
|
const limitArg = String(opts.limit ?? "50").toLowerCase();
|
|
67831
67838
|
const historyLimit = limitArg === "all" ? 5e3 : limitArg === "0" ? 0 : Math.max(0, parseInt(limitArg, 10) || 0);
|
|
67832
67839
|
if (historyLimit > 0) {
|
|
67833
|
-
const kindsParam = opts.opMessages === false ? "&kinds=event" : "";
|
|
67840
|
+
const kindsParam = opts.opMessages === false ? "&kinds=event,file" : "";
|
|
67834
67841
|
try {
|
|
67835
67842
|
const tl = await api.get(`/api/v1/sessions/${encodeURIComponent(sessionId)}/timeline?limit=${historyLimit}${kindsParam}`);
|
|
67836
67843
|
if (tl.items.length > 0) {
|
|
@@ -67843,8 +67850,11 @@ var sessionAttach = new Command("attach").description("open a TUI on a session \
|
|
|
67843
67850
|
/* fromBacklog */
|
|
67844
67851
|
true
|
|
67845
67852
|
);
|
|
67846
|
-
} else {
|
|
67853
|
+
} else if (item.kind === "op-message") {
|
|
67847
67854
|
console.log(`${DIM2}[${shortTs(item.ts)}]${RESET2} ${GREEN}@${item.authorLogin}${RESET2} ${item.text}`);
|
|
67855
|
+
} else if (item.kind === "file") {
|
|
67856
|
+
const verb = item.action === "uploaded" ? `${GREEN}\u{1F4CE} uploaded${RESET2}` : `${RED}\u2717 deleted${RESET2}`;
|
|
67857
|
+
console.log(`${DIM2}[${shortTs(item.ts)}]${RESET2} ${BLUE}@${item.file.uploaderLogin}${RESET2} ${verb} ${BOLD2}${item.file.filename}${RESET2} ${DIM2}(${fmtBytes(item.file.size)} \xB7 fileId=${item.file.id})${RESET2}`);
|
|
67848
67858
|
}
|
|
67849
67859
|
}
|
|
67850
67860
|
console.log(`${DIM2}\u2500\u2500\u2500 live \u2500\u2500\u2500${RESET2}`);
|
|
@@ -68124,6 +68134,12 @@ function printInbound(msg, myLogin) {
|
|
|
68124
68134
|
if (!msg.connected) stopWorking();
|
|
68125
68135
|
break;
|
|
68126
68136
|
}
|
|
68137
|
+
case "file_event": {
|
|
68138
|
+
const verb = msg.action === "uploaded" ? `${GREEN}\u{1F4CE} uploaded${RESET2}` : `${RED}\u2717 deleted${RESET2}`;
|
|
68139
|
+
const f = msg.file;
|
|
68140
|
+
say(`${DIM2}[${ts()}]${RESET2} ${BLUE}@${f.uploaderLogin}${RESET2} ${verb} ${BOLD2}${f.filename}${RESET2} ${DIM2}(${fmtBytes(f.size)} \xB7 fileId=${f.id})${RESET2}`);
|
|
68141
|
+
break;
|
|
68142
|
+
}
|
|
68127
68143
|
case "ack":
|
|
68128
68144
|
break;
|
|
68129
68145
|
case "error":
|
|
@@ -68135,6 +68151,12 @@ function shortTs(iso) {
|
|
|
68135
68151
|
const d = new Date(iso);
|
|
68136
68152
|
return Number.isFinite(d.getTime()) ? d.toLocaleTimeString() : iso.slice(11, 19);
|
|
68137
68153
|
}
|
|
68154
|
+
function fmtBytes(n) {
|
|
68155
|
+
if (n < 1024) return `${n} B`;
|
|
68156
|
+
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
68157
|
+
if (n < 1024 ** 3) return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
68158
|
+
return `${(n / 1024 ** 3).toFixed(2)} GB`;
|
|
68159
|
+
}
|
|
68138
68160
|
function previewPayload(p) {
|
|
68139
68161
|
const text = p?.text ?? p?.preview ?? p?.outputPreview ?? "";
|
|
68140
68162
|
if (typeof text === "string" && text.length > 0) {
|
|
@@ -68315,7 +68337,7 @@ function fmtAgo(iso) {
|
|
|
68315
68337
|
return fmtDuration(Date.now() - new Date(iso).getTime());
|
|
68316
68338
|
}
|
|
68317
68339
|
var UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
68318
|
-
async function resolveSessionId(idOrName) {
|
|
68340
|
+
async function resolveSessionId(idOrName, opts = {}) {
|
|
68319
68341
|
if (UUID_RE.test(idOrName)) return idOrName;
|
|
68320
68342
|
const needle = idOrName.startsWith("@") ? idOrName : "@" + idOrName;
|
|
68321
68343
|
const slash = needle.indexOf("/");
|
|
@@ -68343,7 +68365,7 @@ async function resolveSessionId(idOrName) {
|
|
|
68343
68365
|
throw err;
|
|
68344
68366
|
}
|
|
68345
68367
|
try {
|
|
68346
|
-
const picked = await pickCandidate(idOrName, candidates);
|
|
68368
|
+
const picked = await pickCandidate(idOrName, candidates, { destructive: !!opts.destructive });
|
|
68347
68369
|
return picked.id;
|
|
68348
68370
|
} catch (e) {
|
|
68349
68371
|
if (e instanceof AmbiguousError) {
|
|
@@ -68495,16 +68517,17 @@ var sessionPrune = new Command("prune").description("hard-delete duplicate sessi
|
|
|
68495
68517
|
}
|
|
68496
68518
|
if (r.dryRun) console.log("\n(--dry-run \u2014 re-run without it to apply)");
|
|
68497
68519
|
});
|
|
68498
|
-
var sessionDelete = new Command("delete").description("hard-delete a single session \u2014 cascades events / op-messages / shares. Irreversible. Use `archive` for the soft form (auto-resurrects on reconnect).").argument("<ref>", "session UUID or @routingName").option("--hard", "required: confirm you want a permanent delete (no soft form is offered without this flag)").action(async (ref, opts) => {
|
|
68520
|
+
var sessionDelete = new Command("delete").description("hard-delete a single session \u2014 cascades events / op-messages / shares / files (refcount-sweeps blobs). Irreversible. Use `archive` for the soft form (auto-resurrects on reconnect). Prompts if the routing name matches more than one row, even when only one is online \u2014 both are equally permanent to delete.").argument("<ref>", "session UUID or @routingName").option("--hard", "required: confirm you want a permanent delete (no soft form is offered without this flag)").action(async (ref, opts) => {
|
|
68499
68521
|
if (!opts.hard) {
|
|
68500
68522
|
console.error("error: hard delete requires --hard. Did you mean `claw session archive <ref>`?");
|
|
68501
68523
|
process.exit(2);
|
|
68502
68524
|
}
|
|
68503
|
-
const id = await resolveSessionId(ref);
|
|
68525
|
+
const id = await resolveSessionId(ref, { destructive: true });
|
|
68504
68526
|
const r = await api.delete(
|
|
68505
68527
|
`/api/v1/sessions/${encodeURIComponent(id)}?hard=true`
|
|
68506
68528
|
);
|
|
68507
|
-
|
|
68529
|
+
const sweep = r.blobsSwept && r.blobsSwept > 0 ? ` \xB7 swept ${r.blobsSwept} blob${r.blobsSwept === 1 ? "" : "s"} (${r.bytesFreed ?? 0} bytes freed)` : "";
|
|
68530
|
+
console.log(`\u2717 deleted ${r.sessionId} (events / op-messages / shares / files cascaded)${sweep}`);
|
|
68508
68531
|
});
|
|
68509
68532
|
var sessionPrompt = new Command("prompt").description('send a one-shot prompt to a session\'s live Claude. Fire-and-forget \u2014 to find the eventual reply, run `claw session events <ref> --kind=chat --type=reply` (or `claw route <peer> "..."` for ask-mode that blocks for the answer).').argument("<ref>", "session UUID or @routingName").argument("<text>", "prompt text \u2014 quote multi-word").action(async (ref, text) => {
|
|
68510
68533
|
const id = await resolveSessionId(ref);
|
|
@@ -68543,7 +68566,7 @@ var sessionSharesCmd = new Command("shares").description("list users granted acc
|
|
|
68543
68566
|
console.log(` @${s.login.padEnd(20)} ${s.role.padEnd(9)} since ${s.createdAt}`);
|
|
68544
68567
|
}
|
|
68545
68568
|
});
|
|
68546
|
-
function
|
|
68569
|
+
function fmtBytes2(n) {
|
|
68547
68570
|
if (n < 1024) return `${n} B`;
|
|
68548
68571
|
if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
|
|
68549
68572
|
if (n < 1024 ** 3) return `${(n / 1024 / 1024).toFixed(1)} MB`;
|
|
@@ -68565,7 +68588,7 @@ var sessionFiles = new Command("files").description("list a session's file attac
|
|
|
68565
68588
|
const ts2 = f.uploadedAt.slice(0, 19).replace("T", " ");
|
|
68566
68589
|
const flag = f.deletedAt ? " [deleted]" : "";
|
|
68567
68590
|
const sha = f.sha256.slice(0, 12);
|
|
68568
|
-
console.log(`#${String(f.id).padStart(5)} ${ts2} ${
|
|
68591
|
+
console.log(`#${String(f.id).padStart(5)} ${ts2} ${fmtBytes2(f.size).padStart(8)} @${f.uploaderLogin.padEnd(20)} ${f.scope.padEnd(11)} sha=${sha}\u2026 ${f.filename}${flag}`);
|
|
68569
68592
|
}
|
|
68570
68593
|
});
|
|
68571
68594
|
var sessionFileRm = new Command("file-rm").description("delete a file by id. Soft-deletes the row; on-disk blob is swept once no live row references its sha. Prompter+ on the file's session.").argument("<fileId>", "file id (from `claw session files` output, the # column)").action(async (fileId) => {
|
|
@@ -68583,7 +68606,7 @@ var sessionFileRm = new Command("file-rm").description("delete a file by id. Sof
|
|
|
68583
68606
|
}
|
|
68584
68607
|
const refs = r.refsRemaining ?? 0;
|
|
68585
68608
|
if (r.blobDeleted) {
|
|
68586
|
-
console.log(`\u2717 deleted file #${id} \u2014 blob swept (${
|
|
68609
|
+
console.log(`\u2717 deleted file #${id} \u2014 blob swept (${fmtBytes2(r.freedBytes ?? 0)} freed; was the last reference)`);
|
|
68587
68610
|
} else {
|
|
68588
68611
|
console.log(`\u2717 deleted file #${id} \u2014 blob retained (${refs} other live reference${refs === 1 ? "" : "s"})`);
|
|
68589
68612
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "clawborrator-cli",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.52",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "claw — command-line client for clawborrator. Attach to remote Claude Code sessions, send prompts, resolve permission gates, route across sessions, manage public agents and webhooks. Auth via GitHub OAuth + PKCE.",
|
|
6
6
|
"license": "MIT",
|