dockai 0.2.4 → 0.2.6
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 +15 -3
- package/dist/commands/claude.js +3 -5
- package/dist/commands/claude.js.map +1 -1
- package/dist/commands/completion.js +129 -0
- package/dist/commands/completion.js.map +1 -0
- package/dist/commands/doctor.js +159 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/logs.js +33 -2
- package/dist/commands/logs.js.map +1 -1
- package/dist/commands/sessions.js +6 -14
- package/dist/commands/sessions.js.map +1 -1
- package/dist/commands/ssh-config.js +10 -0
- package/dist/commands/ssh-config.js.map +1 -1
- package/dist/commands/start-stop.js +32 -0
- package/dist/commands/start-stop.js.map +1 -1
- package/dist/index.js +29 -8
- package/dist/index.js.map +1 -1
- package/dist/lib/__tests__/doctor.test.js +41 -0
- package/dist/lib/__tests__/doctor.test.js.map +1 -0
- package/dist/lib/__tests__/git-remote.test.js +26 -0
- package/dist/lib/__tests__/git-remote.test.js.map +1 -0
- package/dist/lib/__tests__/recent.test.js +49 -0
- package/dist/lib/__tests__/recent.test.js.map +1 -0
- package/dist/lib/__tests__/select.test.js +50 -0
- package/dist/lib/__tests__/select.test.js.map +1 -0
- package/dist/lib/follow.js +32 -0
- package/dist/lib/follow.js.map +1 -0
- package/dist/lib/format.js +71 -0
- package/dist/lib/format.js.map +1 -0
- package/dist/lib/git-remote.js +42 -0
- package/dist/lib/git-remote.js.map +1 -0
- package/dist/lib/pick-project.js +19 -66
- package/dist/lib/pick-project.js.map +1 -1
- package/dist/lib/recent.js +63 -0
- package/dist/lib/recent.js.map +1 -0
- package/dist/lib/remote.js +21 -0
- package/dist/lib/remote.js.map +1 -1
- package/dist/lib/select.js +148 -0
- package/dist/lib/select.js.map +1 -0
- package/dist/lib/update-check.js +92 -0
- package/dist/lib/update-check.js.map +1 -0
- package/dist/version.js +1 -1
- package/package.json +1 -1
|
@@ -90,6 +90,16 @@ export function ensureSshConfig() {
|
|
|
90
90
|
writeFileSync(file, `${current}${sep}${current.length ? "\n" : ""}${block}\n`, { mode: 0o600 });
|
|
91
91
|
return "written";
|
|
92
92
|
}
|
|
93
|
+
/** Read-only: is the block there, and is it the one this install would write? */
|
|
94
|
+
export function sshConfigState() {
|
|
95
|
+
const file = path.join(homedir(), ".ssh", "config");
|
|
96
|
+
const current = existsSync(file) ? readFileSync(file, "utf8") : "";
|
|
97
|
+
const start = current.indexOf(BEGIN);
|
|
98
|
+
const end = current.indexOf(END);
|
|
99
|
+
if (start === -1 || end === -1 || end < start)
|
|
100
|
+
return "missing";
|
|
101
|
+
return current.slice(start, end + END.length) === sshConfigBlock() ? "current" : "stale";
|
|
102
|
+
}
|
|
93
103
|
export async function sshConfigCommand(options) {
|
|
94
104
|
const api = createApiClient();
|
|
95
105
|
const projects = (await api.project.list.query());
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssh-config.js","sourceRoot":"","sources":["../../src/commands/ssh-config.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ssh-config.js","sourceRoot":"","sources":["../../src/commands/ssh-config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,oBAAoB,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAE5C,MAAM,KAAK,GAAG,wBAAwB,CAAC;AACvC,MAAM,GAAG,GAAG,sBAAsB,CAAC;AAEnC,8EAA8E;AAC9E,SAAS,OAAO,CAAC,IAAY;IAC3B,IAAI,kBAAkB,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IAC/C,OAAO,IAAI,IAAI,CAAC,OAAO,CAAC,YAAY,EAAE,MAAM,CAAC,GAAG,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAS,WAAW;IAClB,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAC/B,2EAA2E;IAC3E,IAAI,CAAC,MAAM,IAAI,CAAC,UAAU,CAAC,MAAM,CAAC;QAAE,OAAO,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC;AAC3D,CAAC;AAED;;;;;;GAMG;AACH,sGAAsG;AACtG,SAAS,cAAc;IACrB,OAAO;QACL,KAAK;QACL,2EAA2E;QAC3E,sEAAsE;QACtE,wDAAwD;QACxD,eAAe;QACf,eAAe;QACf,kBAAkB,WAAW,EAAE,WAAW;QAC1C,mEAAmE;QACnE,2DAA2D;QAC3D,4BAA4B;QAC5B,gCAAgC;QAChC,kBAAkB;QAClB,GAAG;KACJ,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC;AAED;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,eAAe;IAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAC/B,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;QAAE,SAAS,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvE,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,GAAG,KAAK,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;QACxD,IAAI,QAAQ,KAAK,KAAK;YAAE,OAAO,WAAW,CAAC;QAC3C,aAAa,CAAC,IAAI,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;QACxG,OAAO,SAAS,CAAC;IACnB,CAAC;IACD,MAAM,GAAG,GAAG,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACvE,aAAa,CAAC,IAAI,EAAE,GAAG,OAAO,GAAG,GAAG,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,GAAG,KAAK,IAAI,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAChG,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,cAAc;IAC5B,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC;IACpD,MAAM,OAAO,GAAG,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IACnE,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACrC,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC;IACjC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,GAAG,KAAK,CAAC,CAAC,IAAI,GAAG,GAAG,KAAK;QAAE,OAAO,SAAS,CAAC;IAChE,OAAO,OAAO,CAAC,KAAK,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC,MAAM,CAAC,KAAK,cAAc,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,OAAO,CAAC;AAC3F,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,OAA4B;IACjE,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,MAAM,QAAQ,GAAG,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAA0C,CAAC;IAC3F,MAAM,KAAK,GAAG,cAAc,EAAE,CAAC;IAE/B,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAClB,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,GAAG,IAAI,CAAC,CAAC;QACnC,OAAO;IACT,CAAC;IAED,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,WAAW,CAAC,CAAC,CAAC,iDAAiD,CAAC,CAAC,CAAC,iBAAiB,GAAG,GAAG,CAAC,CAAC;IAC/G,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAC;IACtC,KAAK,MAAM,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,CAAC;QACrC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IACxC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,4DAA4D,CAAC,CAAC;IAC1E,OAAO,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAChB,OAAO,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;IACvE,OAAO,CAAC,GAAG,CAAC,oEAAoE,CAAC,CAAC;AACpF,CAAC;AAED,uDAAuD;AACvD,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY;IAC5C,MAAM,IAAI,GAAG,UAAU,IAAI,EAAE,CAAC;IAC9B,MAAM,UAAU,GAAG,cAAc,IAAI,EAAE,CAAC;IAExC,OAAO,CAAC,GAAG,CAAC,WAAW,UAAU,OAAO,IAAI,KAAK,CAAC,CAAC;IACnD,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,UAAU,EAAE,cAAc,IAAI,EAAE,EAAE,UAAU,CAAC,EAAE;QAC1E,KAAK,EAAE,SAAS;KACjB,CAAC,CAAC;IAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;QACrB,OAAO,CAAC,KAAK,CAAC,0DAA0D,CAAC,CAAC;QAC1E,OAAO,CAAC,KAAK,CAAC,6EAA6E,CAAC,CAAC;QAC7F,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;QAClB,OAAO,CAAC,KAAK,CAAC,sBAAsB,CAAC,CAAC;QACtC,OAAO,CAAC,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;QAC/B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,CAAC,CAAC;IAEH,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,IAAI,EAAE,EAAE;QACzB,IAAI,IAAI,IAAI,IAAI,KAAK,CAAC,EAAE,CAAC;YACvB,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;YAClB,OAAO,CAAC,KAAK,CAAC,uBAAuB,IAAI,sCAAsC,CAAC,CAAC;YACjF,OAAO,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;YAC9D,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,CAAC;IACH,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -32,4 +32,36 @@ export async function stopCommand(slug) {
|
|
|
32
32
|
fail(err, "Could not stop it");
|
|
33
33
|
}
|
|
34
34
|
}
|
|
35
|
+
/**
|
|
36
|
+
* Start a project and wait until its worker is up, printing a dot while it
|
|
37
|
+
* comes. A cold start can take two minutes (the worker agent has to answer
|
|
38
|
+
* before the orchestrator calls it running), so the deadline is generous.
|
|
39
|
+
* Returns whether it got there.
|
|
40
|
+
*/
|
|
41
|
+
export async function startAndWait(api, project, timeoutMs = 180_000) {
|
|
42
|
+
await api.project.start.mutate({ id: project.id });
|
|
43
|
+
process.stdout.write(`Starting ${project.name}`);
|
|
44
|
+
const deadline = Date.now() + timeoutMs;
|
|
45
|
+
while (Date.now() < deadline) {
|
|
46
|
+
await new Promise((r) => setTimeout(r, 3000));
|
|
47
|
+
let status;
|
|
48
|
+
try {
|
|
49
|
+
status = (await api.project.list.query()).find((p) => p.id === project.id)?.status;
|
|
50
|
+
}
|
|
51
|
+
catch {
|
|
52
|
+
// The orchestrator can blip while a worker is created; keep waiting.
|
|
53
|
+
}
|
|
54
|
+
if (status === "RUNNING") {
|
|
55
|
+
process.stdout.write(" running.\n");
|
|
56
|
+
return true;
|
|
57
|
+
}
|
|
58
|
+
if (status === "ERROR") {
|
|
59
|
+
process.stdout.write(" failed.\n");
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
process.stdout.write(".");
|
|
63
|
+
}
|
|
64
|
+
process.stdout.write(" still starting.\n");
|
|
65
|
+
return false;
|
|
66
|
+
}
|
|
35
67
|
//# sourceMappingURL=start-stop.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"start-stop.js","sourceRoot":"","sources":["../../src/commands/start-stop.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAgC,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,IAAI,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAErD,KAAK,UAAU,WAAW,CAAC,GAAc,EAAE,IAAY;IACrD,MAAM,QAAQ,GAAG,CAAC,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,CAAc,CAAC;IAC/D,MAAM,OAAO,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACtD,IAAI,CAAC,OAAO,EAAE,CAAC;QACb,aAAa,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;IAChC,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,IAAY;IAC7C,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,4EAA4E;IAC5E,uEAAuE;IACvE,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7C,MAAM,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QACnD,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,EAAE,oBAAoB,CAAC,CAAC;IAClC,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,IAAY;IAC5C,MAAM,GAAG,GAAG,eAAe,EAAE,CAAC;IAC9B,IAAI,CAAC;QACH,MAAM,OAAO,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC7C,MAAM,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,EAAE,OAAO,CAAC,EAAE,EAAE,CAAC,CAAC;QAClD,OAAO,CAAC,GAAG,CAAC,YAAY,OAAO,CAAC,IAAI,KAAK,CAAC,CAAC;IAC7C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,CAAC,GAAG,EAAE,mBAAmB,CAAC,CAAC;IACjC,CAAC;AACH,CAAC"}
|
|
1
|
+
{"version":3,"file":"start-stop.js","sourceRoot":"","sources":["../../src/commands/start-stop.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
CHANGED
|
@@ -19,6 +19,9 @@ import { ensureSlug } from "./lib/pick-project.js";
|
|
|
19
19
|
import { pasteCommand } from "./commands/paste.js";
|
|
20
20
|
import { accountsCommand, accountsLoginCommand } from "./commands/accounts.js";
|
|
21
21
|
import { CLI_VERSION } from "./version.js";
|
|
22
|
+
import { checkForUpdate } from "./lib/update-check.js";
|
|
23
|
+
import { doctorCommand } from "./commands/doctor.js";
|
|
24
|
+
import { completeCommand, completionCommand } from "./commands/completion.js";
|
|
22
25
|
const program = new Command();
|
|
23
26
|
program
|
|
24
27
|
.name("dockai")
|
|
@@ -31,7 +34,7 @@ program
|
|
|
31
34
|
// guess live in four different command descriptions (audit 6 §17).
|
|
32
35
|
.addHelpText("after", `
|
|
33
36
|
Examples:
|
|
34
|
-
$ dockai login set the server and token, once per
|
|
37
|
+
$ dockai login set the server and token, once per computer
|
|
35
38
|
$ dockai projects --json machine-readable, for scripts
|
|
36
39
|
$ dockai claude app Claude Code in the "app" worker, in tmux
|
|
37
40
|
$ dockai claude app --permission-mode bypassPermissions
|
|
@@ -77,10 +80,11 @@ program
|
|
|
77
80
|
.command("logs <slug>")
|
|
78
81
|
.description("Fetch project logs")
|
|
79
82
|
.option("-t, --tail <lines>", "Number of lines", "100")
|
|
83
|
+
.option("-f, --follow", "Keep printing new lines as they arrive (Ctrl-C to stop)")
|
|
80
84
|
.action(logsCommand);
|
|
81
85
|
program
|
|
82
86
|
.command("open <slug>")
|
|
83
|
-
.description("Open the
|
|
87
|
+
.description("Open the project's page in the dashboard")
|
|
84
88
|
.action(openCommand);
|
|
85
89
|
program
|
|
86
90
|
.command("ssh-config")
|
|
@@ -98,10 +102,10 @@ program
|
|
|
98
102
|
// conversation the phone is on; naming one is an explicit choice.
|
|
99
103
|
.option("-s, --session <name>", "tmux session to attach to or create (before the project name; default claude-cli)")
|
|
100
104
|
.option("--no-tmux", "Skip tmux — the session ends when you disconnect (before the project name)")
|
|
101
|
-
.option("--no-chrome", "Don't forward this
|
|
102
|
-
.option("--no-client", "Don't offer this
|
|
103
|
-
.option("--root <dir>", "Directory the conversation may read from on this
|
|
104
|
-
.option("--allow-run", "Let the conversation run commands on this
|
|
105
|
+
.option("--no-chrome", "Don't forward this computer's Claude in Chrome bridge into the worker (before the project name)")
|
|
106
|
+
.option("--no-client", "Don't offer this computer's files and clipboard to the conversation (before the project name)")
|
|
107
|
+
.option("--root <dir>", "Directory the conversation may read from on this computer; repeatable (default: the current directory)", (v, prev) => [...(prev ?? []), v], [])
|
|
108
|
+
.option("--allow-run", "Let the conversation run commands on this computer (each run is logged here); the project's own setting is the default")
|
|
105
109
|
.option("--no-allow-run", "Refuse commands on this machine even if the project allows them by default")
|
|
106
110
|
.passThroughOptions()
|
|
107
111
|
.action((slug, claudeArgs, options) => claudeCommand(slug, options, claudeArgs));
|
|
@@ -124,7 +128,8 @@ program
|
|
|
124
128
|
.action(accountsCommand);
|
|
125
129
|
const sessions = program
|
|
126
130
|
.command("sessions")
|
|
127
|
-
.
|
|
131
|
+
.alias("conversations")
|
|
132
|
+
.description("A project's conversations: list, resume, hand off, and bring this computer's into it");
|
|
128
133
|
sessions
|
|
129
134
|
.command("list <slug>")
|
|
130
135
|
.description("Conversations on the worker, with ids and whether each is live")
|
|
@@ -167,16 +172,32 @@ program
|
|
|
167
172
|
.command("proxy <host>")
|
|
168
173
|
.description("SSH ProxyCommand transport (used by ssh, not run directly)")
|
|
169
174
|
.action(proxyCommand);
|
|
175
|
+
program
|
|
176
|
+
.command("doctor")
|
|
177
|
+
.description("Check this computer's setup — which dockai runs, its version, the server, the login, ssh — and say how to fix what is wrong")
|
|
178
|
+
.option("--fix", "Also apply the safe fixes (rewrite the ~/.ssh/config block)")
|
|
179
|
+
.action(doctorCommand);
|
|
180
|
+
program
|
|
181
|
+
.command("completion [shell]")
|
|
182
|
+
.description("Print tab completion for zsh or bash; dockai completion zsh > ~/.dockai-completion.zsh, then source it from ~/.zshrc")
|
|
183
|
+
.action(completionCommand);
|
|
184
|
+
program
|
|
185
|
+
.command("__complete <kind>", { hidden: true })
|
|
186
|
+
.action((kind) => completeCommand(program, kind));
|
|
170
187
|
program
|
|
171
188
|
.command("status")
|
|
172
189
|
.description("Show server status and project overview")
|
|
173
190
|
.action(statusCommand);
|
|
191
|
+
checkForUpdate(CLI_VERSION, process.argv);
|
|
174
192
|
// Commands that take a project first: ask for it when it was left out.
|
|
175
193
|
let argv = process.argv;
|
|
176
194
|
argv = await ensureSlug(argv, ["claude"], { flags: ["--no-tmux", "--tmux", "--no-chrome", "--chrome", "--no-client", "--allow-run", "--no-allow-run"], valued: ["-s", "--session", "--root"] });
|
|
177
195
|
// `sessions handoff` was missing from this list, so it alone asked for a slug
|
|
178
196
|
// differently from its three siblings (audit 6 §17).
|
|
179
|
-
for (const path of [
|
|
197
|
+
for (const path of [
|
|
198
|
+
["push"], ["paste"],
|
|
199
|
+
...["sessions", "conversations"].flatMap((group) => ["list", "resume", "push", "handoff"].map((sub) => [group, sub])),
|
|
200
|
+
]) {
|
|
180
201
|
argv = await ensureSlug(argv, path);
|
|
181
202
|
}
|
|
182
203
|
await program.parseAsync(argv);
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACjI,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACrE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACzE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,sBAAsB,EAAE,MAAM,wBAAwB,CAAC;AACjI,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAC;AACnD,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,EAAE,eAAe,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC/E,OAAO,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAC3C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AACrD,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE9E,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,kDAAkD,CAAC;KAC/D,OAAO,CAAC,WAAW,CAAC;IACrB,8EAA8E;IAC9E,8CAA8C;KAC7C,uBAAuB,EAAE;IAC1B,4EAA4E;IAC5E,mEAAmE;KAClE,WAAW,CAAC,OAAO,EAAE;;;;;;;;;;CAUvB,CAAC,CAAC;AAEH,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,qCAAqC,CAAC;KAClD,MAAM,CAAC,oBAAoB,EAAE,YAAY,CAAC;KAC1C,MAAM,CAAC,oBAAoB,EAAE,+BAA+B,CAAC;KAC7D,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,2BAA2B,CAAC;KACxC,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,sCAAsC,CAAC;KACnD,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,+BAA+B,CAAC;KAC5C,MAAM,CAAC,QAAQ,EAAE,iCAAiC,CAAC;KACnD,MAAM,CAAC,eAAe,CAAC,CAAC;AAE3B,OAAO;KACJ,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,iBAAiB,CAAC;KAC9B,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,gBAAgB,CAAC;KAC7B,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,gBAAgB,CAAC;KACzB,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,UAAU,EAAE,gCAAgC,CAAC;KACpD,MAAM,CAAC,OAAO,EAAE,sCAAsC,CAAC;KACvD,MAAM,CAAC,cAAc,CAAC,CAAC;AAE1B,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,oBAAoB,CAAC;KACjC,MAAM,CAAC,oBAAoB,EAAE,iBAAiB,EAAE,KAAK,CAAC;KACtD,MAAM,CAAC,cAAc,EAAE,yDAAyD,CAAC;KACjF,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,0CAA0C,CAAC;KACvD,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,YAAY,CAAC;KACrB,WAAW,CAAC,sEAAsE,CAAC;KACnF,MAAM,CAAC,SAAS,EAAE,sDAAsD,CAAC;KACzE,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAE5B,OAAO;KACJ,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,uDAAuD,CAAC;KACpE,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,OAAO;KACJ,OAAO,CAAC,+BAA+B,CAAC;KACxC,WAAW,CAAC,yQAAyQ,CAAC;IACvR,sEAAsE;IACtE,kEAAkE;KACjE,MAAM,CAAC,sBAAsB,EAAE,mFAAmF,CAAC;KACnH,MAAM,CAAC,WAAW,EAAE,4EAA4E,CAAC;KACjG,MAAM,CAAC,aAAa,EAAE,iGAAiG,CAAC;KACxH,MAAM,CAAC,aAAa,EAAE,+FAA+F,CAAC;KACtH,MAAM,CAAC,cAAc,EAAE,wGAAwG,EAAE,CAAC,CAAS,EAAE,IAAc,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,EAAE,EAAc,CAAC;KACrM,MAAM,CAAC,aAAa,EAAE,wHAAwH,CAAC;KAC/I,MAAM,CAAC,gBAAgB,EAAE,4EAA4E,CAAC;KACtG,kBAAkB,EAAE;KACpB,MAAM,CAAC,CAAC,IAAY,EAAE,UAAoB,EAAE,OAAsH,EAAE,EAAE,CACrK,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,UAAU,CAAC,CACzC,CAAC;AAEJ,OAAO;KACJ,OAAO,CAAC,wBAAwB,CAAC;KACjC,WAAW,CAAC,4FAA4F,CAAC;KACzG,MAAM,CAAC,iBAAiB,EAAE,wDAAwD,CAAC;KACnF,MAAM,CAAC,WAAW,CAAC,CAAC;AAEvB,MAAM,QAAQ,GAAG,OAAO;KACrB,OAAO,CAAC,UAAU,CAAC;KACnB,WAAW,CAAC,sFAAsF,CAAC;KACnG,MAAM,CAAC,eAAe,CAAC,CAAC;AAC3B,QAAQ;KACL,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,6FAA6F,CAAC;KAC1G,MAAM,CAAC,oBAAoB,CAAC,CAAC;AAEhC,OAAO;KACJ,OAAO,CAAC,OAAO,CAAC;KAChB,WAAW,CAAC,0DAA0D,CAAC;KACvE,MAAM,CAAC,eAAe,CAAC,CAAC;AAE3B,MAAM,QAAQ,GAAG,OAAO;KACrB,OAAO,CAAC,UAAU,CAAC;KACnB,KAAK,CAAC,eAAe,CAAC;KACtB,WAAW,CAAC,sFAAsF,CAAC,CAAC;AACvG,QAAQ;KACL,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,gEAAgE,CAAC;KAC7E,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAC/B,QAAQ;KACL,OAAO,CAAC,yBAAyB,CAAC;KAClC,WAAW,CAAC,uGAAuG,CAAC;KACpH,MAAM,CAAC,UAAU,EAAE,8EAA8E,CAAC;KAClG,MAAM,CAAC,qBAAqB,CAAC,CAAC;AACjC,QAAQ;KACL,OAAO,CAAC,sBAAsB,CAAC;KAC/B,WAAW,CAAC,uKAAuK,CAAC;KACpL,MAAM,CAAC,aAAa,EAAE,oEAAoE,CAAC;KAC3F,MAAM,CAAC,iBAAiB,EAAE,yDAAyD,CAAC;KACpF,MAAM,CAAC,aAAa,EAAE,yGAAyG,CAAC;KAChI,MAAM,CAAC,aAAa,EAAE,wHAAwH,CAAC;KAC/I,MAAM,CAAC,YAAY,EAAE,sHAAsH,CAAC;KAC5I,MAAM,CAAC,sBAAsB,CAAC,CAAC;AAClC,QAAQ;KACL,OAAO,CAAC,aAAa,CAAC;KACtB,WAAW,CAAC,+GAA+G,CAAC;KAC5H,MAAM,CAAC,cAAc,EAAE,kFAAkF,CAAC;KAC1G,MAAM,CAAC,cAAc,EAAE,6CAA6C,CAAC;KACrE,MAAM,CAAC,mBAAmB,EAAE,4DAA4D,CAAC;KACzF,MAAM,CAAC,aAAa,EAAE,wDAAwD,CAAC;KAC/E,MAAM,CAAC,UAAU,EAAE,6FAA6F,CAAC;KACjH,MAAM,CAAC,WAAW,EAAE,oDAAoD,CAAC;KACzE,MAAM,CAAC,mBAAmB,CAAC,CAAC;AAE/B,OAAO;KACJ,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,qFAAqF,CAAC;KAClG,MAAM,CAAC,sBAAsB,EAAE,2BAA2B,EAAE,YAAY,CAAC;KACzE,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB,OAAO;KACJ,OAAO,CAAC,iBAAiB,CAAC;KAC1B,WAAW,CAAC,0HAA0H,CAAC;KACvI,MAAM,CAAC,WAAW,EAAE,6DAA6D,CAAC;KAClF,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,cAAc,CAAC;KACvB,WAAW,CAAC,4DAA4D,CAAC;KACzE,MAAM,CAAC,YAAY,CAAC,CAAC;AAExB,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,6HAA6H,CAAC;KAC1I,MAAM,CAAC,OAAO,EAAE,6DAA6D,CAAC;KAC9E,MAAM,CAAC,aAAa,CAAC,CAAC;AAEzB,OAAO;KACJ,OAAO,CAAC,oBAAoB,CAAC;KAC7B,WAAW,CAAC,sHAAsH,CAAC;KACnI,MAAM,CAAC,iBAAiB,CAAC,CAAC;AAE7B,OAAO;KACJ,OAAO,CAAC,mBAAmB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;KAC9C,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,eAAe,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,CAAC;AAE5D,OAAO;KACJ,OAAO,CAAC,QAAQ,CAAC;KACjB,WAAW,CAAC,yCAAyC,CAAC;KACtD,MAAM,CAAC,aAAa,CAAC,CAAC;AAGzB,cAAc,CAAC,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;AAE1C,uEAAuE;AACvE,IAAI,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;AACxB,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,CAAC,QAAQ,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,UAAU,EAAE,aAAa,EAAE,aAAa,EAAE,gBAAgB,CAAC,EAAE,MAAM,EAAE,CAAC,IAAI,EAAE,WAAW,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;AAChM,8EAA8E;AAC9E,qDAAqD;AACrD,KAAK,MAAM,IAAI,IAAI;IACjB,CAAC,MAAM,CAAC,EAAE,CAAC,OAAO,CAAC;IACnB,GAAG,CAAC,UAAU,EAAE,eAAe,CAAC,CAAC,OAAO,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC,CAAC;CACtH,EAAE,CAAC;IACF,IAAI,GAAG,MAAM,UAAU,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AACtC,CAAC;AACD,MAAM,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,CAAC"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { chmodSync, mkdirSync, mkdtempSync, symlinkSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { compareVersions, updateNotice } from "../update-check.js";
|
|
6
|
+
import { dockaiOnPath } from "../../commands/doctor.js";
|
|
7
|
+
describe("the update notice", () => {
|
|
8
|
+
it("compares versions numerically", () => {
|
|
9
|
+
expect(compareVersions("0.2.10", "0.2.9")).toBe(1);
|
|
10
|
+
expect(compareVersions("0.2.5", "0.2.5")).toBe(0);
|
|
11
|
+
expect(compareVersions("0.1.0", "0.2.5")).toBe(-1);
|
|
12
|
+
expect(compareVersions("1.0.0", "1.0.0-beta")).toBe(1);
|
|
13
|
+
});
|
|
14
|
+
it("speaks only when a newer one exists", () => {
|
|
15
|
+
expect(updateNotice("0.1.0", "0.2.5")).toContain("0.2.5 is available (you have 0.1.0)");
|
|
16
|
+
expect(updateNotice("0.2.5", "0.2.5")).toBeNull();
|
|
17
|
+
expect(updateNotice("0.2.6", "0.2.5")).toBeNull();
|
|
18
|
+
expect(updateNotice("0.2.5", null)).toBeNull();
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
describe("which dockai a shell runs", () => {
|
|
22
|
+
// The case that prompted doctor: a symlink in ~/.local/bin into a stale
|
|
23
|
+
// checkout, ahead of the installed release on PATH.
|
|
24
|
+
it("lists every copy in PATH order, resolved through symlinks", () => {
|
|
25
|
+
const root = mkdtempSync(path.join(tmpdir(), "dockai-path-"));
|
|
26
|
+
const checkout = path.join(root, "Projects/DockAI/apps/cli/dist");
|
|
27
|
+
const local = path.join(root, ".local/bin");
|
|
28
|
+
const npm = path.join(root, "npm/bin");
|
|
29
|
+
for (const d of [checkout, local, npm])
|
|
30
|
+
mkdirSync(d, { recursive: true });
|
|
31
|
+
writeFileSync(path.join(checkout, "index.js"), "#!/usr/bin/env node\n");
|
|
32
|
+
chmodSync(path.join(checkout, "index.js"), 0o755);
|
|
33
|
+
symlinkSync(path.join(checkout, "index.js"), path.join(local, "dockai"));
|
|
34
|
+
writeFileSync(path.join(npm, "dockai"), "#!/bin/sh\n");
|
|
35
|
+
chmodSync(path.join(npm, "dockai"), 0o755);
|
|
36
|
+
const found = dockaiOnPath([local, path.join(root, "nothing"), npm, local].join(path.delimiter), ["dockai"]);
|
|
37
|
+
expect(found.map((f) => f.entry)).toEqual([path.join(local, "dockai"), path.join(npm, "dockai")]);
|
|
38
|
+
expect(found[0].target).toMatch(/apps\/cli\/dist\/index\.js$/);
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
//# sourceMappingURL=doctor.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/doctor.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { projectsForRemotes, repoKey } from "../git-remote.js";
|
|
3
|
+
describe("matching a folder's git remote to a project", () => {
|
|
4
|
+
it("reads every remote spelling as one key", () => {
|
|
5
|
+
for (const url of [
|
|
6
|
+
"git@github.com:polamoros/DockAI.git",
|
|
7
|
+
"https://github.com/polamoros/dockai",
|
|
8
|
+
"https://github.com/polamoros/DockAI.git/",
|
|
9
|
+
"ssh://git@github.com/polamoros/DockAI.git",
|
|
10
|
+
"https://x-access-token:abc@github.com/polamoros/DockAI.git",
|
|
11
|
+
])
|
|
12
|
+
expect(repoKey(url)).toBe("github.com/polamoros/dockai");
|
|
13
|
+
expect(repoKey("not a url")).toBeNull();
|
|
14
|
+
expect(repoKey(null)).toBeNull();
|
|
15
|
+
});
|
|
16
|
+
it("finds the projects on that repository and nothing else", () => {
|
|
17
|
+
const projects = [
|
|
18
|
+
{ slug: "dockai", githubRepoUrl: "https://github.com/polamoros/DockAI" },
|
|
19
|
+
{ slug: "dockai-test", githubRepoUrl: null },
|
|
20
|
+
{ slug: "wedding", githubRepoUrl: "https://github.com/polamoros/wedding" },
|
|
21
|
+
];
|
|
22
|
+
expect(projectsForRemotes(projects, ["github.com/polamoros/dockai"])).toEqual(["dockai"]);
|
|
23
|
+
expect(projectsForRemotes(projects, [])).toEqual([]);
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
//# sourceMappingURL=git-remote.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-remote.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/git-remote.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAE/D,QAAQ,CAAC,6CAA6C,EAAE,GAAG,EAAE;IAC3D,EAAE,CAAC,wCAAwC,EAAE,GAAG,EAAE;QAChD,KAAK,MAAM,GAAG,IAAI;YAChB,qCAAqC;YACrC,qCAAqC;YACrC,0CAA0C;YAC1C,2CAA2C;YAC3C,4DAA4D;SAC7D;YAAE,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC;QAC5D,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;QACxC,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,QAAQ,EAAE,CAAC;IACnC,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,wDAAwD,EAAE,GAAG,EAAE;QAChE,MAAM,QAAQ,GAAG;YACf,EAAE,IAAI,EAAE,QAAQ,EAAE,aAAa,EAAE,qCAAqC,EAAE;YACxE,EAAE,IAAI,EAAE,aAAa,EAAE,aAAa,EAAE,IAAI,EAAE;YAC5C,EAAE,IAAI,EAAE,SAAS,EAAE,aAAa,EAAE,sCAAsC,EAAE;SAC3E,CAAC;QACF,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,CAAC,6BAA6B,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC1F,MAAM,CAAC,kBAAkB,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACvD,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { mkdtempSync } from "node:fs";
|
|
3
|
+
import { tmpdir } from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { orderForDir, readRecent, recordUse, withUse } from "../recent.js";
|
|
6
|
+
const projects = [
|
|
7
|
+
{ slug: "camper", name: "Camper 3.0", status: "RUNNING" },
|
|
8
|
+
{ slug: "dockai", name: "DockAI", status: "RUNNING" },
|
|
9
|
+
{ slug: "notestack", name: "NoteStack", status: "STOPPED" },
|
|
10
|
+
{ slug: "wedding", name: "Wedding Assistant", status: "RUNNING" },
|
|
11
|
+
];
|
|
12
|
+
describe("the project picker, per folder", () => {
|
|
13
|
+
it("lists what was used from this folder first, most recent on top", () => {
|
|
14
|
+
let recent = withUse({}, "/p/DockAI", "notestack", 1);
|
|
15
|
+
recent = withUse(recent, "/p/DockAI", "dockai", 2);
|
|
16
|
+
const { ordered, usedHere } = orderForDir(projects, recent, "/p/DockAI");
|
|
17
|
+
expect(ordered.map((p) => p.slug)).toEqual(["dockai", "notestack", "camper", "wedding"]);
|
|
18
|
+
expect(usedHere).toBe(2);
|
|
19
|
+
});
|
|
20
|
+
it("falls back to running first, then by name, in a folder with no history", () => {
|
|
21
|
+
const { ordered, usedHere } = orderForDir(projects, withUse({}, "/elsewhere", "notestack", 1), "/p/new");
|
|
22
|
+
expect(ordered.map((p) => p.slug)).toEqual(["camper", "dockai", "wedding", "notestack"]);
|
|
23
|
+
expect(usedHere).toBe(0);
|
|
24
|
+
});
|
|
25
|
+
it("moves a re-used project to the front without duplicating it", () => {
|
|
26
|
+
let recent = withUse({}, "/d", "a", 1);
|
|
27
|
+
recent = withUse(recent, "/d", "b", 2);
|
|
28
|
+
recent = withUse(recent, "/d", "a", 3);
|
|
29
|
+
expect(recent["/d"].map((e) => e.slug)).toEqual(["a", "b"]);
|
|
30
|
+
});
|
|
31
|
+
it("persists across runs, and survives a missing or broken file", () => {
|
|
32
|
+
const file = path.join(mkdtempSync(path.join(tmpdir(), "dockai-recent-")), "recent.json");
|
|
33
|
+
expect(readRecent(file)).toEqual({});
|
|
34
|
+
recordUse("/p/DockAI", "dockai", file);
|
|
35
|
+
expect(readRecent(file)["/p/DockAI"][0].slug).toBe("dockai");
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
describe("the project picker and the folder's git remote", () => {
|
|
39
|
+
it("defaults to the checkout's project in a folder with no history", () => {
|
|
40
|
+
const { ordered, usedHere } = orderForDir(projects, {}, "/p/Wedding", ["wedding"]);
|
|
41
|
+
expect(ordered[0].slug).toBe("wedding");
|
|
42
|
+
expect(usedHere).toBe(1);
|
|
43
|
+
});
|
|
44
|
+
it("lets history outrank the remote — the last choice here wins", () => {
|
|
45
|
+
const { ordered } = orderForDir(projects, withUse({}, "/p/DockAI", "notestack", 1), "/p/DockAI", ["dockai"]);
|
|
46
|
+
expect(ordered.map((p) => p.slug).slice(0, 2)).toEqual(["notestack", "dockai"]);
|
|
47
|
+
});
|
|
48
|
+
});
|
|
49
|
+
//# sourceMappingURL=recent.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recent.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/recent.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { describe, it, expect } from "vitest";
|
|
2
|
+
import { filterItems, windowFor } from "../select.js";
|
|
3
|
+
import { newLines } from "../follow.js";
|
|
4
|
+
import { ago, compact, conversationRow, modelLabel } from "../format.js";
|
|
5
|
+
const items = ["Camper 3.0", "DockAI", "Wedding Assistant", "Home Assistant"].map((l) => ({ label: `\x1b[2m${l}\x1b[22m`, value: l }));
|
|
6
|
+
describe("typing to filter a list", () => {
|
|
7
|
+
it("matches every word, any order, any case, ignoring colour codes", () => {
|
|
8
|
+
expect(filterItems(items, "assist").map((i) => i.value)).toEqual(["Wedding Assistant", "Home Assistant"]);
|
|
9
|
+
expect(filterItems(items, "ASS wed").map((i) => i.value)).toEqual(["Wedding Assistant"]);
|
|
10
|
+
expect(filterItems(items, "").length).toBe(4);
|
|
11
|
+
expect(filterItems(items, "nope")).toEqual([]);
|
|
12
|
+
});
|
|
13
|
+
it("scrolls a long list so the selection stays in view", () => {
|
|
14
|
+
expect(windowFor(5, 4, 10)).toEqual({ start: 0, end: 5 });
|
|
15
|
+
expect(windowFor(100, 0, 10)).toEqual({ start: 0, end: 10 });
|
|
16
|
+
expect(windowFor(100, 50, 10)).toEqual({ start: 45, end: 55 });
|
|
17
|
+
expect(windowFor(100, 99, 10)).toEqual({ start: 90, end: 100 });
|
|
18
|
+
});
|
|
19
|
+
});
|
|
20
|
+
describe("following logs", () => {
|
|
21
|
+
it("prints only what came after the last lines printed, even when lines repeat", () => {
|
|
22
|
+
expect(newLines(["a", "b", "c"], ["b", "c", "d", "e"]).lines).toEqual(["d", "e"]);
|
|
23
|
+
expect(newLines(["x", "ok", "ok"], ["ok", "ok", "y", "ok", "ok", "z"], 2).lines).toEqual(["z"]);
|
|
24
|
+
expect(newLines(["a", "b"], ["a", "b"]).lines).toEqual([]);
|
|
25
|
+
});
|
|
26
|
+
it("says when more arrived than one snapshot holds", () => {
|
|
27
|
+
expect(newLines(["a", "b"], ["q", "r"])).toEqual({ lines: ["q", "r"], gap: true });
|
|
28
|
+
});
|
|
29
|
+
});
|
|
30
|
+
describe("a conversation row", () => {
|
|
31
|
+
const now = Date.UTC(2026, 8, 23, 12);
|
|
32
|
+
it("says when, how long, how full and which model", () => {
|
|
33
|
+
const row = conversationRow({
|
|
34
|
+
id: "826b6bcf", title: "DockAI", firstPrompt: "", messageCount: 412, updatedAt: now - 3 * 3600_000,
|
|
35
|
+
remoteId: "cse_1", remoteState: "interactive", model: "claude-opus-5-5", contextTokens: 142_300,
|
|
36
|
+
}, now).replace(/\x1b\[[0-9;]*m/g, "");
|
|
37
|
+
for (const part of ["DockAI", "live", "3h ago", "412 msgs", "142k ctx", "Opus 5.5"])
|
|
38
|
+
expect(row).toContain(part);
|
|
39
|
+
});
|
|
40
|
+
it("formats its parts", () => {
|
|
41
|
+
expect(ago(now - 30_000, now)).toBe("just now");
|
|
42
|
+
expect(ago(now - 2 * 86400_000, now)).toBe("2d ago");
|
|
43
|
+
expect(compact(950)).toBe("950");
|
|
44
|
+
expect(compact(1_420_000)).toBe("1.4M");
|
|
45
|
+
expect(modelLabel("claude-haiku-4-5-20251001")).toBe("Haiku 4.5");
|
|
46
|
+
expect(modelLabel("claude-sonnet-5")).toBe("Sonnet 5");
|
|
47
|
+
expect(modelLabel("claude-fable-5-1")).toBe("Fable 5.1");
|
|
48
|
+
});
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=select.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.test.js","sourceRoot":"","sources":["../../../src/lib/__tests__/select.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAC9C,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,eAAe,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAEzE,MAAM,KAAK,GAAG,CAAC,YAAY,EAAE,QAAQ,EAAE,mBAAmB,EAAE,gBAAgB,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,UAAU,CAAC,UAAU,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;AAEvI,QAAQ,CAAC,yBAAyB,EAAE,GAAG,EAAE;IACvC,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,mBAAmB,EAAE,gBAAgB,CAAC,CAAC,CAAC;QAC1G,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAC;QACzF,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAC9C,MAAM,CAAC,WAAW,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,oDAAoD,EAAE,GAAG,EAAE;QAC5D,MAAM,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC,CAAC;QAC1D,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;QAC7D,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,CAAC,CAAC;QAC/D,MAAM,CAAC,SAAS,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC,CAAC;IAClE,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,gBAAgB,EAAE,GAAG,EAAE;IAC9B,EAAE,CAAC,4EAA4E,EAAE,GAAG,EAAE;QACpF,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;QAClF,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,IAAI,EAAE,IAAI,CAAC,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;QAChG,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC7D,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,gDAAgD,EAAE,GAAG,EAAE;QACxD,MAAM,CAAC,QAAQ,CAAC,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC,GAAG,EAAE,GAAG,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC,CAAC;IACrF,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC;AAEH,QAAQ,CAAC,oBAAoB,EAAE,GAAG,EAAE;IAClC,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC;IACtC,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;QACvD,MAAM,GAAG,GAAG,eAAe,CAAC;YAC1B,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,QAAQ,EAAE,WAAW,EAAE,EAAE,EAAE,YAAY,EAAE,GAAG,EAAE,SAAS,EAAE,GAAG,GAAG,CAAC,GAAG,QAAQ;YAClG,QAAQ,EAAE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,KAAK,EAAE,iBAAiB,EAAE,aAAa,EAAE,OAAO;SAChG,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,iBAAiB,EAAE,EAAE,CAAC,CAAC;QACvC,KAAK,MAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,UAAU,EAAE,UAAU,EAAE,UAAU,CAAC;YAAE,MAAM,CAAC,GAAG,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACnH,CAAC,CAAC,CAAC;IAEH,EAAE,CAAC,mBAAmB,EAAE,GAAG,EAAE;QAC3B,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,MAAM,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,CAAC,GAAG,CAAC,GAAG,GAAG,CAAC,GAAG,SAAS,EAAE,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrD,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACjC,MAAM,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,MAAM,CAAC,UAAU,CAAC,2BAA2B,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAClE,MAAM,CAAC,UAAU,CAAC,iBAAiB,CAAC,CAAC,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACvD,MAAM,CAAC,UAAU,CAAC,kBAAkB,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC3D,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The lines of a fresh log snapshot that were not in the last one.
|
|
3
|
+
*
|
|
4
|
+
* Both snapshots are tails of the same stream, so the new one overlaps the
|
|
5
|
+
* old one's end. The last few lines printed are found in the new snapshot —
|
|
6
|
+
* the *last* place they occur, because log lines repeat — and what follows
|
|
7
|
+
* them is new. When they cannot be found the stream moved on by more than a
|
|
8
|
+
* whole snapshot between polls, and everything is new; `gap` says so.
|
|
9
|
+
*/
|
|
10
|
+
export function newLines(printed, snapshot, window = 5) {
|
|
11
|
+
if (!printed.length)
|
|
12
|
+
return { lines: snapshot, gap: false };
|
|
13
|
+
// The longest overlap first, since a short one can match by accident on
|
|
14
|
+
// repeated lines; shorter ones only when the snapshot starts part-way into
|
|
15
|
+
// the window.
|
|
16
|
+
for (let w = Math.min(window, printed.length); w >= 1; w--) {
|
|
17
|
+
const tail = printed.slice(-w);
|
|
18
|
+
for (let end = snapshot.length - 1; end >= w - 1; end--) {
|
|
19
|
+
let match = true;
|
|
20
|
+
for (let k = 0; k < w; k++) {
|
|
21
|
+
if (snapshot[end - w + 1 + k] !== tail[k]) {
|
|
22
|
+
match = false;
|
|
23
|
+
break;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
if (match)
|
|
27
|
+
return { lines: snapshot.slice(end + 1), gap: false };
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return { lines: snapshot, gap: true };
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=follow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follow.js","sourceRoot":"","sources":["../../src/lib/follow.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,MAAM,UAAU,QAAQ,CAAC,OAAiB,EAAE,QAAkB,EAAE,MAAM,GAAG,CAAC;IACxE,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IAC5D,wEAAwE;IACxE,2EAA2E;IAC3E,cAAc;IACd,KAAK,IAAI,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;QAC3D,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/B,KAAK,IAAI,GAAG,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,GAAG,EAAE,EAAE,CAAC;YACxD,IAAI,KAAK,GAAG,IAAI,CAAC;YACjB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC;gBAC3B,IAAI,QAAQ,CAAC,GAAG,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC;oBAAC,KAAK,GAAG,KAAK,CAAC;oBAAC,MAAM;gBAAC,CAAC;YACtE,CAAC;YACD,IAAI,KAAK;gBAAE,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;QACnE,CAAC;IACH,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;AACxC,CAAC"}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { pad } from "./select.js";
|
|
2
|
+
const DIM = "\x1b[2m";
|
|
3
|
+
const RESET_DIM = "\x1b[22m";
|
|
4
|
+
const GREEN = "\x1b[32m";
|
|
5
|
+
const YELLOW = "\x1b[33m";
|
|
6
|
+
const RESET_FG = "\x1b[39m";
|
|
7
|
+
/** "just now", "12m ago", "3h ago", "2d ago", then a date. */
|
|
8
|
+
export function ago(ms, now = Date.now()) {
|
|
9
|
+
if (!ms)
|
|
10
|
+
return "";
|
|
11
|
+
const s = Math.max(0, Math.round((now - ms) / 1000));
|
|
12
|
+
if (s < 60)
|
|
13
|
+
return "just now";
|
|
14
|
+
if (s < 3600)
|
|
15
|
+
return `${Math.floor(s / 60)}m ago`;
|
|
16
|
+
if (s < 86400)
|
|
17
|
+
return `${Math.floor(s / 3600)}h ago`;
|
|
18
|
+
if (s < 86400 * 30)
|
|
19
|
+
return `${Math.floor(s / 86400)}d ago`;
|
|
20
|
+
return new Date(ms).toISOString().slice(0, 10);
|
|
21
|
+
}
|
|
22
|
+
/** 950 → "950", 14_200 → "14k", 1_420_000 → "1.4M". */
|
|
23
|
+
export function compact(n) {
|
|
24
|
+
if (n == null)
|
|
25
|
+
return "";
|
|
26
|
+
if (n < 1000)
|
|
27
|
+
return String(n);
|
|
28
|
+
if (n < 1_000_000)
|
|
29
|
+
return `${Math.round(n / 1000)}k`;
|
|
30
|
+
return `${(n / 1_000_000).toFixed(1).replace(/\.0$/, "")}M`;
|
|
31
|
+
}
|
|
32
|
+
/** `claude-opus-5-5` → "Opus 5.5", `claude-haiku-4-5-20251001` → "Haiku 4.5". */
|
|
33
|
+
export function modelLabel(id) {
|
|
34
|
+
if (!id)
|
|
35
|
+
return "";
|
|
36
|
+
const m = /^claude-([a-z]+)-(\d+)(?:-(\d{1,2}))?(?:-\d{8})?/i.exec(id);
|
|
37
|
+
if (!m)
|
|
38
|
+
return id;
|
|
39
|
+
return `${m[1][0].toUpperCase()}${m[1].slice(1)} ${m[2]}${m[3] ? `.${m[3]}` : ""}`;
|
|
40
|
+
}
|
|
41
|
+
/** Where a conversation is, in the dashboard's words. */
|
|
42
|
+
export function conversationState(s) {
|
|
43
|
+
if (s.remoteState === "interactive")
|
|
44
|
+
return `${GREEN}live${RESET_FG}`;
|
|
45
|
+
if (s.remoteState === "server")
|
|
46
|
+
return `${YELLOW}app only${RESET_FG}`;
|
|
47
|
+
return `${DIM}${s.remoteId ? "idle" : "local"}${RESET_DIM}`;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* One picker row: title, where it is, when it was last used, how long it is,
|
|
51
|
+
* how full its context is, and the model — the things that tell six
|
|
52
|
+
* similar-looking conversations apart. It was the title cut to 60 characters
|
|
53
|
+
* and a state, so two runs of the same schedule could not be told apart
|
|
54
|
+
* (asked for, 2026-09-23). Columns that a conversation has no figure for are
|
|
55
|
+
* left blank rather than dropped, so the rest stay aligned.
|
|
56
|
+
*/
|
|
57
|
+
export function conversationRow(s, now = Date.now(), titleWidth = 44) {
|
|
58
|
+
const raw = (s.title || s.firstPrompt || s.id.slice(0, 8)).replace(/\s+/g, " ").trim();
|
|
59
|
+
const title = raw.length > titleWidth ? `${raw.slice(0, titleWidth - 1)}…` : raw;
|
|
60
|
+
const msgs = s.messageCount ? `${s.messageCount} msg${s.messageCount === 1 ? "" : "s"}` : "";
|
|
61
|
+
const ctx = s.contextTokens ? `${compact(s.contextTokens)} ctx` : "";
|
|
62
|
+
return [
|
|
63
|
+
pad(title, titleWidth + 2),
|
|
64
|
+
pad(conversationState(s), 10),
|
|
65
|
+
pad(`${DIM}${ago(s.updatedAt, now)}${RESET_DIM}`, 10),
|
|
66
|
+
pad(`${DIM}${msgs}${RESET_DIM}`, 10),
|
|
67
|
+
pad(`${DIM}${ctx}${RESET_DIM}`, 10),
|
|
68
|
+
`${DIM}${modelLabel(s.model)}${RESET_DIM}`,
|
|
69
|
+
].join("").trimEnd();
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/lib/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { execFileSync } from "node:child_process";
|
|
2
|
+
/**
|
|
3
|
+
* `git@github.com:owner/repo.git`, `https://github.com/owner/repo`,
|
|
4
|
+
* `ssh://git@github.com/owner/repo.git` → `github.com/owner/repo`.
|
|
5
|
+
* Lower-cased, since GitHub treats owner and repo case-insensitively.
|
|
6
|
+
*/
|
|
7
|
+
export function repoKey(url) {
|
|
8
|
+
if (!url)
|
|
9
|
+
return null;
|
|
10
|
+
let u = url.trim();
|
|
11
|
+
const scp = /^[\w.-]+@([\w.-]+):(.+)$/.exec(u); // git@host:owner/repo
|
|
12
|
+
if (scp)
|
|
13
|
+
u = `${scp[1]}/${scp[2]}`;
|
|
14
|
+
else
|
|
15
|
+
u = u.replace(/^[a-z+]+:\/\//i, "").replace(/^[^@/]+@/, ""); // scheme, user@
|
|
16
|
+
u = u.replace(/\/+$/, "").replace(/\.git$/i, "");
|
|
17
|
+
const parts = u.split("/");
|
|
18
|
+
if (parts.length < 3)
|
|
19
|
+
return null;
|
|
20
|
+
return parts.slice(0, 3).join("/").toLowerCase();
|
|
21
|
+
}
|
|
22
|
+
/** Every remote of the git checkout at `dir`, as repo keys. Empty outside one. */
|
|
23
|
+
export function remotesOf(dir) {
|
|
24
|
+
try {
|
|
25
|
+
const out = execFileSync("git", ["-C", dir, "remote", "-v"], { encoding: "utf8", timeout: 1500, stdio: ["ignore", "pipe", "ignore"] });
|
|
26
|
+
const keys = out.split("\n").map((l) => repoKey(l.split(/\s+/)[1])).filter((k) => Boolean(k));
|
|
27
|
+
return [...new Set(keys)];
|
|
28
|
+
}
|
|
29
|
+
catch {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Slugs of the projects whose repository is one of this folder's remotes. */
|
|
34
|
+
export function projectsForRemotes(projects, remotes) {
|
|
35
|
+
if (!remotes.length)
|
|
36
|
+
return [];
|
|
37
|
+
return projects.filter((p) => {
|
|
38
|
+
const key = repoKey(p.githubRepoUrl);
|
|
39
|
+
return key !== null && remotes.includes(key);
|
|
40
|
+
}).map((p) => p.slug);
|
|
41
|
+
}
|
|
42
|
+
//# sourceMappingURL=git-remote.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-remote.js","sourceRoot":"","sources":["../../src/lib/git-remote.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAElD;;;;GAIG;AACH,MAAM,UAAU,OAAO,CAAC,GAA8B;IACpD,IAAI,CAAC,GAAG;QAAE,OAAO,IAAI,CAAC;IACtB,IAAI,CAAC,GAAG,GAAG,CAAC,IAAI,EAAE,CAAC;IACnB,MAAM,GAAG,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB;IACtE,IAAI,GAAG;QAAE,CAAC,GAAG,GAAG,GAAG,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;;QAC9B,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,gBAAgB,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,gBAAgB;IAClF,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;IACjD,MAAM,KAAK,GAAG,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IAC3B,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,IAAI,CAAC;IAClC,OAAO,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,WAAW,EAAE,CAAC;AACnD,CAAC;AAED,kFAAkF;AAClF,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAC;QACvI,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAe,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;QAC3G,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;IAC5B,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED,8EAA8E;AAC9E,MAAM,UAAU,kBAAkB,CAA4D,QAAa,EAAE,OAAiB;IAC5H,IAAI,CAAC,OAAO,CAAC,MAAM;QAAE,OAAO,EAAE,CAAC;IAC/B,OAAO,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QAC3B,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC;QACrC,OAAO,GAAG,KAAK,IAAI,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IAC/C,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;AACxB,CAAC"}
|