cueloop 0.1.0-alpha.65 → 0.1.0-alpha.67
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/package.json +5 -5
- package/src/dev-command.ts +85 -0
- package/src/main.ts +2 -0
- package/src/share-command.test.ts +1 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cueloop",
|
|
3
|
-
"version": "0.1.0-alpha.
|
|
3
|
+
"version": "0.1.0-alpha.67",
|
|
4
4
|
"description": "Terminal review surface for coding agents: annotate plans and diffs, return a verdict, send structured feedback back",
|
|
5
5
|
"homepage": "https://github.com/mmurakaru/cueloop#readme",
|
|
6
6
|
"bugs": {
|
|
@@ -30,10 +30,10 @@
|
|
|
30
30
|
"build:binary": "bun build --compile --external cpu-features ./src/main.ts --outfile dist/cueloop"
|
|
31
31
|
},
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"@cueloop/adapters": "0.1.0-alpha.
|
|
34
|
-
"@cueloop/client": "0.1.0-alpha.
|
|
35
|
-
"@cueloop/daemon": "0.1.0-alpha.
|
|
36
|
-
"@cueloop/schema": "0.1.0-alpha.
|
|
33
|
+
"@cueloop/adapters": "0.1.0-alpha.67",
|
|
34
|
+
"@cueloop/client": "0.1.0-alpha.67",
|
|
35
|
+
"@cueloop/daemon": "0.1.0-alpha.67",
|
|
36
|
+
"@cueloop/schema": "0.1.0-alpha.67",
|
|
37
37
|
"valibot": "^1.4.2"
|
|
38
38
|
},
|
|
39
39
|
"engines": {
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `cueloop dev`: open the TUI against an isolated dev home seeded once with a
|
|
3
|
+
* plan and a diff under this repo's project plus a standalone reply thread, so
|
|
4
|
+
* the Projects and Threads sidebar and the thread view are populated without a
|
|
5
|
+
* live agent. It never touches the real ~/.cueloop home.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
import { homedir, tmpdir } from "node:os";
|
|
9
|
+
import { join } from "node:path";
|
|
10
|
+
import { DaemonClient } from "@cueloop/daemon/client";
|
|
11
|
+
import { resolveWorkspace } from "@cueloop/daemon/review";
|
|
12
|
+
|
|
13
|
+
const SEED_PLAN = `# Read the repository
|
|
14
|
+
|
|
15
|
+
A seeded plan so \`cueloop dev\` always has a thread to open.
|
|
16
|
+
|
|
17
|
+
## Steps
|
|
18
|
+
- open the thread view
|
|
19
|
+
- move the cursor into the agent's text
|
|
20
|
+
- type to leave a comment
|
|
21
|
+
`;
|
|
22
|
+
|
|
23
|
+
const SEED_REPLY = `A standalone thought, not tied to any repository.
|
|
24
|
+
|
|
25
|
+
It lands under Threads in the sidebar rather than a project.
|
|
26
|
+
`;
|
|
27
|
+
|
|
28
|
+
const SEED_DIFF_PATH = "packages/client/src/theme.ts";
|
|
29
|
+
const SEED_DIFF_OLD = ' accent: "#f5a3a3",\n';
|
|
30
|
+
const SEED_DIFF_NEW = ' accent: "#cba6f7",\n';
|
|
31
|
+
const SEED_DIFF = `diff --git a/${SEED_DIFF_PATH} b/${SEED_DIFF_PATH}
|
|
32
|
+
--- a/${SEED_DIFF_PATH}
|
|
33
|
+
+++ b/${SEED_DIFF_PATH}
|
|
34
|
+
@@ -1 +1 @@
|
|
35
|
+
-${SEED_DIFF_OLD.trimEnd()}
|
|
36
|
+
+${SEED_DIFF_NEW.trimEnd()}
|
|
37
|
+
`;
|
|
38
|
+
|
|
39
|
+
async function seedDevSessions(client: DaemonClient): Promise<void> {
|
|
40
|
+
// the current repo carries a root commit, so its threads gather under a project
|
|
41
|
+
const project = await resolveWorkspace(process.cwd());
|
|
42
|
+
// a non-repo directory has no root commit, so its thread stays standalone
|
|
43
|
+
const standalone = await resolveWorkspace(tmpdir());
|
|
44
|
+
|
|
45
|
+
await client.sessionCreate(project, {
|
|
46
|
+
type: "plan",
|
|
47
|
+
content: SEED_PLAN,
|
|
48
|
+
meta: { title: "Read the repository" },
|
|
49
|
+
});
|
|
50
|
+
await client.sessionCreate(project, {
|
|
51
|
+
type: "diff",
|
|
52
|
+
content: SEED_DIFF,
|
|
53
|
+
meta: { title: "Review the accent change" },
|
|
54
|
+
files: [
|
|
55
|
+
{
|
|
56
|
+
path: SEED_DIFF_PATH,
|
|
57
|
+
oldContents: SEED_DIFF_OLD,
|
|
58
|
+
newContents: SEED_DIFF_NEW,
|
|
59
|
+
status: "modified",
|
|
60
|
+
},
|
|
61
|
+
],
|
|
62
|
+
});
|
|
63
|
+
await client.sessionCreate(standalone, {
|
|
64
|
+
type: "reply",
|
|
65
|
+
content: SEED_REPLY,
|
|
66
|
+
meta: { title: "A standalone thought" },
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** `cueloop dev`: seed an isolated dev home once, then open the TUI on it. */
|
|
71
|
+
export async function devCommand(): Promise<number> {
|
|
72
|
+
process.env.CUELOOP_HOME ??= join(homedir(), ".cueloop-dev");
|
|
73
|
+
|
|
74
|
+
const client = await DaemonClient.connect({ autostart: true });
|
|
75
|
+
try {
|
|
76
|
+
const existing = await client.sessionList();
|
|
77
|
+
if (existing.length === 0) await seedDevSessions(client);
|
|
78
|
+
} finally {
|
|
79
|
+
client.close();
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
const { runClient } = await import("@cueloop/client");
|
|
83
|
+
|
|
84
|
+
return runClient({});
|
|
85
|
+
}
|
package/src/main.ts
CHANGED
|
@@ -116,6 +116,7 @@ const commandHandlers: CommandHandlers = {
|
|
|
116
116
|
refine: async (rest) => (await import("./refine-command")).refineCommand(rest),
|
|
117
117
|
review: (rest) => reviewEntry(rest),
|
|
118
118
|
"review-post": async (rest) => (await import("./pr")).reviewPostCommand(rest),
|
|
119
|
+
dev: async () => (await import("./dev-command")).devCommand(),
|
|
119
120
|
};
|
|
120
121
|
|
|
121
122
|
const versionAliases = new Set(["-v", "--version", "version"]);
|
|
@@ -346,6 +347,7 @@ function printHelp(): void {
|
|
|
346
347
|
" cueloop wake <id> [--harness codex --thread <id>] resume the agent with the verdict (spawn detached)",
|
|
347
348
|
" cueloop review-post <id> <pr> post a resolved session's verdict back to the PR",
|
|
348
349
|
" cueloop daemon run the daemon in the foreground",
|
|
350
|
+
" cueloop dev open the TUI on an isolated home seeded with example threads",
|
|
349
351
|
"",
|
|
350
352
|
" cueloop -v, --version print the installed version",
|
|
351
353
|
" cueloop -h, --help print this help",
|
|
@@ -64,6 +64,7 @@ function fakeClient(sessions: ReviewSession[]): SessionClient {
|
|
|
64
64
|
return fork;
|
|
65
65
|
}),
|
|
66
66
|
sessionSetViewed: unimplemented("sessionSetViewed"),
|
|
67
|
+
sessionSetTitle: unimplemented("sessionSetTitle"),
|
|
67
68
|
sessionSetShareId: mock(async (id: string, shareId: string) => {
|
|
68
69
|
const session = sessions.find((candidate) => candidate.id === id)!;
|
|
69
70
|
|