opencode-supertask 0.1.37 → 0.1.39

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.
@@ -28368,6 +28368,26 @@ function getRunningVersion(env = process.env, cwd = process.cwd()) {
28368
28368
  return null;
28369
28369
  }
28370
28370
  }
28371
+ function packageVersionFromGatewayEntry(gatewayEntry) {
28372
+ if (gatewayEntry === null) return null;
28373
+ let directory = dirname4(gatewayEntry);
28374
+ for (let depth = 0; depth < 6; depth += 1) {
28375
+ const packagePath = join4(directory, "package.json");
28376
+ if (existsSync4(packagePath)) {
28377
+ try {
28378
+ const pkg = JSON.parse(readFileSync3(packagePath, "utf8"));
28379
+ if (pkg.name === "opencode-supertask" && typeof pkg.version === "string") {
28380
+ return pkg.version;
28381
+ }
28382
+ } catch {
28383
+ }
28384
+ }
28385
+ const parent = dirname4(directory);
28386
+ if (parent === directory) break;
28387
+ directory = parent;
28388
+ }
28389
+ return null;
28390
+ }
28371
28391
  function resolveRuntimeExecutable(command, env, cwd) {
28372
28392
  if (isAbsolute2(command) || command.includes("/")) return runtimePath(command, cwd);
28373
28393
  for (const entry of (env.PATH ?? "").split(delimiter)) {
@@ -28428,6 +28448,55 @@ function assertOpenCodeRuntime(runtime) {
28428
28448
  );
28429
28449
  }
28430
28450
  }
28451
+ function getGatewayDiagnostic(options = {}) {
28452
+ const producerScope = currentScope();
28453
+ if (!isPm2Installed()) {
28454
+ return {
28455
+ pm2Installed: false,
28456
+ processFound: false,
28457
+ status: null,
28458
+ pid: null,
28459
+ ready: false,
28460
+ runningVersion: getRunningVersion(),
28461
+ gatewayEntry: null,
28462
+ gatewayPackageVersion: null,
28463
+ logRotationInstalled: false,
28464
+ startupConfigured: process.platform === "darwin" || process.platform === "linux" ? false : null,
28465
+ currentScope: producerScope,
28466
+ gatewayScope: null,
28467
+ scopeMatches: false,
28468
+ gatewayOpenCode: null
28469
+ };
28470
+ }
28471
+ const processes = pm2JsonList();
28472
+ const gateway = processes.find((item) => item.name === PROCESS_NAME);
28473
+ const runtime = gatewayRuntimeFromProcess(gateway);
28474
+ const gatewayEnv = runtime?.env ?? process.env;
28475
+ const managedScope = runtime ? runtimeScope(runtime) : null;
28476
+ const pid = typeof gateway?.pid === "number" ? gateway.pid : null;
28477
+ const readyPath = managedScope?.databasePath ?? databasePath();
28478
+ const lockedVersion = pid == null ? void 0 : gatewayVersionFromLock(pid, readyPath);
28479
+ const gatewayEntry = runtime?.gatewayEntry ?? null;
28480
+ return {
28481
+ pm2Installed: true,
28482
+ processFound: gateway != null,
28483
+ status: gateway?.pm2_env?.status ?? null,
28484
+ pid,
28485
+ ready: pid != null && isGatewayReady(pid, readyPath),
28486
+ runningVersion: lockedVersion === void 0 ? getRunningVersion(gatewayEnv, runtime?.cwd) : lockedVersion,
28487
+ gatewayEntry,
28488
+ gatewayPackageVersion: packageVersionFromGatewayEntry(gatewayEntry),
28489
+ logRotationInstalled: processes.some((item) => item.name === "pm2-logrotate" && item.pm2_env?.status === "online"),
28490
+ startupConfigured: process.platform === "darwin" ? isMacLaunchAgentConfigured(
28491
+ gatewayEnv.PM2_HOME ?? join4(runtimeHome(gatewayEnv), ".pm2"),
28492
+ runtime ?? void 0
28493
+ ) : process.platform === "linux" ? isLinuxStartupConfigured(gatewayEnv, runtime?.cwd, runtime ?? void 0) : null,
28494
+ currentScope: producerScope,
28495
+ gatewayScope: managedScope,
28496
+ scopeMatches: managedScope != null && scopesMatch(producerScope, managedScope),
28497
+ gatewayOpenCode: runtime === null || !options.probeOpenCode ? null : diagnoseOpenCodeRuntime(runtime)
28498
+ };
28499
+ }
28431
28500
  function writeRunningVersion(version3, env = process.env, cwd = process.cwd()) {
28432
28501
  const path = versionFile(env, cwd);
28433
28502
  mkdirSync3(dirname4(path), { recursive: true });
@@ -28451,6 +28520,9 @@ function resolvePm2Bin() {
28451
28520
  function launchAgentPath() {
28452
28521
  return process.env.SUPERTASK_LAUNCH_AGENT_PATH ?? join4(runtimeHome(process.env), "Library/LaunchAgents", `${MAC_LAUNCH_AGENT_LABEL}.plist`);
28453
28522
  }
28523
+ function launchctlBin() {
28524
+ return process.env.SUPERTASK_LAUNCHCTL_BIN ?? "launchctl";
28525
+ }
28454
28526
  function xmlUnescape(value) {
28455
28527
  return value.replaceAll("&apos;", "'").replaceAll("&quot;", '"').replaceAll("&gt;", ">").replaceAll("&lt;", "<").replaceAll("&amp;", "&");
28456
28528
  }
@@ -28459,6 +28531,100 @@ function plistValue(contents, key) {
28459
28531
  const match = contents.match(new RegExp(`<key>\\s*${escapedKey}\\s*</key>\\s*<string>([^<]*)</string>`));
28460
28532
  return match?.[1] ? xmlUnescape(match[1]) : null;
28461
28533
  }
28534
+ function isMacLaunchAgentConfigured(expectedPm2Home, expectedRuntime) {
28535
+ if (typeof process.getuid !== "function") return false;
28536
+ const plistPath = launchAgentPath();
28537
+ if (!existsSync4(plistPath)) return false;
28538
+ try {
28539
+ const contents = readFileSync3(plistPath, "utf8");
28540
+ const argumentsBlock = contents.match(
28541
+ /<key>\s*ProgramArguments\s*<\/key>\s*<array>([\s\S]*?)<\/array>/
28542
+ )?.[1];
28543
+ const programArguments = argumentsBlock ? [...argumentsBlock.matchAll(/<string>([^<]*)<\/string>/g)].map((match) => xmlUnescape(match[1])) : [];
28544
+ const bunPath = programArguments[0];
28545
+ const supervisorEntry = programArguments[1];
28546
+ const pm2Path = programArguments[2];
28547
+ const pm2Home = plistValue(contents, "PM2_HOME");
28548
+ const managementLock = plistValue(contents, "SUPERTASK_PM2_MANAGEMENT_LOCK");
28549
+ if (!bunPath || !supervisorEntry || !pm2Path || !pm2Home || !managementLock) return false;
28550
+ if (expectedPm2Home && pm2Home !== expectedPm2Home) return false;
28551
+ const expectedManagementLock = expectedRuntime ? managementLockPath(expectedRuntime.env, expectedRuntime.cwd) : process.env.SUPERTASK_PM2_MANAGEMENT_LOCK ? managementLockPath() : join4(expectedPm2Home ?? currentScope().pm2Home, "supertask-gateway.manage.sqlite");
28552
+ if (managementLock !== expectedManagementLock) return false;
28553
+ accessSync(bunPath, constants.X_OK);
28554
+ accessSync(supervisorEntry, constants.R_OK);
28555
+ accessSync(pm2Path, constants.X_OK);
28556
+ if (spawnSync(bunPath, ["--version"], {
28557
+ stdio: "ignore",
28558
+ timeout: pm2CommandTimeoutMs(),
28559
+ killSignal: "SIGKILL"
28560
+ }).status !== 0) return false;
28561
+ if (spawnSync(pm2Path, ["--version"], {
28562
+ stdio: "ignore",
28563
+ env: { ...process.env, PM2_HOME: pm2Home },
28564
+ timeout: pm2CommandTimeoutMs(),
28565
+ killSignal: "SIGKILL"
28566
+ }).status !== 0) return false;
28567
+ const loaded = spawnSync(
28568
+ launchctlBin(),
28569
+ ["print", `gui/${process.getuid()}/${MAC_LAUNCH_AGENT_LABEL}`],
28570
+ {
28571
+ encoding: "utf8",
28572
+ stdio: ["ignore", "pipe", "ignore"],
28573
+ timeout: pm2CommandTimeoutMs(),
28574
+ killSignal: "SIGKILL"
28575
+ }
28576
+ );
28577
+ if (loaded.status !== 0) return false;
28578
+ if (!loaded.stdout.includes("state = running")) return false;
28579
+ if (!loaded.stdout.includes(`path = ${plistPath}`)) return false;
28580
+ if (!loaded.stdout.includes(`program = ${bunPath}`)) return false;
28581
+ const dumpPath = join4(pm2Home, "dump.pm2");
28582
+ const dump = JSON.parse(readFileSync3(dumpPath, "utf8"));
28583
+ if (!Array.isArray(dump)) return false;
28584
+ const gateway = dump.find((item) => item.name === PROCESS_NAME);
28585
+ const dumpRuntime = gatewayRuntimeFromProcess(gateway);
28586
+ if (!dumpRuntime || !hasRestorableSavedGatewayRuntime(gateway)) return false;
28587
+ return expectedRuntime === void 0 || dumpRuntime.gatewayEntry === expectedRuntime.gatewayEntry && dumpRuntime.bunPath === expectedRuntime.bunPath && dumpRuntime.cwd === expectedRuntime.cwd && scopesMatch(runtimeScope(dumpRuntime), runtimeScope(expectedRuntime));
28588
+ } catch {
28589
+ return false;
28590
+ }
28591
+ }
28592
+ function systemctlBin(env = process.env) {
28593
+ return env.SUPERTASK_SYSTEMCTL_BIN ?? "systemctl";
28594
+ }
28595
+ function isLinuxStartupConfigured(env = process.env, cwd = process.cwd(), expectedRuntime) {
28596
+ const unit = env.SUPERTASK_PM2_SYSTEMD_UNIT ?? `pm2-${userInfo().username}.service`;
28597
+ const enabled = spawnSync(systemctlBin(env), ["is-enabled", unit], {
28598
+ encoding: "utf8",
28599
+ env,
28600
+ stdio: ["ignore", "pipe", "ignore"],
28601
+ timeout: pm2CommandTimeoutMs(env),
28602
+ killSignal: "SIGKILL"
28603
+ });
28604
+ if (enabled.status !== 0 || enabled.stdout.trim() !== "enabled") return false;
28605
+ const contents = spawnSync(systemctlBin(env), ["cat", unit], {
28606
+ encoding: "utf8",
28607
+ env,
28608
+ stdio: ["ignore", "pipe", "ignore"],
28609
+ timeout: pm2CommandTimeoutMs(env),
28610
+ killSignal: "SIGKILL"
28611
+ });
28612
+ if (contents.status !== 0) return false;
28613
+ const expectedPm2Home = env.PM2_HOME ?? join4(runtimeHome(env), ".pm2");
28614
+ if (!contents.stdout.includes("resurrect") || !contents.stdout.includes(expectedPm2Home)) {
28615
+ return false;
28616
+ }
28617
+ try {
28618
+ const dump = JSON.parse(readFileSync3(join4(expectedPm2Home, "dump.pm2"), "utf8"));
28619
+ if (!Array.isArray(dump)) return false;
28620
+ const gateway = dump.find((item) => item.name === PROCESS_NAME);
28621
+ const runtime = gatewayRuntimeFromProcess(gateway);
28622
+ if (!runtime || !hasRestorableSavedGatewayRuntime(gateway)) return false;
28623
+ return runtime.cwd === resolve(cwd) && scopesMatch(runtimeScope(runtime), runtimeScope({ cwd, env })) && (expectedRuntime === void 0 || runtime.gatewayEntry === expectedRuntime.gatewayEntry && runtime.bunPath === expectedRuntime.bunPath);
28624
+ } catch {
28625
+ return false;
28626
+ }
28627
+ }
28462
28628
  function isPm2Installed(env = process.env) {
28463
28629
  const result = spawnSync(pm2Bin(env), ["--version"], {
28464
28630
  stdio: "ignore",
@@ -28568,6 +28734,9 @@ function gatewayRuntimeFromProcess(processInfo) {
28568
28734
  killTimeoutMs: Number.isInteger(killTimeout) && killTimeout >= 5e3 ? killTimeout : void 0
28569
28735
  };
28570
28736
  }
28737
+ function hasRestorableSavedGatewayRuntime(processInfo) {
28738
+ return gatewayRuntimeFromProcess(processInfo) !== null;
28739
+ }
28571
28740
  function currentGatewayRuntime(gatewayEntry = resolveGatewayEntry()) {
28572
28741
  return {
28573
28742
  gatewayEntry: resolve(gatewayEntry),
@@ -28764,6 +28933,11 @@ function assertRuntimeCanControlPm2(runtime, existing) {
28764
28933
  function savePm2State(env = process.env) {
28765
28934
  requirePm2(["save"], "pm2 save", { env });
28766
28935
  }
28936
+ function managementLockPath(env = process.env, cwd = process.cwd()) {
28937
+ const override = env.SUPERTASK_PM2_MANAGEMENT_LOCK;
28938
+ if (override) return runtimePath(override, cwd);
28939
+ return join4(runtimeScope({ env, cwd }).pm2Home, "supertask-gateway.manage.sqlite");
28940
+ }
28767
28941
  function canonicalManagementLockPath(env = process.env, cwd = process.cwd()) {
28768
28942
  const home = runtimeHome(env);
28769
28943
  const pm2Home = env.PM2_HOME ? runtimePath(env.PM2_HOME, cwd) : join4(home, ".pm2");
@@ -28972,10 +29146,23 @@ function ensureGatewayUnlocked() {
28972
29146
 
28973
29147
  // src/daemon/update.ts
28974
29148
  import { spawnSync as spawnSync2 } from "child_process";
28975
- import { existsSync as existsSync5, readFileSync as readFileSync4, readdirSync, realpathSync } from "fs";
28976
- import { homedir as homedir4 } from "os";
29149
+ import {
29150
+ chmodSync as chmodSync2,
29151
+ closeSync,
29152
+ existsSync as existsSync5,
29153
+ mkdtempSync,
29154
+ openSync,
29155
+ readFileSync as readFileSync4,
29156
+ readdirSync,
29157
+ realpathSync,
29158
+ rmSync as rmSync2
29159
+ } from "fs";
29160
+ import { homedir as homedir4, tmpdir } from "os";
28977
29161
  import { dirname as dirname5, join as join5, resolve as resolve2 } from "path";
28978
29162
  var PACKAGE_NAME = "opencode-supertask";
29163
+ function isVersionConverged(version3, state) {
29164
+ 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;
29165
+ }
28979
29166
  function pluginAt(packageDir) {
28980
29167
  const packageJson = join5(packageDir, "package.json");
28981
29168
  const gatewayEntry = join5(packageDir, "dist/gateway/index.js");
@@ -29127,7 +29314,7 @@ function updateGlobalCli(version3) {
29127
29314
  }
29128
29315
  return { ...after, action: "updated" };
29129
29316
  }
29130
- function latestVersion() {
29317
+ function getLatestVersion() {
29131
29318
  const result = spawnSync2(npmBin(), [
29132
29319
  "view",
29133
29320
  PACKAGE_NAME,
@@ -29167,6 +29354,116 @@ function resolveInstalledPluginVersion(expectedVersion) {
29167
29354
  const actual = installed.length > 0 ? installed.map((plugin) => plugin.version).join(", ") : "\u672A\u627E\u5230\u53EF\u8FD0\u884C\u7F13\u5B58";
29168
29355
  throw new Error(`[supertask] OpenCode \u63D2\u4EF6\u7F13\u5B58\u7248\u672C\u4E0D\u5339\u914D\uFF1A\u671F\u671B ${expectedVersion}\uFF0C\u5B9E\u9645 ${actual}`);
29169
29356
  }
29357
+ function resolveConfiguredPluginSpec(value) {
29358
+ if (!value || typeof value !== "object" || Array.isArray(value)) {
29359
+ throw new Error("[supertask] OpenCode \u6700\u7EC8\u914D\u7F6E\u4E0D\u662F\u5BF9\u8C61");
29360
+ }
29361
+ const plugins = value.plugin;
29362
+ if (!Array.isArray(plugins)) {
29363
+ throw new Error(`[supertask] OpenCode \u6700\u7EC8\u914D\u7F6E\u672A\u542F\u7528 ${PACKAGE_NAME}`);
29364
+ }
29365
+ const matches = plugins.flatMap((entry) => {
29366
+ if (typeof entry === "string") return [entry];
29367
+ if (Array.isArray(entry) && typeof entry[0] === "string") return [entry[0]];
29368
+ return [];
29369
+ }).filter((spec2) => spec2 === PACKAGE_NAME || spec2.startsWith(`${PACKAGE_NAME}@`));
29370
+ if (matches.length === 0) {
29371
+ throw new Error(`[supertask] OpenCode \u6700\u7EC8\u914D\u7F6E\u672A\u542F\u7528 ${PACKAGE_NAME}`);
29372
+ }
29373
+ if (matches.length !== 1) {
29374
+ throw new Error(`[supertask] OpenCode \u6700\u7EC8\u914D\u7F6E\u5305\u542B\u591A\u4E2A ${PACKAGE_NAME} \u58F0\u660E: ${matches.join(", ")}`);
29375
+ }
29376
+ const spec = matches[0];
29377
+ const version3 = spec.startsWith(`${PACKAGE_NAME}@`) ? spec.slice(PACKAGE_NAME.length + 1) : null;
29378
+ return {
29379
+ spec,
29380
+ version: version3 !== null && isSemanticVersion(version3) ? version3 : null,
29381
+ exact: version3 !== null && isSemanticVersion(version3)
29382
+ };
29383
+ }
29384
+ function getOpenCodePluginDiagnostic() {
29385
+ const failed = (message) => ({
29386
+ ok: false,
29387
+ spec: "",
29388
+ version: null,
29389
+ exact: false,
29390
+ cachedVersion: null,
29391
+ packageDir: null,
29392
+ error: message
29393
+ });
29394
+ let outputDirectory = null;
29395
+ let outputFd = null;
29396
+ try {
29397
+ outputDirectory = mkdtempSync(join5(tmpdir(), "opencode-supertask-config-"));
29398
+ chmodSync2(outputDirectory, 448);
29399
+ const outputPath = join5(outputDirectory, "resolved-config.json");
29400
+ outputFd = openSync(outputPath, "w", 384);
29401
+ const result = spawnSync2(opencodeBin(), ["debug", "config", "--pure"], {
29402
+ encoding: "utf8",
29403
+ env: process.env,
29404
+ timeout: 3e4,
29405
+ stdio: ["ignore", outputFd, "pipe"]
29406
+ });
29407
+ closeSync(outputFd);
29408
+ outputFd = null;
29409
+ if (result.error) {
29410
+ return failed(`[supertask] \u65E0\u6CD5\u8BFB\u53D6 OpenCode \u6700\u7EC8\u914D\u7F6E: ${result.error.message}`);
29411
+ }
29412
+ if (result.status !== 0) {
29413
+ const detail = `${result.stderr ?? ""}`.trim();
29414
+ return failed(`[supertask] \u65E0\u6CD5\u8BFB\u53D6 OpenCode \u6700\u7EC8\u914D\u7F6E: ${detail || `\u9000\u51FA\u7801 ${result.status}`}`);
29415
+ }
29416
+ let config2;
29417
+ try {
29418
+ config2 = JSON.parse(readFileSync4(outputPath, "utf8"));
29419
+ } catch {
29420
+ return failed("[supertask] OpenCode \u6700\u7EC8\u914D\u7F6E\u4E0D\u662F\u6709\u6548 JSON");
29421
+ }
29422
+ let configured;
29423
+ try {
29424
+ configured = resolveConfiguredPluginSpec(config2);
29425
+ } catch (error45) {
29426
+ return failed(error45 instanceof Error ? error45.message : String(error45));
29427
+ }
29428
+ if (!configured.exact || configured.version === null) {
29429
+ return {
29430
+ ok: false,
29431
+ ...configured,
29432
+ cachedVersion: null,
29433
+ packageDir: null,
29434
+ error: `[supertask] OpenCode \u63D2\u4EF6\u5FC5\u987B\u56FA\u5B9A\u7CBE\u786E\u7248\u672C\uFF0C\u4E0D\u80FD\u4F7F\u7528 ${configured.spec}`
29435
+ };
29436
+ }
29437
+ try {
29438
+ const installed = resolveInstalledPluginVersion(configured.version);
29439
+ return {
29440
+ ok: true,
29441
+ ...configured,
29442
+ cachedVersion: installed.version,
29443
+ packageDir: installed.packageDir,
29444
+ error: null
29445
+ };
29446
+ } catch (error45) {
29447
+ return {
29448
+ ok: false,
29449
+ ...configured,
29450
+ cachedVersion: null,
29451
+ packageDir: null,
29452
+ error: error45 instanceof Error ? error45.message : String(error45)
29453
+ };
29454
+ }
29455
+ } catch (error45) {
29456
+ return failed(`[supertask] \u65E0\u6CD5\u8BFB\u53D6 OpenCode \u6700\u7EC8\u914D\u7F6E: ${error45 instanceof Error ? error45.message : String(error45)}`);
29457
+ } finally {
29458
+ if (outputFd !== null) {
29459
+ try {
29460
+ closeSync(outputFd);
29461
+ } catch {
29462
+ }
29463
+ }
29464
+ if (outputDirectory !== null) rmSync2(outputDirectory, { recursive: true, force: true });
29465
+ }
29466
+ }
29170
29467
  function installPluginVersion(version3) {
29171
29468
  if (!isSemanticVersion(version3)) {
29172
29469
  throw new Error(`[supertask] OpenCode \u63D2\u4EF6\u7248\u672C\u65E0\u6548: ${version3}`);
@@ -29190,9 +29487,6 @@ function installPluginVersion(version3) {
29190
29487
  }
29191
29488
  return resolveInstalledPluginVersion(version3);
29192
29489
  }
29193
- function installLatestPlugin() {
29194
- return installPluginVersion(latestVersion());
29195
- }
29196
29490
 
29197
29491
  // plugin/supertask.ts
29198
29492
  var _initialized = false;
@@ -29590,11 +29884,31 @@ var SuperTaskPlugin = async () => {
29590
29884
  });
29591
29885
  }
29592
29886
  try {
29593
- console.log("[supertask] Updating OpenCode plugin cache...");
29594
29887
  const previousVersion = getPackageVersion();
29888
+ const targetVersion = getLatestVersion();
29889
+ const plugin = getOpenCodePluginDiagnostic();
29890
+ const cli = getGlobalCliDiagnostic();
29891
+ const gateway = getGatewayDiagnostic();
29892
+ if (isVersionConverged(targetVersion, {
29893
+ packageVersion: previousVersion,
29894
+ plugin,
29895
+ cli,
29896
+ gateway
29897
+ })) {
29898
+ return JSON.stringify({
29899
+ success: true,
29900
+ upToDate: true,
29901
+ before: targetVersion,
29902
+ after: targetVersion,
29903
+ restarted: false,
29904
+ cli,
29905
+ message: `SuperTask \u5DF2\u662F\u6700\u65B0\u7248\u672C ${targetVersion}\uFF0CGateway \u672A\u91CD\u542F\u3002`
29906
+ });
29907
+ }
29908
+ console.log("[supertask] Updating OpenCode plugin cache...");
29595
29909
  let installed;
29596
29910
  try {
29597
- installed = installLatestPlugin();
29911
+ installed = installPluginVersion(targetVersion);
29598
29912
  } catch (updateError) {
29599
29913
  let detail = updateError instanceof Error ? updateError.message : String(updateError);
29600
29914
  try {