ideawave 0.0.103 → 0.0.106

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 CHANGED
@@ -1,41 +1,19 @@
1
- # IdeaWave CLI
1
+ # IdeaWave TUI
2
2
 
3
- Run local coding agents from an IdeaWave board.
3
+ Connect your local AI coding agents to a collaborative [IdeaWave](https://ideawave.app) board.
4
4
 
5
- ```bash
6
- npx --yes ideawave@latest
7
- ```
8
-
9
- Then open [ideawave.app](https://ideawave.app), choose a board, and start an agent run.
10
-
11
- ## Requirements
5
+ ## Get started
12
6
 
13
- - Node.js 18 or newer
14
- - Google Chrome for screenshot capture. Browser cards stay inside the app
15
- iframe and use the CLI's local browser-kit proxy.
16
- - At least one supported agent runtime installed and signed in:
17
- - Claude Code
18
- - Codex CLI
19
- - GitHub Copilot CLI
20
- - OpenCode
21
-
22
- ## Commands
7
+ Install and sign in to a supported agent such as Claude Code, Codex, GitHub
8
+ Copilot, or OpenCode. Then launch IdeaWave:
23
9
 
24
10
  ```bash
25
- npx --yes ideawave@latest --dev
26
- npx ideawave --help
27
- npx ideawave --version
11
+ npx --yes ideawave@latest
12
+ # or
13
+ bunx ideawave@latest
28
14
  ```
29
15
 
30
- ## Troubleshooting
31
-
32
- If a runtime appears unavailable, confirm its command is on your `PATH` and that you are signed in to that tool.
33
-
34
- For supported runtimes, the CLI fetches small ACP bridge packages on first use. npm caches them, so later runs are fast. If npm's cache was cleared, keep the CLI running and retry after the bridge downloads again.
16
+ Keep the TUI running, open [ideawave.app](https://ideawave.app), and start
17
+ working with your agent directly on the board.
35
18
 
36
- The CLI advertises `browser-proxy-v6` and `browser-dom-snapshot-v1` so browser
37
- cards can share one local browser profile, route pages and subresources through
38
- the local browser-kit proxy, and publish a sanitized read-only fallback for
39
- collaborators. The normal command
40
- keeps screenshot capture available. `--dev` skips screenshot-engine setup and
41
- allows Railway PR previews for browser-card development.
19
+ Requires Node.js 22 or newer. Available for macOS, Linux, and Windows.
@@ -0,0 +1,154 @@
1
+ #!/usr/bin/env node
2
+ import { spawn } from "node:child_process";
3
+ import { accessSync, constants, readFileSync } from "node:fs";
4
+ import { createRequire } from "node:module";
5
+ import path from "node:path";
6
+ import { fileURLToPath } from "node:url";
7
+ import { isPathInside, launcherRuntimeError } from "./launcher-core.mjs";
8
+ import { detectLinuxLibc, resolveHostTarget } from "./platform.mjs";
9
+
10
+ const require = createRequire(import.meta.url);
11
+ const packageRoot = fileURLToPath(new URL("..", import.meta.url));
12
+
13
+ function fail(message) {
14
+ process.stderr.write(`${message}\n`);
15
+ process.exitCode = 1;
16
+ }
17
+
18
+ function readManifest(filename, label) {
19
+ try {
20
+ const value = JSON.parse(readFileSync(filename, "utf8"));
21
+ if (!value || typeof value !== "object") throw new Error("not an object");
22
+ return value;
23
+ } catch (error) {
24
+ throw new Error(`${label} manifest is unreadable at ${filename}: ${String(error)}`);
25
+ }
26
+ }
27
+
28
+ function resolveDistribution() {
29
+ const manifest = readManifest(path.join(packageRoot, "package.json"), "IdeaWave launcher");
30
+ if (manifest.name !== "ideawave" || typeof manifest.version !== "string" || !manifest.version) {
31
+ throw new Error("IdeaWave launcher manifest has an invalid package name or version. Reinstall IdeaWave.");
32
+ }
33
+
34
+ const libc = process.platform === "linux" ? detectLinuxLibc() : null;
35
+ const target = resolveHostTarget({
36
+ platform: process.platform,
37
+ architecture: process.arch,
38
+ libc,
39
+ });
40
+ if (!target) {
41
+ const tuple =
42
+ process.platform === "linux"
43
+ ? `${process.platform}/${process.arch}/${libc ?? "unknown-libc"}`
44
+ : `${process.platform}/${process.arch}`;
45
+ throw new Error(
46
+ `IdeaWave does not have a native host for ${tuple}. Supported targets are macOS and Linux glibc/musl on x64 or arm64, and Windows on x64.`,
47
+ );
48
+ }
49
+
50
+ let hostManifestPath;
51
+ try {
52
+ hostManifestPath = require.resolve(`${target.packageName}/package.json`);
53
+ } catch {
54
+ throw new Error(
55
+ `IdeaWave's ${target.key} host package is missing (expected ${target.packageName}@${manifest.version}). ` +
56
+ `Reinstall with optional dependencies enabled, for example \`npm install ideawave@${manifest.version} --include=optional\`.`,
57
+ );
58
+ }
59
+ const hostManifest = readManifest(hostManifestPath, `IdeaWave ${target.key} host`);
60
+ if (hostManifest.name !== target.packageName) {
61
+ throw new Error(
62
+ `IdeaWave host package mismatch: expected ${target.packageName}, found ${hostManifest.name ?? "an unnamed package"}. Reinstall IdeaWave.`,
63
+ );
64
+ }
65
+ if (hostManifest.version !== manifest.version) {
66
+ throw new Error(
67
+ `IdeaWave host version mismatch: launcher ${manifest.version}, host ${hostManifest.version ?? "unknown"}. ` +
68
+ "Clear the package-runner cache and reinstall IdeaWave.",
69
+ );
70
+ }
71
+
72
+ const hostRoot = path.dirname(hostManifestPath);
73
+ const executable = path.resolve(hostRoot, ...target.executable.split("/"));
74
+ if (!isPathInside(hostRoot, executable)) {
75
+ throw new Error(`IdeaWave host package ${target.packageName} declared an unsafe executable path.`);
76
+ }
77
+ try {
78
+ accessSync(executable, process.platform === "win32" ? constants.F_OK : constants.X_OK);
79
+ } catch {
80
+ throw new Error(`IdeaWave's native host is missing or not executable at ${executable}. Reinstall IdeaWave.`);
81
+ }
82
+
83
+ let playwrightManifestPath;
84
+ try {
85
+ playwrightManifestPath = require.resolve("playwright-core/package.json");
86
+ } catch {
87
+ throw new Error("IdeaWave's Playwright runtime sidecar is missing. Reinstall IdeaWave.");
88
+ }
89
+ const playwrightManifest = readManifest(playwrightManifestPath, "IdeaWave Playwright sidecar");
90
+ const expectedPlaywright = manifest.dependencies?.["playwright-core"];
91
+ if (typeof expectedPlaywright !== "string" || playwrightManifest.version !== expectedPlaywright) {
92
+ throw new Error(
93
+ `IdeaWave Playwright sidecar mismatch: expected ${expectedPlaywright ?? "an exact pinned version"}, ` +
94
+ `found ${playwrightManifest.version ?? "unknown"}. Reinstall IdeaWave.`,
95
+ );
96
+ }
97
+
98
+ return {
99
+ executable,
100
+ manifest,
101
+ playwrightRoot: path.dirname(playwrightManifestPath),
102
+ target,
103
+ };
104
+ }
105
+
106
+ const runtimeError = launcherRuntimeError();
107
+ if (runtimeError) {
108
+ fail(runtimeError);
109
+ } else {
110
+ try {
111
+ const distribution = resolveDistribution();
112
+ const child = spawn(distribution.executable, process.argv.slice(2), {
113
+ cwd: process.cwd(),
114
+ stdio: "inherit",
115
+ env: {
116
+ ...process.env,
117
+ IDEAWAVE_DISTRIBUTION_MODE: "standalone",
118
+ IDEAWAVE_LAUNCHER_NODE_PATH: process.execPath,
119
+ IDEAWAVE_LAUNCHER_NODE_VERSION: process.version,
120
+ IDEAWAVE_PLAYWRIGHT_CORE_PATH: distribution.playwrightRoot,
121
+ IDEAWAVE_PRODUCT_VERSION: distribution.manifest.version,
122
+ },
123
+ });
124
+
125
+ const signalHandlers = new Map();
126
+ for (const signal of ["SIGINT", "SIGTERM", "SIGHUP"]) {
127
+ if (process.platform === "win32" && signal === "SIGHUP") continue;
128
+ const handler = () => {
129
+ if (child.exitCode === null && child.signalCode === null) child.kill(signal);
130
+ };
131
+ signalHandlers.set(signal, handler);
132
+ process.on(signal, handler);
133
+ }
134
+ const removeSignalHandlers = () => {
135
+ for (const [signal, handler] of signalHandlers) process.removeListener(signal, handler);
136
+ signalHandlers.clear();
137
+ };
138
+
139
+ child.once("error", (error) => {
140
+ removeSignalHandlers();
141
+ fail(`IdeaWave failed to start its ${distribution.target.key} host: ${String(error)}`);
142
+ });
143
+ child.once("exit", (code, signal) => {
144
+ removeSignalHandlers();
145
+ if (signal && process.platform !== "win32") {
146
+ process.kill(process.pid, signal);
147
+ return;
148
+ }
149
+ process.exitCode = code ?? (signal ? 1 : 0);
150
+ });
151
+ } catch (error) {
152
+ fail(error instanceof Error ? error.message : String(error));
153
+ }
154
+ }
@@ -0,0 +1,35 @@
1
+ import path from "node:path";
2
+
3
+ export const MINIMUM_NODE_MAJOR = 22;
4
+
5
+ export function parseNodeMajor(version) {
6
+ const match = /^v?(\d+)(?:\.|$)/.exec(String(version));
7
+ return match ? Number(match[1]) : null;
8
+ }
9
+
10
+ /**
11
+ * @param {{ nodeVersion?: string, bunVersion?: string | null, runtimeName?: string } | undefined} options
12
+ */
13
+ export function launcherRuntimeError(options = {}) {
14
+ const {
15
+ nodeVersion = process.version,
16
+ bunVersion = process.versions?.bun,
17
+ runtimeName = process.release?.name,
18
+ } = options;
19
+ if (bunVersion) {
20
+ return "IdeaWave's launcher must run on Node.js, not Bun. Run `bunx ideawave` without `--bun`, or use `npx ideawave`.";
21
+ }
22
+ if (runtimeName !== "node") {
23
+ return `IdeaWave's launcher requires Node.js 22 or newer; detected ${runtimeName || "an unknown runtime"}.`;
24
+ }
25
+ const major = parseNodeMajor(nodeVersion);
26
+ if (major === null || major < MINIMUM_NODE_MAJOR) {
27
+ return `IdeaWave requires Node.js 22 or newer; this launcher is using ${nodeVersion || "an unknown version"}.`;
28
+ }
29
+ return null;
30
+ }
31
+
32
+ export function isPathInside(root, candidate) {
33
+ const relative = path.relative(path.resolve(root), path.resolve(candidate));
34
+ return relative !== "" && relative !== ".." && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative);
35
+ }
@@ -0,0 +1,100 @@
1
+ const host = (key, options) => Object.freeze({ key, ...options });
2
+
3
+ const HOSTS = Object.freeze({
4
+ "darwin-arm64": host("darwin-arm64", {
5
+ packageName: "ideawave-host-darwin-arm64",
6
+ bunTarget: "bun-darwin-arm64",
7
+ os: "darwin",
8
+ cpu: "arm64",
9
+ executable: "bin/ideawave-host",
10
+ }),
11
+ "darwin-x64": host("darwin-x64", {
12
+ packageName: "ideawave-host-darwin-x64",
13
+ bunTarget: "bun-darwin-x64-baseline",
14
+ os: "darwin",
15
+ cpu: "x64",
16
+ executable: "bin/ideawave-host",
17
+ }),
18
+ "linux-arm64-glibc": host("linux-arm64-glibc", {
19
+ packageName: "ideawave-host-linux-arm64",
20
+ bunTarget: "bun-linux-arm64",
21
+ os: "linux",
22
+ cpu: "arm64",
23
+ libc: "glibc",
24
+ executable: "bin/ideawave-host",
25
+ }),
26
+ "linux-arm64-musl": host("linux-arm64-musl", {
27
+ packageName: "ideawave-host-linux-arm64-musl",
28
+ bunTarget: "bun-linux-arm64-musl",
29
+ os: "linux",
30
+ cpu: "arm64",
31
+ libc: "musl",
32
+ executable: "bin/ideawave-host",
33
+ }),
34
+ "linux-x64-glibc": host("linux-x64-glibc", {
35
+ packageName: "ideawave-host-linux-x64",
36
+ bunTarget: "bun-linux-x64-baseline",
37
+ os: "linux",
38
+ cpu: "x64",
39
+ libc: "glibc",
40
+ executable: "bin/ideawave-host",
41
+ }),
42
+ "linux-x64-musl": host("linux-x64-musl", {
43
+ packageName: "ideawave-host-linux-x64-musl",
44
+ bunTarget: "bun-linux-x64-baseline-musl",
45
+ os: "linux",
46
+ cpu: "x64",
47
+ libc: "musl",
48
+ executable: "bin/ideawave-host",
49
+ }),
50
+ "win32-x64": host("win32-x64", {
51
+ packageName: "ideawave-host-windows",
52
+ bunTarget: "bun-windows-x64-baseline",
53
+ os: "win32",
54
+ cpu: "x64",
55
+ executable: "bin/ideawave-host.exe",
56
+ }),
57
+ });
58
+
59
+ export const SUPPORTED_HOSTS = HOSTS;
60
+
61
+ /**
62
+ * @param {{
63
+ * platform?: string,
64
+ * report?: { header?: Record<string, unknown> } | null,
65
+ * } | undefined} options
66
+ */
67
+ export function detectLinuxLibc(options = {}) {
68
+ const { platform = process.platform, report = undefined } = options;
69
+ if (platform !== "linux") return null;
70
+
71
+ let runtimeReport = report;
72
+ if (runtimeReport === undefined) {
73
+ try {
74
+ runtimeReport = process.report?.getReport();
75
+ } catch {
76
+ return null;
77
+ }
78
+ }
79
+ if (!runtimeReport || typeof runtimeReport !== "object") return null;
80
+
81
+ const header = runtimeReport.header;
82
+ if (!header || typeof header !== "object") return null;
83
+ if (typeof header.glibcVersionRuntime === "string" && header.glibcVersionRuntime) {
84
+ return "glibc";
85
+ }
86
+
87
+ // Node's Linux diagnostic report exposes glibcVersionRuntime only on glibc.
88
+ // A real Linux report with no such field is therefore a musl runtime. An
89
+ // absent/malformed report remains unknown instead of silently choosing musl.
90
+ return typeof header.nodejsVersion === "string" || typeof header.nodeVersion === "string" ? "musl" : null;
91
+ }
92
+
93
+ export function resolveHostTarget({
94
+ platform = process.platform,
95
+ architecture = process.arch,
96
+ libc = platform === "linux" ? detectLinuxLibc({ platform }) : null,
97
+ } = {}) {
98
+ const key = platform === "linux" ? `${platform}-${architecture}-${libc ?? "unknown"}` : `${platform}-${architecture}`;
99
+ return HOSTS[key] ?? null;
100
+ }
package/package.json CHANGED
@@ -1,44 +1,49 @@
1
1
  {
2
2
  "name": "ideawave",
3
- "version": "0.0.103",
4
- "description": "IdeaWave CLI",
3
+ "version": "0.0.106",
4
+ "description": "IdeaWave local agent host and terminal UI",
5
5
  "type": "module",
6
+ "license": "UNLICENSED",
6
7
  "bin": {
7
- "ideawave": "dist/index.mjs"
8
+ "ideawave": "bin/ideawave.mjs"
8
9
  },
9
10
  "files": [
10
- "dist/index.mjs",
11
+ "bin",
11
12
  "README.md"
12
13
  ],
14
+ "publishConfig": {
15
+ "access": "public"
16
+ },
13
17
  "engines": {
14
- "node": ">=18"
18
+ "node": ">=22"
15
19
  },
16
20
  "homepage": "https://ideawave.app",
17
21
  "repository": {
18
22
  "type": "git",
19
23
  "url": "git+https://github.com/LoopedIn-ai/ideawave-app.git",
20
- "directory": "apps/web/npm/ideawave"
24
+ "directory": "apps/tui"
21
25
  },
22
26
  "bugs": {
23
27
  "url": "https://github.com/LoopedIn-ai/ideawave-app/issues"
24
28
  },
25
29
  "keywords": [
26
30
  "ideawave",
27
- "cli",
31
+ "tui",
28
32
  "agent",
29
33
  "whiteboard",
30
- "mcp"
34
+ "mcp",
35
+ "acp"
31
36
  ],
32
- "license": "UNLICENSED",
33
37
  "dependencies": {
34
- "@agentclientprotocol/sdk": "^1.3.0",
35
- "@modelcontextprotocol/sdk": "^1.29.0",
36
- "css-tree": "^3.2.1",
37
- "playwright-core": "1.60.0",
38
- "ws": "^8.21.0",
39
- "zod": "^4.3.6"
38
+ "playwright-core": "1.62.1"
40
39
  },
41
- "publishConfig": {
42
- "access": "public"
40
+ "optionalDependencies": {
41
+ "ideawave-host-darwin-arm64": "0.0.106",
42
+ "ideawave-host-darwin-x64": "0.0.106",
43
+ "ideawave-host-linux-arm64": "0.0.106",
44
+ "ideawave-host-linux-arm64-musl": "0.0.106",
45
+ "ideawave-host-linux-x64": "0.0.106",
46
+ "ideawave-host-linux-x64-musl": "0.0.106",
47
+ "ideawave-host-windows": "0.0.106"
43
48
  }
44
49
  }