opencode-supertask 0.1.3 → 0.1.5

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 CHANGED
@@ -19106,6 +19106,10 @@ var init_config = __esm({
19106
19106
  cleanupIntervalMs: 6e4,
19107
19107
  retentionDays: 30
19108
19108
  },
19109
+ dashboard: {
19110
+ enabled: true,
19111
+ port: 4680
19112
+ },
19109
19113
  logging: {
19110
19114
  level: "info",
19111
19115
  format: "json"
@@ -19723,137 +19727,6 @@ var init_scheduler = __esm({
19723
19727
  }
19724
19728
  });
19725
19729
 
19726
- // src/gateway/index.ts
19727
- var gateway_exports = {};
19728
- __export(gateway_exports, {
19729
- main: () => main
19730
- });
19731
- function acquireLock() {
19732
- const now = Date.now();
19733
- const pid = process.pid;
19734
- try {
19735
- sqlite.exec("BEGIN IMMEDIATE");
19736
- const existing = sqlite.prepare("SELECT id, pid, heartbeat_at FROM gateway_lock WHERE id = 1").get();
19737
- if (existing) {
19738
- if (now - existing.heartbeat_at < STALE_THRESHOLD_MS) {
19739
- sqlite.exec("ROLLBACK");
19740
- console.error(JSON.stringify({
19741
- ts: (/* @__PURE__ */ new Date()).toISOString(),
19742
- level: "fatal",
19743
- msg: "another Gateway instance is already running",
19744
- existingPid: existing.pid
19745
- }));
19746
- return false;
19747
- }
19748
- sqlite.exec("DELETE FROM gateway_lock WHERE id = 1");
19749
- }
19750
- sqlite.exec(
19751
- "INSERT INTO gateway_lock (id, pid, acquired_at, heartbeat_at) VALUES (1, ?, ?, ?)",
19752
- [pid, now, now]
19753
- );
19754
- sqlite.exec("COMMIT");
19755
- return true;
19756
- } catch (err) {
19757
- try {
19758
- sqlite.exec("ROLLBACK");
19759
- } catch {
19760
- }
19761
- console.error(JSON.stringify({
19762
- ts: (/* @__PURE__ */ new Date()).toISOString(),
19763
- level: "fatal",
19764
- msg: "failed to acquire lock",
19765
- error: err instanceof Error ? err.message : String(err)
19766
- }));
19767
- return false;
19768
- }
19769
- }
19770
- function releaseLock() {
19771
- try {
19772
- sqlite.exec("DELETE FROM gateway_lock WHERE pid = ?", [process.pid]);
19773
- } catch {
19774
- }
19775
- }
19776
- function updateLockHeartbeat() {
19777
- try {
19778
- sqlite.exec(
19779
- "UPDATE gateway_lock SET heartbeat_at = ? WHERE pid = ?",
19780
- [Date.now(), process.pid]
19781
- );
19782
- } catch {
19783
- }
19784
- }
19785
- async function main() {
19786
- console.log(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "info", msg: "SuperTask Gateway starting", pid: process.pid }));
19787
- if (!acquireLock()) {
19788
- process.exit(1);
19789
- }
19790
- const heartbeatTimer = setInterval(updateLockHeartbeat, 1e4);
19791
- heartbeatTimer.unref();
19792
- const cfg = loadConfig();
19793
- const worker = new WorkerEngine(cfg);
19794
- const watchdog = new Watchdog(cfg);
19795
- const scheduler = new Scheduler(cfg);
19796
- worker.start();
19797
- watchdog.start();
19798
- await scheduler.start();
19799
- console.log(JSON.stringify({
19800
- ts: (/* @__PURE__ */ new Date()).toISOString(),
19801
- level: "info",
19802
- msg: "Gateway started",
19803
- maxConcurrency: cfg.worker.maxConcurrency,
19804
- schedulerEnabled: cfg.scheduler.enabled
19805
- }));
19806
- let shuttingDown = false;
19807
- const shutdown = async (signal) => {
19808
- if (shuttingDown) return;
19809
- shuttingDown = true;
19810
- console.log(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "info", msg: `received ${signal}, shutting down...` }));
19811
- clearInterval(heartbeatTimer);
19812
- scheduler.stop();
19813
- watchdog.stop();
19814
- const runningIds = worker.getRunningTaskIds();
19815
- await worker.stop();
19816
- if (runningIds.length > 0) {
19817
- const resetCount = await TaskService.resetRunningToPending(runningIds);
19818
- console.log(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "info", msg: "reset running tasks to pending", count: resetCount }));
19819
- }
19820
- const allRunningRuns = await TaskRunService.getAllRunningRuns();
19821
- for (const run of allRunningRuns) {
19822
- await TaskRunService.fail(run.id, "Gateway shutdown");
19823
- }
19824
- releaseLock();
19825
- closeDb();
19826
- console.log(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "info", msg: "Gateway stopped" }));
19827
- process.exit(0);
19828
- };
19829
- process.on("SIGTERM", () => shutdown("SIGTERM"));
19830
- process.on("SIGINT", () => shutdown("SIGINT"));
19831
- process.on("uncaughtException", (err) => {
19832
- console.error(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "fatal", msg: "uncaughtException", error: err.message, stack: err.stack }));
19833
- });
19834
- process.on("unhandledRejection", (reason) => {
19835
- console.error(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "fatal", msg: "unhandledRejection", reason: String(reason) }));
19836
- });
19837
- }
19838
- var STALE_THRESHOLD_MS;
19839
- var init_gateway = __esm({
19840
- "src/gateway/index.ts"() {
19841
- "use strict";
19842
- init_db2();
19843
- init_config();
19844
- init_worker();
19845
- init_watchdog();
19846
- init_scheduler();
19847
- init_db2();
19848
- init_task_service();
19849
- init_task_run_service();
19850
- STALE_THRESHOLD_MS = 3e4;
19851
- if (import.meta.main) {
19852
- main();
19853
- }
19854
- }
19855
- });
19856
-
19857
19730
  // node_modules/hono/dist/compose.js
19858
19731
  var compose;
19859
19732
  var init_compose = __esm({
@@ -22191,6 +22064,7 @@ var init_html2 = __esm({
22191
22064
  // src/web/index.tsx
22192
22065
  var web_exports = {};
22193
22066
  __export(web_exports, {
22067
+ dashboardApp: () => dashboardApp,
22194
22068
  default: () => web_default
22195
22069
  });
22196
22070
  import { existsSync as existsSync3, readFileSync as readFileSync2, writeFileSync, mkdirSync as mkdirSync2 } from "fs";
@@ -22301,7 +22175,7 @@ async function saveConfig(){
22301
22175
  <dialog id="dd"><div class="dh"><h3 style="margin:0">\u8BE6\u60C5</h3><button class="cb" onclick="document.getElementById('dd').close()">&times;</button></div><div class="db"><pre id="dc"></pre></div></dialog>
22302
22176
  </body></html>`;
22303
22177
  }
22304
- var app, SHARED_STYLES, web_default;
22178
+ var app, SHARED_STYLES, dashboardApp, web_default;
22305
22179
  var init_web = __esm({
22306
22180
  "src/web/index.tsx"() {
22307
22181
  "use strict";
@@ -22725,13 +22599,155 @@ var init_web = __esm({
22725
22599
  return c.json({ success: false, error: err instanceof Error ? err.message : String(err) });
22726
22600
  }
22727
22601
  });
22602
+ dashboardApp = app;
22728
22603
  web_default = {
22729
- port: 3e3,
22604
+ port: 4680,
22730
22605
  fetch: app.fetch
22731
22606
  };
22732
22607
  }
22733
22608
  });
22734
22609
 
22610
+ // src/gateway/index.ts
22611
+ var gateway_exports = {};
22612
+ __export(gateway_exports, {
22613
+ main: () => main
22614
+ });
22615
+ function acquireLock() {
22616
+ const now = Date.now();
22617
+ const pid = process.pid;
22618
+ try {
22619
+ sqlite.exec("BEGIN IMMEDIATE");
22620
+ const existing = sqlite.prepare("SELECT id, pid, heartbeat_at FROM gateway_lock WHERE id = 1").get();
22621
+ if (existing) {
22622
+ if (now - existing.heartbeat_at < STALE_THRESHOLD_MS) {
22623
+ sqlite.exec("ROLLBACK");
22624
+ console.error(JSON.stringify({
22625
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
22626
+ level: "fatal",
22627
+ msg: "another Gateway instance is already running",
22628
+ existingPid: existing.pid
22629
+ }));
22630
+ return false;
22631
+ }
22632
+ sqlite.exec("DELETE FROM gateway_lock WHERE id = 1");
22633
+ }
22634
+ sqlite.exec(
22635
+ "INSERT INTO gateway_lock (id, pid, acquired_at, heartbeat_at) VALUES (1, ?, ?, ?)",
22636
+ [pid, now, now]
22637
+ );
22638
+ sqlite.exec("COMMIT");
22639
+ return true;
22640
+ } catch (err) {
22641
+ try {
22642
+ sqlite.exec("ROLLBACK");
22643
+ } catch {
22644
+ }
22645
+ console.error(JSON.stringify({
22646
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
22647
+ level: "fatal",
22648
+ msg: "failed to acquire lock",
22649
+ error: err instanceof Error ? err.message : String(err)
22650
+ }));
22651
+ return false;
22652
+ }
22653
+ }
22654
+ function releaseLock() {
22655
+ try {
22656
+ sqlite.exec("DELETE FROM gateway_lock WHERE pid = ?", [process.pid]);
22657
+ } catch {
22658
+ }
22659
+ }
22660
+ function updateLockHeartbeat() {
22661
+ try {
22662
+ sqlite.exec(
22663
+ "UPDATE gateway_lock SET heartbeat_at = ? WHERE pid = ?",
22664
+ [Date.now(), process.pid]
22665
+ );
22666
+ } catch {
22667
+ }
22668
+ }
22669
+ async function main() {
22670
+ console.log(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "info", msg: "SuperTask Gateway starting", pid: process.pid }));
22671
+ if (!acquireLock()) {
22672
+ process.exit(1);
22673
+ }
22674
+ const heartbeatTimer = setInterval(updateLockHeartbeat, 1e4);
22675
+ heartbeatTimer.unref();
22676
+ const cfg = loadConfig();
22677
+ const worker = new WorkerEngine(cfg);
22678
+ const watchdog = new Watchdog(cfg);
22679
+ const scheduler = new Scheduler(cfg);
22680
+ worker.start();
22681
+ watchdog.start();
22682
+ await scheduler.start();
22683
+ if (cfg.dashboard.enabled) {
22684
+ const { dashboardApp: dashboardApp2 } = await Promise.resolve().then(() => (init_web(), web_exports));
22685
+ Bun.serve({ port: cfg.dashboard.port, fetch: dashboardApp2.fetch });
22686
+ console.log(JSON.stringify({
22687
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
22688
+ level: "info",
22689
+ msg: "Dashboard started",
22690
+ url: `http://localhost:${cfg.dashboard.port}`
22691
+ }));
22692
+ }
22693
+ console.log(JSON.stringify({
22694
+ ts: (/* @__PURE__ */ new Date()).toISOString(),
22695
+ level: "info",
22696
+ msg: "Gateway started",
22697
+ maxConcurrency: cfg.worker.maxConcurrency,
22698
+ schedulerEnabled: cfg.scheduler.enabled
22699
+ }));
22700
+ let shuttingDown = false;
22701
+ const shutdown = async (signal) => {
22702
+ if (shuttingDown) return;
22703
+ shuttingDown = true;
22704
+ console.log(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "info", msg: `received ${signal}, shutting down...` }));
22705
+ clearInterval(heartbeatTimer);
22706
+ scheduler.stop();
22707
+ watchdog.stop();
22708
+ const runningIds = worker.getRunningTaskIds();
22709
+ await worker.stop();
22710
+ if (runningIds.length > 0) {
22711
+ const resetCount = await TaskService.resetRunningToPending(runningIds);
22712
+ console.log(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "info", msg: "reset running tasks to pending", count: resetCount }));
22713
+ }
22714
+ const allRunningRuns = await TaskRunService.getAllRunningRuns();
22715
+ for (const run of allRunningRuns) {
22716
+ await TaskRunService.fail(run.id, "Gateway shutdown");
22717
+ }
22718
+ releaseLock();
22719
+ closeDb();
22720
+ console.log(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "info", msg: "Gateway stopped" }));
22721
+ process.exit(0);
22722
+ };
22723
+ process.on("SIGTERM", () => shutdown("SIGTERM"));
22724
+ process.on("SIGINT", () => shutdown("SIGINT"));
22725
+ process.on("uncaughtException", (err) => {
22726
+ console.error(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "fatal", msg: "uncaughtException", error: err.message, stack: err.stack }));
22727
+ });
22728
+ process.on("unhandledRejection", (reason) => {
22729
+ console.error(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "fatal", msg: "unhandledRejection", reason: String(reason) }));
22730
+ });
22731
+ }
22732
+ var STALE_THRESHOLD_MS;
22733
+ var init_gateway = __esm({
22734
+ "src/gateway/index.ts"() {
22735
+ "use strict";
22736
+ init_db2();
22737
+ init_config();
22738
+ init_worker();
22739
+ init_watchdog();
22740
+ init_scheduler();
22741
+ init_db2();
22742
+ init_task_service();
22743
+ init_task_run_service();
22744
+ STALE_THRESHOLD_MS = 3e4;
22745
+ if (import.meta.main) {
22746
+ main();
22747
+ }
22748
+ }
22749
+ });
22750
+
22735
22751
  // src/daemon/pm2.ts
22736
22752
  var pm2_exports = {};
22737
22753
  __export(pm2_exports, {
@@ -22871,26 +22887,28 @@ function uninstall() {
22871
22887
  }
22872
22888
  function ensureGateway() {
22873
22889
  try {
22874
- const list2 = pm2JsonList();
22875
- const proc = list2.find((p) => p.name === PROCESS_NAME);
22890
+ const list = pm2JsonList();
22891
+ const proc = list.find((p) => p.name === PROCESS_NAME);
22876
22892
  if (proc && proc.pm2_env?.status === "online") {
22877
22893
  return;
22878
22894
  }
22879
22895
  } catch {
22880
22896
  }
22881
22897
  if (!isPm2Installed()) {
22898
+ console.log("[supertask] Installing pm2 for Gateway process management...");
22882
22899
  try {
22883
22900
  execSync("npm install -g pm2", { stdio: "pipe" });
22884
22901
  } catch {
22885
22902
  try {
22886
22903
  execSync("bun install -g pm2", { stdio: "pipe" });
22887
22904
  } catch {
22905
+ console.warn("[supertask] Could not install pm2. Gateway will not auto-start. Run `supertask install` manually.");
22888
22906
  return;
22889
22907
  }
22890
22908
  }
22891
22909
  }
22892
- const list = pm2JsonList();
22893
- const existing = list.find((p) => p.name === PROCESS_NAME);
22910
+ const pm2List = pm2JsonList();
22911
+ const existing = pm2List.find((p) => p.name === PROCESS_NAME);
22894
22912
  if (existing) {
22895
22913
  pm2Exec(["restart", PROCESS_NAME]);
22896
22914
  } else {
@@ -23160,8 +23178,17 @@ program2.command("gateway").description("Start the Gateway process (foreground)"
23160
23178
  const { main: main2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
23161
23179
  await main2();
23162
23180
  });
23163
- program2.command("ui").description("Start the Web Dashboard").action(async () => {
23164
- await Promise.resolve().then(() => (init_web(), web_exports));
23181
+ program2.command("ui").description("Open Web Dashboard (embedded in Gateway)").action(async () => {
23182
+ const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
23183
+ const cfg = loadConfig2();
23184
+ const url = `http://localhost:${cfg.dashboard.port}`;
23185
+ console.log(`Dashboard: ${url}`);
23186
+ try {
23187
+ const { execSync: execSync2 } = await import("child_process");
23188
+ const cmd = process.platform === "win32" ? `start ${url}` : process.platform === "darwin" ? `open ${url}` : `xdg-open ${url}`;
23189
+ execSync2(cmd, { stdio: "ignore" });
23190
+ } catch {
23191
+ }
23165
23192
  });
23166
23193
  program2.command("config").description("Show current configuration").action(async () => {
23167
23194
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
@@ -23169,12 +23196,22 @@ program2.command("config").description("Show current configuration").action(asyn
23169
23196
  console.log(JSON.stringify(cfg, null, 2));
23170
23197
  });
23171
23198
  program2.command("install").description("Install Gateway as pm2 service (auto-start on boot, crash recovery)").action(async () => {
23172
- const { install: pm2Install } = await Promise.resolve().then(() => (init_pm2(), pm2_exports));
23173
- pm2Install();
23199
+ try {
23200
+ const { install: pm2Install } = await Promise.resolve().then(() => (init_pm2(), pm2_exports));
23201
+ pm2Install();
23202
+ } catch (err) {
23203
+ console.error(err instanceof Error ? err.message : String(err));
23204
+ process.exit(1);
23205
+ }
23174
23206
  });
23175
23207
  program2.command("uninstall").description("Stop and remove Gateway pm2 service").action(async () => {
23176
- const { uninstall: pm2Uninstall } = await Promise.resolve().then(() => (init_pm2(), pm2_exports));
23177
- pm2Uninstall();
23208
+ try {
23209
+ const { uninstall: pm2Uninstall } = await Promise.resolve().then(() => (init_pm2(), pm2_exports));
23210
+ pm2Uninstall();
23211
+ } catch (err) {
23212
+ console.error(err instanceof Error ? err.message : String(err));
23213
+ process.exit(1);
23214
+ }
23178
23215
  });
23179
23216
  program2.parse();
23180
23217
  //# sourceMappingURL=index.js.map