cueloop 0.1.0-alpha.66 → 0.1.0-alpha.68

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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cueloop",
3
- "version": "0.1.0-alpha.66",
3
+ "version": "0.1.0-alpha.68",
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.66",
34
- "@cueloop/client": "0.1.0-alpha.66",
35
- "@cueloop/daemon": "0.1.0-alpha.66",
36
- "@cueloop/schema": "0.1.0-alpha.66",
33
+ "@cueloop/adapters": "0.1.0-alpha.68",
34
+ "@cueloop/client": "0.1.0-alpha.68",
35
+ "@cueloop/daemon": "0.1.0-alpha.68",
36
+ "@cueloop/schema": "0.1.0-alpha.68",
37
37
  "valibot": "^1.4.2"
38
38
  },
39
39
  "engines": {
package/src/main.ts CHANGED
@@ -114,6 +114,7 @@ const commandHandlers: CommandHandlers = {
114
114
  wake: async (rest) => (await import("./wake-command")).wakeCommand(rest),
115
115
  actions: async (rest) => (await import("./actions-command")).actionsCommand(rest),
116
116
  refine: async (rest) => (await import("./refine-command")).refineCommand(rest),
117
+ update: async () => (await import("./update-command")).updateCommand(),
117
118
  review: (rest) => reviewEntry(rest),
118
119
  "review-post": async (rest) => (await import("./pr")).reviewPostCommand(rest),
119
120
  dev: async () => (await import("./dev-command")).devCommand(),
@@ -344,6 +345,7 @@ function printHelp(): void {
344
345
  " cueloop session <primitive> [flags] script the daemon (create|get|list|wait|annotate|remove|cut|restore|curate|set-viewed|navigate|branch|switch|label|fork|name-self|events|resolve|submit-revision)",
345
346
  " cueloop actions list list the quick-action vocabulary (for annotate --action)",
346
347
  " cueloop refine mine past reviews into a markdown report + writeback proposals",
348
+ " cueloop update update the installed cueloop binary",
347
349
  " cueloop wake <id> [--harness codex --thread <id>] resume the agent with the verdict (spawn detached)",
348
350
  " cueloop review-post <id> <pr> post a resolved session's verdict back to the PR",
349
351
  " cueloop daemon run the daemon in the foreground",
@@ -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
 
@@ -0,0 +1,82 @@
1
+ import { basename, dirname, isAbsolute, resolve } from "node:path";
2
+ import * as v from "valibot";
3
+
4
+ const INSTALL_URL = "https://cueloop.dev/install.sh";
5
+ const InstallerScriptSchema = v.pipe(
6
+ v.string(),
7
+ v.minLength(1),
8
+ v.check(
9
+ (script) => script.includes("CUELOOP_INSTALL_DIR"),
10
+ "installer is not a cueloop installer",
11
+ ),
12
+ );
13
+
14
+ function userBinInstallDir(): string | undefined {
15
+ if (process.env.HOME === undefined) return undefined;
16
+
17
+ return `${process.env.HOME}/.local/bin`;
18
+ }
19
+
20
+ function invokedBinaryInstallDir(): string | undefined {
21
+ const invokedPath = process.argv[1];
22
+ if (invokedPath === undefined || basename(invokedPath) !== "cueloop") return undefined;
23
+
24
+ return dirname(isAbsolute(invokedPath) ? invokedPath : resolve(invokedPath));
25
+ }
26
+
27
+ function defaultInstallDir(): string | undefined {
28
+ return invokedBinaryInstallDir() ?? userBinInstallDir();
29
+ }
30
+
31
+ function installDir(): string | undefined {
32
+ return process.env.CUELOOP_INSTALL_DIR || defaultInstallDir();
33
+ }
34
+
35
+ /** Re-run the published installer into the directory that holds this binary. */
36
+ export async function updateCommand(): Promise<number> {
37
+ const targetInstallDir = installDir();
38
+
39
+ if (targetInstallDir === undefined) {
40
+ console.error("cueloop update: HOME is not set and the current binary path is unknown");
41
+
42
+ return 1;
43
+ }
44
+ if (!targetInstallDir.startsWith("/")) {
45
+ console.error("cueloop update: CUELOOP_INSTALL_DIR must be an absolute path");
46
+
47
+ return 1;
48
+ }
49
+
50
+ try {
51
+ console.error(`updating cueloop in ${targetInstallDir}...`);
52
+ const response = await fetch(INSTALL_URL);
53
+
54
+ if (!response.ok) {
55
+ console.error(`cueloop update: failed to fetch installer (${response.status})`);
56
+
57
+ return 1;
58
+ }
59
+ const parsed = v.safeParse(InstallerScriptSchema, await response.text());
60
+
61
+ if (!parsed.success) {
62
+ console.error("cueloop update: fetched installer failed validation");
63
+
64
+ return 1;
65
+ }
66
+ const child = Bun.spawn(["sh"], {
67
+ stdin: "pipe",
68
+ stdout: "inherit",
69
+ stderr: "inherit",
70
+ env: { ...process.env, CUELOOP_INSTALL_DIR: targetInstallDir },
71
+ });
72
+
73
+ child.stdin.write(parsed.output);
74
+ child.stdin.end();
75
+
76
+ return child.exited;
77
+ } catch (error) {
78
+ console.error(`cueloop update: ${error instanceof Error ? error.message : String(error)}`);
79
+
80
+ return 1;
81
+ }
82
+ }