opencode-supertask 0.1.18 → 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 +87 -76
- package/dist/cli/index.js +46 -18
- package/dist/cli/index.js.map +1 -1
- package/dist/gateway/index.js +45 -19
- package/dist/gateway/index.js.map +1 -1
- package/dist/plugin/supertask.js +20356 -20952
- package/dist/plugin/supertask.js.map +1 -1
- package/dist/web/index.js +26 -14
- package/dist/web/index.js.map +1 -1
- package/dist/worker/index.js +12 -8
- package/dist/worker/index.js.map +1 -1
- package/package.json +1 -1
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
|
-
###
|
|
12
|
+
### Quick Install
|
|
13
13
|
|
|
14
|
-
|
|
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
|
-
|
|
22
|
+
Restart OpenCode. That's it.
|
|
34
23
|
|
|
35
|
-
|
|
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
|
-
-
|
|
27
|
+
- A Web Dashboard at http://localhost:4680
|
|
39
28
|
|
|
40
|
-
|
|
29
|
+
### Uninstall
|
|
41
30
|
|
|
42
|
-
|
|
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
|
-
|
|
35
|
+
To clean up all data, delete the database:
|
|
45
36
|
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
"plugin": ["opencode-supertask"]
|
|
49
|
-
}
|
|
37
|
+
```bash
|
|
38
|
+
rm ~/.local/share/opencode/tasks.db
|
|
50
39
|
```
|
|
51
40
|
|
|
52
|
-
|
|
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
|
-
|
|
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
|
-
|
|
84
|
-
|
|
69
|
+
```
|
|
70
|
+
Create a task: "帮我生成项目的 README" with agent "explore"
|
|
85
71
|
```
|
|
86
72
|
|
|
87
|
-
|
|
73
|
+
Or open the Web Dashboard:
|
|
88
74
|
|
|
89
75
|
```bash
|
|
90
|
-
#
|
|
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
|
-
|
|
102
|
-
supertask
|
|
103
|
-
supertask
|
|
104
|
-
supertask
|
|
105
|
-
supertask
|
|
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 (
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
|
158
|
-
| System Status | Config editor, concurrency monitor,
|
|
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
|
|
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
|
-
|
|
208
|
-
supertask
|
|
209
|
-
|
|
210
|
-
|
|
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
|
-
-
|
|
217
|
-
-
|
|
218
|
-
-
|
|
219
|
-
- **
|
|
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, "
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
19310
|
-
|
|
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("
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
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="
|
|
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({
|
|
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
|
|
23310
|
+
worker: { maxConcurrency: 2 },
|
|
23283
23311
|
scheduler: { enabled: true }
|
|
23284
23312
|
}, null, 2) + "\n");
|
|
23285
23313
|
console.log(JSON.stringify({ created: CONFIG_PATH2 }));
|