opencode-supertask 0.1.18 → 0.1.20
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 +48 -17
- package/dist/cli/index.js.map +1 -1
- package/dist/gateway/index.js +47 -18
- package/dist/gateway/index.js.map +1 -1
- package/dist/plugin/supertask.js +20362 -20950
- package/dist/plugin/supertask.js.map +1 -1
- package/dist/web/index.js +33 -13
- package/dist/web/index.js.map +1 -1
- package/dist/worker/index.js +19 -7
- 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,6 +9400,14 @@ 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
|
+
let dir = __dirname2;
|
|
9404
|
+
for (let i = 0; i < 5; i++) {
|
|
9405
|
+
const candidate = join(dir, "drizzle", "meta", "_journal.json");
|
|
9406
|
+
if (existsSync(candidate)) {
|
|
9407
|
+
return join(dir, "drizzle");
|
|
9408
|
+
}
|
|
9409
|
+
dir = dirname(dir);
|
|
9410
|
+
}
|
|
9403
9411
|
return join(__dirname2, "../../drizzle");
|
|
9404
9412
|
}
|
|
9405
9413
|
function initDb() {
|
|
@@ -9424,7 +9432,9 @@ function initDb() {
|
|
|
9424
9432
|
try {
|
|
9425
9433
|
migrate(_db, { migrationsFolder: getMigrationsFolder() });
|
|
9426
9434
|
} catch (err) {
|
|
9427
|
-
|
|
9435
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
9436
|
+
console.error(`[supertask] migration failed: ${msg}`);
|
|
9437
|
+
throw new Error(`[supertask] DB migration failed: ${msg}`);
|
|
9428
9438
|
}
|
|
9429
9439
|
}
|
|
9430
9440
|
return _db;
|
|
@@ -9444,14 +9454,15 @@ function closeDb() {
|
|
|
9444
9454
|
_db = null;
|
|
9445
9455
|
}
|
|
9446
9456
|
}
|
|
9447
|
-
var DB_FILE_PATH, _sqlite, _db, _migrationRan, db, sqlite;
|
|
9457
|
+
var DEFAULT_DB_PATH, DB_FILE_PATH, _sqlite, _db, _migrationRan, db, sqlite;
|
|
9448
9458
|
var init_db2 = __esm({
|
|
9449
9459
|
"src/core/db/index.ts"() {
|
|
9450
9460
|
"use strict";
|
|
9451
9461
|
init_bun_sqlite();
|
|
9452
9462
|
init_migrator2();
|
|
9453
9463
|
init_schema();
|
|
9454
|
-
|
|
9464
|
+
DEFAULT_DB_PATH = join(homedir(), ".local/share/opencode/tasks.db");
|
|
9465
|
+
DB_FILE_PATH = process.env.SUPERTASK_DB_PATH || DEFAULT_DB_PATH;
|
|
9455
9466
|
_sqlite = null;
|
|
9456
9467
|
_db = null;
|
|
9457
9468
|
_migrationRan = false;
|
|
@@ -19306,10 +19317,13 @@ var init_worker = __esm({
|
|
|
19306
19317
|
status: "running"
|
|
19307
19318
|
});
|
|
19308
19319
|
const modelToUse = this.resolveModel(task.model);
|
|
19309
|
-
const
|
|
19310
|
-
|
|
19320
|
+
const args = ["run", "--agent", "supertask-runner", "--format", "json"];
|
|
19321
|
+
if (modelToUse) {
|
|
19322
|
+
args.push("-m", modelToUse);
|
|
19323
|
+
}
|
|
19324
|
+
args.push(`\u6267\u884C\u4EFB\u52A1 ID: ${task.id}${modelToUse ? ` OVERRIDE_MODEL=${modelToUse}` : ""}`);
|
|
19311
19325
|
const cwd = task.cwd || process.cwd();
|
|
19312
|
-
const child = spawn("
|
|
19326
|
+
const child = spawn("opencode", args, { cwd, stdio: ["ignore", "pipe", "pipe"] });
|
|
19313
19327
|
await TaskRunService.updatePid(run.id, process.pid, child.pid ?? 0);
|
|
19314
19328
|
let output = "";
|
|
19315
19329
|
const handleData = (data) => {
|
|
@@ -22102,6 +22116,10 @@ function formatDate(ts) {
|
|
|
22102
22116
|
const d = ts instanceof Date ? ts : new Date(ts);
|
|
22103
22117
|
return d.toLocaleString("zh-CN", { month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit" });
|
|
22104
22118
|
}
|
|
22119
|
+
function esc(s) {
|
|
22120
|
+
if (!s) return "";
|
|
22121
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
22122
|
+
}
|
|
22105
22123
|
function readCurrentConfig() {
|
|
22106
22124
|
if (!existsSync3(CONFIG_PATH)) return {};
|
|
22107
22125
|
try {
|
|
@@ -22122,6 +22140,7 @@ async function retryTask(id){if(!confirm('\u786E\u5B9A\u91CD\u8BD5\u4EFB\u52A1 #
|
|
|
22122
22140
|
async function deleteTask(id){if(!confirm('\u786E\u5B9A\u5220\u9664\u4EFB\u52A1 #'+id+'?'))return;await fetch('/api/tasks/'+id,{method:'DELETE'});location.reload();}
|
|
22123
22141
|
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
22142
|
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');}}
|
|
22143
|
+
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
22144
|
async function enableTmpl(id){await fetch('/api/templates/'+id+'/enable',{method:'POST'});location.reload();}
|
|
22126
22145
|
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
22146
|
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 +22325,8 @@ var init_web = __esm({
|
|
|
22306
22325
|
const st = (task.status ?? "").toUpperCase();
|
|
22307
22326
|
rows += `<tr>
|
|
22308
22327
|
<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>
|
|
22328
|
+
<td><div style="font-weight:500">${esc(task.name)}</div><div class="mu sm el">${esc(task.prompt.substring(0, 120))}</div></td>
|
|
22329
|
+
<td><span class="tag">${esc(task.agent)}</span></td>
|
|
22311
22330
|
<td><span class="badge b-${task.status}">${st}</span></td>
|
|
22312
22331
|
<td class="sm ${task.status === "running" ? "" : "mu"}">${formatDuration(task.startedAt, task.finishedAt)}</td>
|
|
22313
22332
|
<td class="mu sm">${(task.retryCount ?? 0) > 0 ? task.retryCount : "-"}</td>
|
|
@@ -22363,15 +22382,15 @@ var init_web = __esm({
|
|
|
22363
22382
|
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
22383
|
rows += `<tr>
|
|
22365
22384
|
<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>
|
|
22385
|
+
<td><div style="font-weight:500">${esc(t.name)}</div><div class="mu sm el">${esc(t.prompt.substring(0, 100))}</div>
|
|
22386
|
+
<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
22387
|
<td><span class="${typeClass}">${typeLabel}</span></td>
|
|
22369
22388
|
<td class="m sm">${rule}</td>
|
|
22370
22389
|
<td>${statusBadge}</td>
|
|
22371
22390
|
<td class="sm">${t.lastRunAt ? timeAgo(t.lastRunAt) : "-"}</td>
|
|
22372
22391
|
<td class="sm">${t.nextRunAt ? timeUntil(t.nextRunAt) : "-"}</td>
|
|
22373
22392
|
<td>
|
|
22374
|
-
<button class="btn btn-sm" onclick="
|
|
22393
|
+
<button class="btn btn-sm" onclick="showTemplateDetail(${t.id})">\u8BE6\u60C5</button>
|
|
22375
22394
|
<button class="btn btn-sm btn-primary" onclick="triggerTmpl(${t.id})">\u89E6\u53D1</button>
|
|
22376
22395
|
${toggleBtn}
|
|
22377
22396
|
<button class="btn btn-sm btn-danger" onclick="deleteTmpl(${t.id})">\u5220\u9664</button>
|
|
@@ -22423,9 +22442,9 @@ var init_web = __esm({
|
|
|
22423
22442
|
const logBtn = run.log ? `<button class="btn btn-sm" onclick="toggleLog(${run.id})">\u65E5\u5FD7</button>` : "";
|
|
22424
22443
|
rows += `<tr>
|
|
22425
22444
|
<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>
|
|
22445
|
+
<td><div style="font-weight:500">${esc(run.taskName)} <span class="mu">(#${run.taskId})</span></div>
|
|
22446
|
+
${run.model ? `<div class="sm"><span class="tag">${esc(run.model)}</span></div>` : ""}</td>
|
|
22447
|
+
<td><span class="tag">${esc(run.taskAgent)}</span></td>
|
|
22429
22448
|
<td><span class="badge b-${run.status}">${(run.status ?? "").toUpperCase()}</span></td>
|
|
22430
22449
|
<td class="sm">${formatDuration(run.startedAt, run.finishedAt)}</td>
|
|
22431
22450
|
<td class="sm mu">${run.heartbeatAt ? timeAgo(run.heartbeatAt) : "-"}</td>
|
|
@@ -22471,7 +22490,7 @@ var init_web = __esm({
|
|
|
22471
22490
|
runRows += `<tr>
|
|
22472
22491
|
<td class="mu">#${run.id}</td><td>#${run.taskId}</td>
|
|
22473
22492
|
<td class="m sm">${shortS}</td>
|
|
22474
|
-
<td class="sm">${run.model || "-"}</td>
|
|
22493
|
+
<td class="sm">${esc(run.model) || "-"}</td>
|
|
22475
22494
|
<td class="sm">${formatDate(run.startedAt)}</td>
|
|
22476
22495
|
<td class="sm">${run.heartbeatAt ? timeAgo(run.heartbeatAt) : "-"}</td>
|
|
22477
22496
|
<td class="m sm">W:${run.workerPid ?? "-"} C:${run.childPid ?? "-"}</td>
|
|
@@ -22560,6 +22579,12 @@ var init_web = __esm({
|
|
|
22560
22579
|
if (!run) return c.json({ error: "not found" }, 404);
|
|
22561
22580
|
return c.json(run);
|
|
22562
22581
|
});
|
|
22582
|
+
app.get("/api/templates/:id", async (c) => {
|
|
22583
|
+
const id = Number(c.req.param("id"));
|
|
22584
|
+
const tmpl = await TaskTemplateService.getById(id);
|
|
22585
|
+
if (!tmpl) return c.json({ error: "not found" }, 404);
|
|
22586
|
+
return c.json(tmpl);
|
|
22587
|
+
});
|
|
22563
22588
|
app.post("/api/tasks/:id/retry", async (c) => {
|
|
22564
22589
|
await TaskService.retry(Number(c.req.param("id")));
|
|
22565
22590
|
return c.json({ success: true });
|
|
@@ -22709,7 +22734,11 @@ async function main() {
|
|
|
22709
22734
|
await scheduler.start();
|
|
22710
22735
|
if (cfg.dashboard.enabled) {
|
|
22711
22736
|
const { dashboardApp: dashboardApp2 } = await Promise.resolve().then(() => (init_web(), web_exports));
|
|
22712
|
-
Bun.serve({
|
|
22737
|
+
Bun.serve({
|
|
22738
|
+
hostname: "127.0.0.1",
|
|
22739
|
+
port: cfg.dashboard.port,
|
|
22740
|
+
fetch: dashboardApp2.fetch
|
|
22741
|
+
});
|
|
22713
22742
|
console.log(JSON.stringify({
|
|
22714
22743
|
ts: (/* @__PURE__ */ new Date()).toISOString(),
|
|
22715
22744
|
level: "info",
|
|
@@ -22751,9 +22780,11 @@ async function main() {
|
|
|
22751
22780
|
process.on("SIGINT", () => shutdown("SIGINT"));
|
|
22752
22781
|
process.on("uncaughtException", (err) => {
|
|
22753
22782
|
console.error(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "fatal", msg: "uncaughtException", error: err.message, stack: err.stack }));
|
|
22783
|
+
process.exit(1);
|
|
22754
22784
|
});
|
|
22755
22785
|
process.on("unhandledRejection", (reason) => {
|
|
22756
22786
|
console.error(JSON.stringify({ ts: (/* @__PURE__ */ new Date()).toISOString(), level: "fatal", msg: "unhandledRejection", reason: String(reason) }));
|
|
22787
|
+
process.exit(1);
|
|
22757
22788
|
});
|
|
22758
22789
|
}
|
|
22759
22790
|
var STALE_THRESHOLD_MS;
|
|
@@ -23279,7 +23310,7 @@ program2.command("init").description("Initialize SuperTask (create config + run
|
|
|
23279
23310
|
const dir = dirname4(CONFIG_PATH2);
|
|
23280
23311
|
if (!existsSync5(dir)) mkdirSync3(dir, { recursive: true });
|
|
23281
23312
|
writeFileSync3(CONFIG_PATH2, JSON.stringify({
|
|
23282
|
-
worker: { maxConcurrency: 2
|
|
23313
|
+
worker: { maxConcurrency: 2 },
|
|
23283
23314
|
scheduler: { enabled: true }
|
|
23284
23315
|
}, null, 2) + "\n");
|
|
23285
23316
|
console.log(JSON.stringify({ created: CONFIG_PATH2 }));
|