@synaplink/orqlaude 0.5.1 → 0.5.5
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 +49 -12
- package/dist/__tests__/desktop_config.test.d.ts +1 -0
- package/dist/__tests__/desktop_config.test.js +110 -0
- package/dist/__tests__/desktop_config.test.js.map +1 -0
- package/dist/__tests__/v05.test.js +6 -2
- package/dist/__tests__/v05.test.js.map +1 -1
- package/dist/__tests__/v052.test.d.ts +1 -0
- package/dist/__tests__/v052.test.js +53 -0
- package/dist/__tests__/v052.test.js.map +1 -0
- package/dist/__tests__/v053.test.d.ts +1 -0
- package/dist/__tests__/v053.test.js +89 -0
- package/dist/__tests__/v053.test.js.map +1 -0
- package/dist/cli.js +118 -0
- package/dist/cli.js.map +1 -1
- package/dist/lib/desktop_config.d.ts +66 -0
- package/dist/lib/desktop_config.js +126 -0
- package/dist/lib/desktop_config.js.map +1 -0
- package/dist/lib/spawn_cli.d.ts +79 -0
- package/dist/lib/spawn_cli.js +211 -0
- package/dist/lib/spawn_cli.js.map +1 -0
- package/dist/lib/state.d.ts +10 -6
- package/dist/lib/state.js.map +1 -1
- package/dist/lib/telegram_status.d.ts +24 -0
- package/dist/lib/telegram_status.js +87 -0
- package/dist/lib/telegram_status.js.map +1 -0
- package/dist/server.js +1 -1
- package/dist/telegram/api.d.ts +0 -20
- package/dist/telegram/api.js +0 -32
- package/dist/telegram/api.js.map +1 -1
- package/dist/telegram/bot.js +54 -6
- package/dist/telegram/bot.js.map +1 -1
- package/dist/telegram/notifier.js +10 -98
- package/dist/telegram/notifier.js.map +1 -1
- package/dist/tools/broker.js +47 -1
- package/dist/tools/broker.js.map +1 -1
- package/dist/tools/dispatch.js +163 -23
- package/dist/tools/dispatch.js.map +1 -1
- package/dist/tools/ping.js +16 -2
- package/dist/tools/ping.js.map +1 -1
- package/dist/tools/userio.js +40 -9
- package/dist/tools/userio.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -44,20 +44,55 @@ orqlaude is the thin layer that adds those things. It never spawns processes its
|
|
|
44
44
|
npm install -g @synaplink/orqlaude # CLI + MCP server
|
|
45
45
|
```
|
|
46
46
|
|
|
47
|
-
|
|
47
|
+
Then wire it into Claude Desktop's MCP config in one command:
|
|
48
|
+
|
|
49
|
+
```sh
|
|
50
|
+
cd /path/to/your/project
|
|
51
|
+
orql setup
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
`orql setup` **patches** Claude Desktop's `claude_desktop_config.json` in place — adds an `orqlaude` MCP server entry pointed at this project's state dir, and **preserves every other server you have configured** (lm-studio, etc.) plus the entire `preferences` block. Writes a timestamped `.bak` before changing anything. Re-runs are idempotent — if the entry is already correct, it reports `already correct; nothing to do` and exits without touching the file.
|
|
55
|
+
|
|
56
|
+
Flags:
|
|
57
|
+
- `--state-dir <path>` override the default (which walks up from cwd for a `.git`)
|
|
58
|
+
- `--config-path <path>` override Claude Desktop's config path
|
|
59
|
+
- `--yes` skip prompts
|
|
60
|
+
|
|
61
|
+
Fully quit and relaunch Claude Desktop after running. The `mcp__orqlaude__*` tools will then appear in your sessions.
|
|
62
|
+
|
|
63
|
+
If you'd rather edit the config yourself, the entry should look like:
|
|
48
64
|
|
|
49
65
|
```json
|
|
50
66
|
{
|
|
51
67
|
"mcpServers": {
|
|
52
68
|
"orqlaude": {
|
|
53
69
|
"command": "npx",
|
|
54
|
-
"args": ["-y", "@synaplink/orqlaude"]
|
|
70
|
+
"args": ["-y", "-p", "@synaplink/orqlaude", "orqlaude-mcp"],
|
|
71
|
+
"env": {
|
|
72
|
+
"ORQLAUDE_STATE_DIR": "/absolute/path/to/your/project/.orqlaude"
|
|
73
|
+
}
|
|
55
74
|
}
|
|
56
75
|
}
|
|
57
76
|
}
|
|
58
77
|
```
|
|
59
78
|
|
|
60
|
-
|
|
79
|
+
The `ORQLAUDE_STATE_DIR` env var is important — it pins state to a specific path so the MCP server (running with `cwd=/` on some hosts) and the Telegram bot (running in your project) share the same state file.
|
|
80
|
+
|
|
81
|
+
## Spawning Agnets: which tool to use
|
|
82
|
+
|
|
83
|
+
orqlaude itself doesn't spawn processes — it returns prompts and lets the orchestrator pick a spawn tool. Use them in this priority order:
|
|
84
|
+
|
|
85
|
+
| Priority | Tool | Isolation | Visibility | When to use |
|
|
86
|
+
|---|---|---|---|---|
|
|
87
|
+
| **1** | `mcp__ccd_session__spawn_task` | git worktree per Agnet | Claude Desktop Code sidebar | **Default.** Worktree-isolated, sandbox-clean, the Agnet shows up as its own session you can switch into. |
|
|
88
|
+
| 2 | Host's `Agent` tool (Claude Code built-in) | none — shares your cwd | tool-use only, not a separate session | Faster, no chip-click. **Loses worktree isolation** — Agnets may race on shared files. `claim_files` from the broker is your only collision signal. |
|
|
89
|
+
| 3 | Shell out `claude -p --worktree …` | explicit `--worktree` flag | JSONL on disk — not in sidebar until Desktop restart | Headless / cron / non-Desktop hosts. |
|
|
90
|
+
|
|
91
|
+
`next_task` returns a `spawn_strategies[]` array with ready-to-call args for each option, so the orchestrator can pick deliberately. **Picking by habit is the most common way to bypass orqlaude's isolation guarantees** — check the returned strategies and make a conscious choice.
|
|
92
|
+
|
|
93
|
+
### Orphan detection
|
|
94
|
+
|
|
95
|
+
If an Agnet is dispatched but doesn't call `mcp__orqlaude__checkin` within 60 s, `status()` flags it in `orphan_alerts[]`. Common cause: the orchestrator used a non-`ccd_session__spawn_task` path and the Agnet skipped (or never reached) the protocol footer that tells it to register.
|
|
61
96
|
|
|
62
97
|
## Tool reference
|
|
63
98
|
|
|
@@ -116,13 +151,13 @@ Without a running `orqlaude tg start`, `notify_user` queues silently, `request_u
|
|
|
116
151
|
|
|
117
152
|
#### Streaming transport
|
|
118
153
|
|
|
119
|
-
orqlaude streams
|
|
154
|
+
orqlaude streams by opening a single Telegram message with `sendMessage`, then calling `editMessageText` on each append. The final `stream_to_user_end` does one more edit appending a `✓` marker.
|
|
120
155
|
|
|
121
|
-
|
|
156
|
+
(v0.5.1 briefly used `sendMessageDraft` for animated, ephemeral previews — reverted in v0.5.4 after that endpoint proved unreliable in the standard Bot API.)
|
|
122
157
|
|
|
123
158
|
Limits to know:
|
|
124
159
|
- A Telegram message tops out at 4096 chars. orqlaude caps stream content at 3800 to leave room for the title + completion marker; further appends are silently truncated.
|
|
125
|
-
-
|
|
160
|
+
- Edits are rate-limited (~1/sec per message); orqlaude throttles to 1.5 s between edits per stream.
|
|
126
161
|
- If you need to stream more than 4 kb of output, start a new stream when you're approaching the cap.
|
|
127
162
|
|
|
128
163
|
### Health
|
|
@@ -191,13 +226,15 @@ False positives are acceptable here — we surface concerns, we don't auto-kill.
|
|
|
191
226
|
|
|
192
227
|
## CLI
|
|
193
228
|
|
|
229
|
+
Two binaries are installed: `orqlaude` and the short alias `orql`. Use whichever feels right.
|
|
230
|
+
|
|
194
231
|
```sh
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
232
|
+
orql list # every plan in this project
|
|
233
|
+
orql status <plan_id> # refreshed status of one plan
|
|
234
|
+
orql show <plan_id> # raw plan JSON
|
|
235
|
+
orql history --limit 50 # tail audit log
|
|
236
|
+
orql where # show resolved state dir
|
|
237
|
+
orql help
|
|
201
238
|
```
|
|
202
239
|
|
|
203
240
|
Read-only. For active orchestration, use the MCP from inside Claude Code.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
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 { planPatch, buildOrqlaudeEntry, readDesktopConfig, writeDesktopConfigAtomic, findDesktopConfigPath, } from "../lib/desktop_config.js";
|
|
7
|
+
/** v0.5.5: regression tests for the desktop_config patcher. */
|
|
8
|
+
const STATE_DIR = "/Users/matthew/Documents/orqlaude/.orqlaude";
|
|
9
|
+
test("planPatch with no existing config creates one + adds orqlaude entry", () => {
|
|
10
|
+
const result = planPatch(null, STATE_DIR);
|
|
11
|
+
assert.equal(result.action, "create-config");
|
|
12
|
+
assert.equal(result.before, null);
|
|
13
|
+
assert.equal(result.after.command, "npx");
|
|
14
|
+
assert.deepEqual(result.after.args, ["-y", "-p", "@synaplink/orqlaude", "orqlaude-mcp"]);
|
|
15
|
+
assert.equal(result.after.env?.ORQLAUDE_STATE_DIR, STATE_DIR);
|
|
16
|
+
});
|
|
17
|
+
test("planPatch with existing config but no orqlaude key adds it without touching others", () => {
|
|
18
|
+
const existing = {
|
|
19
|
+
mcpServers: {
|
|
20
|
+
"lm-studio": {
|
|
21
|
+
command: "npx",
|
|
22
|
+
args: ["-y", "@mzxrai/mcp-openai"],
|
|
23
|
+
env: { OPENAI_API_KEY: "lm-studio" },
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
preferences: { someFlag: true },
|
|
27
|
+
};
|
|
28
|
+
const result = planPatch(existing, STATE_DIR);
|
|
29
|
+
assert.equal(result.action, "create-server");
|
|
30
|
+
// Original is preserved
|
|
31
|
+
assert.deepEqual(result.config.mcpServers["lm-studio"], existing.mcpServers["lm-studio"]);
|
|
32
|
+
assert.deepEqual(result.config.preferences, { someFlag: true });
|
|
33
|
+
// New entry present
|
|
34
|
+
assert.equal(result.config.mcpServers["orqlaude"].env?.ORQLAUDE_STATE_DIR, STATE_DIR);
|
|
35
|
+
});
|
|
36
|
+
test("planPatch with correct orqlaude entry already present → noop", () => {
|
|
37
|
+
const existing = {
|
|
38
|
+
mcpServers: { orqlaude: buildOrqlaudeEntry(STATE_DIR) },
|
|
39
|
+
};
|
|
40
|
+
const result = planPatch(existing, STATE_DIR);
|
|
41
|
+
assert.equal(result.action, "noop");
|
|
42
|
+
});
|
|
43
|
+
test("planPatch with orqlaude entry at wrong state dir → update; preserve other env keys", () => {
|
|
44
|
+
const existing = {
|
|
45
|
+
mcpServers: {
|
|
46
|
+
orqlaude: {
|
|
47
|
+
command: "npx",
|
|
48
|
+
args: ["-y", "-p", "@synaplink/orqlaude", "orqlaude-mcp"],
|
|
49
|
+
env: { ORQLAUDE_STATE_DIR: "/old/path", CUSTOM_DEBUG_FLAG: "1" },
|
|
50
|
+
},
|
|
51
|
+
},
|
|
52
|
+
};
|
|
53
|
+
const result = planPatch(existing, STATE_DIR);
|
|
54
|
+
assert.equal(result.action, "update-server");
|
|
55
|
+
// New state dir applied
|
|
56
|
+
assert.equal(result.after.env?.ORQLAUDE_STATE_DIR, STATE_DIR);
|
|
57
|
+
// Custom env key preserved
|
|
58
|
+
assert.equal(result.after.env?.CUSTOM_DEBUG_FLAG, "1");
|
|
59
|
+
});
|
|
60
|
+
test("planPatch preserves top-level keys we don't recognize", () => {
|
|
61
|
+
const existing = {
|
|
62
|
+
mcpServers: {},
|
|
63
|
+
preferences: { x: 1 },
|
|
64
|
+
futureField: { whatever: true },
|
|
65
|
+
};
|
|
66
|
+
const result = planPatch(existing, STATE_DIR);
|
|
67
|
+
assert.equal(result.action, "create-server");
|
|
68
|
+
assert.deepEqual(result.config.preferences, { x: 1 });
|
|
69
|
+
assert.deepEqual(result.config.futureField, { whatever: true });
|
|
70
|
+
});
|
|
71
|
+
test("writeDesktopConfigAtomic creates a timestamped backup when the file exists", async () => {
|
|
72
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-desktop-"));
|
|
73
|
+
const filePath = path.join(dir, "config.json");
|
|
74
|
+
await fs.writeFile(filePath, JSON.stringify({ original: true }, null, 2));
|
|
75
|
+
const { backupPath } = await writeDesktopConfigAtomic(filePath, { updated: true });
|
|
76
|
+
assert.ok(backupPath, "expected a backup path");
|
|
77
|
+
const backed = JSON.parse(await fs.readFile(backupPath, "utf8"));
|
|
78
|
+
assert.deepEqual(backed, { original: true });
|
|
79
|
+
const updated = JSON.parse(await fs.readFile(filePath, "utf8"));
|
|
80
|
+
assert.deepEqual(updated, { updated: true });
|
|
81
|
+
});
|
|
82
|
+
test("writeDesktopConfigAtomic creates parent dirs + no backup on fresh file", async () => {
|
|
83
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-desktop-"));
|
|
84
|
+
const filePath = path.join(dir, "nested", "deep", "config.json");
|
|
85
|
+
const { backupPath } = await writeDesktopConfigAtomic(filePath, { fresh: true });
|
|
86
|
+
assert.equal(backupPath, null);
|
|
87
|
+
const got = JSON.parse(await fs.readFile(filePath, "utf8"));
|
|
88
|
+
assert.deepEqual(got, { fresh: true });
|
|
89
|
+
});
|
|
90
|
+
test("readDesktopConfig returns null for missing files; throws on malformed JSON", async () => {
|
|
91
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-desktop-"));
|
|
92
|
+
const filePath = path.join(dir, "config.json");
|
|
93
|
+
assert.equal(await readDesktopConfig(filePath), null);
|
|
94
|
+
await fs.writeFile(filePath, "{ not valid json,,,");
|
|
95
|
+
await assert.rejects(() => readDesktopConfig(filePath), /Failed to parse/);
|
|
96
|
+
});
|
|
97
|
+
test("findDesktopConfigPath returns a platform-appropriate path", () => {
|
|
98
|
+
const p = findDesktopConfigPath();
|
|
99
|
+
assert.ok(p.endsWith("claude_desktop_config.json"), `got: ${p}`);
|
|
100
|
+
if (process.platform === "darwin") {
|
|
101
|
+
assert.ok(p.includes("Library/Application Support/Claude"), `got: ${p}`);
|
|
102
|
+
}
|
|
103
|
+
else if (process.platform === "win32") {
|
|
104
|
+
assert.ok(p.includes("Claude"), `got: ${p}`);
|
|
105
|
+
}
|
|
106
|
+
else {
|
|
107
|
+
assert.ok(p.includes(".config/Claude"), `got: ${p}`);
|
|
108
|
+
}
|
|
109
|
+
});
|
|
110
|
+
//# sourceMappingURL=desktop_config.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"desktop_config.test.js","sourceRoot":"","sources":["../../src/__tests__/desktop_config.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -72,9 +72,13 @@ test("v0.5 schema: newPlan initializes userStreams empty", async () => {
|
|
|
72
72
|
});
|
|
73
73
|
assert.deepEqual(plan.userStreams, []);
|
|
74
74
|
});
|
|
75
|
-
test("TelegramApi
|
|
75
|
+
test("TelegramApi has the expected post-v0.5.4 surface", async () => {
|
|
76
|
+
// v0.5.4 removed sendMessageDraft after sendMessage proved unreliable in
|
|
77
|
+
// the standard Bot API. Confirm it's no longer exported.
|
|
76
78
|
const { TelegramApi } = await import("../telegram/api.js");
|
|
77
79
|
const api = new TelegramApi("test:token");
|
|
78
|
-
|
|
80
|
+
assert.equal(typeof api.sendMessage, "function");
|
|
81
|
+
assert.equal(typeof api.editMessageText, "function");
|
|
82
|
+
assert.equal(api.sendMessageDraft, undefined);
|
|
79
83
|
});
|
|
80
84
|
//# sourceMappingURL=v05.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"v05.test.js","sourceRoot":"","sources":["../../src/__tests__/v05.test.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"v05.test.js","sourceRoot":"","sources":["../../src/__tests__/v05.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,53 @@
|
|
|
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 { StateStore, newPlan, findPlan } from "../lib/state.js";
|
|
7
|
+
/** v0.5.2: orphan detection on dispatched-but-unregistered Agnets. */
|
|
8
|
+
async function tmpStore() {
|
|
9
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-v052-"));
|
|
10
|
+
return { store: new StateStore(dir), dir };
|
|
11
|
+
}
|
|
12
|
+
test("orphan: task dispatched > 60s ago with no spawnedSessionId is detectable", async () => {
|
|
13
|
+
const { store } = await tmpStore();
|
|
14
|
+
let planId = "";
|
|
15
|
+
await store.update((s) => {
|
|
16
|
+
const p = newPlan("root", 100_000, [
|
|
17
|
+
{ title: "T1", prompt: "p", tldr: "tl" },
|
|
18
|
+
{ title: "T2", prompt: "p", tldr: "tl" },
|
|
19
|
+
]);
|
|
20
|
+
p.tasks[0].status = "dispatched";
|
|
21
|
+
p.tasks[0].startedAt = Date.now() - 120_000; // 2 min ago
|
|
22
|
+
// Task 1 has no spawnedSessionId — orphan.
|
|
23
|
+
p.tasks[1].status = "dispatched";
|
|
24
|
+
p.tasks[1].startedAt = Date.now() - 30_000; // 30s ago, NOT orphan yet
|
|
25
|
+
p.tasks[1].spawnedSessionId = "registered";
|
|
26
|
+
planId = p.id;
|
|
27
|
+
s.plans[p.id] = p;
|
|
28
|
+
});
|
|
29
|
+
const plan = await store.read((s) => findPlan(s, planId));
|
|
30
|
+
const ORPHAN_MS = 60_000;
|
|
31
|
+
const orphans = plan.tasks.filter((t) => t.status === "dispatched" &&
|
|
32
|
+
!t.spawnedSessionId &&
|
|
33
|
+
t.startedAt &&
|
|
34
|
+
Date.now() - t.startedAt > ORPHAN_MS);
|
|
35
|
+
assert.equal(orphans.length, 1);
|
|
36
|
+
assert.equal(orphans[0].title, "T1");
|
|
37
|
+
});
|
|
38
|
+
test("orphan: dispatched < 60s ago is NOT yet an orphan", async () => {
|
|
39
|
+
const { store } = await tmpStore();
|
|
40
|
+
await store.update((s) => {
|
|
41
|
+
const p = newPlan("root", 100_000, [{ title: "T", prompt: "p", tldr: "tl" }]);
|
|
42
|
+
p.tasks[0].status = "dispatched";
|
|
43
|
+
p.tasks[0].startedAt = Date.now() - 10_000; // 10s ago
|
|
44
|
+
s.plans[p.id] = p;
|
|
45
|
+
});
|
|
46
|
+
const plan = await store.read((s) => Object.values(s.plans)[0]);
|
|
47
|
+
const orphans = plan.tasks.filter((t) => t.status === "dispatched" &&
|
|
48
|
+
!t.spawnedSessionId &&
|
|
49
|
+
t.startedAt &&
|
|
50
|
+
Date.now() - t.startedAt > 60_000);
|
|
51
|
+
assert.equal(orphans.length, 0);
|
|
52
|
+
});
|
|
53
|
+
//# sourceMappingURL=v052.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v052.test.js","sourceRoot":"","sources":["../../src/__tests__/v052.test.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,89 @@
|
|
|
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 { StateStore, newPlan, planForSession, unclaimedTaskById } from "../lib/state.js";
|
|
7
|
+
/**
|
|
8
|
+
* v0.5.3: regression tests for checkin conflict detection. We test the
|
|
9
|
+
* underlying state lookup primitives rather than the MCP tool itself —
|
|
10
|
+
* the conflict-detection branches in broker.ts use exactly these helpers.
|
|
11
|
+
*/
|
|
12
|
+
async function tmpStore() {
|
|
13
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-v053-"));
|
|
14
|
+
return new StateStore(dir);
|
|
15
|
+
}
|
|
16
|
+
test("v0.5.3: session bound to task A cannot be retargeted by passing task B's id", async () => {
|
|
17
|
+
const store = await tmpStore();
|
|
18
|
+
let planId = "";
|
|
19
|
+
let taskAId = "";
|
|
20
|
+
let taskBId = "";
|
|
21
|
+
await store.update((s) => {
|
|
22
|
+
const p = newPlan("root", 100_000, [
|
|
23
|
+
{ title: "A", prompt: "a", tldr: "a" },
|
|
24
|
+
{ title: "B", prompt: "b", tldr: "b" },
|
|
25
|
+
]);
|
|
26
|
+
p.tasks[0].status = "dispatched";
|
|
27
|
+
p.tasks[0].spawnedSessionId = "session-X";
|
|
28
|
+
p.tasks[1].status = "dispatched";
|
|
29
|
+
planId = p.id;
|
|
30
|
+
taskAId = p.tasks[0].id;
|
|
31
|
+
taskBId = p.tasks[1].id;
|
|
32
|
+
s.plans[p.id] = p;
|
|
33
|
+
});
|
|
34
|
+
// Caller session X is already bound to task A. If they pass task_id=B,
|
|
35
|
+
// planForSession should return A — not silently switch them to B.
|
|
36
|
+
const result = await store.read((state) => {
|
|
37
|
+
const found = planForSession(state, "session-X");
|
|
38
|
+
return found ? { taskId: found.task.id, title: found.task.title } : null;
|
|
39
|
+
});
|
|
40
|
+
assert.ok(result, "session should be found");
|
|
41
|
+
assert.equal(result.taskId, taskAId);
|
|
42
|
+
assert.notEqual(result.taskId, taskBId);
|
|
43
|
+
});
|
|
44
|
+
test("v0.5.3: task already claimed by another session cannot be re-claimed via task_id", async () => {
|
|
45
|
+
const store = await tmpStore();
|
|
46
|
+
let taskId = "";
|
|
47
|
+
await store.update((s) => {
|
|
48
|
+
const p = newPlan("root", 100_000, [{ title: "T", prompt: "p", tldr: "tl" }]);
|
|
49
|
+
p.tasks[0].status = "running";
|
|
50
|
+
p.tasks[0].spawnedSessionId = "first-session";
|
|
51
|
+
taskId = p.tasks[0].id;
|
|
52
|
+
s.plans[p.id] = p;
|
|
53
|
+
});
|
|
54
|
+
// A different session calls checkin with that task_id.
|
|
55
|
+
// unclaimedTaskById should return undefined because the task IS claimed.
|
|
56
|
+
const target = await store.read((state) => unclaimedTaskById(state, taskId));
|
|
57
|
+
assert.equal(target, undefined);
|
|
58
|
+
});
|
|
59
|
+
test("v0.5.3: spawn_cli util discovers git root via .git directory", async () => {
|
|
60
|
+
const dir = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-git-root-"));
|
|
61
|
+
await fs.mkdir(path.join(dir, ".git"));
|
|
62
|
+
await fs.mkdir(path.join(dir, "nested", "deeper"), { recursive: true });
|
|
63
|
+
const { findGitRoot } = await import("../lib/spawn_cli.js");
|
|
64
|
+
const real = await fs.realpath(dir);
|
|
65
|
+
assert.equal(findGitRoot(path.join(real, "nested", "deeper")), real);
|
|
66
|
+
});
|
|
67
|
+
test("v0.5.3: telegram_status returns 'unconfigured' when no config file exists", async () => {
|
|
68
|
+
const stateDir = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-tg-status-"));
|
|
69
|
+
const { probeTelegramStatus } = await import("../lib/telegram_status.js");
|
|
70
|
+
// Override HOME so it can't find a real config.
|
|
71
|
+
const realHome = process.env.HOME;
|
|
72
|
+
const fakeHome = await fs.mkdtemp(path.join(os.tmpdir(), "orqlaude-fakehome-"));
|
|
73
|
+
process.env.HOME = fakeHome;
|
|
74
|
+
try {
|
|
75
|
+
const status = await probeTelegramStatus(stateDir);
|
|
76
|
+
// We can't be certain the user has no real config — but the path under
|
|
77
|
+
// a freshly-minted fake HOME doesn't exist, so status should be
|
|
78
|
+
// unconfigured.
|
|
79
|
+
assert.equal(status.status, "unconfigured");
|
|
80
|
+
assert.equal(status.hasToken, false);
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
if (realHome)
|
|
84
|
+
process.env.HOME = realHome;
|
|
85
|
+
else
|
|
86
|
+
delete process.env.HOME;
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
//# sourceMappingURL=v053.test.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"v053.test.js","sourceRoot":"","sources":["../../src/__tests__/v053.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,MAAM,MAAM,oBAAoB,CAAC;AACxC,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,UAAU,EAAE,OAAO,EAAY,cAAc,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AAEnG;;;;GAIG;AAEH,KAAK,UAAU,QAAQ;IACrB,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,gBAAgB,CAAC,CAAC,CAAC;IACvE,OAAO,IAAI,UAAU,CAAC,GAAG,CAAC,CAAC;AAC7B,CAAC;AAED,IAAI,CAAC,6EAA6E,EAAE,KAAK,IAAI,EAAE;IAC7F,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC/B,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,IAAI,OAAO,GAAG,EAAE,CAAC;IACjB,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACvB,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE;YACjC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE;YACtC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,GAAG,EAAE;SACvC,CAAC,CAAC;QACH,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,YAAY,CAAC;QACjC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,GAAG,WAAW,CAAC;QAC1C,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,YAAY,CAAC;QACjC,MAAM,GAAG,CAAC,CAAC,EAAE,CAAC;QACd,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxB,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACxB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IACH,uEAAuE;IACvE,kEAAkE;IAClE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE;QACxC,MAAM,KAAK,GAAG,cAAc,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QACjD,OAAO,KAAK,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3E,CAAC,CAAC,CAAC;IACH,MAAM,CAAC,EAAE,CAAC,MAAM,EAAE,yBAAyB,CAAC,CAAC;IAC7C,MAAM,CAAC,KAAK,CAAC,MAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACtC,MAAM,CAAC,QAAQ,CAAC,MAAO,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAC3C,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,kFAAkF,EAAE,KAAK,IAAI,EAAE;IAClG,MAAM,KAAK,GAAG,MAAM,QAAQ,EAAE,CAAC;IAC/B,IAAI,MAAM,GAAG,EAAE,CAAC;IAChB,MAAM,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;QACvB,MAAM,CAAC,GAAG,OAAO,CAAC,MAAM,EAAE,OAAO,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAC9E,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,GAAG,SAAS,CAAC;QAC9B,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,gBAAgB,GAAG,eAAe,CAAC;QAC9C,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACvB,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC;IACpB,CAAC,CAAC,CAAC;IACH,uDAAuD;IACvD,yEAAyE;IACzE,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,iBAAiB,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC;IAC7E,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC;AAClC,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;IAC9E,MAAM,GAAG,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAC3E,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC;IACvC,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,EAAE,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACxE,MAAM,EAAE,WAAW,EAAE,GAAG,MAAM,MAAM,CAAC,qBAAqB,CAAC,CAAC;IAC5D,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;IACpC,MAAM,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE,QAAQ,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;AACvE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,2EAA2E,EAAE,KAAK,IAAI,EAAE;IAC3F,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,qBAAqB,CAAC,CAAC,CAAC;IACjF,MAAM,EAAE,mBAAmB,EAAE,GAAG,MAAM,MAAM,CAAC,2BAA2B,CAAC,CAAC;IAC1E,gDAAgD;IAChD,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAClC,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,MAAM,EAAE,EAAE,oBAAoB,CAAC,CAAC,CAAC;IAChF,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC;IAC5B,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC,QAAQ,CAAC,CAAC;QACnD,uEAAuE;QACvE,gEAAgE;QAChE,gBAAgB;QAChB,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;QAC5C,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;IACvC,CAAC;YAAS,CAAC;QACT,IAAI,QAAQ;YAAE,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,QAAQ,CAAC;;YACrC,OAAO,OAAO,CAAC,GAAG,CAAC,IAAI,CAAC;IAC/B,CAAC;AACH,CAAC,CAAC,CAAC"}
|
package/dist/cli.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import path from "node:path";
|
|
2
3
|
import readline from "node:readline/promises";
|
|
3
4
|
import { stdin, stdout } from "node:process";
|
|
4
5
|
import { StateStore } from "./lib/state.js";
|
|
@@ -10,6 +11,8 @@ import { runBot } from "./telegram/bot.js";
|
|
|
10
11
|
import { resolveStateDir } from "./lib/state_dir.js";
|
|
11
12
|
import { style, styleStatus, banner } from "./lib/style.js";
|
|
12
13
|
import { agnetLabel } from "./lib/agnet.js";
|
|
14
|
+
import { findDesktopConfigPath, readDesktopConfig, planPatch, writeDesktopConfigAtomic, } from "./lib/desktop_config.js";
|
|
15
|
+
import { existsSync } from "node:fs";
|
|
13
16
|
/**
|
|
14
17
|
* orqlaude CLI — read-only inspection of state + audit log + Telegram setup
|
|
15
18
|
* and run.
|
|
@@ -40,6 +43,8 @@ async function main() {
|
|
|
40
43
|
return await cmdHistory(parseLimit(rest));
|
|
41
44
|
case "where":
|
|
42
45
|
return cmdWhere();
|
|
46
|
+
case "setup":
|
|
47
|
+
return await cmdSetup(rest);
|
|
43
48
|
case "tg":
|
|
44
49
|
return await cmdTg(rest);
|
|
45
50
|
default:
|
|
@@ -51,6 +56,10 @@ async function main() {
|
|
|
51
56
|
function printHelp() {
|
|
52
57
|
console.log(banner());
|
|
53
58
|
console.log("");
|
|
59
|
+
console.log(style.bold(style.cream("Setup")));
|
|
60
|
+
console.log(` ${style.coral("orql setup")} ${style.sand("[--state-dir PATH] [--yes]")}`);
|
|
61
|
+
console.log(` Wire orqlaude into Claude Desktop's MCP config (idempotent, preserves other servers)`);
|
|
62
|
+
console.log("");
|
|
54
63
|
console.log(style.bold(style.cream("Inspection")));
|
|
55
64
|
console.log(` ${style.coral("orqlaude list")} List every plan in this project`);
|
|
56
65
|
console.log(` ${style.coral("orqlaude status")} ${style.sand("<plan_id>")} Refreshed status of one plan`);
|
|
@@ -154,6 +163,115 @@ async function cmdShow(planId) {
|
|
|
154
163
|
return 1;
|
|
155
164
|
}
|
|
156
165
|
}
|
|
166
|
+
// ---- setup -----------------------------------------------------------------
|
|
167
|
+
/**
|
|
168
|
+
* Detect a sensible default state dir for the current shell. Walks up from
|
|
169
|
+
* cwd for a `.git`; falls back to cwd.
|
|
170
|
+
*/
|
|
171
|
+
function defaultStateDir() {
|
|
172
|
+
let dir = process.cwd();
|
|
173
|
+
for (let i = 0; i < 10; i++) {
|
|
174
|
+
if (existsSync(path.join(dir, ".git"))) {
|
|
175
|
+
return path.join(dir, ".orqlaude");
|
|
176
|
+
}
|
|
177
|
+
const parent = path.dirname(dir);
|
|
178
|
+
if (parent === dir)
|
|
179
|
+
break;
|
|
180
|
+
dir = parent;
|
|
181
|
+
}
|
|
182
|
+
return path.join(process.cwd(), ".orqlaude");
|
|
183
|
+
}
|
|
184
|
+
async function cmdSetup(args) {
|
|
185
|
+
console.log(banner());
|
|
186
|
+
console.log("");
|
|
187
|
+
console.log(style.bold(style.cream("Setup")));
|
|
188
|
+
console.log("Wires orqlaude into Claude Desktop's MCP config.");
|
|
189
|
+
console.log("");
|
|
190
|
+
// Parse flags
|
|
191
|
+
const stateDirIdx = args.indexOf("--state-dir");
|
|
192
|
+
const overrideStateDir = stateDirIdx !== -1 ? args[stateDirIdx + 1] : null;
|
|
193
|
+
const yes = args.includes("--yes") || args.includes("-y");
|
|
194
|
+
const configPathIdx = args.indexOf("--config-path");
|
|
195
|
+
const configPath = configPathIdx !== -1 ? args[configPathIdx + 1] : findDesktopConfigPath();
|
|
196
|
+
console.log(` ${style.sand("config:")} ${configPath}`);
|
|
197
|
+
// 1. Read existing config (preserve everything we don't own).
|
|
198
|
+
let existing;
|
|
199
|
+
try {
|
|
200
|
+
existing = await readDesktopConfig(configPath);
|
|
201
|
+
}
|
|
202
|
+
catch (err) {
|
|
203
|
+
console.error("");
|
|
204
|
+
console.error(style.crimson(`✗ ${err.message}`));
|
|
205
|
+
return 1;
|
|
206
|
+
}
|
|
207
|
+
if (!existing) {
|
|
208
|
+
console.log(` ${style.sand("status:")} ${style.crimson("config file does not exist — will create")}`);
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
const otherServerCount = Object.keys(existing.mcpServers ?? {}).filter((k) => k !== "orqlaude").length;
|
|
212
|
+
const orqEntry = existing.mcpServers?.orqlaude;
|
|
213
|
+
const has = orqEntry ? style.coral("orqlaude entry present") : style.sand("no orqlaude entry yet");
|
|
214
|
+
console.log(` ${style.sand("status:")} ${has}, ${otherServerCount} other server(s) preserved`);
|
|
215
|
+
}
|
|
216
|
+
// 2. Pick state dir.
|
|
217
|
+
let stateDir = overrideStateDir;
|
|
218
|
+
if (!stateDir) {
|
|
219
|
+
const suggested = defaultStateDir();
|
|
220
|
+
if (yes) {
|
|
221
|
+
stateDir = suggested;
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
const rl = readline.createInterface({ input: stdin, output: stdout });
|
|
225
|
+
const answer = (await rl.question(`\n ${style.coral("?")} state dir (where plans/audit live) [${suggested}]: `)).trim();
|
|
226
|
+
rl.close();
|
|
227
|
+
stateDir = answer || suggested;
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
stateDir = path.resolve(stateDir);
|
|
231
|
+
// 3. Compute patch.
|
|
232
|
+
const plan = planPatch(existing, stateDir);
|
|
233
|
+
console.log("");
|
|
234
|
+
console.log(style.bold(style.cream("Plan")));
|
|
235
|
+
switch (plan.action) {
|
|
236
|
+
case "noop":
|
|
237
|
+
console.log(` ${style.coral("✓")} already correct; nothing to do`);
|
|
238
|
+
return 0;
|
|
239
|
+
case "create-config":
|
|
240
|
+
console.log(` ${style.coral("→")} create ${configPath} with one server (orqlaude → ${stateDir})`);
|
|
241
|
+
break;
|
|
242
|
+
case "create-server":
|
|
243
|
+
console.log(` ${style.coral("→")} add orqlaude entry (→ ${stateDir}); preserve existing servers + preferences`);
|
|
244
|
+
break;
|
|
245
|
+
case "update-server":
|
|
246
|
+
console.log(` ${style.coral("→")} update orqlaude entry`);
|
|
247
|
+
console.log(` ${style.sand("before:")} ${JSON.stringify(plan.before)}`);
|
|
248
|
+
console.log(` ${style.sand("after:")} ${JSON.stringify(plan.after)}`);
|
|
249
|
+
break;
|
|
250
|
+
}
|
|
251
|
+
// 4. Confirm + write.
|
|
252
|
+
if (!yes) {
|
|
253
|
+
const rl2 = readline.createInterface({ input: stdin, output: stdout });
|
|
254
|
+
const ans = (await rl2.question(`\n ${style.coral("?")} apply? [Y/n] `)).trim().toLowerCase();
|
|
255
|
+
rl2.close();
|
|
256
|
+
if (ans && ans !== "y" && ans !== "yes") {
|
|
257
|
+
console.log(style.crimson(" ✗ cancelled"));
|
|
258
|
+
return 1;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
const { backupPath } = await writeDesktopConfigAtomic(configPath, plan.config);
|
|
262
|
+
console.log("");
|
|
263
|
+
console.log(style.bold(style.coral("Done.")));
|
|
264
|
+
console.log(` ${style.sand("config:")} ${configPath}`);
|
|
265
|
+
if (backupPath)
|
|
266
|
+
console.log(` ${style.sand("backup:")} ${backupPath}`);
|
|
267
|
+
console.log(` ${style.sand("state dir:")} ${stateDir}`);
|
|
268
|
+
console.log("");
|
|
269
|
+
console.log(style.dim("Next steps:"));
|
|
270
|
+
console.log(style.dim(" 1. Fully quit Claude Desktop (Cmd-Q on macOS) and relaunch."));
|
|
271
|
+
console.log(style.dim(" 2. Open a session in this project. Call `mcp__orqlaude__ping` — it should report state_dir_source:'env'."));
|
|
272
|
+
console.log(style.dim(" 3. (Optional) Set up the Telegram bot: `orql tg setup`."));
|
|
273
|
+
return 0;
|
|
274
|
+
}
|
|
157
275
|
function cmdWhere() {
|
|
158
276
|
console.log(banner());
|
|
159
277
|
console.log("");
|