kandev 0.17.0 → 0.39.2
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 +24 -6
- package/dist/args.js +10 -6
- package/dist/cli.js +18 -13
- package/dist/run.js +67 -58
- package/dist/runtime.js +76 -0
- package/package.json +19 -2
- package/dist/update.js +0 -87
package/README.md
CHANGED
|
@@ -4,18 +4,36 @@ Manage tasks. Orchestrate agents. Review changes. Ship value.
|
|
|
4
4
|
|
|
5
5
|
## Quick Start
|
|
6
6
|
|
|
7
|
+
### Homebrew
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
brew install kdlbs/kandev/kandev
|
|
11
|
+
kandev
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
### NPX (requires npm 7+)
|
|
15
|
+
|
|
7
16
|
```bash
|
|
8
|
-
npx kandev
|
|
17
|
+
npx kandev@latest
|
|
9
18
|
```
|
|
10
19
|
|
|
11
|
-
|
|
20
|
+
Either install path resolves a platform-matched runtime (Go backend, agentctl, Next.js standalone web), launches the backend + web, and opens your browser. Data (worktrees, SQLite DB) is stored in `~/.kandev` by default.
|
|
12
21
|
|
|
13
22
|
## Version and Updates
|
|
14
23
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
-
|
|
18
|
-
-
|
|
24
|
+
The package manager owns the runtime version. `kandev@X.Y.Z` ships with the matching runtime.
|
|
25
|
+
|
|
26
|
+
- **Update via Homebrew**: `brew upgrade kandev`
|
|
27
|
+
- **Update via npm/npx**: `npx kandev@latest` or `npm install -g kandev@latest`
|
|
28
|
+
- **Print CLI version**: `kandev --version`
|
|
29
|
+
|
|
30
|
+
### Advanced: pin a specific runtime tag
|
|
31
|
+
|
|
32
|
+
`--runtime-version <tag>` downloads a specific GitHub release runtime instead of using the installed one. For debugging compatibility issues only:
|
|
33
|
+
|
|
34
|
+
```bash
|
|
35
|
+
kandev --runtime-version v0.16.0
|
|
36
|
+
```
|
|
19
37
|
|
|
20
38
|
## What You Get
|
|
21
39
|
|
package/dist/args.js
CHANGED
|
@@ -20,20 +20,24 @@ function parseArgs(argv) {
|
|
|
20
20
|
showHelp = true;
|
|
21
21
|
continue;
|
|
22
22
|
}
|
|
23
|
+
if (arg === "--version" || arg === "-V") {
|
|
24
|
+
opts.showVersion = true;
|
|
25
|
+
continue;
|
|
26
|
+
}
|
|
23
27
|
if (arg === "dev" || arg === "run" || arg === "start") {
|
|
24
28
|
opts.command = arg;
|
|
25
29
|
continue;
|
|
26
30
|
}
|
|
27
|
-
if (arg === "--version") {
|
|
28
|
-
opts.
|
|
31
|
+
if (arg === "--runtime-version") {
|
|
32
|
+
opts.runtimeVersion = takeValue(argv, i, "--runtime-version");
|
|
29
33
|
i += 1;
|
|
30
34
|
continue;
|
|
31
35
|
}
|
|
32
|
-
if (arg.startsWith("--version=")) {
|
|
33
|
-
const value = arg.slice("--version=".length);
|
|
36
|
+
if (arg.startsWith("--runtime-version=")) {
|
|
37
|
+
const value = arg.slice("--runtime-version=".length);
|
|
34
38
|
if (value.length === 0)
|
|
35
|
-
throw new ParseError("--version requires a value");
|
|
36
|
-
opts.
|
|
39
|
+
throw new ParseError("--runtime-version requires a value");
|
|
40
|
+
opts.runtimeVersion = value;
|
|
37
41
|
continue;
|
|
38
42
|
}
|
|
39
43
|
if (arg === "--dev") {
|
package/dist/cli.js
CHANGED
|
@@ -11,15 +11,14 @@ const dev_1 = require("./dev");
|
|
|
11
11
|
const run_1 = require("./run");
|
|
12
12
|
const start_1 = require("./start");
|
|
13
13
|
const ports_1 = require("./ports");
|
|
14
|
-
const update_1 = require("./update");
|
|
15
14
|
function printHelp() {
|
|
16
15
|
console.log(`kandev launcher
|
|
17
16
|
|
|
18
17
|
Usage:
|
|
19
|
-
kandev run [--
|
|
18
|
+
kandev run [--port <port>] [--verbose] [--debug]
|
|
20
19
|
kandev dev [--port <port>]
|
|
21
20
|
kandev start [--port <port>] [--verbose] [--debug]
|
|
22
|
-
kandev [--
|
|
21
|
+
kandev [--port <port>] [--verbose] [--debug]
|
|
23
22
|
kandev --dev [--port <port>]
|
|
24
23
|
|
|
25
24
|
Examples:
|
|
@@ -28,16 +27,16 @@ Examples:
|
|
|
28
27
|
kandev --dev
|
|
29
28
|
kandev dev
|
|
30
29
|
kandev start
|
|
31
|
-
kandev --version
|
|
30
|
+
kandev --version
|
|
32
31
|
kandev --port 3000
|
|
33
32
|
kandev --debug
|
|
34
33
|
|
|
35
34
|
Options:
|
|
36
35
|
dev Use local repo for dev (make dev + next dev) if available.
|
|
37
36
|
start Use local production build (make build + next start).
|
|
38
|
-
run Use
|
|
37
|
+
run Use installed runtime bundle (default).
|
|
39
38
|
--dev Alias for "dev".
|
|
40
|
-
--version
|
|
39
|
+
--version, -V Print CLI version and exit.
|
|
41
40
|
--port Port for the Go backend (the URL kandev opens on in
|
|
42
41
|
start/run). Alias for --backend-port. Also reads
|
|
43
42
|
KANDEV_PORT or KANDEV_BACKEND_PORT.
|
|
@@ -46,11 +45,14 @@ Options:
|
|
|
46
45
|
--help, -h Show help.
|
|
47
46
|
|
|
48
47
|
Advanced:
|
|
49
|
-
--backend-port
|
|
50
|
-
--web-internal-port
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
--web-port
|
|
48
|
+
--backend-port Same as --port.
|
|
49
|
+
--web-internal-port Override the internal Next.js port. The Go backend
|
|
50
|
+
reverse-proxies to it; users hit the backend port.
|
|
51
|
+
Also reads KANDEV_WEB_PORT.
|
|
52
|
+
--web-port Deprecated alias for --web-internal-port.
|
|
53
|
+
--runtime-version <tag> Download and use a specific release tag instead of
|
|
54
|
+
the installed runtime. For debugging only.
|
|
55
|
+
Example: kandev --runtime-version v0.16.0
|
|
54
56
|
`);
|
|
55
57
|
}
|
|
56
58
|
function findRepoRoot(startDir) {
|
|
@@ -77,6 +79,10 @@ function findRepoRoot(startDir) {
|
|
|
77
79
|
}
|
|
78
80
|
async function main() {
|
|
79
81
|
const { options, showHelp, deprecatedFlags } = (0, args_1.parseArgs)(process.argv.slice(2));
|
|
82
|
+
if (options.showVersion) {
|
|
83
|
+
console.log(package_json_1.default.version);
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
80
86
|
if (showHelp) {
|
|
81
87
|
printHelp();
|
|
82
88
|
return;
|
|
@@ -109,9 +115,8 @@ async function main() {
|
|
|
109
115
|
});
|
|
110
116
|
return;
|
|
111
117
|
}
|
|
112
|
-
await (0, update_1.maybePromptForUpdate)(package_json_1.default.version, process.argv.slice(2));
|
|
113
118
|
await (0, run_1.runRelease)({
|
|
114
|
-
|
|
119
|
+
runtimeVersion: options.runtimeVersion,
|
|
115
120
|
backendPort,
|
|
116
121
|
webPort,
|
|
117
122
|
verbose: options.verbose,
|
package/dist/run.js
CHANGED
|
@@ -18,6 +18,7 @@ const platform_1 = require("./platform");
|
|
|
18
18
|
const version_1 = require("./version");
|
|
19
19
|
const ports_1 = require("./ports");
|
|
20
20
|
const process_1 = require("./process");
|
|
21
|
+
const runtime_1 = require("./runtime");
|
|
21
22
|
const shared_1 = require("./shared");
|
|
22
23
|
const web_1 = require("./web");
|
|
23
24
|
/**
|
|
@@ -77,47 +78,62 @@ function cleanOldReleases(currentTag) {
|
|
|
77
78
|
// Non-critical — don't fail the launch if cleanup errors.
|
|
78
79
|
}
|
|
79
80
|
}
|
|
80
|
-
|
|
81
|
+
/**
|
|
82
|
+
* Download a specific release version into the local cache.
|
|
83
|
+
* Only used when --runtime-version is given explicitly.
|
|
84
|
+
*/
|
|
85
|
+
async function downloadRuntimeVersion(runtimeVersion) {
|
|
81
86
|
const platformDir = (0, platform_1.getPlatformDir)();
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
|
|
89
|
-
const
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
87
|
+
const release = await (0, github_1.getRelease)(runtimeVersion);
|
|
88
|
+
const tag = release.tag_name;
|
|
89
|
+
const assetName = `kandev-${platformDir}.tar.gz`;
|
|
90
|
+
const cacheDir = node_path_1.default.join(constants_1.CACHE_DIR, tag, platformDir);
|
|
91
|
+
const archivePath = await (0, github_1.ensureAsset)(tag, assetName, cacheDir, (downloaded, total) => {
|
|
92
|
+
const percent = total ? Math.round((downloaded / total) * 100) : 0;
|
|
93
|
+
const mb = (downloaded / (1024 * 1024)).toFixed(1);
|
|
94
|
+
const totalMb = total ? (total / (1024 * 1024)).toFixed(1) : "?";
|
|
95
|
+
process.stderr.write(`\r Downloading: ${mb}MB / ${totalMb}MB (${percent}%)`);
|
|
96
|
+
});
|
|
97
|
+
process.stderr.write("\n");
|
|
98
|
+
(0, bundle_1.ensureExtracted)(archivePath, cacheDir);
|
|
99
|
+
cleanOldReleases(tag);
|
|
100
|
+
return tag;
|
|
101
|
+
}
|
|
102
|
+
async function prepareBundleForLaunch({ runtimeVersion, backendPort, webPort, verbose = false, debug = false, }) {
|
|
103
|
+
let bundleDir;
|
|
104
|
+
let releaseTag;
|
|
105
|
+
if (runtimeVersion) {
|
|
106
|
+
// Explicit version: ensure it is in the cache (downloading if needed), then resolve.
|
|
107
|
+
const platformDir = (0, platform_1.getPlatformDir)();
|
|
108
|
+
const cached = findCachedRelease(platformDir, runtimeVersion);
|
|
109
|
+
let tag;
|
|
110
|
+
if (cached) {
|
|
111
|
+
tag = cached.tag;
|
|
112
|
+
bundleDir = (0, bundle_1.findBundleRoot)(cached.cacheDir);
|
|
108
113
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
114
|
+
else {
|
|
115
|
+
try {
|
|
116
|
+
tag = await downloadRuntimeVersion(runtimeVersion);
|
|
117
|
+
const cacheDir = node_path_1.default.join(constants_1.CACHE_DIR, tag, platformDir);
|
|
118
|
+
bundleDir = (0, bundle_1.findBundleRoot)(cacheDir);
|
|
119
|
+
}
|
|
120
|
+
catch (err) {
|
|
121
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
122
|
+
throw new Error(`Failed to fetch runtime version ${runtimeVersion}.\n` +
|
|
123
|
+
` Reason: ${reason}\n` +
|
|
124
|
+
` Run kandev once while online to cache a release for offline use.`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
// Validate the resolved bundle has all required binaries before launching.
|
|
128
|
+
(0, runtime_1.validateBundle)(bundleDir);
|
|
129
|
+
releaseTag = tag;
|
|
117
130
|
}
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
131
|
+
else {
|
|
132
|
+
// Default path: resolve from KANDEV_BUNDLE_DIR or installed npm runtime package.
|
|
133
|
+
const resolved = (0, runtime_1.resolveRuntime)();
|
|
134
|
+
bundleDir = resolved.bundleDir;
|
|
135
|
+
// Use KANDEV_VERSION if set (e.g. by Homebrew wrapper), otherwise show source.
|
|
136
|
+
releaseTag = process.env.KANDEV_VERSION ?? `(${resolved.source})`;
|
|
121
137
|
}
|
|
122
138
|
const actualBackendPort = backendPort ?? (await (0, ports_1.pickAvailablePort)(constants_1.DEFAULT_BACKEND_PORT));
|
|
123
139
|
const actualWebPort = webPort ?? (await (0, ports_1.pickAvailablePort)(constants_1.DEFAULT_WEB_PORT));
|
|
@@ -127,10 +143,7 @@ async function prepareReleaseBundle({ version, backendPort, webPort, verbose = f
|
|
|
127
143
|
const logLevel = process.env.KANDEV_LOG_LEVEL?.trim() || (debug ? "debug" : verbose ? "info" : "warn");
|
|
128
144
|
node_fs_1.default.mkdirSync(constants_1.DATA_DIR, { recursive: true });
|
|
129
145
|
const dbPath = node_path_1.default.join(constants_1.DATA_DIR, "kandev.db");
|
|
130
|
-
|
|
131
|
-
// the bundled configuration. Only backend and agentctl ports are set.
|
|
132
|
-
// Log level defaults to warn for clean output and can be overridden
|
|
133
|
-
// via KANDEV_LOG_LEVEL or --verbose/--debug flags.
|
|
146
|
+
const backendBin = node_path_1.default.join(bundleDir, "bin", (0, platform_1.getBinaryName)("kandev"));
|
|
134
147
|
const backendEnv = {
|
|
135
148
|
...process.env,
|
|
136
149
|
KANDEV_SERVER_PORT: String(actualBackendPort),
|
|
@@ -144,8 +157,6 @@ async function prepareReleaseBundle({ version, backendPort, webPort, verbose = f
|
|
|
144
157
|
...process.env,
|
|
145
158
|
KANDEV_API_BASE_URL: backendUrl,
|
|
146
159
|
PORT: String(actualWebPort),
|
|
147
|
-
// Ensure Next.js standalone server binds to 127.0.0.1 so localhost health checks work.
|
|
148
|
-
// Without this, HOSTNAME from the host environment can cause binding issues.
|
|
149
160
|
HOSTNAME: "127.0.0.1",
|
|
150
161
|
};
|
|
151
162
|
webEnv.NODE_ENV = "production";
|
|
@@ -155,8 +166,7 @@ async function prepareReleaseBundle({ version, backendPort, webPort, verbose = f
|
|
|
155
166
|
backendUrl,
|
|
156
167
|
backendEnv,
|
|
157
168
|
webEnv,
|
|
158
|
-
releaseTag
|
|
159
|
-
requestedVersion: version,
|
|
169
|
+
releaseTag,
|
|
160
170
|
webPort: actualWebPort,
|
|
161
171
|
agentctlPort,
|
|
162
172
|
dbPath,
|
|
@@ -179,12 +189,9 @@ function attachRingBuffer(stream, maxChars = 64 * 1024) {
|
|
|
179
189
|
});
|
|
180
190
|
return () => buf;
|
|
181
191
|
}
|
|
182
|
-
function
|
|
183
|
-
const releaseSource = prepared.requestedVersion
|
|
184
|
-
? `(requested: ${prepared.requestedVersion})`
|
|
185
|
-
: "(github latest)";
|
|
192
|
+
function launchBundle(prepared) {
|
|
186
193
|
(0, shared_1.logStartupInfo)({
|
|
187
|
-
header: `release: ${prepared.releaseTag}
|
|
194
|
+
header: `release: ${prepared.releaseTag}`,
|
|
188
195
|
ports: {
|
|
189
196
|
backendPort: Number(prepared.backendEnv.KANDEV_SERVER_PORT),
|
|
190
197
|
webPort: prepared.webPort,
|
|
@@ -196,10 +203,6 @@ function launchReleaseApps(prepared) {
|
|
|
196
203
|
});
|
|
197
204
|
const supervisor = (0, process_1.createProcessSupervisor)();
|
|
198
205
|
supervisor.attachSignalHandlers();
|
|
199
|
-
// Start backend: ignore stdin, always show stderr immediately.
|
|
200
|
-
// In verbose/debug mode stream stdout live; otherwise capture it into a ring
|
|
201
|
-
// buffer so we can dump the last few KB if the healthcheck fails (users were
|
|
202
|
-
// previously seeing opaque "timed out" errors with no backend context).
|
|
203
206
|
const backendProc = (0, node_child_process_1.spawn)(prepared.backendBin, [], {
|
|
204
207
|
cwd: node_path_1.default.dirname(prepared.backendBin),
|
|
205
208
|
env: prepared.backendEnv,
|
|
@@ -226,9 +229,15 @@ function launchReleaseApps(prepared) {
|
|
|
226
229
|
}
|
|
227
230
|
return { supervisor, backendProc, webServerPath, dumpBackendLogs };
|
|
228
231
|
}
|
|
229
|
-
async function runRelease({
|
|
230
|
-
const prepared = await
|
|
231
|
-
|
|
232
|
+
async function runRelease({ runtimeVersion, backendPort, webPort, verbose = false, debug = false, }) {
|
|
233
|
+
const prepared = await prepareBundleForLaunch({
|
|
234
|
+
runtimeVersion,
|
|
235
|
+
backendPort,
|
|
236
|
+
webPort,
|
|
237
|
+
verbose,
|
|
238
|
+
debug,
|
|
239
|
+
});
|
|
240
|
+
const { supervisor, backendProc, webServerPath, dumpBackendLogs } = launchBundle(prepared);
|
|
232
241
|
const healthTimeoutMs = (0, health_1.resolveHealthTimeoutMs)(constants_1.HEALTH_TIMEOUT_MS_RELEASE);
|
|
233
242
|
console.log("[kandev] starting backend...");
|
|
234
243
|
await (0, health_1.waitForHealth)(prepared.backendUrl, backendProc, healthTimeoutMs, dumpBackendLogs);
|
package/dist/runtime.js
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.resolveRuntime = resolveRuntime;
|
|
7
|
+
exports.validateBundle = validateBundle;
|
|
8
|
+
const node_path_1 = __importDefault(require("node:path"));
|
|
9
|
+
const node_fs_1 = __importDefault(require("node:fs"));
|
|
10
|
+
const bundle_1 = require("./bundle");
|
|
11
|
+
const platform_1 = require("./platform");
|
|
12
|
+
const PLATFORM_TO_NPM_PACKAGE = {
|
|
13
|
+
"linux-x64": "@kdlbs/runtime-linux-x64",
|
|
14
|
+
"linux-arm64": "@kdlbs/runtime-linux-arm64",
|
|
15
|
+
"macos-x64": "@kdlbs/runtime-darwin-x64",
|
|
16
|
+
"macos-arm64": "@kdlbs/runtime-darwin-arm64",
|
|
17
|
+
"windows-x64": "@kdlbs/runtime-win32-x64",
|
|
18
|
+
};
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the runtime bundle directory using a two-step priority chain:
|
|
21
|
+
*
|
|
22
|
+
* 1. KANDEV_BUNDLE_DIR env var — set by the Homebrew formula wrapper and
|
|
23
|
+
* useful for local testing. Skips all other resolution.
|
|
24
|
+
* 2. Installed npm runtime package — looks for @kdlbs/runtime-{platform}
|
|
25
|
+
* in node_modules via Node module resolution. Works after
|
|
26
|
+
* `npx kandev@latest` or `npm install -g kandev` (requires npm 7+).
|
|
27
|
+
*
|
|
28
|
+
* The explicit `--runtime-version <tag>` download path is handled directly
|
|
29
|
+
* in run.ts (which manages the GitHub download + cache itself); it does
|
|
30
|
+
* not flow through this function.
|
|
31
|
+
*
|
|
32
|
+
* Throws with an actionable error message if no runtime is found.
|
|
33
|
+
*/
|
|
34
|
+
function resolveRuntime() {
|
|
35
|
+
const envBundleDir = process.env.KANDEV_BUNDLE_DIR;
|
|
36
|
+
if (envBundleDir) {
|
|
37
|
+
validateBundle(envBundleDir);
|
|
38
|
+
return { bundleDir: envBundleDir, source: "env" };
|
|
39
|
+
}
|
|
40
|
+
const platformDir = (0, platform_1.getPlatformDir)();
|
|
41
|
+
const packageName = PLATFORM_TO_NPM_PACKAGE[platformDir];
|
|
42
|
+
let pkgJsonPath = null;
|
|
43
|
+
try {
|
|
44
|
+
pkgJsonPath = require.resolve(`${packageName}/package.json`);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
// MODULE_NOT_FOUND — npm runtime package is not installed. Fall through
|
|
48
|
+
// to the actionable error below.
|
|
49
|
+
}
|
|
50
|
+
if (pkgJsonPath) {
|
|
51
|
+
// The package IS installed. If validateBundle throws here, the bundle is
|
|
52
|
+
// present but corrupt — surface the error rather than the generic
|
|
53
|
+
// "no runtime found" message below.
|
|
54
|
+
const packageRoot = node_path_1.default.dirname(pkgJsonPath);
|
|
55
|
+
validateBundle(packageRoot);
|
|
56
|
+
return { bundleDir: packageRoot, source: "npm" };
|
|
57
|
+
}
|
|
58
|
+
throw new Error(`No Kandev runtime found for ${platformDir}.\n` +
|
|
59
|
+
` Install via npm (requires npm 7+): npx kandev@latest\n` +
|
|
60
|
+
` Install via Homebrew: brew install kdlbs/kandev/kandev\n` +
|
|
61
|
+
` Download a specific version (debug): kandev --runtime-version <tag>`);
|
|
62
|
+
}
|
|
63
|
+
function validateBundle(bundleDir) {
|
|
64
|
+
const backendBin = node_path_1.default.join(bundleDir, "bin", (0, platform_1.getBinaryName)("kandev"));
|
|
65
|
+
if (!node_fs_1.default.existsSync(backendBin)) {
|
|
66
|
+
throw new Error(`Backend binary not found in bundle at ${bundleDir}`);
|
|
67
|
+
}
|
|
68
|
+
const agentctlBin = node_path_1.default.join(bundleDir, "bin", (0, platform_1.getBinaryName)("agentctl"));
|
|
69
|
+
if (!node_fs_1.default.existsSync(agentctlBin)) {
|
|
70
|
+
throw new Error(`agentctl binary not found in bundle at ${bundleDir}`);
|
|
71
|
+
}
|
|
72
|
+
const webServerPath = (0, bundle_1.resolveWebServerPath)(bundleDir);
|
|
73
|
+
if (!webServerPath) {
|
|
74
|
+
throw new Error(`Web server (server.js) not found in bundle at ${bundleDir}`);
|
|
75
|
+
}
|
|
76
|
+
}
|
package/package.json
CHANGED
|
@@ -1,9 +1,14 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kandev",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.39.2",
|
|
4
4
|
"private": false,
|
|
5
|
-
"description": "
|
|
5
|
+
"description": "Launcher for Kandev — manage tasks, orchestrate agents, review changes, and ship value",
|
|
6
6
|
"license": "AGPL-3.0-only",
|
|
7
|
+
"repository": {
|
|
8
|
+
"type": "git",
|
|
9
|
+
"url": "git+https://github.com/kdlbs/kandev.git"
|
|
10
|
+
},
|
|
11
|
+
"homepage": "https://github.com/kdlbs/kandev",
|
|
7
12
|
"type": "commonjs",
|
|
8
13
|
"bin": {
|
|
9
14
|
"kandev": "bin/cli.js"
|
|
@@ -13,12 +18,23 @@
|
|
|
13
18
|
"bin",
|
|
14
19
|
"dist"
|
|
15
20
|
],
|
|
21
|
+
"engines": {
|
|
22
|
+
"npm": ">=7"
|
|
23
|
+
},
|
|
24
|
+
"optionalDependencies": {
|
|
25
|
+
"@kdlbs/runtime-linux-x64": "0.39.2",
|
|
26
|
+
"@kdlbs/runtime-linux-arm64": "0.39.2",
|
|
27
|
+
"@kdlbs/runtime-darwin-x64": "0.39.2",
|
|
28
|
+
"@kdlbs/runtime-darwin-arm64": "0.39.2",
|
|
29
|
+
"@kdlbs/runtime-win32-x64": "0.39.2"
|
|
30
|
+
},
|
|
16
31
|
"dependencies": {
|
|
17
32
|
"tar": "^7.5.11",
|
|
18
33
|
"tree-kill": "^1.2.2"
|
|
19
34
|
},
|
|
20
35
|
"devDependencies": {
|
|
21
36
|
"@types/node": "^20",
|
|
37
|
+
"esbuild": "^0.24.0",
|
|
22
38
|
"tsx": "^4.15.7",
|
|
23
39
|
"typescript": "^5",
|
|
24
40
|
"vitest": "^1.6.0"
|
|
@@ -26,6 +42,7 @@
|
|
|
26
42
|
"scripts": {
|
|
27
43
|
"dev": "unset npm_config_prefix && tsx src/cli.ts",
|
|
28
44
|
"build": "tsc -p tsconfig.json",
|
|
45
|
+
"bundle": "esbuild dist/cli.js --bundle --platform=node --format=cjs --outfile=dist/cli.bundle.js",
|
|
29
46
|
"start": "node dist/cli.js",
|
|
30
47
|
"test": "vitest run",
|
|
31
48
|
"prepublishOnly": "pnpm build"
|
package/dist/update.js
DELETED
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
-
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
-
};
|
|
5
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
-
exports.maybePromptForUpdate = maybePromptForUpdate;
|
|
7
|
-
const node_child_process_1 = require("node:child_process");
|
|
8
|
-
const node_https_1 = __importDefault(require("node:https"));
|
|
9
|
-
const node_readline_1 = __importDefault(require("node:readline"));
|
|
10
|
-
const version_1 = require("./version");
|
|
11
|
-
function requestJson(url) {
|
|
12
|
-
return new Promise((resolve, reject) => {
|
|
13
|
-
const req = node_https_1.default.get(url, { headers: { "User-Agent": "kandev-npx" } }, (res) => {
|
|
14
|
-
if (res.statusCode !== 200) {
|
|
15
|
-
return reject(new Error(`HTTP ${res.statusCode} fetching ${url}`));
|
|
16
|
-
}
|
|
17
|
-
let body = "";
|
|
18
|
-
res.on("data", (chunk) => (body += chunk));
|
|
19
|
-
res.on("end", () => {
|
|
20
|
-
try {
|
|
21
|
-
resolve(JSON.parse(body));
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
reject(new Error(`Failed to parse JSON from ${url}`));
|
|
25
|
-
}
|
|
26
|
-
});
|
|
27
|
-
});
|
|
28
|
-
req.setTimeout(5000, () => {
|
|
29
|
-
req.destroy(new Error(`Request timed out fetching ${url}`));
|
|
30
|
-
});
|
|
31
|
-
req.on("error", reject);
|
|
32
|
-
});
|
|
33
|
-
}
|
|
34
|
-
async function getLatestNpmVersion() {
|
|
35
|
-
const data = await requestJson("https://registry.npmjs.org/kandev");
|
|
36
|
-
return data?.["dist-tags"]?.latest;
|
|
37
|
-
}
|
|
38
|
-
function promptYesNo(question, defaultYes = false) {
|
|
39
|
-
return new Promise((resolve) => {
|
|
40
|
-
if (!process.stdin.isTTY) {
|
|
41
|
-
resolve(false);
|
|
42
|
-
return;
|
|
43
|
-
}
|
|
44
|
-
const rl = node_readline_1.default.createInterface({
|
|
45
|
-
input: process.stdin,
|
|
46
|
-
output: process.stdout,
|
|
47
|
-
});
|
|
48
|
-
const suffix = defaultYes ? "[Y/n]" : "[y/N]";
|
|
49
|
-
rl.question(`${question} ${suffix} `, (answer) => {
|
|
50
|
-
rl.close();
|
|
51
|
-
const normalized = String(answer || "")
|
|
52
|
-
.trim()
|
|
53
|
-
.toLowerCase();
|
|
54
|
-
if (!normalized) {
|
|
55
|
-
resolve(Boolean(defaultYes));
|
|
56
|
-
return;
|
|
57
|
-
}
|
|
58
|
-
resolve(normalized === "y" || normalized === "yes");
|
|
59
|
-
});
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
async function maybePromptForUpdate(currentVersion, args) {
|
|
63
|
-
// Allow disabling update checks for CI or automation.
|
|
64
|
-
if (process.env.KANDEV_SKIP_UPDATE === "1" || process.env.KANDEV_NO_UPDATE_PROMPT === "1") {
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
try {
|
|
68
|
-
const latest = await getLatestNpmVersion();
|
|
69
|
-
if (!latest)
|
|
70
|
-
return;
|
|
71
|
-
if ((0, version_1.compareVersions)(latest, currentVersion) <= 0)
|
|
72
|
-
return;
|
|
73
|
-
const wantsUpdate = await promptYesNo(`Update available: ${currentVersion} -> ${latest}. Update now?`, false);
|
|
74
|
-
if (!wantsUpdate)
|
|
75
|
-
return;
|
|
76
|
-
const env = { ...process.env, KANDEV_SKIP_UPDATE: "1" };
|
|
77
|
-
const child = (0, node_child_process_1.spawn)("npx", ["kandev@latest", ...args], {
|
|
78
|
-
stdio: "inherit",
|
|
79
|
-
env,
|
|
80
|
-
});
|
|
81
|
-
child.on("exit", (code) => process.exit(code || 0));
|
|
82
|
-
await new Promise(() => { });
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
// ignore update errors
|
|
86
|
-
}
|
|
87
|
-
}
|