opencode-supertask 0.1.38 → 0.1.40

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.
@@ -26774,6 +26774,7 @@ var tasks = sqliteTable("tasks", {
26774
26774
  name: text("name").notNull(),
26775
26775
  agent: text("agent").notNull(),
26776
26776
  model: text("model").default("default"),
26777
+ variant: text("variant"),
26777
26778
  prompt: text("prompt").notNull(),
26778
26779
  cwd: text("cwd"),
26779
26780
  // 分类与优先级
@@ -26818,6 +26819,7 @@ var taskRuns = sqliteTable("task_runs", {
26818
26819
  taskId: integer2("task_id").notNull().references(() => tasks.id, { onDelete: "cascade" }),
26819
26820
  sessionId: text("session_id"),
26820
26821
  model: text("model"),
26822
+ variant: text("variant"),
26821
26823
  status: text("status").default("running"),
26822
26824
  startedAt: integer2("started_at", { mode: "timestamp" }).$defaultFn(() => /* @__PURE__ */ new Date()),
26823
26825
  finishedAt: integer2("finished_at", { mode: "timestamp" }),
@@ -26838,6 +26840,7 @@ var taskTemplates = sqliteTable("task_templates", {
26838
26840
  name: text("name").notNull(),
26839
26841
  agent: text("agent").notNull(),
26840
26842
  model: text("model").default("default"),
26843
+ variant: text("variant"),
26841
26844
  prompt: text("prompt").notNull(),
26842
26845
  cwd: text("cwd"),
26843
26846
  category: text("category").default("general"),
@@ -27012,6 +27015,22 @@ function normalizeTaskBatchId(batchId) {
27012
27015
  return batchId.trim() || null;
27013
27016
  }
27014
27017
 
27018
+ // src/core/model-variant.ts
27019
+ var MAX_MODEL_VARIANT_LENGTH = 128;
27020
+ var CONTROL_CHARACTER_PATTERN = /[\u0000-\u001F\u007F]/;
27021
+ function normalizeModelVariant(value) {
27022
+ if (value === void 0 || value === null) return value;
27023
+ const normalized = value.trim();
27024
+ if (!normalized) return null;
27025
+ if (normalized.length > MAX_MODEL_VARIANT_LENGTH) {
27026
+ throw new Error(`variant \u957F\u5EA6\u4E0D\u80FD\u8D85\u8FC7 ${MAX_MODEL_VARIANT_LENGTH} \u4E2A\u5B57\u7B26`);
27027
+ }
27028
+ if (CONTROL_CHARACTER_PATTERN.test(normalized)) {
27029
+ throw new Error("variant \u4E0D\u80FD\u5305\u542B\u63A7\u5236\u5B57\u7B26");
27030
+ }
27031
+ return normalized;
27032
+ }
27033
+
27015
27034
  // src/core/services/task.service.ts
27016
27035
  var { tasks: tasks2, taskRuns: taskRuns2 } = schema_exports;
27017
27036
  var cleanupInvocation = 0;
@@ -27077,7 +27096,8 @@ var TaskService = class {
27077
27096
  static async add(data) {
27078
27097
  const normalizedData = {
27079
27098
  ...data,
27080
- batchId: normalizeTaskBatchId(data.batchId)
27099
+ batchId: normalizeTaskBatchId(data.batchId),
27100
+ variant: normalizeModelVariant(data.variant)
27081
27101
  };
27082
27102
  this.validateNewTask(normalizedData);
27083
27103
  return db.transaction((tx) => {
@@ -27105,7 +27125,11 @@ var TaskService = class {
27105
27125
  }
27106
27126
  static async update(id, data, scope = {}) {
27107
27127
  if (Object.keys(data).length === 0) throw new Error("\u81F3\u5C11\u63D0\u4F9B\u4E00\u4E2A\u8981\u4FEE\u6539\u7684\u5B57\u6BB5");
27108
- const normalizedData = data.batchId === void 0 ? data : { ...data, batchId: normalizeTaskBatchId(data.batchId) ?? null };
27128
+ const normalizedData = {
27129
+ ...data,
27130
+ ...data.batchId === void 0 ? {} : { batchId: normalizeTaskBatchId(data.batchId) ?? null },
27131
+ ...data.variant === void 0 ? {} : { variant: normalizeModelVariant(data.variant) ?? null }
27132
+ };
27109
27133
  return db.transaction((tx) => {
27110
27134
  const task = tx.select().from(tasks2).where(and(
27111
27135
  eq(tasks2.id, id),
@@ -27117,6 +27141,7 @@ var TaskService = class {
27117
27141
  name: normalizedData.name ?? task.name,
27118
27142
  agent: normalizedData.agent ?? task.agent,
27119
27143
  model: normalizedData.model ?? task.model,
27144
+ variant: normalizedData.variant === void 0 ? task.variant : normalizedData.variant,
27120
27145
  prompt: normalizedData.prompt ?? task.prompt,
27121
27146
  cwd: task.cwd,
27122
27147
  category: normalizedData.category ?? task.category,
@@ -27891,7 +27916,8 @@ var TaskTemplateService = class {
27891
27916
  static async create(data) {
27892
27917
  const normalizedData = {
27893
27918
  ...data,
27894
- batchId: normalizeTaskBatchId(data.batchId)
27919
+ batchId: normalizeTaskBatchId(data.batchId),
27920
+ variant: normalizeModelVariant(data.variant)
27895
27921
  };
27896
27922
  this.validate(normalizedData);
27897
27923
  const now = Date.now();
@@ -27957,7 +27983,8 @@ var TaskTemplateService = class {
27957
27983
  static async update(id, data) {
27958
27984
  const normalizedData = {
27959
27985
  ...data,
27960
- batchId: normalizeTaskBatchId(data.batchId) ?? null
27986
+ batchId: normalizeTaskBatchId(data.batchId) ?? null,
27987
+ ...data.variant === void 0 ? {} : { variant: normalizeModelVariant(data.variant) ?? null }
27961
27988
  };
27962
27989
  this.validate(normalizedData);
27963
27990
  const now = Date.now();
@@ -28368,6 +28395,26 @@ function getRunningVersion(env = process.env, cwd = process.cwd()) {
28368
28395
  return null;
28369
28396
  }
28370
28397
  }
28398
+ function packageVersionFromGatewayEntry(gatewayEntry) {
28399
+ if (gatewayEntry === null) return null;
28400
+ let directory = dirname4(gatewayEntry);
28401
+ for (let depth = 0; depth < 6; depth += 1) {
28402
+ const packagePath = join4(directory, "package.json");
28403
+ if (existsSync4(packagePath)) {
28404
+ try {
28405
+ const pkg = JSON.parse(readFileSync3(packagePath, "utf8"));
28406
+ if (pkg.name === "opencode-supertask" && typeof pkg.version === "string") {
28407
+ return pkg.version;
28408
+ }
28409
+ } catch {
28410
+ }
28411
+ }
28412
+ const parent = dirname4(directory);
28413
+ if (parent === directory) break;
28414
+ directory = parent;
28415
+ }
28416
+ return null;
28417
+ }
28371
28418
  function resolveRuntimeExecutable(command, env, cwd) {
28372
28419
  if (isAbsolute2(command) || command.includes("/")) return runtimePath(command, cwd);
28373
28420
  for (const entry of (env.PATH ?? "").split(delimiter)) {
@@ -28428,6 +28475,55 @@ function assertOpenCodeRuntime(runtime) {
28428
28475
  );
28429
28476
  }
28430
28477
  }
28478
+ function getGatewayDiagnostic(options = {}) {
28479
+ const producerScope = currentScope();
28480
+ if (!isPm2Installed()) {
28481
+ return {
28482
+ pm2Installed: false,
28483
+ processFound: false,
28484
+ status: null,
28485
+ pid: null,
28486
+ ready: false,
28487
+ runningVersion: getRunningVersion(),
28488
+ gatewayEntry: null,
28489
+ gatewayPackageVersion: null,
28490
+ logRotationInstalled: false,
28491
+ startupConfigured: process.platform === "darwin" || process.platform === "linux" ? false : null,
28492
+ currentScope: producerScope,
28493
+ gatewayScope: null,
28494
+ scopeMatches: false,
28495
+ gatewayOpenCode: null
28496
+ };
28497
+ }
28498
+ const processes = pm2JsonList();
28499
+ const gateway = processes.find((item) => item.name === PROCESS_NAME);
28500
+ const runtime = gatewayRuntimeFromProcess(gateway);
28501
+ const gatewayEnv = runtime?.env ?? process.env;
28502
+ const managedScope = runtime ? runtimeScope(runtime) : null;
28503
+ const pid = typeof gateway?.pid === "number" ? gateway.pid : null;
28504
+ const readyPath = managedScope?.databasePath ?? databasePath();
28505
+ const lockedVersion = pid == null ? void 0 : gatewayVersionFromLock(pid, readyPath);
28506
+ const gatewayEntry = runtime?.gatewayEntry ?? null;
28507
+ return {
28508
+ pm2Installed: true,
28509
+ processFound: gateway != null,
28510
+ status: gateway?.pm2_env?.status ?? null,
28511
+ pid,
28512
+ ready: pid != null && isGatewayReady(pid, readyPath),
28513
+ runningVersion: lockedVersion === void 0 ? getRunningVersion(gatewayEnv, runtime?.cwd) : lockedVersion,
28514
+ gatewayEntry,
28515
+ gatewayPackageVersion: packageVersionFromGatewayEntry(gatewayEntry),
28516
+ logRotationInstalled: processes.some((item) => item.name === "pm2-logrotate" && item.pm2_env?.status === "online"),
28517
+ startupConfigured: process.platform === "darwin" ? isMacLaunchAgentConfigured(
28518
+ gatewayEnv.PM2_HOME ?? join4(runtimeHome(gatewayEnv), ".pm2"),
28519
+ runtime ?? void 0
28520
+ ) : process.platform === "linux" ? isLinuxStartupConfigured(gatewayEnv, runtime?.cwd, runtime ?? void 0) : null,
28521
+ currentScope: producerScope,
28522
+ gatewayScope: managedScope,
28523
+ scopeMatches: managedScope != null && scopesMatch(producerScope, managedScope),
28524
+ gatewayOpenCode: runtime === null || !options.probeOpenCode ? null : diagnoseOpenCodeRuntime(runtime)
28525
+ };
28526
+ }
28431
28527
  function writeRunningVersion(version3, env = process.env, cwd = process.cwd()) {
28432
28528
  const path = versionFile(env, cwd);
28433
28529
  mkdirSync3(dirname4(path), { recursive: true });
@@ -28451,6 +28547,9 @@ function resolvePm2Bin() {
28451
28547
  function launchAgentPath() {
28452
28548
  return process.env.SUPERTASK_LAUNCH_AGENT_PATH ?? join4(runtimeHome(process.env), "Library/LaunchAgents", `${MAC_LAUNCH_AGENT_LABEL}.plist`);
28453
28549
  }
28550
+ function launchctlBin() {
28551
+ return process.env.SUPERTASK_LAUNCHCTL_BIN ?? "launchctl";
28552
+ }
28454
28553
  function xmlUnescape(value) {
28455
28554
  return value.replaceAll("&apos;", "'").replaceAll("&quot;", '"').replaceAll("&gt;", ">").replaceAll("&lt;", "<").replaceAll("&amp;", "&");
28456
28555
  }
@@ -28459,6 +28558,100 @@ function plistValue(contents, key) {
28459
28558
  const match = contents.match(new RegExp(`<key>\\s*${escapedKey}\\s*</key>\\s*<string>([^<]*)</string>`));
28460
28559
  return match?.[1] ? xmlUnescape(match[1]) : null;
28461
28560
  }
28561
+ function isMacLaunchAgentConfigured(expectedPm2Home, expectedRuntime) {
28562
+ if (typeof process.getuid !== "function") return false;
28563
+ const plistPath = launchAgentPath();
28564
+ if (!existsSync4(plistPath)) return false;
28565
+ try {
28566
+ const contents = readFileSync3(plistPath, "utf8");
28567
+ const argumentsBlock = contents.match(
28568
+ /<key>\s*ProgramArguments\s*<\/key>\s*<array>([\s\S]*?)<\/array>/
28569
+ )?.[1];
28570
+ const programArguments = argumentsBlock ? [...argumentsBlock.matchAll(/<string>([^<]*)<\/string>/g)].map((match) => xmlUnescape(match[1])) : [];
28571
+ const bunPath = programArguments[0];
28572
+ const supervisorEntry = programArguments[1];
28573
+ const pm2Path = programArguments[2];
28574
+ const pm2Home = plistValue(contents, "PM2_HOME");
28575
+ const managementLock = plistValue(contents, "SUPERTASK_PM2_MANAGEMENT_LOCK");
28576
+ if (!bunPath || !supervisorEntry || !pm2Path || !pm2Home || !managementLock) return false;
28577
+ if (expectedPm2Home && pm2Home !== expectedPm2Home) return false;
28578
+ const expectedManagementLock = expectedRuntime ? managementLockPath(expectedRuntime.env, expectedRuntime.cwd) : process.env.SUPERTASK_PM2_MANAGEMENT_LOCK ? managementLockPath() : join4(expectedPm2Home ?? currentScope().pm2Home, "supertask-gateway.manage.sqlite");
28579
+ if (managementLock !== expectedManagementLock) return false;
28580
+ accessSync(bunPath, constants.X_OK);
28581
+ accessSync(supervisorEntry, constants.R_OK);
28582
+ accessSync(pm2Path, constants.X_OK);
28583
+ if (spawnSync(bunPath, ["--version"], {
28584
+ stdio: "ignore",
28585
+ timeout: pm2CommandTimeoutMs(),
28586
+ killSignal: "SIGKILL"
28587
+ }).status !== 0) return false;
28588
+ if (spawnSync(pm2Path, ["--version"], {
28589
+ stdio: "ignore",
28590
+ env: { ...process.env, PM2_HOME: pm2Home },
28591
+ timeout: pm2CommandTimeoutMs(),
28592
+ killSignal: "SIGKILL"
28593
+ }).status !== 0) return false;
28594
+ const loaded = spawnSync(
28595
+ launchctlBin(),
28596
+ ["print", `gui/${process.getuid()}/${MAC_LAUNCH_AGENT_LABEL}`],
28597
+ {
28598
+ encoding: "utf8",
28599
+ stdio: ["ignore", "pipe", "ignore"],
28600
+ timeout: pm2CommandTimeoutMs(),
28601
+ killSignal: "SIGKILL"
28602
+ }
28603
+ );
28604
+ if (loaded.status !== 0) return false;
28605
+ if (!loaded.stdout.includes("state = running")) return false;
28606
+ if (!loaded.stdout.includes(`path = ${plistPath}`)) return false;
28607
+ if (!loaded.stdout.includes(`program = ${bunPath}`)) return false;
28608
+ const dumpPath = join4(pm2Home, "dump.pm2");
28609
+ const dump = JSON.parse(readFileSync3(dumpPath, "utf8"));
28610
+ if (!Array.isArray(dump)) return false;
28611
+ const gateway = dump.find((item) => item.name === PROCESS_NAME);
28612
+ const dumpRuntime = gatewayRuntimeFromProcess(gateway);
28613
+ if (!dumpRuntime || !hasRestorableSavedGatewayRuntime(gateway)) return false;
28614
+ return expectedRuntime === void 0 || dumpRuntime.gatewayEntry === expectedRuntime.gatewayEntry && dumpRuntime.bunPath === expectedRuntime.bunPath && dumpRuntime.cwd === expectedRuntime.cwd && scopesMatch(runtimeScope(dumpRuntime), runtimeScope(expectedRuntime));
28615
+ } catch {
28616
+ return false;
28617
+ }
28618
+ }
28619
+ function systemctlBin(env = process.env) {
28620
+ return env.SUPERTASK_SYSTEMCTL_BIN ?? "systemctl";
28621
+ }
28622
+ function isLinuxStartupConfigured(env = process.env, cwd = process.cwd(), expectedRuntime) {
28623
+ const unit = env.SUPERTASK_PM2_SYSTEMD_UNIT ?? `pm2-${userInfo().username}.service`;
28624
+ const enabled = spawnSync(systemctlBin(env), ["is-enabled", unit], {
28625
+ encoding: "utf8",
28626
+ env,
28627
+ stdio: ["ignore", "pipe", "ignore"],
28628
+ timeout: pm2CommandTimeoutMs(env),
28629
+ killSignal: "SIGKILL"
28630
+ });
28631
+ if (enabled.status !== 0 || enabled.stdout.trim() !== "enabled") return false;
28632
+ const contents = spawnSync(systemctlBin(env), ["cat", unit], {
28633
+ encoding: "utf8",
28634
+ env,
28635
+ stdio: ["ignore", "pipe", "ignore"],
28636
+ timeout: pm2CommandTimeoutMs(env),
28637
+ killSignal: "SIGKILL"
28638
+ });
28639
+ if (contents.status !== 0) return false;
28640
+ const expectedPm2Home = env.PM2_HOME ?? join4(runtimeHome(env), ".pm2");
28641
+ if (!contents.stdout.includes("resurrect") || !contents.stdout.includes(expectedPm2Home)) {
28642
+ return false;
28643
+ }
28644
+ try {
28645
+ const dump = JSON.parse(readFileSync3(join4(expectedPm2Home, "dump.pm2"), "utf8"));
28646
+ if (!Array.isArray(dump)) return false;
28647
+ const gateway = dump.find((item) => item.name === PROCESS_NAME);
28648
+ const runtime = gatewayRuntimeFromProcess(gateway);
28649
+ if (!runtime || !hasRestorableSavedGatewayRuntime(gateway)) return false;
28650
+ return runtime.cwd === resolve(cwd) && scopesMatch(runtimeScope(runtime), runtimeScope({ cwd, env })) && (expectedRuntime === void 0 || runtime.gatewayEntry === expectedRuntime.gatewayEntry && runtime.bunPath === expectedRuntime.bunPath);
28651
+ } catch {
28652
+ return false;
28653
+ }
28654
+ }
28462
28655
  function isPm2Installed(env = process.env) {
28463
28656
  const result = spawnSync(pm2Bin(env), ["--version"], {
28464
28657
  stdio: "ignore",
@@ -28568,6 +28761,9 @@ function gatewayRuntimeFromProcess(processInfo) {
28568
28761
  killTimeoutMs: Number.isInteger(killTimeout) && killTimeout >= 5e3 ? killTimeout : void 0
28569
28762
  };
28570
28763
  }
28764
+ function hasRestorableSavedGatewayRuntime(processInfo) {
28765
+ return gatewayRuntimeFromProcess(processInfo) !== null;
28766
+ }
28571
28767
  function currentGatewayRuntime(gatewayEntry = resolveGatewayEntry()) {
28572
28768
  return {
28573
28769
  gatewayEntry: resolve(gatewayEntry),
@@ -28764,6 +28960,11 @@ function assertRuntimeCanControlPm2(runtime, existing) {
28764
28960
  function savePm2State(env = process.env) {
28765
28961
  requirePm2(["save"], "pm2 save", { env });
28766
28962
  }
28963
+ function managementLockPath(env = process.env, cwd = process.cwd()) {
28964
+ const override = env.SUPERTASK_PM2_MANAGEMENT_LOCK;
28965
+ if (override) return runtimePath(override, cwd);
28966
+ return join4(runtimeScope({ env, cwd }).pm2Home, "supertask-gateway.manage.sqlite");
28967
+ }
28767
28968
  function canonicalManagementLockPath(env = process.env, cwd = process.cwd()) {
28768
28969
  const home = runtimeHome(env);
28769
28970
  const pm2Home = env.PM2_HOME ? runtimePath(env.PM2_HOME, cwd) : join4(home, ".pm2");
@@ -28986,6 +29187,9 @@ import {
28986
29187
  import { homedir as homedir4, tmpdir } from "os";
28987
29188
  import { dirname as dirname5, join as join5, resolve as resolve2 } from "path";
28988
29189
  var PACKAGE_NAME = "opencode-supertask";
29190
+ function isVersionConverged(version3, state) {
29191
+ return state.packageVersion === version3 && state.plugin.ok && state.plugin.version === version3 && state.plugin.cachedVersion === version3 && (!state.cli.installed || state.cli.version === version3) && state.gateway.pm2Installed && state.gateway.processFound && state.gateway.status === "online" && state.gateway.ready && state.gateway.runningVersion === version3 && state.gateway.gatewayPackageVersion === version3 && state.gateway.scopeMatches;
29192
+ }
28989
29193
  function pluginAt(packageDir) {
28990
29194
  const packageJson = join5(packageDir, "package.json");
28991
29195
  const gatewayEntry = join5(packageDir, "dist/gateway/index.js");
@@ -29137,7 +29341,7 @@ function updateGlobalCli(version3) {
29137
29341
  }
29138
29342
  return { ...after, action: "updated" };
29139
29343
  }
29140
- function latestVersion() {
29344
+ function getLatestVersion() {
29141
29345
  const result = spawnSync2(npmBin(), [
29142
29346
  "view",
29143
29347
  PACKAGE_NAME,
@@ -29177,6 +29381,116 @@ function resolveInstalledPluginVersion(expectedVersion) {
29177
29381
  const actual = installed.length > 0 ? installed.map((plugin) => plugin.version).join(", ") : "\u672A\u627E\u5230\u53EF\u8FD0\u884C\u7F13\u5B58";
29178
29382
  throw new Error(`[supertask] OpenCode \u63D2\u4EF6\u7F13\u5B58\u7248\u672C\u4E0D\u5339\u914D\uFF1A\u671F\u671B ${expectedVersion}\uFF0C\u5B9E\u9645 ${actual}`);
29179
29383
  }
29384
+ function resolveConfiguredPluginSpec(value) {
29385
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
29386
+ throw new Error("[supertask] OpenCode \u6700\u7EC8\u914D\u7F6E\u4E0D\u662F\u5BF9\u8C61");
29387
+ }
29388
+ const plugins = value.plugin;
29389
+ if (!Array.isArray(plugins)) {
29390
+ throw new Error(`[supertask] OpenCode \u6700\u7EC8\u914D\u7F6E\u672A\u542F\u7528 ${PACKAGE_NAME}`);
29391
+ }
29392
+ const matches = plugins.flatMap((entry) => {
29393
+ if (typeof entry === "string") return [entry];
29394
+ if (Array.isArray(entry) && typeof entry[0] === "string") return [entry[0]];
29395
+ return [];
29396
+ }).filter((spec2) => spec2 === PACKAGE_NAME || spec2.startsWith(`${PACKAGE_NAME}@`));
29397
+ if (matches.length === 0) {
29398
+ throw new Error(`[supertask] OpenCode \u6700\u7EC8\u914D\u7F6E\u672A\u542F\u7528 ${PACKAGE_NAME}`);
29399
+ }
29400
+ if (matches.length !== 1) {
29401
+ throw new Error(`[supertask] OpenCode \u6700\u7EC8\u914D\u7F6E\u5305\u542B\u591A\u4E2A ${PACKAGE_NAME} \u58F0\u660E: ${matches.join(", ")}`);
29402
+ }
29403
+ const spec = matches[0];
29404
+ const version3 = spec.startsWith(`${PACKAGE_NAME}@`) ? spec.slice(PACKAGE_NAME.length + 1) : null;
29405
+ return {
29406
+ spec,
29407
+ version: version3 !== null && isSemanticVersion(version3) ? version3 : null,
29408
+ exact: version3 !== null && isSemanticVersion(version3)
29409
+ };
29410
+ }
29411
+ function getOpenCodePluginDiagnostic() {
29412
+ const failed = (message) => ({
29413
+ ok: false,
29414
+ spec: "",
29415
+ version: null,
29416
+ exact: false,
29417
+ cachedVersion: null,
29418
+ packageDir: null,
29419
+ error: message
29420
+ });
29421
+ let outputDirectory = null;
29422
+ let outputFd = null;
29423
+ try {
29424
+ outputDirectory = mkdtempSync(join5(tmpdir(), "opencode-supertask-config-"));
29425
+ chmodSync2(outputDirectory, 448);
29426
+ const outputPath = join5(outputDirectory, "resolved-config.json");
29427
+ outputFd = openSync(outputPath, "w", 384);
29428
+ const result = spawnSync2(opencodeBin(), ["debug", "config", "--pure"], {
29429
+ encoding: "utf8",
29430
+ env: process.env,
29431
+ timeout: 3e4,
29432
+ stdio: ["ignore", outputFd, "pipe"]
29433
+ });
29434
+ closeSync(outputFd);
29435
+ outputFd = null;
29436
+ if (result.error) {
29437
+ return failed(`[supertask] \u65E0\u6CD5\u8BFB\u53D6 OpenCode \u6700\u7EC8\u914D\u7F6E: ${result.error.message}`);
29438
+ }
29439
+ if (result.status !== 0) {
29440
+ const detail = `${result.stderr ?? ""}`.trim();
29441
+ return failed(`[supertask] \u65E0\u6CD5\u8BFB\u53D6 OpenCode \u6700\u7EC8\u914D\u7F6E: ${detail || `\u9000\u51FA\u7801 ${result.status}`}`);
29442
+ }
29443
+ let config2;
29444
+ try {
29445
+ config2 = JSON.parse(readFileSync4(outputPath, "utf8"));
29446
+ } catch {
29447
+ return failed("[supertask] OpenCode \u6700\u7EC8\u914D\u7F6E\u4E0D\u662F\u6709\u6548 JSON");
29448
+ }
29449
+ let configured;
29450
+ try {
29451
+ configured = resolveConfiguredPluginSpec(config2);
29452
+ } catch (error45) {
29453
+ return failed(error45 instanceof Error ? error45.message : String(error45));
29454
+ }
29455
+ if (!configured.exact || configured.version === null) {
29456
+ return {
29457
+ ok: false,
29458
+ ...configured,
29459
+ cachedVersion: null,
29460
+ packageDir: null,
29461
+ error: `[supertask] OpenCode \u63D2\u4EF6\u5FC5\u987B\u56FA\u5B9A\u7CBE\u786E\u7248\u672C\uFF0C\u4E0D\u80FD\u4F7F\u7528 ${configured.spec}`
29462
+ };
29463
+ }
29464
+ try {
29465
+ const installed = resolveInstalledPluginVersion(configured.version);
29466
+ return {
29467
+ ok: true,
29468
+ ...configured,
29469
+ cachedVersion: installed.version,
29470
+ packageDir: installed.packageDir,
29471
+ error: null
29472
+ };
29473
+ } catch (error45) {
29474
+ return {
29475
+ ok: false,
29476
+ ...configured,
29477
+ cachedVersion: null,
29478
+ packageDir: null,
29479
+ error: error45 instanceof Error ? error45.message : String(error45)
29480
+ };
29481
+ }
29482
+ } catch (error45) {
29483
+ return failed(`[supertask] \u65E0\u6CD5\u8BFB\u53D6 OpenCode \u6700\u7EC8\u914D\u7F6E: ${error45 instanceof Error ? error45.message : String(error45)}`);
29484
+ } finally {
29485
+ if (outputFd !== null) {
29486
+ try {
29487
+ closeSync(outputFd);
29488
+ } catch {
29489
+ }
29490
+ }
29491
+ if (outputDirectory !== null) rmSync2(outputDirectory, { recursive: true, force: true });
29492
+ }
29493
+ }
29180
29494
  function installPluginVersion(version3) {
29181
29495
  if (!isSemanticVersion(version3)) {
29182
29496
  throw new Error(`[supertask] OpenCode \u63D2\u4EF6\u7248\u672C\u65E0\u6548: ${version3}`);
@@ -29200,9 +29514,6 @@ function installPluginVersion(version3) {
29200
29514
  }
29201
29515
  return resolveInstalledPluginVersion(version3);
29202
29516
  }
29203
- function installLatestPlugin() {
29204
- return installPluginVersion(latestVersion());
29205
- }
29206
29517
 
29207
29518
  // plugin/supertask.ts
29208
29519
  var _initialized = false;
@@ -29320,6 +29631,7 @@ var SuperTaskPlugin = async () => {
29320
29631
  agent: tool.schema.string().trim().min(1).describe("\u6267\u884C\u7684 Agent \u540D\u79F0\uFF0C\u5982 localize-gen, course-gen"),
29321
29632
  prompt: tool.schema.string().trim().min(1).describe("\u53D1\u9001\u7ED9 Agent \u7684\u5B8C\u6574\u63D0\u793A\u8BCD"),
29322
29633
  model: tool.schema.string().optional().describe("\u4F7F\u7528\u7684\u6A21\u578B\uFF0C\u5982 gemini-2.5-pro"),
29634
+ variant: tool.schema.string().trim().min(1).max(128).optional().describe("\u6A21\u578B variant\uFF0C\u5982 low\u3001high\u3001xhigh\uFF1B\u4EC5\u5728\u6A21\u578B\u652F\u6301\u65F6\u4F7F\u7528"),
29323
29635
  category: tool.schema.enum(["translate", "generate", "review", "test", "general"]).optional().describe("\u4EFB\u52A1\u5206\u7C7B"),
29324
29636
  importance: tool.schema.number().int().min(1).max(5).optional().describe("\u91CD\u8981\u7A0B\u5EA6 1-5\uFF085 \u6700\u91CD\u8981\uFF09"),
29325
29637
  urgency: tool.schema.number().int().min(1).max(5).optional().describe("\u7D27\u6025\u7A0B\u5EA6 1-5\uFF085 \u6700\u7D27\u6025\uFF09"),
@@ -29340,6 +29652,7 @@ var SuperTaskPlugin = async () => {
29340
29652
  agent: args.agent,
29341
29653
  prompt: args.prompt,
29342
29654
  model: args.model,
29655
+ variant: args.variant,
29343
29656
  category: args.category ?? "general",
29344
29657
  importance: args.importance ?? 3,
29345
29658
  urgency: args.urgency ?? 3,
@@ -29373,6 +29686,7 @@ var SuperTaskPlugin = async () => {
29373
29686
  name: task.name,
29374
29687
  agent: task.agent,
29375
29688
  model: task.model,
29689
+ variant: task.variant,
29376
29690
  prompt: task.prompt,
29377
29691
  cwd: task.cwd,
29378
29692
  category: task.category,
@@ -29494,6 +29808,7 @@ var SuperTaskPlugin = async () => {
29494
29808
  name: task.name,
29495
29809
  agent: task.agent,
29496
29810
  model: task.model,
29811
+ variant: task.variant,
29497
29812
  prompt: task.prompt,
29498
29813
  cwd: task.cwd,
29499
29814
  category: task.category,
@@ -29517,6 +29832,7 @@ var SuperTaskPlugin = async () => {
29517
29832
  agent: tool.schema.string().trim().min(1).describe("\u6267\u884C\u7684 Agent \u540D\u79F0"),
29518
29833
  prompt: tool.schema.string().trim().min(1).describe("\u53D1\u9001\u7ED9 Agent \u7684\u5B8C\u6574\u63D0\u793A\u8BCD"),
29519
29834
  model: tool.schema.string().optional().describe("\u4F7F\u7528\u7684\u6A21\u578B"),
29835
+ variant: tool.schema.string().trim().min(1).max(128).optional().describe("\u6A21\u578B variant\uFF0C\u5982 low\u3001high\u3001xhigh\uFF1B\u4EC5\u5728\u6A21\u578B\u652F\u6301\u65F6\u4F7F\u7528"),
29520
29836
  category: tool.schema.enum(["translate", "generate", "review", "test", "general"]).optional().describe("\u4EFB\u52A1\u5206\u7C7B"),
29521
29837
  importance: tool.schema.number().int().min(1).max(5).optional().describe("\u91CD\u8981\u7A0B\u5EA6 1-5"),
29522
29838
  urgency: tool.schema.number().int().min(1).max(5).optional().describe("\u7D27\u6025\u7A0B\u5EA6 1-5"),
@@ -29560,6 +29876,7 @@ var SuperTaskPlugin = async () => {
29560
29876
  agent: args.agent,
29561
29877
  prompt: args.prompt,
29562
29878
  model: args.model,
29879
+ variant: args.variant,
29563
29880
  category: args.category ?? "general",
29564
29881
  importance: args.importance ?? 3,
29565
29882
  urgency: args.urgency ?? 3,
@@ -29600,11 +29917,31 @@ var SuperTaskPlugin = async () => {
29600
29917
  });
29601
29918
  }
29602
29919
  try {
29603
- console.log("[supertask] Updating OpenCode plugin cache...");
29604
29920
  const previousVersion = getPackageVersion();
29921
+ const targetVersion = getLatestVersion();
29922
+ const plugin = getOpenCodePluginDiagnostic();
29923
+ const cli = getGlobalCliDiagnostic();
29924
+ const gateway = getGatewayDiagnostic();
29925
+ if (isVersionConverged(targetVersion, {
29926
+ packageVersion: previousVersion,
29927
+ plugin,
29928
+ cli,
29929
+ gateway
29930
+ })) {
29931
+ return JSON.stringify({
29932
+ success: true,
29933
+ upToDate: true,
29934
+ before: targetVersion,
29935
+ after: targetVersion,
29936
+ restarted: false,
29937
+ cli,
29938
+ message: `SuperTask \u5DF2\u662F\u6700\u65B0\u7248\u672C ${targetVersion}\uFF0CGateway \u672A\u91CD\u542F\u3002`
29939
+ });
29940
+ }
29941
+ console.log("[supertask] Updating OpenCode plugin cache...");
29605
29942
  let installed;
29606
29943
  try {
29607
- installed = installLatestPlugin();
29944
+ installed = installPluginVersion(targetVersion);
29608
29945
  } catch (updateError) {
29609
29946
  let detail = updateError instanceof Error ? updateError.message : String(updateError);
29610
29947
  try {