taskplane 0.2.8 → 0.3.0
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 +19 -1
- package/bin/taskplane.mjs +278 -8
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -19,7 +19,24 @@ Taskplane turns your coding project into an AI-managed task board. You define ta
|
|
|
19
19
|
|
|
20
20
|
## Install
|
|
21
21
|
|
|
22
|
-
Taskplane is a [pi package](https://github.com/badlogic/pi-mono). You need [Node.js](https://nodejs.org/) ≥
|
|
22
|
+
Taskplane is a [pi package](https://github.com/badlogic/pi-mono). You need [Node.js](https://nodejs.org/) ≥ 22 and [pi](https://github.com/badlogic/pi-mono) installed first.
|
|
23
|
+
|
|
24
|
+
### Prerequisites
|
|
25
|
+
|
|
26
|
+
| Dependency | Required | Notes |
|
|
27
|
+
|-----------|----------|-------|
|
|
28
|
+
| [Node.js](https://nodejs.org/) ≥ 22 | Yes | Runtime |
|
|
29
|
+
| [pi](https://github.com/badlogic/pi-mono) | Yes | Agent framework |
|
|
30
|
+
| [Git](https://git-scm.com/) | Yes | Version control, worktrees |
|
|
31
|
+
| **tmux** | **Strongly recommended** | Required for `/orch` parallel execution |
|
|
32
|
+
|
|
33
|
+
**tmux** is needed for the orchestrator to spawn parallel worker sessions. Without it, `/orch` will not work. On Windows, Taskplane can install it for you:
|
|
34
|
+
|
|
35
|
+
```bash
|
|
36
|
+
taskplane install-tmux
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
On macOS: `brew install tmux` · On Linux: `sudo apt install tmux` (or your distro's package manager)
|
|
23
40
|
|
|
24
41
|
### Option A: Global Install (all projects)
|
|
25
42
|
|
|
@@ -138,6 +155,7 @@ Orchestrator lanes execute tasks through task-runner under the hood, so `/task`
|
|
|
138
155
|
|---------|-------------|
|
|
139
156
|
| `taskplane init` | Scaffold project config (interactive or `--preset`) |
|
|
140
157
|
| `taskplane doctor` | Validate installation and config |
|
|
158
|
+
| `taskplane install-tmux` | Install or upgrade tmux for Git Bash (Windows) |
|
|
141
159
|
| `taskplane version` | Show version info |
|
|
142
160
|
| `taskplane dashboard` | Launch the web dashboard |
|
|
143
161
|
| `taskplane uninstall` | Remove Taskplane project files and optionally uninstall package (`--package`) |
|
package/bin/taskplane.mjs
CHANGED
|
@@ -10,6 +10,18 @@
|
|
|
10
10
|
* and auto-discovered by pi. This CLI is for everything else.
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
+
// ─── Node.js version gate (fail fast) ───────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
const MIN_NODE_MAJOR = 22;
|
|
16
|
+
const nodeMajor = parseInt(process.versions.node.split(".")[0], 10);
|
|
17
|
+
if (nodeMajor < MIN_NODE_MAJOR) {
|
|
18
|
+
console.error(
|
|
19
|
+
`\x1b[31m❌ Taskplane requires Node.js >= ${MIN_NODE_MAJOR}.0.0 (found ${process.versions.node}).\x1b[0m\n` +
|
|
20
|
+
` Upgrade: https://nodejs.org/\n`
|
|
21
|
+
);
|
|
22
|
+
process.exit(1);
|
|
23
|
+
}
|
|
24
|
+
|
|
13
25
|
import fs from "node:fs";
|
|
14
26
|
import path from "node:path";
|
|
15
27
|
import readline from "node:readline";
|
|
@@ -992,6 +1004,251 @@ function parseWorkspaceYaml(raw) {
|
|
|
992
1004
|
return result;
|
|
993
1005
|
}
|
|
994
1006
|
|
|
1007
|
+
// ─── install-tmux ───────────────────────────────────────────────────────────
|
|
1008
|
+
|
|
1009
|
+
/**
|
|
1010
|
+
* Install or upgrade tmux for Git Bash on Windows.
|
|
1011
|
+
*
|
|
1012
|
+
* Downloads tmux and libevent packages from the official MSYS2 package
|
|
1013
|
+
* repository, extracts the required binaries, and places them in ~/bin/.
|
|
1014
|
+
*
|
|
1015
|
+
* Requirements:
|
|
1016
|
+
* - Windows with Git Bash (provides tar and msys-2.0.dll runtime)
|
|
1017
|
+
* - Node.js >= 21.7 (native zstd decompression)
|
|
1018
|
+
*
|
|
1019
|
+
* The install target is ~/bin/ because:
|
|
1020
|
+
* - It's user-writable (no admin rights needed)
|
|
1021
|
+
* - Git Bash includes it in PATH by default
|
|
1022
|
+
* - It doesn't conflict with Git's own /usr/bin/
|
|
1023
|
+
*/
|
|
1024
|
+
|
|
1025
|
+
const TMUX_PACKAGES = [
|
|
1026
|
+
{
|
|
1027
|
+
name: "tmux",
|
|
1028
|
+
url: "https://mirror.msys2.org/msys/x86_64/tmux-3.6.a-1-x86_64.pkg.tar.zst",
|
|
1029
|
+
version: "3.6a",
|
|
1030
|
+
files: ["usr/bin/tmux.exe"],
|
|
1031
|
+
},
|
|
1032
|
+
{
|
|
1033
|
+
name: "libevent",
|
|
1034
|
+
url: "https://mirror.msys2.org/msys/x86_64/libevent-2.1.12-4-x86_64.pkg.tar.zst",
|
|
1035
|
+
version: "2.1.12",
|
|
1036
|
+
files: ["usr/bin/msys-event-2-1-7.dll", "usr/bin/msys-event_core-2-1-7.dll"],
|
|
1037
|
+
},
|
|
1038
|
+
];
|
|
1039
|
+
|
|
1040
|
+
const TMUX_INSTALL_DIR_NAME = "bin";
|
|
1041
|
+
|
|
1042
|
+
function getTmuxInstallDir() {
|
|
1043
|
+
return path.join(process.env.HOME || process.env.USERPROFILE || "", TMUX_INSTALL_DIR_NAME);
|
|
1044
|
+
}
|
|
1045
|
+
|
|
1046
|
+
function detectCurrentTmux() {
|
|
1047
|
+
try {
|
|
1048
|
+
const out = execSync("tmux -V", { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"] }).trim();
|
|
1049
|
+
const match = out.match(/tmux\s+([\d.]+\w*)/);
|
|
1050
|
+
const version = match ? match[1] : "unknown";
|
|
1051
|
+
|
|
1052
|
+
// Find where tmux lives
|
|
1053
|
+
let location = "";
|
|
1054
|
+
try {
|
|
1055
|
+
location = execSync("which tmux", { encoding: "utf-8", timeout: 5000, stdio: ["pipe", "pipe", "pipe"], shell: "C:/Program Files/Git/bin/bash.exe" }).trim();
|
|
1056
|
+
} catch { /* ignore */ }
|
|
1057
|
+
|
|
1058
|
+
return { installed: true, version, location };
|
|
1059
|
+
} catch {
|
|
1060
|
+
return { installed: false, version: null, location: null };
|
|
1061
|
+
}
|
|
1062
|
+
}
|
|
1063
|
+
|
|
1064
|
+
async function httpFollowRedirects(url) {
|
|
1065
|
+
const https = await import("node:https");
|
|
1066
|
+
const http = await import("node:http");
|
|
1067
|
+
|
|
1068
|
+
return new Promise((resolve, reject) => {
|
|
1069
|
+
const mod = url.startsWith("https") ? https.default : http.default;
|
|
1070
|
+
mod.get(url, { headers: { "User-Agent": "taskplane" } }, (res) => {
|
|
1071
|
+
if (res.statusCode >= 300 && res.statusCode < 400 && res.headers.location) {
|
|
1072
|
+
return httpFollowRedirects(res.headers.location).then(resolve, reject);
|
|
1073
|
+
}
|
|
1074
|
+
if (res.statusCode !== 200) {
|
|
1075
|
+
return reject(new Error(`HTTP ${res.statusCode} for ${url}`));
|
|
1076
|
+
}
|
|
1077
|
+
const chunks = [];
|
|
1078
|
+
res.on("data", (chunk) => chunks.push(chunk));
|
|
1079
|
+
res.on("end", () => resolve(Buffer.concat(chunks)));
|
|
1080
|
+
res.on("error", reject);
|
|
1081
|
+
}).on("error", reject);
|
|
1082
|
+
});
|
|
1083
|
+
}
|
|
1084
|
+
|
|
1085
|
+
function toPosixPath(p) {
|
|
1086
|
+
return p.replace(/\\/g, "/").replace(/^([A-Z]):/i, (_m, d) => "/" + d.toLowerCase());
|
|
1087
|
+
}
|
|
1088
|
+
|
|
1089
|
+
async function cmdInstallTmux(args) {
|
|
1090
|
+
const checkOnly = args.includes("--check");
|
|
1091
|
+
const force = args.includes("--force");
|
|
1092
|
+
|
|
1093
|
+
console.log(`\n${c.bold}Taskplane — tmux installer${c.reset}\n`);
|
|
1094
|
+
|
|
1095
|
+
// ── Platform check ───────────────────────────────────────────
|
|
1096
|
+
if (process.platform !== "win32") {
|
|
1097
|
+
console.log(` ${INFO} This command is for Windows only.`);
|
|
1098
|
+
console.log(` On macOS: ${c.cyan}brew install tmux${c.reset}`);
|
|
1099
|
+
console.log(` On Linux: ${c.cyan}sudo apt install tmux${c.reset} (or your distro's package manager)\n`);
|
|
1100
|
+
return;
|
|
1101
|
+
}
|
|
1102
|
+
|
|
1103
|
+
// ── Node.js version check (need >= 21.7 for zstd) ───────────
|
|
1104
|
+
const [nodeMajor, nodeMinor] = process.versions.node.split(".").map(Number);
|
|
1105
|
+
if (nodeMajor < 21 || (nodeMajor === 21 && nodeMinor < 7)) {
|
|
1106
|
+
die(`Node.js >= 21.7 required for zstd decompression (found ${process.versions.node}).\n Upgrade Node.js: https://nodejs.org/`);
|
|
1107
|
+
}
|
|
1108
|
+
|
|
1109
|
+
// ── Git Bash check ───────────────────────────────────────────
|
|
1110
|
+
const gitBashBin = "C:/Program Files/Git/bin/bash.exe";
|
|
1111
|
+
if (!fs.existsSync(gitBashBin)) {
|
|
1112
|
+
die(`Git Bash not found at ${gitBashBin}.\n Install Git for Windows: https://git-scm.com/downloads`);
|
|
1113
|
+
}
|
|
1114
|
+
|
|
1115
|
+
// ── MSYS2 runtime check ──────────────────────────────────────
|
|
1116
|
+
const msysDll = "C:/Program Files/Git/usr/bin/msys-2.0.dll";
|
|
1117
|
+
if (!fs.existsSync(msysDll)) {
|
|
1118
|
+
die(`MSYS2 runtime (msys-2.0.dll) not found.\n This should ship with Git for Windows. Reinstall Git if missing.`);
|
|
1119
|
+
}
|
|
1120
|
+
|
|
1121
|
+
// ── Current tmux status ──────────────────────────────────────
|
|
1122
|
+
const current = detectCurrentTmux();
|
|
1123
|
+
if (current.installed) {
|
|
1124
|
+
console.log(` ${OK} tmux ${c.bold}${current.version}${c.reset} found`);
|
|
1125
|
+
if (current.location) {
|
|
1126
|
+
console.log(` Location: ${c.dim}${current.location}${c.reset}`);
|
|
1127
|
+
}
|
|
1128
|
+
} else {
|
|
1129
|
+
console.log(` ${FAIL} tmux not found`);
|
|
1130
|
+
}
|
|
1131
|
+
|
|
1132
|
+
const targetVersion = TMUX_PACKAGES[0].version;
|
|
1133
|
+
console.log(` ${INFO} Available version: ${c.bold}${targetVersion}${c.reset} (MSYS2 package)\n`);
|
|
1134
|
+
|
|
1135
|
+
if (checkOnly) return;
|
|
1136
|
+
|
|
1137
|
+
// ── Skip if already up to date ───────────────────────────────
|
|
1138
|
+
if (current.installed && current.version === targetVersion && !force) {
|
|
1139
|
+
console.log(` ${OK} Already up to date. Use ${c.cyan}--force${c.reset} to reinstall.\n`);
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
|
|
1143
|
+
// ── Download and extract ─────────────────────────────────────
|
|
1144
|
+
const zlib = await import("node:zlib");
|
|
1145
|
+
const os = await import("node:os");
|
|
1146
|
+
const tmpDir = os.default.tmpdir();
|
|
1147
|
+
const extractDir = path.join(tmpDir, "taskplane-tmux-install");
|
|
1148
|
+
|
|
1149
|
+
// Clean previous extract
|
|
1150
|
+
fs.rmSync(extractDir, { recursive: true, force: true });
|
|
1151
|
+
fs.mkdirSync(extractDir, { recursive: true });
|
|
1152
|
+
|
|
1153
|
+
for (const pkg of TMUX_PACKAGES) {
|
|
1154
|
+
process.stdout.write(` ⏳ Downloading ${pkg.name} (v${pkg.version})...`);
|
|
1155
|
+
let buf;
|
|
1156
|
+
try {
|
|
1157
|
+
buf = await httpFollowRedirects(pkg.url);
|
|
1158
|
+
} catch (err) {
|
|
1159
|
+
console.log(` ${c.red}failed${c.reset}`);
|
|
1160
|
+
die(`Download failed: ${err.message}\n URL: ${pkg.url}`);
|
|
1161
|
+
}
|
|
1162
|
+
console.log(` ${c.green}${Math.round(buf.length / 1024)}KB${c.reset}`);
|
|
1163
|
+
|
|
1164
|
+
// Decompress zstd → tar
|
|
1165
|
+
let tar;
|
|
1166
|
+
try {
|
|
1167
|
+
tar = zlib.default.zstdDecompressSync(buf);
|
|
1168
|
+
} catch (err) {
|
|
1169
|
+
die(`zstd decompression failed for ${pkg.name}: ${err.message}`);
|
|
1170
|
+
}
|
|
1171
|
+
const tarPath = path.join(tmpDir, `${pkg.name}.pkg.tar`);
|
|
1172
|
+
fs.writeFileSync(tarPath, tar);
|
|
1173
|
+
|
|
1174
|
+
// Extract needed files
|
|
1175
|
+
const posixTar = toPosixPath(tarPath);
|
|
1176
|
+
const posixExtract = toPosixPath(extractDir);
|
|
1177
|
+
for (const f of pkg.files) {
|
|
1178
|
+
try {
|
|
1179
|
+
execSync(`tar xf "${posixTar}" -C "${posixExtract}" ${f}`, {
|
|
1180
|
+
shell: gitBashBin,
|
|
1181
|
+
timeout: 10000,
|
|
1182
|
+
stdio: ["pipe", "pipe", "pipe"],
|
|
1183
|
+
});
|
|
1184
|
+
} catch (err) {
|
|
1185
|
+
die(`Failed to extract ${f} from ${pkg.name}: ${err.message}`);
|
|
1186
|
+
}
|
|
1187
|
+
}
|
|
1188
|
+
|
|
1189
|
+
// Clean up tar
|
|
1190
|
+
try { fs.unlinkSync(tarPath); } catch { /* best effort */ }
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1193
|
+
// ── Install to ~/bin/ ────────────────────────────────────────
|
|
1194
|
+
const installDir = getTmuxInstallDir();
|
|
1195
|
+
fs.mkdirSync(installDir, { recursive: true });
|
|
1196
|
+
|
|
1197
|
+
const extractBinDir = path.join(extractDir, "usr", "bin");
|
|
1198
|
+
const installedFiles = [];
|
|
1199
|
+
const lockedFiles = [];
|
|
1200
|
+
for (const f of fs.readdirSync(extractBinDir)) {
|
|
1201
|
+
const src = path.join(extractBinDir, f);
|
|
1202
|
+
const dest = path.join(installDir, f);
|
|
1203
|
+
try {
|
|
1204
|
+
fs.copyFileSync(src, dest);
|
|
1205
|
+
installedFiles.push(f);
|
|
1206
|
+
} catch (err) {
|
|
1207
|
+
if (err.code === "EBUSY" || err.code === "EPERM") {
|
|
1208
|
+
// File is locked (e.g., DLL in use by running tmux session).
|
|
1209
|
+
// Try rename-then-copy: rename old file, copy new, delete old.
|
|
1210
|
+
const backup = dest + ".old";
|
|
1211
|
+
try {
|
|
1212
|
+
if (fs.existsSync(backup)) fs.unlinkSync(backup);
|
|
1213
|
+
fs.renameSync(dest, backup);
|
|
1214
|
+
fs.copyFileSync(src, dest);
|
|
1215
|
+
try { fs.unlinkSync(backup); } catch { /* clean up later */ }
|
|
1216
|
+
installedFiles.push(f);
|
|
1217
|
+
} catch {
|
|
1218
|
+
lockedFiles.push(f);
|
|
1219
|
+
}
|
|
1220
|
+
} else {
|
|
1221
|
+
throw err;
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
}
|
|
1225
|
+
|
|
1226
|
+
// Clean up extract dir
|
|
1227
|
+
fs.rmSync(extractDir, { recursive: true, force: true });
|
|
1228
|
+
|
|
1229
|
+
// ── Verify ───────────────────────────────────────────────────
|
|
1230
|
+
console.log("");
|
|
1231
|
+
if (lockedFiles.length > 0) {
|
|
1232
|
+
console.log(` ${WARN} Some files are locked (tmux may be running): ${lockedFiles.join(", ")}`);
|
|
1233
|
+
console.log(` Close all tmux sessions and re-run ${c.cyan}taskplane install-tmux --force${c.reset}`);
|
|
1234
|
+
if (installedFiles.length > 0) {
|
|
1235
|
+
console.log(` Updated: ${installedFiles.join(", ")}`);
|
|
1236
|
+
}
|
|
1237
|
+
} else {
|
|
1238
|
+
const verify = detectCurrentTmux();
|
|
1239
|
+
if (verify.installed) {
|
|
1240
|
+
console.log(` ${OK} tmux ${c.bold}${verify.version}${c.reset} installed successfully`);
|
|
1241
|
+
console.log(` Location: ${c.dim}${installDir}${c.reset}`);
|
|
1242
|
+
console.log(` Files: ${installedFiles.join(", ")}`);
|
|
1243
|
+
} else {
|
|
1244
|
+
console.log(` ${WARN} Files installed to ${installDir} but tmux not found on PATH.`);
|
|
1245
|
+
console.log(` Ensure ${c.cyan}~/bin${c.reset} is in your PATH. In Git Bash, add to ~/.bashrc:`);
|
|
1246
|
+
console.log(` ${c.dim}export PATH="$HOME/bin:$PATH"${c.reset}`);
|
|
1247
|
+
}
|
|
1248
|
+
}
|
|
1249
|
+
console.log("");
|
|
1250
|
+
}
|
|
1251
|
+
|
|
995
1252
|
// ─── doctor ─────────────────────────────────────────────────────────────────
|
|
996
1253
|
|
|
997
1254
|
function cmdDoctor() {
|
|
@@ -1004,10 +1261,10 @@ function cmdDoctor() {
|
|
|
1004
1261
|
const checks = [
|
|
1005
1262
|
{ label: "pi installed", check: () => commandExists("pi"), detail: () => getVersion("pi") },
|
|
1006
1263
|
{
|
|
1007
|
-
label: "Node.js >=
|
|
1264
|
+
label: "Node.js >= 22.0.0",
|
|
1008
1265
|
check: () => {
|
|
1009
1266
|
const v = process.versions.node;
|
|
1010
|
-
return parseInt(v.split(".")[0]) >=
|
|
1267
|
+
return parseInt(v.split(".")[0]) >= 22;
|
|
1011
1268
|
},
|
|
1012
1269
|
detail: () => `v${process.versions.node}`,
|
|
1013
1270
|
},
|
|
@@ -1026,6 +1283,9 @@ function cmdDoctor() {
|
|
|
1026
1283
|
console.log(
|
|
1027
1284
|
` ${hasTmux ? OK : `${WARN}`} tmux installed${hasTmux ? ` ${c.dim}(${getVersion("tmux", "-V")})${c.reset}` : ` ${c.dim}(optional — needed for spawn_mode: tmux)${c.reset}`}`
|
|
1028
1285
|
);
|
|
1286
|
+
if (!hasTmux && process.platform === "win32") {
|
|
1287
|
+
console.log(` ${c.dim}→ Run ${c.cyan}taskplane install-tmux${c.dim} to install${c.reset}`);
|
|
1288
|
+
}
|
|
1029
1289
|
|
|
1030
1290
|
// Check package installation
|
|
1031
1291
|
const pkgJson = path.join(PACKAGE_ROOT, "package.json");
|
|
@@ -1272,12 +1532,13 @@ ${c.bold}Usage:${c.reset}
|
|
|
1272
1532
|
taskplane <command> [options]
|
|
1273
1533
|
|
|
1274
1534
|
${c.bold}Commands:${c.reset}
|
|
1275
|
-
${c.cyan}init${c.reset}
|
|
1276
|
-
${c.cyan}doctor${c.reset}
|
|
1277
|
-
${c.cyan}
|
|
1278
|
-
${c.cyan}
|
|
1279
|
-
${c.cyan}
|
|
1280
|
-
${c.cyan}
|
|
1535
|
+
${c.cyan}init${c.reset} Scaffold Taskplane config in the current project
|
|
1536
|
+
${c.cyan}doctor${c.reset} Validate installation and project configuration
|
|
1537
|
+
${c.cyan}install-tmux${c.reset} Install or upgrade tmux for Git Bash (Windows)
|
|
1538
|
+
${c.cyan}version${c.reset} Show version information
|
|
1539
|
+
${c.cyan}dashboard${c.reset} Launch the web-based orchestrator dashboard
|
|
1540
|
+
${c.cyan}uninstall${c.reset} Remove Taskplane project files and/or package install
|
|
1541
|
+
${c.cyan}help${c.reset} Show this help message
|
|
1281
1542
|
|
|
1282
1543
|
${c.bold}Init options:${c.reset}
|
|
1283
1544
|
--preset <name> Use a preset: minimal, full, runner-only
|
|
@@ -1301,7 +1562,13 @@ ${c.bold}Uninstall options:${c.reset}
|
|
|
1301
1562
|
--remove-tasks Also remove task area directories from task-runner.yaml
|
|
1302
1563
|
--all Equivalent to --package + --remove-tasks
|
|
1303
1564
|
|
|
1565
|
+
${c.bold}Install-tmux options:${c.reset}
|
|
1566
|
+
--check Check tmux status without installing
|
|
1567
|
+
--force Reinstall even if tmux is already present
|
|
1568
|
+
|
|
1304
1569
|
${c.bold}Examples:${c.reset}
|
|
1570
|
+
taskplane install-tmux # Install or upgrade tmux
|
|
1571
|
+
taskplane install-tmux --check # Check tmux status only
|
|
1305
1572
|
taskplane init # Interactive project setup
|
|
1306
1573
|
taskplane init --preset full # Quick setup with defaults
|
|
1307
1574
|
taskplane init --preset full --tasks-root docs/task-management
|
|
@@ -1333,6 +1600,9 @@ switch (command) {
|
|
|
1333
1600
|
case "doctor":
|
|
1334
1601
|
cmdDoctor();
|
|
1335
1602
|
break;
|
|
1603
|
+
case "install-tmux":
|
|
1604
|
+
await cmdInstallTmux(args);
|
|
1605
|
+
break;
|
|
1336
1606
|
case "version":
|
|
1337
1607
|
case "--version":
|
|
1338
1608
|
case "-v":
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "taskplane",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "AI agent orchestration for pi — parallel task execution with checkpoint discipline",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pi-package",
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"type": "module",
|
|
26
26
|
"engines": {
|
|
27
|
-
"node": ">=
|
|
27
|
+
"node": ">=22.0.0"
|
|
28
28
|
},
|
|
29
29
|
"files": [
|
|
30
30
|
"bin/",
|