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 +11 -33
- package/bin/ideawave.mjs +154 -0
- package/bin/launcher-core.mjs +35 -0
- package/bin/platform.mjs +100 -0
- package/package.json +22 -17
- package/dist/index.mjs +0 -1174
package/README.md
CHANGED
|
@@ -1,41 +1,19 @@
|
|
|
1
|
-
# IdeaWave
|
|
1
|
+
# IdeaWave TUI
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Connect your local AI coding agents to a collaborative [IdeaWave](https://ideawave.app) board.
|
|
4
4
|
|
|
5
|
-
|
|
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
|
-
|
|
14
|
-
|
|
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
|
|
26
|
-
|
|
27
|
-
|
|
11
|
+
npx --yes ideawave@latest
|
|
12
|
+
# or
|
|
13
|
+
bunx ideawave@latest
|
|
28
14
|
```
|
|
29
15
|
|
|
30
|
-
|
|
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
|
-
|
|
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.
|
package/bin/ideawave.mjs
ADDED
|
@@ -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
|
+
}
|
package/bin/platform.mjs
ADDED
|
@@ -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.
|
|
4
|
-
"description": "IdeaWave
|
|
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": "
|
|
8
|
+
"ideawave": "bin/ideawave.mjs"
|
|
8
9
|
},
|
|
9
10
|
"files": [
|
|
10
|
-
"
|
|
11
|
+
"bin",
|
|
11
12
|
"README.md"
|
|
12
13
|
],
|
|
14
|
+
"publishConfig": {
|
|
15
|
+
"access": "public"
|
|
16
|
+
},
|
|
13
17
|
"engines": {
|
|
14
|
-
"node": ">=
|
|
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/
|
|
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
|
-
"
|
|
31
|
+
"tui",
|
|
28
32
|
"agent",
|
|
29
33
|
"whiteboard",
|
|
30
|
-
"mcp"
|
|
34
|
+
"mcp",
|
|
35
|
+
"acp"
|
|
31
36
|
],
|
|
32
|
-
"license": "UNLICENSED",
|
|
33
37
|
"dependencies": {
|
|
34
|
-
"
|
|
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
|
-
"
|
|
42
|
-
"
|
|
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
|
}
|