opencode-supertask 0.1.33 → 0.1.35
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/CHANGELOG.md +59 -0
- package/README.md +66 -13
- package/dist/cli/index.js +853 -152
- package/dist/cli/index.js.map +1 -1
- package/dist/gateway/index.js +449 -32
- package/dist/gateway/index.js.map +1 -1
- package/dist/plugin/supertask.js +166 -4
- package/dist/plugin/supertask.js.map +1 -1
- package/dist/web/index.d.ts +12 -1
- package/dist/web/index.js +459 -63
- package/dist/web/index.js.map +1 -1
- package/dist/worker/index.d.ts +3 -1
- package/dist/worker/index.js +19 -4
- package/dist/worker/index.js.map +1 -1
- package/package.json +2 -1
package/dist/cli/index.js
CHANGED
|
@@ -4506,7 +4506,7 @@ var init_sql = __esm({
|
|
|
4506
4506
|
return new SQL([new StringChunk(str)]);
|
|
4507
4507
|
}
|
|
4508
4508
|
sql2.raw = raw2;
|
|
4509
|
-
function
|
|
4509
|
+
function join8(chunks, separator) {
|
|
4510
4510
|
const result = [];
|
|
4511
4511
|
for (const [i, chunk] of chunks.entries()) {
|
|
4512
4512
|
if (i > 0 && separator !== void 0) {
|
|
@@ -4516,7 +4516,7 @@ var init_sql = __esm({
|
|
|
4516
4516
|
}
|
|
4517
4517
|
return new SQL(result);
|
|
4518
4518
|
}
|
|
4519
|
-
sql2.join =
|
|
4519
|
+
sql2.join = join8;
|
|
4520
4520
|
function identifier(value) {
|
|
4521
4521
|
return new Name(value);
|
|
4522
4522
|
}
|
|
@@ -7132,7 +7132,7 @@ var init_select2 = __esm({
|
|
|
7132
7132
|
return (table, on) => {
|
|
7133
7133
|
const baseTableName = this.tableName;
|
|
7134
7134
|
const tableName = getTableLikeName(table);
|
|
7135
|
-
if (typeof tableName === "string" && this.config.joins?.some((
|
|
7135
|
+
if (typeof tableName === "string" && this.config.joins?.some((join8) => join8.alias === tableName)) {
|
|
7136
7136
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
7137
7137
|
}
|
|
7138
7138
|
if (!this.isPartialSelect) {
|
|
@@ -7974,7 +7974,7 @@ var init_update = __esm({
|
|
|
7974
7974
|
createJoin(joinType) {
|
|
7975
7975
|
return (table, on) => {
|
|
7976
7976
|
const tableName = getTableLikeName(table);
|
|
7977
|
-
if (typeof tableName === "string" && this.config.joins.some((
|
|
7977
|
+
if (typeof tableName === "string" && this.config.joins.some((join8) => join8.alias === tableName)) {
|
|
7978
7978
|
throw new Error(`Alias "${tableName}" is already used in this query`);
|
|
7979
7979
|
}
|
|
7980
7980
|
if (typeof on === "function") {
|
|
@@ -12696,8 +12696,8 @@ var require_luxon = __commonJS({
|
|
|
12696
12696
|
* Set whether Luxon will throw when it encounters invalid DateTimes, Durations, or Intervals
|
|
12697
12697
|
* @type {boolean}
|
|
12698
12698
|
*/
|
|
12699
|
-
static set throwOnInvalid(
|
|
12700
|
-
throwOnInvalid =
|
|
12699
|
+
static set throwOnInvalid(t3) {
|
|
12700
|
+
throwOnInvalid = t3;
|
|
12701
12701
|
}
|
|
12702
12702
|
/**
|
|
12703
12703
|
* Reset Luxon's global caches. Should only be necessary in testing scenarios.
|
|
@@ -13590,7 +13590,7 @@ var require_luxon = __commonJS({
|
|
|
13590
13590
|
}, tokens = _Formatter.parseFormat(fmt), realTokens = tokens.reduce((found, {
|
|
13591
13591
|
literal,
|
|
13592
13592
|
val
|
|
13593
|
-
}) => literal ? found : found.concat(val), []), collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((
|
|
13593
|
+
}) => literal ? found : found.concat(val), []), collapsed = dur.shiftTo(...realTokens.map(tokenToField).filter((t3) => t3)), durationInfo = {
|
|
13594
13594
|
isNegativeDuration: collapsed < 0,
|
|
13595
13595
|
// this relies on "collapsed" being based on "shiftTo", which builds up the object
|
|
13596
13596
|
// in order
|
|
@@ -15500,15 +15500,15 @@ var require_luxon = __commonJS({
|
|
|
15500
15500
|
return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
|
|
15501
15501
|
}
|
|
15502
15502
|
function unitForToken(token, loc) {
|
|
15503
|
-
const one = digitRegex(loc), two = digitRegex(loc, "{2}"), three = digitRegex(loc, "{3}"), four = digitRegex(loc, "{4}"), six = digitRegex(loc, "{6}"), oneOrTwo = digitRegex(loc, "{1,2}"), oneToThree = digitRegex(loc, "{1,3}"), oneToSix = digitRegex(loc, "{1,6}"), oneToNine = digitRegex(loc, "{1,9}"), twoToFour = digitRegex(loc, "{2,4}"), fourToSix = digitRegex(loc, "{4,6}"), literal = (
|
|
15504
|
-
regex: RegExp(escapeToken(
|
|
15503
|
+
const one = digitRegex(loc), two = digitRegex(loc, "{2}"), three = digitRegex(loc, "{3}"), four = digitRegex(loc, "{4}"), six = digitRegex(loc, "{6}"), oneOrTwo = digitRegex(loc, "{1,2}"), oneToThree = digitRegex(loc, "{1,3}"), oneToSix = digitRegex(loc, "{1,6}"), oneToNine = digitRegex(loc, "{1,9}"), twoToFour = digitRegex(loc, "{2,4}"), fourToSix = digitRegex(loc, "{4,6}"), literal = (t3) => ({
|
|
15504
|
+
regex: RegExp(escapeToken(t3.val)),
|
|
15505
15505
|
deser: ([s2]) => s2,
|
|
15506
15506
|
literal: true
|
|
15507
|
-
}), unitate = (
|
|
15507
|
+
}), unitate = (t3) => {
|
|
15508
15508
|
if (token.literal) {
|
|
15509
|
-
return literal(
|
|
15509
|
+
return literal(t3);
|
|
15510
15510
|
}
|
|
15511
|
-
switch (
|
|
15511
|
+
switch (t3.val) {
|
|
15512
15512
|
// era
|
|
15513
15513
|
case "G":
|
|
15514
15514
|
return oneOf(loc.eras("short"), 0);
|
|
@@ -15623,7 +15623,7 @@ var require_luxon = __commonJS({
|
|
|
15623
15623
|
case " ":
|
|
15624
15624
|
return simple(/[^\S\n\r]/);
|
|
15625
15625
|
default:
|
|
15626
|
-
return literal(
|
|
15626
|
+
return literal(t3);
|
|
15627
15627
|
}
|
|
15628
15628
|
};
|
|
15629
15629
|
const unit = unitate(token) || {
|
|
@@ -15825,15 +15825,15 @@ var require_luxon = __commonJS({
|
|
|
15825
15825
|
return tokens;
|
|
15826
15826
|
}
|
|
15827
15827
|
function expandMacroTokens(tokens, locale) {
|
|
15828
|
-
return Array.prototype.concat(...tokens.map((
|
|
15828
|
+
return Array.prototype.concat(...tokens.map((t3) => maybeExpandMacroToken(t3, locale)));
|
|
15829
15829
|
}
|
|
15830
15830
|
var TokenParser = class {
|
|
15831
15831
|
constructor(locale, format) {
|
|
15832
15832
|
this.locale = locale;
|
|
15833
15833
|
this.format = format;
|
|
15834
15834
|
this.tokens = expandMacroTokens(Formatter.parseFormat(format), locale);
|
|
15835
|
-
this.units = this.tokens.map((
|
|
15836
|
-
this.disqualifyingUnit = this.units.find((
|
|
15835
|
+
this.units = this.tokens.map((t3) => unitForToken(t3, locale));
|
|
15836
|
+
this.disqualifyingUnit = this.units.find((t3) => t3.invalidReason);
|
|
15837
15837
|
if (!this.disqualifyingUnit) {
|
|
15838
15838
|
const [regexString, handlers] = buildRegex(this.units);
|
|
15839
15839
|
this.regex = RegExp(regexString, "i");
|
|
@@ -16658,7 +16658,7 @@ var require_luxon = __commonJS({
|
|
|
16658
16658
|
*/
|
|
16659
16659
|
static parseFormatForOpts(formatOpts, localeOpts = {}) {
|
|
16660
16660
|
const tokenList = formatOptsToTokens(formatOpts, Locale.fromObject(localeOpts));
|
|
16661
|
-
return !tokenList ? null : tokenList.map((
|
|
16661
|
+
return !tokenList ? null : tokenList.map((t3) => t3 ? t3.val : null).join("");
|
|
16662
16662
|
}
|
|
16663
16663
|
/**
|
|
16664
16664
|
* Produce the the fully expanded format token for the locale
|
|
@@ -16669,7 +16669,7 @@ var require_luxon = __commonJS({
|
|
|
16669
16669
|
*/
|
|
16670
16670
|
static expandFormat(fmt, localeOpts = {}) {
|
|
16671
16671
|
const expanded = expandMacroTokens(Formatter.parseFormat(fmt), Locale.fromObject(localeOpts));
|
|
16672
|
-
return expanded.map((
|
|
16672
|
+
return expanded.map((t3) => t3.val).join("");
|
|
16673
16673
|
}
|
|
16674
16674
|
static resetCache() {
|
|
16675
16675
|
zoneOffsetTs = void 0;
|
|
@@ -19526,10 +19526,10 @@ var require_random = __commonJS({
|
|
|
19526
19526
|
}
|
|
19527
19527
|
function mulberry32(seed) {
|
|
19528
19528
|
return () => {
|
|
19529
|
-
let
|
|
19530
|
-
|
|
19531
|
-
|
|
19532
|
-
return ((
|
|
19529
|
+
let t3 = seed += 1831565813;
|
|
19530
|
+
t3 = Math.imul(t3 ^ t3 >>> 15, t3 | 1);
|
|
19531
|
+
t3 ^= t3 + Math.imul(t3 ^ t3 >>> 7, t3 | 61);
|
|
19532
|
+
return ((t3 ^ t3 >>> 14) >>> 0) / 4294967296;
|
|
19533
19533
|
};
|
|
19534
19534
|
}
|
|
19535
19535
|
function seededRandom(str) {
|
|
@@ -21542,6 +21542,25 @@ function currentGatewayRuntime(gatewayEntry = resolveGatewayEntry()) {
|
|
|
21542
21542
|
env: { ...process.env }
|
|
21543
21543
|
};
|
|
21544
21544
|
}
|
|
21545
|
+
function refreshGatewayExecutionEnvironment(runtime, gatewayEntry) {
|
|
21546
|
+
const env = { ...process.env };
|
|
21547
|
+
for (const key of /* @__PURE__ */ new Set([
|
|
21548
|
+
...Object.keys(runtime.env).filter((name) => name.startsWith("SUPERTASK_")),
|
|
21549
|
+
...Object.keys(env).filter((name) => name.startsWith("SUPERTASK_")),
|
|
21550
|
+
"HOME",
|
|
21551
|
+
"PATH",
|
|
21552
|
+
"PM2_HOME"
|
|
21553
|
+
])) {
|
|
21554
|
+
const value = runtime.env[key];
|
|
21555
|
+
if (value === void 0) delete env[key];
|
|
21556
|
+
else env[key] = value;
|
|
21557
|
+
}
|
|
21558
|
+
return {
|
|
21559
|
+
...runtime,
|
|
21560
|
+
gatewayEntry: resolve3(gatewayEntry),
|
|
21561
|
+
env
|
|
21562
|
+
};
|
|
21563
|
+
}
|
|
21545
21564
|
function isGatewayRunning() {
|
|
21546
21565
|
if (!isPm2Installed()) return false;
|
|
21547
21566
|
const proc = pm2JsonList().find((item) => item.name === PROCESS_NAME);
|
|
@@ -21894,7 +21913,7 @@ function installUnlocked() {
|
|
|
21894
21913
|
}
|
|
21895
21914
|
const existing = pm2JsonList().find((item) => item.name === PROCESS_NAME);
|
|
21896
21915
|
const oldRuntime = gatewayRuntimeFromProcess(existing);
|
|
21897
|
-
const targetRuntime = oldRuntime ?
|
|
21916
|
+
const targetRuntime = oldRuntime ? refreshGatewayExecutionEnvironment(oldRuntime, resolveGatewayEntry()) : currentGatewayRuntime();
|
|
21898
21917
|
const before = getRunningVersion(oldRuntime?.env ?? process.env, oldRuntime?.cwd);
|
|
21899
21918
|
if (oldRuntime && !scopesMatch(currentScope(), runtimeScope(oldRuntime))) {
|
|
21900
21919
|
throw new Error("[supertask] \u5F53\u524D CLI \u4E0E PM2 Gateway \u7684\u6570\u636E\u5E93/\u914D\u7F6E/OpenCode \u8FD0\u884C\u4F5C\u7528\u57DF\u4E0D\u4E00\u81F4\uFF0C\u5DF2\u62D2\u7EDD\u8986\u76D6");
|
|
@@ -22007,7 +22026,10 @@ function upgradeUnlocked(target) {
|
|
|
22007
22026
|
const oldRuntime = gatewayRuntimeFromProcess(existing) ?? (process.env.SUPERTASK_GATEWAY_ENTRY ? currentGatewayRuntime(resolveGatewayEntry()) : null);
|
|
22008
22027
|
const before = getRunningVersion(oldRuntime?.env ?? process.env, oldRuntime?.cwd);
|
|
22009
22028
|
const currentVersion = target?.version ?? getPackageVersion();
|
|
22010
|
-
const targetRuntime = oldRuntime ?
|
|
22029
|
+
const targetRuntime = oldRuntime ? refreshGatewayExecutionEnvironment(
|
|
22030
|
+
oldRuntime,
|
|
22031
|
+
target?.gatewayEntry ?? oldRuntime.gatewayEntry
|
|
22032
|
+
) : currentGatewayRuntime(target?.gatewayEntry ?? resolveGatewayEntry());
|
|
22011
22033
|
assertRuntimeCanControlPm2(oldRuntime, existing);
|
|
22012
22034
|
gatewayKillTimeoutMs(targetRuntime);
|
|
22013
22035
|
gatewayTerminationCommandTimeoutMs(targetRuntime);
|
|
@@ -22163,17 +22185,19 @@ var init_semver = __esm({
|
|
|
22163
22185
|
// src/daemon/update.ts
|
|
22164
22186
|
var update_exports = {};
|
|
22165
22187
|
__export(update_exports, {
|
|
22188
|
+
getGlobalCliDiagnostic: () => getGlobalCliDiagnostic,
|
|
22166
22189
|
getOpenCodePluginDiagnostic: () => getOpenCodePluginDiagnostic,
|
|
22167
22190
|
installLatestPlugin: () => installLatestPlugin,
|
|
22168
22191
|
installPluginVersion: () => installPluginVersion,
|
|
22169
22192
|
resolveConfiguredPluginSpec: () => resolveConfiguredPluginSpec,
|
|
22170
22193
|
resolveInstalledPlugin: () => resolveInstalledPlugin,
|
|
22171
|
-
resolveInstalledPluginVersion: () => resolveInstalledPluginVersion
|
|
22194
|
+
resolveInstalledPluginVersion: () => resolveInstalledPluginVersion,
|
|
22195
|
+
updateGlobalCli: () => updateGlobalCli
|
|
22172
22196
|
});
|
|
22173
22197
|
import { spawnSync as spawnSync3 } from "child_process";
|
|
22174
|
-
import { existsSync as existsSync6, readFileSync as readFileSync4, readdirSync } from "fs";
|
|
22198
|
+
import { existsSync as existsSync6, readFileSync as readFileSync4, readdirSync, realpathSync } from "fs";
|
|
22175
22199
|
import { homedir as homedir4 } from "os";
|
|
22176
|
-
import { join as join5 } from "path";
|
|
22200
|
+
import { dirname as dirname7, join as join5, resolve as resolve4 } from "path";
|
|
22177
22201
|
function pluginAt(packageDir) {
|
|
22178
22202
|
const packageJson = join5(packageDir, "package.json");
|
|
22179
22203
|
const gatewayEntry = join5(packageDir, "dist/gateway/index.js");
|
|
@@ -22216,6 +22240,131 @@ function opencodeBin() {
|
|
|
22216
22240
|
function npmBin() {
|
|
22217
22241
|
return process.env.SUPERTASK_NPM_BIN ?? "npm";
|
|
22218
22242
|
}
|
|
22243
|
+
function bunBin() {
|
|
22244
|
+
return process.env.SUPERTASK_BUN_BIN ?? "bun";
|
|
22245
|
+
}
|
|
22246
|
+
function resolveGlobalCliExecutable() {
|
|
22247
|
+
const override = process.env.SUPERTASK_CLI_BIN;
|
|
22248
|
+
if (override) return existsSync6(override) ? resolve4(override) : null;
|
|
22249
|
+
const result = spawnSync3(process.platform === "win32" ? "where" : "which", ["supertask"], {
|
|
22250
|
+
encoding: "utf8",
|
|
22251
|
+
env: process.env,
|
|
22252
|
+
timeout: 1e4
|
|
22253
|
+
});
|
|
22254
|
+
if (result.status !== 0) return null;
|
|
22255
|
+
const executable = `${result.stdout ?? ""}`.trim().split(/\r?\n/)[0];
|
|
22256
|
+
return executable && existsSync6(executable) ? resolve4(executable) : null;
|
|
22257
|
+
}
|
|
22258
|
+
function cliPackageDir(executable) {
|
|
22259
|
+
try {
|
|
22260
|
+
let directory = dirname7(realpathSync(executable));
|
|
22261
|
+
for (let depth = 0; depth < 6; depth += 1) {
|
|
22262
|
+
const packagePath = join5(directory, "package.json");
|
|
22263
|
+
if (existsSync6(packagePath)) {
|
|
22264
|
+
const pkg = JSON.parse(readFileSync4(packagePath, "utf8"));
|
|
22265
|
+
if (pkg.name === PACKAGE_NAME) return directory;
|
|
22266
|
+
}
|
|
22267
|
+
const parent = dirname7(directory);
|
|
22268
|
+
if (parent === directory) break;
|
|
22269
|
+
directory = parent;
|
|
22270
|
+
}
|
|
22271
|
+
} catch {
|
|
22272
|
+
}
|
|
22273
|
+
return null;
|
|
22274
|
+
}
|
|
22275
|
+
function packageVersion(packageDir) {
|
|
22276
|
+
try {
|
|
22277
|
+
const pkg = JSON.parse(readFileSync4(join5(packageDir, "package.json"), "utf8"));
|
|
22278
|
+
return pkg.name === PACKAGE_NAME && typeof pkg.version === "string" ? pkg.version : null;
|
|
22279
|
+
} catch {
|
|
22280
|
+
return null;
|
|
22281
|
+
}
|
|
22282
|
+
}
|
|
22283
|
+
function npmGlobalRoot() {
|
|
22284
|
+
const result = spawnSync3(npmBin(), ["root", "-g"], {
|
|
22285
|
+
encoding: "utf8",
|
|
22286
|
+
env: process.env,
|
|
22287
|
+
timeout: 3e4
|
|
22288
|
+
});
|
|
22289
|
+
if (result.status !== 0) return null;
|
|
22290
|
+
const root = `${result.stdout ?? ""}`.trim();
|
|
22291
|
+
if (!root) return null;
|
|
22292
|
+
try {
|
|
22293
|
+
return realpathSync(root);
|
|
22294
|
+
} catch {
|
|
22295
|
+
return resolve4(root);
|
|
22296
|
+
}
|
|
22297
|
+
}
|
|
22298
|
+
function globalCliPackageManager(packageDir) {
|
|
22299
|
+
const normalized = packageDir.replaceAll("\\", "/");
|
|
22300
|
+
if (normalized.includes("/install/global/node_modules/")) return "bun";
|
|
22301
|
+
const npmRoot = npmGlobalRoot();
|
|
22302
|
+
if (npmRoot && resolve4(packageDir) === join5(npmRoot, PACKAGE_NAME)) return "npm";
|
|
22303
|
+
return null;
|
|
22304
|
+
}
|
|
22305
|
+
function getGlobalCliDiagnostic() {
|
|
22306
|
+
const executable = resolveGlobalCliExecutable();
|
|
22307
|
+
if (!executable) {
|
|
22308
|
+
return {
|
|
22309
|
+
installed: false,
|
|
22310
|
+
executable: null,
|
|
22311
|
+
packageDir: null,
|
|
22312
|
+
version: null,
|
|
22313
|
+
packageManager: null
|
|
22314
|
+
};
|
|
22315
|
+
}
|
|
22316
|
+
const packageDir = cliPackageDir(executable);
|
|
22317
|
+
if (!packageDir) {
|
|
22318
|
+
return {
|
|
22319
|
+
installed: true,
|
|
22320
|
+
executable,
|
|
22321
|
+
packageDir: null,
|
|
22322
|
+
version: null,
|
|
22323
|
+
packageManager: null
|
|
22324
|
+
};
|
|
22325
|
+
}
|
|
22326
|
+
return {
|
|
22327
|
+
installed: true,
|
|
22328
|
+
executable,
|
|
22329
|
+
packageDir,
|
|
22330
|
+
version: packageVersion(packageDir),
|
|
22331
|
+
packageManager: globalCliPackageManager(packageDir)
|
|
22332
|
+
};
|
|
22333
|
+
}
|
|
22334
|
+
function updateGlobalCli(version2) {
|
|
22335
|
+
if (!isSemanticVersion(version2)) {
|
|
22336
|
+
throw new Error(`[supertask] \u5168\u5C40 CLI \u76EE\u6807\u7248\u672C\u65E0\u6548: ${version2}`);
|
|
22337
|
+
}
|
|
22338
|
+
const before = getGlobalCliDiagnostic();
|
|
22339
|
+
if (!before.installed) return { ...before, action: "not-installed" };
|
|
22340
|
+
if (before.version === version2) return { ...before, action: "already-current" };
|
|
22341
|
+
if (!before.packageManager) {
|
|
22342
|
+
throw new Error(
|
|
22343
|
+
`[supertask] \u65E0\u6CD5\u786E\u8BA4\u5168\u5C40 CLI \u7684\u5305\u7BA1\u7406\u5668\uFF08\u5F53\u524D ${before.version ?? "unknown"}\uFF0C\u76EE\u6807 ${version2}\uFF09\uFF1B\u8BF7\u6267\u884C npm install -g ${PACKAGE_NAME}@${version2} \u6216 bun add -g ${PACKAGE_NAME}@${version2}`
|
|
22344
|
+
);
|
|
22345
|
+
}
|
|
22346
|
+
const command = before.packageManager === "npm" ? npmBin() : bunBin();
|
|
22347
|
+
const args = before.packageManager === "npm" ? ["install", "-g", `${PACKAGE_NAME}@${version2}`] : ["add", "-g", `${PACKAGE_NAME}@${version2}`];
|
|
22348
|
+
const result = spawnSync3(command, args, {
|
|
22349
|
+
encoding: "utf8",
|
|
22350
|
+
env: process.env,
|
|
22351
|
+
timeout: 12e4
|
|
22352
|
+
});
|
|
22353
|
+
const output = `${result.stdout ?? ""}${result.stderr ?? ""}`.trim();
|
|
22354
|
+
if (result.error) {
|
|
22355
|
+
throw new Error(`[supertask] \u5168\u5C40 CLI \u66F4\u65B0\u5931\u8D25: ${result.error.message}`);
|
|
22356
|
+
}
|
|
22357
|
+
if (result.status !== 0) {
|
|
22358
|
+
throw new Error(`[supertask] \u5168\u5C40 CLI \u66F4\u65B0\u5931\u8D25: ${output || `\u9000\u51FA\u7801 ${result.status}`}`);
|
|
22359
|
+
}
|
|
22360
|
+
const after = getGlobalCliDiagnostic();
|
|
22361
|
+
if (after.version !== version2) {
|
|
22362
|
+
throw new Error(
|
|
22363
|
+
`[supertask] \u5168\u5C40 CLI \u66F4\u65B0\u540E\u7248\u672C\u4E0D\u5339\u914D\uFF1A\u671F\u671B ${version2}\uFF0C\u5B9E\u9645 ${after.version ?? "unknown"}`
|
|
22364
|
+
);
|
|
22365
|
+
}
|
|
22366
|
+
return { ...after, action: "updated" };
|
|
22367
|
+
}
|
|
22219
22368
|
function latestVersion() {
|
|
22220
22369
|
const result = spawnSync3(npmBin(), [
|
|
22221
22370
|
"view",
|
|
@@ -22515,8 +22664,16 @@ var init_health = __esm({
|
|
|
22515
22664
|
import { spawn } from "child_process";
|
|
22516
22665
|
import { fileURLToPath as fileURLToPath5 } from "url";
|
|
22517
22666
|
import { existsSync as existsSync7 } from "fs";
|
|
22518
|
-
import { dirname as
|
|
22667
|
+
import { dirname as dirname8, join as join6 } from "path";
|
|
22519
22668
|
import { randomUUID as randomUUID2 } from "crypto";
|
|
22669
|
+
function runCommandContext(executable, args, cwd) {
|
|
22670
|
+
return JSON.stringify({
|
|
22671
|
+
type: "supertask_command",
|
|
22672
|
+
executable,
|
|
22673
|
+
args,
|
|
22674
|
+
cwd
|
|
22675
|
+
});
|
|
22676
|
+
}
|
|
22520
22677
|
function assertWorkerProcessIsolationSupported(platform = process.platform) {
|
|
22521
22678
|
if (platform === "win32") {
|
|
22522
22679
|
throw new Error(
|
|
@@ -22704,7 +22861,7 @@ var init_worker = __esm({
|
|
|
22704
22861
|
}
|
|
22705
22862
|
launcherEntry() {
|
|
22706
22863
|
const extension = import.meta.url.endsWith(".ts") ? "ts" : "js";
|
|
22707
|
-
const moduleDir =
|
|
22864
|
+
const moduleDir = dirname8(fileURLToPath5(import.meta.url));
|
|
22708
22865
|
const candidates = [
|
|
22709
22866
|
join6(moduleDir, `launcher.${extension}`),
|
|
22710
22867
|
join6(moduleDir, `../worker/launcher.${extension}`)
|
|
@@ -22738,6 +22895,7 @@ var init_worker = __esm({
|
|
|
22738
22895
|
runId,
|
|
22739
22896
|
launchIdentity,
|
|
22740
22897
|
child,
|
|
22898
|
+
commandContext: runCommandContext(this.opencodeBin, args, task.cwd || process.cwd()),
|
|
22741
22899
|
output: "",
|
|
22742
22900
|
sessionId: null,
|
|
22743
22901
|
timeoutTimer: null,
|
|
@@ -22773,8 +22931,8 @@ var init_worker = __esm({
|
|
|
22773
22931
|
}
|
|
22774
22932
|
});
|
|
22775
22933
|
let spawnError = null;
|
|
22776
|
-
const spawned = new Promise((
|
|
22777
|
-
child.once("spawn",
|
|
22934
|
+
const spawned = new Promise((resolve5, reject) => {
|
|
22935
|
+
child.once("spawn", resolve5);
|
|
22778
22936
|
child.once("error", (error) => {
|
|
22779
22937
|
spawnError = error;
|
|
22780
22938
|
reject(error);
|
|
@@ -22822,10 +22980,10 @@ var init_worker = __esm({
|
|
|
22822
22980
|
return;
|
|
22823
22981
|
}
|
|
22824
22982
|
try {
|
|
22825
|
-
await new Promise((
|
|
22983
|
+
await new Promise((resolve5, reject) => {
|
|
22826
22984
|
child.stdin.end("START\n", (error) => {
|
|
22827
22985
|
if (error) reject(error);
|
|
22828
|
-
else
|
|
22986
|
+
else resolve5();
|
|
22829
22987
|
});
|
|
22830
22988
|
});
|
|
22831
22989
|
} catch (error) {
|
|
@@ -22872,7 +23030,7 @@ var init_worker = __esm({
|
|
|
22872
23030
|
);
|
|
22873
23031
|
return;
|
|
22874
23032
|
}
|
|
22875
|
-
const failure = code === 0 ? void 0 : `${spawnError ? "\u65E0\u6CD5\u542F\u52A8 opencode" : "opencode \u9000\u51FA\u7801"} ${spawnError?.message ?? code ?? "null"}${signal ? `\uFF0C\u4FE1\u53F7 ${signal}` : ""}`;
|
|
23033
|
+
const failure = code === 0 ? void 0 : `${spawnError ? "\u65E0\u6CD5\u542F\u52A8 opencode" : "opencode \u9000\u51FA\u7801"} ${spawnError?.message ?? code ?? "null"}${signal ? `\uFF0C\u4FE1\u53F7 ${signal}` : ""}\uFF08agent=${entry.task.agent}\uFF0Cmodel=${this.resolveModel(entry.task.model) ?? "Agent/\u9ED8\u8BA4\u914D\u7F6E"}\uFF0Ccwd=${entry.task.cwd ?? process.cwd()}\uFF09`;
|
|
22876
23034
|
this.runDetached(
|
|
22877
23035
|
this.settleEntry(entry, code, failure),
|
|
22878
23036
|
"task settlement failed",
|
|
@@ -22902,7 +23060,7 @@ var init_worker = __esm({
|
|
|
22902
23060
|
const termination = entry.termination;
|
|
22903
23061
|
if (termination?.kind === "shutdown") return;
|
|
22904
23062
|
if (termination?.kind === "cancel") {
|
|
22905
|
-
const output2 =
|
|
23063
|
+
const output2 = this.outputWithCommand(entry);
|
|
22906
23064
|
const log2 = `${termination.message}${output2 ? `
|
|
22907
23065
|
${output2}` : ""}`;
|
|
22908
23066
|
await TaskRunService.fail(entry.runId, log2);
|
|
@@ -22916,7 +23074,7 @@ ${output2}` : ""}`;
|
|
|
22916
23074
|
}
|
|
22917
23075
|
const currentRun = await TaskRunService.getById(entry.runId);
|
|
22918
23076
|
if (!currentRun || currentRun.status !== "running") return;
|
|
22919
|
-
const output =
|
|
23077
|
+
const output = this.outputWithCommand(entry);
|
|
22920
23078
|
const log = failure ? `${failure}${output ? `
|
|
22921
23079
|
${output}` : ""}` : output;
|
|
22922
23080
|
if (code === 0 && !failure) {
|
|
@@ -23052,6 +23210,11 @@ ${output}` : ""}` : output;
|
|
|
23052
23210
|
const batchId = normalizeTaskBatchId(task.batchId);
|
|
23053
23211
|
if (batchId) this.activeBatchIds.delete(batchId);
|
|
23054
23212
|
}
|
|
23213
|
+
outputWithCommand(entry) {
|
|
23214
|
+
const output = entry.output.trim();
|
|
23215
|
+
return `${entry.commandContext}${output ? `
|
|
23216
|
+
${output}` : ""}`;
|
|
23217
|
+
}
|
|
23055
23218
|
resolveModel(taskModel) {
|
|
23056
23219
|
if (!taskModel || taskModel === "default") return null;
|
|
23057
23220
|
return taskModel;
|
|
@@ -25828,6 +25991,116 @@ var init_dist = __esm({
|
|
|
25828
25991
|
}
|
|
25829
25992
|
});
|
|
25830
25993
|
|
|
25994
|
+
// src/core/opencode-catalog.ts
|
|
25995
|
+
import { spawn as spawn2 } from "child_process";
|
|
25996
|
+
function cleanOutput(value) {
|
|
25997
|
+
return value.replace(ANSI_PATTERN, "").replace(/\r/g, "");
|
|
25998
|
+
}
|
|
25999
|
+
function runOpenCode(executable, args, cwd, timeoutMs) {
|
|
26000
|
+
return new Promise((resolve5, reject) => {
|
|
26001
|
+
const child = spawn2(executable, args, {
|
|
26002
|
+
cwd,
|
|
26003
|
+
env: process.env,
|
|
26004
|
+
stdio: ["ignore", "pipe", "pipe"]
|
|
26005
|
+
});
|
|
26006
|
+
let stdout = "";
|
|
26007
|
+
let stderr = "";
|
|
26008
|
+
let failure = null;
|
|
26009
|
+
let finished = false;
|
|
26010
|
+
const append = (current, chunk) => {
|
|
26011
|
+
const next = current + chunk.toString();
|
|
26012
|
+
if (Buffer.byteLength(next) > MAX_OUTPUT_BYTES && failure === null) {
|
|
26013
|
+
failure = new Error(`OpenCode \u8F93\u51FA\u8D85\u8FC7 ${MAX_OUTPUT_BYTES} bytes`);
|
|
26014
|
+
child.kill("SIGTERM");
|
|
26015
|
+
}
|
|
26016
|
+
return next.slice(-MAX_OUTPUT_BYTES);
|
|
26017
|
+
};
|
|
26018
|
+
child.stdout?.on("data", (chunk) => {
|
|
26019
|
+
stdout = append(stdout, chunk);
|
|
26020
|
+
});
|
|
26021
|
+
child.stderr?.on("data", (chunk) => {
|
|
26022
|
+
stderr = append(stderr, chunk);
|
|
26023
|
+
});
|
|
26024
|
+
child.once("error", (error) => {
|
|
26025
|
+
failure ??= error;
|
|
26026
|
+
});
|
|
26027
|
+
const timer = setTimeout(() => {
|
|
26028
|
+
failure ??= new Error(`OpenCode \u547D\u4EE4\u8D85\u8FC7 ${timeoutMs}ms \u672A\u5B8C\u6210`);
|
|
26029
|
+
child.kill("SIGTERM");
|
|
26030
|
+
}, timeoutMs);
|
|
26031
|
+
child.once("close", (code) => {
|
|
26032
|
+
if (finished) return;
|
|
26033
|
+
finished = true;
|
|
26034
|
+
clearTimeout(timer);
|
|
26035
|
+
if (failure) {
|
|
26036
|
+
reject(failure);
|
|
26037
|
+
return;
|
|
26038
|
+
}
|
|
26039
|
+
if (code !== 0) {
|
|
26040
|
+
const detail = cleanOutput(stderr).trim() || `\u9000\u51FA\u7801 ${code ?? "null"}`;
|
|
26041
|
+
reject(new Error(`OpenCode ${args.join(" ")} \u5931\u8D25\uFF1A${detail}`));
|
|
26042
|
+
return;
|
|
26043
|
+
}
|
|
26044
|
+
resolve5(cleanOutput(stdout));
|
|
26045
|
+
});
|
|
26046
|
+
});
|
|
26047
|
+
}
|
|
26048
|
+
function parseOpenCodeModels(output) {
|
|
26049
|
+
return [...new Set(cleanOutput(output).split("\n").map((line) => line.trim()).filter((line) => /^[^\s/]+\/.+/.test(line)))].sort((left, right) => left.localeCompare(right));
|
|
26050
|
+
}
|
|
26051
|
+
function parseOpenCodeAgents(output) {
|
|
26052
|
+
const agents = /* @__PURE__ */ new Map();
|
|
26053
|
+
for (const line of cleanOutput(output).split("\n")) {
|
|
26054
|
+
const match2 = /^([^\s()]+) \((primary|subagent|all)\)$/.exec(line.trim());
|
|
26055
|
+
if (!match2) continue;
|
|
26056
|
+
const name = match2[1];
|
|
26057
|
+
const mode = match2[2];
|
|
26058
|
+
if (name === "supertask-runner") continue;
|
|
26059
|
+
agents.set(name, { name, mode });
|
|
26060
|
+
}
|
|
26061
|
+
const rank = { primary: 0, all: 1, subagent: 2 };
|
|
26062
|
+
return [...agents.values()].sort((left, right) => rank[left.mode] - rank[right.mode] || left.name.localeCompare(right.name));
|
|
26063
|
+
}
|
|
26064
|
+
async function loadOpenCodeCatalog(cwd, options = {}) {
|
|
26065
|
+
validateTaskWorkingDirectory(cwd);
|
|
26066
|
+
const executable = options.executable ?? process.env.SUPERTASK_OPENCODE_BIN ?? "opencode";
|
|
26067
|
+
const timeoutMs = options.timeoutMs ?? COMMAND_TIMEOUT_MS;
|
|
26068
|
+
const cacheKey = `${executable}\0${cwd}`;
|
|
26069
|
+
const cached = catalogCache.get(cacheKey);
|
|
26070
|
+
if (options.useCache !== false && cached && cached.expiresAt > Date.now()) {
|
|
26071
|
+
return cached.result;
|
|
26072
|
+
}
|
|
26073
|
+
const result = Promise.all([
|
|
26074
|
+
runOpenCode(executable, ["models"], cwd, timeoutMs),
|
|
26075
|
+
runOpenCode(executable, ["agent", "list"], cwd, timeoutMs)
|
|
26076
|
+
]).then(([modelsOutput, agentsOutput]) => {
|
|
26077
|
+
const models = parseOpenCodeModels(modelsOutput);
|
|
26078
|
+
const agents = parseOpenCodeAgents(agentsOutput).filter((agent) => agent.mode !== "subagent");
|
|
26079
|
+
if (models.length === 0) throw new Error("OpenCode \u6CA1\u6709\u8FD4\u56DE\u53EF\u7528\u6A21\u578B");
|
|
26080
|
+
if (agents.length === 0) throw new Error("OpenCode \u6CA1\u6709\u8FD4\u56DE\u53EF\u76F4\u63A5\u8FD0\u884C\u7684\u4E3B Agent");
|
|
26081
|
+
return { cwd, models, agents };
|
|
26082
|
+
});
|
|
26083
|
+
if (options.useCache !== false) {
|
|
26084
|
+
catalogCache.set(cacheKey, { expiresAt: Date.now() + CATALOG_CACHE_MS, result });
|
|
26085
|
+
result.catch(() => {
|
|
26086
|
+
if (catalogCache.get(cacheKey)?.result === result) catalogCache.delete(cacheKey);
|
|
26087
|
+
});
|
|
26088
|
+
}
|
|
26089
|
+
return result;
|
|
26090
|
+
}
|
|
26091
|
+
var CATALOG_CACHE_MS, COMMAND_TIMEOUT_MS, MAX_OUTPUT_BYTES, ANSI_PATTERN, catalogCache;
|
|
26092
|
+
var init_opencode_catalog = __esm({
|
|
26093
|
+
"src/core/opencode-catalog.ts"() {
|
|
26094
|
+
"use strict";
|
|
26095
|
+
init_task_working_directory();
|
|
26096
|
+
CATALOG_CACHE_MS = 3e4;
|
|
26097
|
+
COMMAND_TIMEOUT_MS = 2e4;
|
|
26098
|
+
MAX_OUTPUT_BYTES = 4 * 1024 * 1024;
|
|
26099
|
+
ANSI_PATTERN = /\x1B(?:[@-_][0-?]*[ -/]*[@-~]|\][^\x07]*(?:\x07|\x1B\\))/g;
|
|
26100
|
+
catalogCache = /* @__PURE__ */ new Map();
|
|
26101
|
+
}
|
|
26102
|
+
});
|
|
26103
|
+
|
|
25831
26104
|
// src/web/ui.ts
|
|
25832
26105
|
function t(locale, key, values = {}) {
|
|
25833
26106
|
const template = (locale === "en" ? EN : ZH)[key];
|
|
@@ -25891,7 +26164,8 @@ function icon(name, className = "icon") {
|
|
|
25891
26164
|
check: '<path d="m5 12 4 4L19 6"/>',
|
|
25892
26165
|
alert: '<path d="M12 3 2.8 19h18.4L12 3Z"/><path d="M12 9v4M12 17h.01"/>',
|
|
25893
26166
|
clock: '<circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/>',
|
|
25894
|
-
database: '<ellipse cx="12" cy="5" rx="8" ry="3"/><path d="M4 5v6c0 1.66 3.58 3 8 3s8-1.34 8-3V5M4 11v6c0 1.66 3.58 3 8 3s8-1.34 8-3v-6"/>'
|
|
26167
|
+
database: '<ellipse cx="12" cy="5" rx="8" ry="3"/><path d="M4 5v6c0 1.66 3.58 3 8 3s8-1.34 8-3V5M4 11v6c0 1.66 3.58 3 8 3s8-1.34 8-3v-6"/>',
|
|
26168
|
+
folder: '<path d="M3 7.5A2.5 2.5 0 0 1 5.5 5H10l2 2h6.5A2.5 2.5 0 0 1 21 9.5v7A2.5 2.5 0 0 1 18.5 19h-13A2.5 2.5 0 0 1 3 16.5v-9Z"/>'
|
|
25895
26169
|
};
|
|
25896
26170
|
return `<svg class="${className}" viewBox="0 0 24 24" aria-hidden="true" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round">${paths[name]}</svg>`;
|
|
25897
26171
|
}
|
|
@@ -25946,7 +26220,20 @@ function clientMessages(locale) {
|
|
|
25946
26220
|
"feedback.restartTimeout",
|
|
25947
26221
|
"template.createTitle",
|
|
25948
26222
|
"template.editTitle",
|
|
25949
|
-
"filter.noResults"
|
|
26223
|
+
"filter.noResults",
|
|
26224
|
+
"catalog.chooseProject",
|
|
26225
|
+
"catalog.defaultModel",
|
|
26226
|
+
"catalog.defaultProvider",
|
|
26227
|
+
"catalog.loading",
|
|
26228
|
+
"catalog.loaded",
|
|
26229
|
+
"catalog.failed",
|
|
26230
|
+
"catalog.primary",
|
|
26231
|
+
"catalog.subagent",
|
|
26232
|
+
"catalog.all",
|
|
26233
|
+
"directory.empty",
|
|
26234
|
+
"feedback.commandCopied",
|
|
26235
|
+
"action.showHidden",
|
|
26236
|
+
"action.hideHidden"
|
|
25950
26237
|
];
|
|
25951
26238
|
return Object.fromEntries(keys.map((key) => [key, t(locale, key)]));
|
|
25952
26239
|
}
|
|
@@ -26014,6 +26301,11 @@ function renderLayout(options) {
|
|
|
26014
26301
|
<footer>${t(locale, "app.footer")}</footer>
|
|
26015
26302
|
</div>
|
|
26016
26303
|
<div id="toast-region" class="toast-region" role="status" aria-live="polite"></div>
|
|
26304
|
+
<dialog id="directory-dialog" class="directory-dialog">
|
|
26305
|
+
<div class="dialog-head"><div><h2>${t(locale, "directory.title")}</h2><p>${t(locale, "directory.subtitle")}</p></div><button type="button" class="icon-button" onclick="document.getElementById('directory-dialog').close()" aria-label="${t(locale, "action.close")}">${icon("close")}</button></div>
|
|
26306
|
+
<div class="dialog-body"><div class="directory-toolbar"><button id="directory-home" type="button" class="btn">${t(locale, "action.home")}</button><button id="directory-up" type="button" class="btn">${t(locale, "action.up")}</button><button id="directory-hidden" type="button" class="btn">${t(locale, "action.showHidden")}</button><div id="directory-path" class="directory-path"></div></div><div id="directory-list" class="directory-list"></div></div>
|
|
26307
|
+
<div class="dialog-actions"><button type="button" class="btn" onclick="document.getElementById('directory-dialog').close()">${t(locale, "action.cancel")}</button><button id="directory-choose" type="button" class="btn btn-primary">${icon("folder")}${t(locale, "action.chooseThisFolder")}</button></div>
|
|
26308
|
+
</dialog>
|
|
26017
26309
|
<dialog id="detail-dialog">
|
|
26018
26310
|
<div class="dialog-head"><div><h2>${t(locale, "details.title")}</h2><p>${t(locale, "details.subtitle")}</p></div><button class="icon-button" onclick="document.getElementById('detail-dialog').close()" aria-label="${t(locale, "action.close")}">${icon("close")}</button></div>
|
|
26019
26311
|
<div class="dialog-body"><pre id="detail-content" class="json-view"></pre></div>
|
|
@@ -26052,21 +26344,38 @@ function renderLayout(options) {
|
|
|
26052
26344
|
const showDetail=id=>showRecord('/api/tasks/'+id);const showRunDetail=id=>showRecord('/api/runs/'+id);const showTemplateDetail=id=>showRecord('/api/templates/'+id);
|
|
26053
26345
|
async function copyDetails(){try{await navigator.clipboard.writeText(document.getElementById('detail-content').textContent);showToast(text('details.copySuccess'))}catch{showToast(text('feedback.copyFailed'),'error')}}
|
|
26054
26346
|
async function copySessionCommand(id){try{const data=await readJson(await fetch('/api/runs/'+id+'/session-command'));await navigator.clipboard.writeText(data.command);showToast(text('feedback.sessionCommandCopied'))}catch(error){showToast(error.message||text('feedback.copyFailed'),'error')}}
|
|
26347
|
+
async function copyRunCommand(id){try{await navigator.clipboard.writeText(document.getElementById('command-'+id).textContent);showToast(text('feedback.commandCopied'))}catch{showToast(text('feedback.copyFailed'),'error')}}
|
|
26055
26348
|
function taskField(name){return document.getElementById('task-'+name)}
|
|
26349
|
+
function templateField(name){return document.getElementById('template-'+name)}
|
|
26056
26350
|
function taskProjects(){const node=document.getElementById('task-project-data');if(!node)return {};try{return JSON.parse(node.textContent||'{}')}catch{return {}}}
|
|
26057
26351
|
function updateTaskProjectStatus(){const node=taskField('project-status');if(!node)return;const cwd=taskField('cwd').value.trim();if(!cwd){node.textContent='';return}const project=taskProjects()[cwd];node.textContent=project?text('task.projectExisting',project):text('task.projectNew')}
|
|
26058
|
-
|
|
26059
|
-
|
|
26060
|
-
|
|
26061
|
-
function
|
|
26062
|
-
function
|
|
26352
|
+
const catalogTimers={};const catalogRequests={};const catalogModels={};
|
|
26353
|
+
function catalogField(prefix,name){return document.getElementById(prefix+'-'+name)}
|
|
26354
|
+
function resetCatalog(prefix){const agent=catalogField(prefix,'agent');const provider=catalogField(prefix,'model-provider');const model=catalogField(prefix,'model');if(!agent||!provider||!model)return;catalogModels[prefix]=[];agent.replaceChildren(new Option(text('catalog.chooseProject'),''));provider.replaceChildren(new Option(text('catalog.defaultProvider'),''));model.replaceChildren(new Option(text('catalog.defaultModel'),'default'));agent.disabled=false;provider.disabled=true;model.disabled=true;catalogField(prefix,'catalog-status').textContent='';}
|
|
26355
|
+
function appendCurrentOption(select,value){if(!value||[...select.options].some(option=>option.value===value))return;select.appendChild(new Option(value,value));}
|
|
26356
|
+
function modelProvider(value){const slash=value.indexOf('/');return slash>0?value.slice(0,slash):''}
|
|
26357
|
+
function populateModelOptions(prefix,preferredModel=''){const provider=catalogField(prefix,'model-provider');const model=catalogField(prefix,'model');if(!provider||!model)return;const selectedProvider=provider.value;model.replaceChildren();if(!selectedProvider){model.appendChild(new Option(text('catalog.defaultModel'),'default'));model.disabled=true;return}const available=(catalogModels[prefix]||[]).filter(value=>modelProvider(value)===selectedProvider);for(const value of available)model.appendChild(new Option(value,value));if(preferredModel&&available.includes(preferredModel))model.value=preferredModel;model.disabled=available.length===0}
|
|
26358
|
+
async function loadCatalog(prefix,preferredAgent='',preferredModel='default',preserveUnavailable=false){const cwd=catalogField(prefix,'cwd')?.value.trim()||'';const status=catalogField(prefix,'catalog-status');const agent=catalogField(prefix,'agent');const provider=catalogField(prefix,'model-provider');const model=catalogField(prefix,'model');if(!cwd||!status||!agent||!provider||!model){if(!cwd)resetCatalog(prefix);return}const request=(catalogRequests[prefix]||0)+1;catalogRequests[prefix]=request;status.dataset.state='loading';status.textContent=text('catalog.loading');agent.disabled=true;provider.disabled=true;model.disabled=true;try{const data=await readJson(await fetch('/api/opencode/catalog?cwd='+encodeURIComponent(cwd)));if(catalogRequests[prefix]!==request||catalogField(prefix,'cwd').value.trim()!==cwd)return;agent.replaceChildren();for(const item of data.agents){const label=item.name+' \u2014 '+text('catalog.'+item.mode);agent.appendChild(new Option(label,item.name))}if(preserveUnavailable)appendCurrentOption(agent,preferredAgent);const defaultAgent=preferredAgent||data.agents.find(item=>item.name==='build')?.name||data.agents.find(item=>item.mode==='primary')?.name||data.agents[0]?.name||'';agent.value=[...agent.options].some(option=>option.value===defaultAgent)?defaultAgent:(agent.options[0]?.value||'');catalogModels[prefix]=[...data.models];if(preserveUnavailable&&preferredModel&&preferredModel!=='default'&&!catalogModels[prefix].includes(preferredModel))catalogModels[prefix].push(preferredModel);provider.replaceChildren(new Option(text('catalog.defaultProvider'),''));for(const name of [...new Set(catalogModels[prefix].map(modelProvider).filter(Boolean))].sort())provider.appendChild(new Option(name,name));const preferredProvider=preferredModel==='default'?'':modelProvider(preferredModel);provider.value=[...provider.options].some(option=>option.value===preferredProvider)?preferredProvider:'';populateModelOptions(prefix,preferredModel);status.dataset.state='ready';status.textContent=text('catalog.loaded',{agents:data.agents.length,models:data.models.length})}catch(error){if(catalogRequests[prefix]!==request)return;resetCatalog(prefix);if(preserveUnavailable){appendCurrentOption(agent,preferredAgent);if(preferredModel&&preferredModel!=='default'){catalogModels[prefix]=[preferredModel];appendCurrentOption(provider,modelProvider(preferredModel));provider.value=modelProvider(preferredModel);populateModelOptions(prefix,preferredModel)}}status.dataset.state='error';status.textContent=text('catalog.failed',{error:error.message})}finally{if(catalogRequests[prefix]===request){agent.disabled=false;provider.disabled=false;if(provider.value)model.disabled=false}}}
|
|
26359
|
+
function scheduleCatalogLoad(prefix){clearTimeout(catalogTimers[prefix]);catalogTimers[prefix]=setTimeout(()=>loadCatalog(prefix),450)}
|
|
26360
|
+
let directoryTargetId='';let directoryCurrent='';let directoryEntries=[];let directoryShowHidden=false;
|
|
26361
|
+
function renderDirectoryEntries(){const list=document.getElementById('directory-list');list.replaceChildren();const entries=directoryEntries.filter(entry=>directoryShowHidden||!entry.hidden);const hidden=document.getElementById('directory-hidden');hidden.textContent=text(directoryShowHidden?'action.hideHidden':'action.showHidden');if(entries.length===0){const empty=document.createElement('div');empty.className='directory-empty';empty.textContent=text('directory.empty');list.appendChild(empty);return}for(const entry of entries){const button=document.createElement('button');button.type='button';button.className='directory-item';button.innerHTML='${icon("folder")}<span></span>';button.querySelector('span').textContent=entry.name;button.onclick=()=>browseDirectory(entry.path);list.appendChild(button)}}
|
|
26362
|
+
async function browseDirectory(path=''){const choose=document.getElementById('directory-choose');choose.disabled=true;try{const suffix=path?'?path='+encodeURIComponent(path):'';const data=await readJson(await fetch('/api/filesystem/directories'+suffix));directoryCurrent=data.path;directoryEntries=data.directories;document.getElementById('directory-path').textContent=data.path;document.getElementById('directory-up').disabled=data.parent===data.path;document.getElementById('directory-up').onclick=()=>browseDirectory(data.parent);document.getElementById('directory-home').onclick=()=>browseDirectory(data.home);renderDirectoryEntries();choose.disabled=false;return true}catch(error){directoryCurrent='';directoryEntries=[];document.getElementById('directory-path').textContent='';renderDirectoryEntries();showToast(error.message,'error');return false}}
|
|
26363
|
+
document.getElementById('directory-hidden').onclick=()=>{directoryShowHidden=!directoryShowHidden;renderDirectoryEntries()};
|
|
26364
|
+
async function openDirectoryPicker(targetId){const input=document.getElementById(targetId);if(!input||input.readOnly)return;directoryTargetId=targetId;directoryShowHidden=false;document.getElementById('directory-dialog').showModal();if(!await browseDirectory(input.value.trim()||''))await browseDirectory('')}
|
|
26365
|
+
document.getElementById('directory-choose').onclick=()=>{const input=document.getElementById(directoryTargetId);if(!input||!directoryCurrent)return;input.value=directoryCurrent;input.dispatchEvent(new Event('input',{bubbles:true}));document.getElementById('directory-dialog').close();const prefix=directoryTargetId.startsWith('task-')?'task':'template';loadCatalog(prefix)};
|
|
26366
|
+
function updateDurationControl(id){const preset=document.getElementById(id+'-preset');const custom=document.getElementById(id+'-custom');const input=document.getElementById(id+'-value');const visible=preset.value==='custom';custom.hidden=!visible;input.required=visible;if(visible&&!input.value)input.value='1'}
|
|
26367
|
+
function readDuration(id){const preset=document.getElementById(id+'-preset').value;if(preset==='')return '';if(preset!=='custom')return preset==='0'?'0':preset+'ms';const value=document.getElementById(id+'-value').value.trim();return value===''?'':value+document.getElementById(id+'-unit').value}
|
|
26368
|
+
function setDuration(id,milliseconds){const preset=document.getElementById(id+'-preset');const exact=milliseconds==null?'':String(milliseconds);if([...preset.options].some(option=>option.value===exact)){preset.value=exact;updateDurationControl(id);return}preset.value='custom';const input=document.getElementById(id+'-value');const unit=document.getElementById(id+'-unit');const units=[['d',86400000],['h',3600000],['min',60000],['s',1000]];let matched=false;for(const [name,factor] of units){if(milliseconds!=null&&(milliseconds===0||milliseconds%factor===0)){input.value=String(milliseconds/factor);unit.value=name;matched=true;break}}if(!matched){input.value=String((milliseconds??60000)/1000);unit.value='s'}updateDurationControl(id)}
|
|
26369
|
+
function openTaskCreator(){const form=document.getElementById('task-form');form.reset();taskField('id').value='';taskField('cwd').readOnly=false;taskField('cwd-picker').hidden=false;taskField('cwd').value=form.dataset.defaultCwd||'';setDuration('task-retry-backoff',30000);setDuration('task-timeout',null);taskField('dialog-title').textContent=text('task.createTitle');taskField('save').textContent=text('action.saveTask');updateTaskProjectStatus();resetCatalog('task');document.getElementById('task-dialog').showModal();if(taskField('cwd').value)loadCatalog('task');setTimeout(()=>taskField('name').focus(),50)}
|
|
26370
|
+
async function openTaskEditor(id){try{const data=await readJson(await fetch('/api/tasks/'+id));taskField('id').value=String(id);taskField('cwd').value=data.cwd||'';taskField('cwd').readOnly=true;taskField('cwd-picker').hidden=true;taskField('name').value=data.name||'';taskField('prompt').value=data.prompt||'';taskField('category').value=data.category||'general';taskField('batch').value=data.batchId||'';taskField('importance').value=String(data.importance??3);taskField('urgency').value=String(data.urgency??3);taskField('max-retries').value=String(data.maxRetries??3);setDuration('task-retry-backoff',data.retryBackoffMs??30000);setDuration('task-timeout',data.timeoutMs);taskField('dialog-title').textContent=text('task.editTitle');taskField('save').textContent=text('action.updateTask');updateTaskProjectStatus();resetCatalog('task');document.getElementById('task-dialog').showModal();loadCatalog('task',data.agent||'',data.model||'default',true);setTimeout(()=>taskField('name').focus(),50)}catch(error){showToast(error.message,'error')}}
|
|
26371
|
+
async function saveTask(event){event.preventDefault();const form=document.getElementById('task-form');if(!form.reportValidity())return;const id=taskField('id').value;const body={name:taskField('name').value,cwd:taskField('cwd').value,agent:taskField('agent').value,model:taskField('model').value,prompt:taskField('prompt').value,category:taskField('category').value,batchId:taskField('batch').value,importance:Number(taskField('importance').value),urgency:Number(taskField('urgency').value),maxRetries:Number(taskField('max-retries').value),retryBackoff:readDuration('task-retry-backoff'),timeout:readDuration('task-timeout')};const button=taskField('save');button.disabled=true;try{const data=await readJson(await fetch(id?'/api/tasks/'+id:'/api/tasks',{method:id?'PUT':'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)}));showToast(text(id?'feedback.taskUpdated':'feedback.taskCreated',{id:data.task.id}));document.getElementById('task-dialog').close();setTimeout(()=>location.assign(id?location.href:'/?cwd='+encodeURIComponent(data.task.cwd||'')),450)}catch(error){showToast(error.message,'error')}finally{button.disabled=false}}
|
|
26063
26372
|
function localDateTime(milliseconds){const date=new Date(milliseconds);const local=new Date(milliseconds-date.getTimezoneOffset()*60000);return local.toISOString().slice(0,23)}
|
|
26064
|
-
function updateTemplateScheduleFields(){const type=templateField('schedule-type').value;const fields={cron:templateField('cron-field'),recurring:templateField('interval-field'),delayed:templateField('run-at-field')};for(const [name,node] of Object.entries(fields)){node.hidden=name!==type;node.querySelector('input').required=name===type}}
|
|
26373
|
+
function updateTemplateScheduleFields(){const type=templateField('schedule-type').value;const fields={cron:templateField('cron-field'),recurring:templateField('interval-field'),delayed:templateField('run-at-field')};for(const [name,node] of Object.entries(fields)){node.hidden=name!==type;for(const control of node.querySelectorAll('input,select'))control.required=false;const required=name==='recurring'?node.querySelector('[id$="-preset"]'):node.querySelector('input');if(required)required.required=name===type;if(name==='recurring'&&name===type)updateDurationControl('template-interval')}}
|
|
26065
26374
|
function setOriginalRunAt(epoch){const input=templateField('run-at');const local=epoch?localDateTime(epoch):'';input.value=local;input.dataset.originalEpoch=epoch?String(epoch):'';input.dataset.originalLocal=local}
|
|
26066
26375
|
function selectedRunAt(){const input=templateField('run-at');return resolveEditedRunAt(input.dataset.originalEpoch?Number(input.dataset.originalEpoch):null,input.dataset.originalLocal||'',input.value)}
|
|
26067
|
-
function openTemplateCreator(){const form=document.getElementById('template-form');form.reset();templateField('id').value='';templateField('dialog-title').textContent=text('template.createTitle');setOriginalRunAt(null);templateField('run-at').value=localDateTime(Date.now()+3600000);updateTemplateScheduleFields();document.getElementById('template-dialog').showModal();setTimeout(()=>templateField('name').focus(),50)}
|
|
26068
|
-
async function openTemplateEditor(id){try{const data=await readJson(await fetch('/api/templates/'+id));templateField('id').value=String(id);templateField('dialog-title').textContent=text('template.editTitle');templateField('name').value=data.name||'';templateField('cwd').value=data.cwd||'';templateField('
|
|
26069
|
-
async function saveTemplate(event){event.preventDefault();const form=document.getElementById('template-form');if(!form.reportValidity())return;const id=templateField('id').value;const type=templateField('schedule-type').value;const body={name:templateField('name').value,cwd:templateField('cwd').value,agent:templateField('agent').value,model:templateField('model').value,prompt:templateField('prompt').value,scheduleType:type,cronExpr:templateField('cron').value,interval:
|
|
26376
|
+
function openTemplateCreator(){const form=document.getElementById('template-form');form.reset();templateField('id').value='';templateField('dialog-title').textContent=text('template.createTitle');setDuration('template-interval',3600000);setDuration('template-retry-backoff',30000);setDuration('template-timeout',null);setOriginalRunAt(null);templateField('run-at').value=localDateTime(Date.now()+3600000);updateTemplateScheduleFields();resetCatalog('template');document.getElementById('template-dialog').showModal();if(templateField('cwd').value)loadCatalog('template');setTimeout(()=>templateField('name').focus(),50)}
|
|
26377
|
+
async function openTemplateEditor(id){try{const data=await readJson(await fetch('/api/templates/'+id));templateField('id').value=String(id);templateField('dialog-title').textContent=text('template.editTitle');templateField('name').value=data.name||'';templateField('cwd').value=data.cwd||'';templateField('prompt').value=data.prompt||'';templateField('schedule-type').value=data.scheduleType;templateField('cron').value=data.cronExpr||'';setDuration('template-interval',data.intervalMs);setOriginalRunAt(data.runAt||null);if(!data.runAt)templateField('run-at').value=localDateTime(Date.now()+3600000);templateField('category').value=data.category||'general';templateField('batch').value=data.batchId||'';templateField('importance').value=String(data.importance??3);templateField('urgency').value=String(data.urgency??3);templateField('max-instances').value=String(data.maxInstances??1);templateField('max-retries').value=String(data.maxRetries??3);setDuration('template-retry-backoff',data.retryBackoffMs??30000);setDuration('template-timeout',data.timeoutMs);updateTemplateScheduleFields();resetCatalog('template');document.getElementById('template-dialog').showModal();loadCatalog('template',data.agent||'',data.model||'default',true);setTimeout(()=>templateField('name').focus(),50)}catch(error){showToast(error.message,'error')}}
|
|
26378
|
+
async function saveTemplate(event){event.preventDefault();const form=document.getElementById('template-form');if(!form.reportValidity())return;const id=templateField('id').value;const type=templateField('schedule-type').value;const body={name:templateField('name').value,cwd:templateField('cwd').value,agent:templateField('agent').value,model:templateField('model').value,prompt:templateField('prompt').value,scheduleType:type,cronExpr:templateField('cron').value,interval:readDuration('template-interval'),runAt:type==='delayed'?selectedRunAt():null,category:templateField('category').value,batchId:templateField('batch').value,importance:Number(templateField('importance').value),urgency:Number(templateField('urgency').value),maxInstances:Number(templateField('max-instances').value),maxRetries:Number(templateField('max-retries').value),retryBackoff:readDuration('template-retry-backoff'),timeout:readDuration('template-timeout')};const button=templateField('save');button.disabled=true;try{await readJson(await fetch(id?'/api/templates/'+id:'/api/templates',{method:id?'PUT':'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(body)}));showToast(text(id?'feedback.templateUpdated':'feedback.templateCreated'));document.getElementById('template-dialog').close();setTimeout(()=>location.assign(id?location.href:'/templates'),450)}catch(error){showToast(error.message,'error')}finally{button.disabled=false}}
|
|
26070
26379
|
async function enableTmpl(id){try{await readJson(await fetch('/api/templates/'+id+'/enable',{method:'POST'}));location.reload()}catch(error){showToast(error.message,'error')}}
|
|
26071
26380
|
async function disableTmpl(id){if(!await ask(text('dialog.disableTemplate'),text('dialog.disableTemplateBody')))return;try{await readJson(await fetch('/api/templates/'+id+'/disable',{method:'POST'}));location.reload()}catch(error){showToast(error.message,'error')}}
|
|
26072
26381
|
async function deleteTmpl(id){if(!await ask(text('dialog.deleteTemplate'),text('dialog.deleteTemplateBody'),true))return;try{await readJson(await fetch('/api/templates/'+id,{method:'DELETE'}));location.reload()}catch(error){showToast(error.message,'error')}}
|
|
@@ -26126,6 +26435,13 @@ var init_ui = __esm({
|
|
|
26126
26435
|
"action.updateTask": "\u4FDD\u5B58\u4FEE\u6539",
|
|
26127
26436
|
"action.createTemplate": "\u65B0\u5EFA\u5B9A\u65F6\u4EFB\u52A1",
|
|
26128
26437
|
"action.saveTemplate": "\u4FDD\u5B58\u5B9A\u65F6\u4EFB\u52A1",
|
|
26438
|
+
"action.chooseFolder": "\u9009\u62E9\u6587\u4EF6\u5939",
|
|
26439
|
+
"action.chooseThisFolder": "\u9009\u62E9\u5F53\u524D\u6587\u4EF6\u5939",
|
|
26440
|
+
"action.home": "\u4E3B\u76EE\u5F55",
|
|
26441
|
+
"action.up": "\u4E0A\u4E00\u7EA7",
|
|
26442
|
+
"action.copyCommand": "\u590D\u5236\u547D\u4EE4",
|
|
26443
|
+
"action.showHidden": "\u663E\u793A\u9690\u85CF\u6587\u4EF6\u5939",
|
|
26444
|
+
"action.hideHidden": "\u9690\u85CF\u9690\u85CF\u6587\u4EF6\u5939",
|
|
26129
26445
|
"status.pending": "\u5F85\u6267\u884C",
|
|
26130
26446
|
"status.running": "\u8FD0\u884C\u4E2D",
|
|
26131
26447
|
"status.done": "\u5DF2\u5B8C\u6210",
|
|
@@ -26192,6 +26508,15 @@ var init_ui = __esm({
|
|
|
26192
26508
|
"schedule.hours": "{count} \u5C0F\u65F6",
|
|
26193
26509
|
"schedule.days": "{count} \u5929",
|
|
26194
26510
|
"schedule.overdue": "\u5DF2\u5230\u671F",
|
|
26511
|
+
"duration.unit": "\u65F6\u95F4\u5355\u4F4D",
|
|
26512
|
+
"duration.seconds": "\u79D2",
|
|
26513
|
+
"duration.minutes": "\u5206\u949F",
|
|
26514
|
+
"duration.hours": "\u5C0F\u65F6",
|
|
26515
|
+
"duration.days": "\u5929",
|
|
26516
|
+
"duration.systemDefault": "\u4F7F\u7528 Gateway \u9ED8\u8BA4\u8D85\u65F6",
|
|
26517
|
+
"duration.immediate": "\u7ACB\u5373\u91CD\u8BD5",
|
|
26518
|
+
"duration.custom": "\u81EA\u5B9A\u4E49\u2026",
|
|
26519
|
+
"duration.every": "\u6BCF {duration}",
|
|
26195
26520
|
"system.worker": "\u4EFB\u52A1\u6267\u884C",
|
|
26196
26521
|
"system.scheduler": "\u5B9A\u65F6\u4EFB\u52A1\u670D\u52A1",
|
|
26197
26522
|
"system.watchdog": "\u8FD0\u884C\u76D1\u63A7",
|
|
@@ -26239,6 +26564,9 @@ var init_ui = __esm({
|
|
|
26239
26564
|
"template.interval": "\u6267\u884C\u95F4\u9694",
|
|
26240
26565
|
"template.runAt": "\u6267\u884C\u65F6\u95F4",
|
|
26241
26566
|
"template.durationHint": "\u652F\u6301 30s\u30015min\u30011h\u30012d",
|
|
26567
|
+
"template.intervalHint": "\u76F4\u63A5\u9009\u62E9\u5E38\u7528\u9891\u7387\uFF1B\u53EA\u6709\u7279\u6B8A\u9700\u6C42\u624D\u9700\u8981\u81EA\u5B9A\u4E49\u3002",
|
|
26568
|
+
"template.retryBackoffHint": "\u4E00\u6B21\u5931\u8D25\u540E\uFF0C\u7B49\u5F85\u591A\u4E45\u518D\u91CD\u8BD5\u3002",
|
|
26569
|
+
"template.timeoutHint": "\u7559\u7A7A\u8868\u793A\u4F7F\u7528 Gateway \u7684\u9ED8\u8BA4\u4EFB\u52A1\u8D85\u65F6\u3002",
|
|
26242
26570
|
"template.advanced": "\u66F4\u591A\u6267\u884C\u8BBE\u7F6E",
|
|
26243
26571
|
"template.category": "\u5206\u7C7B",
|
|
26244
26572
|
"template.batchId": "\u6279\u6B21 ID",
|
|
@@ -26263,6 +26591,28 @@ var init_ui = __esm({
|
|
|
26263
26591
|
"task.batchHint": "\u76F8\u540C\u975E\u7A7A\u6279\u6B21 ID \u7684\u4EFB\u52A1\u4E25\u683C\u4E32\u884C\uFF1B\u7559\u7A7A\u5219\u4E0D\u53D7\u6279\u6B21\u4E32\u884C\u9650\u5236\uFF0C\u4F46\u4ECD\u53D7\u5168\u5C40\u5E76\u53D1\u548C\u4F9D\u8D56\u7EA6\u675F\u3002",
|
|
26264
26592
|
"task.projectExisting": "\u6B64\u9879\u76EE\u73B0\u6709 {total} \u4E2A\u4EFB\u52A1\uFF1A\u8FD0\u884C {running}\uFF0C\u6392\u961F {pending}\uFF0C\u5F02\u5E38 {failed}\u3002",
|
|
26265
26593
|
"task.projectNew": "\u8FD9\u662F\u4E00\u4E2A\u65B0\u9879\u76EE\u5206\u7EC4\uFF1B\u521B\u5EFA\u540E\u4F1A\u51FA\u73B0\u5728\u9879\u76EE\u5217\u8868\u4E2D\u3002",
|
|
26594
|
+
"catalog.chooseProject": "\u8BF7\u5148\u9009\u62E9\u9879\u76EE\u76EE\u5F55",
|
|
26595
|
+
"catalog.defaultModel": "\u8DDF\u968F Agent / OpenCode \u9ED8\u8BA4\u6A21\u578B",
|
|
26596
|
+
"catalog.defaultProvider": "\u9ED8\u8BA4\u6A21\u578B",
|
|
26597
|
+
"catalog.provider": "\u6A21\u578B\u63D0\u4F9B\u5546",
|
|
26598
|
+
"catalog.model": "\u5177\u4F53\u6A21\u578B",
|
|
26599
|
+
"catalog.modelHint": "\u5148\u9009\u63D0\u4F9B\u5546\uFF0C\u518D\u9009\u672C\u9879\u76EE opencode models \u8FD4\u56DE\u7684\u6A21\u578B\uFF1B\u9ED8\u8BA4\u9009\u9879\u4E0D\u4F1A\u4F20\u5165 -m\u3002",
|
|
26600
|
+
"catalog.agentHint": "\u6765\u81EA\u5F53\u524D\u9879\u76EE\u7684 opencode agent list\u3002",
|
|
26601
|
+
"catalog.loading": "\u6B63\u5728\u8BFB\u53D6\u6B64\u9879\u76EE\u53EF\u7528\u7684 Agent \u548C\u6A21\u578B\u2026",
|
|
26602
|
+
"catalog.loaded": "\u5DF2\u4ECE\u672C\u673A OpenCode \u8BFB\u53D6 {agents} \u4E2A Agent\u3001{models} \u4E2A\u6A21\u578B\u3002",
|
|
26603
|
+
"catalog.failed": "\u65E0\u6CD5\u8BFB\u53D6\u6B64\u9879\u76EE\u7684 OpenCode \u914D\u7F6E\uFF1A{error}",
|
|
26604
|
+
"catalog.primary": "\u4E3B Agent",
|
|
26605
|
+
"catalog.subagent": "\u5B50 Agent",
|
|
26606
|
+
"catalog.all": "\u901A\u7528 Agent",
|
|
26607
|
+
"directory.title": "\u9009\u62E9\u9879\u76EE\u76EE\u5F55",
|
|
26608
|
+
"directory.subtitle": "\u9009\u62E9\u540E\uFF0C\u7CFB\u7EDF\u4F1A\u5728\u8BE5\u76EE\u5F55\u8FD0\u884C OpenCode\uFF0C\u5E76\u8BFB\u53D6\u8BE5\u9879\u76EE\u53EF\u7528\u7684 Agent \u548C\u6A21\u578B\u3002",
|
|
26609
|
+
"directory.empty": "\u8FD9\u4E2A\u6587\u4EF6\u5939\u4E2D\u6CA1\u6709\u5B50\u6587\u4EF6\u5939",
|
|
26610
|
+
"logs.command": "\u5B9E\u9645\u6267\u884C\u547D\u4EE4",
|
|
26611
|
+
"logs.output": "Agent \u8F93\u51FA",
|
|
26612
|
+
"logs.error": "\u5931\u8D25\u539F\u56E0",
|
|
26613
|
+
"logs.tools": "\u5DE5\u5177\u8C03\u7528",
|
|
26614
|
+
"logs.raw": "\u67E5\u770B\u539F\u59CB\u6267\u884C\u65E5\u5FD7",
|
|
26615
|
+
"logs.noText": "\u8FD9\u6B21\u6267\u884C\u6CA1\u6709\u4EA7\u751F\u53EF\u5C55\u793A\u7684\u6587\u672C\u8F93\u51FA\uFF0C\u8BF7\u67E5\u770B\u539F\u59CB\u65E5\u5FD7\u3002",
|
|
26266
26616
|
"theme.label": "\u4E3B\u9898",
|
|
26267
26617
|
"theme.system": "\u8DDF\u968F\u7CFB\u7EDF",
|
|
26268
26618
|
"theme.light": "\u6D45\u8272",
|
|
@@ -26300,6 +26650,7 @@ var init_ui = __esm({
|
|
|
26300
26650
|
"feedback.templateUpdated": "\u5B9A\u65F6\u4EFB\u52A1\u5DF2\u66F4\u65B0",
|
|
26301
26651
|
"feedback.configSaved": "\u8BBE\u7F6E\u5DF2\u4FDD\u5B58",
|
|
26302
26652
|
"feedback.sessionCommandCopied": "\u4F1A\u8BDD\u547D\u4EE4\u5DF2\u590D\u5236\uFF0C\u53EF\u76F4\u63A5\u7C98\u8D34\u5230\u7EC8\u7AEF\u8FD0\u884C",
|
|
26653
|
+
"feedback.commandCopied": "\u6267\u884C\u547D\u4EE4\u5DF2\u590D\u5236",
|
|
26303
26654
|
"feedback.restarting": "Gateway \u6B63\u5728\u91CD\u542F\uFF0C\u8BF7\u7A0D\u5019\u2026",
|
|
26304
26655
|
"feedback.restartTimeout": "Gateway \u5C1A\u672A\u6062\u590D\uFF0C\u8BF7\u7A0D\u540E\u5237\u65B0\u6216\u68C0\u67E5 PM2 \u72B6\u6001",
|
|
26305
26656
|
"feedback.databaseCleared": "\u6570\u636E\u5E93\u5DF2\u6E05\u7A7A\uFF0C\u5907\u4EFD\u4F4D\u4E8E\uFF1A{path}",
|
|
@@ -26348,6 +26699,13 @@ var init_ui = __esm({
|
|
|
26348
26699
|
"action.updateTask": "Save changes",
|
|
26349
26700
|
"action.createTemplate": "New scheduled task",
|
|
26350
26701
|
"action.saveTemplate": "Save scheduled task",
|
|
26702
|
+
"action.chooseFolder": "Choose folder",
|
|
26703
|
+
"action.chooseThisFolder": "Choose this folder",
|
|
26704
|
+
"action.home": "Home",
|
|
26705
|
+
"action.up": "Up",
|
|
26706
|
+
"action.copyCommand": "Copy command",
|
|
26707
|
+
"action.showHidden": "Show hidden folders",
|
|
26708
|
+
"action.hideHidden": "Hide hidden folders",
|
|
26351
26709
|
"status.pending": "Pending",
|
|
26352
26710
|
"status.running": "Running",
|
|
26353
26711
|
"status.done": "Done",
|
|
@@ -26414,6 +26772,15 @@ var init_ui = __esm({
|
|
|
26414
26772
|
"schedule.hours": "{count} hr",
|
|
26415
26773
|
"schedule.days": "{count} days",
|
|
26416
26774
|
"schedule.overdue": "Overdue",
|
|
26775
|
+
"duration.unit": "Time unit",
|
|
26776
|
+
"duration.seconds": "seconds",
|
|
26777
|
+
"duration.minutes": "minutes",
|
|
26778
|
+
"duration.hours": "hours",
|
|
26779
|
+
"duration.days": "days",
|
|
26780
|
+
"duration.systemDefault": "Use Gateway default timeout",
|
|
26781
|
+
"duration.immediate": "Retry immediately",
|
|
26782
|
+
"duration.custom": "Custom\u2026",
|
|
26783
|
+
"duration.every": "Every {duration}",
|
|
26417
26784
|
"system.worker": "Task execution",
|
|
26418
26785
|
"system.scheduler": "Scheduled task service",
|
|
26419
26786
|
"system.watchdog": "Runtime monitor",
|
|
@@ -26461,6 +26828,9 @@ var init_ui = __esm({
|
|
|
26461
26828
|
"template.interval": "Interval",
|
|
26462
26829
|
"template.runAt": "Run at",
|
|
26463
26830
|
"template.durationHint": "Supports 30s, 5min, 1h, 2d",
|
|
26831
|
+
"template.intervalHint": "Choose a common frequency directly; customize only when necessary.",
|
|
26832
|
+
"template.retryBackoffHint": "How long to wait after a failure before retrying.",
|
|
26833
|
+
"template.timeoutHint": "Leave blank to use the Gateway default task timeout.",
|
|
26464
26834
|
"template.advanced": "More execution settings",
|
|
26465
26835
|
"template.category": "Category",
|
|
26466
26836
|
"template.batchId": "Batch ID",
|
|
@@ -26485,6 +26855,28 @@ var init_ui = __esm({
|
|
|
26485
26855
|
"task.batchHint": "Tasks with the same non-empty batch ID run serially. Blank removes the batch constraint; global concurrency and dependencies still apply.",
|
|
26486
26856
|
"task.projectExisting": "This project has {total} tasks: {running} running, {pending} queued, and {failed} with issues.",
|
|
26487
26857
|
"task.projectNew": "This is a new project group. It appears in the project list after creation.",
|
|
26858
|
+
"catalog.chooseProject": "Choose a project directory first",
|
|
26859
|
+
"catalog.defaultModel": "Use the Agent / OpenCode default model",
|
|
26860
|
+
"catalog.defaultProvider": "Default model",
|
|
26861
|
+
"catalog.provider": "Model provider",
|
|
26862
|
+
"catalog.model": "Model",
|
|
26863
|
+
"catalog.modelHint": "Choose a provider, then a model returned by opencode models for this project. Default does not pass -m.",
|
|
26864
|
+
"catalog.agentHint": "Loaded from opencode agent list for this project.",
|
|
26865
|
+
"catalog.loading": "Loading Agents and models available to this project\u2026",
|
|
26866
|
+
"catalog.loaded": "Loaded {agents} Agents and {models} models from local OpenCode.",
|
|
26867
|
+
"catalog.failed": "Could not load this project\u2019s OpenCode configuration: {error}",
|
|
26868
|
+
"catalog.primary": "primary Agent",
|
|
26869
|
+
"catalog.subagent": "subagent",
|
|
26870
|
+
"catalog.all": "general Agent",
|
|
26871
|
+
"directory.title": "Choose project directory",
|
|
26872
|
+
"directory.subtitle": "OpenCode runs in this directory, and its project-specific Agents and models are loaded.",
|
|
26873
|
+
"directory.empty": "This folder has no subfolders",
|
|
26874
|
+
"logs.command": "Executed command",
|
|
26875
|
+
"logs.output": "Agent output",
|
|
26876
|
+
"logs.error": "Failure reason",
|
|
26877
|
+
"logs.tools": "Tool calls",
|
|
26878
|
+
"logs.raw": "View raw execution log",
|
|
26879
|
+
"logs.noText": "This run produced no displayable text. Inspect the raw log for details.",
|
|
26488
26880
|
"theme.label": "Theme",
|
|
26489
26881
|
"theme.system": "System",
|
|
26490
26882
|
"theme.light": "Light",
|
|
@@ -26522,6 +26914,7 @@ var init_ui = __esm({
|
|
|
26522
26914
|
"feedback.templateUpdated": "Scheduled task updated",
|
|
26523
26915
|
"feedback.configSaved": "Settings saved",
|
|
26524
26916
|
"feedback.sessionCommandCopied": "Session command copied. Paste it into a terminal to continue.",
|
|
26917
|
+
"feedback.commandCopied": "Execution command copied",
|
|
26525
26918
|
"feedback.restarting": "Gateway is restarting\u2026",
|
|
26526
26919
|
"feedback.restartTimeout": "Gateway has not recovered yet. Refresh later or check PM2 status.",
|
|
26527
26920
|
"feedback.databaseCleared": "Database cleared. Backup: {path}",
|
|
@@ -26732,6 +27125,18 @@ var init_ui = __esm({
|
|
|
26732
27125
|
.danger-card h2 .icon { width:17px; height:17px; }
|
|
26733
27126
|
.danger-card p { max-width:800px; margin:0 0 14px; color:var(--text-2); font-size:12px; }
|
|
26734
27127
|
.log-panel { margin:12px 0; animation:reveal .18s ease both; }
|
|
27128
|
+
.log-content { display:grid; gap:14px; padding:16px; }
|
|
27129
|
+
.log-section-head { display:flex; align-items:center; justify-content:space-between; gap:12px; margin-bottom:7px; }
|
|
27130
|
+
.run-command,.run-output,.run-error,.run-tools { min-width:0; }
|
|
27131
|
+
.run-command strong,.run-output>strong,.run-error>strong,.run-tools>strong { display:block; margin-bottom:7px; font-size:12px; }
|
|
27132
|
+
.command-cwd { margin-bottom:6px; color:var(--text-3); font-family:"SFMono-Regular",Consolas,monospace; font-size:10px; overflow-wrap:anywhere; }
|
|
27133
|
+
.run-command pre,.run-output pre,.run-error pre { margin:0; padding:12px; overflow:auto; border:1px solid var(--border); border-radius:9px;
|
|
27134
|
+
color:var(--text-2); background:var(--surface-2); font-family:"SFMono-Regular",Consolas,monospace; font-size:11px; white-space:pre-wrap; overflow-wrap:anywhere; }
|
|
27135
|
+
.run-output pre { color:var(--text); font-family:inherit; font-size:13px; line-height:1.65; }
|
|
27136
|
+
.run-error pre { color:var(--red); border-color:color-mix(in srgb,var(--red) 28%,var(--border)); background:var(--red-soft); }
|
|
27137
|
+
.raw-log { padding-top:12px; border-top:1px solid var(--border); }
|
|
27138
|
+
.raw-log summary { color:var(--text-2); cursor:pointer; font-size:12px; font-weight:650; }
|
|
27139
|
+
.raw-log .log-box { margin-top:10px; border-radius:9px; }
|
|
26735
27140
|
.log-box { max-height:360px; overflow:auto; padding:16px; color:var(--text-2); background:#0b1018; font-family:"SFMono-Regular",Consolas,monospace;
|
|
26736
27141
|
font-size:12px; white-space:pre-wrap; overflow-wrap:anywhere; }
|
|
26737
27142
|
:root[data-theme="light"] .log-box { color:#dbe5f3; }
|
|
@@ -26750,12 +27155,33 @@ var init_ui = __esm({
|
|
|
26750
27155
|
.form-field-wide { grid-column:1 / -1; }
|
|
26751
27156
|
.form-field input,.form-field select,.form-field textarea { width:100%; min-height:39px; padding:8px 10px; border:1px solid var(--border); border-radius:9px;
|
|
26752
27157
|
outline:none; color:var(--text); background:var(--surface-2); font-weight:450; }
|
|
27158
|
+
.field-action { display:flex; align-items:stretch; gap:7px; }
|
|
27159
|
+
.field-action input { min-width:0; flex:1; }
|
|
27160
|
+
.field-action .btn { flex:0 0 auto; white-space:nowrap; }
|
|
27161
|
+
.model-selector { display:grid; grid-template-columns:minmax(120px,.75fr) minmax(0,1.25fr); gap:7px; }
|
|
27162
|
+
.duration-picker { display:grid; gap:7px; }
|
|
27163
|
+
.duration-control { display:grid; grid-template-columns:minmax(0,1fr) 112px; gap:7px; }
|
|
27164
|
+
.duration-control input,.duration-control select { min-width:0; }
|
|
26753
27165
|
.form-field textarea { resize:vertical; line-height:1.5; }
|
|
26754
27166
|
.form-field input:focus,.form-field select:focus,.form-field textarea:focus { border-color:var(--primary); box-shadow:var(--focus); background:var(--surface); }
|
|
26755
27167
|
.form-field small { color:var(--text-3); font-size:10px; font-weight:450; }
|
|
26756
27168
|
.advanced-fields { margin-top:18px; padding-top:14px; border-top:1px solid var(--border); }
|
|
26757
27169
|
.advanced-fields summary { margin-bottom:14px; color:var(--text-2); cursor:pointer; font-size:12px; font-weight:700; }
|
|
26758
27170
|
.form-note { margin:16px 0 0; color:var(--text-3); font-size:11px; }
|
|
27171
|
+
.catalog-status[data-state="loading"] { color:var(--blue); }
|
|
27172
|
+
.catalog-status[data-state="ready"] { color:var(--green); }
|
|
27173
|
+
.catalog-status[data-state="error"] { color:var(--red); }
|
|
27174
|
+
.directory-dialog { width:min(720px,calc(100% - 32px)); }
|
|
27175
|
+
.directory-toolbar { display:flex; align-items:center; gap:8px; margin-bottom:12px; }
|
|
27176
|
+
.directory-path { min-width:0; flex:1; padding:9px 11px; overflow:hidden; border:1px solid var(--border); border-radius:9px;
|
|
27177
|
+
color:var(--text-2); background:var(--surface-2); font-family:"SFMono-Regular",Consolas,monospace; font-size:11px; text-overflow:ellipsis; white-space:nowrap; }
|
|
27178
|
+
.directory-list { min-height:260px; max-height:48vh; display:grid; align-content:start; gap:6px; overflow:auto; }
|
|
27179
|
+
.directory-item { width:100%; min-height:40px; display:flex; align-items:center; gap:9px; padding:0 11px; border:1px solid transparent; border-radius:9px;
|
|
27180
|
+
color:var(--text-2); background:transparent; cursor:pointer; text-align:left; transition:background-color .15s ease,border-color .15s ease,color .15s ease,transform .12s ease; }
|
|
27181
|
+
.directory-item:hover { color:var(--text); border-color:var(--border); background:var(--surface-2); }
|
|
27182
|
+
.directory-item:active { transform:scale(.99); }
|
|
27183
|
+
.directory-item .icon { width:17px; height:17px; color:var(--primary); flex:0 0 auto; }
|
|
27184
|
+
.directory-empty { min-height:220px; display:grid; place-items:center; color:var(--text-3); }
|
|
26759
27185
|
.json-view { min-height:160px; margin:0; padding:15px; overflow:auto; border:1px solid var(--border); border-radius:10px; color:var(--text-2);
|
|
26760
27186
|
background:var(--surface-2); font-size:12px; white-space:pre-wrap; overflow-wrap:anywhere; }
|
|
26761
27187
|
.confirm-copy { color:var(--text-2); margin:0; }
|
|
@@ -26824,6 +27250,9 @@ var init_ui = __esm({
|
|
|
26824
27250
|
.project-grid { grid-template-columns:1fr; }
|
|
26825
27251
|
.template-form-grid { grid-template-columns:1fr; }
|
|
26826
27252
|
.form-field-wide { grid-column:auto; }
|
|
27253
|
+
.field-action { align-items:stretch; flex-direction:column; }
|
|
27254
|
+
.field-action .btn { width:100%; }
|
|
27255
|
+
.model-selector { grid-template-columns:1fr; }
|
|
26827
27256
|
}
|
|
26828
27257
|
@media (max-width:520px) {
|
|
26829
27258
|
.stats-grid,.stats-grid.three { grid-template-columns:1fr 1fr; }
|
|
@@ -26853,11 +27282,21 @@ __export(web_exports, {
|
|
|
26853
27282
|
dashboardApp: () => dashboardApp,
|
|
26854
27283
|
default: () => web_default,
|
|
26855
27284
|
isSafeDashboardRestartTarget: () => isSafeDashboardRestartTarget,
|
|
27285
|
+
presentRunLog: () => presentRunLog,
|
|
26856
27286
|
resolveDashboardConfigState: () => resolveDashboardConfigState,
|
|
26857
27287
|
setDashboardRuntimeConfig: () => setDashboardRuntimeConfig
|
|
26858
27288
|
});
|
|
26859
|
-
import {
|
|
26860
|
-
|
|
27289
|
+
import {
|
|
27290
|
+
existsSync as existsSync8,
|
|
27291
|
+
mkdirSync as mkdirSync5,
|
|
27292
|
+
readFileSync as readFileSync5,
|
|
27293
|
+
readdirSync as readdirSync2,
|
|
27294
|
+
renameSync as renameSync2,
|
|
27295
|
+
statSync as statSync4,
|
|
27296
|
+
writeFileSync as writeFileSync3
|
|
27297
|
+
} from "fs";
|
|
27298
|
+
import { homedir as homedir5 } from "os";
|
|
27299
|
+
import { basename as basename3, dirname as dirname9, join as join7 } from "path";
|
|
26861
27300
|
function setDashboardRuntimeConfig(config) {
|
|
26862
27301
|
runtimeConfig = config === null ? null : structuredClone(config);
|
|
26863
27302
|
}
|
|
@@ -26898,6 +27337,23 @@ function parsePositiveInteger2(value) {
|
|
|
26898
27337
|
function parseTaskStatus2(value) {
|
|
26899
27338
|
return TASK_STATUSES2.has(value) ? value : null;
|
|
26900
27339
|
}
|
|
27340
|
+
function listChildDirectories(path) {
|
|
27341
|
+
return readdirSync2(path, { withFileTypes: true }).flatMap((entry) => {
|
|
27342
|
+
const entryPath = join7(path, entry.name);
|
|
27343
|
+
if (entry.isDirectory()) return [{ name: entry.name, path: entryPath, hidden: entry.name.startsWith(".") }];
|
|
27344
|
+
if (!entry.isSymbolicLink()) return [];
|
|
27345
|
+
try {
|
|
27346
|
+
return statSync4(entryPath).isDirectory() ? [{ name: entry.name, path: entryPath, hidden: entry.name.startsWith(".") }] : [];
|
|
27347
|
+
} catch {
|
|
27348
|
+
return [];
|
|
27349
|
+
}
|
|
27350
|
+
}).sort((left, right) => {
|
|
27351
|
+
const leftHidden = left.name.startsWith(".");
|
|
27352
|
+
const rightHidden = right.name.startsWith(".");
|
|
27353
|
+
if (leftHidden !== rightHidden) return leftHidden ? 1 : -1;
|
|
27354
|
+
return left.name.localeCompare(right.name);
|
|
27355
|
+
});
|
|
27356
|
+
}
|
|
26901
27357
|
function parseTaskPayload(value) {
|
|
26902
27358
|
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
26903
27359
|
throw new Error("\u8BF7\u6C42\u5185\u5BB9\u5FC5\u987B\u662F\u5BF9\u8C61");
|
|
@@ -27054,6 +27510,66 @@ function formatDuration(startAt, endAt) {
|
|
|
27054
27510
|
if (seconds < 3600) return `${Math.floor(seconds / 60)}m ${seconds % 60}s`;
|
|
27055
27511
|
return `${Math.floor(seconds / 3600)}h ${Math.floor(seconds % 3600 / 60)}m`;
|
|
27056
27512
|
}
|
|
27513
|
+
function recordValue(value) {
|
|
27514
|
+
return value !== null && typeof value === "object" && !Array.isArray(value) ? value : null;
|
|
27515
|
+
}
|
|
27516
|
+
function shellQuote(value) {
|
|
27517
|
+
if (/^[A-Za-z0-9_./:@%+=,-]+$/.test(value)) return value;
|
|
27518
|
+
return `'${value.replace(/'/g, `'"'"'`)}'`;
|
|
27519
|
+
}
|
|
27520
|
+
function presentRunLog(log) {
|
|
27521
|
+
let command = null;
|
|
27522
|
+
const textParts = [];
|
|
27523
|
+
const errors = [];
|
|
27524
|
+
const tools = [];
|
|
27525
|
+
for (const line of log.split("\n")) {
|
|
27526
|
+
const trimmed = line.trim();
|
|
27527
|
+
if (!trimmed) continue;
|
|
27528
|
+
let parsed = null;
|
|
27529
|
+
try {
|
|
27530
|
+
parsed = recordValue(JSON.parse(trimmed));
|
|
27531
|
+
} catch {
|
|
27532
|
+
errors.push(line);
|
|
27533
|
+
continue;
|
|
27534
|
+
}
|
|
27535
|
+
if (!parsed) continue;
|
|
27536
|
+
if (parsed.type === "supertask_command") {
|
|
27537
|
+
const executable = typeof parsed.executable === "string" ? parsed.executable : null;
|
|
27538
|
+
const cwd = typeof parsed.cwd === "string" ? parsed.cwd : null;
|
|
27539
|
+
const args = Array.isArray(parsed.args) && parsed.args.every((item) => typeof item === "string") ? parsed.args : null;
|
|
27540
|
+
if (executable && cwd && args) {
|
|
27541
|
+
command = {
|
|
27542
|
+
cwd,
|
|
27543
|
+
command: `cd ${shellQuote(cwd)} && ${[executable, ...args].map(shellQuote).join(" ")}`
|
|
27544
|
+
};
|
|
27545
|
+
}
|
|
27546
|
+
continue;
|
|
27547
|
+
}
|
|
27548
|
+
const part = recordValue(parsed.part);
|
|
27549
|
+
const eventType = typeof parsed.type === "string" ? parsed.type : "";
|
|
27550
|
+
const partType = typeof part?.type === "string" ? part.type : "";
|
|
27551
|
+
const text2 = typeof part?.text === "string" ? part.text : typeof parsed.text === "string" ? parsed.text : null;
|
|
27552
|
+
if (text2 && (eventType === "text" || partType === "text")) textParts.push(text2);
|
|
27553
|
+
const tool = typeof part?.tool === "string" ? part.tool : typeof parsed.tool === "string" ? parsed.tool : null;
|
|
27554
|
+
if (tool && (eventType === "tool_use" || partType === "tool")) tools.push(tool);
|
|
27555
|
+
const error = typeof parsed.error === "string" ? parsed.error : typeof part?.error === "string" ? part.error : null;
|
|
27556
|
+
if (error) errors.push(error);
|
|
27557
|
+
}
|
|
27558
|
+
return {
|
|
27559
|
+
command,
|
|
27560
|
+
text: textParts.join("\n").trim(),
|
|
27561
|
+
errors: [...new Set(errors)],
|
|
27562
|
+
tools
|
|
27563
|
+
};
|
|
27564
|
+
}
|
|
27565
|
+
function renderRunLog(runId, taskName, log, locale) {
|
|
27566
|
+
const presentation = presentRunLog(log);
|
|
27567
|
+
const command = presentation.command ? `<div class="run-command"><div class="log-section-head"><strong>${t(locale, "logs.command")}</strong><button type="button" class="btn" onclick="copyRunCommand(${runId})">${icon("copy")}${t(locale, "action.copyCommand")}</button></div><div class="command-cwd">${esc(presentation.command.cwd)}</div><pre id="command-${runId}">${esc(presentation.command.command)}</pre></div>` : "";
|
|
27568
|
+
const errors = presentation.errors.length > 0 ? `<div class="run-error"><strong>${t(locale, "logs.error")}</strong><pre>${esc(presentation.errors.join("\n"))}</pre></div>` : "";
|
|
27569
|
+
const tools = presentation.tools.length > 0 ? `<div class="run-tools"><strong>${t(locale, "logs.tools")}</strong><div class="actions">${presentation.tools.map((tool) => `<span class="tag">${esc(tool)}</span>`).join("")}</div></div>` : "";
|
|
27570
|
+
const output = `<div class="run-output"><strong>${t(locale, "logs.output")}</strong><pre>${esc(presentation.text || t(locale, "logs.noText"))}</pre></div>`;
|
|
27571
|
+
return `<section id="log-${runId}" class="panel log-panel" hidden><div class="panel-head"><h3>Run #${runId} \xB7 ${esc(taskName)}</h3></div><div class="log-content">${command}${errors}${output}${tools}<details class="raw-log"><summary>${t(locale, "logs.raw")}</summary><div class="log-box">${esc(log)}</div></details></div></section>`;
|
|
27572
|
+
}
|
|
27057
27573
|
function esc(value) {
|
|
27058
27574
|
if (!value) return "";
|
|
27059
27575
|
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """).replace(/'/g, "'");
|
|
@@ -27069,7 +27585,7 @@ function readCurrentConfig() {
|
|
|
27069
27585
|
}
|
|
27070
27586
|
function writeConfig(cfg) {
|
|
27071
27587
|
const configPath = getConfigPath();
|
|
27072
|
-
const dir =
|
|
27588
|
+
const dir = dirname9(configPath);
|
|
27073
27589
|
if (!existsSync8(dir)) mkdirSync5(dir, { recursive: true });
|
|
27074
27590
|
const tempPath = `${configPath}.${process.pid}.tmp`;
|
|
27075
27591
|
writeFileSync3(tempPath, JSON.stringify(cfg, null, 2) + "\n", { mode: 384 });
|
|
@@ -27085,6 +27601,25 @@ function emptyState(title, hint, code = "") {
|
|
|
27085
27601
|
return `<div class="empty-state"><div><div class="empty-icon">${icon("inbox")}</div>
|
|
27086
27602
|
<h3>${title}</h3><p>${hint}</p>${code ? `<code>${code}</code>` : ""}</div></div>`;
|
|
27087
27603
|
}
|
|
27604
|
+
function durationControl(locale, id, value, kind) {
|
|
27605
|
+
const units = [
|
|
27606
|
+
{ value: "s", label: t(locale, "duration.seconds") },
|
|
27607
|
+
{ value: "min", label: t(locale, "duration.minutes") },
|
|
27608
|
+
{ value: "h", label: t(locale, "duration.hours") },
|
|
27609
|
+
{ value: "d", label: t(locale, "duration.days") }
|
|
27610
|
+
];
|
|
27611
|
+
const values = kind === "interval" ? [3e5, 9e5, 18e5, 36e5, 216e5, 432e5, 864e5] : kind === "retry" ? [0, 1e4, 3e4, 6e4, 3e5] : [3e5, 9e5, 18e5, 36e5, 72e5, 144e5];
|
|
27612
|
+
const presets = [
|
|
27613
|
+
...kind === "timeout" ? [{ value: "", label: t(locale, "duration.systemDefault") }] : [],
|
|
27614
|
+
...values.map((milliseconds) => ({
|
|
27615
|
+
value: String(milliseconds),
|
|
27616
|
+
label: milliseconds === 0 ? t(locale, "duration.immediate") : kind === "interval" ? t(locale, "duration.every", { duration: formatInterval(milliseconds, locale) }) : formatInterval(milliseconds, locale)
|
|
27617
|
+
})),
|
|
27618
|
+
{ value: "custom", label: t(locale, "duration.custom") }
|
|
27619
|
+
];
|
|
27620
|
+
const selected = value === null ? "" : String(value);
|
|
27621
|
+
return `<div class="duration-picker"><select id="${id}-preset" onchange="updateDurationControl('${id}')">${presets.map((item) => `<option value="${item.value}" ${item.value === selected ? "selected" : ""}>${item.label}</option>`).join("")}</select><div id="${id}-custom" class="duration-control" hidden><input id="${id}-value" type="number" min="${kind === "retry" ? 0 : 0.1}" step="0.1" inputmode="decimal"><select id="${id}-unit" aria-label="${t(locale, "duration.unit")}">${units.map((item) => `<option value="${item.value}">${item.label}</option>`).join("")}</select></div></div>`;
|
|
27622
|
+
}
|
|
27088
27623
|
function formatInterval(milliseconds, locale) {
|
|
27089
27624
|
const formatter = new Intl.NumberFormat(locale === "en" ? "en-US" : "zh-CN", {
|
|
27090
27625
|
maximumFractionDigits: 1
|
|
@@ -27113,6 +27648,8 @@ var init_web = __esm({
|
|
|
27113
27648
|
init_drizzle_orm();
|
|
27114
27649
|
init_db2();
|
|
27115
27650
|
init_duration();
|
|
27651
|
+
init_opencode_catalog();
|
|
27652
|
+
init_task_working_directory();
|
|
27116
27653
|
init_database_maintenance_service();
|
|
27117
27654
|
init_task_run_service();
|
|
27118
27655
|
init_task_service();
|
|
@@ -27166,6 +27703,33 @@ var init_web = __esm({
|
|
|
27166
27703
|
const health = getGatewayHealth();
|
|
27167
27704
|
return c.json(health, health.status === "ok" ? 200 : 503);
|
|
27168
27705
|
});
|
|
27706
|
+
app.get("/api/filesystem/directories", (c) => {
|
|
27707
|
+
const requestedPath = c.req.query("path")?.trim() || homedir5();
|
|
27708
|
+
try {
|
|
27709
|
+
validateTaskWorkingDirectory(requestedPath);
|
|
27710
|
+
return c.json({
|
|
27711
|
+
path: requestedPath,
|
|
27712
|
+
parent: dirname9(requestedPath),
|
|
27713
|
+
home: homedir5(),
|
|
27714
|
+
directories: listChildDirectories(requestedPath)
|
|
27715
|
+
});
|
|
27716
|
+
} catch (error) {
|
|
27717
|
+
return c.json({
|
|
27718
|
+
error: error instanceof Error ? error.message : String(error)
|
|
27719
|
+
}, 400);
|
|
27720
|
+
}
|
|
27721
|
+
});
|
|
27722
|
+
app.get("/api/opencode/catalog", async (c) => {
|
|
27723
|
+
const cwd = c.req.query("cwd")?.trim();
|
|
27724
|
+
if (!cwd) return c.json({ error: "cwd \u4E0D\u80FD\u4E3A\u7A7A" }, 400);
|
|
27725
|
+
try {
|
|
27726
|
+
return c.json(await loadOpenCodeCatalog(cwd));
|
|
27727
|
+
} catch (error) {
|
|
27728
|
+
return c.json({
|
|
27729
|
+
error: error instanceof Error ? error.message : String(error)
|
|
27730
|
+
}, 400);
|
|
27731
|
+
}
|
|
27732
|
+
});
|
|
27169
27733
|
app.get("/", async (c) => {
|
|
27170
27734
|
const locale = resolveLocale(c);
|
|
27171
27735
|
const page = parsePositiveInteger2(c.req.query("page") || "1");
|
|
@@ -27310,13 +27874,14 @@ var init_web = __esm({
|
|
|
27310
27874
|
<div class="dialog-body">
|
|
27311
27875
|
<div class="template-form-grid">
|
|
27312
27876
|
<label class="form-field"><span>${t(locale, "template.name")}</span><input id="task-name" required maxlength="200" autocomplete="off"></label>
|
|
27313
|
-
<label class="form-field"><span>${t(locale, "template.cwd")}</span><input id="task-cwd" required autocomplete="off" list="task-cwd-options" placeholder="/path/to/project" oninput="updateTaskProjectStatus()"><small>${t(locale, "template.cwdHint")}</small></label>
|
|
27877
|
+
<label class="form-field"><span>${t(locale, "template.cwd")}</span><div class="field-action"><input id="task-cwd" required autocomplete="off" list="task-cwd-options" placeholder="/path/to/project" oninput="updateTaskProjectStatus();scheduleCatalogLoad('task')"><button id="task-cwd-picker" type="button" class="btn" onclick="openDirectoryPicker('task-cwd')">${icon("folder")}${t(locale, "action.chooseFolder")}</button></div><small>${t(locale, "template.cwdHint")}</small></label>
|
|
27314
27878
|
<datalist id="task-cwd-options">${projects.map((project) => `<option value="${esc(project.cwd)}"></option>`).join("")}</datalist>
|
|
27315
|
-
<label class="form-field"><span>${t(locale, "template.agent")}</span><
|
|
27316
|
-
<label class="form-field"><span>${t(locale, "template.model")}</span><
|
|
27879
|
+
<label class="form-field"><span>${t(locale, "template.agent")}</span><select id="task-agent" required><option value="">${t(locale, "catalog.chooseProject")}</option></select><small>${t(locale, "catalog.agentHint")}</small></label>
|
|
27880
|
+
<label class="form-field"><span>${t(locale, "template.model")}</span><div class="model-selector"><select id="task-model-provider" aria-label="${t(locale, "catalog.provider")}" onchange="populateModelOptions('task')"><option value="">${t(locale, "catalog.defaultProvider")}</option></select><select id="task-model" required aria-label="${t(locale, "catalog.model")}" disabled><option value="default">${t(locale, "catalog.defaultModel")}</option></select></div><small>${t(locale, "catalog.modelHint")}</small></label>
|
|
27317
27881
|
<label class="form-field form-field-wide"><span>${t(locale, "template.prompt")}</span><textarea id="task-prompt" rows="6" required></textarea></label>
|
|
27318
27882
|
</div>
|
|
27319
27883
|
<p id="task-project-status" class="form-note"></p>
|
|
27884
|
+
<p id="task-catalog-status" class="form-note catalog-status"></p>
|
|
27320
27885
|
<details class="advanced-fields">
|
|
27321
27886
|
<summary>${t(locale, "template.advanced")}</summary>
|
|
27322
27887
|
<div class="template-form-grid">
|
|
@@ -27325,8 +27890,8 @@ var init_web = __esm({
|
|
|
27325
27890
|
<label class="form-field"><span>${t(locale, "template.importance")}</span><input id="task-importance" type="number" min="1" max="5" step="1" value="3" required></label>
|
|
27326
27891
|
<label class="form-field"><span>${t(locale, "template.urgency")}</span><input id="task-urgency" type="number" min="1" max="5" step="1" value="3" required></label>
|
|
27327
27892
|
<label class="form-field"><span>${t(locale, "template.maxRetries")}</span><input id="task-max-retries" type="number" min="0" max="1000" step="1" value="3" required></label>
|
|
27328
|
-
<label class="form-field"><span>${t(locale, "template.retryBackoff")}</span
|
|
27329
|
-
<label class="form-field"><span>${t(locale, "template.timeout")}</span
|
|
27893
|
+
<label class="form-field"><span>${t(locale, "template.retryBackoff")}</span>${durationControl(locale, "task-retry-backoff", 3e4, "retry")}<small>${t(locale, "template.retryBackoffHint")}</small></label>
|
|
27894
|
+
<label class="form-field"><span>${t(locale, "template.timeout")}</span>${durationControl(locale, "task-timeout", null, "timeout")}<small>${t(locale, "template.timeoutHint")}</small></label>
|
|
27330
27895
|
</div>
|
|
27331
27896
|
</details>
|
|
27332
27897
|
</div>
|
|
@@ -27386,15 +27951,16 @@ var init_web = __esm({
|
|
|
27386
27951
|
<div class="dialog-body">
|
|
27387
27952
|
<div class="template-form-grid">
|
|
27388
27953
|
<label class="form-field"><span>${t(locale, "template.name")}</span><input id="template-name" required maxlength="200" autocomplete="off"></label>
|
|
27389
|
-
<label class="form-field"><span>${t(locale, "template.cwd")}</span><input id="template-cwd" required autocomplete="off" placeholder="/path/to/project"><small>${t(locale, "template.cwdHint")}</small></label>
|
|
27390
|
-
<label class="form-field"><span>${t(locale, "template.agent")}</span><
|
|
27391
|
-
<label class="form-field"><span>${t(locale, "template.model")}</span><
|
|
27954
|
+
<label class="form-field"><span>${t(locale, "template.cwd")}</span><div class="field-action"><input id="template-cwd" required autocomplete="off" placeholder="/path/to/project" oninput="scheduleCatalogLoad('template')"><button type="button" class="btn" onclick="openDirectoryPicker('template-cwd')">${icon("folder")}${t(locale, "action.chooseFolder")}</button></div><small>${t(locale, "template.cwdHint")}</small></label>
|
|
27955
|
+
<label class="form-field"><span>${t(locale, "template.agent")}</span><select id="template-agent" required><option value="">${t(locale, "catalog.chooseProject")}</option></select><small>${t(locale, "catalog.agentHint")}</small></label>
|
|
27956
|
+
<label class="form-field"><span>${t(locale, "template.model")}</span><div class="model-selector"><select id="template-model-provider" aria-label="${t(locale, "catalog.provider")}" onchange="populateModelOptions('template')"><option value="">${t(locale, "catalog.defaultProvider")}</option></select><select id="template-model" required aria-label="${t(locale, "catalog.model")}" disabled><option value="default">${t(locale, "catalog.defaultModel")}</option></select></div><small>${t(locale, "catalog.modelHint")}</small></label>
|
|
27392
27957
|
<label class="form-field form-field-wide"><span>${t(locale, "template.prompt")}</span><textarea id="template-prompt" rows="6" required></textarea></label>
|
|
27393
27958
|
<label class="form-field"><span>${t(locale, "template.scheduleType")}</span><select id="template-schedule-type" onchange="updateTemplateScheduleFields()"><option value="recurring">${t(locale, "schedule.recurring")}</option><option value="delayed">${t(locale, "schedule.delayed")}</option><option value="cron">${t(locale, "schedule.cron")}</option></select></label>
|
|
27394
27959
|
<label id="template-cron-field" class="form-field" hidden><span>${t(locale, "template.cronExpr")}</span><input id="template-cron" autocomplete="off" placeholder="0 9 * * *"><small>${t(locale, "template.cronHint")}</small></label>
|
|
27395
|
-
<label id="template-interval-field" class="form-field"><span>${t(locale, "template.interval")}</span
|
|
27960
|
+
<label id="template-interval-field" class="form-field"><span>${t(locale, "template.interval")}</span>${durationControl(locale, "template-interval", 36e5, "interval")}<small>${t(locale, "template.intervalHint")}</small></label>
|
|
27396
27961
|
<label id="template-run-at-field" class="form-field" hidden><span>${t(locale, "template.runAt")}</span><input id="template-run-at" type="datetime-local" step="0.001"></label>
|
|
27397
27962
|
</div>
|
|
27963
|
+
<p id="template-catalog-status" class="form-note catalog-status"></p>
|
|
27398
27964
|
<details class="advanced-fields">
|
|
27399
27965
|
<summary>${t(locale, "template.advanced")}</summary>
|
|
27400
27966
|
<div class="template-form-grid">
|
|
@@ -27404,8 +27970,8 @@ var init_web = __esm({
|
|
|
27404
27970
|
<label class="form-field"><span>${t(locale, "template.urgency")}</span><input id="template-urgency" type="number" min="1" max="5" step="1" value="3" required></label>
|
|
27405
27971
|
<label class="form-field"><span>${t(locale, "template.maxInstances")}</span><input id="template-max-instances" type="number" min="1" max="1000" step="1" value="1" required><small>${t(locale, "template.maxInstancesHint")}</small></label>
|
|
27406
27972
|
<label class="form-field"><span>${t(locale, "template.maxRetries")}</span><input id="template-max-retries" type="number" min="0" max="1000" step="1" value="3" required></label>
|
|
27407
|
-
<label class="form-field"><span>${t(locale, "template.retryBackoff")}</span
|
|
27408
|
-
<label class="form-field"><span>${t(locale, "template.timeout")}</span
|
|
27973
|
+
<label class="form-field"><span>${t(locale, "template.retryBackoff")}</span>${durationControl(locale, "template-retry-backoff", 3e4, "retry")}<small>${t(locale, "template.retryBackoffHint")}</small></label>
|
|
27974
|
+
<label class="form-field"><span>${t(locale, "template.timeout")}</span>${durationControl(locale, "template-timeout", null, "timeout")}<small>${t(locale, "template.timeoutHint")}</small></label>
|
|
27409
27975
|
</div>
|
|
27410
27976
|
</details>
|
|
27411
27977
|
<p class="form-note">${t(locale, "template.futureOnly")}</p>
|
|
@@ -27447,7 +28013,7 @@ var init_web = __esm({
|
|
|
27447
28013
|
const status = safeStatus(run.status);
|
|
27448
28014
|
const resumable = isValidSessionId(run.sessionId);
|
|
27449
28015
|
if (run.log) {
|
|
27450
|
-
logs.push(
|
|
28016
|
+
logs.push(renderRunLog(run.id, run.taskName, run.log, locale));
|
|
27451
28017
|
}
|
|
27452
28018
|
return `<tr>
|
|
27453
28019
|
<td class="faint" data-label="${t(locale, "table.run")}">#${run.id}</td>
|
|
@@ -28084,6 +28650,26 @@ init_pm2();
|
|
|
28084
28650
|
init_config();
|
|
28085
28651
|
import { spawnSync as spawnSync4 } from "child_process";
|
|
28086
28652
|
|
|
28653
|
+
// src/cli/i18n.ts
|
|
28654
|
+
function requestedLanguage(argv) {
|
|
28655
|
+
for (let index2 = 2; index2 < argv.length; index2 += 1) {
|
|
28656
|
+
const argument = argv[index2];
|
|
28657
|
+
if (argument === "--lang") return argv[index2 + 1];
|
|
28658
|
+
if (argument.startsWith("--lang=")) return argument.slice("--lang=".length);
|
|
28659
|
+
}
|
|
28660
|
+
return void 0;
|
|
28661
|
+
}
|
|
28662
|
+
function resolveCliLocale(argv = process.argv, env = process.env) {
|
|
28663
|
+
const requested = requestedLanguage(argv) ?? env.SUPERTASK_LANG ?? "auto";
|
|
28664
|
+
if (requested === "zh" || requested === "zh-CN") return "zh-CN";
|
|
28665
|
+
if (requested === "en") return "en";
|
|
28666
|
+
const systemLocale = env.LC_ALL || env.LC_MESSAGES || env.LANG || "";
|
|
28667
|
+
return /^zh(?:[_-]|$)/i.test(systemLocale) ? "zh-CN" : "en";
|
|
28668
|
+
}
|
|
28669
|
+
function cliText(locale, zh, en) {
|
|
28670
|
+
return locale === "zh-CN" ? zh : en;
|
|
28671
|
+
}
|
|
28672
|
+
|
|
28087
28673
|
// src/cli/database-output.ts
|
|
28088
28674
|
function useJson(options) {
|
|
28089
28675
|
const isTTY = options.isTTY ?? process.stdout.isTTY === true;
|
|
@@ -28100,23 +28686,52 @@ function formatBytes(bytes) {
|
|
|
28100
28686
|
const rendered = Number.isInteger(value) ? String(value) : value.toFixed(1);
|
|
28101
28687
|
return `${rendered} ${units[unit]}`;
|
|
28102
28688
|
}
|
|
28103
|
-
function formatCounts(counts) {
|
|
28104
|
-
return
|
|
28105
|
-
|
|
28106
|
-
|
|
28107
|
-
|
|
28108
|
-
|
|
28109
|
-
if (!gateway.wasRunning) return "\u65E0\u9700\u81EA\u52A8\u505C\u542F\uFF08\u672A\u53D1\u73B0\u5339\u914D\u5F53\u524D\u6570\u636E\u5E93\u7684 PM2 Gateway\uFF09";
|
|
28110
|
-
return "\u539F Gateway \u672A\u6062\u590D\u8FD0\u884C";
|
|
28689
|
+
function formatCounts(counts, locale) {
|
|
28690
|
+
return cliText(
|
|
28691
|
+
locale,
|
|
28692
|
+
`\u4EFB\u52A1 ${counts.tasks} \xB7 \u6267\u884C\u8BB0\u5F55 ${counts.taskRuns} \xB7 \u5B9A\u65F6\u4EFB\u52A1\u6A21\u677F ${counts.taskTemplates}`,
|
|
28693
|
+
`tasks ${counts.tasks} \xB7 runs ${counts.taskRuns} \xB7 scheduled templates ${counts.taskTemplates}`
|
|
28694
|
+
);
|
|
28111
28695
|
}
|
|
28112
|
-
function
|
|
28696
|
+
function formatGateway(gateway, locale) {
|
|
28697
|
+
if (gateway.restarted) return cliText(locale, "\u5DF2\u81EA\u52A8\u505C\u6B62\u3001\u91CD\u542F\u5E76\u6062\u590D\u5C31\u7EEA", "stopped, restarted, and ready");
|
|
28698
|
+
if (gateway.keptStopped) return cliText(locale, "\u5DF2\u81EA\u52A8\u505C\u6B62\uFF0C\u6309\u8981\u6C42\u4FDD\u6301\u505C\u6B62", "stopped and left stopped as requested");
|
|
28699
|
+
if (!gateway.wasRunning) {
|
|
28700
|
+
return cliText(
|
|
28701
|
+
locale,
|
|
28702
|
+
"\u65E0\u9700\u81EA\u52A8\u505C\u542F\uFF08\u672A\u53D1\u73B0\u5339\u914D\u5F53\u524D\u6570\u636E\u5E93\u7684 PM2 Gateway\uFF09",
|
|
28703
|
+
"no matching PM2 Gateway was running"
|
|
28704
|
+
);
|
|
28705
|
+
}
|
|
28706
|
+
return cliText(locale, "\u539F Gateway \u672A\u6062\u590D\u8FD0\u884C", "the previous Gateway was not restored");
|
|
28707
|
+
}
|
|
28708
|
+
function formatCheck(result, locale) {
|
|
28709
|
+
if (locale === "en") {
|
|
28710
|
+
const lines2 = [
|
|
28711
|
+
result.ok ? "\u2713 Database check passed" : "\u2717 Database check failed",
|
|
28712
|
+
"",
|
|
28713
|
+
`Database: ${result.path}`,
|
|
28714
|
+
`Size: ${formatBytes(result.sizeBytes)}`,
|
|
28715
|
+
`Journal mode: ${result.journalMode}`,
|
|
28716
|
+
`Counts: ${formatCounts(result.counts, locale)}`,
|
|
28717
|
+
`Running: tasks ${result.runningTasks} \xB7 runs ${result.runningRuns}`
|
|
28718
|
+
];
|
|
28719
|
+
if (!result.ok) {
|
|
28720
|
+
lines2.push(
|
|
28721
|
+
`Integrity: ${result.integrityMessages.join("; ") || "no result"}`,
|
|
28722
|
+
`Foreign-key violations: ${result.foreignKeyViolations}`,
|
|
28723
|
+
`Missing tables: ${result.missingTables.join(", ") || "none"}`
|
|
28724
|
+
);
|
|
28725
|
+
}
|
|
28726
|
+
return lines2.join("\n");
|
|
28727
|
+
}
|
|
28113
28728
|
const lines = [
|
|
28114
28729
|
result.ok ? "\u2713 \u6570\u636E\u5E93\u68C0\u67E5\u901A\u8FC7" : "\u2717 \u6570\u636E\u5E93\u68C0\u67E5\u672A\u901A\u8FC7",
|
|
28115
28730
|
"",
|
|
28116
28731
|
`\u6570\u636E\u5E93\uFF1A${result.path}`,
|
|
28117
28732
|
`\u5927\u5C0F\uFF1A${formatBytes(result.sizeBytes)}`,
|
|
28118
28733
|
`\u65E5\u5FD7\u6A21\u5F0F\uFF1A${result.journalMode}`,
|
|
28119
|
-
`\u6570\u636E\u7EDF\u8BA1\uFF1A${formatCounts(result.counts)}`,
|
|
28734
|
+
`\u6570\u636E\u7EDF\u8BA1\uFF1A${formatCounts(result.counts, locale)}`,
|
|
28120
28735
|
`\u8FD0\u884C\u4E2D\uFF1A\u4EFB\u52A1 ${result.runningTasks} \xB7 \u6267\u884C\u8BB0\u5F55 ${result.runningRuns}`
|
|
28121
28736
|
];
|
|
28122
28737
|
if (!result.ok) {
|
|
@@ -28128,49 +28743,81 @@ function formatCheck(result) {
|
|
|
28128
28743
|
}
|
|
28129
28744
|
return lines.join("\n");
|
|
28130
28745
|
}
|
|
28131
|
-
function formatHuman(operation, result) {
|
|
28746
|
+
function formatHuman(operation, result, locale) {
|
|
28132
28747
|
switch (operation) {
|
|
28133
28748
|
case "check":
|
|
28134
|
-
return formatCheck(result);
|
|
28749
|
+
return formatCheck(result, locale);
|
|
28135
28750
|
case "backup": {
|
|
28136
28751
|
const backup = result;
|
|
28752
|
+
if (locale === "en") {
|
|
28753
|
+
return [
|
|
28754
|
+
"\u2713 Database backup completed",
|
|
28755
|
+
"",
|
|
28756
|
+
`Backup: ${backup.path}`,
|
|
28757
|
+
`Size: ${formatBytes(backup.sizeBytes)}`,
|
|
28758
|
+
`Counts: ${formatCounts(backup.check.counts, locale)}`,
|
|
28759
|
+
`Integrity: ${backup.check.ok ? "passed" : "failed"}`
|
|
28760
|
+
].join("\n");
|
|
28761
|
+
}
|
|
28137
28762
|
return [
|
|
28138
28763
|
"\u2713 \u6570\u636E\u5E93\u5907\u4EFD\u5B8C\u6210",
|
|
28139
28764
|
"",
|
|
28140
28765
|
`\u5907\u4EFD\u6587\u4EF6\uFF1A${backup.path}`,
|
|
28141
28766
|
`\u5927\u5C0F\uFF1A${formatBytes(backup.sizeBytes)}`,
|
|
28142
|
-
`\u6570\u636E\u7EDF\u8BA1\uFF1A${formatCounts(backup.check.counts)}`,
|
|
28767
|
+
`\u6570\u636E\u7EDF\u8BA1\uFF1A${formatCounts(backup.check.counts, locale)}`,
|
|
28143
28768
|
`\u6570\u636E\u5E93\u5B8C\u6574\u6027\uFF1A${backup.check.ok ? "\u901A\u8FC7" : "\u672A\u901A\u8FC7"}`
|
|
28144
28769
|
].join("\n");
|
|
28145
28770
|
}
|
|
28146
28771
|
case "clear": {
|
|
28147
28772
|
const cleared = result;
|
|
28773
|
+
if (locale === "en") {
|
|
28774
|
+
return [
|
|
28775
|
+
"\u2713 Database safely cleared",
|
|
28776
|
+
"",
|
|
28777
|
+
`Deleted: ${formatCounts(cleared.deleted, locale)}`,
|
|
28778
|
+
`Safety backup: ${cleared.backupPath}`,
|
|
28779
|
+
`Gateway: ${formatGateway(cleared.gateway, locale)}`,
|
|
28780
|
+
`Integrity: ${cleared.check.ok ? "passed" : "failed"}`
|
|
28781
|
+
].join("\n");
|
|
28782
|
+
}
|
|
28148
28783
|
return [
|
|
28149
28784
|
"\u2713 \u6570\u636E\u5E93\u5DF2\u5B89\u5168\u6E05\u7A7A",
|
|
28150
28785
|
"",
|
|
28151
|
-
`\u5DF2\u5220\u9664\uFF1A${formatCounts(cleared.deleted)}`,
|
|
28786
|
+
`\u5DF2\u5220\u9664\uFF1A${formatCounts(cleared.deleted, locale)}`,
|
|
28152
28787
|
`\u5B89\u5168\u5907\u4EFD\uFF1A${cleared.backupPath}`,
|
|
28153
|
-
`Gateway\uFF1A${formatGateway(cleared.gateway)}`,
|
|
28788
|
+
`Gateway\uFF1A${formatGateway(cleared.gateway, locale)}`,
|
|
28154
28789
|
`\u6570\u636E\u5E93\u5B8C\u6574\u6027\uFF1A${cleared.check.ok ? "\u901A\u8FC7" : "\u672A\u901A\u8FC7"}`
|
|
28155
28790
|
].join("\n");
|
|
28156
28791
|
}
|
|
28157
28792
|
case "restore": {
|
|
28158
28793
|
const restored = result;
|
|
28794
|
+
if (locale === "en") {
|
|
28795
|
+
return [
|
|
28796
|
+
"\u2713 Database restore completed",
|
|
28797
|
+
"",
|
|
28798
|
+
`Source: ${restored.sourcePath}`,
|
|
28799
|
+
`Pre-restore safety backup: ${restored.safetyBackupPath}`,
|
|
28800
|
+
`Recovered runtime state: tasks ${restored.recoveredRunningTasks} \xB7 runs ${restored.closedRunningRuns}`,
|
|
28801
|
+
`Counts: ${formatCounts(restored.check.counts, locale)}`,
|
|
28802
|
+
`Gateway: ${formatGateway(restored.gateway, locale)}`,
|
|
28803
|
+
`Integrity: ${restored.check.ok ? "passed" : "failed"}`
|
|
28804
|
+
].join("\n");
|
|
28805
|
+
}
|
|
28159
28806
|
return [
|
|
28160
28807
|
"\u2713 \u6570\u636E\u5E93\u6062\u590D\u5B8C\u6210",
|
|
28161
28808
|
"",
|
|
28162
28809
|
`\u6062\u590D\u6765\u6E90\uFF1A${restored.sourcePath}`,
|
|
28163
28810
|
`\u6062\u590D\u524D\u5B89\u5168\u5907\u4EFD\uFF1A${restored.safetyBackupPath}`,
|
|
28164
28811
|
`\u8FD0\u884C\u6001\u6536\u655B\uFF1A\u4EFB\u52A1 ${restored.recoveredRunningTasks} \xB7 \u6267\u884C\u8BB0\u5F55 ${restored.closedRunningRuns}`,
|
|
28165
|
-
`\u6570\u636E\u7EDF\u8BA1\uFF1A${formatCounts(restored.check.counts)}`,
|
|
28166
|
-
`Gateway\uFF1A${formatGateway(restored.gateway)}`,
|
|
28812
|
+
`\u6570\u636E\u7EDF\u8BA1\uFF1A${formatCounts(restored.check.counts, locale)}`,
|
|
28813
|
+
`Gateway\uFF1A${formatGateway(restored.gateway, locale)}`,
|
|
28167
28814
|
`\u6570\u636E\u5E93\u5B8C\u6574\u6027\uFF1A${restored.check.ok ? "\u901A\u8FC7" : "\u672A\u901A\u8FC7"}`
|
|
28168
28815
|
].join("\n");
|
|
28169
28816
|
}
|
|
28170
28817
|
}
|
|
28171
28818
|
}
|
|
28172
28819
|
function renderDatabaseResult(operation, result, options = {}) {
|
|
28173
|
-
return useJson(options) ? JSON.stringify(result, null, 2) : formatHuman(operation, result);
|
|
28820
|
+
return useJson(options) ? JSON.stringify(result, null, 2) : formatHuman(operation, result, options.locale ?? "zh-CN");
|
|
28174
28821
|
}
|
|
28175
28822
|
function renderDatabaseError(error, options = {}) {
|
|
28176
28823
|
const message = error instanceof Error ? error.message : String(error);
|
|
@@ -28214,6 +28861,8 @@ function parseTaskStatus(value) {
|
|
|
28214
28861
|
|
|
28215
28862
|
// src/cli/index.ts
|
|
28216
28863
|
init_update2();
|
|
28864
|
+
var cliLocale = resolveCliLocale();
|
|
28865
|
+
var t2 = (zh, en) => cliText(cliLocale, zh, en);
|
|
28217
28866
|
async function withDb(fn, formatError = (error) => JSON.stringify({
|
|
28218
28867
|
error: error instanceof Error ? error.message : String(error)
|
|
28219
28868
|
})) {
|
|
@@ -28239,8 +28888,13 @@ function runDestructiveDatabaseMaintenance(keepStopped, operation) {
|
|
|
28239
28888
|
};
|
|
28240
28889
|
}
|
|
28241
28890
|
var program2 = new Command();
|
|
28242
|
-
program2.name("supertask").description("\
|
|
28243
|
-
|
|
28891
|
+
program2.name("supertask").description(t2("\u9762\u5411 OpenCode Agent \u7684\u6301\u4E45\u5316\u4EFB\u52A1\u961F\u5217\u4E0E\u5B9A\u65F6\u4EFB\u52A1\u7CFB\u7EDF", "Durable task queue and scheduler for OpenCode agents")).addOption(new Option("--lang <language>", t2("CLI \u8BED\u8A00\uFF1Aauto / zh-CN / en", "CLI language: auto / zh-CN / en")).choices(["auto", "zh-CN", "en"]).default("auto")).helpOption("-h, --help", t2("\u663E\u793A\u5E2E\u52A9", "display help for command")).addHelpCommand("help [command]", t2("\u663E\u793A\u547D\u4EE4\u5E2E\u52A9", "display help for command")).version(getPackageVersion(), "-V, --version", t2("\u663E\u793A\u7248\u672C\u53F7", "output the version number"));
|
|
28892
|
+
if (cliLocale === "zh-CN") {
|
|
28893
|
+
program2.configureOutput({
|
|
28894
|
+
writeOut: (value) => process.stdout.write(value.replace(/^Usage:/gm, "\u7528\u6CD5\uFF1A").replace(/^Options:/gm, "\u9009\u9879\uFF1A").replace(/^Commands:/gm, "\u547D\u4EE4\uFF1A").replace(/^Arguments:/gm, "\u53C2\u6570\uFF1A"))
|
|
28895
|
+
});
|
|
28896
|
+
}
|
|
28897
|
+
program2.command("add").description(t2("\u521B\u5EFA\u65B0\u4EFB\u52A1", "create a queued task")).requiredOption("-n, --name <name>", t2("\u4EFB\u52A1\u540D\u79F0", "task name")).requiredOption("-a, --agent <agent>", t2("\u4E3B Agent \u540D\u79F0", "primary agent name")).requiredOption("-p, --prompt <prompt>", t2("\u63D0\u793A\u8BCD", "prompt")).option("-m, --model <model>", t2("\u6A21\u578B", "model")).option("-c, --category <category>", t2("\u5206\u7C7B", "category"), "general").option("-i, --importance <number>", t2("\u91CD\u8981\u7A0B\u5EA6 (1-5)", "importance (1-5)"), "3").option("-u, --urgency <number>", t2("\u7D27\u6025\u7A0B\u5EA6 (1-5)", "urgency (1-5)"), "3").option("-b, --batch <batchId>", t2("\u6279\u6B21 ID", "batch ID")).option("-d, --depends <taskId>", t2("\u4F9D\u8D56\u7684\u4EFB\u52A1 ID", "dependency task ID")).option("--max-retries <number>", t2("\u9996\u6B21\u6267\u884C\u4E4B\u5916\u5141\u8BB8\u7684\u91CD\u8BD5\u6B21\u6570", "retries allowed after the first attempt"), "3").option("--retry-backoff <duration>", t2("\u91CD\u8BD5\u9000\u907F\u57FA\u7840\u95F4\u9694\uFF0C\u5982 30s / 5min", "retry backoff base, e.g. 30s / 5min"), "30s").option("--timeout <duration>", t2("\u4EFB\u52A1\u786C\u8D85\u65F6\uFF0C\u5982 30min / 2h", "hard timeout, e.g. 30min / 2h")).option("-w, --cwd <path>", t2("(\u5DF2\u5E9F\u5F03) \u7CFB\u7EDF\u4F1A\u81EA\u52A8\u8BB0\u5F55\u63D0\u4EA4\u65F6\u7684\u5F53\u524D\u76EE\u5F55", "(deprecated) the submission directory is recorded automatically")).action(async (options) => withDb(async () => {
|
|
28244
28898
|
const submitCwd = process.cwd();
|
|
28245
28899
|
const retryBackoffMs = parseDuration(options.retryBackoff);
|
|
28246
28900
|
const timeoutMs = options.timeout ? parseDuration(options.timeout) : null;
|
|
@@ -28264,7 +28918,7 @@ program2.command("add").description("\u521B\u5EFA\u65B0\u4EFB\u52A1").requiredOp
|
|
|
28264
28918
|
});
|
|
28265
28919
|
console.log(JSON.stringify({ id: task.id, status: "created" }, null, 2));
|
|
28266
28920
|
}));
|
|
28267
|
-
program2.command("edit").description("\u4FEE\u6539\u5F53\u524D\u9879\u76EE\u4E2D\u5C1A\u672A\u5B8C\u6210\u7684\u4EFB\u52A1").requiredOption("--id <id>", "\u4EFB\u52A1 ID").option("-n, --name <name>", "\u4EFB\u52A1\u540D\u79F0").option("-a, --agent <agent>", "Agent \u540D\u79F0").option("-m, --model <model>", "\u6A21\u578B").option("-p, --prompt <prompt>", "\u63D0\u793A\u8BCD").option("-c, --category <category>", "\u5206\u7C7B").option("-i, --importance <number>", "\u91CD\u8981\u7A0B\u5EA6 (1-5)").option("-u, --urgency <number>", "\u7D27\u6025\u7A0B\u5EA6 (1-5)").option("-b, --batch <batchId>", "\u6279\u6B21 ID").option("--clear-batch", "\u6E05\u7A7A\u6279\u6B21 ID").option("--max-retries <number>", "\u9996\u6B21\u6267\u884C\u4E4B\u5916\u5141\u8BB8\u7684\u91CD\u8BD5\u6B21\u6570").option("--retry-backoff <duration>", "\u91CD\u8BD5\u9000\u907F\u57FA\u7840\u95F4\u9694\uFF0C\u5982 30s / 5min").option("--timeout <duration>", "\u4EFB\u52A1\u786C\u8D85\u65F6\uFF0C\u5982 30min / 2h").option("--clear-timeout", "\u6E05\u7A7A\u4EFB\u52A1\u7EA7\u8D85\u65F6\uFF0C\u6539\u7528 Gateway \u9ED8\u8BA4\u503C").action(async (options) => withDb(async () => {
|
|
28921
|
+
program2.command("edit").description(t2("\u4FEE\u6539\u5F53\u524D\u9879\u76EE\u4E2D\u5C1A\u672A\u5B8C\u6210\u7684\u4EFB\u52A1", "edit an unfinished task in the current project")).requiredOption("--id <id>", t2("\u4EFB\u52A1 ID", "task ID")).option("-n, --name <name>", t2("\u4EFB\u52A1\u540D\u79F0", "task name")).option("-a, --agent <agent>", t2("Agent \u540D\u79F0", "agent name")).option("-m, --model <model>", t2("\u6A21\u578B", "model")).option("-p, --prompt <prompt>", t2("\u63D0\u793A\u8BCD", "prompt")).option("-c, --category <category>", t2("\u5206\u7C7B", "category")).option("-i, --importance <number>", t2("\u91CD\u8981\u7A0B\u5EA6 (1-5)", "importance (1-5)")).option("-u, --urgency <number>", t2("\u7D27\u6025\u7A0B\u5EA6 (1-5)", "urgency (1-5)")).option("-b, --batch <batchId>", t2("\u6279\u6B21 ID", "batch ID")).option("--clear-batch", t2("\u6E05\u7A7A\u6279\u6B21 ID", "clear the batch ID")).option("--max-retries <number>", t2("\u9996\u6B21\u6267\u884C\u4E4B\u5916\u5141\u8BB8\u7684\u91CD\u8BD5\u6B21\u6570", "retries allowed after the first attempt")).option("--retry-backoff <duration>", t2("\u91CD\u8BD5\u9000\u907F\u57FA\u7840\u95F4\u9694\uFF0C\u5982 30s / 5min", "retry backoff base, e.g. 30s / 5min")).option("--timeout <duration>", t2("\u4EFB\u52A1\u786C\u8D85\u65F6\uFF0C\u5982 30min / 2h", "hard timeout, e.g. 30min / 2h")).option("--clear-timeout", t2("\u6E05\u7A7A\u4EFB\u52A1\u7EA7\u8D85\u65F6\uFF0C\u6539\u7528 Gateway \u9ED8\u8BA4\u503C", "clear the task timeout and use the Gateway default")).action(async (options) => withDb(async () => {
|
|
28268
28922
|
if (options.batch !== void 0 && options.clearBatch) {
|
|
28269
28923
|
throw new Error("batch \u548C clear-batch \u4E0D\u80FD\u540C\u65F6\u4F7F\u7528");
|
|
28270
28924
|
}
|
|
@@ -28302,7 +28956,7 @@ program2.command("edit").description("\u4FEE\u6539\u5F53\u524D\u9879\u76EE\u4E2D
|
|
|
28302
28956
|
if (!task) throw new Error(`\u4EFB\u52A1 #${id} \u4E0D\u5B58\u5728\u4E8E\u5F53\u524D\u9879\u76EE\uFF0C\u6216\u5176\u72B6\u6001\u4E0D\u5141\u8BB8\u7F16\u8F91`);
|
|
28303
28957
|
console.log(JSON.stringify({ id: task.id, status: task.status, updated: true }, null, 2));
|
|
28304
28958
|
}));
|
|
28305
|
-
program2.command("next").description("\u83B7\u53D6\u4E0B\u4E00\u4E2A\u5F85\u6267\u884C\u7684\u4EFB\u52A1").action(async () => withDb(async () => {
|
|
28959
|
+
program2.command("next").description(t2("\u83B7\u53D6\u4E0B\u4E00\u4E2A\u5F85\u6267\u884C\u7684\u4EFB\u52A1", "show the next runnable task")).action(async () => withDb(async () => {
|
|
28306
28960
|
const task = await TaskService.next({ cwd: process.cwd() });
|
|
28307
28961
|
if (task) {
|
|
28308
28962
|
console.log(JSON.stringify({
|
|
@@ -28320,7 +28974,7 @@ program2.command("next").description("\u83B7\u53D6\u4E0B\u4E00\u4E2A\u5F85\u6267
|
|
|
28320
28974
|
console.log(JSON.stringify({ id: null, message: "No executable tasks" }));
|
|
28321
28975
|
}
|
|
28322
28976
|
}));
|
|
28323
|
-
program2.command("cancel").description("\u53D6\u6D88\u4EFB\u52A1").requiredOption("--id <id>", "\u4EFB\u52A1 ID").action(async (options) => withDb(async () => {
|
|
28977
|
+
program2.command("cancel").description(t2("\u53D6\u6D88\u4EFB\u52A1", "cancel a task")).requiredOption("--id <id>", t2("\u4EFB\u52A1 ID", "task ID")).action(async (options) => withDb(async () => {
|
|
28324
28978
|
const task = await TaskService.cancel(parsePositiveInteger(options.id, "id"), { cwd: process.cwd() });
|
|
28325
28979
|
if (task) {
|
|
28326
28980
|
console.log(JSON.stringify({ id: task.id, status: task.status }));
|
|
@@ -28329,8 +28983,8 @@ program2.command("cancel").description("\u53D6\u6D88\u4EFB\u52A1").requiredOptio
|
|
|
28329
28983
|
process.exit(1);
|
|
28330
28984
|
}
|
|
28331
28985
|
}));
|
|
28332
|
-
var runCommand = new Command("run").description("\u7BA1\u7406\u9694\u79BB\u7684\u6267\u884C\u8BB0\u5F55");
|
|
28333
|
-
runCommand.command("abandon").description("\u4EBA\u5DE5\u5173\u95ED\u5DF2\u786E\u8BA4\u4E0D\u5B58\u5728\u9057\u7559\u8FDB\u7A0B\u7684\u65E7\u7248\u65E0 PID \u9694\u79BB\u8BB0\u5F55").requiredOption("--id <id>", "\u6267\u884C\u8BB0\u5F55 run ID").option("--confirm <word>", "\u5371\u9669\u64CD\u4F5C\u786E\u8BA4\uFF0C\u5FC5\u987B\u586B\u5199 ABANDON").action(async (options) => withDb(async () => {
|
|
28986
|
+
var runCommand = new Command("run").description(t2("\u7BA1\u7406\u9694\u79BB\u7684\u6267\u884C\u8BB0\u5F55", "manage quarantined task runs"));
|
|
28987
|
+
runCommand.command("abandon").description(t2("\u4EBA\u5DE5\u5173\u95ED\u5DF2\u786E\u8BA4\u4E0D\u5B58\u5728\u9057\u7559\u8FDB\u7A0B\u7684\u65E7\u7248\u65E0 PID \u9694\u79BB\u8BB0\u5F55", "close a legacy no-PID quarantine after confirming no process remains")).requiredOption("--id <id>", t2("\u6267\u884C\u8BB0\u5F55 run ID", "run ID")).option("--confirm <word>", t2("\u5371\u9669\u64CD\u4F5C\u786E\u8BA4\uFF0C\u5FC5\u987B\u586B\u5199 ABANDON", "confirmation word; must be ABANDON")).action(async (options) => withDb(async () => {
|
|
28334
28988
|
if (options.confirm !== "ABANDON") {
|
|
28335
28989
|
throw new Error("\u5173\u95ED\u65E7\u7248\u9694\u79BB run \u5FC5\u987B\u663E\u5F0F\u4F20\u5165 --confirm ABANDON");
|
|
28336
28990
|
}
|
|
@@ -28340,7 +28994,7 @@ runCommand.command("abandon").description("\u4EBA\u5DE5\u5173\u95ED\u5DF2\u786E\
|
|
|
28340
28994
|
console.log(JSON.stringify(result, null, 2));
|
|
28341
28995
|
}));
|
|
28342
28996
|
program2.addCommand(runCommand);
|
|
28343
|
-
program2.command("retry").description("\u91CD\u8BD5\u5931\u8D25\u7684\u4EFB\u52A1").option("--id <id>", "\u4EFB\u52A1 ID").option("-b, --batch <batchId>", "\u6279\u6B21 ID\uFF08\u6279\u91CF\u91CD\u8BD5\uFF09").action(async (options) => withDb(async () => {
|
|
28997
|
+
program2.command("retry").description(t2("\u91CD\u8BD5\u5931\u8D25\u7684\u4EFB\u52A1", "retry failed tasks")).option("--id <id>", t2("\u4EFB\u52A1 ID", "task ID")).option("-b, --batch <batchId>", t2("\u6279\u6B21 ID\uFF08\u6279\u91CF\u91CD\u8BD5\uFF09", "batch ID for bulk retry")).action(async (options) => withDb(async () => {
|
|
28344
28998
|
if (options.id) {
|
|
28345
28999
|
const task = await TaskService.retry(parsePositiveInteger(options.id, "id"), { cwd: process.cwd() });
|
|
28346
29000
|
if (task) {
|
|
@@ -28357,11 +29011,11 @@ program2.command("retry").description("\u91CD\u8BD5\u5931\u8D25\u7684\u4EFB\u52A
|
|
|
28357
29011
|
process.exit(1);
|
|
28358
29012
|
}
|
|
28359
29013
|
}));
|
|
28360
|
-
program2.command("status").description("\u67E5\u770B\u4EFB\u52A1\u7EDF\u8BA1").option("-b, --batch <batchId>", "\u6309\u6279\u6B21\u7EDF\u8BA1").action(async (options) => withDb(async () => {
|
|
29014
|
+
program2.command("status").description(t2("\u67E5\u770B\u4EFB\u52A1\u7EDF\u8BA1", "show task counts")).option("-b, --batch <batchId>", t2("\u6309\u6279\u6B21\u7EDF\u8BA1", "filter counts by batch")).action(async (options) => withDb(async () => {
|
|
28361
29015
|
const stats = await TaskService.stats({ batchId: options.batch, cwd: process.cwd() });
|
|
28362
29016
|
console.log(JSON.stringify(stats, null, 2));
|
|
28363
29017
|
}));
|
|
28364
|
-
program2.command("list").description("\u5217\u51FA\u4EFB\u52A1").option("-s, --status <status>", "\u6309\u72B6\u6001\u7B5B\u9009").option("-b, --batch <batchId>", "\u6309\u6279\u6B21\u7B5B\u9009").option("-c, --category <category>", "\u6309\u5206\u7C7B\u7B5B\u9009").option("-l, --limit <number>", "\u9650\u5236\u6570\u91CF", "20").action(async (options) => withDb(async () => {
|
|
29018
|
+
program2.command("list").description(t2("\u5217\u51FA\u4EFB\u52A1", "list tasks")).option("-s, --status <status>", t2("\u6309\u72B6\u6001\u7B5B\u9009", "filter by status")).option("-b, --batch <batchId>", t2("\u6309\u6279\u6B21\u7B5B\u9009", "filter by batch")).option("-c, --category <category>", t2("\u6309\u5206\u7C7B\u7B5B\u9009", "filter by category")).option("-l, --limit <number>", t2("\u9650\u5236\u6570\u91CF", "maximum rows"), "20").action(async (options) => withDb(async () => {
|
|
28365
29019
|
const tasks4 = await TaskService.list({
|
|
28366
29020
|
status: parseTaskStatus(options.status),
|
|
28367
29021
|
batchId: options.batch,
|
|
@@ -28371,7 +29025,7 @@ program2.command("list").description("\u5217\u51FA\u4EFB\u52A1").option("-s, --s
|
|
|
28371
29025
|
});
|
|
28372
29026
|
console.log(JSON.stringify(tasks4, null, 2));
|
|
28373
29027
|
}));
|
|
28374
|
-
program2.command("get").description("\u83B7\u53D6\u5355\u4E2A\u4EFB\u52A1\u8BE6\u60C5").requiredOption("--id <id>", "\u4EFB\u52A1 ID").action(async (options) => withDb(async () => {
|
|
29028
|
+
program2.command("get").description(t2("\u83B7\u53D6\u5355\u4E2A\u4EFB\u52A1\u8BE6\u60C5", "show one task")).requiredOption("--id <id>", t2("\u4EFB\u52A1 ID", "task ID")).action(async (options) => withDb(async () => {
|
|
28375
29029
|
const task = await TaskService.getById(parsePositiveInteger(options.id, "id"), { cwd: process.cwd() });
|
|
28376
29030
|
if (task) {
|
|
28377
29031
|
console.log(JSON.stringify(task, null, 2));
|
|
@@ -28380,13 +29034,13 @@ program2.command("get").description("\u83B7\u53D6\u5355\u4E2A\u4EFB\u52A1\u8BE6\
|
|
|
28380
29034
|
process.exit(1);
|
|
28381
29035
|
}
|
|
28382
29036
|
}));
|
|
28383
|
-
program2.command("delete").description("\u5220\u9664\u4EFB\u52A1").requiredOption("--id <id>", "\u4EFB\u52A1 ID").action(async (options) => withDb(async () => {
|
|
29037
|
+
program2.command("delete").description(t2("\u5220\u9664\u4EFB\u52A1", "delete a task")).requiredOption("--id <id>", t2("\u4EFB\u52A1 ID", "task ID")).action(async (options) => withDb(async () => {
|
|
28384
29038
|
const id = parsePositiveInteger(options.id, "id");
|
|
28385
29039
|
const deleted = await TaskService.delete(id, { cwd: process.cwd() });
|
|
28386
29040
|
console.log(JSON.stringify({ deleted, id }));
|
|
28387
29041
|
}));
|
|
28388
|
-
program2.command("template").description("\u7BA1\u7406\u4EFB\u52A1\
|
|
28389
|
-
new Command("add").description("\u521B\u5EFA\
|
|
29042
|
+
program2.command("template").description(t2("\u7BA1\u7406\u5B9A\u65F6\u4EFB\u52A1\u6A21\u677F", "manage scheduled task templates")).addCommand(
|
|
29043
|
+
new Command("add").description(t2("\u521B\u5EFA\u5B9A\u65F6\u4EFB\u52A1\u6A21\u677F", "create a scheduled task template")).requiredOption("-n, --name <name>", t2("\u6A21\u677F\u540D\u79F0", "template name")).requiredOption("-a, --agent <agent>", t2("Agent \u540D\u79F0", "agent name")).requiredOption("-p, --prompt <prompt>", t2("\u63D0\u793A\u8BCD", "prompt")).requiredOption("-t, --type <type>", t2("\u5B9A\u65F6\u7C7B\u578B\uFF1Acron/delayed/recurring", "schedule type: cron/delayed/recurring")).option("--cron <expr>", t2("cron \u8868\u8FBE\u5F0F\uFF08cron \u7C7B\u578B\u5FC5\u586B\uFF09", "cron expression (required for cron)")).option("--delay <duration>", t2("\u5EF6\u8FDF\u65F6\u95F4\uFF08delayed \u5FC5\u586B\uFF09\uFF0C\u5982 30s / 5min / 1h / 2d", "delay (required for delayed), e.g. 30s / 5min / 1h / 2d")).option("--interval <duration>", t2("\u5FAA\u73AF\u95F4\u9694\uFF08recurring \u5FC5\u586B\uFF09\uFF0C\u5982 1h / 30min / 5s", "interval (required for recurring), e.g. 1h / 30min / 5s")).option("-m, --model <model>", t2("\u6A21\u578B", "model")).option("-c, --category <category>", t2("\u5206\u7C7B", "category"), "general").option("-i, --importance <number>", t2("\u91CD\u8981\u7A0B\u5EA6 1-5", "importance 1-5"), "3").option("-u, --urgency <number>", t2("\u7D27\u6025\u7A0B\u5EA6 1-5", "urgency 1-5"), "3").option("-b, --batch <batchId>", t2("\u6A21\u677F\u751F\u6210\u4EFB\u52A1\u7684\u6279\u6B21 ID", "batch ID for generated tasks")).option("--max-instances <number>", t2("\u81EA\u52A8\u5B9A\u65F6\u4EFB\u52A1\u7684\u6D3B\u8DC3\u5B9E\u4F8B\u4E0A\u9650\uFF08\u7ACB\u5373\u89E6\u53D1\u4E0D\u53D7\u9650\uFF09", "active instance limit for automatic scheduling (Run now is unrestricted)"), "1").option("--max-retries <number>", t2("\u6700\u5927\u91CD\u8BD5\u6B21\u6570", "maximum retries"), "3").option("--retry-backoff <duration>", t2("\u9000\u907F\u57FA\u7840\u95F4\u9694\uFF0C\u5982 30s / 5min", "retry backoff base, e.g. 30s / 5min"), "30s").option("--timeout <duration>", t2("\u6BCF\u6B21\u4EFB\u52A1\u786C\u8D85\u65F6\uFF0C\u5982 30min / 2h", "hard timeout per task, e.g. 30min / 2h")).action(async (options) => withDb(async () => {
|
|
28390
29044
|
let intervalMs = null;
|
|
28391
29045
|
let runAt = null;
|
|
28392
29046
|
const retryBackoffMs = parseDuration(options.retryBackoff);
|
|
@@ -28431,12 +29085,12 @@ program2.command("template").description("\u7BA1\u7406\u4EFB\u52A1\u8C03\u5EA6\u
|
|
|
28431
29085
|
console.log(JSON.stringify({ id: tmpl.id, status: "created", nextRunAt: tmpl.nextRunAt }, null, 2));
|
|
28432
29086
|
}))
|
|
28433
29087
|
).addCommand(
|
|
28434
|
-
new Command("list").description("\u5217\u51FA\
|
|
29088
|
+
new Command("list").description(t2("\u5217\u51FA\u5B9A\u65F6\u4EFB\u52A1\u6A21\u677F", "list scheduled task templates")).action(async () => withDb(async () => {
|
|
28435
29089
|
const templates = await TaskTemplateService.list();
|
|
28436
29090
|
console.log(JSON.stringify(templates, null, 2));
|
|
28437
29091
|
}))
|
|
28438
29092
|
).addCommand(
|
|
28439
|
-
new Command("enable").description("\u542F\u7528\u6A21\u677F").requiredOption("--id <id>", "\u6A21\u677F ID").action(async (options) => withDb(async () => {
|
|
29093
|
+
new Command("enable").description(t2("\u542F\u7528\u6A21\u677F", "enable a template")).requiredOption("--id <id>", t2("\u6A21\u677F ID", "template ID")).action(async (options) => withDb(async () => {
|
|
28440
29094
|
const tmpl = await TaskTemplateService.enable(parsePositiveInteger(options.id, "id"));
|
|
28441
29095
|
if (tmpl) {
|
|
28442
29096
|
console.log(JSON.stringify({ id: tmpl.id, enabled: true }));
|
|
@@ -28446,7 +29100,7 @@ program2.command("template").description("\u7BA1\u7406\u4EFB\u52A1\u8C03\u5EA6\u
|
|
|
28446
29100
|
}
|
|
28447
29101
|
}))
|
|
28448
29102
|
).addCommand(
|
|
28449
|
-
new Command("disable").description("\u7981\u7528\u6A21\u677F").requiredOption("--id <id>", "\u6A21\u677F ID").action(async (options) => withDb(async () => {
|
|
29103
|
+
new Command("disable").description(t2("\u7981\u7528\u6A21\u677F", "disable a template")).requiredOption("--id <id>", t2("\u6A21\u677F ID", "template ID")).action(async (options) => withDb(async () => {
|
|
28450
29104
|
const tmpl = await TaskTemplateService.disable(parsePositiveInteger(options.id, "id"));
|
|
28451
29105
|
if (tmpl) {
|
|
28452
29106
|
console.log(JSON.stringify({ id: tmpl.id, enabled: false }));
|
|
@@ -28456,23 +29110,23 @@ program2.command("template").description("\u7BA1\u7406\u4EFB\u52A1\u8C03\u5EA6\u
|
|
|
28456
29110
|
}
|
|
28457
29111
|
}))
|
|
28458
29112
|
).addCommand(
|
|
28459
|
-
new Command("delete").description("\u5220\u9664\u6A21\u677F").requiredOption("--id <id>", "\u6A21\u677F ID").action(async (options) => withDb(async () => {
|
|
29113
|
+
new Command("delete").description(t2("\u5220\u9664\u6A21\u677F", "delete a template")).requiredOption("--id <id>", t2("\u6A21\u677F ID", "template ID")).action(async (options) => withDb(async () => {
|
|
28460
29114
|
const id = parsePositiveInteger(options.id, "id");
|
|
28461
29115
|
const deleted = await TaskTemplateService.delete(id);
|
|
28462
29116
|
console.log(JSON.stringify({ deleted, id }));
|
|
28463
29117
|
}))
|
|
28464
29118
|
);
|
|
28465
|
-
var databaseCommand = new Command("db").description("\u6570\u636E\u5E93\u68C0\u67E5\u3001\u5907\u4EFD\u3001\u6E05\u7A7A\u4E0E\u6062\u590D");
|
|
28466
|
-
databaseCommand.command("check").description("\u68C0\u67E5\u6570\u636E\u5E93\u5B8C\u6574\u6027\u3001\u5916\u952E\u548C\u4E1A\u52A1\u8868\u7EDF\u8BA1").option("--json", "\u5F3A\u5236\u8F93\u51FA JSON\uFF08\u975E\u4EA4\u4E92\u8C03\u7528\u9ED8\u8BA4\u5DF2\u8F93\u51FA JSON\uFF09").action(async (options) => withDb(async () => {
|
|
29119
|
+
var databaseCommand = new Command("db").description(t2("\u6570\u636E\u5E93\u68C0\u67E5\u3001\u5907\u4EFD\u3001\u6E05\u7A7A\u4E0E\u6062\u590D", "check, back up, clear, and restore the database"));
|
|
29120
|
+
databaseCommand.command("check").description(t2("\u68C0\u67E5\u6570\u636E\u5E93\u5B8C\u6574\u6027\u3001\u5916\u952E\u548C\u4E1A\u52A1\u8868\u7EDF\u8BA1", "check integrity, foreign keys, and table counts")).option("--json", t2("\u5F3A\u5236\u8F93\u51FA JSON\uFF08\u975E\u4EA4\u4E92\u8C03\u7528\u9ED8\u8BA4\u5DF2\u8F93\u51FA JSON\uFF09", "force JSON output (already the default when non-interactive)")).action(async (options) => withDb(async () => {
|
|
28467
29121
|
const result = DatabaseMaintenanceService.check();
|
|
28468
|
-
console.log(renderDatabaseResult("check", result, { forceJson: options.json }));
|
|
29122
|
+
console.log(renderDatabaseResult("check", result, { forceJson: options.json, locale: cliLocale }));
|
|
28469
29123
|
if (!result.ok) process.exitCode = 1;
|
|
28470
29124
|
}, (error) => renderDatabaseError(error, { forceJson: options.json })));
|
|
28471
|
-
databaseCommand.command("backup").description("\u521B\u5EFA\u7ECF\u8FC7\u5B8C\u6574\u6027\u6821\u9A8C\u7684\u4E00\u81F4\u6027\u5907\u4EFD").option("-o, --output <path>", "\u5907\u4EFD\u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u5199\u5165\u6570\u636E\u5E93\u76EE\u5F55\uFF09").option("--json", "\u5F3A\u5236\u8F93\u51FA JSON\uFF08\u975E\u4EA4\u4E92\u8C03\u7528\u9ED8\u8BA4\u5DF2\u8F93\u51FA JSON\uFF09").action(async (options) => withDb(async () => {
|
|
29125
|
+
databaseCommand.command("backup").description(t2("\u521B\u5EFA\u7ECF\u8FC7\u5B8C\u6574\u6027\u6821\u9A8C\u7684\u4E00\u81F4\u6027\u5907\u4EFD", "create a consistent, integrity-checked backup")).option("-o, --output <path>", t2("\u5907\u4EFD\u6587\u4EF6\u8DEF\u5F84\uFF08\u9ED8\u8BA4\u5199\u5165\u6570\u636E\u5E93\u76EE\u5F55\uFF09", "backup path (defaults to the database directory)")).option("--json", t2("\u5F3A\u5236\u8F93\u51FA JSON\uFF08\u975E\u4EA4\u4E92\u8C03\u7528\u9ED8\u8BA4\u5DF2\u8F93\u51FA JSON\uFF09", "force JSON output (already the default when non-interactive)")).action(async (options) => withDb(async () => {
|
|
28472
29126
|
const result = DatabaseMaintenanceService.backup(options.output);
|
|
28473
|
-
console.log(renderDatabaseResult("backup", result, { forceJson: options.json }));
|
|
29127
|
+
console.log(renderDatabaseResult("backup", result, { forceJson: options.json, locale: cliLocale }));
|
|
28474
29128
|
}, (error) => renderDatabaseError(error, { forceJson: options.json })));
|
|
28475
|
-
databaseCommand.command("clear").description("\u5907\u4EFD\u540E\u4E8B\u52A1\u6027\u6E05\u7A7A\u4EFB\u52A1\u3001\u6267\u884C\u8BB0\u5F55\u548C\
|
|
29129
|
+
databaseCommand.command("clear").description(t2("\u5907\u4EFD\u540E\u4E8B\u52A1\u6027\u6E05\u7A7A\u4EFB\u52A1\u3001\u6267\u884C\u8BB0\u5F55\u548C\u5B9A\u65F6\u4EFB\u52A1\u6A21\u677F", "back up, then transactionally clear tasks, runs, and scheduled templates")).option("--confirm <word>", t2("\u5371\u9669\u64CD\u4F5C\u786E\u8BA4\uFF0C\u5FC5\u987B\u586B\u5199 CLEAR", "confirmation word; must be CLEAR")).option("--keep-stopped", t2("\u7EF4\u62A4\u7ED3\u675F\u540E\u4E0D\u91CD\u542F\u539F\u672C\u7531 PM2 \u7BA1\u7406\u7684 Gateway", "leave a previously managed Gateway stopped")).option("--json", t2("\u5F3A\u5236\u8F93\u51FA JSON\uFF08\u975E\u4EA4\u4E92\u8C03\u7528\u9ED8\u8BA4\u5DF2\u8F93\u51FA JSON\uFF09", "force JSON output (already the default when non-interactive)")).action(async (options) => withDb(async () => {
|
|
28476
29130
|
if (options.confirm !== "CLEAR") {
|
|
28477
29131
|
throw new Error("\u6E05\u7A7A\u6570\u636E\u5E93\u5FC5\u987B\u663E\u5F0F\u4F20\u5165 --confirm CLEAR");
|
|
28478
29132
|
}
|
|
@@ -28480,9 +29134,9 @@ databaseCommand.command("clear").description("\u5907\u4EFD\u540E\u4E8B\u52A1\u60
|
|
|
28480
29134
|
options.keepStopped ?? false,
|
|
28481
29135
|
() => DatabaseMaintenanceService.clear()
|
|
28482
29136
|
);
|
|
28483
|
-
console.log(renderDatabaseResult("clear", result, { forceJson: options.json }));
|
|
29137
|
+
console.log(renderDatabaseResult("clear", result, { forceJson: options.json, locale: cliLocale }));
|
|
28484
29138
|
}, (error) => renderDatabaseError(error, { forceJson: options.json })));
|
|
28485
|
-
databaseCommand.command("restore").description("\u81EA\u52A8\u5907\u4EFD\u5F53\u524D\u5E93\u540E\uFF0C\u4ECE\u6307\u5B9A\u5907\u4EFD\u6062\u590D\u6570\u636E\u5E93").requiredOption("--from <path>", "\u8981\u6062\u590D\u7684 SQLite \u5907\u4EFD\u6587\u4EF6").option("--confirm <word>", "\u5371\u9669\u64CD\u4F5C\u786E\u8BA4\uFF0C\u5FC5\u987B\u586B\u5199 RESTORE").option("--keep-stopped", "\u7EF4\u62A4\u7ED3\u675F\u540E\u4E0D\u91CD\u542F\u539F\u672C\u7531 PM2 \u7BA1\u7406\u7684 Gateway").option("--json", "\u5F3A\u5236\u8F93\u51FA JSON\uFF08\u975E\u4EA4\u4E92\u8C03\u7528\u9ED8\u8BA4\u5DF2\u8F93\u51FA JSON\uFF09").action(async (options) => withDb(async () => {
|
|
29139
|
+
databaseCommand.command("restore").description(t2("\u81EA\u52A8\u5907\u4EFD\u5F53\u524D\u5E93\u540E\uFF0C\u4ECE\u6307\u5B9A\u5907\u4EFD\u6062\u590D\u6570\u636E\u5E93", "back up the live database, then restore from a backup")).requiredOption("--from <path>", t2("\u8981\u6062\u590D\u7684 SQLite \u5907\u4EFD\u6587\u4EF6", "SQLite backup to restore")).option("--confirm <word>", t2("\u5371\u9669\u64CD\u4F5C\u786E\u8BA4\uFF0C\u5FC5\u987B\u586B\u5199 RESTORE", "confirmation word; must be RESTORE")).option("--keep-stopped", t2("\u7EF4\u62A4\u7ED3\u675F\u540E\u4E0D\u91CD\u542F\u539F\u672C\u7531 PM2 \u7BA1\u7406\u7684 Gateway", "leave a previously managed Gateway stopped")).option("--json", t2("\u5F3A\u5236\u8F93\u51FA JSON\uFF08\u975E\u4EA4\u4E92\u8C03\u7528\u9ED8\u8BA4\u5DF2\u8F93\u51FA JSON\uFF09", "force JSON output (already the default when non-interactive)")).action(async (options) => withDb(async () => {
|
|
28486
29140
|
if (options.confirm !== "RESTORE") {
|
|
28487
29141
|
throw new Error("\u6062\u590D\u6570\u636E\u5E93\u5FC5\u987B\u663E\u5F0F\u4F20\u5165 --confirm RESTORE");
|
|
28488
29142
|
}
|
|
@@ -28490,16 +29144,16 @@ databaseCommand.command("restore").description("\u81EA\u52A8\u5907\u4EFD\u5F53\u
|
|
|
28490
29144
|
options.keepStopped ?? false,
|
|
28491
29145
|
() => DatabaseMaintenanceService.restore(options.from)
|
|
28492
29146
|
);
|
|
28493
|
-
console.log(renderDatabaseResult("restore", result, { forceJson: options.json }));
|
|
29147
|
+
console.log(renderDatabaseResult("restore", result, { forceJson: options.json, locale: cliLocale }));
|
|
28494
29148
|
}, (error) => renderDatabaseError(error, { forceJson: options.json })));
|
|
28495
29149
|
program2.addCommand(databaseCommand);
|
|
28496
|
-
program2.command("init").description("
|
|
29150
|
+
program2.command("init").description(t2("\u521D\u59CB\u5316 SuperTask\uFF08\u521B\u5EFA\u914D\u7F6E\u5E76\u6267\u884C\u8FC1\u79FB\uFF09", "initialize SuperTask (create config and run migrations)")).action(async () => withDb(async () => {
|
|
28497
29151
|
const { existsSync: existsSync9, mkdirSync: mkdirSync6, writeFileSync: writeFileSync4 } = await import("fs");
|
|
28498
|
-
const { dirname:
|
|
29152
|
+
const { dirname: dirname10 } = await import("path");
|
|
28499
29153
|
const { getConfigPath: getConfigPath2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
28500
29154
|
const configPath = getConfigPath2();
|
|
28501
29155
|
if (!existsSync9(configPath)) {
|
|
28502
|
-
const dir =
|
|
29156
|
+
const dir = dirname10(configPath);
|
|
28503
29157
|
if (!existsSync9(dir)) mkdirSync6(dir, { recursive: true });
|
|
28504
29158
|
writeFileSync4(configPath, JSON.stringify({
|
|
28505
29159
|
configVersion: 2,
|
|
@@ -28514,16 +29168,16 @@ program2.command("init").description("Initialize SuperTask (create config + run
|
|
|
28514
29168
|
getDb2();
|
|
28515
29169
|
console.log(JSON.stringify({ migrated: true }));
|
|
28516
29170
|
}));
|
|
28517
|
-
program2.command("migrate").description("
|
|
29171
|
+
program2.command("migrate").description(t2("\u6267\u884C\u6570\u636E\u5E93\u8FC1\u79FB", "run database migrations")).action(async () => withDb(async () => {
|
|
28518
29172
|
const { getDb: getDb2 } = await Promise.resolve().then(() => (init_db2(), db_exports));
|
|
28519
29173
|
getDb2();
|
|
28520
29174
|
console.log(JSON.stringify({ migrated: true }));
|
|
28521
29175
|
}));
|
|
28522
|
-
program2.command("gateway").description("
|
|
29176
|
+
program2.command("gateway").description(t2("\u5728\u524D\u53F0\u542F\u52A8 Gateway", "start the Gateway in the foreground")).action(async () => {
|
|
28523
29177
|
const { main: main2 } = await Promise.resolve().then(() => (init_gateway(), gateway_exports));
|
|
28524
29178
|
await main2();
|
|
28525
29179
|
});
|
|
28526
|
-
program2.command("ui").description("
|
|
29180
|
+
program2.command("ui").description(t2("\u6253\u5F00 Gateway \u5185\u7F6E\u7684 Web \u7BA1\u7406\u754C\u9762", "open the Web Dashboard embedded in the Gateway")).action(async () => {
|
|
28527
29181
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
28528
29182
|
const cfg = loadConfig2();
|
|
28529
29183
|
const url = `http://localhost:${cfg.dashboard.port}`;
|
|
@@ -28535,19 +29189,19 @@ program2.command("ui").description("Open Web Dashboard (embedded in Gateway)").a
|
|
|
28535
29189
|
} catch {
|
|
28536
29190
|
}
|
|
28537
29191
|
});
|
|
28538
|
-
program2.command("config").description("
|
|
29192
|
+
program2.command("config").description(t2("\u663E\u793A\u5F53\u524D\u914D\u7F6E", "show the current configuration")).action(async () => {
|
|
28539
29193
|
const { loadConfig: loadConfig2 } = await Promise.resolve().then(() => (init_config(), config_exports));
|
|
28540
29194
|
const cfg = loadConfig2();
|
|
28541
29195
|
console.log(JSON.stringify(cfg, null, 2));
|
|
28542
29196
|
});
|
|
28543
|
-
program2.command("doctor").description("\u68C0\u67E5 OpenCode\u3001\u6570\u636E\u5E93\u3001Gateway\
|
|
29197
|
+
program2.command("doctor").description(t2("\u68C0\u67E5 OpenCode\u3001\u6570\u636E\u5E93\u3001Gateway\u3001Web \u754C\u9762\u548C\u65E5\u5FD7\u8F6E\u8F6C", "diagnose OpenCode, database, Gateway, Dashboard, and log rotation")).option("--json", t2("\u5F3A\u5236\u8F93\u51FA JSON", "force JSON output")).action(async (options) => withDb(async () => {
|
|
28544
29198
|
const config = loadConfig();
|
|
28545
29199
|
const database = DatabaseMaintenanceService.check();
|
|
28546
29200
|
const legacyQuarantinedRuns = await TaskRunService.listLegacyQuarantinedRuns(
|
|
28547
29201
|
config.watchdog.heartbeatTimeoutMs
|
|
28548
29202
|
);
|
|
28549
29203
|
const gateway = getGatewayDiagnostic();
|
|
28550
|
-
const
|
|
29204
|
+
const packageVersion2 = getPackageVersion();
|
|
28551
29205
|
const opencodeBin2 = process.env.SUPERTASK_OPENCODE_BIN ?? "opencode";
|
|
28552
29206
|
const opencodeResult = spawnSync4(opencodeBin2, ["--version"], {
|
|
28553
29207
|
encoding: "utf8",
|
|
@@ -28557,7 +29211,7 @@ program2.command("doctor").description("\u68C0\u67E5 OpenCode\u3001\u6570\u636E\
|
|
|
28557
29211
|
ok: opencodeResult.status === 0,
|
|
28558
29212
|
executable: opencodeBin2,
|
|
28559
29213
|
version: opencodeResult.status === 0 ? opencodeResult.stdout.trim() : null,
|
|
28560
|
-
error: opencodeResult.status === 0 ? null : opencodeResult.error?.message || opencodeResult.stderr.trim() || `\u9000\u51FA\u7801 ${opencodeResult.status}`
|
|
29214
|
+
error: opencodeResult.status === 0 ? null : opencodeResult.error?.message || opencodeResult.stderr.trim() || t2(`\u9000\u51FA\u7801 ${opencodeResult.status}`, `exit code ${opencodeResult.status}`)
|
|
28561
29215
|
};
|
|
28562
29216
|
const plugin = getOpenCodePluginDiagnostic();
|
|
28563
29217
|
let dashboard = {
|
|
@@ -28582,44 +29236,68 @@ program2.command("doctor").description("\u68C0\u67E5 OpenCode\u3001\u6570\u636E\
|
|
|
28582
29236
|
const gatewayEntryPinned = gateway.gatewayEntry === null || !/[\\/]opencode-supertask@(latest|next)[\\/]/.test(gateway.gatewayEntry);
|
|
28583
29237
|
const gatewayVersionMatchesPackage = gateway.gatewayPackageVersion !== null && gateway.runningVersion === gateway.gatewayPackageVersion;
|
|
28584
29238
|
const configuredVersionsMatch = plugin.ok && plugin.version === gateway.gatewayPackageVersion;
|
|
29239
|
+
const cliVersionMatchesPlugin = plugin.ok && plugin.version === packageVersion2;
|
|
28585
29240
|
if (!plugin.ok && plugin.error) {
|
|
28586
29241
|
warnings.push(plugin.error);
|
|
28587
29242
|
}
|
|
28588
|
-
if (plugin.version !== null && plugin.version !==
|
|
28589
|
-
warnings.push(
|
|
29243
|
+
if (plugin.version !== null && plugin.version !== packageVersion2) {
|
|
29244
|
+
warnings.push(t2(
|
|
29245
|
+
`\u5F53\u524D CLI v${packageVersion2} \u4E0E OpenCode \u63D2\u4EF6 v${plugin.version} \u4E0D\u4E00\u81F4\uFF1B\u6267\u884C supertask upgrade \u8BA9 CLI\u3001\u63D2\u4EF6\u548C Gateway \u6536\u655B\u5230\u540C\u4E00\u7CBE\u786E\u7248\u672C`,
|
|
29246
|
+
`CLI v${packageVersion2} does not match OpenCode plugin v${plugin.version}; run supertask upgrade to converge the CLI, plugin, and Gateway on one exact version`
|
|
29247
|
+
));
|
|
28590
29248
|
}
|
|
28591
29249
|
if (!gatewayEntryPinned) {
|
|
28592
|
-
warnings.push(
|
|
29250
|
+
warnings.push(t2(
|
|
29251
|
+
`PM2 Gateway \u4ECD\u4ECE\u6D6E\u52A8\u7F13\u5B58\u8DEF\u5F84\u542F\u52A8\uFF1A${gateway.gatewayEntry}`,
|
|
29252
|
+
`The PM2 Gateway still starts from a floating cache path: ${gateway.gatewayEntry}`
|
|
29253
|
+
));
|
|
28593
29254
|
}
|
|
28594
29255
|
if (gateway.processFound && gateway.gatewayPackageVersion === null) {
|
|
28595
|
-
warnings.push(
|
|
29256
|
+
warnings.push(t2(
|
|
29257
|
+
`\u65E0\u6CD5\u4ECE PM2 Gateway \u5165\u53E3\u786E\u8BA4 opencode-supertask \u5305\u7248\u672C\uFF1A${gateway.gatewayEntry ?? "unknown"}`,
|
|
29258
|
+
`Could not determine the opencode-supertask package version from the PM2 Gateway entry: ${gateway.gatewayEntry ?? "unknown"}`
|
|
29259
|
+
));
|
|
28596
29260
|
} else if (gateway.processFound && !gatewayVersionMatchesPackage) {
|
|
28597
|
-
warnings.push(
|
|
29261
|
+
warnings.push(t2(
|
|
29262
|
+
`Gateway ready \u9501\u7248\u672C ${gateway.runningVersion ?? "unknown"} \u4E0E\u5165\u53E3\u5305\u7248\u672C ${gateway.gatewayPackageVersion ?? "unknown"} \u4E0D\u4E00\u81F4`,
|
|
29263
|
+
`Gateway ready-lock version ${gateway.runningVersion ?? "unknown"} does not match entry package version ${gateway.gatewayPackageVersion ?? "unknown"}`
|
|
29264
|
+
));
|
|
28598
29265
|
}
|
|
28599
29266
|
if (plugin.version !== null && gateway.gatewayPackageVersion !== null && plugin.version !== gateway.gatewayPackageVersion) {
|
|
28600
|
-
warnings.push(
|
|
29267
|
+
warnings.push(t2(
|
|
29268
|
+
`OpenCode \u63D2\u4EF6 v${plugin.version} \u4E0E PM2 Gateway v${gateway.gatewayPackageVersion} \u4E0D\u4E00\u81F4\uFF1B\u6267\u884C supertask upgrade`,
|
|
29269
|
+
`OpenCode plugin v${plugin.version} does not match PM2 Gateway v${gateway.gatewayPackageVersion}; run supertask upgrade`
|
|
29270
|
+
));
|
|
28601
29271
|
}
|
|
28602
29272
|
if (gateway.pm2Installed && !gateway.logRotationInstalled) {
|
|
28603
|
-
warnings.push(
|
|
29273
|
+
warnings.push(t2(
|
|
29274
|
+
"\u672A\u68C0\u6D4B\u5230 pm2-logrotate\uFF1B\u957F\u671F\u8FD0\u884C\u524D\u5EFA\u8BAE\u5B89\u88C5\u5E76\u9650\u5236\u65E5\u5FD7\u4FDD\u7559\u91CF",
|
|
29275
|
+
"pm2-logrotate was not detected; install it and limit log retention before long-running use"
|
|
29276
|
+
));
|
|
28604
29277
|
}
|
|
28605
29278
|
if (gateway.startupConfigured === false) {
|
|
28606
|
-
warnings.push(process.platform === "linux" ? "\u672A\u68C0\u6D4B\u5230\u5DF2\u542F\u7528\u4E14\u5305\u542B\u53EF\u6062\u590D PM2 dump \u7684 systemd \u81EA\u542F\u670D\u52A1" : "\u672A\u68C0\u6D4B\u5230\u6B63\u5728\u8FD0\u884C\u4E14\u5305\u542B\u53EF\u6062\u590D PM2 dump \u7684 macOS LaunchAgent");
|
|
29279
|
+
warnings.push(process.platform === "linux" ? t2("\u672A\u68C0\u6D4B\u5230\u5DF2\u542F\u7528\u4E14\u5305\u542B\u53EF\u6062\u590D PM2 dump \u7684 systemd \u81EA\u542F\u670D\u52A1", "No enabled systemd startup service with a recoverable PM2 dump was detected") : t2("\u672A\u68C0\u6D4B\u5230\u6B63\u5728\u8FD0\u884C\u4E14\u5305\u542B\u53EF\u6062\u590D PM2 dump \u7684 macOS LaunchAgent", "No running macOS LaunchAgent with a recoverable PM2 dump was detected"));
|
|
28607
29280
|
}
|
|
28608
29281
|
if (gateway.processFound && !gateway.scopeMatches) {
|
|
28609
|
-
warnings.push(
|
|
29282
|
+
warnings.push(t2(
|
|
29283
|
+
"\u5F53\u524D CLI/OpenCode \u4E0E PM2 Gateway \u7684\u6570\u636E\u5E93\u3001\u914D\u7F6E\u6216 OpenCode \u53EF\u6267\u884C\u6587\u4EF6\u4F5C\u7528\u57DF\u4E0D\u4E00\u81F4",
|
|
29284
|
+
"The current CLI/OpenCode database, config, or OpenCode executable scope does not match the PM2 Gateway"
|
|
29285
|
+
));
|
|
28610
29286
|
}
|
|
28611
29287
|
for (const run of legacyQuarantinedRuns) {
|
|
28612
|
-
const cwdHint = run.taskCwd == null ? "\uFF08\u65E7\u4EFB\u52A1\u6CA1\u6709 cwd\uFF0C\u8BF7\u5148\u5728 Dashboard \u53D6\u6D88\uFF09" : `\uFF08\u5728 ${run.taskCwd} \u6267\u884C\uFF09
|
|
28613
|
-
const cancel = run.taskStatus === "cancelled" ? "" : `\u5148${cwdHint} supertask cancel --id ${run.taskId}\uFF1B
|
|
28614
|
-
const owner = run.ownerAlive ? `owner PID ${run.workerPid} \u4ECD\u5B58\u6D3B\uFF0C\u5148\u786E\u8BA4\u5E76\u505C\u6B62\u5BF9\u5E94\u8FDB\u7A0B\uFF1B` : "";
|
|
28615
|
-
warnings.push(
|
|
28616
|
-
`\u65E7\u7248\u9694\u79BB run #${run.runId}\uFF1A${owner}${cancel}\u786E\u8BA4\u6CA1\u6709\u9057\u7559 OpenCode \u8FDB\u7A0B\u540E\u6267\u884C supertask run abandon --id ${run.runId} --confirm ABANDON
|
|
28617
|
-
|
|
28618
|
-
|
|
28619
|
-
|
|
29288
|
+
const cwdHint = run.taskCwd == null ? t2("\uFF08\u65E7\u4EFB\u52A1\u6CA1\u6709 cwd\uFF0C\u8BF7\u5148\u5728 Dashboard \u53D6\u6D88\uFF09", " (the legacy task has no cwd; cancel it in the Dashboard first)") : t2(`\uFF08\u5728 ${run.taskCwd} \u6267\u884C\uFF09`, ` (run in ${run.taskCwd})`);
|
|
29289
|
+
const cancel = run.taskStatus === "cancelled" ? "" : t2(`\u5148${cwdHint} supertask cancel --id ${run.taskId}\uFF1B`, `first${cwdHint}: supertask cancel --id ${run.taskId}; `);
|
|
29290
|
+
const owner = run.ownerAlive ? t2(`owner PID ${run.workerPid} \u4ECD\u5B58\u6D3B\uFF0C\u5148\u786E\u8BA4\u5E76\u505C\u6B62\u5BF9\u5E94\u8FDB\u7A0B\uFF1B`, `owner PID ${run.workerPid} is still alive; confirm and stop it first; `) : "";
|
|
29291
|
+
warnings.push(t2(
|
|
29292
|
+
`\u65E7\u7248\u9694\u79BB run #${run.runId}\uFF1A${owner}${cancel}\u786E\u8BA4\u6CA1\u6709\u9057\u7559 OpenCode \u8FDB\u7A0B\u540E\u6267\u884C supertask run abandon --id ${run.runId} --confirm ABANDON`,
|
|
29293
|
+
`Legacy quarantined run #${run.runId}: ${owner}${cancel}after confirming no OpenCode process remains, run supertask run abandon --id ${run.runId} --confirm ABANDON`
|
|
29294
|
+
));
|
|
29295
|
+
}
|
|
29296
|
+
const ok = opencode.ok && plugin.ok && database.ok && legacyQuarantinedRuns.length === 0 && gateway.pm2Installed && gateway.status === "online" && gateway.ready && gatewayEntryPinned && gatewayVersionMatchesPackage && configuredVersionsMatch && cliVersionMatchesPlugin && gateway.scopeMatches && gateway.logRotationInstalled && gateway.startupConfigured !== false && dashboard.ok;
|
|
28620
29297
|
const report = {
|
|
28621
29298
|
ok,
|
|
28622
|
-
packageVersion,
|
|
29299
|
+
packageVersion: packageVersion2,
|
|
29300
|
+
cliVersionMatchesPlugin,
|
|
28623
29301
|
configPath: getConfigPath(),
|
|
28624
29302
|
opencode,
|
|
28625
29303
|
plugin,
|
|
@@ -28634,17 +29312,17 @@ program2.command("doctor").description("\u68C0\u67E5 OpenCode\u3001\u6570\u636E\
|
|
|
28634
29312
|
console.log(JSON.stringify(report, null, 2));
|
|
28635
29313
|
} else {
|
|
28636
29314
|
const mark = (value) => value ? "\u2713" : "\u2717";
|
|
28637
|
-
console.log(`SuperTask doctor: ${ok ? "\u6B63\u5E38" : "\u5F02\u5E38"}`);
|
|
28638
|
-
console.log(`${mark(opencode.ok)} OpenCode ${opencode.version ?? opencode.error ?? "\u4E0D\u53EF\u7528"}`);
|
|
28639
|
-
console.log(`${mark(plugin.ok)} OpenCode \u63D2\u4EF6 ${plugin.spec || plugin.error || "\u672A\u914D\u7F6E"}${plugin.cachedVersion ? `\uFF08\u7F13\u5B58 v${plugin.cachedVersion}\uFF09` : ""}`);
|
|
28640
|
-
console.log(`${mark(database.ok)} \u6570\u636E\u5E93 ${database.path}
|
|
29315
|
+
console.log(`SuperTask doctor: ${ok ? t2("\u6B63\u5E38", "healthy") : t2("\u5F02\u5E38", "unhealthy")}`);
|
|
29316
|
+
console.log(`${mark(opencode.ok)} OpenCode ${opencode.version ?? opencode.error ?? t2("\u4E0D\u53EF\u7528", "unavailable")}`);
|
|
29317
|
+
console.log(`${mark(plugin.ok)} ${t2("OpenCode \u63D2\u4EF6", "OpenCode plugin")} ${plugin.spec || plugin.error || t2("\u672A\u914D\u7F6E", "not configured")}${plugin.cachedVersion ? t2(`\uFF08\u7F13\u5B58 v${plugin.cachedVersion}\uFF09`, ` (cached v${plugin.cachedVersion})`) : ""}`);
|
|
29318
|
+
console.log(`${mark(database.ok)} ${t2("\u6570\u636E\u5E93", "Database")} ${database.path}${t2(`\uFF08\u4EFB\u52A1 ${database.counts.tasks}\uFF0C\u8FD0\u884C\u4E2D ${database.runningTasks}\uFF09`, ` (tasks ${database.counts.tasks}, running ${database.runningTasks})`)}`);
|
|
28641
29319
|
console.log(`${mark(gateway.status === "online" && gateway.ready && gatewayEntryPinned && gatewayVersionMatchesPackage)} Gateway ${gateway.status ?? "missing"}${gateway.pid ? `\uFF0CPID ${gateway.pid}` : ""}${gateway.runningVersion ? `\uFF0Cv${gateway.runningVersion}` : ""}${gateway.gatewayEntry ? `\uFF0C${gateway.gatewayEntry}` : ""}`);
|
|
28642
|
-
console.log(`${mark(dashboard.ok)} Dashboard ${dashboard.enabled ? dashboard.url : "\u5DF2\u7981\u7528"}`);
|
|
29320
|
+
console.log(`${mark(dashboard.ok)} Dashboard ${dashboard.enabled ? dashboard.url : t2("\u5DF2\u7981\u7528", "disabled")}`);
|
|
28643
29321
|
for (const warning of warnings) console.log(`! ${warning}`);
|
|
28644
29322
|
}
|
|
28645
29323
|
if (!ok) process.exitCode = 1;
|
|
28646
29324
|
}));
|
|
28647
|
-
program2.command("install").description("
|
|
29325
|
+
program2.command("install").description(t2("\u7528 PM2 \u5B89\u88C5 Gateway\uFF08\u5F00\u673A\u542F\u52A8\u3001\u5D29\u6E83\u6062\u590D\u3001\u65E5\u5FD7\u8F6E\u8F6C\uFF09", "install the Gateway with PM2 (startup, crash recovery, log rotation)")).action(async () => {
|
|
28648
29326
|
try {
|
|
28649
29327
|
const { install: pm2Install } = await Promise.resolve().then(() => (init_pm2(), pm2_exports));
|
|
28650
29328
|
pm2Install();
|
|
@@ -28653,7 +29331,7 @@ program2.command("install").description("Install Gateway as pm2 service (auto-st
|
|
|
28653
29331
|
process.exit(1);
|
|
28654
29332
|
}
|
|
28655
29333
|
});
|
|
28656
|
-
program2.command("uninstall").description("
|
|
29334
|
+
program2.command("uninstall").description(t2("\u505C\u6B62\u5E76\u79FB\u9664 PM2 Gateway", "stop and remove the PM2 Gateway")).action(async () => {
|
|
28657
29335
|
try {
|
|
28658
29336
|
const { uninstall: pm2Uninstall } = await Promise.resolve().then(() => (init_pm2(), pm2_exports));
|
|
28659
29337
|
pm2Uninstall();
|
|
@@ -28662,15 +29340,15 @@ program2.command("uninstall").description("Stop and remove Gateway pm2 service")
|
|
|
28662
29340
|
process.exit(1);
|
|
28663
29341
|
}
|
|
28664
29342
|
});
|
|
28665
|
-
program2.command("upgrade").description("
|
|
28666
|
-
console.log("Updating opencode-supertask...");
|
|
29343
|
+
program2.command("upgrade").description(t2("\u66F4\u65B0 OpenCode \u63D2\u4EF6\u7F13\u5B58\u5E76\u91CD\u542F Gateway", "update the OpenCode plugin cache and restart the Gateway")).action(async () => {
|
|
29344
|
+
console.log(t2("\u6B63\u5728\u66F4\u65B0 opencode-supertask...", "Updating opencode-supertask..."));
|
|
28667
29345
|
let installed;
|
|
28668
29346
|
let previousVersion;
|
|
28669
29347
|
try {
|
|
28670
29348
|
const { resolveInstalledPlugin: resolveInstalledPlugin2 } = await Promise.resolve().then(() => (init_update2(), update_exports));
|
|
28671
29349
|
previousVersion = resolveInstalledPlugin2().version;
|
|
28672
29350
|
} catch (error) {
|
|
28673
|
-
console.error(
|
|
29351
|
+
console.error(t2("\u65E0\u6CD5\u786E\u8BA4\u5F53\u524D OpenCode \u63D2\u4EF6\u7248\u672C\uFF0C\u5DF2\u53D6\u6D88\u5347\u7EA7\uFF1A", "Could not determine the current OpenCode plugin version; upgrade cancelled: ") + (error instanceof Error ? error.message : String(error)));
|
|
28674
29352
|
process.exit(1);
|
|
28675
29353
|
}
|
|
28676
29354
|
try {
|
|
@@ -28685,17 +29363,40 @@ program2.command("upgrade").description("Update OpenCode plugin cache and restar
|
|
|
28685
29363
|
detail += `; OpenCode \u63D2\u4EF6\u56DE\u6EDA\u5931\u8D25: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`;
|
|
28686
29364
|
}
|
|
28687
29365
|
console.error(detail);
|
|
28688
|
-
console.error(
|
|
29366
|
+
console.error(t2(
|
|
29367
|
+
"\u53EF\u4EBA\u5DE5\u67E5\u8BE2 npm dist-tags.latest\uFF0C\u518D\u7528 opencode plugin \u5B89\u88C5\u8BE5\u7CBE\u786E\u7248\u672C\u3002",
|
|
29368
|
+
"Try manually: query npm dist-tags.latest, then install that exact version with opencode plugin."
|
|
29369
|
+
));
|
|
28689
29370
|
process.exit(1);
|
|
28690
29371
|
}
|
|
28691
29372
|
try {
|
|
28692
29373
|
const { upgrade: pm2Upgrade } = await Promise.resolve().then(() => (init_pm2(), pm2_exports));
|
|
28693
29374
|
const result = pm2Upgrade(installed);
|
|
28694
|
-
console.log(
|
|
28695
|
-
|
|
28696
|
-
|
|
28697
|
-
|
|
28698
|
-
|
|
29375
|
+
console.log(t2(
|
|
29376
|
+
`
|
|
29377
|
+
SuperTask \u5DF2\u5347\u7EA7\uFF1A${result.before ?? "unknown"} \u2192 ${result.after}`,
|
|
29378
|
+
`
|
|
29379
|
+
SuperTask upgraded: ${result.before ?? "unknown"} \u2192 ${result.after}`
|
|
29380
|
+
));
|
|
29381
|
+
console.log(t2("Gateway \u5DF2\u91CD\u542F\u3002\u8BF7\u91CD\u542F OpenCode \u52A0\u8F7D\u65B0\u63D2\u4EF6\u3002", "Gateway restarted. Restart OpenCode to load the new plugin."));
|
|
29382
|
+
try {
|
|
29383
|
+
const { updateGlobalCli: updateGlobalCli2 } = await Promise.resolve().then(() => (init_update2(), update_exports));
|
|
29384
|
+
const cli = updateGlobalCli2(installed.version);
|
|
29385
|
+
if (cli.action === "updated") {
|
|
29386
|
+
console.log(t2(
|
|
29387
|
+
`\u5DF2\u4F7F\u7528 ${cli.packageManager} \u5C06\u5168\u5C40 CLI \u66F4\u65B0\u5230 v${installed.version}\u3002`,
|
|
29388
|
+
`Global CLI updated to v${installed.version} with ${cli.packageManager}.`
|
|
29389
|
+
));
|
|
29390
|
+
} else if (cli.action === "not-installed") {
|
|
29391
|
+
console.log(t2("\u672A\u627E\u5230\u5168\u5C40 CLI\uFF1B\u63D2\u4EF6\u548C Gateway \u5347\u7EA7\u5DF2\u5B8C\u6210\u3002", "No global CLI installation was found; plugin and Gateway upgrade is complete."));
|
|
29392
|
+
}
|
|
29393
|
+
} catch (cliError) {
|
|
29394
|
+
console.error(t2("\u63D2\u4EF6\u548C Gateway \u5DF2\u5347\u7EA7\uFF0C\u4F46\u5168\u5C40 CLI \u672A\u66F4\u65B0\uFF1A", "Plugin and Gateway were upgraded, but the global CLI was not: ") + (cliError instanceof Error ? cliError.message : String(cliError)));
|
|
29395
|
+
console.error(t2(
|
|
29396
|
+
`\u6267\u884C npm install -g opencode-supertask@${installed.version} \u6216 bun add -g opencode-supertask@${installed.version}\uFF0C\u518D\u8FD0\u884C supertask doctor\u3002`,
|
|
29397
|
+
`Run npm install -g opencode-supertask@${installed.version} or bun add -g opencode-supertask@${installed.version}, then run supertask doctor.`
|
|
29398
|
+
));
|
|
29399
|
+
process.exit(1);
|
|
28699
29400
|
}
|
|
28700
29401
|
} catch (err) {
|
|
28701
29402
|
let detail = err instanceof Error ? err.message : String(err);
|
|
@@ -28707,7 +29408,7 @@ SuperTask upgraded: ${result.before ?? "unknown"} \u2192 ${result.after}`);
|
|
|
28707
29408
|
} catch (rollbackError) {
|
|
28708
29409
|
detail += `; Gateway \u5DF2\u56DE\u6EDA\uFF0C\u4F46 OpenCode \u63D2\u4EF6\u56DE\u6EDA\u5931\u8D25: ${rollbackError instanceof Error ? rollbackError.message : String(rollbackError)}`;
|
|
28709
29410
|
}
|
|
28710
|
-
console.error("Gateway restart failed:", detail);
|
|
29411
|
+
console.error(t2("Gateway \u91CD\u542F\u5931\u8D25\uFF1A", "Gateway restart failed:"), detail);
|
|
28711
29412
|
process.exit(1);
|
|
28712
29413
|
}
|
|
28713
29414
|
});
|