oh-my-opencode 3.15.2 → 3.15.3
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/dist/cli/index.js +438 -187
- package/dist/cli/run/continuation-state.d.ts +2 -1
- package/dist/features/boulder-state/storage.d.ts +1 -1
- package/dist/features/boulder-state/types.d.ts +1 -0
- package/dist/hooks/atlas/background-launch-session-tracking.d.ts +11 -0
- package/dist/hooks/atlas/boulder-continuation-injector.d.ts +2 -1
- package/dist/hooks/atlas/task-context.d.ts +7 -0
- package/dist/hooks/atlas/types.d.ts +1 -0
- package/dist/index.js +646 -366
- package/dist/shared/agent-display-names.d.ts +1 -0
- package/dist/tools/delegate-task/resolve-call-id.d.ts +2 -0
- package/package.json +12 -12
package/dist/cli/index.js
CHANGED
|
@@ -6367,18 +6367,88 @@ var TAURI_APP_IDENTIFIER = "ai.opencode.desktop", TAURI_APP_IDENTIFIER_DEV = "ai
|
|
|
6367
6367
|
var init_opencode_config_dir = () => {};
|
|
6368
6368
|
|
|
6369
6369
|
// src/shared/opencode-version.ts
|
|
6370
|
-
|
|
6370
|
+
import { execSync } from "child_process";
|
|
6371
|
+
function parseVersion(version) {
|
|
6372
|
+
const cleaned = version.replace(/^v/, "").split("-")[0];
|
|
6373
|
+
return cleaned.split(".").map((n) => parseInt(n, 10) || 0);
|
|
6374
|
+
}
|
|
6375
|
+
function compareVersions(a, b) {
|
|
6376
|
+
const partsA = parseVersion(a);
|
|
6377
|
+
const partsB = parseVersion(b);
|
|
6378
|
+
const maxLen = Math.max(partsA.length, partsB.length);
|
|
6379
|
+
for (let i2 = 0;i2 < maxLen; i2++) {
|
|
6380
|
+
const numA = partsA[i2] ?? 0;
|
|
6381
|
+
const numB = partsB[i2] ?? 0;
|
|
6382
|
+
if (numA < numB)
|
|
6383
|
+
return -1;
|
|
6384
|
+
if (numA > numB)
|
|
6385
|
+
return 1;
|
|
6386
|
+
}
|
|
6387
|
+
return 0;
|
|
6388
|
+
}
|
|
6389
|
+
function getOpenCodeVersion() {
|
|
6390
|
+
if (cachedVersion !== NOT_CACHED) {
|
|
6391
|
+
return cachedVersion;
|
|
6392
|
+
}
|
|
6393
|
+
try {
|
|
6394
|
+
const result = execSync("opencode --version", {
|
|
6395
|
+
encoding: "utf-8",
|
|
6396
|
+
timeout: 5000,
|
|
6397
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
6398
|
+
}).trim();
|
|
6399
|
+
const versionMatch = result.match(/(\d+\.\d+\.\d+(?:-[\w.]+)?)/);
|
|
6400
|
+
cachedVersion = versionMatch?.[1] ?? null;
|
|
6401
|
+
return cachedVersion;
|
|
6402
|
+
} catch {
|
|
6403
|
+
cachedVersion = null;
|
|
6404
|
+
return null;
|
|
6405
|
+
}
|
|
6406
|
+
}
|
|
6407
|
+
function isOpenCodeVersionAtLeast(version) {
|
|
6408
|
+
const current = getOpenCodeVersion();
|
|
6409
|
+
if (!current)
|
|
6410
|
+
return true;
|
|
6411
|
+
return compareVersions(current, version) >= 0;
|
|
6412
|
+
}
|
|
6413
|
+
var OPENCODE_SQLITE_VERSION = "1.1.53", NOT_CACHED, cachedVersion;
|
|
6371
6414
|
var init_opencode_version = __esm(() => {
|
|
6372
6415
|
NOT_CACHED = Symbol("NOT_CACHED");
|
|
6416
|
+
cachedVersion = NOT_CACHED;
|
|
6373
6417
|
});
|
|
6374
6418
|
|
|
6375
6419
|
// src/shared/opencode-storage-detection.ts
|
|
6376
|
-
|
|
6420
|
+
import { existsSync as existsSync3 } from "fs";
|
|
6421
|
+
import { join as join5 } from "path";
|
|
6422
|
+
function isSqliteBackend() {
|
|
6423
|
+
if (cachedResult === true)
|
|
6424
|
+
return true;
|
|
6425
|
+
if (cachedResult === false)
|
|
6426
|
+
return false;
|
|
6427
|
+
const check = () => {
|
|
6428
|
+
const versionOk = isOpenCodeVersionAtLeast(OPENCODE_SQLITE_VERSION);
|
|
6429
|
+
const dbPath = join5(getDataDir(), "opencode", "opencode.db");
|
|
6430
|
+
return versionOk && existsSync3(dbPath);
|
|
6431
|
+
};
|
|
6432
|
+
if (cachedResult === FALSE_PENDING_RETRY) {
|
|
6433
|
+
const result2 = check();
|
|
6434
|
+
cachedResult = result2;
|
|
6435
|
+
return result2;
|
|
6436
|
+
}
|
|
6437
|
+
const result = check();
|
|
6438
|
+
if (result) {
|
|
6439
|
+
cachedResult = true;
|
|
6440
|
+
} else {
|
|
6441
|
+
cachedResult = FALSE_PENDING_RETRY;
|
|
6442
|
+
}
|
|
6443
|
+
return result;
|
|
6444
|
+
}
|
|
6445
|
+
var NOT_CACHED2, FALSE_PENDING_RETRY, cachedResult;
|
|
6377
6446
|
var init_opencode_storage_detection = __esm(() => {
|
|
6378
6447
|
init_data_path();
|
|
6379
6448
|
init_opencode_version();
|
|
6380
6449
|
NOT_CACHED2 = Symbol("NOT_CACHED");
|
|
6381
6450
|
FALSE_PENDING_RETRY = Symbol("FALSE_PENDING_RETRY");
|
|
6451
|
+
cachedResult = NOT_CACHED2;
|
|
6382
6452
|
});
|
|
6383
6453
|
// src/shared/load-opencode-plugins.ts
|
|
6384
6454
|
var init_load_opencode_plugins = __esm(() => {
|
|
@@ -6793,19 +6863,19 @@ function normalizeModelID(modelID) {
|
|
|
6793
6863
|
}
|
|
6794
6864
|
|
|
6795
6865
|
// src/shared/json-file-cache-store.ts
|
|
6796
|
-
import { existsSync as
|
|
6797
|
-
import { join as
|
|
6866
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync2, readFileSync as readFileSync2, writeFileSync as writeFileSync2 } from "fs";
|
|
6867
|
+
import { join as join6 } from "path";
|
|
6798
6868
|
function toLogLabel(cacheLabel) {
|
|
6799
6869
|
return cacheLabel.toLowerCase();
|
|
6800
6870
|
}
|
|
6801
6871
|
function createJsonFileCacheStore(options) {
|
|
6802
6872
|
let memoryValue;
|
|
6803
6873
|
function getCacheFilePath() {
|
|
6804
|
-
return
|
|
6874
|
+
return join6(options.getCacheDir(), options.filename);
|
|
6805
6875
|
}
|
|
6806
6876
|
function ensureCacheDir() {
|
|
6807
6877
|
const cacheDir = options.getCacheDir();
|
|
6808
|
-
if (!
|
|
6878
|
+
if (!existsSync4(cacheDir)) {
|
|
6809
6879
|
mkdirSync2(cacheDir, { recursive: true });
|
|
6810
6880
|
}
|
|
6811
6881
|
}
|
|
@@ -6814,7 +6884,7 @@ function createJsonFileCacheStore(options) {
|
|
|
6814
6884
|
return memoryValue;
|
|
6815
6885
|
}
|
|
6816
6886
|
const cacheFile = getCacheFilePath();
|
|
6817
|
-
if (!
|
|
6887
|
+
if (!existsSync4(cacheFile)) {
|
|
6818
6888
|
memoryValue = null;
|
|
6819
6889
|
log(`[${options.logPrefix}] ${options.cacheLabel} file not found`, { cacheFile });
|
|
6820
6890
|
return null;
|
|
@@ -6834,7 +6904,7 @@ function createJsonFileCacheStore(options) {
|
|
|
6834
6904
|
}
|
|
6835
6905
|
}
|
|
6836
6906
|
function has() {
|
|
6837
|
-
return
|
|
6907
|
+
return existsSync4(getCacheFilePath());
|
|
6838
6908
|
}
|
|
6839
6909
|
function write(value) {
|
|
6840
6910
|
ensureCacheDir();
|
|
@@ -7003,14 +7073,14 @@ var init_connected_providers_cache = __esm(() => {
|
|
|
7003
7073
|
});
|
|
7004
7074
|
|
|
7005
7075
|
// src/shared/model-availability.ts
|
|
7006
|
-
import { existsSync as
|
|
7007
|
-
import { join as
|
|
7076
|
+
import { existsSync as existsSync5, readFileSync as readFileSync3 } from "fs";
|
|
7077
|
+
import { join as join7 } from "path";
|
|
7008
7078
|
function isModelCacheAvailable() {
|
|
7009
7079
|
if (hasProviderModelsCache()) {
|
|
7010
7080
|
return true;
|
|
7011
7081
|
}
|
|
7012
|
-
const cacheFile =
|
|
7013
|
-
return
|
|
7082
|
+
const cacheFile = join7(getOpenCodeCacheDir(), "models.json");
|
|
7083
|
+
return existsSync5(cacheFile);
|
|
7014
7084
|
}
|
|
7015
7085
|
var init_model_availability = __esm(() => {
|
|
7016
7086
|
init_logger();
|
|
@@ -48323,17 +48393,43 @@ var init_hook_message_injector = __esm(() => {
|
|
|
48323
48393
|
});
|
|
48324
48394
|
|
|
48325
48395
|
// src/shared/opencode-storage-paths.ts
|
|
48326
|
-
import { join as
|
|
48396
|
+
import { join as join8 } from "path";
|
|
48327
48397
|
var OPENCODE_STORAGE, MESSAGE_STORAGE, PART_STORAGE, SESSION_STORAGE;
|
|
48328
48398
|
var init_opencode_storage_paths = __esm(() => {
|
|
48329
48399
|
init_data_path();
|
|
48330
48400
|
OPENCODE_STORAGE = getOpenCodeStorageDir();
|
|
48331
|
-
MESSAGE_STORAGE =
|
|
48332
|
-
PART_STORAGE =
|
|
48333
|
-
SESSION_STORAGE =
|
|
48401
|
+
MESSAGE_STORAGE = join8(OPENCODE_STORAGE, "message");
|
|
48402
|
+
PART_STORAGE = join8(OPENCODE_STORAGE, "part");
|
|
48403
|
+
SESSION_STORAGE = join8(OPENCODE_STORAGE, "session");
|
|
48334
48404
|
});
|
|
48335
48405
|
|
|
48336
48406
|
// src/shared/opencode-message-dir.ts
|
|
48407
|
+
import { existsSync as existsSync6, readdirSync } from "fs";
|
|
48408
|
+
import { join as join9 } from "path";
|
|
48409
|
+
function getMessageDir(sessionID) {
|
|
48410
|
+
if (!sessionID.startsWith("ses_"))
|
|
48411
|
+
return null;
|
|
48412
|
+
if (/[/\\]|\.\./.test(sessionID))
|
|
48413
|
+
return null;
|
|
48414
|
+
if (!existsSync6(MESSAGE_STORAGE))
|
|
48415
|
+
return null;
|
|
48416
|
+
const directPath = join9(MESSAGE_STORAGE, sessionID);
|
|
48417
|
+
if (existsSync6(directPath)) {
|
|
48418
|
+
return directPath;
|
|
48419
|
+
}
|
|
48420
|
+
try {
|
|
48421
|
+
for (const dir of readdirSync(MESSAGE_STORAGE)) {
|
|
48422
|
+
const sessionPath = join9(MESSAGE_STORAGE, dir, sessionID);
|
|
48423
|
+
if (existsSync6(sessionPath)) {
|
|
48424
|
+
return sessionPath;
|
|
48425
|
+
}
|
|
48426
|
+
}
|
|
48427
|
+
} catch (error) {
|
|
48428
|
+
log("[opencode-message-dir] Failed to scan message directories", { sessionID, error: String(error) });
|
|
48429
|
+
return null;
|
|
48430
|
+
}
|
|
48431
|
+
return null;
|
|
48432
|
+
}
|
|
48337
48433
|
var init_opencode_message_dir = __esm(() => {
|
|
48338
48434
|
init_opencode_storage_paths();
|
|
48339
48435
|
init_logger();
|
|
@@ -48821,10 +48917,10 @@ var init_plugin_name_with_version = __esm(() => {
|
|
|
48821
48917
|
});
|
|
48822
48918
|
|
|
48823
48919
|
// src/cli/config-manager/ensure-config-directory-exists.ts
|
|
48824
|
-
import { existsSync as
|
|
48920
|
+
import { existsSync as existsSync7, mkdirSync as mkdirSync3 } from "fs";
|
|
48825
48921
|
function ensureConfigDirectoryExists() {
|
|
48826
48922
|
const configDir = getConfigDir();
|
|
48827
|
-
if (!
|
|
48923
|
+
if (!existsSync7(configDir)) {
|
|
48828
48924
|
mkdirSync3(configDir, { recursive: true });
|
|
48829
48925
|
}
|
|
48830
48926
|
}
|
|
@@ -48862,14 +48958,14 @@ function formatErrorWithSuggestion(err, context) {
|
|
|
48862
48958
|
}
|
|
48863
48959
|
|
|
48864
48960
|
// src/cli/config-manager/opencode-config-format.ts
|
|
48865
|
-
import { existsSync as
|
|
48961
|
+
import { existsSync as existsSync8 } from "fs";
|
|
48866
48962
|
function detectConfigFormat() {
|
|
48867
48963
|
const configJsonc = getConfigJsonc();
|
|
48868
48964
|
const configJson = getConfigJson();
|
|
48869
|
-
if (
|
|
48965
|
+
if (existsSync8(configJsonc)) {
|
|
48870
48966
|
return { format: "jsonc", path: configJsonc };
|
|
48871
48967
|
}
|
|
48872
|
-
if (
|
|
48968
|
+
if (existsSync8(configJson)) {
|
|
48873
48969
|
return { format: "json", path: configJson };
|
|
48874
48970
|
}
|
|
48875
48971
|
return { format: "none", path: configJson };
|
|
@@ -49220,7 +49316,7 @@ function deepMergeRecord(target, source) {
|
|
|
49220
49316
|
}
|
|
49221
49317
|
|
|
49222
49318
|
// src/cli/config-manager/write-omo-config.ts
|
|
49223
|
-
import { existsSync as
|
|
49319
|
+
import { existsSync as existsSync9, readFileSync as readFileSync6, statSync as statSync2, writeFileSync as writeFileSync4 } from "fs";
|
|
49224
49320
|
function isEmptyOrWhitespace2(content) {
|
|
49225
49321
|
return content.trim().length === 0;
|
|
49226
49322
|
}
|
|
@@ -49237,7 +49333,7 @@ function writeOmoConfig(installConfig) {
|
|
|
49237
49333
|
const omoConfigPath = getOmoConfigPath();
|
|
49238
49334
|
try {
|
|
49239
49335
|
const newConfig = generateOmoConfig(installConfig);
|
|
49240
|
-
if (
|
|
49336
|
+
if (existsSync9(omoConfigPath)) {
|
|
49241
49337
|
try {
|
|
49242
49338
|
const stat = statSync2(omoConfigPath);
|
|
49243
49339
|
const content = readFileSync6(omoConfigPath, "utf-8");
|
|
@@ -49368,7 +49464,7 @@ async function isOpenCodeInstalled() {
|
|
|
49368
49464
|
const result = await findOpenCodeBinaryWithVersion();
|
|
49369
49465
|
return result !== null;
|
|
49370
49466
|
}
|
|
49371
|
-
async function
|
|
49467
|
+
async function getOpenCodeVersion2() {
|
|
49372
49468
|
const result = await findOpenCodeBinaryWithVersion();
|
|
49373
49469
|
return result?.version ?? null;
|
|
49374
49470
|
}
|
|
@@ -49380,10 +49476,10 @@ var init_opencode_binary = __esm(() => {
|
|
|
49380
49476
|
});
|
|
49381
49477
|
|
|
49382
49478
|
// src/cli/config-manager/detect-current-config.ts
|
|
49383
|
-
import { existsSync as
|
|
49479
|
+
import { existsSync as existsSync10, readFileSync as readFileSync7 } from "fs";
|
|
49384
49480
|
function detectProvidersFromOmoConfig() {
|
|
49385
49481
|
const omoConfigPath = getOmoConfigPath();
|
|
49386
|
-
if (!
|
|
49482
|
+
if (!existsSync10(omoConfigPath)) {
|
|
49387
49483
|
return {
|
|
49388
49484
|
hasOpenAI: true,
|
|
49389
49485
|
hasOpencodeZen: true,
|
|
@@ -49469,10 +49565,10 @@ var init_detect_current_config = __esm(() => {
|
|
|
49469
49565
|
});
|
|
49470
49566
|
|
|
49471
49567
|
// src/cli/config-manager/bun-install.ts
|
|
49472
|
-
import { existsSync as
|
|
49473
|
-
import { join as
|
|
49568
|
+
import { existsSync as existsSync11 } from "fs";
|
|
49569
|
+
import { join as join10 } from "path";
|
|
49474
49570
|
function getDefaultWorkspaceDir() {
|
|
49475
|
-
return
|
|
49571
|
+
return join10(getOpenCodeCacheDir(), "packages");
|
|
49476
49572
|
}
|
|
49477
49573
|
function readProcessOutput(stream) {
|
|
49478
49574
|
if (!stream) {
|
|
@@ -49498,7 +49594,7 @@ async function runBunInstallWithDetails(options) {
|
|
|
49498
49594
|
const outputMode = options?.outputMode ?? "pipe";
|
|
49499
49595
|
const cacheDir = options?.workspaceDir ?? getDefaultWorkspaceDir();
|
|
49500
49596
|
const packageJsonPath = `${cacheDir}/package.json`;
|
|
49501
|
-
if (!
|
|
49597
|
+
if (!existsSync11(packageJsonPath)) {
|
|
49502
49598
|
return {
|
|
49503
49599
|
success: false,
|
|
49504
49600
|
error: `Workspace not initialized: ${packageJsonPath} not found. OpenCode should create this on first run.`
|
|
@@ -50197,8 +50293,8 @@ var init_update_toasts = __esm(() => {
|
|
|
50197
50293
|
});
|
|
50198
50294
|
|
|
50199
50295
|
// src/hooks/auto-update-checker/hook/background-update-check.ts
|
|
50200
|
-
import { existsSync as
|
|
50201
|
-
import { join as
|
|
50296
|
+
import { existsSync as existsSync23 } from "fs";
|
|
50297
|
+
import { join as join23 } from "path";
|
|
50202
50298
|
function getCacheWorkspaceDir(deps) {
|
|
50203
50299
|
return deps.join(deps.getOpenCodeCacheDir(), "packages");
|
|
50204
50300
|
}
|
|
@@ -50255,8 +50351,8 @@ function createBackgroundUpdateCheckRunner(overrides = {}) {
|
|
|
50255
50351
|
deps.log("[auto-update-checker] Plugin not found in config");
|
|
50256
50352
|
return;
|
|
50257
50353
|
}
|
|
50258
|
-
const
|
|
50259
|
-
const currentVersion =
|
|
50354
|
+
const cachedVersion2 = deps.getCachedVersion();
|
|
50355
|
+
const currentVersion = cachedVersion2 ?? pluginInfo.pinnedVersion;
|
|
50260
50356
|
if (!currentVersion) {
|
|
50261
50357
|
deps.log("[auto-update-checker] No version found (cached or pinned)");
|
|
50262
50358
|
return;
|
|
@@ -50316,8 +50412,8 @@ var init_background_update_check = __esm(() => {
|
|
|
50316
50412
|
init_checker();
|
|
50317
50413
|
init_update_toasts();
|
|
50318
50414
|
defaultDeps = {
|
|
50319
|
-
existsSync:
|
|
50320
|
-
join:
|
|
50415
|
+
existsSync: existsSync23,
|
|
50416
|
+
join: join23,
|
|
50321
50417
|
runBunInstallWithDetails,
|
|
50322
50418
|
log,
|
|
50323
50419
|
getOpenCodeCacheDir,
|
|
@@ -50526,9 +50622,9 @@ v${latestVersion} available. Restart OpenCode to apply.` : "OpenCode is now on S
|
|
|
50526
50622
|
return;
|
|
50527
50623
|
hasChecked = true;
|
|
50528
50624
|
setTimeout(async () => {
|
|
50529
|
-
const
|
|
50625
|
+
const cachedVersion2 = getCachedVersion();
|
|
50530
50626
|
const localDevVersion = getLocalDevVersion(ctx.directory);
|
|
50531
|
-
const displayVersion = localDevVersion ??
|
|
50627
|
+
const displayVersion = localDevVersion ?? cachedVersion2;
|
|
50532
50628
|
await showConfigErrorsIfAny(ctx);
|
|
50533
50629
|
await updateAndShowConnectedProvidersCacheStatus(ctx);
|
|
50534
50630
|
await refreshModelCapabilitiesOnStartup(modelCapabilities);
|
|
@@ -50597,7 +50693,7 @@ var {
|
|
|
50597
50693
|
// package.json
|
|
50598
50694
|
var package_default = {
|
|
50599
50695
|
name: "oh-my-opencode",
|
|
50600
|
-
version: "3.15.
|
|
50696
|
+
version: "3.15.3",
|
|
50601
50697
|
description: "The Best AI Agent Harness - Batteries-Included OpenCode Plugin with Multi-Model Orchestration, Parallel Background Agents, and Crafted LSP/AST Tools",
|
|
50602
50698
|
main: "./dist/index.js",
|
|
50603
50699
|
types: "dist/index.d.ts",
|
|
@@ -50675,17 +50771,17 @@ var package_default = {
|
|
|
50675
50771
|
typescript: "^5.7.3"
|
|
50676
50772
|
},
|
|
50677
50773
|
optionalDependencies: {
|
|
50678
|
-
"oh-my-opencode-darwin-arm64": "3.15.
|
|
50679
|
-
"oh-my-opencode-darwin-x64": "3.15.
|
|
50680
|
-
"oh-my-opencode-darwin-x64-baseline": "3.15.
|
|
50681
|
-
"oh-my-opencode-linux-arm64": "3.15.
|
|
50682
|
-
"oh-my-opencode-linux-arm64-musl": "3.15.
|
|
50683
|
-
"oh-my-opencode-linux-x64": "3.15.
|
|
50684
|
-
"oh-my-opencode-linux-x64-baseline": "3.15.
|
|
50685
|
-
"oh-my-opencode-linux-x64-musl": "3.15.
|
|
50686
|
-
"oh-my-opencode-linux-x64-musl-baseline": "3.15.
|
|
50687
|
-
"oh-my-opencode-windows-x64": "3.15.
|
|
50688
|
-
"oh-my-opencode-windows-x64-baseline": "3.15.
|
|
50774
|
+
"oh-my-opencode-darwin-arm64": "3.15.3",
|
|
50775
|
+
"oh-my-opencode-darwin-x64": "3.15.3",
|
|
50776
|
+
"oh-my-opencode-darwin-x64-baseline": "3.15.3",
|
|
50777
|
+
"oh-my-opencode-linux-arm64": "3.15.3",
|
|
50778
|
+
"oh-my-opencode-linux-arm64-musl": "3.15.3",
|
|
50779
|
+
"oh-my-opencode-linux-x64": "3.15.3",
|
|
50780
|
+
"oh-my-opencode-linux-x64-baseline": "3.15.3",
|
|
50781
|
+
"oh-my-opencode-linux-x64-musl": "3.15.3",
|
|
50782
|
+
"oh-my-opencode-linux-x64-musl-baseline": "3.15.3",
|
|
50783
|
+
"oh-my-opencode-windows-x64": "3.15.3",
|
|
50784
|
+
"oh-my-opencode-windows-x64-baseline": "3.15.3"
|
|
50689
50785
|
},
|
|
50690
50786
|
overrides: {
|
|
50691
50787
|
"@opencode-ai/sdk": "^1.2.24"
|
|
@@ -50868,7 +50964,7 @@ async function runCliInstaller(args, version) {
|
|
|
50868
50964
|
let step = 1;
|
|
50869
50965
|
printStep(step++, totalSteps, "Checking OpenCode installation...");
|
|
50870
50966
|
const installed = await isOpenCodeInstalled();
|
|
50871
|
-
const openCodeVersion = await
|
|
50967
|
+
const openCodeVersion = await getOpenCodeVersion2();
|
|
50872
50968
|
if (!installed) {
|
|
50873
50969
|
printWarning("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
|
|
50874
50970
|
printInfo("Visit https://opencode.ai/docs for installation instructions");
|
|
@@ -51643,7 +51739,7 @@ async function runTuiInstaller(args, version) {
|
|
|
51643
51739
|
const spinner = Y2();
|
|
51644
51740
|
spinner.start("Checking OpenCode installation");
|
|
51645
51741
|
const installed = await isOpenCodeInstalled();
|
|
51646
|
-
const openCodeVersion = await
|
|
51742
|
+
const openCodeVersion = await getOpenCodeVersion2();
|
|
51647
51743
|
if (!installed) {
|
|
51648
51744
|
spinner.stop(`OpenCode binary not found ${import_picocolors4.default.yellow("[!]")}`);
|
|
51649
51745
|
M2.warn("OpenCode binary not found. Plugin will be configured, but you'll need to install OpenCode to use it.");
|
|
@@ -66488,12 +66584,12 @@ init_shared();
|
|
|
66488
66584
|
// src/shared/migrate-legacy-config-file.ts
|
|
66489
66585
|
init_logger();
|
|
66490
66586
|
init_write_file_atomically();
|
|
66491
|
-
import { existsSync as
|
|
66492
|
-
import { join as
|
|
66587
|
+
import { existsSync as existsSync12, readFileSync as readFileSync8, renameSync as renameSync2, rmSync } from "fs";
|
|
66588
|
+
import { join as join11, dirname, basename } from "path";
|
|
66493
66589
|
function buildCanonicalPath(legacyPath) {
|
|
66494
66590
|
const dir = dirname(legacyPath);
|
|
66495
66591
|
const ext = basename(legacyPath).includes(".jsonc") ? ".jsonc" : ".json";
|
|
66496
|
-
return
|
|
66592
|
+
return join11(dir, `${CONFIG_BASENAME}${ext}`);
|
|
66497
66593
|
}
|
|
66498
66594
|
function archiveLegacyConfigFile(legacyPath) {
|
|
66499
66595
|
const backupPath = `${legacyPath}.bak`;
|
|
@@ -66525,12 +66621,12 @@ function archiveLegacyConfigFile(legacyPath) {
|
|
|
66525
66621
|
}
|
|
66526
66622
|
}
|
|
66527
66623
|
function migrateLegacyConfigFile(legacyPath) {
|
|
66528
|
-
if (!
|
|
66624
|
+
if (!existsSync12(legacyPath))
|
|
66529
66625
|
return false;
|
|
66530
66626
|
if (!basename(legacyPath).startsWith(LEGACY_CONFIG_BASENAME))
|
|
66531
66627
|
return false;
|
|
66532
66628
|
const canonicalPath = buildCanonicalPath(legacyPath);
|
|
66533
|
-
if (
|
|
66629
|
+
if (existsSync12(canonicalPath))
|
|
66534
66630
|
return false;
|
|
66535
66631
|
try {
|
|
66536
66632
|
const content = readFileSync8(legacyPath, "utf-8");
|
|
@@ -68173,7 +68269,7 @@ var import_picocolors9 = __toESM(require_picocolors(), 1);
|
|
|
68173
68269
|
|
|
68174
68270
|
// src/cli/run/opencode-binary-resolver.ts
|
|
68175
68271
|
init_spawn_with_windows_hide();
|
|
68176
|
-
import { delimiter, dirname as dirname3, join as
|
|
68272
|
+
import { delimiter, dirname as dirname3, join as join13 } from "path";
|
|
68177
68273
|
var OPENCODE_COMMANDS = ["opencode", "opencode-desktop"];
|
|
68178
68274
|
var WINDOWS_SUFFIXES = ["", ".exe", ".cmd", ".bat", ".ps1"];
|
|
68179
68275
|
function getCommandCandidates(platform) {
|
|
@@ -68196,7 +68292,7 @@ function collectCandidateBinaryPaths(pathEnv, which = Bun.which, platform = proc
|
|
|
68196
68292
|
}
|
|
68197
68293
|
for (const entry of (pathEnv ?? "").split(delimiter).filter(Boolean)) {
|
|
68198
68294
|
for (const command of commandCandidates) {
|
|
68199
|
-
addCandidate(
|
|
68295
|
+
addCandidate(join13(entry, command));
|
|
68200
68296
|
}
|
|
68201
68297
|
}
|
|
68202
68298
|
return candidates;
|
|
@@ -68579,15 +68675,15 @@ var BOULDER_STATE_PATH = `${BOULDER_DIR}/${BOULDER_FILE}`;
|
|
|
68579
68675
|
var NOTEPAD_DIR = "notepads";
|
|
68580
68676
|
var NOTEPAD_BASE_PATH = `${BOULDER_DIR}/${NOTEPAD_DIR}`;
|
|
68581
68677
|
// src/features/boulder-state/storage.ts
|
|
68582
|
-
import { existsSync as
|
|
68583
|
-
import { dirname as dirname4, join as
|
|
68678
|
+
import { existsSync as existsSync14, readFileSync as readFileSync10, writeFileSync as writeFileSync5, mkdirSync as mkdirSync4, readdirSync as readdirSync2 } from "fs";
|
|
68679
|
+
import { dirname as dirname4, join as join14, basename as basename3 } from "path";
|
|
68584
68680
|
var RESERVED_KEYS = new Set(["__proto__", "prototype", "constructor"]);
|
|
68585
68681
|
function getBoulderFilePath(directory) {
|
|
68586
|
-
return
|
|
68682
|
+
return join14(directory, BOULDER_DIR, BOULDER_FILE);
|
|
68587
68683
|
}
|
|
68588
68684
|
function readBoulderState(directory) {
|
|
68589
68685
|
const filePath = getBoulderFilePath(directory);
|
|
68590
|
-
if (!
|
|
68686
|
+
if (!existsSync14(filePath)) {
|
|
68591
68687
|
return null;
|
|
68592
68688
|
}
|
|
68593
68689
|
try {
|
|
@@ -68599,6 +68695,15 @@ function readBoulderState(directory) {
|
|
|
68599
68695
|
if (!Array.isArray(parsed.session_ids)) {
|
|
68600
68696
|
parsed.session_ids = [];
|
|
68601
68697
|
}
|
|
68698
|
+
if (!parsed.session_origins || typeof parsed.session_origins !== "object" || Array.isArray(parsed.session_origins)) {
|
|
68699
|
+
parsed.session_origins = {};
|
|
68700
|
+
}
|
|
68701
|
+
if (parsed.session_ids.length === 1) {
|
|
68702
|
+
const soleSessionId = parsed.session_ids[0];
|
|
68703
|
+
if (typeof soleSessionId === "string" && parsed.session_origins[soleSessionId] !== "appended" && parsed.session_origins[soleSessionId] !== "direct") {
|
|
68704
|
+
parsed.session_origins[soleSessionId] = "direct";
|
|
68705
|
+
}
|
|
68706
|
+
}
|
|
68602
68707
|
if (!parsed.task_sessions || typeof parsed.task_sessions !== "object" || Array.isArray(parsed.task_sessions)) {
|
|
68603
68708
|
parsed.task_sessions = {};
|
|
68604
68709
|
}
|
|
@@ -68608,7 +68713,7 @@ function readBoulderState(directory) {
|
|
|
68608
68713
|
}
|
|
68609
68714
|
}
|
|
68610
68715
|
function getPlanProgress(planPath) {
|
|
68611
|
-
if (!
|
|
68716
|
+
if (!existsSync14(planPath)) {
|
|
68612
68717
|
return { total: 0, completed: 0, isComplete: true };
|
|
68613
68718
|
}
|
|
68614
68719
|
try {
|
|
@@ -68626,17 +68731,26 @@ function getPlanProgress(planPath) {
|
|
|
68626
68731
|
return { total: 0, completed: 0, isComplete: true };
|
|
68627
68732
|
}
|
|
68628
68733
|
}
|
|
68734
|
+
// src/features/claude-code-session-state/state.ts
|
|
68735
|
+
init_agent_display_names();
|
|
68736
|
+
var subagentSessions = new Set;
|
|
68737
|
+
var syncSubagentSessions = new Set;
|
|
68738
|
+
var registeredAgentNames = new Set;
|
|
68739
|
+
var sessionAgentMap = new Map;
|
|
68740
|
+
function getSessionAgent(sessionID) {
|
|
68741
|
+
return sessionAgentMap.get(sessionID);
|
|
68742
|
+
}
|
|
68629
68743
|
// src/features/run-continuation-state/constants.ts
|
|
68630
68744
|
var CONTINUATION_MARKER_DIR = ".sisyphus/run-continuation";
|
|
68631
68745
|
// src/features/run-continuation-state/storage.ts
|
|
68632
|
-
import { existsSync as
|
|
68633
|
-
import { join as
|
|
68746
|
+
import { existsSync as existsSync15, mkdirSync as mkdirSync5, readFileSync as readFileSync11, rmSync as rmSync2, writeFileSync as writeFileSync6 } from "fs";
|
|
68747
|
+
import { join as join15 } from "path";
|
|
68634
68748
|
function getMarkerPath(directory, sessionID) {
|
|
68635
|
-
return
|
|
68749
|
+
return join15(directory, CONTINUATION_MARKER_DIR, `${sessionID}.json`);
|
|
68636
68750
|
}
|
|
68637
68751
|
function readContinuationMarker(directory, sessionID) {
|
|
68638
68752
|
const markerPath = getMarkerPath(directory, sessionID);
|
|
68639
|
-
if (!
|
|
68753
|
+
if (!existsSync15(markerPath))
|
|
68640
68754
|
return null;
|
|
68641
68755
|
try {
|
|
68642
68756
|
const raw = readFileSync11(markerPath, "utf-8");
|
|
@@ -68662,10 +68776,113 @@ function getActiveContinuationMarkerReason(marker) {
|
|
|
68662
68776
|
const [source, entry] = active;
|
|
68663
68777
|
return entry.reason ?? `${source} continuation is active`;
|
|
68664
68778
|
}
|
|
68779
|
+
// src/hooks/atlas/boulder-session-lineage.ts
|
|
68780
|
+
init_logger();
|
|
68781
|
+
|
|
68782
|
+
// src/hooks/atlas/hook-name.ts
|
|
68783
|
+
var HOOK_NAME = "atlas";
|
|
68784
|
+
|
|
68785
|
+
// src/hooks/atlas/boulder-session-lineage.ts
|
|
68786
|
+
async function isSessionInBoulderLineage(input) {
|
|
68787
|
+
const visitedSessionIDs = new Set;
|
|
68788
|
+
let currentSessionID = input.sessionID;
|
|
68789
|
+
while (!visitedSessionIDs.has(currentSessionID)) {
|
|
68790
|
+
visitedSessionIDs.add(currentSessionID);
|
|
68791
|
+
const sessionResult = await input.client.session.get({ path: { id: currentSessionID } }).catch((error48) => {
|
|
68792
|
+
log(`[${HOOK_NAME}] Failed to resolve session lineage`, {
|
|
68793
|
+
sessionID: input.sessionID,
|
|
68794
|
+
currentSessionID,
|
|
68795
|
+
error: error48
|
|
68796
|
+
});
|
|
68797
|
+
return null;
|
|
68798
|
+
});
|
|
68799
|
+
if (!sessionResult || sessionResult.error) {
|
|
68800
|
+
return false;
|
|
68801
|
+
}
|
|
68802
|
+
const parentSessionID = sessionResult.data?.parentID;
|
|
68803
|
+
if (!parentSessionID) {
|
|
68804
|
+
return false;
|
|
68805
|
+
}
|
|
68806
|
+
if (input.boulderSessionIDs.includes(parentSessionID)) {
|
|
68807
|
+
return true;
|
|
68808
|
+
}
|
|
68809
|
+
currentSessionID = parentSessionID;
|
|
68810
|
+
}
|
|
68811
|
+
return false;
|
|
68812
|
+
}
|
|
68813
|
+
|
|
68814
|
+
// src/hooks/atlas/session-last-agent.ts
|
|
68815
|
+
init_shared();
|
|
68816
|
+
import { readFileSync as readFileSync12, readdirSync as readdirSync3 } from "fs";
|
|
68817
|
+
import { join as join16 } from "path";
|
|
68818
|
+
function isCompactionAgent(agent) {
|
|
68819
|
+
return typeof agent === "string" && agent.toLowerCase() === "compaction";
|
|
68820
|
+
}
|
|
68821
|
+
function getLastAgentFromMessageDir(messageDir) {
|
|
68822
|
+
try {
|
|
68823
|
+
const messages = readdirSync3(messageDir).filter((fileName) => fileName.endsWith(".json")).map((fileName) => {
|
|
68824
|
+
try {
|
|
68825
|
+
const content = readFileSync12(join16(messageDir, fileName), "utf-8");
|
|
68826
|
+
const parsed = JSON.parse(content);
|
|
68827
|
+
return {
|
|
68828
|
+
fileName,
|
|
68829
|
+
agent: parsed.agent,
|
|
68830
|
+
createdAt: typeof parsed.time?.created === "number" ? parsed.time.created : Number.NEGATIVE_INFINITY
|
|
68831
|
+
};
|
|
68832
|
+
} catch {
|
|
68833
|
+
return null;
|
|
68834
|
+
}
|
|
68835
|
+
}).filter((message) => message !== null).sort((left, right) => right.createdAt - left.createdAt || right.fileName.localeCompare(left.fileName));
|
|
68836
|
+
for (const message of messages) {
|
|
68837
|
+
if (typeof message.agent === "string" && !isCompactionAgent(message.agent)) {
|
|
68838
|
+
return message.agent.toLowerCase();
|
|
68839
|
+
}
|
|
68840
|
+
}
|
|
68841
|
+
} catch {
|
|
68842
|
+
return null;
|
|
68843
|
+
}
|
|
68844
|
+
return null;
|
|
68845
|
+
}
|
|
68846
|
+
async function getLastAgentFromSession(sessionID, client3) {
|
|
68847
|
+
if (isSqliteBackend() && client3) {
|
|
68848
|
+
try {
|
|
68849
|
+
const response = await client3.session.messages({ path: { id: sessionID } });
|
|
68850
|
+
const messages = normalizeSDKResponse(response, [], {
|
|
68851
|
+
preferResponseOnMissingData: true
|
|
68852
|
+
}).sort((left, right) => {
|
|
68853
|
+
const leftTime = left.info?.time?.created ?? Number.NEGATIVE_INFINITY;
|
|
68854
|
+
const rightTime = right.info?.time?.created ?? Number.NEGATIVE_INFINITY;
|
|
68855
|
+
if (leftTime !== rightTime) {
|
|
68856
|
+
return rightTime - leftTime;
|
|
68857
|
+
}
|
|
68858
|
+
const leftId = typeof left.id === "string" ? left.id : "";
|
|
68859
|
+
const rightId = typeof right.id === "string" ? right.id : "";
|
|
68860
|
+
return rightId.localeCompare(leftId);
|
|
68861
|
+
});
|
|
68862
|
+
for (const message of messages) {
|
|
68863
|
+
const agent = message.info?.agent;
|
|
68864
|
+
if (typeof agent === "string" && !isCompactionAgent(agent)) {
|
|
68865
|
+
return agent.toLowerCase();
|
|
68866
|
+
}
|
|
68867
|
+
}
|
|
68868
|
+
} catch {
|
|
68869
|
+
return null;
|
|
68870
|
+
}
|
|
68871
|
+
return null;
|
|
68872
|
+
}
|
|
68873
|
+
const messageDir = getMessageDir(sessionID);
|
|
68874
|
+
if (!messageDir)
|
|
68875
|
+
return null;
|
|
68876
|
+
return getLastAgentFromMessageDir(messageDir);
|
|
68877
|
+
}
|
|
68878
|
+
|
|
68879
|
+
// src/cli/run/continuation-state.ts
|
|
68880
|
+
init_agent_display_names();
|
|
68881
|
+
|
|
68665
68882
|
// src/hooks/ralph-loop/storage.ts
|
|
68666
68883
|
init_frontmatter();
|
|
68667
|
-
import { existsSync as
|
|
68668
|
-
import { dirname as dirname5, join as
|
|
68884
|
+
import { existsSync as existsSync16, readFileSync as readFileSync13, writeFileSync as writeFileSync7, unlinkSync, mkdirSync as mkdirSync6 } from "fs";
|
|
68885
|
+
import { dirname as dirname5, join as join17 } from "path";
|
|
68669
68886
|
|
|
68670
68887
|
// src/hooks/ralph-loop/constants.ts
|
|
68671
68888
|
var DEFAULT_STATE_FILE = ".sisyphus/ralph-loop.local.md";
|
|
@@ -68674,15 +68891,15 @@ var DEFAULT_COMPLETION_PROMISE = "DONE";
|
|
|
68674
68891
|
|
|
68675
68892
|
// src/hooks/ralph-loop/storage.ts
|
|
68676
68893
|
function getStateFilePath(directory, customPath) {
|
|
68677
|
-
return customPath ?
|
|
68894
|
+
return customPath ? join17(directory, customPath) : join17(directory, DEFAULT_STATE_FILE);
|
|
68678
68895
|
}
|
|
68679
68896
|
function readState(directory, customPath) {
|
|
68680
68897
|
const filePath = getStateFilePath(directory, customPath);
|
|
68681
|
-
if (!
|
|
68898
|
+
if (!existsSync16(filePath)) {
|
|
68682
68899
|
return null;
|
|
68683
68900
|
}
|
|
68684
68901
|
try {
|
|
68685
|
-
const content =
|
|
68902
|
+
const content = readFileSync13(filePath, "utf-8");
|
|
68686
68903
|
const { data, body } = parseFrontmatter(content);
|
|
68687
68904
|
const active = data.active;
|
|
68688
68905
|
const iteration = data.iteration;
|
|
@@ -68722,10 +68939,10 @@ function readState(directory, customPath) {
|
|
|
68722
68939
|
}
|
|
68723
68940
|
|
|
68724
68941
|
// src/cli/run/continuation-state.ts
|
|
68725
|
-
function getContinuationState(directory, sessionID) {
|
|
68942
|
+
async function getContinuationState(directory, sessionID, client3) {
|
|
68726
68943
|
const marker = readContinuationMarker(directory, sessionID);
|
|
68727
68944
|
return {
|
|
68728
|
-
hasActiveBoulder: hasActiveBoulderContinuation(directory, sessionID),
|
|
68945
|
+
hasActiveBoulder: await hasActiveBoulderContinuation(directory, sessionID, client3),
|
|
68729
68946
|
hasActiveRalphLoop: hasActiveRalphLoopContinuation(directory, sessionID),
|
|
68730
68947
|
hasHookMarker: marker !== null,
|
|
68731
68948
|
hasTodoHookMarker: marker?.sources.todo !== undefined,
|
|
@@ -68733,20 +68950,54 @@ function getContinuationState(directory, sessionID) {
|
|
|
68733
68950
|
activeHookMarkerReason: getActiveContinuationMarkerReason(marker)
|
|
68734
68951
|
};
|
|
68735
68952
|
}
|
|
68736
|
-
function hasActiveBoulderContinuation(directory, sessionID) {
|
|
68953
|
+
async function hasActiveBoulderContinuation(directory, sessionID, client3) {
|
|
68737
68954
|
const boulder = readBoulderState(directory);
|
|
68738
68955
|
if (!boulder)
|
|
68739
68956
|
return false;
|
|
68740
|
-
if (!boulder.session_ids.includes(sessionID))
|
|
68741
|
-
return false;
|
|
68742
68957
|
const progress = getPlanProgress(boulder.active_plan);
|
|
68743
|
-
|
|
68958
|
+
if (progress.isComplete)
|
|
68959
|
+
return false;
|
|
68960
|
+
if (!client3)
|
|
68961
|
+
return false;
|
|
68962
|
+
const isTrackedSession = boulder.session_ids.includes(sessionID);
|
|
68963
|
+
const sessionOrigin = boulder.session_origins?.[sessionID];
|
|
68964
|
+
if (!isTrackedSession) {
|
|
68965
|
+
return false;
|
|
68966
|
+
}
|
|
68967
|
+
const isTrackedDescendant = await isTrackedDescendantSession(client3, sessionID, boulder.session_ids);
|
|
68968
|
+
if (isTrackedSession && sessionOrigin === "direct") {
|
|
68969
|
+
return true;
|
|
68970
|
+
}
|
|
68971
|
+
if (isTrackedSession && sessionOrigin !== "direct" && !isTrackedDescendant) {
|
|
68972
|
+
return false;
|
|
68973
|
+
}
|
|
68974
|
+
const sessionAgent = await getLastAgentFromSession(sessionID, client3) ?? getSessionAgent(sessionID);
|
|
68975
|
+
if (!sessionAgent) {
|
|
68976
|
+
return false;
|
|
68977
|
+
}
|
|
68978
|
+
const requiredAgentKey = getAgentConfigKey(boulder.agent ?? "atlas");
|
|
68979
|
+
const sessionAgentKey = getAgentConfigKey(sessionAgent);
|
|
68980
|
+
if (sessionAgentKey !== requiredAgentKey && !(requiredAgentKey === getAgentConfigKey("atlas") && sessionAgentKey === getAgentConfigKey("sisyphus"))) {
|
|
68981
|
+
return false;
|
|
68982
|
+
}
|
|
68983
|
+
return isTrackedSession || isTrackedDescendant;
|
|
68984
|
+
}
|
|
68985
|
+
async function isTrackedDescendantSession(client3, sessionID, trackedSessionIDs) {
|
|
68986
|
+
const ancestorSessionIDs = trackedSessionIDs.filter((trackedSessionID) => trackedSessionID !== sessionID);
|
|
68987
|
+
if (ancestorSessionIDs.length === 0) {
|
|
68988
|
+
return false;
|
|
68989
|
+
}
|
|
68990
|
+
return isSessionInBoulderLineage({
|
|
68991
|
+
client: client3,
|
|
68992
|
+
sessionID,
|
|
68993
|
+
boulderSessionIDs: ancestorSessionIDs
|
|
68994
|
+
});
|
|
68744
68995
|
}
|
|
68745
68996
|
function hasActiveRalphLoopContinuation(directory, sessionID) {
|
|
68746
|
-
const
|
|
68747
|
-
if (!
|
|
68997
|
+
const state2 = readState(directory);
|
|
68998
|
+
if (!state2 || !state2.active)
|
|
68748
68999
|
return false;
|
|
68749
|
-
if (
|
|
69000
|
+
if (state2.session_id && state2.session_id !== sessionID) {
|
|
68750
69001
|
return false;
|
|
68751
69002
|
}
|
|
68752
69003
|
return true;
|
|
@@ -68755,7 +69006,7 @@ function hasActiveRalphLoopContinuation(directory, sessionID) {
|
|
|
68755
69006
|
// src/cli/run/completion.ts
|
|
68756
69007
|
async function checkCompletionConditions(ctx) {
|
|
68757
69008
|
try {
|
|
68758
|
-
const continuationState = getContinuationState(ctx.directory, ctx.sessionID);
|
|
69009
|
+
const continuationState = await getContinuationState(ctx.directory, ctx.sessionID, ctx.client);
|
|
68759
69010
|
if (continuationState.hasActiveHookMarker) {
|
|
68760
69011
|
const reason = continuationState.activeHookMarkerReason ?? "continuation hook is active";
|
|
68761
69012
|
logWaiting(ctx, reason);
|
|
@@ -69388,30 +69639,30 @@ var PACKAGE_NAME2 = PLUGIN_NAME;
|
|
|
69388
69639
|
var OPENCODE_BINARIES2 = ["opencode", "opencode-desktop"];
|
|
69389
69640
|
|
|
69390
69641
|
// src/cli/doctor/checks/system.ts
|
|
69391
|
-
import { existsSync as
|
|
69642
|
+
import { existsSync as existsSync27, readFileSync as readFileSync23 } from "fs";
|
|
69392
69643
|
|
|
69393
69644
|
// src/cli/doctor/checks/system-binary.ts
|
|
69394
69645
|
init_spawn_with_windows_hide();
|
|
69395
|
-
import { existsSync as
|
|
69646
|
+
import { existsSync as existsSync24 } from "fs";
|
|
69396
69647
|
import { homedir as homedir5 } from "os";
|
|
69397
|
-
import { join as
|
|
69648
|
+
import { join as join24 } from "path";
|
|
69398
69649
|
function getDesktopAppPaths(platform) {
|
|
69399
69650
|
const home = homedir5();
|
|
69400
69651
|
switch (platform) {
|
|
69401
69652
|
case "darwin":
|
|
69402
69653
|
return [
|
|
69403
69654
|
"/Applications/OpenCode.app/Contents/MacOS/OpenCode",
|
|
69404
|
-
|
|
69655
|
+
join24(home, "Applications", "OpenCode.app", "Contents", "MacOS", "OpenCode")
|
|
69405
69656
|
];
|
|
69406
69657
|
case "win32": {
|
|
69407
69658
|
const programFiles = process.env.ProgramFiles;
|
|
69408
69659
|
const localAppData = process.env.LOCALAPPDATA;
|
|
69409
69660
|
const paths = [];
|
|
69410
69661
|
if (programFiles) {
|
|
69411
|
-
paths.push(
|
|
69662
|
+
paths.push(join24(programFiles, "OpenCode", "OpenCode.exe"));
|
|
69412
69663
|
}
|
|
69413
69664
|
if (localAppData) {
|
|
69414
|
-
paths.push(
|
|
69665
|
+
paths.push(join24(localAppData, "OpenCode", "OpenCode.exe"));
|
|
69415
69666
|
}
|
|
69416
69667
|
return paths;
|
|
69417
69668
|
}
|
|
@@ -69419,8 +69670,8 @@ function getDesktopAppPaths(platform) {
|
|
|
69419
69670
|
return [
|
|
69420
69671
|
"/usr/bin/opencode",
|
|
69421
69672
|
"/usr/lib/opencode/opencode",
|
|
69422
|
-
|
|
69423
|
-
|
|
69673
|
+
join24(home, "Applications", "opencode-desktop-linux-x86_64.AppImage"),
|
|
69674
|
+
join24(home, "Applications", "opencode-desktop-linux-aarch64.AppImage")
|
|
69424
69675
|
];
|
|
69425
69676
|
default:
|
|
69426
69677
|
return [];
|
|
@@ -69432,7 +69683,7 @@ function buildVersionCommand(binaryPath, platform) {
|
|
|
69432
69683
|
}
|
|
69433
69684
|
return [binaryPath, "--version"];
|
|
69434
69685
|
}
|
|
69435
|
-
function findDesktopBinary(platform = process.platform, checkExists =
|
|
69686
|
+
function findDesktopBinary(platform = process.platform, checkExists = existsSync24) {
|
|
69436
69687
|
for (const desktopPath of getDesktopAppPaths(platform)) {
|
|
69437
69688
|
if (checkExists(desktopPath)) {
|
|
69438
69689
|
return { binary: "opencode", path: desktopPath };
|
|
@@ -69449,7 +69700,7 @@ async function findOpenCodeBinary() {
|
|
|
69449
69700
|
}
|
|
69450
69701
|
return findDesktopBinary();
|
|
69451
69702
|
}
|
|
69452
|
-
async function
|
|
69703
|
+
async function getOpenCodeVersion3(binaryPath, platform = process.platform) {
|
|
69453
69704
|
try {
|
|
69454
69705
|
const command = buildVersionCommand(binaryPath, platform);
|
|
69455
69706
|
const processResult = spawnWithWindowsHide(command, { stdout: "pipe", stderr: "pipe" });
|
|
@@ -69462,10 +69713,10 @@ async function getOpenCodeVersion2(binaryPath, platform = process.platform) {
|
|
|
69462
69713
|
return null;
|
|
69463
69714
|
}
|
|
69464
69715
|
}
|
|
69465
|
-
function
|
|
69466
|
-
const
|
|
69467
|
-
const currentParts =
|
|
69468
|
-
const minimumParts =
|
|
69716
|
+
function compareVersions2(current, minimum) {
|
|
69717
|
+
const parseVersion2 = (version2) => version2.replace(/^v/, "").split("-")[0].split(".").map((part) => Number.parseInt(part, 10) || 0);
|
|
69718
|
+
const currentParts = parseVersion2(current);
|
|
69719
|
+
const minimumParts = parseVersion2(minimum);
|
|
69469
69720
|
const length = Math.max(currentParts.length, minimumParts.length);
|
|
69470
69721
|
for (let index = 0;index < length; index++) {
|
|
69471
69722
|
const currentPart = currentParts[index] ?? 0;
|
|
@@ -69480,12 +69731,12 @@ function compareVersions(current, minimum) {
|
|
|
69480
69731
|
|
|
69481
69732
|
// src/cli/doctor/checks/system-plugin.ts
|
|
69482
69733
|
init_shared();
|
|
69483
|
-
import { existsSync as
|
|
69734
|
+
import { existsSync as existsSync25, readFileSync as readFileSync21 } from "fs";
|
|
69484
69735
|
function detectConfigPath() {
|
|
69485
69736
|
const paths = getOpenCodeConfigPaths({ binary: "opencode", version: null });
|
|
69486
|
-
if (
|
|
69737
|
+
if (existsSync25(paths.configJsonc))
|
|
69487
69738
|
return paths.configJsonc;
|
|
69488
|
-
if (
|
|
69739
|
+
if (existsSync25(paths.configJson))
|
|
69489
69740
|
return paths.configJson;
|
|
69490
69741
|
return null;
|
|
69491
69742
|
}
|
|
@@ -69531,7 +69782,7 @@ function getPluginInfo() {
|
|
|
69531
69782
|
};
|
|
69532
69783
|
}
|
|
69533
69784
|
try {
|
|
69534
|
-
const content =
|
|
69785
|
+
const content = readFileSync21(configPath, "utf-8");
|
|
69535
69786
|
const parsedConfig = parseJsonc(content);
|
|
69536
69787
|
const pluginEntry = findPluginEntry2(parsedConfig.plugin ?? []);
|
|
69537
69788
|
if (!pluginEntry) {
|
|
@@ -69569,37 +69820,37 @@ function getPluginInfo() {
|
|
|
69569
69820
|
init_file_utils();
|
|
69570
69821
|
init_checker();
|
|
69571
69822
|
init_auto_update_checker();
|
|
69572
|
-
import { existsSync as
|
|
69823
|
+
import { existsSync as existsSync26, readFileSync as readFileSync22 } from "fs";
|
|
69573
69824
|
import { homedir as homedir6 } from "os";
|
|
69574
|
-
import { join as
|
|
69825
|
+
import { join as join25 } from "path";
|
|
69575
69826
|
init_shared();
|
|
69576
69827
|
function getPlatformDefaultCacheDir(platform = process.platform) {
|
|
69577
69828
|
if (platform === "darwin")
|
|
69578
|
-
return
|
|
69829
|
+
return join25(homedir6(), "Library", "Caches");
|
|
69579
69830
|
if (platform === "win32")
|
|
69580
|
-
return process.env.LOCALAPPDATA ??
|
|
69581
|
-
return
|
|
69831
|
+
return process.env.LOCALAPPDATA ?? join25(homedir6(), "AppData", "Local");
|
|
69832
|
+
return join25(homedir6(), ".cache");
|
|
69582
69833
|
}
|
|
69583
69834
|
function resolveOpenCodeCacheDir() {
|
|
69584
69835
|
const xdgCacheHome = process.env.XDG_CACHE_HOME;
|
|
69585
69836
|
if (xdgCacheHome)
|
|
69586
|
-
return
|
|
69837
|
+
return join25(xdgCacheHome, "opencode");
|
|
69587
69838
|
const fromShared = getOpenCodeCacheDir();
|
|
69588
|
-
const platformDefault =
|
|
69589
|
-
if (
|
|
69839
|
+
const platformDefault = join25(getPlatformDefaultCacheDir(), "opencode");
|
|
69840
|
+
if (existsSync26(fromShared) || !existsSync26(platformDefault))
|
|
69590
69841
|
return fromShared;
|
|
69591
69842
|
return platformDefault;
|
|
69592
69843
|
}
|
|
69593
69844
|
function resolveExistingDir(dirPath) {
|
|
69594
|
-
if (!
|
|
69845
|
+
if (!existsSync26(dirPath))
|
|
69595
69846
|
return dirPath;
|
|
69596
69847
|
return resolveSymlink(dirPath);
|
|
69597
69848
|
}
|
|
69598
69849
|
function readPackageJson(filePath) {
|
|
69599
|
-
if (!
|
|
69850
|
+
if (!existsSync26(filePath))
|
|
69600
69851
|
return null;
|
|
69601
69852
|
try {
|
|
69602
|
-
const content =
|
|
69853
|
+
const content = readFileSync22(filePath, "utf-8");
|
|
69603
69854
|
return parseJsonc(content);
|
|
69604
69855
|
} catch {
|
|
69605
69856
|
return null;
|
|
@@ -69618,16 +69869,16 @@ function getLoadedPluginVersion() {
|
|
|
69618
69869
|
const candidates = [
|
|
69619
69870
|
{
|
|
69620
69871
|
cacheDir: configDir,
|
|
69621
|
-
cachePackagePath:
|
|
69622
|
-
installedPackagePath:
|
|
69872
|
+
cachePackagePath: join25(configDir, "package.json"),
|
|
69873
|
+
installedPackagePath: join25(configDir, "node_modules", PACKAGE_NAME2, "package.json")
|
|
69623
69874
|
},
|
|
69624
69875
|
{
|
|
69625
69876
|
cacheDir,
|
|
69626
|
-
cachePackagePath:
|
|
69627
|
-
installedPackagePath:
|
|
69877
|
+
cachePackagePath: join25(cacheDir, "package.json"),
|
|
69878
|
+
installedPackagePath: join25(cacheDir, "node_modules", PACKAGE_NAME2, "package.json")
|
|
69628
69879
|
}
|
|
69629
69880
|
];
|
|
69630
|
-
const selectedCandidate = candidates.find((candidate) =>
|
|
69881
|
+
const selectedCandidate = candidates.find((candidate) => existsSync26(candidate.installedPackagePath)) ?? candidates[0];
|
|
69631
69882
|
const { cacheDir: selectedDir, cachePackagePath, installedPackagePath } = selectedCandidate;
|
|
69632
69883
|
const cachePackage = readPackageJson(cachePackagePath);
|
|
69633
69884
|
const installedPackage = readPackageJson(installedPackagePath);
|
|
@@ -69654,10 +69905,10 @@ init_shared();
|
|
|
69654
69905
|
function isConfigValid(configPath) {
|
|
69655
69906
|
if (!configPath)
|
|
69656
69907
|
return true;
|
|
69657
|
-
if (!
|
|
69908
|
+
if (!existsSync27(configPath))
|
|
69658
69909
|
return false;
|
|
69659
69910
|
try {
|
|
69660
|
-
parseJsonc(
|
|
69911
|
+
parseJsonc(readFileSync23(configPath, "utf-8"));
|
|
69661
69912
|
return true;
|
|
69662
69913
|
} catch {
|
|
69663
69914
|
return false;
|
|
@@ -69680,7 +69931,7 @@ function buildMessage(status, issues) {
|
|
|
69680
69931
|
async function gatherSystemInfo() {
|
|
69681
69932
|
const [binaryInfo, pluginInfo] = await Promise.all([findOpenCodeBinary(), Promise.resolve(getPluginInfo())]);
|
|
69682
69933
|
const loadedInfo = getLoadedPluginVersion();
|
|
69683
|
-
const opencodeVersion = binaryInfo ? await
|
|
69934
|
+
const opencodeVersion = binaryInfo ? await getOpenCodeVersion3(binaryInfo.path) : null;
|
|
69684
69935
|
const pluginVersion = pluginInfo.pinnedVersion ?? loadedInfo.expectedVersion ?? loadedInfo.loadedVersion;
|
|
69685
69936
|
return {
|
|
69686
69937
|
opencodeVersion,
|
|
@@ -69708,7 +69959,7 @@ async function checkSystem() {
|
|
|
69708
69959
|
affects: ["doctor", "run"]
|
|
69709
69960
|
});
|
|
69710
69961
|
}
|
|
69711
|
-
if (systemInfo.opencodeVersion && !
|
|
69962
|
+
if (systemInfo.opencodeVersion && !compareVersions2(systemInfo.opencodeVersion, MIN_OPENCODE_VERSION)) {
|
|
69712
69963
|
issues.push({
|
|
69713
69964
|
title: "OpenCode version below minimum",
|
|
69714
69965
|
description: `Detected ${systemInfo.opencodeVersion}; required >= ${MIN_OPENCODE_VERSION}.`,
|
|
@@ -69748,7 +69999,7 @@ async function checkSystem() {
|
|
|
69748
69999
|
affects: ["plugin loading"]
|
|
69749
70000
|
});
|
|
69750
70001
|
}
|
|
69751
|
-
if (systemInfo.loadedVersion && latestVersion && !
|
|
70002
|
+
if (systemInfo.loadedVersion && latestVersion && !compareVersions2(systemInfo.loadedVersion, latestVersion)) {
|
|
69752
70003
|
issues.push({
|
|
69753
70004
|
title: "Loaded plugin is outdated",
|
|
69754
70005
|
description: `Loaded ${systemInfo.loadedVersion}, latest ${latestVersion}.`,
|
|
@@ -69773,28 +70024,28 @@ async function checkSystem() {
|
|
|
69773
70024
|
}
|
|
69774
70025
|
|
|
69775
70026
|
// src/cli/doctor/checks/config.ts
|
|
69776
|
-
import { readFileSync as
|
|
69777
|
-
import { join as
|
|
70027
|
+
import { readFileSync as readFileSync26 } from "fs";
|
|
70028
|
+
import { join as join29 } from "path";
|
|
69778
70029
|
init_shared();
|
|
69779
70030
|
|
|
69780
70031
|
// src/cli/doctor/checks/model-resolution-cache.ts
|
|
69781
70032
|
init_shared();
|
|
69782
|
-
import { existsSync as
|
|
70033
|
+
import { existsSync as existsSync28, readFileSync as readFileSync24 } from "fs";
|
|
69783
70034
|
import { homedir as homedir7 } from "os";
|
|
69784
|
-
import { join as
|
|
70035
|
+
import { join as join26 } from "path";
|
|
69785
70036
|
function getOpenCodeCacheDir2() {
|
|
69786
70037
|
const xdgCache = process.env.XDG_CACHE_HOME;
|
|
69787
70038
|
if (xdgCache)
|
|
69788
|
-
return
|
|
69789
|
-
return
|
|
70039
|
+
return join26(xdgCache, "opencode");
|
|
70040
|
+
return join26(homedir7(), ".cache", "opencode");
|
|
69790
70041
|
}
|
|
69791
70042
|
function loadAvailableModelsFromCache() {
|
|
69792
|
-
const cacheFile =
|
|
69793
|
-
if (!
|
|
70043
|
+
const cacheFile = join26(getOpenCodeCacheDir2(), "models.json");
|
|
70044
|
+
if (!existsSync28(cacheFile)) {
|
|
69794
70045
|
return { providers: [], modelCount: 0, cacheExists: false };
|
|
69795
70046
|
}
|
|
69796
70047
|
try {
|
|
69797
|
-
const content =
|
|
70048
|
+
const content = readFileSync24(cacheFile, "utf-8");
|
|
69798
70049
|
const data = parseJsonc(content);
|
|
69799
70050
|
const providers = Object.keys(data);
|
|
69800
70051
|
let modelCount = 0;
|
|
@@ -69816,14 +70067,14 @@ init_model_capabilities();
|
|
|
69816
70067
|
|
|
69817
70068
|
// src/cli/doctor/checks/model-resolution-config.ts
|
|
69818
70069
|
init_shared();
|
|
69819
|
-
import { readFileSync as
|
|
69820
|
-
import { join as
|
|
69821
|
-
var PROJECT_CONFIG_DIR =
|
|
70070
|
+
import { readFileSync as readFileSync25 } from "fs";
|
|
70071
|
+
import { join as join27 } from "path";
|
|
70072
|
+
var PROJECT_CONFIG_DIR = join27(process.cwd(), ".opencode");
|
|
69822
70073
|
function loadOmoConfig() {
|
|
69823
70074
|
const projectDetected = detectPluginConfigFile(PROJECT_CONFIG_DIR);
|
|
69824
70075
|
if (projectDetected.format !== "none") {
|
|
69825
70076
|
try {
|
|
69826
|
-
const content =
|
|
70077
|
+
const content = readFileSync25(projectDetected.path, "utf-8");
|
|
69827
70078
|
return parseJsonc(content);
|
|
69828
70079
|
} catch {
|
|
69829
70080
|
return null;
|
|
@@ -69833,7 +70084,7 @@ function loadOmoConfig() {
|
|
|
69833
70084
|
const userDetected = detectPluginConfigFile(userConfigDir);
|
|
69834
70085
|
if (userDetected.format !== "none") {
|
|
69835
70086
|
try {
|
|
69836
|
-
const content =
|
|
70087
|
+
const content = readFileSync25(userDetected.path, "utf-8");
|
|
69837
70088
|
return parseJsonc(content);
|
|
69838
70089
|
} catch {
|
|
69839
70090
|
return null;
|
|
@@ -69844,7 +70095,7 @@ function loadOmoConfig() {
|
|
|
69844
70095
|
|
|
69845
70096
|
// src/cli/doctor/checks/model-resolution-details.ts
|
|
69846
70097
|
init_shared();
|
|
69847
|
-
import { join as
|
|
70098
|
+
import { join as join28 } from "path";
|
|
69848
70099
|
|
|
69849
70100
|
// src/cli/doctor/checks/model-resolution-variant.ts
|
|
69850
70101
|
function formatModelWithVariant(model, variant) {
|
|
@@ -69886,7 +70137,7 @@ function formatCapabilityResolutionLabel(mode) {
|
|
|
69886
70137
|
}
|
|
69887
70138
|
function buildModelResolutionDetails(options) {
|
|
69888
70139
|
const details = [];
|
|
69889
|
-
const cacheFile =
|
|
70140
|
+
const cacheFile = join28(getOpenCodeCacheDir(), "models.json");
|
|
69890
70141
|
details.push("\u2550\u2550\u2550 Available Models (from cache) \u2550\u2550\u2550");
|
|
69891
70142
|
details.push("");
|
|
69892
70143
|
if (options.available.cacheExists) {
|
|
@@ -70041,7 +70292,7 @@ async function checkModels() {
|
|
|
70041
70292
|
}
|
|
70042
70293
|
|
|
70043
70294
|
// src/cli/doctor/checks/config.ts
|
|
70044
|
-
var PROJECT_CONFIG_DIR2 =
|
|
70295
|
+
var PROJECT_CONFIG_DIR2 = join29(process.cwd(), ".opencode");
|
|
70045
70296
|
function findConfigPath() {
|
|
70046
70297
|
const projectConfig = detectPluginConfigFile(PROJECT_CONFIG_DIR2);
|
|
70047
70298
|
if (projectConfig.format !== "none")
|
|
@@ -70058,7 +70309,7 @@ function validateConfig() {
|
|
|
70058
70309
|
return { exists: false, path: null, valid: true, config: null, errors: [] };
|
|
70059
70310
|
}
|
|
70060
70311
|
try {
|
|
70061
|
-
const content =
|
|
70312
|
+
const content = readFileSync26(configPath, "utf-8");
|
|
70062
70313
|
const rawConfig = parseJsonc(content);
|
|
70063
70314
|
const schemaResult = OhMyOpenCodeConfigSchema.safeParse(rawConfig);
|
|
70064
70315
|
if (!schemaResult.success) {
|
|
@@ -70162,9 +70413,9 @@ async function checkConfig() {
|
|
|
70162
70413
|
|
|
70163
70414
|
// src/cli/doctor/checks/dependencies.ts
|
|
70164
70415
|
init_spawn_with_windows_hide();
|
|
70165
|
-
import { existsSync as
|
|
70416
|
+
import { existsSync as existsSync29 } from "fs";
|
|
70166
70417
|
import { createRequire } from "module";
|
|
70167
|
-
import { dirname as dirname9, join as
|
|
70418
|
+
import { dirname as dirname9, join as join30 } from "path";
|
|
70168
70419
|
async function checkBinaryExists(binary2) {
|
|
70169
70420
|
try {
|
|
70170
70421
|
const path10 = Bun.which(binary2);
|
|
@@ -70220,15 +70471,15 @@ async function checkAstGrepNapi() {
|
|
|
70220
70471
|
path: null
|
|
70221
70472
|
};
|
|
70222
70473
|
} catch {
|
|
70223
|
-
const { existsSync:
|
|
70224
|
-
const { join:
|
|
70474
|
+
const { existsSync: existsSync30 } = await import("fs");
|
|
70475
|
+
const { join: join31 } = await import("path");
|
|
70225
70476
|
const { homedir: homedir8 } = await import("os");
|
|
70226
70477
|
const pathsToCheck = [
|
|
70227
|
-
|
|
70228
|
-
|
|
70478
|
+
join31(homedir8(), ".config", "opencode", "node_modules", "@ast-grep", "napi"),
|
|
70479
|
+
join31(process.cwd(), "node_modules", "@ast-grep", "napi")
|
|
70229
70480
|
];
|
|
70230
70481
|
for (const napiPath of pathsToCheck) {
|
|
70231
|
-
if (
|
|
70482
|
+
if (existsSync30(napiPath)) {
|
|
70232
70483
|
return {
|
|
70233
70484
|
name: "AST-Grep NAPI",
|
|
70234
70485
|
required: false,
|
|
@@ -70253,8 +70504,8 @@ function findCommentCheckerPackageBinary() {
|
|
|
70253
70504
|
try {
|
|
70254
70505
|
const require2 = createRequire(import.meta.url);
|
|
70255
70506
|
const pkgPath = require2.resolve("@code-yeongyu/comment-checker/package.json");
|
|
70256
|
-
const binaryPath =
|
|
70257
|
-
if (
|
|
70507
|
+
const binaryPath = join30(dirname9(pkgPath), "bin", binaryName);
|
|
70508
|
+
if (existsSync29(binaryPath))
|
|
70258
70509
|
return binaryPath;
|
|
70259
70510
|
} catch {}
|
|
70260
70511
|
return null;
|
|
@@ -70411,15 +70662,15 @@ var BUILTIN_SERVERS = {
|
|
|
70411
70662
|
"kotlin-ls": { command: ["kotlin-lsp"], extensions: [".kt", ".kts"] }
|
|
70412
70663
|
};
|
|
70413
70664
|
// src/tools/lsp/server-config-loader.ts
|
|
70414
|
-
import { existsSync as
|
|
70415
|
-
import { join as
|
|
70665
|
+
import { existsSync as existsSync30, readFileSync as readFileSync27 } from "fs";
|
|
70666
|
+
import { join as join31 } from "path";
|
|
70416
70667
|
init_shared();
|
|
70417
70668
|
init_jsonc_parser();
|
|
70418
70669
|
function loadJsonFile(path10) {
|
|
70419
|
-
if (!
|
|
70670
|
+
if (!existsSync30(path10))
|
|
70420
70671
|
return null;
|
|
70421
70672
|
try {
|
|
70422
|
-
return parseJsonc(
|
|
70673
|
+
return parseJsonc(readFileSync27(path10, "utf-8"));
|
|
70423
70674
|
} catch {
|
|
70424
70675
|
return null;
|
|
70425
70676
|
}
|
|
@@ -70428,9 +70679,9 @@ function getConfigPaths2() {
|
|
|
70428
70679
|
const cwd = process.cwd();
|
|
70429
70680
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
70430
70681
|
return {
|
|
70431
|
-
project: detectPluginConfigFile(
|
|
70682
|
+
project: detectPluginConfigFile(join31(cwd, ".opencode")).path,
|
|
70432
70683
|
user: detectPluginConfigFile(configDir).path,
|
|
70433
|
-
opencode: detectConfigFile(
|
|
70684
|
+
opencode: detectConfigFile(join31(configDir, "opencode")).path
|
|
70434
70685
|
};
|
|
70435
70686
|
}
|
|
70436
70687
|
function loadAllConfigs() {
|
|
@@ -70499,21 +70750,21 @@ function getMergedServers() {
|
|
|
70499
70750
|
}
|
|
70500
70751
|
|
|
70501
70752
|
// src/tools/lsp/server-installation.ts
|
|
70502
|
-
import { existsSync as
|
|
70503
|
-
import { delimiter as delimiter2, join as
|
|
70753
|
+
import { existsSync as existsSync31 } from "fs";
|
|
70754
|
+
import { delimiter as delimiter2, join as join33 } from "path";
|
|
70504
70755
|
|
|
70505
70756
|
// src/tools/lsp/server-path-bases.ts
|
|
70506
70757
|
init_shared();
|
|
70507
|
-
import { join as
|
|
70758
|
+
import { join as join32 } from "path";
|
|
70508
70759
|
function getLspServerAdditionalPathBases(workingDirectory) {
|
|
70509
70760
|
const configDir = getOpenCodeConfigDir({ binary: "opencode" });
|
|
70510
|
-
const dataDir =
|
|
70761
|
+
const dataDir = join32(getDataDir(), "opencode");
|
|
70511
70762
|
return [
|
|
70512
|
-
|
|
70513
|
-
|
|
70514
|
-
|
|
70515
|
-
|
|
70516
|
-
|
|
70763
|
+
join32(workingDirectory, "node_modules", ".bin"),
|
|
70764
|
+
join32(configDir, "bin"),
|
|
70765
|
+
join32(configDir, "node_modules", ".bin"),
|
|
70766
|
+
join32(dataDir, "bin"),
|
|
70767
|
+
join32(dataDir, "bin", "node_modules", ".bin")
|
|
70517
70768
|
];
|
|
70518
70769
|
}
|
|
70519
70770
|
|
|
@@ -70523,7 +70774,7 @@ function isServerInstalled(command) {
|
|
|
70523
70774
|
return false;
|
|
70524
70775
|
const cmd = command[0];
|
|
70525
70776
|
if (cmd.includes("/") || cmd.includes("\\")) {
|
|
70526
|
-
if (
|
|
70777
|
+
if (existsSync31(cmd))
|
|
70527
70778
|
return true;
|
|
70528
70779
|
}
|
|
70529
70780
|
const isWindows = process.platform === "win32";
|
|
@@ -70544,14 +70795,14 @@ function isServerInstalled(command) {
|
|
|
70544
70795
|
const paths = pathEnv.split(delimiter2);
|
|
70545
70796
|
for (const p2 of paths) {
|
|
70546
70797
|
for (const suffix of exts) {
|
|
70547
|
-
if (
|
|
70798
|
+
if (existsSync31(join33(p2, cmd + suffix))) {
|
|
70548
70799
|
return true;
|
|
70549
70800
|
}
|
|
70550
70801
|
}
|
|
70551
70802
|
}
|
|
70552
70803
|
for (const base of getLspServerAdditionalPathBases(process.cwd())) {
|
|
70553
70804
|
for (const suffix of exts) {
|
|
70554
|
-
if (
|
|
70805
|
+
if (existsSync31(join33(base, cmd + suffix))) {
|
|
70555
70806
|
return true;
|
|
70556
70807
|
}
|
|
70557
70808
|
}
|
|
@@ -70613,24 +70864,24 @@ function getInstalledLspServers() {
|
|
|
70613
70864
|
|
|
70614
70865
|
// src/cli/doctor/checks/tools-mcp.ts
|
|
70615
70866
|
init_shared();
|
|
70616
|
-
import { existsSync as
|
|
70867
|
+
import { existsSync as existsSync32, readFileSync as readFileSync28 } from "fs";
|
|
70617
70868
|
import { homedir as homedir8 } from "os";
|
|
70618
|
-
import { join as
|
|
70869
|
+
import { join as join34 } from "path";
|
|
70619
70870
|
var BUILTIN_MCP_SERVERS = ["context7", "grep_app"];
|
|
70620
70871
|
function getMcpConfigPaths() {
|
|
70621
70872
|
return [
|
|
70622
|
-
|
|
70623
|
-
|
|
70624
|
-
|
|
70873
|
+
join34(homedir8(), ".claude", ".mcp.json"),
|
|
70874
|
+
join34(process.cwd(), ".mcp.json"),
|
|
70875
|
+
join34(process.cwd(), ".claude", ".mcp.json")
|
|
70625
70876
|
];
|
|
70626
70877
|
}
|
|
70627
70878
|
function loadUserMcpConfig() {
|
|
70628
70879
|
const servers = {};
|
|
70629
70880
|
for (const configPath of getMcpConfigPaths()) {
|
|
70630
|
-
if (!
|
|
70881
|
+
if (!existsSync32(configPath))
|
|
70631
70882
|
continue;
|
|
70632
70883
|
try {
|
|
70633
|
-
const content =
|
|
70884
|
+
const content = readFileSync28(configPath, "utf-8");
|
|
70634
70885
|
const config2 = parseJsonc(content);
|
|
70635
70886
|
if (config2.mcpServers) {
|
|
70636
70887
|
Object.assign(servers, config2.mcpServers);
|
|
@@ -71083,11 +71334,11 @@ async function refreshModelCapabilities(options, deps = {}) {
|
|
|
71083
71334
|
|
|
71084
71335
|
// src/features/mcp-oauth/storage.ts
|
|
71085
71336
|
init_shared();
|
|
71086
|
-
import { chmodSync, existsSync as
|
|
71087
|
-
import { dirname as dirname10, join as
|
|
71337
|
+
import { chmodSync, existsSync as existsSync33, mkdirSync as mkdirSync8, readFileSync as readFileSync29, unlinkSync as unlinkSync4, writeFileSync as writeFileSync10 } from "fs";
|
|
71338
|
+
import { dirname as dirname10, join as join35 } from "path";
|
|
71088
71339
|
var STORAGE_FILE_NAME = "mcp-oauth.json";
|
|
71089
71340
|
function getMcpOauthStoragePath() {
|
|
71090
|
-
return
|
|
71341
|
+
return join35(getOpenCodeConfigDir({ binary: "opencode" }), STORAGE_FILE_NAME);
|
|
71091
71342
|
}
|
|
71092
71343
|
function normalizeHost(serverHost) {
|
|
71093
71344
|
let host = serverHost.trim();
|
|
@@ -71124,11 +71375,11 @@ function buildKey(serverHost, resource) {
|
|
|
71124
71375
|
}
|
|
71125
71376
|
function readStore() {
|
|
71126
71377
|
const filePath = getMcpOauthStoragePath();
|
|
71127
|
-
if (!
|
|
71378
|
+
if (!existsSync33(filePath)) {
|
|
71128
71379
|
return null;
|
|
71129
71380
|
}
|
|
71130
71381
|
try {
|
|
71131
|
-
const content =
|
|
71382
|
+
const content = readFileSync29(filePath, "utf-8");
|
|
71132
71383
|
return JSON.parse(content);
|
|
71133
71384
|
} catch {
|
|
71134
71385
|
return null;
|
|
@@ -71138,7 +71389,7 @@ function writeStore(store2) {
|
|
|
71138
71389
|
const filePath = getMcpOauthStoragePath();
|
|
71139
71390
|
try {
|
|
71140
71391
|
const dir = dirname10(filePath);
|
|
71141
|
-
if (!
|
|
71392
|
+
if (!existsSync33(dir)) {
|
|
71142
71393
|
mkdirSync8(dir, { recursive: true });
|
|
71143
71394
|
}
|
|
71144
71395
|
writeFileSync10(filePath, JSON.stringify(store2, null, 2), { encoding: "utf-8", mode: 384 });
|
|
@@ -71173,7 +71424,7 @@ function deleteToken(serverHost, resource) {
|
|
|
71173
71424
|
if (Object.keys(store2).length === 0) {
|
|
71174
71425
|
try {
|
|
71175
71426
|
const filePath = getMcpOauthStoragePath();
|
|
71176
|
-
if (
|
|
71427
|
+
if (existsSync33(filePath)) {
|
|
71177
71428
|
unlinkSync4(filePath);
|
|
71178
71429
|
}
|
|
71179
71430
|
return true;
|
|
@@ -71396,7 +71647,7 @@ function startCallbackServer(port) {
|
|
|
71396
71647
|
clearTimeout(timeoutId);
|
|
71397
71648
|
const requestUrl = new URL(request.url ?? "/", `http://localhost:${port}`);
|
|
71398
71649
|
const code = requestUrl.searchParams.get("code");
|
|
71399
|
-
const
|
|
71650
|
+
const state2 = requestUrl.searchParams.get("state");
|
|
71400
71651
|
const error48 = requestUrl.searchParams.get("error");
|
|
71401
71652
|
if (error48) {
|
|
71402
71653
|
const errorDescription = requestUrl.searchParams.get("error_description") ?? error48;
|
|
@@ -71406,7 +71657,7 @@ function startCallbackServer(port) {
|
|
|
71406
71657
|
reject(new Error(`OAuth authorization error: ${errorDescription}`));
|
|
71407
71658
|
return;
|
|
71408
71659
|
}
|
|
71409
|
-
if (!code || !
|
|
71660
|
+
if (!code || !state2) {
|
|
71410
71661
|
response.writeHead(400, { "content-type": "text/html" });
|
|
71411
71662
|
response.end("<html><body><h1>Missing code or state</h1></body></html>");
|
|
71412
71663
|
server2.close();
|
|
@@ -71416,7 +71667,7 @@ function startCallbackServer(port) {
|
|
|
71416
71667
|
response.writeHead(200, { "content-type": "text/html" });
|
|
71417
71668
|
response.end("<html><body><h1>Authorization successful. You can close this tab.</h1></body></html>");
|
|
71418
71669
|
server2.close();
|
|
71419
|
-
resolve2({ code, state });
|
|
71670
|
+
resolve2({ code, state: state2 });
|
|
71420
71671
|
});
|
|
71421
71672
|
timeoutId = setTimeout(() => {
|
|
71422
71673
|
server2.close();
|
|
@@ -71452,19 +71703,19 @@ function openBrowser(url2) {
|
|
|
71452
71703
|
async function runAuthorizationCodeRedirect(options) {
|
|
71453
71704
|
const verifier = generateCodeVerifier();
|
|
71454
71705
|
const challenge = generateCodeChallenge(verifier);
|
|
71455
|
-
const
|
|
71706
|
+
const state2 = randomBytes2(16).toString("hex");
|
|
71456
71707
|
const authorizationUrl = buildAuthorizationUrl(options.authorizationEndpoint, {
|
|
71457
71708
|
clientId: options.clientId,
|
|
71458
71709
|
redirectUri: options.redirectUri,
|
|
71459
71710
|
codeChallenge: challenge,
|
|
71460
|
-
state,
|
|
71711
|
+
state: state2,
|
|
71461
71712
|
scopes: options.scopes,
|
|
71462
71713
|
resource: options.resource
|
|
71463
71714
|
});
|
|
71464
71715
|
const callbackPromise = startCallbackServer(options.callbackPort);
|
|
71465
71716
|
openBrowser(authorizationUrl);
|
|
71466
71717
|
const result = await callbackPromise;
|
|
71467
|
-
if (result.state !==
|
|
71718
|
+
if (result.state !== state2) {
|
|
71468
71719
|
throw new Error("OAuth state mismatch");
|
|
71469
71720
|
}
|
|
71470
71721
|
return { code: result.code, verifier };
|