opencode-supertask 0.1.4 → 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, {
@@ -23162,8 +23178,17 @@ program2.command("gateway").description("Start the Gateway process (foreground)"
23162
23178
  const { main: main2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
23163
23179
  await main2();
23164
23180
  });
23165
- program2.command("ui").description("Start the Web Dashboard").action(async () => {
23166
- 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
+ }
23167
23192
  });
23168
23193
  program2.command("config").description("Show current configuration").action(async () => {
23169
23194
  const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));