opencode-supertask 0.1.21 → 0.1.22
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/cli/index.js +136 -9
- package/dist/cli/index.js.map +1 -1
- package/dist/gateway/index.d.ts +3 -1
- package/dist/gateway/index.js +40 -2
- package/dist/gateway/index.js.map +1 -1
- package/dist/plugin/supertask.js +19 -2
- package/dist/plugin/supertask.js.map +1 -1
- package/dist/web/index.js +17 -0
- package/dist/web/index.js.map +1 -1
- package/dist/worker/index.js +17 -0
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
package/dist/cli/index.js
CHANGED
|
@@ -9734,6 +9734,23 @@ var init_task_service = __esm({
|
|
|
9734
9734
|
).returning();
|
|
9735
9735
|
return result.length;
|
|
9736
9736
|
}
|
|
9737
|
+
static async resetOrphanRunningToPending() {
|
|
9738
|
+
const result = await db.update(tasks2).set({
|
|
9739
|
+
status: "pending",
|
|
9740
|
+
startedAt: null,
|
|
9741
|
+
finishedAt: null
|
|
9742
|
+
}).where(
|
|
9743
|
+
and(
|
|
9744
|
+
eq(tasks2.status, "running"),
|
|
9745
|
+
sql`NOT EXISTS (
|
|
9746
|
+
SELECT 1 FROM ${taskRuns2}
|
|
9747
|
+
WHERE ${taskRuns2.taskId} = ${tasks2.id}
|
|
9748
|
+
AND ${taskRuns2.status} = 'running'
|
|
9749
|
+
)`
|
|
9750
|
+
)
|
|
9751
|
+
).returning();
|
|
9752
|
+
return result.length;
|
|
9753
|
+
}
|
|
9737
9754
|
static async cancel(id, scope = {}) {
|
|
9738
9755
|
const conditions = [
|
|
9739
9756
|
eq(tasks2.id, id),
|
|
@@ -19290,6 +19307,7 @@ __export(pm2_exports, {
|
|
|
19290
19307
|
ensureGateway: () => ensureGateway,
|
|
19291
19308
|
getPackageVersion: () => getPackageVersion,
|
|
19292
19309
|
install: () => install,
|
|
19310
|
+
installMacLaunchAgent: () => installMacLaunchAgent,
|
|
19293
19311
|
isGatewayReady: () => isGatewayReady,
|
|
19294
19312
|
isGatewayRunning: () => isGatewayRunning,
|
|
19295
19313
|
isPm2Installed: () => isPm2Installed,
|
|
@@ -19298,9 +19316,9 @@ __export(pm2_exports, {
|
|
|
19298
19316
|
upgrade: () => upgrade
|
|
19299
19317
|
});
|
|
19300
19318
|
import { execSync, spawnSync } from "child_process";
|
|
19301
|
-
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
19319
|
+
import { chmodSync, existsSync as existsSync3, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync } from "fs";
|
|
19302
19320
|
import { homedir as homedir3 } from "os";
|
|
19303
|
-
import { dirname as dirname2, join as join3 } from "path";
|
|
19321
|
+
import { dirname as dirname2, isAbsolute, join as join3 } from "path";
|
|
19304
19322
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
19305
19323
|
import { Database as Database3 } from "bun:sqlite";
|
|
19306
19324
|
function getPackageVersion() {
|
|
@@ -19348,6 +19366,83 @@ function writeRunningVersion(version2) {
|
|
|
19348
19366
|
function pm2Bin() {
|
|
19349
19367
|
return process.env.SUPERTASK_PM2_BIN ?? (process.platform === "win32" ? "pm2.cmd" : "pm2");
|
|
19350
19368
|
}
|
|
19369
|
+
function xmlEscape(value) {
|
|
19370
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll("'", "'");
|
|
19371
|
+
}
|
|
19372
|
+
function resolvePm2Bin() {
|
|
19373
|
+
const configured = pm2Bin();
|
|
19374
|
+
if (isAbsolute(configured)) return configured;
|
|
19375
|
+
const result = spawnSync("which", [configured], { encoding: "utf8" });
|
|
19376
|
+
const resolved = result.status === 0 ? result.stdout.trim().split("\n")[0] : "";
|
|
19377
|
+
if (!resolved) throw new Error(`[supertask] \u65E0\u6CD5\u89E3\u6790 pm2 \u53EF\u6267\u884C\u6587\u4EF6: ${configured}`);
|
|
19378
|
+
return resolved;
|
|
19379
|
+
}
|
|
19380
|
+
function launchAgentPath() {
|
|
19381
|
+
return process.env.SUPERTASK_LAUNCH_AGENT_PATH ?? join3(homedir3(), "Library/LaunchAgents", `${MAC_LAUNCH_AGENT_LABEL}.plist`);
|
|
19382
|
+
}
|
|
19383
|
+
function launchctlBin() {
|
|
19384
|
+
return process.env.SUPERTASK_LAUNCHCTL_BIN ?? "launchctl";
|
|
19385
|
+
}
|
|
19386
|
+
function installMacLaunchAgent() {
|
|
19387
|
+
if (typeof process.getuid !== "function") {
|
|
19388
|
+
throw new Error("[supertask] \u5F53\u524D\u8FD0\u884C\u65F6\u65E0\u6CD5\u83B7\u53D6 macOS \u7528\u6237 ID");
|
|
19389
|
+
}
|
|
19390
|
+
const path = launchAgentPath();
|
|
19391
|
+
const home = homedir3();
|
|
19392
|
+
const pm2Home = process.env.PM2_HOME ?? join3(home, ".pm2");
|
|
19393
|
+
const environmentPath = process.env.PATH ?? "/opt/homebrew/bin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin";
|
|
19394
|
+
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
19395
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
19396
|
+
<plist version="1.0">
|
|
19397
|
+
<dict>
|
|
19398
|
+
<key>Label</key>
|
|
19399
|
+
<string>${MAC_LAUNCH_AGENT_LABEL}</string>
|
|
19400
|
+
<key>ProgramArguments</key>
|
|
19401
|
+
<array>
|
|
19402
|
+
<string>${xmlEscape(resolvePm2Bin())}</string>
|
|
19403
|
+
<string>resurrect</string>
|
|
19404
|
+
</array>
|
|
19405
|
+
<key>RunAtLoad</key>
|
|
19406
|
+
<true/>
|
|
19407
|
+
<key>KeepAlive</key>
|
|
19408
|
+
<dict>
|
|
19409
|
+
<key>SuccessfulExit</key>
|
|
19410
|
+
<false/>
|
|
19411
|
+
</dict>
|
|
19412
|
+
<key>ThrottleInterval</key>
|
|
19413
|
+
<integer>10</integer>
|
|
19414
|
+
<key>EnvironmentVariables</key>
|
|
19415
|
+
<dict>
|
|
19416
|
+
<key>HOME</key>
|
|
19417
|
+
<string>${xmlEscape(home)}</string>
|
|
19418
|
+
<key>PATH</key>
|
|
19419
|
+
<string>${xmlEscape(environmentPath)}</string>
|
|
19420
|
+
<key>PM2_HOME</key>
|
|
19421
|
+
<string>${xmlEscape(pm2Home)}</string>
|
|
19422
|
+
</dict>
|
|
19423
|
+
<key>StandardErrorPath</key>
|
|
19424
|
+
<string>${xmlEscape(join3(pm2Home, "supertask-launchd-error.log"))}</string>
|
|
19425
|
+
<key>StandardOutPath</key>
|
|
19426
|
+
<string>${xmlEscape(join3(pm2Home, "supertask-launchd-output.log"))}</string>
|
|
19427
|
+
</dict>
|
|
19428
|
+
</plist>
|
|
19429
|
+
`;
|
|
19430
|
+
mkdirSync2(dirname2(path), { recursive: true });
|
|
19431
|
+
writeFileSync(path, plist, { mode: 384 });
|
|
19432
|
+
chmodSync(path, 384);
|
|
19433
|
+
const domain = `gui/${process.getuid()}`;
|
|
19434
|
+
spawnSync(launchctlBin(), ["bootout", `${domain}/${MAC_LAUNCH_AGENT_LABEL}`], {
|
|
19435
|
+
stdio: "ignore"
|
|
19436
|
+
});
|
|
19437
|
+
const loaded = spawnSync(launchctlBin(), ["bootstrap", domain, path], {
|
|
19438
|
+
encoding: "utf8"
|
|
19439
|
+
});
|
|
19440
|
+
if (loaded.status !== 0) {
|
|
19441
|
+
const output = `${loaded.stdout ?? ""}${loaded.stderr ?? ""}`.trim();
|
|
19442
|
+
throw new Error(`[supertask] macOS LaunchAgent \u52A0\u8F7D\u5931\u8D25: ${output || `\u9000\u51FA\u7801 ${loaded.status}`}`);
|
|
19443
|
+
}
|
|
19444
|
+
return path;
|
|
19445
|
+
}
|
|
19351
19446
|
function isPm2Installed() {
|
|
19352
19447
|
const result = spawnSync(pm2Bin(), ["--version"], {
|
|
19353
19448
|
stdio: "ignore",
|
|
@@ -19486,10 +19581,19 @@ function install() {
|
|
|
19486
19581
|
pm2StartGateway();
|
|
19487
19582
|
writeRunningVersion(version2);
|
|
19488
19583
|
savePm2State();
|
|
19489
|
-
|
|
19490
|
-
|
|
19491
|
-
|
|
19492
|
-
|
|
19584
|
+
if (process.platform === "darwin") {
|
|
19585
|
+
try {
|
|
19586
|
+
const path = installMacLaunchAgent();
|
|
19587
|
+
console.log(`[supertask] macOS LaunchAgent installed: ${path}`);
|
|
19588
|
+
} catch (error) {
|
|
19589
|
+
console.warn(error instanceof Error ? error.message : String(error));
|
|
19590
|
+
}
|
|
19591
|
+
} else {
|
|
19592
|
+
const startup = pm2Exec(["startup"]);
|
|
19593
|
+
if (startup.output) console.log(startup.output);
|
|
19594
|
+
if (!startup.ok) {
|
|
19595
|
+
console.warn("[supertask] pm2 startup \u672A\u5B8C\u6210\uFF1B\u8BF7\u6309 pm2 \u8F93\u51FA\u6267\u884C\u9700\u8981\u7BA1\u7406\u5458\u6743\u9650\u7684\u547D\u4EE4\uFF0C\u7136\u540E\u8FD0\u884C `pm2 save`\u3002");
|
|
19596
|
+
}
|
|
19493
19597
|
}
|
|
19494
19598
|
console.log("[supertask] Gateway installed and running.");
|
|
19495
19599
|
console.log("[supertask] Manage with: pm2 status / pm2 logs supertask-gateway");
|
|
@@ -19547,13 +19651,14 @@ function ensureGateway() {
|
|
|
19547
19651
|
savePm2State();
|
|
19548
19652
|
return { ok: true, action: existing ? "restarted" : "started" };
|
|
19549
19653
|
}
|
|
19550
|
-
var __dirname, PROCESS_NAME, GATEWAY_LOCK_STALE_MS;
|
|
19654
|
+
var __dirname, PROCESS_NAME, MAC_LAUNCH_AGENT_LABEL, GATEWAY_LOCK_STALE_MS;
|
|
19551
19655
|
var init_pm2 = __esm({
|
|
19552
19656
|
"src/daemon/pm2.ts"() {
|
|
19553
19657
|
"use strict";
|
|
19554
19658
|
init_config();
|
|
19555
19659
|
__dirname = dirname2(fileURLToPath2(import.meta.url));
|
|
19556
19660
|
PROCESS_NAME = "supertask-gateway";
|
|
19661
|
+
MAC_LAUNCH_AGENT_LABEL = "com.supertask.pm2-resurrect";
|
|
19557
19662
|
GATEWAY_LOCK_STALE_MS = 3e4;
|
|
19558
19663
|
}
|
|
19559
19664
|
});
|
|
@@ -19768,6 +19873,15 @@ import { basename } from "path";
|
|
|
19768
19873
|
function isSafePid(pid) {
|
|
19769
19874
|
return Number.isInteger(pid) && pid > 1 && pid !== process.pid;
|
|
19770
19875
|
}
|
|
19876
|
+
function isProcessAlive(pid) {
|
|
19877
|
+
if (!Number.isInteger(pid) || pid <= 0) return false;
|
|
19878
|
+
try {
|
|
19879
|
+
process.kill(pid, 0);
|
|
19880
|
+
return true;
|
|
19881
|
+
} catch (error) {
|
|
19882
|
+
return error instanceof Error && "code" in error && error.code === "EPERM";
|
|
19883
|
+
}
|
|
19884
|
+
}
|
|
19771
19885
|
function inspectUnixProcess(pid) {
|
|
19772
19886
|
const result = spawnSync2("ps", ["-o", "pgid=", "-o", "command=", "-p", String(pid)], {
|
|
19773
19887
|
encoding: "utf8",
|
|
@@ -23463,7 +23577,9 @@ var init_web = __esm({
|
|
|
23463
23577
|
// src/gateway/index.ts
|
|
23464
23578
|
var gateway_exports = {};
|
|
23465
23579
|
__export(gateway_exports, {
|
|
23466
|
-
|
|
23580
|
+
acquireLock: () => acquireLock,
|
|
23581
|
+
main: () => main,
|
|
23582
|
+
releaseLock: () => releaseLock
|
|
23467
23583
|
});
|
|
23468
23584
|
function acquireLock() {
|
|
23469
23585
|
const now = Date.now();
|
|
@@ -23472,7 +23588,8 @@ function acquireLock() {
|
|
|
23472
23588
|
sqlite.exec("BEGIN IMMEDIATE");
|
|
23473
23589
|
const existing = sqlite.prepare("SELECT id, pid, heartbeat_at FROM gateway_lock WHERE id = 1").get();
|
|
23474
23590
|
if (existing) {
|
|
23475
|
-
|
|
23591
|
+
const lockHolderAlive = existing.pid !== pid && isProcessAlive(existing.pid);
|
|
23592
|
+
if (now - existing.heartbeat_at < STALE_THRESHOLD_MS && lockHolderAlive) {
|
|
23476
23593
|
sqlite.exec("ROLLBACK");
|
|
23477
23594
|
console.error(JSON.stringify({
|
|
23478
23595
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
@@ -23542,6 +23659,15 @@ async function main() {
|
|
|
23542
23659
|
const worker = new WorkerEngine(cfg);
|
|
23543
23660
|
const watchdog = new Watchdog(cfg);
|
|
23544
23661
|
const scheduler = new Scheduler(cfg);
|
|
23662
|
+
const recoveredOrphans = await TaskService.resetOrphanRunningToPending();
|
|
23663
|
+
if (recoveredOrphans > 0) {
|
|
23664
|
+
console.log(JSON.stringify({
|
|
23665
|
+
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
23666
|
+
level: "warn",
|
|
23667
|
+
msg: "reset orphan running tasks to pending",
|
|
23668
|
+
count: recoveredOrphans
|
|
23669
|
+
}));
|
|
23670
|
+
}
|
|
23545
23671
|
initializeGatewayHealth({
|
|
23546
23672
|
workerPollIntervalMs: cfg.worker.pollIntervalMs,
|
|
23547
23673
|
schedulerEnabled: cfg.scheduler.enabled,
|
|
@@ -23621,6 +23747,7 @@ var init_gateway = __esm({
|
|
|
23621
23747
|
init_task_service();
|
|
23622
23748
|
init_task_run_service();
|
|
23623
23749
|
init_health();
|
|
23750
|
+
init_process_control();
|
|
23624
23751
|
STALE_THRESHOLD_MS = 3e4;
|
|
23625
23752
|
if (import.meta.main) {
|
|
23626
23753
|
main();
|