@synaplink/orqlaude 0.8.0 → 0.9.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (40) hide show
  1. package/dist/__tests__/v09.test.d.ts +1 -0
  2. package/dist/__tests__/v09.test.js +189 -0
  3. package/dist/__tests__/v09.test.js.map +1 -0
  4. package/dist/__tests__/v092.test.d.ts +1 -0
  5. package/dist/__tests__/v092.test.js +125 -0
  6. package/dist/__tests__/v092.test.js.map +1 -0
  7. package/dist/cli/easter_egg.js +127 -39
  8. package/dist/cli/easter_egg.js.map +1 -1
  9. package/dist/cli.js +1 -1
  10. package/dist/cli.js.map +1 -1
  11. package/dist/lib/jsonl_tail.d.ts +68 -5
  12. package/dist/lib/jsonl_tail.js +70 -11
  13. package/dist/lib/jsonl_tail.js.map +1 -1
  14. package/dist/lib/spawn_cli.d.ts +26 -0
  15. package/dist/lib/spawn_cli.js +45 -1
  16. package/dist/lib/spawn_cli.js.map +1 -1
  17. package/dist/lib/state.d.ts +33 -0
  18. package/dist/lib/state.js +14 -4
  19. package/dist/lib/state.js.map +1 -1
  20. package/dist/lib/telegram_status.js +7 -1
  21. package/dist/lib/telegram_status.js.map +1 -1
  22. package/dist/lib/version.d.ts +18 -0
  23. package/dist/lib/version.js +19 -0
  24. package/dist/lib/version.js.map +1 -0
  25. package/dist/server.js +2 -1
  26. package/dist/server.js.map +1 -1
  27. package/dist/telegram/notifier.js +33 -1
  28. package/dist/telegram/notifier.js.map +1 -1
  29. package/dist/tools/dispatch.d.ts +29 -1
  30. package/dist/tools/dispatch.js +445 -35
  31. package/dist/tools/dispatch.js.map +1 -1
  32. package/dist/tools/lifecycle.js +44 -2
  33. package/dist/tools/lifecycle.js.map +1 -1
  34. package/dist/tools/ping.js +2 -1
  35. package/dist/tools/ping.js.map +1 -1
  36. package/dist/tools/planning.js +4 -1
  37. package/dist/tools/planning.js.map +1 -1
  38. package/dist/tools/userio.js +16 -6
  39. package/dist/tools/userio.js.map +1 -1
  40. package/package.json +1 -1
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,189 @@
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
+ import { snapshotSession, clearTailCache } from "../lib/jsonl_tail.js";
7
+ import { readChildExitRecord } from "../lib/spawn_cli.js";
8
+ /**
9
+ * v0.9.0 — observability overhaul.
10
+ *
11
+ * Covers:
12
+ * • A. snapshotSession falls back to stdoutPath when JSONL is missing
13
+ * • E. readChildExitRecord parses the exit JSON file
14
+ * • D. orphan notifications round-trip via state.ts schema
15
+ * • F. wait_for_status_change fingerprint changes on key transitions
16
+ * (smoke; the long-poll loop itself is integration-tested by
17
+ * running a fleet end-to-end).
18
+ * • cleanup_worktrees lock-release predicate (state mutation only).
19
+ *
20
+ * Smoke style: build temp files / state, call the unit-under-test
21
+ * directly, assert observable behavior. No subprocess spawning - those
22
+ * paths are covered by manual integration runs.
23
+ */
24
+ async function mkTempDir(prefix) {
25
+ const raw = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
26
+ return await fs.realpath(raw);
27
+ }
28
+ // ---- A: stdoutPath fallback in snapshotSession -----------------------------
29
+ test("v0.9.0 A: snapshotSession reads tokens from stdout log when JSONL is missing", async () => {
30
+ clearTailCache();
31
+ const dir = await mkTempDir("orq-v09-A-");
32
+ const stdoutPath = path.join(dir, ".orqlaude.stdout.log");
33
+ // Write two stream-json events: one assistant with usage, one result.
34
+ const events = [
35
+ {
36
+ type: "assistant",
37
+ message: {
38
+ content: [{ type: "text", text: "Working on it" }],
39
+ usage: { input_tokens: 100, output_tokens: 50, cache_read_input_tokens: 0, cache_creation_input_tokens: 0 },
40
+ },
41
+ timestamp: new Date().toISOString(),
42
+ },
43
+ {
44
+ type: "result",
45
+ subtype: "completed",
46
+ total_cost_usd: 0.0012,
47
+ timestamp: new Date().toISOString(),
48
+ },
49
+ ];
50
+ await fs.writeFile(stdoutPath, events.map((e) => JSON.stringify(e)).join("\n") + "\n");
51
+ // session id is fake - the canonical JSONL path won't exist.
52
+ const fakeSession = "00000000-0000-4000-8000-000000000000";
53
+ const snap = await snapshotSession("/tmp/non-existent-cwd", fakeSession, stdoutPath);
54
+ assert.equal(snap.exists, true);
55
+ assert.equal(snap.source, "stdout_log");
56
+ assert.equal(snap.resolvedPath, stdoutPath);
57
+ assert.equal(snap.inputTokens, 100);
58
+ assert.equal(snap.outputTokens, 50);
59
+ assert.equal(snap.terminated, true);
60
+ assert.equal(snap.terminationReason, "completed");
61
+ });
62
+ test("v0.9.0 A: snapshotSession returns 'none' source when neither file exists", async () => {
63
+ clearTailCache();
64
+ const fakeSession = "11111111-0000-4000-8000-000000000000";
65
+ const snap = await snapshotSession("/tmp/non-existent-cwd-2", fakeSession);
66
+ assert.equal(snap.exists, false);
67
+ assert.equal(snap.source, "none");
68
+ assert.equal(snap.resolvedPath, null);
69
+ });
70
+ test("v0.9.0 A: snapshotSession prefers JSONL when both exist", async () => {
71
+ clearTailCache();
72
+ const dir = await mkTempDir("orq-v09-A-pref-");
73
+ const stdoutPath = path.join(dir, ".orqlaude.stdout.log");
74
+ // Stdout says 50 input tokens; JSONL we'll forge to say 200.
75
+ await fs.writeFile(stdoutPath, JSON.stringify({
76
+ type: "assistant",
77
+ message: { content: [], usage: { input_tokens: 50, output_tokens: 0 } },
78
+ }) + "\n");
79
+ // Build the JSONL at the canonical path so the resolver picks it.
80
+ const sessionId = "22222222-0000-4000-8000-000000000000";
81
+ // We need to mirror jsonlPathFor's encoding without importing it again.
82
+ const fakeCwd = await mkTempDir("orq-v09-A-cwd-");
83
+ const home = process.env.HOME ?? process.env.USERPROFILE ?? "";
84
+ const jsonlDir = path.join(home, ".claude", "projects", fakeCwd.replace(/\//g, "-"));
85
+ await fs.mkdir(jsonlDir, { recursive: true });
86
+ const jsonlPath = path.join(jsonlDir, `${sessionId}.jsonl`);
87
+ await fs.writeFile(jsonlPath, JSON.stringify({
88
+ type: "assistant",
89
+ message: { content: [], usage: { input_tokens: 200, output_tokens: 0 } },
90
+ }) + "\n");
91
+ try {
92
+ const snap = await snapshotSession(fakeCwd, sessionId, stdoutPath);
93
+ assert.equal(snap.source, "jsonl");
94
+ assert.equal(snap.resolvedPath, jsonlPath);
95
+ assert.equal(snap.inputTokens, 200, "JSONL wins over stdout log when both exist");
96
+ }
97
+ finally {
98
+ await fs.rm(jsonlPath, { force: true });
99
+ await fs.rm(jsonlDir, { recursive: true, force: true });
100
+ }
101
+ });
102
+ // ---- E: readChildExitRecord ------------------------------------------------
103
+ test("v0.9.0 E: readChildExitRecord returns null when file missing", async () => {
104
+ const dir = await mkTempDir("orq-v09-E-");
105
+ const exitPath = path.join(dir, ".orqlaude.exit.json");
106
+ const rec = await readChildExitRecord(exitPath);
107
+ assert.equal(rec, null);
108
+ });
109
+ test("v0.9.0 E: readChildExitRecord parses a written record", async () => {
110
+ const dir = await mkTempDir("orq-v09-E2-");
111
+ const exitPath = path.join(dir, ".orqlaude.exit.json");
112
+ const written = {
113
+ exit_code: 0,
114
+ signal: null,
115
+ terminated_at: Date.now(),
116
+ success: true,
117
+ };
118
+ await fs.writeFile(exitPath, JSON.stringify(written));
119
+ const rec = await readChildExitRecord(exitPath);
120
+ assert.ok(rec, "should parse");
121
+ assert.equal(rec.exit_code, 0);
122
+ assert.equal(rec.signal, null);
123
+ assert.equal(rec.success, true);
124
+ assert.equal(typeof rec.terminated_at, "number");
125
+ });
126
+ test("v0.9.0 E: readChildExitRecord rejects malformed json gracefully", async () => {
127
+ const dir = await mkTempDir("orq-v09-E3-");
128
+ const exitPath = path.join(dir, ".orqlaude.exit.json");
129
+ await fs.writeFile(exitPath, "{not json");
130
+ const rec = await readChildExitRecord(exitPath);
131
+ assert.equal(rec, null);
132
+ });
133
+ // ---- D: orphan-notification migration --------------------------------------
134
+ test("v0.9.0 D: state.ts migrate fills orphanNotifications on a fresh v3 state", async () => {
135
+ const stateDir = await mkTempDir("orq-v09-D-");
136
+ // Write a hand-rolled state.json that omits the orphan arrays (mimicking
137
+ // a v3 file written by v0.8.0).
138
+ await fs.writeFile(path.join(stateDir, "orqlaude-state.json"), JSON.stringify({ schemaVersion: 3, plans: {} }));
139
+ const { StateStore } = await import("../lib/state.js");
140
+ const store = new StateStore(stateDir);
141
+ const orphans = await store.read((s) => ({
142
+ n: s.orphanNotifications,
143
+ r: s.orphanResponseRequests,
144
+ }));
145
+ // v0.9.1: pin the migration contract. The migrate fn explicitly
146
+ // initializes these arrays (out.orphanNotifications = out.orphanNotifications
147
+ // ?? []) so a load of a v3-without-orphans file must result in arrays,
148
+ // not undefineds. The notifier's `?? []` is defense-in-depth, not the
149
+ // primary contract.
150
+ assert.ok(Array.isArray(orphans.n), "orphanNotifications should be initialized as []");
151
+ assert.ok(Array.isArray(orphans.r), "orphanResponseRequests should be initialized as []");
152
+ assert.equal(orphans.n.length, 0);
153
+ assert.equal(orphans.r.length, 0);
154
+ });
155
+ test("v0.9.0 D: notify_user without plan_id pushes to orphan queue", async () => {
156
+ const stateDir = await mkTempDir("orq-v09-D2-");
157
+ const { StateStore } = await import("../lib/state.js");
158
+ const store = new StateStore(stateDir);
159
+ // Simulate what notify_user does when plan_id is absent.
160
+ await store.update((state) => {
161
+ state.orphanNotifications = state.orphanNotifications ?? [];
162
+ state.orphanNotifications.push({
163
+ id: "abc123",
164
+ text: "test ping",
165
+ urgency: "normal",
166
+ createdAt: Date.now(),
167
+ delivered: false,
168
+ });
169
+ });
170
+ const out = await store.read((s) => s.orphanNotifications);
171
+ assert.equal(out.length, 1);
172
+ assert.equal(out[0].text, "test ping");
173
+ });
174
+ // ---- F: fingerprint computation --------------------------------------------
175
+ //
176
+ // We can't call wait_for_status_change directly (it's tool-registered) but
177
+ // the fingerprint shape is part of the contract. This test pins the
178
+ // observable contract: token deltas of < 1 KB don't churn the fingerprint,
179
+ // but a status transition does.
180
+ test("v0.9.0 F: fingerprint shape is stable across sub-KB token deltas", () => {
181
+ const fp = (status, tokens) => `${status}|t1:${status}::${Math.floor(tokens / 1024)}::0:?`;
182
+ // 500-token to 800-token delta: same KB bucket.
183
+ assert.equal(fp("running", 500), fp("running", 800));
184
+ // 500 to 1500: different KB bucket.
185
+ assert.notEqual(fp("running", 500), fp("running", 1500));
186
+ // Status transition: always different.
187
+ assert.notEqual(fp("running", 500), fp("done", 500));
188
+ });
189
+ //# sourceMappingURL=v09.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v09.test.js","sourceRoot":"","sources":["../../src/__tests__/v09.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,125 @@
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
+ import { snapshotSession, clearTailCache } from "../lib/jsonl_tail.js";
7
+ /**
8
+ * v0.9.2 — billed-vs-cached token accounting.
9
+ *
10
+ * Covers:
11
+ * • SessionSnapshot exposes separate billedTokens / cachedTokens / total
12
+ * • billedTokens = input + output (Plan-cost-relevant)
13
+ * • cachedTokens = cache_read + cache_creation (free on the Plan)
14
+ * • totalEffectiveTokens = sum (back-compat)
15
+ * • Plan.budgetMode defaults to "billed" via newPlan
16
+ *
17
+ * The budget-enforcement flow (status() / wait_for_status_change calling
18
+ * enforceBudget with the right bucket) is covered by integration-style
19
+ * runs against a live fleet; the unit tests here pin the snapshot maths.
20
+ */
21
+ async function mkTempDir(prefix) {
22
+ const raw = await fs.mkdtemp(path.join(os.tmpdir(), prefix));
23
+ return await fs.realpath(raw);
24
+ }
25
+ test("v0.9.2: snapshotSession exposes billed and cached buckets separately", async () => {
26
+ clearTailCache();
27
+ const dir = await mkTempDir("orq-v092-buckets-");
28
+ const stdoutPath = path.join(dir, ".orqlaude.stdout.log");
29
+ // One assistant event with usage covering all four bucket fields.
30
+ await fs.writeFile(stdoutPath, JSON.stringify({
31
+ type: "assistant",
32
+ message: {
33
+ content: [{ type: "text", text: "x" }],
34
+ usage: {
35
+ input_tokens: 100,
36
+ output_tokens: 50,
37
+ cache_read_input_tokens: 8000,
38
+ cache_creation_input_tokens: 200,
39
+ },
40
+ },
41
+ timestamp: new Date().toISOString(),
42
+ }) + "\n");
43
+ const fakeSession = "00000000-0000-4000-8000-000000000aaa";
44
+ const snap = await snapshotSession("/tmp/non-existent-cwd-v092", fakeSession, stdoutPath);
45
+ assert.equal(snap.billedTokens, 150, "input + output only");
46
+ assert.equal(snap.cachedTokens, 8200, "cache_read + cache_creation");
47
+ assert.equal(snap.totalEffectiveTokens, 8350, "sum of all four buckets");
48
+ assert.equal(snap.totalEffectiveTokens, snap.billedTokens + snap.cachedTokens, "total = billed + cached");
49
+ });
50
+ test("v0.9.2: billed bucket excludes cache reads (the user is on the Claude Plan)", async () => {
51
+ clearTailCache();
52
+ const dir = await mkTempDir("orq-v092-billed-");
53
+ const stdoutPath = path.join(dir, ".orqlaude.stdout.log");
54
+ // A typical agent turn: small fresh input, small output, huge cache read.
55
+ // This mirrors the pattern we saw in the v0.9.1 live test where Agnets
56
+ // were reading 100k+ from cache per turn.
57
+ await fs.writeFile(stdoutPath, [
58
+ JSON.stringify({
59
+ type: "assistant",
60
+ message: {
61
+ content: [],
62
+ usage: { input_tokens: 200, output_tokens: 100, cache_read_input_tokens: 100000 },
63
+ },
64
+ }),
65
+ JSON.stringify({
66
+ type: "assistant",
67
+ message: {
68
+ content: [],
69
+ usage: { input_tokens: 150, output_tokens: 80, cache_read_input_tokens: 100000 },
70
+ },
71
+ }),
72
+ ].join("\n") + "\n");
73
+ const fakeSession = "00000000-0000-4000-8000-000000000bbb";
74
+ const snap = await snapshotSession("/tmp/non-existent-cwd-v092-b", fakeSession, stdoutPath);
75
+ assert.equal(snap.billedTokens, 530, "200+100 + 150+80 = 530 - what the Plan cares about");
76
+ assert.equal(snap.cachedTokens, 200000, "two turns of 100k cache reads");
77
+ assert.equal(snap.totalEffectiveTokens, 200530);
78
+ // The KEY ratio: cache reads are 376x larger than billed. A budget cap
79
+ // applied to `totalEffectiveTokens` would fire spuriously; applied to
80
+ // `billedTokens` it reflects real Plan usage.
81
+ const inflationRatio = snap.totalEffectiveTokens / snap.billedTokens;
82
+ assert.ok(inflationRatio > 100, `cache inflates the total by ${Math.round(inflationRatio)}x`);
83
+ });
84
+ test("v0.9.2: empty snapshot has zeros for all three rollups", async () => {
85
+ clearTailCache();
86
+ const snap = await snapshotSession("/tmp/non-existent-cwd-v092-empty", "11111111-0000-4000-8000-000000000000");
87
+ assert.equal(snap.billedTokens, 0);
88
+ assert.equal(snap.cachedTokens, 0);
89
+ assert.equal(snap.totalEffectiveTokens, 0);
90
+ });
91
+ test("v0.9.2: Plan.budgetMode defaults to undefined on newPlan; consumers treat undefined as 'billed'", async () => {
92
+ const { newPlan } = await import("../lib/state.js");
93
+ const p = newPlan("test", 100000, [
94
+ { title: "a", prompt: "p", tldr: "t" },
95
+ { title: "b", prompt: "p", tldr: "t" },
96
+ ]);
97
+ // newPlan itself doesn't set budgetMode - create_plan does. Both
98
+ // semantics are valid; consumers must fallback to "billed" on undefined.
99
+ // This pins the contract.
100
+ assert.ok(p.budgetMode === undefined || p.budgetMode === "billed");
101
+ });
102
+ test("v0.9.2: total = billed + cached invariant holds across mixed events", async () => {
103
+ clearTailCache();
104
+ const dir = await mkTempDir("orq-v092-invariant-");
105
+ const stdoutPath = path.join(dir, ".orqlaude.stdout.log");
106
+ // Mix of event shapes: assistant with full usage, assistant with partial,
107
+ // user (no usage), result row.
108
+ await fs.writeFile(stdoutPath, [
109
+ JSON.stringify({
110
+ type: "assistant",
111
+ message: { content: [], usage: { input_tokens: 10, output_tokens: 5, cache_read_input_tokens: 100, cache_creation_input_tokens: 20 } },
112
+ }),
113
+ JSON.stringify({ type: "user", message: { content: "noop" } }),
114
+ JSON.stringify({
115
+ type: "assistant",
116
+ message: { content: [], usage: { input_tokens: 7, output_tokens: 3 } },
117
+ }),
118
+ JSON.stringify({ type: "result", subtype: "completed" }),
119
+ ].join("\n") + "\n");
120
+ const snap = await snapshotSession("/tmp/non-existent-cwd-v092-inv", "22222222-0000-4000-8000-000000000000", stdoutPath);
121
+ assert.equal(snap.billedTokens, 25); // 10+5 + 7+3
122
+ assert.equal(snap.cachedTokens, 120); // 100 + 20
123
+ assert.equal(snap.totalEffectiveTokens, snap.billedTokens + snap.cachedTokens);
124
+ });
125
+ //# sourceMappingURL=v092.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"v092.test.js","sourceRoot":"","sources":["../../src/__tests__/v092.test.ts"],"names":[],"mappings":"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"}
@@ -1,18 +1,40 @@
1
1
  import { TAGLINES } from "./taglines.js";
2
2
  import { style } from "../lib/style.js";
3
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.
4
+ * Bare `orql` easter egg — typewriter cycling through 149 tagline variants
5
+ * beneath the orqlaude diamond. Runs until Ctrl-C / Ctrl-D.
6
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.
7
+ * v0.9.3 rewrite. Two fixes over the v0.6.1 implementation:
8
+ *
9
+ * 1. **Stdin echo no longer bleeds into the line.** Previously the
10
+ * terminal was in cooked mode with echo on, so anything the user
11
+ * typed at the keyboard while the animation ran was printed inline
12
+ * with the tagline — and the `\b \b` erase pass walked back over
13
+ * their characters too, leaving partial garbage when the next
14
+ * tagline started. Now we put stdin in raw mode and silently
15
+ * swallow every byte except Ctrl-C (0x03) and Ctrl-D (0x04).
16
+ *
17
+ * 2. **Full-screen ownership + resize-aware redraw.** Enters the
18
+ * alternate screen buffer (\x1b[?1049h, the same mode vim / less /
19
+ * htop use) so the orqlaude logo claims the entire viewport while
20
+ * running, with nothing else visible. On exit, the original shell
21
+ * contents are restored. We repaint the full frame from top-left on
22
+ * every animation tick AND on `process.stdout` resize events — so
23
+ * the watermark always lives in the top-left corner regardless of
24
+ * window size.
25
+ *
26
+ * If stdout isn't a TTY (piped, CI, redirected), we fall back to a
27
+ * single-line static print and exit immediately. Animation only happens
28
+ * when there's an interactive terminal on the other end.
9
29
  */
10
30
  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`;
31
+ const ALT_SCREEN_ENTER = `${ESC}?1049h`;
32
+ const ALT_SCREEN_LEAVE = `${ESC}?1049l`;
33
+ const HIDE_CURSOR = `${ESC}?25l`;
34
+ const SHOW_CURSOR = `${ESC}?25h`;
35
+ const CLEAR_SCREEN = `${ESC}2J`;
36
+ const MOVE_TO_HOME = `${ESC}H`;
37
+ const moveTo = (row, col) => `${ESC}${row};${col}H`;
16
38
  const TYPE_MIN_MS = 28;
17
39
  const TYPE_MAX_MS = 90;
18
40
  const HOLD_MIN_MS = 1100;
@@ -21,65 +43,131 @@ const ERASE_MIN_MS = 12;
21
43
  const ERASE_MAX_MS = 30;
22
44
  const BETWEEN_MIN_MS = 280;
23
45
  const BETWEEN_MAX_MS = 600;
46
+ // Layout: 1-based rows/cols (ANSI convention).
47
+ // Row 1: blank padding so the logo doesn't kiss the top edge.
48
+ // Row 2-4: logo + wordmark + tagline.
49
+ // The tagline starts at column 14 (after ` ◆◆◆ ` which is exactly
50
+ // 13 visible chars when the ANSI color codes are stripped: 3 spaces + 3
51
+ // glyphs + 6 spaces + 1 = column 14 for the first tagline char).
52
+ const LOGO_ROW = 2;
53
+ const WORDMARK_ROW = 3;
54
+ const TAGLINE_ROW = 4;
55
+ const TAGLINE_COL = 14;
24
56
  export async function runEasterEgg() {
57
+ // Non-TTY fallback (piped, redirected, CI). No animation, no alt screen.
58
+ if (!process.stdout.isTTY) {
59
+ process.stdout.write(`◆ orqlaude — ${TAGLINES[0]}\n`);
60
+ return 0;
61
+ }
25
62
  return new Promise((resolve) => {
26
63
  let stopped = false;
27
- const onSig = () => {
64
+ let currentText = "";
65
+ const cleanup = () => {
66
+ try {
67
+ if (process.stdin.isTTY && process.stdin.setRawMode) {
68
+ process.stdin.setRawMode(false);
69
+ }
70
+ }
71
+ catch {
72
+ /* harmless on shutdown */
73
+ }
74
+ process.stdin.removeListener("data", onData);
75
+ process.stdin.pause();
76
+ process.stdout.off("resize", onResize);
77
+ process.removeListener("SIGINT", stop);
78
+ process.stdout.write(SHOW_CURSOR + ALT_SCREEN_LEAVE);
79
+ };
80
+ const stop = () => {
81
+ if (stopped)
82
+ return;
28
83
  stopped = true;
29
- // Move cursor below the tagline line and reset, then exit.
30
- process.stdout.write(RESET + "\n\n");
84
+ cleanup();
31
85
  resolve(0);
32
86
  };
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.
87
+ // Raw-mode keystroke capture. Every byte is swallowed; Ctrl-C / Ctrl-D
88
+ // exit. This is what stops the user's keyboard from echoing into the
89
+ // animation.
90
+ const onData = (chunk) => {
91
+ for (const byte of chunk) {
92
+ if (byte === 0x03 /* Ctrl-C */ || byte === 0x04 /* Ctrl-D */) {
93
+ stop();
94
+ return;
95
+ }
96
+ // All other input is silently discarded.
97
+ }
98
+ };
99
+ // Repaint the full frame from the top-left. Called on every animation
100
+ // tick and on terminal resize. Idempotent.
101
+ const paintFrame = () => {
102
+ const out = [
103
+ MOVE_TO_HOME,
104
+ CLEAR_SCREEN,
105
+ moveTo(LOGO_ROW, 4),
106
+ style.coral("◆◆◆"),
107
+ moveTo(WORDMARK_ROW, 3),
108
+ style.coral("◆ ◆"),
109
+ " ",
110
+ style.bold(style.coral("orqlaude")),
111
+ moveTo(TAGLINE_ROW, 4),
112
+ style.coral("◆◆◆"),
113
+ moveTo(TAGLINE_ROW, TAGLINE_COL),
114
+ style.sand(currentText),
115
+ ];
116
+ process.stdout.write(out.join(""));
117
+ };
118
+ const onResize = () => {
119
+ paintFrame();
120
+ };
121
+ // Initial setup.
122
+ process.stdout.write(ALT_SCREEN_ENTER + HIDE_CURSOR);
123
+ try {
124
+ if (process.stdin.isTTY && process.stdin.setRawMode) {
125
+ process.stdin.setRawMode(true);
126
+ }
127
+ process.stdin.resume();
128
+ process.stdin.on("data", onData);
129
+ }
130
+ catch {
131
+ /* if raw mode isn't available, we'll only react to SIGINT */
132
+ }
133
+ process.on("SIGINT", stop);
134
+ process.stdout.on("resize", onResize);
135
+ paintFrame();
136
+ // Animation loop.
46
137
  (async () => {
47
138
  let lastIdx = -1;
48
139
  while (!stopped) {
49
140
  let idx = Math.floor(Math.random() * TAGLINES.length);
50
- // Never repeat the previous tagline.
51
141
  while (idx === lastIdx) {
52
142
  idx = Math.floor(Math.random() * TAGLINES.length);
53
143
  }
54
144
  lastIdx = idx;
55
145
  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++) {
146
+ // Type out character by character. Repainting the whole frame
147
+ // each tick is overkill, but it's correct under resize and
148
+ // makes the code easier to reason about than tracking partial
149
+ // updates.
150
+ for (let i = 1; i <= tagline.length; i++) {
62
151
  if (stopped)
63
152
  return;
64
- process.stdout.write(tagline[i]);
153
+ currentText = tagline.slice(0, i);
154
+ paintFrame();
65
155
  await sleep(rand(TYPE_MIN_MS, TYPE_MAX_MS));
66
156
  }
67
- // Hold while the natural terminal cursor blinks at the end.
68
157
  await sleep(rand(HOLD_MIN_MS, HOLD_MAX_MS));
69
158
  if (stopped)
70
159
  return;
71
- // Erase backwards for a satisfying "delete" feel.
72
- for (let i = tagline.length; i > 0; i--) {
160
+ for (let i = tagline.length - 1; i >= 0; i--) {
73
161
  if (stopped)
74
162
  return;
75
- process.stdout.write("\b \b");
163
+ currentText = tagline.slice(0, i);
164
+ paintFrame();
76
165
  await sleep(rand(ERASE_MIN_MS, ERASE_MAX_MS));
77
166
  }
78
- process.stdout.write(RESET);
79
167
  await sleep(rand(BETWEEN_MIN_MS, BETWEEN_MAX_MS));
80
168
  }
81
169
  })().catch(() => {
82
- /* swallow — never crash on the easter egg */
170
+ /* never crash the easter egg */
83
171
  });
84
172
  });
85
173
  }
@@ -1 +1 @@
1
- {"version":3,"file":"easter_egg.js","sourceRoot":"","sources":["../../src/cli/easter_egg.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"easter_egg.js","sourceRoot":"","sources":["../../src/cli/easter_egg.ts"],"names":[],"mappings":"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"}
package/dist/cli.js CHANGED
@@ -26,7 +26,7 @@ import { tailAudit } from "./cli/tail.js";
26
26
  import { openPlan } from "./cli/open.js";
27
27
  import { showAbout } from "./cli/about.js";
28
28
  import { runEasterEgg } from "./cli/easter_egg.js";
29
- const VERSION = "0.8.0";
29
+ import { VERSION } from "./lib/version.js";
30
30
  /**
31
31
  * orqlaude CLI — read-only inspection of state + audit log + Telegram setup
32
32
  * and run.