sparkecoder 0.1.6 → 0.1.8
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/dist/agent/index.js +2 -1
- package/dist/agent/index.js.map +1 -1
- package/dist/cli.js +130 -35
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.js +125 -34
- package/dist/index.js.map +1 -1
- package/dist/server/index.d.ts +1 -0
- package/dist/server/index.js +125 -34
- package/dist/server/index.js.map +1 -1
- package/dist/tools/index.js +2 -1
- package/dist/tools/index.js.map +1 -1
- package/package.json +4 -1
package/dist/server/index.d.ts
CHANGED
package/dist/server/index.js
CHANGED
|
@@ -1131,7 +1131,8 @@ async function runBackground(command, workingDirectory, options) {
|
|
|
1131
1131
|
cwd: workingDirectory,
|
|
1132
1132
|
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
1133
1133
|
sessionId: options.sessionId,
|
|
1134
|
-
background: true
|
|
1134
|
+
background: true,
|
|
1135
|
+
name: options.name
|
|
1135
1136
|
}, workingDirectory);
|
|
1136
1137
|
const logFile = join2(logDir, "output.log");
|
|
1137
1138
|
const wrappedCommand = `(${command}) 2>&1 | tee -a ${shellEscape(logFile)}`;
|
|
@@ -3954,7 +3955,10 @@ terminals2.post(
|
|
|
3954
3955
|
return c.json({ error: "tmux is not installed. Background terminals require tmux." }, 400);
|
|
3955
3956
|
}
|
|
3956
3957
|
const workingDirectory = body.cwd || session.workingDirectory;
|
|
3957
|
-
const result = await runBackground(body.command, workingDirectory, {
|
|
3958
|
+
const result = await runBackground(body.command, workingDirectory, {
|
|
3959
|
+
sessionId,
|
|
3960
|
+
name: body.name
|
|
3961
|
+
});
|
|
3958
3962
|
return c.json({
|
|
3959
3963
|
id: result.id,
|
|
3960
3964
|
name: body.name || null,
|
|
@@ -3978,7 +3982,7 @@ terminals2.get("/:sessionId/terminals", async (c) => {
|
|
|
3978
3982
|
const running = await isRunning(meta.id);
|
|
3979
3983
|
return {
|
|
3980
3984
|
id: meta.id,
|
|
3981
|
-
name: null,
|
|
3985
|
+
name: meta.name || null,
|
|
3982
3986
|
command: meta.command,
|
|
3983
3987
|
cwd: meta.cwd,
|
|
3984
3988
|
status: running ? "running" : "stopped",
|
|
@@ -4062,10 +4066,17 @@ terminals2.post(
|
|
|
4062
4066
|
"/:sessionId/terminals/:terminalId/write",
|
|
4063
4067
|
zValidator4("json", writeSchema),
|
|
4064
4068
|
async (c) => {
|
|
4065
|
-
|
|
4066
|
-
|
|
4067
|
-
|
|
4068
|
-
|
|
4069
|
+
const terminalId = c.req.param("terminalId");
|
|
4070
|
+
const body = c.req.valid("json");
|
|
4071
|
+
const isRunning2 = await isRunning(terminalId);
|
|
4072
|
+
if (!isRunning2) {
|
|
4073
|
+
return c.json({ error: "Terminal is not running" }, 400);
|
|
4074
|
+
}
|
|
4075
|
+
const success = await sendInput(terminalId, body.input, { pressEnter: false });
|
|
4076
|
+
if (!success) {
|
|
4077
|
+
return c.json({ error: "Failed to write to terminal" }, 500);
|
|
4078
|
+
}
|
|
4079
|
+
return c.json({ success: true, written: body.input.length });
|
|
4069
4080
|
}
|
|
4070
4081
|
);
|
|
4071
4082
|
terminals2.post("/:sessionId/terminals/kill-all", async (c) => {
|
|
@@ -4074,12 +4085,12 @@ terminals2.post("/:sessionId/terminals/kill-all", async (c) => {
|
|
|
4074
4085
|
if (!session) {
|
|
4075
4086
|
return c.json({ error: "Session not found" }, 404);
|
|
4076
4087
|
}
|
|
4077
|
-
const
|
|
4088
|
+
const sessionTerminals = await listSessionTerminals(sessionId, session.workingDirectory);
|
|
4078
4089
|
let killed = 0;
|
|
4079
|
-
for (const
|
|
4080
|
-
const
|
|
4081
|
-
if (
|
|
4082
|
-
const success = await killTerminal(id);
|
|
4090
|
+
for (const terminal of sessionTerminals) {
|
|
4091
|
+
const isRunning2 = await isRunning(terminal.id);
|
|
4092
|
+
if (isRunning2) {
|
|
4093
|
+
const success = await killTerminal(terminal.id);
|
|
4083
4094
|
if (success) killed++;
|
|
4084
4095
|
}
|
|
4085
4096
|
}
|
|
@@ -4377,6 +4388,33 @@ async function findWebPort(preferredPort) {
|
|
|
4377
4388
|
}
|
|
4378
4389
|
return { port: preferredPort, alreadyRunning: false };
|
|
4379
4390
|
}
|
|
4391
|
+
function hasProductionBuild(webDir) {
|
|
4392
|
+
const buildIdPath = join3(webDir, ".next", "BUILD_ID");
|
|
4393
|
+
return existsSync7(buildIdPath);
|
|
4394
|
+
}
|
|
4395
|
+
function runCommand(command, args, cwd, env) {
|
|
4396
|
+
return new Promise((resolve7) => {
|
|
4397
|
+
const child = spawn(command, args, {
|
|
4398
|
+
cwd,
|
|
4399
|
+
stdio: ["ignore", "pipe", "pipe"],
|
|
4400
|
+
env,
|
|
4401
|
+
shell: true
|
|
4402
|
+
});
|
|
4403
|
+
let output = "";
|
|
4404
|
+
child.stdout?.on("data", (data) => {
|
|
4405
|
+
output += data.toString();
|
|
4406
|
+
});
|
|
4407
|
+
child.stderr?.on("data", (data) => {
|
|
4408
|
+
output += data.toString();
|
|
4409
|
+
});
|
|
4410
|
+
child.on("close", (code) => {
|
|
4411
|
+
resolve7({ success: code === 0, output });
|
|
4412
|
+
});
|
|
4413
|
+
child.on("error", (err) => {
|
|
4414
|
+
resolve7({ success: false, output: err.message });
|
|
4415
|
+
});
|
|
4416
|
+
});
|
|
4417
|
+
}
|
|
4380
4418
|
async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false) {
|
|
4381
4419
|
const webDir = getWebDirectory();
|
|
4382
4420
|
if (!webDir) {
|
|
@@ -4388,39 +4426,90 @@ async function startWebUI(apiPort, webPort = DEFAULT_WEB_PORT, quiet = false) {
|
|
|
4388
4426
|
if (!quiet) console.log(` \u2713 Web UI already running at http://localhost:${actualPort}`);
|
|
4389
4427
|
return { process: null, port: actualPort };
|
|
4390
4428
|
}
|
|
4391
|
-
const
|
|
4392
|
-
const
|
|
4393
|
-
const
|
|
4429
|
+
const usePnpm = existsSync7(join3(webDir, "pnpm-lock.yaml"));
|
|
4430
|
+
const useNpm = !usePnpm && existsSync7(join3(webDir, "package-lock.json"));
|
|
4431
|
+
const pkgManager = usePnpm ? "pnpm" : useNpm ? "npm" : "npx";
|
|
4432
|
+
const { NODE_OPTIONS, TSX_TSCONFIG_PATH, ...cleanEnv } = process.env;
|
|
4433
|
+
const webEnv = {
|
|
4434
|
+
...cleanEnv,
|
|
4435
|
+
NEXT_PUBLIC_API_URL: `http://127.0.0.1:${apiPort}`
|
|
4436
|
+
};
|
|
4437
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
4438
|
+
let command;
|
|
4439
|
+
let args;
|
|
4440
|
+
if (isProduction) {
|
|
4441
|
+
if (!hasProductionBuild(webDir)) {
|
|
4442
|
+
if (!quiet) console.log(" \u{1F4E6} Building Web UI for production...");
|
|
4443
|
+
const buildArgs = pkgManager === "npx" ? ["next", "build"] : ["run", "build"];
|
|
4444
|
+
const buildResult = await runCommand(pkgManager, buildArgs, webDir, webEnv);
|
|
4445
|
+
if (!buildResult.success) {
|
|
4446
|
+
if (!quiet) console.error(" \u274C Web UI build failed");
|
|
4447
|
+
return { process: null, port: actualPort };
|
|
4448
|
+
}
|
|
4449
|
+
if (!quiet) console.log(" \u2713 Web UI build complete");
|
|
4450
|
+
}
|
|
4451
|
+
command = pkgManager;
|
|
4452
|
+
args = pkgManager === "npx" ? ["next", "start", "-p", String(actualPort)] : ["run", "start", "-p", String(actualPort)];
|
|
4453
|
+
} else {
|
|
4454
|
+
command = pkgManager;
|
|
4455
|
+
args = pkgManager === "npx" ? ["next", "dev", "-p", String(actualPort)] : ["run", "dev", "-p", String(actualPort)];
|
|
4456
|
+
}
|
|
4394
4457
|
const child = spawn(command, args, {
|
|
4395
4458
|
cwd: webDir,
|
|
4396
4459
|
stdio: ["ignore", "pipe", "pipe"],
|
|
4397
|
-
env:
|
|
4398
|
-
|
|
4399
|
-
|
|
4400
|
-
},
|
|
4401
|
-
detached: false
|
|
4460
|
+
env: webEnv,
|
|
4461
|
+
detached: false,
|
|
4462
|
+
shell: true
|
|
4402
4463
|
});
|
|
4464
|
+
const startupTimeout = 3e4;
|
|
4403
4465
|
let started = false;
|
|
4404
|
-
|
|
4405
|
-
|
|
4406
|
-
|
|
4407
|
-
|
|
4408
|
-
if (!
|
|
4409
|
-
|
|
4410
|
-
|
|
4411
|
-
|
|
4466
|
+
let exited = false;
|
|
4467
|
+
let exitCode = null;
|
|
4468
|
+
const startedPromise = new Promise((resolve7) => {
|
|
4469
|
+
const timeout = setTimeout(() => {
|
|
4470
|
+
if (!started && !exited) {
|
|
4471
|
+
resolve7(false);
|
|
4472
|
+
}
|
|
4473
|
+
}, startupTimeout);
|
|
4474
|
+
child.stdout?.on("data", (data) => {
|
|
4475
|
+
const output = data.toString();
|
|
4476
|
+
if (!started && (output.includes("Ready") || output.includes("started") || output.includes("localhost"))) {
|
|
4477
|
+
started = true;
|
|
4478
|
+
clearTimeout(timeout);
|
|
4479
|
+
resolve7(true);
|
|
4480
|
+
}
|
|
4481
|
+
});
|
|
4412
4482
|
child.stderr?.on("data", (data) => {
|
|
4413
4483
|
const output = data.toString();
|
|
4414
4484
|
if (output.toLowerCase().includes("error")) {
|
|
4415
|
-
console.error(` Web UI error: ${output.trim()}`);
|
|
4485
|
+
if (!quiet) console.error(` Web UI error: ${output.trim().slice(0, 200)}`);
|
|
4416
4486
|
}
|
|
4417
4487
|
});
|
|
4418
|
-
|
|
4419
|
-
|
|
4420
|
-
|
|
4488
|
+
child.on("error", (err) => {
|
|
4489
|
+
if (!quiet) console.error(` \u274C Web UI spawn error: ${err.message}`);
|
|
4490
|
+
clearTimeout(timeout);
|
|
4491
|
+
resolve7(false);
|
|
4492
|
+
});
|
|
4493
|
+
child.on("exit", (code) => {
|
|
4494
|
+
exited = true;
|
|
4495
|
+
exitCode = code;
|
|
4496
|
+
if (!started) {
|
|
4497
|
+
clearTimeout(timeout);
|
|
4498
|
+
resolve7(false);
|
|
4499
|
+
}
|
|
4500
|
+
webUIProcess = null;
|
|
4501
|
+
});
|
|
4421
4502
|
});
|
|
4422
4503
|
webUIProcess = child;
|
|
4423
|
-
|
|
4504
|
+
const didStart = await startedPromise;
|
|
4505
|
+
if (!didStart) {
|
|
4506
|
+
if (exited && exitCode !== 0) {
|
|
4507
|
+
if (!quiet) console.error(` \u274C Web UI failed to start (exit code: ${exitCode})`);
|
|
4508
|
+
} else if (!exited) {
|
|
4509
|
+
if (!quiet) console.log(` \u26A0 Web UI startup timed out, continuing anyway...`);
|
|
4510
|
+
}
|
|
4511
|
+
}
|
|
4512
|
+
return { process: child, port: actualPort, started: didStart };
|
|
4424
4513
|
}
|
|
4425
4514
|
function stopWebUI() {
|
|
4426
4515
|
if (webUIProcess) {
|
|
@@ -4514,11 +4603,13 @@ async function startServer(options = {}) {
|
|
|
4514
4603
|
hostname: host
|
|
4515
4604
|
});
|
|
4516
4605
|
let webPort;
|
|
4606
|
+
let webStarted;
|
|
4517
4607
|
if (options.webUI !== false) {
|
|
4518
4608
|
const result = await startWebUI(port, options.webPort || DEFAULT_WEB_PORT, options.quiet);
|
|
4519
4609
|
webPort = result.port;
|
|
4610
|
+
webStarted = result.started;
|
|
4520
4611
|
}
|
|
4521
|
-
return { app, port, host, webPort };
|
|
4612
|
+
return { app, port, host, webPort, webStarted };
|
|
4522
4613
|
}
|
|
4523
4614
|
function stopServer() {
|
|
4524
4615
|
stopWebUI();
|