opencode-supertask 0.1.17 → 0.1.19

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 CHANGED
@@ -9,20 +9,9 @@ AI-powered task queue for [OpenCode](https://opencode.ai) agents — schedule, r
9
9
 
10
10
  ## Installation
11
11
 
12
- ### Let an LLM do it
12
+ ### Quick Install
13
13
 
14
- Paste this into any LLM agent (Claude Code, OpenCode, Cursor, etc.):
15
-
16
- ```
17
- Install the opencode-supertask plugin by following: https://raw.githubusercontent.com/vbgate/opencode-supertask/main/README.md
18
- ```
19
-
20
- <details>
21
- <summary><b>Instructions for LLM agents</b></summary>
22
-
23
- To install this plugin, perform these steps:
24
-
25
- 1. Add `"opencode-supertask"` to the `plugin` array in `~/.config/opencode/opencode.json`:
14
+ Add the plugin to `~/.config/opencode/opencode.json`:
26
15
 
27
16
  ```json
28
17
  {
@@ -30,26 +19,31 @@ To install this plugin, perform these steps:
30
19
  }
31
20
  ```
32
21
 
33
- 2. Tell the user to restart OpenCode.
22
+ Restart OpenCode. That's it.
34
23
 
35
- After restart, the plugin auto-injects:
24
+ The plugin auto-starts a Gateway process (via pm2) and injects:
36
25
  - 10 MCP tools (`supertask_add`, `supertask_next`, `supertask_start`, `supertask_done`, `supertask_fail`, `supertask_get`, `supertask_list`, `supertask_status`, `supertask_retry`, `supertask_schedule`)
37
26
  - A `supertask-runner` agent (used internally by the Gateway)
38
- - Usage instructions in the system prompt
27
+ - A Web Dashboard at http://localhost:4680
39
28
 
40
- </details>
29
+ ### Uninstall
41
30
 
42
- ### Manual Installation
31
+ 1. Run `supertask uninstall` to stop the Gateway and remove it from pm2
32
+ 2. Remove `"opencode-supertask"` from `~/.config/opencode/opencode.json`
33
+ 3. Restart OpenCode
43
34
 
44
- 1. Add the plugin to your `~/.config/opencode/opencode.json`:
35
+ To clean up all data, delete the database:
45
36
 
46
- ```json
47
- {
48
- "plugin": ["opencode-supertask"]
49
- }
37
+ ```bash
38
+ rm ~/.local/share/opencode/tasks.db
50
39
  ```
51
40
 
52
- 2. Restart OpenCode
41
+ ### CLI Install / Uninstall
42
+
43
+ ```bash
44
+ supertask install # Install Gateway as pm2 service (auto-start, crash recovery)
45
+ supertask uninstall # Stop and remove Gateway from pm2
46
+ ```
53
47
 
54
48
  ### From Source
55
49
 
@@ -70,39 +64,27 @@ Then add the local path to your config:
70
64
 
71
65
  ## Quick Start
72
66
 
73
- ```bash
74
- # Install globally for CLI + Gateway
75
- bun install -g opencode-supertask
76
-
77
- # Initialize (create config + run migrations)
78
- supertask init
79
-
80
- # Start Gateway (foreground)
81
- supertask gateway
67
+ After installation, the Gateway starts automatically. Use the MCP tools in OpenCode:
82
68
 
83
- # Start Web Dashboard
84
- supertask ui # http://localhost:3000
69
+ ```
70
+ Create a task: "帮我生成项目的 README" with agent "explore"
85
71
  ```
86
72
 
87
- ### Background Running
73
+ Or open the Web Dashboard:
88
74
 
89
75
  ```bash
90
- # pm2 (recommended)
91
- pm2 start "supertask gateway" --name supertask-gateway
92
-
93
- # systemd
94
- cp deploy/supertask-gateway.service ~/.config/systemd/user/
95
- systemctl --user enable --now supertask-gateway
76
+ supertask ui # Opens http://localhost:4680 in browser
96
77
  ```
97
78
 
98
79
  ## CLI Reference
99
80
 
100
81
  ```bash
101
- supertask init # init config + db
102
- supertask migrate # run migrations
103
- supertask gateway # start gateway (foreground)
104
- supertask ui # start web dashboard
105
- supertask config # show current config
82
+ # Gateway management
83
+ supertask install # install Gateway as pm2 service
84
+ supertask uninstall # stop and remove from pm2
85
+ supertask gateway # start Gateway in foreground
86
+ supertask ui # open Web Dashboard in browser
87
+ supertask config # show current config
106
88
 
107
89
  # Task management
108
90
  supertask add -n "Task" -a "agent" -p "prompt" --importance 5
@@ -112,33 +94,54 @@ supertask status
112
94
  supertask cancel --id 1
113
95
  supertask retry --id 1
114
96
 
115
- # Scheduled templates
97
+ # Scheduled templates (friendly duration format)
116
98
  supertask template add --name "Daily" --agent "gen" \
117
99
  --prompt "..." --type cron --cron "0 9 * * *"
100
+ supertask template add --name "Delayed" --agent "gen" \
101
+ --prompt "..." --type delayed --delay "30min"
102
+ supertask template add --name "Hourly" --agent "gen" \
103
+ --prompt "..." --type recurring --interval "1h"
118
104
  supertask template list
119
105
  supertask template enable --id 1
120
106
  ```
121
107
 
108
+ ### Duration Format
109
+
110
+ Schedule supports friendly duration strings:
111
+
112
+ | Format | Examples |
113
+ |--------|----------|
114
+ | Seconds | `30s`, `5sec` |
115
+ | Minutes | `5min`, `30minutes` |
116
+ | Hours | `1h`, `2hours` |
117
+ | Days | `1d`, `3days` |
118
+ | Weeks | `1w`, `2weeks` |
119
+ | ISO 8601 | `PT30M`, `PT1H30M` |
120
+
122
121
  ## Architecture
123
122
 
124
123
  ```
125
- Gateway (supertask gateway)
126
- ├── Worker → claim tasks, spawn supertask-runner via opencode
124
+ Gateway (auto-started by pm2)
125
+ ├── Worker → claim tasks, spawn supertask-runner via opencode run
127
126
  ├── Scheduler → clone tasks from templates (cron / delayed / recurring)
128
- └── Watchdog → heartbeat timeout, auto-retry, data cleanup
127
+ ├── Watchdog → heartbeat timeout, auto-retry, data cleanup
128
+ └── Dashboard → Web UI on port 4680 (Hono SSR)
129
129
  ```
130
130
 
131
131
  Config file: `~/.config/opencode/supertask.json`
132
132
 
133
133
  ```json
134
134
  {
135
- "worker": { "maxConcurrency": 2, "defaultModel": "zhipuai-coding-plan/glm-4.7" },
135
+ "worker": { "maxConcurrency": 2 },
136
136
  "scheduler": { "enabled": true, "catchUp": "next" },
137
- "watchdog": { "heartbeatTimeoutMs": 600000, "retentionDays": 30 }
137
+ "watchdog": { "heartbeatTimeoutMs": 600000, "retentionDays": 30 },
138
+ "dashboard": { "enabled": true, "port": 4680 }
138
139
  }
139
140
  ```
140
141
 
141
142
  Key mechanisms:
143
+ - **Auto-start** — Plugin auto-installs pm2 and starts Gateway on first use
144
+ - **Auto-upgrade** — Plugin detects version changes and auto-reloads Gateway
142
145
  - **Process lock** — SQLite `BEGIN IMMEDIATE` ensures single instance
143
146
  - **Heartbeat** — Worker updates every 30s; Watchdog kills stale processes
144
147
  - **Exponential backoff** — 30s × 2^n, capped at 30min
@@ -148,14 +151,14 @@ Key mechanisms:
148
151
 
149
152
  ## Web Dashboard
150
153
 
151
- `supertask ui` starts a dashboard at http://localhost:3000 with 4 pages:
154
+ http://localhost:4680 4 pages:
152
155
 
153
156
  | Page | Features |
154
157
  |------|----------|
155
158
  | Task Queue | Filter by status, retry, delete |
156
159
  | Scheduled Tasks | Template CRUD, enable/disable, manual trigger |
157
- | Execution Logs | task_runs history, log viewer |
158
- | System Status | Config editor, concurrency monitor, stats |
160
+ | Execution Logs | task_runs history with session tracking |
161
+ | System Status | Config editor, concurrency monitor, clear database |
159
162
 
160
163
  ## Data
161
164
 
@@ -181,16 +184,6 @@ SuperTask 是一个基于 SQLite 的 AI Agent 任务调度系统,专为 [OpenC
181
184
 
182
185
  ### 安装
183
186
 
184
- #### 让 AI 帮你装
185
-
186
- 把这段话粘贴到任意 LLM agent(Claude Code、OpenCode、Cursor 等):
187
-
188
- ```
189
- 安装 opencode-supertask 插件,参照:https://raw.githubusercontent.com/vbgate/opencode-supertask/main/README.md
190
- ```
191
-
192
- #### 手动安装
193
-
194
187
  在 `~/.config/opencode/opencode.json` 中添加:
195
188
 
196
189
  ```json
@@ -199,24 +192,42 @@ SuperTask 是一个基于 SQLite 的 AI Agent 任务调度系统,专为 [OpenC
199
192
  }
200
193
  ```
201
194
 
202
- 重启 OpenCode 即可。插件会自动注入 10 个 MCP 工具、supertask-runner Agent 和使用说明。
195
+ 重启 OpenCode 即可。插件会自动:
196
+ - 安装 pm2 并启动 Gateway 常驻进程
197
+ - 注入 10 个 MCP 工具和 supertask-runner Agent
198
+ - 启动 Web 控制台(http://localhost:4680)
199
+
200
+ ### 卸载
201
+
202
+ 1. 运行 `supertask uninstall` 停止 Gateway
203
+ 2. 从 `~/.config/opencode/opencode.json` 中移除 `"opencode-supertask"`
204
+ 3. 重启 OpenCode
203
205
 
204
- ### 快速开始
206
+ 清理所有数据:`rm ~/.local/share/opencode/tasks.db`
207
+
208
+ ### 定时任务
209
+
210
+ 支持友好的时间格式:
205
211
 
206
212
  ```bash
207
- bun install -g opencode-supertask
208
- supertask init # 初始化
209
- supertask gateway # 启动 Gateway
210
- supertask ui # Web 控制台
213
+ # 30秒后执行
214
+ supertask template add --type delayed --delay "30s" ...
215
+
216
+ # 每5分钟循环
217
+ supertask template add --type recurring --interval "5min" ...
218
+
219
+ # 每天上午9点(cron)
220
+ supertask template add --type cron --cron "0 9 * * *" ...
211
221
  ```
212
222
 
213
223
  ### 核心功能
214
224
 
215
225
  - **任务队列** — 优先级调度、批次隔离、依赖管理
216
- - **Gateway 常驻进程** Worker + Scheduler + Watchdog,自动重试 + 指数退避
217
- - **定时任务**支持 cron / delayed / recurring 三种调度类型
218
- - **Web 控制台** 任务监控、执行日志、在线配置
219
- - **CLI 工具**完整的命令行管理
226
+ - **自动启动**插件首次加载时自动安装 pm2 并启动 Gateway
227
+ - **自动升级**插件更新后自动检测版本变化并 reload Gateway
228
+ - **定时任务**cron / delayed / recurring,支持友好时间格式
229
+ - **Web 控制台**任务监控、执行日志、在线配置、清空数据库
230
+ - **Session 追踪** — 自动从 opencode run 输出中捕获 session ID
220
231
 
221
232
  ### 数据位置
222
233
 
package/dist/cli/index.js CHANGED
@@ -9400,7 +9400,7 @@ import { join, dirname } from "path";
9400
9400
  import { fileURLToPath } from "url";
9401
9401
  function getMigrationsFolder() {
9402
9402
  const __dirname2 = dirname(fileURLToPath(import.meta.url));
9403
- return join(__dirname2, "../../drizzle");
9403
+ return join(__dirname2, "../../../drizzle");
9404
9404
  }
9405
9405
  function initDb() {
9406
9406
  const dataDir = dirname(DB_FILE_PATH);
@@ -9424,7 +9424,9 @@ function initDb() {
9424
9424
  try {
9425
9425
  migrate(_db, { migrationsFolder: getMigrationsFolder() });
9426
9426
  } catch (err) {
9427
- console.error("[supertask] migration failed:", err instanceof Error ? err.message : String(err));
9427
+ const msg = err instanceof Error ? err.message : String(err);
9428
+ console.error(`[supertask] migration failed: ${msg}`);
9429
+ throw new Error(`[supertask] DB migration failed: ${msg}`);
9428
9430
  }
9429
9431
  }
9430
9432
  return _db;
@@ -9444,14 +9446,15 @@ function closeDb() {
9444
9446
  _db = null;
9445
9447
  }
9446
9448
  }
9447
- var DB_FILE_PATH, _sqlite, _db, _migrationRan, db, sqlite;
9449
+ var DEFAULT_DB_PATH, DB_FILE_PATH, _sqlite, _db, _migrationRan, db, sqlite;
9448
9450
  var init_db2 = __esm({
9449
9451
  "src/core/db/index.ts"() {
9450
9452
  "use strict";
9451
9453
  init_bun_sqlite();
9452
9454
  init_migrator2();
9453
9455
  init_schema();
9454
- DB_FILE_PATH = join(homedir(), ".local/share/opencode/tasks.db");
9456
+ DEFAULT_DB_PATH = join(homedir(), ".local/share/opencode/tasks.db");
9457
+ DB_FILE_PATH = process.env.SUPERTASK_DB_PATH || DEFAULT_DB_PATH;
9455
9458
  _sqlite = null;
9456
9459
  _db = null;
9457
9460
  _migrationRan = false;
@@ -19306,10 +19309,13 @@ var init_worker = __esm({
19306
19309
  status: "running"
19307
19310
  });
19308
19311
  const modelToUse = this.resolveModel(task.model);
19309
- const modelArg = modelToUse ? ` -m "${modelToUse}"` : "";
19310
- const cmd = `opencode run --agent supertask-runner${modelArg} --format json "\u6267\u884C\u4EFB\u52A1 ID: ${task.id}${modelToUse ? ` OVERRIDE_MODEL=${modelToUse}` : ""}"`;
19312
+ const args = ["run", "--agent", "supertask-runner", "--format", "json"];
19313
+ if (modelToUse) {
19314
+ args.push("-m", modelToUse);
19315
+ }
19316
+ args.push(`\u6267\u884C\u4EFB\u52A1 ID: ${task.id}${modelToUse ? ` OVERRIDE_MODEL=${modelToUse}` : ""}`);
19311
19317
  const cwd = task.cwd || process.cwd();
19312
- const child = spawn("sh", ["-c", cmd], { cwd, stdio: ["ignore", "pipe", "pipe"] });
19318
+ const child = spawn("opencode", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
19313
19319
  await TaskRunService.updatePid(run.id, process.pid, child.pid ?? 0);
19314
19320
  let output = "";
19315
19321
  const handleData = (data) => {
@@ -22102,6 +22108,10 @@ function formatDate(ts) {
22102
22108
  const d = ts instanceof Date ? ts : new Date(ts);
22103
22109
  return d.toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" });
22104
22110
  }
22111
+ function esc(s) {
22112
+ if (!s) return "";
22113
+ return s.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#39;");
22114
+ }
22105
22115
  function readCurrentConfig() {
22106
22116
  if (!existsSync3(CONFIG_PATH)) return {};
22107
22117
  try {
@@ -22122,6 +22132,7 @@ async function retryTask(id){if(!confirm('\u786E\u5B9A\u91CD\u8BD5\u4EFB\u52A1 #
22122
22132
  async function deleteTask(id){if(!confirm('\u786E\u5B9A\u5220\u9664\u4EFB\u52A1 #'+id+'?'))return;await fetch('/api/tasks/'+id,{method:'DELETE'});location.reload();}
22123
22133
  async function showDetail(id){try{const r=await fetch('/api/tasks/'+id);const t=await r.json();document.getElementById('dc').textContent=JSON.stringify(t,null,2);document.getElementById('dd').showModal();}catch(e){alert('\u83B7\u53D6\u8BE6\u60C5\u5931\u8D25');}}
22124
22134
  async function showRunDetail(id){try{const r=await fetch('/api/runs/'+id);const t=await r.json();document.getElementById('dc').textContent=JSON.stringify(t,null,2);document.getElementById('dd').showModal();}catch(e){alert('\u83B7\u53D6\u8BE6\u60C5\u5931\u8D25');}}
22135
+ async function showTemplateDetail(id){try{const r=await fetch('/api/templates/'+id);const t=await r.json();document.getElementById('dc').textContent=JSON.stringify(t,null,2);document.getElementById('dd').showModal();}catch(e){alert('\u83B7\u53D6\u8BE6\u60C5\u5931\u8D25');}}
22125
22136
  async function enableTmpl(id){await fetch('/api/templates/'+id+'/enable',{method:'POST'});location.reload();}
22126
22137
  async function disableTmpl(id){if(!confirm('\u786E\u5B9A\u7981\u7528\u6B64\u6A21\u677F?'))return;await fetch('/api/templates/'+id+'/disable',{method:'POST'});location.reload();}
22127
22138
  async function deleteTmpl(id){if(!confirm('\u786E\u5B9A\u5220\u9664\u6B64\u6A21\u677F? \u6B64\u64CD\u4F5C\u4E0D\u53EF\u6062\u590D!'))return;await fetch('/api/templates/'+id,{method:'DELETE'});location.reload();}
@@ -22306,8 +22317,8 @@ var init_web = __esm({
22306
22317
  const st = (task.status ?? "").toUpperCase();
22307
22318
  rows += `<tr>
22308
22319
  <td class="mu">#${task.id}</td>
22309
- <td><div style="font-weight:500">${task.name}</div><div class="mu sm el">${task.prompt.substring(0, 120)}</div></td>
22310
- <td><span class="tag">${task.agent}</span></td>
22320
+ <td><div style="font-weight:500">${esc(task.name)}</div><div class="mu sm el">${esc(task.prompt.substring(0, 120))}</div></td>
22321
+ <td><span class="tag">${esc(task.agent)}</span></td>
22311
22322
  <td><span class="badge b-${task.status}">${st}</span></td>
22312
22323
  <td class="sm ${task.status === "running" ? "" : "mu"}">${formatDuration(task.startedAt, task.finishedAt)}</td>
22313
22324
  <td class="mu sm">${(task.retryCount ?? 0) > 0 ? task.retryCount : "-"}</td>
@@ -22363,15 +22374,15 @@ var init_web = __esm({
22363
22374
  const toggleBtn = t.enabled ? `<button class="btn btn-sm btn-warn" onclick="disableTmpl(${t.id})">\u7981\u7528</button>` : `<button class="btn btn-sm" onclick="enableTmpl(${t.id})">\u542F\u7528</button>`;
22364
22375
  rows += `<tr>
22365
22376
  <td class="mu">#${t.id}</td>
22366
- <td><div style="font-weight:500">${t.name}</div><div class="mu sm el">${t.prompt.substring(0, 100)}</div>
22367
- <div class="sm" style="margin-top:2px"><span class="tag">${t.agent}</span>${t.model && t.model !== "default" ? ` <span class="tag">${t.model}</span>` : ""}</div></td>
22377
+ <td><div style="font-weight:500">${esc(t.name)}</div><div class="mu sm el">${esc(t.prompt.substring(0, 100))}</div>
22378
+ <div class="sm" style="margin-top:2px"><span class="tag">${esc(t.agent)}</span>${t.model && t.model !== "default" ? ` <span class="tag">${esc(t.model)}</span>` : ""}</div></td>
22368
22379
  <td><span class="${typeClass}">${typeLabel}</span></td>
22369
22380
  <td class="m sm">${rule}</td>
22370
22381
  <td>${statusBadge}</td>
22371
22382
  <td class="sm">${t.lastRunAt ? timeAgo(t.lastRunAt) : "-"}</td>
22372
22383
  <td class="sm">${t.nextRunAt ? timeUntil(t.nextRunAt) : "-"}</td>
22373
22384
  <td>
22374
- <button class="btn btn-sm" onclick="showDetail(${t.id})">\u8BE6\u60C5</button>
22385
+ <button class="btn btn-sm" onclick="showTemplateDetail(${t.id})">\u8BE6\u60C5</button>
22375
22386
  <button class="btn btn-sm btn-primary" onclick="triggerTmpl(${t.id})">\u89E6\u53D1</button>
22376
22387
  ${toggleBtn}
22377
22388
  <button class="btn btn-sm btn-danger" onclick="deleteTmpl(${t.id})">\u5220\u9664</button>
@@ -22423,9 +22434,9 @@ var init_web = __esm({
22423
22434
  const logBtn = run.log ? `<button class="btn btn-sm" onclick="toggleLog(${run.id})">\u65E5\u5FD7</button>` : "";
22424
22435
  rows += `<tr>
22425
22436
  <td class="mu">#${run.id}</td>
22426
- <td><div style="font-weight:500">${run.taskName} <span class="mu">(#${run.taskId})</span></div>
22427
- ${run.model ? `<div class="sm"><span class="tag">${run.model}</span></div>` : ""}</td>
22428
- <td><span class="tag">${run.taskAgent}</span></td>
22437
+ <td><div style="font-weight:500">${esc(run.taskName)} <span class="mu">(#${run.taskId})</span></div>
22438
+ ${run.model ? `<div class="sm"><span class="tag">${esc(run.model)}</span></div>` : ""}</td>
22439
+ <td><span class="tag">${esc(run.taskAgent)}</span></td>
22429
22440
  <td><span class="badge b-${run.status}">${(run.status ?? "").toUpperCase()}</span></td>
22430
22441
  <td class="sm">${formatDuration(run.startedAt, run.finishedAt)}</td>
22431
22442
  <td class="sm mu">${run.heartbeatAt ? timeAgo(run.heartbeatAt) : "-"}</td>
@@ -22471,7 +22482,7 @@ var init_web = __esm({
22471
22482
  runRows += `<tr>
22472
22483
  <td class="mu">#${run.id}</td><td>#${run.taskId}</td>
22473
22484
  <td class="m sm">${shortS}</td>
22474
- <td class="sm">${run.model || "-"}</td>
22485
+ <td class="sm">${esc(run.model) || "-"}</td>
22475
22486
  <td class="sm">${formatDate(run.startedAt)}</td>
22476
22487
  <td class="sm">${run.heartbeatAt ? timeAgo(run.heartbeatAt) : "-"}</td>
22477
22488
  <td class="m sm">W:${run.workerPid ?? "-"} C:${run.childPid ?? "-"}</td>
@@ -22560,6 +22571,12 @@ var init_web = __esm({
22560
22571
  if (!run) return c.json({ error: "not found" }, 404);
22561
22572
  return c.json(run);
22562
22573
  });
22574
+ app.get("/api/templates/:id", async (c) => {
22575
+ const id = Number(c.req.param("id"));
22576
+ const tmpl = await TaskTemplateService.getById(id);
22577
+ if (!tmpl) return c.json({ error: "not found" }, 404);
22578
+ return c.json(tmpl);
22579
+ });
22563
22580
  app.post("/api/tasks/:id/retry", async (c) => {
22564
22581
  await TaskService.retry(Number(c.req.param("id")));
22565
22582
  return c.json({ success: true });
@@ -22709,7 +22726,16 @@ async function main() {
22709
22726
  await scheduler.start();
22710
22727
  if (cfg.dashboard.enabled) {
22711
22728
  const { dashboardApp: dashboardApp2 } = await Promise.resolve().then(() => (init_web(), web_exports));
22712
- Bun.serve({ port: cfg.dashboard.port, fetch: dashboardApp2.fetch });
22729
+ Bun.serve({
22730
+ port: cfg.dashboard.port,
22731
+ fetch(req) {
22732
+ const url = new URL(req.url);
22733
+ if (url.hostname !== "localhost" && url.hostname !== "127.0.0.1" && url.hostname !== "::1") {
22734
+ return new Response("Forbidden", { status: 403 });
22735
+ }
22736
+ return dashboardApp2.fetch(req);
22737
+ }
22738
+ });
22713
22739
  console.log(JSON.stringify({
22714
22740
  ts: (/* @__PURE__ */ new Date()).toISOString(),
22715
22741
  level: "info",
@@ -22751,9 +22777,11 @@ async function main() {
22751
22777
  process.on("SIGINT", () => shutdown("SIGINT"));
22752
22778
  process.on("uncaughtException", (err) => {
22753
22779
  console.error(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "fatal", msg: "uncaughtException", error: err.message, stack: err.stack }));
22780
+ process.exit(1);
22754
22781
  });
22755
22782
  process.on("unhandledRejection", (reason) => {
22756
22783
  console.error(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "fatal", msg: "unhandledRejection", reason: String(reason) }));
22784
+ process.exit(1);
22757
22785
  });
22758
22786
  }
22759
22787
  var STALE_THRESHOLD_MS;
@@ -23279,7 +23307,7 @@ program2.command("init").description("Initialize SuperTask (create config + run
23279
23307
  const dir = dirname4(CONFIG_PATH2);
23280
23308
  if (!existsSync5(dir)) mkdirSync3(dir, { recursive: true });
23281
23309
  writeFileSync3(CONFIG_PATH2, JSON.stringify({
23282
- worker: { maxConcurrency: 2, defaultModel: "zhipuai-coding-plan/glm-4.7" },
23310
+ worker: { maxConcurrency: 2 },
23283
23311
  scheduler: { enabled: true }
23284
23312
  }, null, 2) + "\n");
23285
23313
  console.log(JSON.stringify({ created: CONFIG_PATH2 }));
@@ -23342,13 +23370,31 @@ program2.command("uninstall").description("Stop and remove Gateway pm2 service")
23342
23370
  process.exit(1);
23343
23371
  }
23344
23372
  });
23345
- program2.command("upgrade").description("Restart Gateway with current plugin version").action(async () => {
23373
+ program2.command("upgrade").description("Update npm package and restart Gateway").action(async () => {
23374
+ const { execSync: execSync2 } = await import("child_process");
23375
+ const { homedir: homedir4 } = await import("os");
23376
+ const { join: join4 } = await import("path");
23377
+ const configDir = join4(homedir4(), ".config/opencode");
23378
+ console.log("Updating opencode-supertask...");
23379
+ try {
23380
+ execSync2("npm install opencode-supertask@latest", {
23381
+ cwd: configDir,
23382
+ stdio: "inherit",
23383
+ timeout: 6e4
23384
+ });
23385
+ } catch (err) {
23386
+ console.error("npm install failed:", err instanceof Error ? err.message : String(err));
23387
+ console.error("Try manually: cd ~/.config/opencode && npm install opencode-supertask@latest");
23388
+ process.exit(1);
23389
+ }
23346
23390
  try {
23347
23391
  const { upgrade: pm2Upgrade } = await Promise.resolve().then(() => (init_pm2(), pm2_exports));
23348
23392
  const result = pm2Upgrade();
23349
- console.log(JSON.stringify({ before: result.before, after: result.after, restarted: result.restarted }));
23393
+ console.log(`
23394
+ SuperTask upgraded: ${result.before ?? "unknown"} \u2192 ${result.after}`);
23395
+ console.log("Gateway restarted. Please restart opencode to load the new plugin.");
23350
23396
  } catch (err) {
23351
- console.error(err instanceof Error ? err.message : String(err));
23397
+ console.error("Gateway restart failed:", err instanceof Error ? err.message : String(err));
23352
23398
  process.exit(1);
23353
23399
  }
23354
23400
  });