@synaplink/orqlaude 0.5.6 → 0.6.1
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 +29 -3
- package/dist/__tests__/v06.test.d.ts +1 -0
- package/dist/__tests__/v06.test.js +74 -0
- package/dist/__tests__/v06.test.js.map +1 -0
- package/dist/cli/about.d.ts +5 -0
- package/dist/cli/about.js +27 -0
- package/dist/cli/about.js.map +1 -0
- package/dist/cli/doctor.d.ts +1 -0
- package/dist/cli/doctor.js +180 -0
- package/dist/cli/doctor.js.map +1 -0
- package/dist/cli/easter_egg.d.ts +1 -0
- package/dist/cli/easter_egg.js +92 -0
- package/dist/cli/easter_egg.js.map +1 -0
- package/dist/cli/open.d.ts +6 -0
- package/dist/cli/open.js +57 -0
- package/dist/cli/open.js.map +1 -0
- package/dist/cli/taglines.d.ts +12 -0
- package/dist/cli/taglines.js +163 -0
- package/dist/cli/taglines.js.map +1 -0
- package/dist/cli/tail.d.ts +7 -0
- package/dist/cli/tail.js +87 -0
- package/dist/cli/tail.js.map +1 -0
- package/dist/cli/watch.d.ts +1 -0
- package/dist/cli/watch.js +169 -0
- package/dist/cli/watch.js.map +1 -0
- package/dist/cli.js +234 -43
- package/dist/cli.js.map +1 -1
- package/dist/lib/error_ui.d.ts +21 -0
- package/dist/lib/error_ui.js +59 -0
- package/dist/lib/error_ui.js.map +1 -0
- package/dist/lib/json_out.d.ts +9 -0
- package/dist/lib/json_out.js +15 -0
- package/dist/lib/json_out.js.map +1 -0
- package/dist/lib/notifications.d.ts +14 -0
- package/dist/lib/notifications.js +37 -0
- package/dist/lib/notifications.js.map +1 -0
- package/dist/lib/picker.d.ts +6 -0
- package/dist/lib/picker.js +50 -0
- package/dist/lib/picker.js.map +1 -0
- package/dist/lib/preferences.d.ts +25 -0
- package/dist/lib/preferences.js +32 -0
- package/dist/lib/preferences.js.map +1 -0
- package/dist/lib/update_check.d.ts +1 -0
- package/dist/lib/update_check.js +78 -0
- package/dist/lib/update_check.js.map +1 -0
- package/dist/server.js +1 -1
- package/dist/telegram/notifier.js +30 -0
- package/dist/telegram/notifier.js.map +1 -1
- package/dist/tools/ping.js +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -226,17 +226,43 @@ False positives are acceptable here — we surface concerns, we don't auto-kill.
|
|
|
226
226
|
|
|
227
227
|
## CLI
|
|
228
228
|
|
|
229
|
-
Two binaries are installed: `orqlaude` and the short alias `orql`. Use whichever feels right.
|
|
229
|
+
Two binaries are installed: `orqlaude` and the short alias `orql`. Use whichever feels right. All commands work the same.
|
|
230
|
+
|
|
231
|
+
### Live (v0.6+)
|
|
232
|
+
|
|
233
|
+
```sh
|
|
234
|
+
orql watch <plan_id> # live-updating dashboard (1Hz, Ctrl-C to exit)
|
|
235
|
+
orql tail [plan_id] # tail -f the audit log; filter by plan if given
|
|
236
|
+
orql open <plan_id> # open every PR from a plan in your browser
|
|
237
|
+
orql doctor # end-to-end health check
|
|
238
|
+
orql about # the easter egg
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Local desktop notifications (macOS)
|
|
242
|
+
|
|
243
|
+
```sh
|
|
244
|
+
orql notify on # enable; the Telegram bot will also fire osascript banners
|
|
245
|
+
orql notify off # disable
|
|
246
|
+
orql notify test # send a test notification
|
|
247
|
+
orql notify status # is it on?
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### Read-only inspection (`--json` on every one)
|
|
251
|
+
|
|
252
|
+
|
|
230
253
|
|
|
231
254
|
```sh
|
|
255
|
+
orql # banner + active-plan summary
|
|
232
256
|
orql list # every plan in this project
|
|
233
|
-
orql status
|
|
234
|
-
orql show
|
|
257
|
+
orql status [plan_id] # if omitted, picker prompts
|
|
258
|
+
orql show [plan_id] # raw plan JSON
|
|
235
259
|
orql history --limit 50 # tail audit log
|
|
236
260
|
orql where # show resolved state dir
|
|
237
261
|
orql help
|
|
238
262
|
```
|
|
239
263
|
|
|
264
|
+
Every read command supports `--json` to emit machine-readable output for scripting.
|
|
265
|
+
|
|
240
266
|
Read-only. For active orchestration, use the MCP from inside Claude Code.
|
|
241
267
|
|
|
242
268
|
### Branding & colors (v0.5+)
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { promises as fs } from "node:fs";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import os from "node:os";
|
|
6
|
+
/** v0.6.0 regression tests covering the polish-pack modules. */
|
|
7
|
+
test("preferences: read/write/update round-trip", async () => {
|
|
8
|
+
const fakeHome = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-prefs-"));
|
|
9
|
+
const realHome = process.env.HOME;
|
|
10
|
+
process.env.HOME = fakeHome;
|
|
11
|
+
try {
|
|
12
|
+
// Re-import so PREFS_PATH picks up the new HOME. The module caches the
|
|
13
|
+
// path at import time, so this technique only works in a fresh worker —
|
|
14
|
+
// we accept that and validate the shape rather than the path.
|
|
15
|
+
const { readPreferences, updatePreferences } = await import(`../lib/preferences.js?cache=${Date.now()}`);
|
|
16
|
+
let prefs = await readPreferences();
|
|
17
|
+
assert.deepEqual(prefs, {});
|
|
18
|
+
await updatePreferences((p) => {
|
|
19
|
+
p.welcomedAt = 1234;
|
|
20
|
+
p.localNotifications = true;
|
|
21
|
+
});
|
|
22
|
+
prefs = await readPreferences();
|
|
23
|
+
assert.equal(prefs.welcomedAt, 1234);
|
|
24
|
+
assert.equal(prefs.localNotifications, true);
|
|
25
|
+
}
|
|
26
|
+
finally {
|
|
27
|
+
if (realHome)
|
|
28
|
+
process.env.HOME = realHome;
|
|
29
|
+
else
|
|
30
|
+
delete process.env.HOME;
|
|
31
|
+
}
|
|
32
|
+
});
|
|
33
|
+
test("error_ui: formatError attaches suggestions for known patterns", async () => {
|
|
34
|
+
const { formatError } = await import("../lib/error_ui.js");
|
|
35
|
+
assert.match(formatError(new Error("Plan not found: abc")).suggestion, /orql list/);
|
|
36
|
+
assert.match(formatError(new Error("EACCES: write failed")).suggestion, /ORQLAUDE_STATE_DIR/);
|
|
37
|
+
assert.match(formatError(new Error("ENOENT: nope")).suggestion, /missing path|orql setup/);
|
|
38
|
+
// Unknown messages get no suggestion (returns undefined).
|
|
39
|
+
assert.equal(formatError(new Error("something obscure")).suggestion, undefined);
|
|
40
|
+
});
|
|
41
|
+
test("json_out: hasJsonFlag detects --json anywhere in args", async () => {
|
|
42
|
+
const { hasJsonFlag } = await import("../lib/json_out.js");
|
|
43
|
+
assert.equal(hasJsonFlag([]), false);
|
|
44
|
+
assert.equal(hasJsonFlag(["foo"]), false);
|
|
45
|
+
assert.equal(hasJsonFlag(["--json"]), true);
|
|
46
|
+
assert.equal(hasJsonFlag(["foo", "--json", "bar"]), true);
|
|
47
|
+
});
|
|
48
|
+
test("notifications: isNotificationsAvailable matches platform", async () => {
|
|
49
|
+
const { isNotificationsAvailable } = await import("../lib/notifications.js");
|
|
50
|
+
assert.equal(isNotificationsAvailable(), process.platform === "darwin");
|
|
51
|
+
});
|
|
52
|
+
test("error_ui: errorLine includes ✗ glyph and optional suggestion", async () => {
|
|
53
|
+
const { errorLine } = await import("../lib/error_ui.js");
|
|
54
|
+
const noSuggestion = errorLine("bad");
|
|
55
|
+
// String includes "bad" and the glyph "✗"
|
|
56
|
+
assert.ok(noSuggestion.includes("✗"));
|
|
57
|
+
assert.ok(noSuggestion.includes("bad"));
|
|
58
|
+
const withSuggestion = errorLine("bad", "try foo");
|
|
59
|
+
assert.ok(withSuggestion.includes("try foo"));
|
|
60
|
+
assert.ok(withSuggestion.includes("→"));
|
|
61
|
+
});
|
|
62
|
+
test("v0.6.1 taglines: exactly 149, all non-empty, no consecutive duplicates", async () => {
|
|
63
|
+
const { TAGLINES } = await import("../cli/taglines.js");
|
|
64
|
+
assert.equal(TAGLINES.length, 149);
|
|
65
|
+
for (let i = 0; i < TAGLINES.length; i++) {
|
|
66
|
+
assert.ok(typeof TAGLINES[i] === "string" && TAGLINES[i].length > 0, `tagline ${i} is empty`);
|
|
67
|
+
}
|
|
68
|
+
// The picker uses a never-repeat-last constraint, so duplicates between
|
|
69
|
+
// non-adjacent indices are fine — but adjacent duplicates would defeat it.
|
|
70
|
+
for (let i = 1; i < TAGLINES.length; i++) {
|
|
71
|
+
assert.notEqual(TAGLINES[i], TAGLINES[i - 1], `adjacent duplicate at ${i - 1}/${i}`);
|
|
72
|
+
}
|
|
73
|
+
});
|
|
74
|
+
//# sourceMappingURL=v06.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v06.test.js","sourceRoot":"","sources":["../../src/__tests__/v06.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { style } from "../lib/style.js";
|
|
2
|
+
/**
|
|
3
|
+
* `orql about` — the easter egg. Print a small stylized "what is this"
|
|
4
|
+
* blurb in the brand palette. Just because.
|
|
5
|
+
*/
|
|
6
|
+
export function showAbout(version) {
|
|
7
|
+
const lines = [
|
|
8
|
+
"",
|
|
9
|
+
` ${style.coral("◆")} ${style.bold(style.coral("orqlaude"))}`,
|
|
10
|
+
"",
|
|
11
|
+
` ${style.sand("one Claude session decomposes a task,")}`,
|
|
12
|
+
` ${style.sand("approves a budget,")}`,
|
|
13
|
+
` ${style.sand("dispatches a fleet of")} ${style.coral("Agnets")} ${style.sand("—")}`,
|
|
14
|
+
` ${style.sand("each in its own worktree, named, tracked,")}`,
|
|
15
|
+
` ${style.sand("brokered, budgeted, watchable.")}`,
|
|
16
|
+
"",
|
|
17
|
+
` ${style.dim(`v${version} · MIT · @synaplink/orqlaude`)}`,
|
|
18
|
+
"",
|
|
19
|
+
` ${style.cream("\"More agents working on a task in parallel is just")}`,
|
|
20
|
+
` ${style.cream("a faster way of reaching")} ${style.coral("the same insight")}.${style.cream("\"")}`,
|
|
21
|
+
` ${style.dim("— Claude (probably)")}`,
|
|
22
|
+
"",
|
|
23
|
+
];
|
|
24
|
+
process.stdout.write(lines.join("\n"));
|
|
25
|
+
return 0;
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=about.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"about.js","sourceRoot":"","sources":["../../src/cli/about.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAExC;;;GAGG;AAEH,MAAM,UAAU,SAAS,CAAC,OAAe;IACvC,MAAM,KAAK,GAAG;QACZ,EAAE;QACF,KAAK,KAAK,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE;QAC9D,EAAE;QACF,KAAK,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,EAAE;QAC1D,KAAK,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,EAAE;QACvC,KAAK,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,QAAQ,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE;QACtF,KAAK,KAAK,CAAC,IAAI,CAAC,2CAA2C,CAAC,EAAE;QAC9D,KAAK,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,EAAE;QACnD,EAAE;QACF,KAAK,KAAK,CAAC,GAAG,CAAC,IAAI,OAAO,8BAA8B,CAAC,EAAE;QAC3D,EAAE;QACF,KAAK,KAAK,CAAC,KAAK,CAAC,qDAAqD,CAAC,EAAE;QACzE,KAAK,KAAK,CAAC,KAAK,CAAC,0BAA0B,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,kBAAkB,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,EAAE;QACtG,KAAK,KAAK,CAAC,GAAG,CAAC,qBAAqB,CAAC,EAAE;QACvC,EAAE;KACH,CAAC;IACF,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;IACvC,OAAO,CAAC,CAAC;AACX,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runDoctor(currentVersion: string): Promise<number>;
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { existsSync } from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { style, banner } from "../lib/style.js";
|
|
5
|
+
import { discoverClaudeBinary } from "../lib/spawn_cli.js";
|
|
6
|
+
import { resolveStateDir } from "../lib/state_dir.js";
|
|
7
|
+
import { probeTelegramStatus } from "../lib/telegram_status.js";
|
|
8
|
+
import { findDesktopConfigPath, readDesktopConfig } from "../lib/desktop_config.js";
|
|
9
|
+
export async function runDoctor(currentVersion) {
|
|
10
|
+
console.log(banner());
|
|
11
|
+
console.log("");
|
|
12
|
+
console.log(style.bold(style.cream("doctor")));
|
|
13
|
+
console.log("");
|
|
14
|
+
const checks = [];
|
|
15
|
+
// 1. Node version
|
|
16
|
+
const nodeVer = process.version.replace(/^v/, "");
|
|
17
|
+
const major = parseInt(nodeVer.split(".")[0], 10);
|
|
18
|
+
checks.push({
|
|
19
|
+
name: "Node.js >= 22",
|
|
20
|
+
status: major >= 22 ? "ok" : "fail",
|
|
21
|
+
detail: `Node ${nodeVer}`,
|
|
22
|
+
fix: major < 22 ? "Install Node 22+ (brew install node@22)" : undefined,
|
|
23
|
+
});
|
|
24
|
+
// 2. claude binary
|
|
25
|
+
try {
|
|
26
|
+
const claudeBin = discoverClaudeBinary();
|
|
27
|
+
let claudeVer = "(version probe failed)";
|
|
28
|
+
try {
|
|
29
|
+
claudeVer = execSync(`"${claudeBin}" --version`, { encoding: "utf8", timeout: 3000 }).trim();
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
/* ignore */
|
|
33
|
+
}
|
|
34
|
+
checks.push({ name: "claude binary", status: "ok", detail: `${claudeBin} (${claudeVer})` });
|
|
35
|
+
}
|
|
36
|
+
catch (err) {
|
|
37
|
+
checks.push({
|
|
38
|
+
name: "claude binary",
|
|
39
|
+
status: "fail",
|
|
40
|
+
detail: err.message,
|
|
41
|
+
fix: "Install Claude Code, or set CLAUDE_BIN env var to its path. spawn_via_cli won't work without this.",
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
// 3. gh CLI
|
|
45
|
+
try {
|
|
46
|
+
const ghVer = execSync("gh --version", { encoding: "utf8", timeout: 3000 }).split("\n")[0];
|
|
47
|
+
let authed = false;
|
|
48
|
+
try {
|
|
49
|
+
execSync("gh auth status", { encoding: "utf8", timeout: 3000, stdio: "pipe" });
|
|
50
|
+
authed = true;
|
|
51
|
+
}
|
|
52
|
+
catch {
|
|
53
|
+
authed = false;
|
|
54
|
+
}
|
|
55
|
+
checks.push({
|
|
56
|
+
name: "gh CLI + auth",
|
|
57
|
+
status: authed ? "ok" : "warn",
|
|
58
|
+
detail: authed ? ghVer : `${ghVer} (not authenticated)`,
|
|
59
|
+
fix: authed ? undefined : "Run `gh auth login` so Agnets can open PRs.",
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
catch {
|
|
63
|
+
checks.push({
|
|
64
|
+
name: "gh CLI + auth",
|
|
65
|
+
status: "warn",
|
|
66
|
+
detail: "gh not installed",
|
|
67
|
+
fix: "brew install gh; gh auth login. Agnets can still run without it, but PRs won't auto-open.",
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
// 4. Resolved state dir
|
|
71
|
+
const stateRes = resolveStateDir();
|
|
72
|
+
const stateOk = stateRes.source === "env" || stateRes.source === "project-root" || stateRes.source === "worktree";
|
|
73
|
+
checks.push({
|
|
74
|
+
name: "state dir",
|
|
75
|
+
status: stateOk ? "ok" : "warn",
|
|
76
|
+
detail: `${stateRes.path} (source: ${stateRes.source})`,
|
|
77
|
+
fix: stateOk
|
|
78
|
+
? undefined
|
|
79
|
+
: `Run \`orql setup\` from your project to pin state via ORQLAUDE_STATE_DIR in the Desktop MCP config.`,
|
|
80
|
+
});
|
|
81
|
+
// 5. Claude Desktop MCP config
|
|
82
|
+
const cfgPath = findDesktopConfigPath();
|
|
83
|
+
if (existsSync(cfgPath)) {
|
|
84
|
+
try {
|
|
85
|
+
const cfg = await readDesktopConfig(cfgPath);
|
|
86
|
+
const entry = cfg?.mcpServers?.orqlaude;
|
|
87
|
+
if (!entry) {
|
|
88
|
+
checks.push({
|
|
89
|
+
name: "Desktop MCP config",
|
|
90
|
+
status: "fail",
|
|
91
|
+
detail: `${cfgPath} exists, but no orqlaude entry`,
|
|
92
|
+
fix: "Run `orql setup` in your project to add the entry.",
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
else if (!entry.env?.ORQLAUDE_STATE_DIR) {
|
|
96
|
+
checks.push({
|
|
97
|
+
name: "Desktop MCP config",
|
|
98
|
+
status: "warn",
|
|
99
|
+
detail: "orqlaude entry present but has no ORQLAUDE_STATE_DIR env",
|
|
100
|
+
fix: "Run `orql setup` to pin a state dir; without it, MCP cwd=/ can split state.",
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
else {
|
|
104
|
+
checks.push({
|
|
105
|
+
name: "Desktop MCP config",
|
|
106
|
+
status: "ok",
|
|
107
|
+
detail: `ORQLAUDE_STATE_DIR → ${entry.env.ORQLAUDE_STATE_DIR}`,
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
catch (err) {
|
|
112
|
+
checks.push({
|
|
113
|
+
name: "Desktop MCP config",
|
|
114
|
+
status: "fail",
|
|
115
|
+
detail: err.message,
|
|
116
|
+
});
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
else {
|
|
120
|
+
checks.push({
|
|
121
|
+
name: "Desktop MCP config",
|
|
122
|
+
status: "warn",
|
|
123
|
+
detail: `${cfgPath} does not exist`,
|
|
124
|
+
fix: "Run `orql setup` to create it.",
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
// 6. Telegram
|
|
128
|
+
const tg = await probeTelegramStatus(stateRes.path);
|
|
129
|
+
let tgStatus = "ok";
|
|
130
|
+
if (tg.status === "unconfigured")
|
|
131
|
+
tgStatus = "warn";
|
|
132
|
+
else if (tg.status === "stale" || tg.status === "configured" || tg.status === "started")
|
|
133
|
+
tgStatus = "warn";
|
|
134
|
+
checks.push({
|
|
135
|
+
name: "Telegram bot",
|
|
136
|
+
status: tgStatus,
|
|
137
|
+
detail: `${tg.status} (token: ${tg.hasToken ? "set" : "missing"}, whitelist: ${tg.whitelistSize})`,
|
|
138
|
+
fix: tg.status === "unconfigured"
|
|
139
|
+
? "`orql tg setup` to wire a bot — optional but recommended."
|
|
140
|
+
: tg.status === "stale" || tg.status === "configured" || tg.status === "started"
|
|
141
|
+
? "Run `orql tg start` from your project to bring the bot online."
|
|
142
|
+
: undefined,
|
|
143
|
+
});
|
|
144
|
+
// 7. orqlaude self-test (MCP server startup)
|
|
145
|
+
try {
|
|
146
|
+
const serverPath = path.resolve(path.dirname(new URL(import.meta.url).pathname), "..", "server.js");
|
|
147
|
+
if (existsSync(serverPath)) {
|
|
148
|
+
checks.push({ name: "orqlaude MCP server", status: "ok", detail: `${serverPath}` });
|
|
149
|
+
}
|
|
150
|
+
else {
|
|
151
|
+
checks.push({
|
|
152
|
+
name: "orqlaude MCP server",
|
|
153
|
+
status: "fail",
|
|
154
|
+
detail: `Missing ${serverPath}`,
|
|
155
|
+
fix: "Reinstall: npm i -g @synaplink/orqlaude@latest",
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (err) {
|
|
160
|
+
checks.push({ name: "orqlaude MCP server", status: "warn", detail: err.message });
|
|
161
|
+
}
|
|
162
|
+
// Render
|
|
163
|
+
const counts = { ok: 0, warn: 0, fail: 0 };
|
|
164
|
+
for (const c of checks) {
|
|
165
|
+
counts[c.status]++;
|
|
166
|
+
const glyph = c.status === "ok"
|
|
167
|
+
? style.coral("✓")
|
|
168
|
+
: c.status === "warn"
|
|
169
|
+
? style.crimson("⚠")
|
|
170
|
+
: style.crimson("✗");
|
|
171
|
+
console.log(` ${glyph} ${style.bold(c.name.padEnd(26))} ${c.detail}`);
|
|
172
|
+
if (c.fix)
|
|
173
|
+
console.log(` ${style.coral("→")} ${style.sand(c.fix)}`);
|
|
174
|
+
}
|
|
175
|
+
console.log("");
|
|
176
|
+
const summary = `${style.coral(`${counts.ok} ok`)} · ${style.crimson(`${counts.warn} warn`)} · ${style.crimson(`${counts.fail} fail`)}`;
|
|
177
|
+
console.log(` ${summary} ${style.dim(`(orqlaude ${currentVersion})`)}`);
|
|
178
|
+
return counts.fail > 0 ? 1 : 0;
|
|
179
|
+
}
|
|
180
|
+
//# sourceMappingURL=doctor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"doctor.js","sourceRoot":"","sources":["../../src/cli/doctor.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function runEasterEgg(): Promise<number>;
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { TAGLINES } from "./taglines.js";
|
|
2
|
+
import { style } from "../lib/style.js";
|
|
3
|
+
/**
|
|
4
|
+
* Bare `orql` easter egg — a never-repeating typewriter cycling through
|
|
5
|
+
* 149 tagline variants under the orqlaude diamond logo. Runs until Ctrl-C.
|
|
6
|
+
*
|
|
7
|
+
* The natural terminal cursor sits at the end of each tagline while it's
|
|
8
|
+
* displayed and blinks on its own — no explicit blink animation needed.
|
|
9
|
+
*/
|
|
10
|
+
const ESC = "\x1b[";
|
|
11
|
+
const SAVE = `${ESC}s`;
|
|
12
|
+
const RESTORE = `${ESC}u`;
|
|
13
|
+
const CLEAR_TO_EOL = `${ESC}K`;
|
|
14
|
+
const SAND_FG = `${ESC}38;2;185;182;171m`;
|
|
15
|
+
const RESET = `${ESC}0m`;
|
|
16
|
+
const TYPE_MIN_MS = 28;
|
|
17
|
+
const TYPE_MAX_MS = 90;
|
|
18
|
+
const HOLD_MIN_MS = 1100;
|
|
19
|
+
const HOLD_MAX_MS = 2200;
|
|
20
|
+
const ERASE_MIN_MS = 12;
|
|
21
|
+
const ERASE_MAX_MS = 30;
|
|
22
|
+
const BETWEEN_MIN_MS = 280;
|
|
23
|
+
const BETWEEN_MAX_MS = 600;
|
|
24
|
+
export async function runEasterEgg() {
|
|
25
|
+
return new Promise((resolve) => {
|
|
26
|
+
let stopped = false;
|
|
27
|
+
const onSig = () => {
|
|
28
|
+
stopped = true;
|
|
29
|
+
// Move cursor below the tagline line and reset, then exit.
|
|
30
|
+
process.stdout.write(RESET + "\n\n");
|
|
31
|
+
resolve(0);
|
|
32
|
+
};
|
|
33
|
+
process.on("SIGINT", onSig);
|
|
34
|
+
// Static logo + wordmark. Last line ends without a newline so the
|
|
35
|
+
// cursor sits where taglines should animate.
|
|
36
|
+
const logo = [
|
|
37
|
+
` ${style.coral("◆◆◆")}`,
|
|
38
|
+
` ${style.coral("◆ ◆")} ${style.bold(style.coral("orqlaude"))}`,
|
|
39
|
+
` ${style.coral("◆◆◆")} `, // trailing spaces are the "padding" before the tagline
|
|
40
|
+
];
|
|
41
|
+
process.stdout.write("\n" + logo.join("\n"));
|
|
42
|
+
process.stdout.write(SAVE);
|
|
43
|
+
// Animate in a loop. We do this without `await` in the main scope so
|
|
44
|
+
// SIGINT can interrupt cleanly via the `stopped` flag check between
|
|
45
|
+
// sleeps.
|
|
46
|
+
(async () => {
|
|
47
|
+
let lastIdx = -1;
|
|
48
|
+
while (!stopped) {
|
|
49
|
+
let idx = Math.floor(Math.random() * TAGLINES.length);
|
|
50
|
+
// Never repeat the previous tagline.
|
|
51
|
+
while (idx === lastIdx) {
|
|
52
|
+
idx = Math.floor(Math.random() * TAGLINES.length);
|
|
53
|
+
}
|
|
54
|
+
lastIdx = idx;
|
|
55
|
+
const tagline = TAGLINES[idx];
|
|
56
|
+
// Reset cursor + clear any leftover from the previous tagline.
|
|
57
|
+
process.stdout.write(RESTORE + CLEAR_TO_EOL + SAND_FG);
|
|
58
|
+
// Type out character by character. Each char is plain text — the
|
|
59
|
+
// SAND_FG above persists until we reset, so a single \b backspace
|
|
60
|
+
// erases one visible character.
|
|
61
|
+
for (let i = 0; i < tagline.length; i++) {
|
|
62
|
+
if (stopped)
|
|
63
|
+
return;
|
|
64
|
+
process.stdout.write(tagline[i]);
|
|
65
|
+
await sleep(rand(TYPE_MIN_MS, TYPE_MAX_MS));
|
|
66
|
+
}
|
|
67
|
+
// Hold while the natural terminal cursor blinks at the end.
|
|
68
|
+
await sleep(rand(HOLD_MIN_MS, HOLD_MAX_MS));
|
|
69
|
+
if (stopped)
|
|
70
|
+
return;
|
|
71
|
+
// Erase backwards for a satisfying "delete" feel.
|
|
72
|
+
for (let i = tagline.length; i > 0; i--) {
|
|
73
|
+
if (stopped)
|
|
74
|
+
return;
|
|
75
|
+
process.stdout.write("\b \b");
|
|
76
|
+
await sleep(rand(ERASE_MIN_MS, ERASE_MAX_MS));
|
|
77
|
+
}
|
|
78
|
+
process.stdout.write(RESET);
|
|
79
|
+
await sleep(rand(BETWEEN_MIN_MS, BETWEEN_MAX_MS));
|
|
80
|
+
}
|
|
81
|
+
})().catch(() => {
|
|
82
|
+
/* swallow — never crash on the easter egg */
|
|
83
|
+
});
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
function sleep(ms) {
|
|
87
|
+
return new Promise((res) => setTimeout(res, ms));
|
|
88
|
+
}
|
|
89
|
+
function rand(min, max) {
|
|
90
|
+
return min + Math.random() * (max - min);
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=easter_egg.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"easter_egg.js","sourceRoot":"","sources":["../../src/cli/easter_egg.ts"],"names":[],"mappings":"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"}
|
package/dist/cli/open.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { execSync } from "node:child_process";
|
|
2
|
+
import { StateStore } from "../lib/state.js";
|
|
3
|
+
import { style } from "../lib/style.js";
|
|
4
|
+
/**
|
|
5
|
+
* `orql open <plan_id>` — open every PR URL the fleet produced in the
|
|
6
|
+
* default browser, plus print worktree paths for tasks that don't yet
|
|
7
|
+
* have PRs.
|
|
8
|
+
*/
|
|
9
|
+
export async function openPlan(stateDir, planId) {
|
|
10
|
+
const store = new StateStore(stateDir);
|
|
11
|
+
let plan;
|
|
12
|
+
try {
|
|
13
|
+
plan = await store.read((s) => {
|
|
14
|
+
const p = s.plans[planId] ?? Object.values(s.plans).find((x) => x.id.startsWith(planId));
|
|
15
|
+
if (!p)
|
|
16
|
+
throw new Error(`Plan not found: ${planId}`);
|
|
17
|
+
return p;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
catch (err) {
|
|
21
|
+
process.stderr.write(style.crimson(`✗ ${err.message}\n`));
|
|
22
|
+
return 1;
|
|
23
|
+
}
|
|
24
|
+
const withPr = plan.tasks.filter((t) => t.prUrl);
|
|
25
|
+
const withoutPr = plan.tasks.filter((t) => !t.prUrl);
|
|
26
|
+
if (withPr.length === 0 && withoutPr.length === 0) {
|
|
27
|
+
process.stdout.write(style.sand("Plan has no tasks.\n"));
|
|
28
|
+
return 0;
|
|
29
|
+
}
|
|
30
|
+
if (withPr.length > 0) {
|
|
31
|
+
process.stdout.write(`${style.bold(style.cream("Opening"))} ${withPr.length} PR(s) in your default browser:\n`);
|
|
32
|
+
for (const t of withPr) {
|
|
33
|
+
process.stdout.write(` ${style.coral("→")} ${t.prUrl} ${style.dim(`(${t.agnetName ? "Agnet " + t.agnetName : t.title})`)}\n`);
|
|
34
|
+
openUrl(t.prUrl);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
if (withoutPr.length > 0) {
|
|
38
|
+
process.stdout.write("\n" + style.sand("Tasks without PRs yet:") + "\n");
|
|
39
|
+
for (const t of withoutPr) {
|
|
40
|
+
const agnet = t.agnetName ? "Agnet " + t.agnetName : "Agnet";
|
|
41
|
+
process.stdout.write(` ${style.sand("·")} ${agnet} ${style.dim(t.title)}\n`);
|
|
42
|
+
if (t.worktreePath)
|
|
43
|
+
process.stdout.write(` ${style.sand("worktree:")} ${t.worktreePath}\n`);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return 0;
|
|
47
|
+
}
|
|
48
|
+
function openUrl(url) {
|
|
49
|
+
try {
|
|
50
|
+
const cmd = process.platform === "darwin" ? "open" : process.platform === "win32" ? "start" : "xdg-open";
|
|
51
|
+
execSync(`${cmd} "${url}"`, { stdio: "ignore" });
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
/* swallow */
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
//# sourceMappingURL=open.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"open.js","sourceRoot":"","sources":["../../src/cli/open.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 149 creative variants of the orqlaude tagline.
|
|
3
|
+
*
|
|
4
|
+
* Used by the bare-`orql` easter egg (src/cli/easter_egg.ts): a random
|
|
5
|
+
* tagline is typed out, paused, erased, and the cycle repeats. The
|
|
6
|
+
* picker guarantees consecutive picks are never the same string.
|
|
7
|
+
*
|
|
8
|
+
* Index 0 is the "canonical" descriptive tagline used elsewhere as a
|
|
9
|
+
* watermark fallback. The rest are intentionally varied — technical,
|
|
10
|
+
* playful, poetic, self-aware — to keep the easter egg interesting.
|
|
11
|
+
*/
|
|
12
|
+
export declare const TAGLINES: readonly string[];
|