claude-multi 0.6.4 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +49 -0
- package/dist/cli.js +1040 -664
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -7300,15 +7300,31 @@ function getApiKeyPlaceholder(providerName) {
|
|
|
7300
7300
|
return prefix ? `${prefix}...` : "sk-...";
|
|
7301
7301
|
}
|
|
7302
7302
|
function providerHasRegions(providerName) {
|
|
7303
|
-
return providerName
|
|
7303
|
+
return providerName in PROVIDER_REGION_MAPS;
|
|
7304
|
+
}
|
|
7305
|
+
function getProviderRegions(providerName) {
|
|
7306
|
+
return PROVIDER_REGION_MAPS[providerName];
|
|
7307
|
+
}
|
|
7308
|
+
function detectRegionFromBaseUrl(baseUrl) {
|
|
7309
|
+
for (const regionMap of Object.values(PROVIDER_REGION_MAPS)) {
|
|
7310
|
+
for (const [regionCode, config] of Object.entries(regionMap)) {
|
|
7311
|
+
const escaped = config.baseUrl.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
7312
|
+
const regex = new RegExp(`^${escaped}/?$`);
|
|
7313
|
+
if (regex.test(baseUrl)) {
|
|
7314
|
+
return regionCode;
|
|
7315
|
+
}
|
|
7316
|
+
}
|
|
7317
|
+
}
|
|
7318
|
+
return null;
|
|
7304
7319
|
}
|
|
7305
7320
|
function resolveRegionTemplate(template, region) {
|
|
7306
7321
|
if (!providerHasRegions(template.name)) {
|
|
7307
7322
|
return template;
|
|
7308
7323
|
}
|
|
7309
|
-
const
|
|
7324
|
+
const regionMap = PROVIDER_REGION_MAPS[template.name];
|
|
7325
|
+
const regionConfig = regionMap?.[region];
|
|
7310
7326
|
if (!regionConfig) {
|
|
7311
|
-
throw new Error(`Unknown region '${region}' for ${template.name}. Available: ${Object.keys(
|
|
7327
|
+
throw new Error(`Unknown region '${region}' for ${template.name}. Available: ${regionMap ? Object.keys(regionMap).join(", ") : "none"}`);
|
|
7312
7328
|
}
|
|
7313
7329
|
const resolved = structuredClone(template);
|
|
7314
7330
|
resolved.settings.env.ANTHROPIC_BASE_URL = regionConfig.baseUrl;
|
|
@@ -7338,7 +7354,8 @@ function getProviderByBaseUrl(baseUrl) {
|
|
|
7338
7354
|
if (baseUrl === templateUrl)
|
|
7339
7355
|
return name;
|
|
7340
7356
|
}
|
|
7341
|
-
|
|
7357
|
+
const regionCode = detectRegionFromBaseUrl(baseUrl);
|
|
7358
|
+
if (regionCode) {
|
|
7342
7359
|
return "mimo-token";
|
|
7343
7360
|
}
|
|
7344
7361
|
return null;
|
|
@@ -7357,7 +7374,7 @@ function detectProvider(configDir) {
|
|
|
7357
7374
|
return null;
|
|
7358
7375
|
}
|
|
7359
7376
|
}
|
|
7360
|
-
var PROVIDER_COMMON_ENV, PROVIDER_TEMPLATES, API_KEY_PREFIXES, MIMO_TOKEN_REGIONS;
|
|
7377
|
+
var PROVIDER_COMMON_ENV, PROVIDER_TEMPLATES, API_KEY_PREFIXES, MIMO_TOKEN_REGIONS, PROVIDER_REGION_MAPS;
|
|
7361
7378
|
var init_templates = __esm(() => {
|
|
7362
7379
|
PROVIDER_COMMON_ENV = {};
|
|
7363
7380
|
PROVIDER_TEMPLATES = {
|
|
@@ -7379,7 +7396,9 @@ var init_templates = __esm(() => {
|
|
|
7379
7396
|
REASONING_EFFORT: "high",
|
|
7380
7397
|
MAX_THINKING_TOKENS: "8000",
|
|
7381
7398
|
ENABLE_STREAMING: "true",
|
|
7382
|
-
MAX_OUTPUT_TOKENS: "64000"
|
|
7399
|
+
MAX_OUTPUT_TOKENS: "64000",
|
|
7400
|
+
CLAUDE_CODE_AUTO_COMPACT_WINDOW: "131072",
|
|
7401
|
+
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "75"
|
|
7383
7402
|
},
|
|
7384
7403
|
includeCoAuthoredBy: false,
|
|
7385
7404
|
alwaysThinkingEnabled: false
|
|
@@ -7403,7 +7422,9 @@ var init_templates = __esm(() => {
|
|
|
7403
7422
|
ENABLE_THINKING: "true",
|
|
7404
7423
|
REASONING_EFFORT: "high",
|
|
7405
7424
|
MAX_OUTPUT_TOKENS: "64000",
|
|
7406
|
-
MAX_THINKING_TOKENS: "32000"
|
|
7425
|
+
MAX_THINKING_TOKENS: "32000",
|
|
7426
|
+
CLAUDE_CODE_AUTO_COMPACT_WINDOW: "131072",
|
|
7427
|
+
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "75"
|
|
7407
7428
|
},
|
|
7408
7429
|
includeCoAuthoredBy: false,
|
|
7409
7430
|
alwaysThinkingEnabled: true
|
|
@@ -7493,7 +7514,9 @@ var init_templates = __esm(() => {
|
|
|
7493
7514
|
ENABLE_THINKING: "true",
|
|
7494
7515
|
REASONING_EFFORT: "high",
|
|
7495
7516
|
MAX_THINKING_TOKENS: "16000",
|
|
7496
|
-
MAX_OUTPUT_TOKENS: "65536"
|
|
7517
|
+
MAX_OUTPUT_TOKENS: "65536",
|
|
7518
|
+
CLAUDE_CODE_AUTO_COMPACT_WINDOW: "131072",
|
|
7519
|
+
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "75"
|
|
7497
7520
|
},
|
|
7498
7521
|
includeCoAuthoredBy: false,
|
|
7499
7522
|
alwaysThinkingEnabled: false
|
|
@@ -7516,7 +7539,9 @@ var init_templates = __esm(() => {
|
|
|
7516
7539
|
ENABLE_THINKING: "true",
|
|
7517
7540
|
REASONING_EFFORT: "high",
|
|
7518
7541
|
MAX_THINKING_TOKENS: "16000",
|
|
7519
|
-
MAX_OUTPUT_TOKENS: "65536"
|
|
7542
|
+
MAX_OUTPUT_TOKENS: "65536",
|
|
7543
|
+
CLAUDE_CODE_AUTO_COMPACT_WINDOW: "131072",
|
|
7544
|
+
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "75"
|
|
7520
7545
|
},
|
|
7521
7546
|
includeCoAuthoredBy: false,
|
|
7522
7547
|
alwaysThinkingEnabled: false
|
|
@@ -7539,7 +7564,9 @@ var init_templates = __esm(() => {
|
|
|
7539
7564
|
ENABLE_THINKING: "true",
|
|
7540
7565
|
REASONING_EFFORT: "high",
|
|
7541
7566
|
MAX_THINKING_TOKENS: "16000",
|
|
7542
|
-
MAX_OUTPUT_TOKENS: "65536"
|
|
7567
|
+
MAX_OUTPUT_TOKENS: "65536",
|
|
7568
|
+
CLAUDE_CODE_AUTO_COMPACT_WINDOW: "131072",
|
|
7569
|
+
CLAUDE_AUTOCOMPACT_PCT_OVERRIDE: "75"
|
|
7543
7570
|
},
|
|
7544
7571
|
includeCoAuthoredBy: false,
|
|
7545
7572
|
alwaysThinkingEnabled: false
|
|
@@ -7563,6 +7590,9 @@ var init_templates = __esm(() => {
|
|
|
7563
7590
|
baseUrl: "https://token-plan-ams.xiaomimimo.com/anthropic"
|
|
7564
7591
|
}
|
|
7565
7592
|
};
|
|
7593
|
+
PROVIDER_REGION_MAPS = {
|
|
7594
|
+
"mimo-token": MIMO_TOKEN_REGIONS
|
|
7595
|
+
};
|
|
7566
7596
|
});
|
|
7567
7597
|
|
|
7568
7598
|
// src/util/json-file.ts
|
|
@@ -7665,6 +7695,22 @@ var init_constants = __esm(() => {
|
|
|
7665
7695
|
};
|
|
7666
7696
|
});
|
|
7667
7697
|
|
|
7698
|
+
// src/constants/env.ts
|
|
7699
|
+
var TUNABLE_ENV_VARS;
|
|
7700
|
+
var init_env = __esm(() => {
|
|
7701
|
+
TUNABLE_ENV_VARS = new Set([
|
|
7702
|
+
"MAX_OUTPUT_TOKENS",
|
|
7703
|
+
"MAX_THINKING_TOKENS",
|
|
7704
|
+
"REASONING_EFFORT",
|
|
7705
|
+
"ENABLE_THINKING",
|
|
7706
|
+
"ENABLE_STREAMING",
|
|
7707
|
+
"API_TIMEOUT_MS",
|
|
7708
|
+
"CLAUDE_CODE_EFFORT_LEVEL",
|
|
7709
|
+
"CLAUDE_CODE_AUTO_COMPACT_WINDOW",
|
|
7710
|
+
"CLAUDE_AUTOCOMPACT_PCT_OVERRIDE"
|
|
7711
|
+
]);
|
|
7712
|
+
});
|
|
7713
|
+
|
|
7668
7714
|
// node_modules/semver/internal/constants.js
|
|
7669
7715
|
var require_constants = __commonJS((exports, module) => {
|
|
7670
7716
|
var SEMVER_SPEC_VERSION = "2.0.0";
|
|
@@ -9492,22 +9538,11 @@ var require_semver2 = __commonJS((exports, module) => {
|
|
|
9492
9538
|
});
|
|
9493
9539
|
|
|
9494
9540
|
// src/paths.ts
|
|
9495
|
-
var exports_paths = {};
|
|
9496
|
-
__export(exports_paths, {
|
|
9497
|
-
getBaseDir: () => getBaseDir,
|
|
9498
|
-
PINNED_CLAUDE_BIN: () => PINNED_CLAUDE_BIN,
|
|
9499
|
-
PINNED_BIN_DIR: () => PINNED_BIN_DIR
|
|
9500
|
-
});
|
|
9501
9541
|
import { homedir } from "node:os";
|
|
9502
|
-
import { join as join2 } from "node:path";
|
|
9503
9542
|
function getBaseDir() {
|
|
9504
9543
|
return process.env.CLAUDE_MULTI_HOME || homedir();
|
|
9505
9544
|
}
|
|
9506
|
-
var
|
|
9507
|
-
var init_paths = __esm(() => {
|
|
9508
|
-
PINNED_BIN_DIR = join2(homedir(), ".claude-multi", "bin");
|
|
9509
|
-
PINNED_CLAUDE_BIN = process.platform === "win32" ? join2(PINNED_BIN_DIR, "node_modules", ".bin", "claude.cmd") : join2(PINNED_BIN_DIR, "node_modules", ".bin", "claude");
|
|
9510
|
-
});
|
|
9545
|
+
var init_paths = () => {};
|
|
9511
9546
|
|
|
9512
9547
|
// src/util/runtime.ts
|
|
9513
9548
|
function detectPackageManager() {
|
|
@@ -9521,27 +9556,12 @@ function detectPackageManager() {
|
|
|
9521
9556
|
}
|
|
9522
9557
|
|
|
9523
9558
|
// src/version.ts
|
|
9524
|
-
var exports_version = {};
|
|
9525
|
-
__export(exports_version, {
|
|
9526
|
-
upgradeClaudeMulti: () => upgradeClaudeMulti,
|
|
9527
|
-
updateClaudeCode: () => updateClaudeCode,
|
|
9528
|
-
isThirdPartyApiBroken: () => isThirdPartyApiBroken,
|
|
9529
|
-
installPinnedClaude: () => installPinnedClaude,
|
|
9530
|
-
getPinnedBinaryVersion: () => getPinnedBinaryVersion,
|
|
9531
|
-
getLatestVersion: () => getLatestVersion,
|
|
9532
|
-
getLatestClaudeMultiVersion: () => getLatestClaudeMultiVersion,
|
|
9533
|
-
getCurrentVersion: () => getCurrentVersion,
|
|
9534
|
-
getClaudeMultiVersion: () => getClaudeMultiVersion,
|
|
9535
|
-
checkForUpdates: () => checkForUpdates,
|
|
9536
|
-
checkForClaudeMultiUpdates: () => checkForClaudeMultiUpdates,
|
|
9537
|
-
COMPATIBLE_CLAUDE_VERSION: () => COMPATIBLE_CLAUDE_VERSION
|
|
9538
|
-
});
|
|
9539
9559
|
import { execSync } from "node:child_process";
|
|
9540
|
-
import {
|
|
9541
|
-
import { join as
|
|
9560
|
+
import { readFileSync as readFileSync2 } from "node:fs";
|
|
9561
|
+
import { join as join2, dirname } from "node:path";
|
|
9542
9562
|
import { fileURLToPath } from "node:url";
|
|
9543
9563
|
function getClaudeMultiVersion() {
|
|
9544
|
-
const pkgPath =
|
|
9564
|
+
const pkgPath = join2(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
9545
9565
|
const pkg = JSON.parse(readFileSync2(pkgPath, "utf-8"));
|
|
9546
9566
|
if (typeof pkg !== "object" || pkg === null || typeof pkg.version !== "string") {
|
|
9547
9567
|
throw new ClaudeMultiError(ErrorCode.CONFIG_CORRUPTED, "Could not read package version");
|
|
@@ -9601,40 +9621,6 @@ function getCurrentVersion() {
|
|
|
9601
9621
|
return null;
|
|
9602
9622
|
}
|
|
9603
9623
|
}
|
|
9604
|
-
function isThirdPartyApiBroken(version) {
|
|
9605
|
-
return import_semver.default.gte(version, "2.1.154") && import_semver.default.lt(version, "2.1.156");
|
|
9606
|
-
}
|
|
9607
|
-
function getPinnedBinaryVersion() {
|
|
9608
|
-
const pkgJsonPath = join3(PINNED_BIN_DIR, "node_modules", "@anthropic-ai", "claude-code", "package.json");
|
|
9609
|
-
try {
|
|
9610
|
-
if (!existsSync2(pkgJsonPath))
|
|
9611
|
-
return null;
|
|
9612
|
-
const pkg = JSON.parse(readFileSync2(pkgJsonPath, "utf-8"));
|
|
9613
|
-
return pkg.version ?? null;
|
|
9614
|
-
} catch {
|
|
9615
|
-
return null;
|
|
9616
|
-
}
|
|
9617
|
-
}
|
|
9618
|
-
function installPinnedClaude() {
|
|
9619
|
-
const pm = detectPackageManager();
|
|
9620
|
-
mkdirSync(PINNED_BIN_DIR, { recursive: true });
|
|
9621
|
-
const pkgJsonPath = join3(PINNED_BIN_DIR, "package.json");
|
|
9622
|
-
if (!existsSync2(pkgJsonPath)) {
|
|
9623
|
-
writeFileSync(pkgJsonPath, JSON.stringify({ dependencies: {} }, null, 2));
|
|
9624
|
-
}
|
|
9625
|
-
const pkg = `@anthropic-ai/claude-code@${COMPATIBLE_CLAUDE_VERSION}`;
|
|
9626
|
-
const commands = {
|
|
9627
|
-
bun: `bun add --cwd ${PINNED_BIN_DIR} ${pkg}`,
|
|
9628
|
-
npm: `npm install --prefix ${PINNED_BIN_DIR} ${pkg}`,
|
|
9629
|
-
pnpm: `pnpm add --dir ${PINNED_BIN_DIR} ${pkg}`,
|
|
9630
|
-
deno: `cd ${PINNED_BIN_DIR} && npm install ${pkg}`
|
|
9631
|
-
};
|
|
9632
|
-
try {
|
|
9633
|
-
execSync(commands[pm], { stdio: "inherit" });
|
|
9634
|
-
} catch (err) {
|
|
9635
|
-
throw new ClaudeMultiError(ErrorCode.UPDATE_FAILED, `Failed to install pinned Claude v${COMPATIBLE_CLAUDE_VERSION}: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
9636
|
-
}
|
|
9637
|
-
}
|
|
9638
9624
|
async function getLatestVersion() {
|
|
9639
9625
|
try {
|
|
9640
9626
|
const response = await fetch("https://registry.npmjs.org/@anthropic-ai/claude-code/latest");
|
|
@@ -9669,20 +9655,15 @@ function updateClaudeCode() {
|
|
|
9669
9655
|
throw new ClaudeMultiError(ErrorCode.UPDATE_FAILED, `Failed to update @anthropic-ai/claude-code: ${err instanceof Error ? err.message : String(err)}`, { cause: err });
|
|
9670
9656
|
}
|
|
9671
9657
|
}
|
|
9672
|
-
var import_semver, COMPATIBLE_CLAUDE_VERSION = "2.1.156";
|
|
9673
9658
|
var init_version = __esm(() => {
|
|
9674
9659
|
init_errors();
|
|
9675
|
-
init_paths();
|
|
9676
|
-
import_semver = __toESM(require_semver2(), 1);
|
|
9677
9660
|
});
|
|
9678
9661
|
|
|
9679
9662
|
// src/wrapper.ts
|
|
9680
9663
|
var exports_wrapper = {};
|
|
9681
9664
|
__export(exports_wrapper, {
|
|
9682
|
-
tryGetGlobalClaudePath: () => tryGetGlobalClaudePath,
|
|
9683
9665
|
tryGetClaudePath: () => tryGetClaudePath,
|
|
9684
9666
|
removeWrapper: () => removeWrapper,
|
|
9685
|
-
getGlobalClaudePath: () => getGlobalClaudePath,
|
|
9686
9667
|
getDefaultBinaryPath: () => getDefaultBinaryPath,
|
|
9687
9668
|
getClaudePath: () => getClaudePath,
|
|
9688
9669
|
generateWrapperScriptSafe: () => generateWrapperScriptSafe,
|
|
@@ -9691,7 +9672,7 @@ __export(exports_wrapper, {
|
|
|
9691
9672
|
createWrapper: () => createWrapper,
|
|
9692
9673
|
buildWrapperScript: () => buildWrapperScript
|
|
9693
9674
|
});
|
|
9694
|
-
import { existsSync as
|
|
9675
|
+
import { existsSync as existsSync2, mkdirSync, chmodSync, unlinkSync } from "node:fs";
|
|
9695
9676
|
import { writeFile as writeFile2 } from "node:fs/promises";
|
|
9696
9677
|
import { resolve, dirname as dirname2 } from "node:path";
|
|
9697
9678
|
import { execSync as execSync2 } from "node:child_process";
|
|
@@ -9699,19 +9680,15 @@ function getClaudePath() {
|
|
|
9699
9680
|
const override = process.env.CLAUDE_MULTI_CLAUDE_PATH;
|
|
9700
9681
|
if (override) {
|
|
9701
9682
|
const resolved = resolve(override);
|
|
9702
|
-
if (!
|
|
9683
|
+
if (!existsSync2(resolved)) {
|
|
9703
9684
|
throw new ClaudeMultiError(ErrorCode.CLAUDE_NOT_FOUND, `CLAUDE_MULTI_CLAUDE_PATH points to ${resolved} but that file does not exist`);
|
|
9704
9685
|
}
|
|
9705
9686
|
return resolved;
|
|
9706
9687
|
}
|
|
9707
|
-
if (existsSync3(PINNED_CLAUDE_BIN)) {
|
|
9708
|
-
return PINNED_CLAUDE_BIN;
|
|
9709
|
-
}
|
|
9710
9688
|
try {
|
|
9711
9689
|
const command = process.platform === "win32" ? "where claude" : "which claude";
|
|
9712
9690
|
const claudePath = execSync2(command, { encoding: "utf-8" }).trim();
|
|
9713
|
-
const firstPath = claudePath.split(
|
|
9714
|
-
`)[0];
|
|
9691
|
+
const firstPath = claudePath.split(/\r?\n/)[0];
|
|
9715
9692
|
if (!firstPath) {
|
|
9716
9693
|
throw new ClaudeMultiError(ErrorCode.CLAUDE_NOT_FOUND, "Could not determine Claude path");
|
|
9717
9694
|
}
|
|
@@ -9729,37 +9706,6 @@ function tryGetClaudePath() {
|
|
|
9729
9706
|
return null;
|
|
9730
9707
|
}
|
|
9731
9708
|
}
|
|
9732
|
-
function getGlobalClaudePath() {
|
|
9733
|
-
const override = process.env.CLAUDE_MULTI_CLAUDE_PATH;
|
|
9734
|
-
if (override) {
|
|
9735
|
-
const resolved = resolve(override);
|
|
9736
|
-
if (!existsSync3(resolved)) {
|
|
9737
|
-
throw new ClaudeMultiError(ErrorCode.CLAUDE_NOT_FOUND, `CLAUDE_MULTI_CLAUDE_PATH points to ${resolved} but that file does not exist`);
|
|
9738
|
-
}
|
|
9739
|
-
return resolved;
|
|
9740
|
-
}
|
|
9741
|
-
try {
|
|
9742
|
-
const command = process.platform === "win32" ? "where claude" : "which claude";
|
|
9743
|
-
const claudePath = execSync2(command, { encoding: "utf-8" }).trim();
|
|
9744
|
-
const firstPath = claudePath.split(`
|
|
9745
|
-
`)[0];
|
|
9746
|
-
if (!firstPath) {
|
|
9747
|
-
throw new ClaudeMultiError(ErrorCode.CLAUDE_NOT_FOUND, "Could not determine Claude path");
|
|
9748
|
-
}
|
|
9749
|
-
return firstPath.trim();
|
|
9750
|
-
} catch (err) {
|
|
9751
|
-
if (err instanceof ClaudeMultiError)
|
|
9752
|
-
throw err;
|
|
9753
|
-
throw new ClaudeMultiError(ErrorCode.CLAUDE_NOT_FOUND, "Claude Code is not installed. Please install @anthropic-ai/claude-code first.", { cause: err });
|
|
9754
|
-
}
|
|
9755
|
-
}
|
|
9756
|
-
function tryGetGlobalClaudePath() {
|
|
9757
|
-
try {
|
|
9758
|
-
return getGlobalClaudePath();
|
|
9759
|
-
} catch {
|
|
9760
|
-
return null;
|
|
9761
|
-
}
|
|
9762
|
-
}
|
|
9763
9709
|
function generateWrapperScriptSafe(options) {
|
|
9764
9710
|
const claudePath = tryGetClaudePath();
|
|
9765
9711
|
if (!claudePath)
|
|
@@ -9791,11 +9737,11 @@ set "CLAUDE_CONFIG_DIR=${options.configDir}"
|
|
|
9791
9737
|
async function createWrapper(options) {
|
|
9792
9738
|
const { binaryPath, configDir } = options;
|
|
9793
9739
|
const binDir = dirname2(binaryPath);
|
|
9794
|
-
if (!
|
|
9795
|
-
|
|
9740
|
+
if (!existsSync2(binDir)) {
|
|
9741
|
+
mkdirSync(binDir, { recursive: true });
|
|
9796
9742
|
}
|
|
9797
|
-
if (!
|
|
9798
|
-
|
|
9743
|
+
if (!existsSync2(configDir)) {
|
|
9744
|
+
mkdirSync(configDir, { recursive: true });
|
|
9799
9745
|
}
|
|
9800
9746
|
if (process.platform === "win32") {
|
|
9801
9747
|
const script = generateWindowsWrapperScript(options);
|
|
@@ -9807,7 +9753,7 @@ async function createWrapper(options) {
|
|
|
9807
9753
|
}
|
|
9808
9754
|
}
|
|
9809
9755
|
function removeWrapper(binaryPath) {
|
|
9810
|
-
if (
|
|
9756
|
+
if (existsSync2(binaryPath)) {
|
|
9811
9757
|
unlinkSync(binaryPath);
|
|
9812
9758
|
}
|
|
9813
9759
|
}
|
|
@@ -9832,7 +9778,6 @@ function getDefaultBinaryPath(name) {
|
|
|
9832
9778
|
}
|
|
9833
9779
|
var init_wrapper = __esm(() => {
|
|
9834
9780
|
init_errors();
|
|
9835
|
-
init_paths();
|
|
9836
9781
|
});
|
|
9837
9782
|
|
|
9838
9783
|
// src/migration.ts
|
|
@@ -9849,11 +9794,11 @@ __export(exports_migration, {
|
|
|
9849
9794
|
LEGACY_INSTANCE_VERSION: () => LEGACY_INSTANCE_VERSION,
|
|
9850
9795
|
CONFIG_VERSION: () => CONFIG_VERSION
|
|
9851
9796
|
});
|
|
9852
|
-
import { existsSync as
|
|
9853
|
-
import { join as
|
|
9797
|
+
import { existsSync as existsSync3, mkdirSync as mkdirSync2, readdirSync, copyFileSync, readFileSync as readFileSync3, rmSync, writeFileSync, chmodSync as chmodSync2 } from "node:fs";
|
|
9798
|
+
import { join as join3, dirname as dirname3 } from "node:path";
|
|
9854
9799
|
function updateClaudeJson(configDir) {
|
|
9855
|
-
const stateFile =
|
|
9856
|
-
if (!
|
|
9800
|
+
const stateFile = join3(configDir, ".claude.json");
|
|
9801
|
+
if (!existsSync3(stateFile))
|
|
9857
9802
|
return;
|
|
9858
9803
|
try {
|
|
9859
9804
|
const raw = JSON.parse(readFileSync3(stateFile, "utf-8"));
|
|
@@ -9863,7 +9808,7 @@ function updateClaudeJson(configDir) {
|
|
|
9863
9808
|
changed = true;
|
|
9864
9809
|
}
|
|
9865
9810
|
if (changed) {
|
|
9866
|
-
|
|
9811
|
+
writeFileSync(stateFile, JSON.stringify(raw, null, 2), "utf-8");
|
|
9867
9812
|
}
|
|
9868
9813
|
} catch {}
|
|
9869
9814
|
}
|
|
@@ -9872,10 +9817,10 @@ function needsInstanceMigration(config) {
|
|
|
9872
9817
|
const stored = config.instanceMigrationVersion;
|
|
9873
9818
|
if (!stored)
|
|
9874
9819
|
return INSTANCE_MIGRATIONS.length > 0;
|
|
9875
|
-
const storedCoerced =
|
|
9820
|
+
const storedCoerced = import_semver.default.coerce(stored);
|
|
9876
9821
|
if (!storedCoerced)
|
|
9877
9822
|
return INSTANCE_MIGRATIONS.length > 0;
|
|
9878
|
-
return INSTANCE_MIGRATIONS.some((m) =>
|
|
9823
|
+
return INSTANCE_MIGRATIONS.some((m) => import_semver.default.gt(m.version, storedCoerced) && import_semver.default.lte(m.version, current));
|
|
9879
9824
|
}
|
|
9880
9825
|
async function runInstanceMigrations(config) {
|
|
9881
9826
|
if (!needsInstanceMigration(config))
|
|
@@ -9885,8 +9830,8 @@ async function runInstanceMigrations(config) {
|
|
|
9885
9830
|
try {
|
|
9886
9831
|
createBackup(config);
|
|
9887
9832
|
const currentVersion = getClaudeMultiVersion();
|
|
9888
|
-
const stored =
|
|
9889
|
-
const applicable = INSTANCE_MIGRATIONS.filter((m) => stored ?
|
|
9833
|
+
const stored = import_semver.default.coerce(config.instanceMigrationVersion || "0.0.0");
|
|
9834
|
+
const applicable = INSTANCE_MIGRATIONS.filter((m) => stored ? import_semver.default.gt(m.version, stored) && import_semver.default.lte(m.version, currentVersion) : true).toSorted((a, b) => import_semver.default.compare(a.version, b.version));
|
|
9890
9835
|
for (const migration of applicable) {
|
|
9891
9836
|
for (let i = 0;i < config.instances.length; i++) {
|
|
9892
9837
|
const migrated = await migration.migrate({ ...config.instances[i] }, config);
|
|
@@ -9900,26 +9845,31 @@ async function runInstanceMigrations(config) {
|
|
|
9900
9845
|
}
|
|
9901
9846
|
}
|
|
9902
9847
|
function getBackupDir() {
|
|
9903
|
-
return
|
|
9848
|
+
return join3(getBaseDir(), ".claude-multi", "backups");
|
|
9904
9849
|
}
|
|
9905
9850
|
function getLockFile() {
|
|
9906
|
-
return
|
|
9851
|
+
return join3(getBaseDir(), ".claude-multi", ".migration.lock");
|
|
9907
9852
|
}
|
|
9908
9853
|
function createLock() {
|
|
9909
9854
|
const lockFile = getLockFile();
|
|
9910
9855
|
const lockDir = dirname3(lockFile);
|
|
9911
|
-
if (!
|
|
9912
|
-
|
|
9913
|
-
if (
|
|
9856
|
+
if (!existsSync3(lockDir))
|
|
9857
|
+
mkdirSync2(lockDir, { recursive: true });
|
|
9858
|
+
if (existsSync3(lockFile)) {
|
|
9914
9859
|
try {
|
|
9915
9860
|
const raw = JSON.parse(readFileSync3(lockFile, "utf-8"));
|
|
9916
9861
|
if (typeof raw === "object" && raw !== null && "pid" in raw && typeof raw.pid === "number") {
|
|
9917
9862
|
const lock = raw;
|
|
9918
|
-
|
|
9919
|
-
|
|
9920
|
-
return false;
|
|
9921
|
-
} catch {
|
|
9863
|
+
const lockAge = Date.now() - new Date(lock.startedAt).getTime();
|
|
9864
|
+
if (lockAge > 30 * 60 * 1000) {
|
|
9922
9865
|
rmSync(lockFile, { force: true });
|
|
9866
|
+
} else {
|
|
9867
|
+
try {
|
|
9868
|
+
process.kill(lock.pid, 0);
|
|
9869
|
+
return false;
|
|
9870
|
+
} catch {
|
|
9871
|
+
rmSync(lockFile, { force: true });
|
|
9872
|
+
}
|
|
9923
9873
|
}
|
|
9924
9874
|
} else {
|
|
9925
9875
|
rmSync(lockFile, { force: true });
|
|
@@ -9928,7 +9878,7 @@ function createLock() {
|
|
|
9928
9878
|
rmSync(lockFile, { force: true });
|
|
9929
9879
|
}
|
|
9930
9880
|
}
|
|
9931
|
-
|
|
9881
|
+
writeFileSync(lockFile, JSON.stringify({
|
|
9932
9882
|
pid: process.pid,
|
|
9933
9883
|
startedAt: new Date().toISOString()
|
|
9934
9884
|
}), "utf-8");
|
|
@@ -9953,30 +9903,30 @@ function clearMigrationFailure(config) {
|
|
|
9953
9903
|
}
|
|
9954
9904
|
function createBackup(config) {
|
|
9955
9905
|
const backupDir = getBackupDir();
|
|
9956
|
-
if (!
|
|
9957
|
-
|
|
9906
|
+
if (!existsSync3(backupDir)) {
|
|
9907
|
+
mkdirSync2(backupDir, { recursive: true });
|
|
9958
9908
|
}
|
|
9959
9909
|
const ts = new Date().toISOString().replace(/[:.]/g, "-");
|
|
9960
9910
|
const rand = Math.random().toString(36).slice(2, 6);
|
|
9961
9911
|
const fromV = config.version || "1.0.0";
|
|
9962
|
-
const backupPath =
|
|
9963
|
-
|
|
9964
|
-
const configSrc =
|
|
9965
|
-
if (
|
|
9966
|
-
copyFileSync(configSrc,
|
|
9912
|
+
const backupPath = join3(backupDir, `${ts}-${rand}-v${fromV}-to-v${CONFIG_VERSION}`);
|
|
9913
|
+
mkdirSync2(backupPath, { recursive: true });
|
|
9914
|
+
const configSrc = join3(getBaseDir(), ".claude-multi", "config.json");
|
|
9915
|
+
if (existsSync3(configSrc)) {
|
|
9916
|
+
copyFileSync(configSrc, join3(backupPath, "config.json"));
|
|
9967
9917
|
}
|
|
9968
|
-
const instancesDir =
|
|
9918
|
+
const instancesDir = join3(backupPath, "instances");
|
|
9969
9919
|
for (const inst of config.instances) {
|
|
9970
|
-
const settingsFile =
|
|
9971
|
-
if (
|
|
9972
|
-
const instDir =
|
|
9973
|
-
|
|
9974
|
-
copyFileSync(settingsFile,
|
|
9920
|
+
const settingsFile = join3(inst.configDir, "settings.json");
|
|
9921
|
+
if (existsSync3(settingsFile)) {
|
|
9922
|
+
const instDir = join3(instancesDir, inst.name);
|
|
9923
|
+
mkdirSync2(instDir, { recursive: true });
|
|
9924
|
+
copyFileSync(settingsFile, join3(instDir, "settings.json"));
|
|
9975
9925
|
}
|
|
9976
9926
|
}
|
|
9977
9927
|
const backups = readdirSync(backupDir).toSorted();
|
|
9978
9928
|
for (let i = 0;i < backups.length - 3; i++) {
|
|
9979
|
-
rmSync(
|
|
9929
|
+
rmSync(join3(backupDir, backups[i]), { force: true, recursive: true });
|
|
9980
9930
|
}
|
|
9981
9931
|
return backupPath;
|
|
9982
9932
|
}
|
|
@@ -9994,7 +9944,7 @@ function runMigration(config) {
|
|
|
9994
9944
|
if (!inst.name || !inst.configDir || !inst.binaryPath) {
|
|
9995
9945
|
warnings.push(`Instance entry missing required fields, skipping: ${JSON.stringify(inst)}`);
|
|
9996
9946
|
}
|
|
9997
|
-
if (inst.configDir && !
|
|
9947
|
+
if (inst.configDir && !existsSync3(inst.configDir)) {
|
|
9998
9948
|
warnings.push(`Instance '${inst.name}' configDir does not exist: ${inst.configDir}`);
|
|
9999
9949
|
}
|
|
10000
9950
|
}
|
|
@@ -10027,18 +9977,19 @@ function getMigrationStatus(config) {
|
|
|
10027
9977
|
}
|
|
10028
9978
|
function listBackups() {
|
|
10029
9979
|
const backupDir = getBackupDir();
|
|
10030
|
-
if (!
|
|
9980
|
+
if (!existsSync3(backupDir))
|
|
10031
9981
|
return [];
|
|
10032
9982
|
return readdirSync(backupDir).toSorted().toReversed();
|
|
10033
9983
|
}
|
|
10034
|
-
var
|
|
9984
|
+
var import_semver, CONFIG_VERSION = "2.0.0", LEGACY_INSTANCE_VERSION = "0.5", INSTANCE_MIGRATIONS;
|
|
10035
9985
|
var init_migration = __esm(() => {
|
|
10036
9986
|
init_paths();
|
|
10037
9987
|
init_constants();
|
|
10038
9988
|
init_version();
|
|
9989
|
+
init_env();
|
|
10039
9990
|
init_wrapper();
|
|
10040
9991
|
init_templates();
|
|
10041
|
-
|
|
9992
|
+
import_semver = __toESM(require_semver2(), 1);
|
|
10042
9993
|
INSTANCE_MIGRATIONS = [
|
|
10043
9994
|
{
|
|
10044
9995
|
version: "0.6.2",
|
|
@@ -10048,17 +9999,19 @@ var init_migration = __esm(() => {
|
|
|
10048
9999
|
if (instance.createdWithVersion && instance.createdWithVersion !== LEGACY_INSTANCE_VERSION && instance.createdWithVersion === currentVersion) {
|
|
10049
10000
|
return Promise.resolve(instance);
|
|
10050
10001
|
}
|
|
10051
|
-
if (
|
|
10052
|
-
const claudePath =
|
|
10002
|
+
if (existsSync3(instance.binaryPath)) {
|
|
10003
|
+
const claudePath = tryGetClaudePath();
|
|
10053
10004
|
if (claudePath !== null) {
|
|
10054
10005
|
const expected = buildWrapperScript(instance, claudePath);
|
|
10055
10006
|
try {
|
|
10056
10007
|
const current = readFileSync3(instance.binaryPath, "utf-8");
|
|
10057
10008
|
if (current !== expected) {
|
|
10058
|
-
|
|
10009
|
+
writeFileSync(instance.binaryPath, expected, { mode: 493 });
|
|
10059
10010
|
chmodSync2(instance.binaryPath, 493);
|
|
10060
10011
|
}
|
|
10061
10012
|
} catch {}
|
|
10013
|
+
} else {
|
|
10014
|
+
console.warn(`[migration] Could not find claude binary, skipping wrapper regeneration for instance: ${instance.name}`);
|
|
10062
10015
|
}
|
|
10063
10016
|
}
|
|
10064
10017
|
updateClaudeJson(instance.configDir);
|
|
@@ -10069,28 +10022,53 @@ var init_migration = __esm(() => {
|
|
|
10069
10022
|
version: "0.6.3",
|
|
10070
10023
|
description: "Sync provider template env vars (model names, thinking/output limits) to latest",
|
|
10071
10024
|
migrate: (instance) => {
|
|
10025
|
+
const currentVersion = getClaudeMultiVersion();
|
|
10026
|
+
if (instance.createdWithVersion && instance.createdWithVersion !== LEGACY_INSTANCE_VERSION && instance.createdWithVersion === currentVersion) {
|
|
10027
|
+
return Promise.resolve(instance);
|
|
10028
|
+
}
|
|
10072
10029
|
const providerName = instance.providerTemplate ?? detectProvider(instance.configDir);
|
|
10073
10030
|
if (!providerName)
|
|
10074
10031
|
return Promise.resolve(instance);
|
|
10075
|
-
|
|
10032
|
+
let template = getProviderTemplate(providerName);
|
|
10076
10033
|
if (!template)
|
|
10077
10034
|
return Promise.resolve(instance);
|
|
10078
|
-
const settingsFile =
|
|
10035
|
+
const settingsFile = join3(instance.configDir, "settings.json");
|
|
10079
10036
|
try {
|
|
10080
|
-
if (!
|
|
10037
|
+
if (!existsSync3(settingsFile))
|
|
10081
10038
|
return Promise.resolve(instance);
|
|
10082
10039
|
const existing = JSON.parse(readFileSync3(settingsFile, "utf-8"));
|
|
10083
10040
|
const existingEnv = existing.env ?? {};
|
|
10084
10041
|
const apiKey = existingEnv.ANTHROPIC_AUTH_TOKEN ?? "";
|
|
10042
|
+
const existingBaseUrl = existingEnv.ANTHROPIC_BASE_URL;
|
|
10043
|
+
let resolvedRegional = false;
|
|
10044
|
+
if (providerHasRegions(providerName)) {
|
|
10045
|
+
const providerRegions = getProviderRegions(providerName);
|
|
10046
|
+
const detectedRegion = detectRegionFromBaseUrl(existingBaseUrl ?? "") ?? instance.providerRegion;
|
|
10047
|
+
if (detectedRegion && providerRegions && detectedRegion in providerRegions) {
|
|
10048
|
+
template = resolveRegionTemplate(template, detectedRegion);
|
|
10049
|
+
instance.providerRegion = detectedRegion;
|
|
10050
|
+
resolvedRegional = true;
|
|
10051
|
+
}
|
|
10052
|
+
}
|
|
10085
10053
|
const templateSettings = structuredClone(template.settings);
|
|
10086
10054
|
const newEnv = { ...templateSettings.env, ANTHROPIC_AUTH_TOKEN: apiKey };
|
|
10055
|
+
if (providerHasRegions(providerName) && !resolvedRegional && existingBaseUrl) {
|
|
10056
|
+
newEnv.ANTHROPIC_BASE_URL = existingBaseUrl;
|
|
10057
|
+
}
|
|
10058
|
+
for (const key of TUNABLE_ENV_VARS) {
|
|
10059
|
+
if (key in existingEnv && existingEnv[key] !== templateSettings.env[key]) {
|
|
10060
|
+
newEnv[key] = existingEnv[key];
|
|
10061
|
+
}
|
|
10062
|
+
}
|
|
10087
10063
|
existing.env = { ...existingEnv, ...newEnv };
|
|
10088
10064
|
existing.includeCoAuthoredBy = template.settings.includeCoAuthoredBy;
|
|
10089
10065
|
existing.alwaysThinkingEnabled = template.settings.alwaysThinkingEnabled;
|
|
10090
|
-
|
|
10091
|
-
|
|
10092
|
-
|
|
10093
|
-
|
|
10066
|
+
writeFileSync(settingsFile, JSON.stringify(existing, null, 2), "utf-8");
|
|
10067
|
+
if (!instance.providerTemplate) {
|
|
10068
|
+
instance.providerTemplate = providerName;
|
|
10069
|
+
}
|
|
10070
|
+
} catch (err) {
|
|
10071
|
+
console.warn(`[migration] Failed to sync provider template for '${instance.name}': ${err instanceof Error ? err.message : String(err)}`);
|
|
10094
10072
|
}
|
|
10095
10073
|
return Promise.resolve(instance);
|
|
10096
10074
|
}
|
|
@@ -10105,6 +10083,7 @@ __export(exports_config, {
|
|
|
10105
10083
|
validatePluginOperation: () => validatePluginOperation,
|
|
10106
10084
|
updateInstanceAutoSync: () => updateInstanceAutoSync,
|
|
10107
10085
|
unsyncPluginsAndSkills: () => unsyncPluginsAndSkills,
|
|
10086
|
+
syncProviderTemplateForInstance: () => syncProviderTemplateForInstance,
|
|
10108
10087
|
syncPluginsAndSkills: () => syncPluginsAndSkills,
|
|
10109
10088
|
setTestDefaultClaudeDir: () => setTestDefaultClaudeDir,
|
|
10110
10089
|
setTestConfigDir: () => setTestConfigDir,
|
|
@@ -10151,11 +10130,11 @@ __export(exports_config, {
|
|
|
10151
10130
|
clearTestConfigDir: () => clearTestConfigDir,
|
|
10152
10131
|
addInstance: () => addInstance
|
|
10153
10132
|
});
|
|
10154
|
-
import { existsSync as
|
|
10133
|
+
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync2, statSync, readlinkSync, rmSync as rmSync2, lstatSync, readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync } from "node:fs";
|
|
10155
10134
|
import { readFile as readFile2, writeFile as writeFile3, copyFile, mkdir, symlink } from "node:fs/promises";
|
|
10156
10135
|
import { homedir as homedir2 } from "node:os";
|
|
10157
10136
|
import { randomBytes as randomBytes2 } from "node:crypto";
|
|
10158
|
-
import { dirname as dirname4, isAbsolute, join as
|
|
10137
|
+
import { dirname as dirname4, isAbsolute, join as join4, relative, resolve as resolve2 } from "node:path";
|
|
10159
10138
|
function setTestConfigDir(dir) {
|
|
10160
10139
|
_testConfigDir = dir;
|
|
10161
10140
|
}
|
|
@@ -10163,19 +10142,19 @@ function clearTestConfigDir() {
|
|
|
10163
10142
|
_testConfigDir = undefined;
|
|
10164
10143
|
}
|
|
10165
10144
|
function getConfigDir() {
|
|
10166
|
-
return _testConfigDir ??
|
|
10145
|
+
return _testConfigDir ?? join4(homedir2(), ".claude-multi");
|
|
10167
10146
|
}
|
|
10168
10147
|
function getConfigFile() {
|
|
10169
|
-
return
|
|
10148
|
+
return join4(getConfigDir(), "config.json");
|
|
10170
10149
|
}
|
|
10171
10150
|
async function copyDirRecursive(source, target) {
|
|
10172
|
-
if (!
|
|
10151
|
+
if (!existsSync4(target)) {
|
|
10173
10152
|
await mkdir(target, { recursive: true });
|
|
10174
10153
|
}
|
|
10175
10154
|
const entries = readdirSync2(source);
|
|
10176
10155
|
await Promise.all(entries.map(async (entry) => {
|
|
10177
|
-
const src =
|
|
10178
|
-
const tgt =
|
|
10156
|
+
const src = join4(source, entry);
|
|
10157
|
+
const tgt = join4(target, entry);
|
|
10179
10158
|
const s = statSync(src);
|
|
10180
10159
|
if (s.isDirectory()) {
|
|
10181
10160
|
await copyDirRecursive(src, tgt);
|
|
@@ -10192,8 +10171,8 @@ function lstatSafe(path) {
|
|
|
10192
10171
|
}
|
|
10193
10172
|
}
|
|
10194
10173
|
function ensureConfigDir() {
|
|
10195
|
-
if (!
|
|
10196
|
-
|
|
10174
|
+
if (!existsSync4(getConfigDir())) {
|
|
10175
|
+
mkdirSync3(getConfigDir(), { recursive: true });
|
|
10197
10176
|
}
|
|
10198
10177
|
}
|
|
10199
10178
|
function isConfig(raw) {
|
|
@@ -10201,7 +10180,7 @@ function isConfig(raw) {
|
|
|
10201
10180
|
}
|
|
10202
10181
|
async function loadConfig() {
|
|
10203
10182
|
ensureConfigDir();
|
|
10204
|
-
if (!
|
|
10183
|
+
if (!existsSync4(getConfigFile())) {
|
|
10205
10184
|
const defaultConfig = {
|
|
10206
10185
|
instances: [],
|
|
10207
10186
|
version: "2.0.0"
|
|
@@ -10297,7 +10276,7 @@ function getDefaultClaudeDir() {
|
|
|
10297
10276
|
if (_testDefaultClaudeDir) {
|
|
10298
10277
|
return _testDefaultClaudeDir;
|
|
10299
10278
|
}
|
|
10300
|
-
return
|
|
10279
|
+
return join4(homedir2(), ".claude");
|
|
10301
10280
|
}
|
|
10302
10281
|
function isBrokenSymlink(path) {
|
|
10303
10282
|
try {
|
|
@@ -10313,7 +10292,7 @@ function isBrokenSymlink(path) {
|
|
|
10313
10292
|
} else {
|
|
10314
10293
|
targetPath = resolve2(dirname4(path), target);
|
|
10315
10294
|
}
|
|
10316
|
-
return !
|
|
10295
|
+
return !existsSync4(targetPath);
|
|
10317
10296
|
} catch {
|
|
10318
10297
|
return false;
|
|
10319
10298
|
}
|
|
@@ -10321,7 +10300,7 @@ function isBrokenSymlink(path) {
|
|
|
10321
10300
|
function detectBrokenSymlinks(configDir) {
|
|
10322
10301
|
const result = { broken: [], all: [] };
|
|
10323
10302
|
for (const dir of SYNC_DIRS) {
|
|
10324
|
-
const targetPath =
|
|
10303
|
+
const targetPath = join4(configDir, dir);
|
|
10325
10304
|
try {
|
|
10326
10305
|
const stats = lstatSync(targetPath);
|
|
10327
10306
|
result.all.push(dir);
|
|
@@ -10334,13 +10313,13 @@ function detectBrokenSymlinks(configDir) {
|
|
|
10334
10313
|
}
|
|
10335
10314
|
function hasDefaultClaudeConfig() {
|
|
10336
10315
|
const defaultDir = getDefaultClaudeDir();
|
|
10337
|
-
const settingsFile =
|
|
10338
|
-
return
|
|
10316
|
+
const settingsFile = join4(defaultDir, "settings.json");
|
|
10317
|
+
return existsSync4(defaultDir) && existsSync4(settingsFile);
|
|
10339
10318
|
}
|
|
10340
10319
|
async function copySettingsFromDefault(targetConfigDir) {
|
|
10341
10320
|
const defaultDir = getDefaultClaudeDir();
|
|
10342
|
-
const sourceSettings =
|
|
10343
|
-
if (!
|
|
10321
|
+
const sourceSettings = join4(defaultDir, "settings.json");
|
|
10322
|
+
if (!existsSync4(sourceSettings)) {
|
|
10344
10323
|
throw new ClaudeMultiError(ErrorCode.DEFAULT_SETTINGS_NOT_FOUND, "Default Claude settings.json not found");
|
|
10345
10324
|
}
|
|
10346
10325
|
const content = await readFile2(sourceSettings, "utf-8");
|
|
@@ -10356,18 +10335,18 @@ async function copySettingsFromDefault(targetConfigDir) {
|
|
|
10356
10335
|
safeSettings[key] = settings[key];
|
|
10357
10336
|
}
|
|
10358
10337
|
}
|
|
10359
|
-
if (!
|
|
10338
|
+
if (!existsSync4(targetConfigDir)) {
|
|
10360
10339
|
await mkdir(targetConfigDir, { recursive: true });
|
|
10361
10340
|
}
|
|
10362
|
-
const targetSettings =
|
|
10341
|
+
const targetSettings = join4(targetConfigDir, "settings.json");
|
|
10363
10342
|
await writeFile3(targetSettings, JSON.stringify(safeSettings, null, 2), "utf-8");
|
|
10364
10343
|
}
|
|
10365
10344
|
async function copyAllFromDefault(targetConfigDir, autoSync = false) {
|
|
10366
10345
|
const defaultDir = getDefaultClaudeDir();
|
|
10367
|
-
if (!
|
|
10346
|
+
if (!existsSync4(defaultDir)) {
|
|
10368
10347
|
throw new ClaudeMultiError(ErrorCode.DEFAULT_DIR_NOT_FOUND, "Default Claude directory not found");
|
|
10369
10348
|
}
|
|
10370
|
-
if (!
|
|
10349
|
+
if (!existsSync4(targetConfigDir)) {
|
|
10371
10350
|
await mkdir(targetConfigDir, { recursive: true });
|
|
10372
10351
|
}
|
|
10373
10352
|
const excludeFiles = [
|
|
@@ -10390,8 +10369,8 @@ async function copyAllFromDefault(targetConfigDir, autoSync = false) {
|
|
|
10390
10369
|
const copyRecursive = async (source, target) => {
|
|
10391
10370
|
const entries = readdirSync2(source);
|
|
10392
10371
|
for (const entry of entries) {
|
|
10393
|
-
const sourcePath =
|
|
10394
|
-
const targetPath =
|
|
10372
|
+
const sourcePath = join4(source, entry);
|
|
10373
|
+
const targetPath = join4(target, entry);
|
|
10395
10374
|
const stat = statSync(sourcePath);
|
|
10396
10375
|
if (excludeSet.has(entry)) {
|
|
10397
10376
|
continue;
|
|
@@ -10415,7 +10394,7 @@ async function copyAllFromDefault(targetConfigDir, autoSync = false) {
|
|
|
10415
10394
|
await symlink(sourcePath, targetPath, "dir");
|
|
10416
10395
|
console.log(` Symlinked: ${entry} -> ${sourcePath}`);
|
|
10417
10396
|
} else {
|
|
10418
|
-
if (!
|
|
10397
|
+
if (!existsSync4(targetPath)) {
|
|
10419
10398
|
await mkdir(targetPath, { recursive: true });
|
|
10420
10399
|
}
|
|
10421
10400
|
await copyRecursive(sourcePath, targetPath);
|
|
@@ -10428,11 +10407,11 @@ async function copyAllFromDefault(targetConfigDir, autoSync = false) {
|
|
|
10428
10407
|
await copyRecursive(defaultDir, targetConfigDir);
|
|
10429
10408
|
}
|
|
10430
10409
|
async function detectMcpConfigurations(configDir) {
|
|
10431
|
-
if (!
|
|
10410
|
+
if (!existsSync4(configDir)) {
|
|
10432
10411
|
return null;
|
|
10433
10412
|
}
|
|
10434
|
-
const settingsFile =
|
|
10435
|
-
if (
|
|
10413
|
+
const settingsFile = join4(configDir, "settings.json");
|
|
10414
|
+
if (existsSync4(settingsFile)) {
|
|
10436
10415
|
try {
|
|
10437
10416
|
const settingsContent = await readFile2(settingsFile, "utf-8");
|
|
10438
10417
|
const settings = JSON.parse(settingsContent);
|
|
@@ -10443,8 +10422,8 @@ async function detectMcpConfigurations(configDir) {
|
|
|
10443
10422
|
}
|
|
10444
10423
|
const mcpFiles = ["mcp.json", "mcp-servers.json", "claude-mcp.json"];
|
|
10445
10424
|
for (const mcpFile of mcpFiles) {
|
|
10446
|
-
const mcpFilePath =
|
|
10447
|
-
if (
|
|
10425
|
+
const mcpFilePath = join4(configDir, mcpFile);
|
|
10426
|
+
if (existsSync4(mcpFilePath)) {
|
|
10448
10427
|
try {
|
|
10449
10428
|
const mcpContent = await readFile2(mcpFilePath, "utf-8");
|
|
10450
10429
|
const mcpConfig = JSON.parse(mcpContent);
|
|
@@ -10463,12 +10442,12 @@ async function hasDefaultMcpConfig() {
|
|
|
10463
10442
|
}
|
|
10464
10443
|
async function copyMcpServersFromDefault(targetConfigDir) {
|
|
10465
10444
|
const defaultDir = getDefaultClaudeDir();
|
|
10466
|
-
if (!
|
|
10445
|
+
if (!existsSync4(targetConfigDir)) {
|
|
10467
10446
|
await mkdir(targetConfigDir, { recursive: true });
|
|
10468
10447
|
}
|
|
10469
|
-
const pluginsDir =
|
|
10470
|
-
const defaultPluginsDir =
|
|
10471
|
-
if (
|
|
10448
|
+
const pluginsDir = join4(targetConfigDir, "plugins");
|
|
10449
|
+
const defaultPluginsDir = join4(defaultDir, "plugins");
|
|
10450
|
+
if (existsSync4(defaultPluginsDir) && !existsSync4(pluginsDir)) {
|
|
10472
10451
|
await copyDirRecursive(defaultPluginsDir, pluginsDir);
|
|
10473
10452
|
}
|
|
10474
10453
|
const mcpConfig = await detectMcpConfigurations(defaultDir);
|
|
@@ -10488,8 +10467,8 @@ async function copyMcpServersFromDefault(targetConfigDir) {
|
|
|
10488
10467
|
}
|
|
10489
10468
|
}
|
|
10490
10469
|
async function writeMcpConfiguration(targetConfigDir, mcpConfig) {
|
|
10491
|
-
const settingsFile =
|
|
10492
|
-
if (
|
|
10470
|
+
const settingsFile = join4(targetConfigDir, "settings.json");
|
|
10471
|
+
if (existsSync4(settingsFile)) {
|
|
10493
10472
|
try {
|
|
10494
10473
|
const settingsContent = await readFile2(settingsFile, "utf-8");
|
|
10495
10474
|
const settings = JSON.parse(settingsContent);
|
|
@@ -10498,7 +10477,7 @@ async function writeMcpConfiguration(targetConfigDir, mcpConfig) {
|
|
|
10498
10477
|
return;
|
|
10499
10478
|
} catch {}
|
|
10500
10479
|
}
|
|
10501
|
-
const mcpFile =
|
|
10480
|
+
const mcpFile = join4(targetConfigDir, "mcp.json");
|
|
10502
10481
|
await writeFile3(mcpFile, JSON.stringify(mcpConfig, null, 2), "utf-8");
|
|
10503
10482
|
}
|
|
10504
10483
|
async function copyMcpServersBetweenInstances(sourceInstanceName, targetInstanceName) {
|
|
@@ -10527,18 +10506,18 @@ async function listMcpServers(instanceName) {
|
|
|
10527
10506
|
return mcpConfig?.mcpServers || null;
|
|
10528
10507
|
}
|
|
10529
10508
|
async function createSettingsFromTemplate(targetConfigDir, template, apiKey) {
|
|
10530
|
-
if (!
|
|
10509
|
+
if (!existsSync4(targetConfigDir)) {
|
|
10531
10510
|
await mkdir(targetConfigDir, { recursive: true });
|
|
10532
10511
|
}
|
|
10533
10512
|
const settings = applyProviderTemplate(template, apiKey);
|
|
10534
|
-
const settingsFile =
|
|
10513
|
+
const settingsFile = join4(targetConfigDir, "settings.json");
|
|
10535
10514
|
await writeFile3(settingsFile, JSON.stringify(settings, null, 2), "utf-8");
|
|
10536
10515
|
}
|
|
10537
10516
|
async function initializeInstanceState(configDir) {
|
|
10538
|
-
const stateFile =
|
|
10539
|
-
if (
|
|
10517
|
+
const stateFile = join4(configDir, ".claude.json");
|
|
10518
|
+
if (existsSync4(stateFile))
|
|
10540
10519
|
return;
|
|
10541
|
-
if (!
|
|
10520
|
+
if (!existsSync4(configDir)) {
|
|
10542
10521
|
await mkdir(configDir, { recursive: true });
|
|
10543
10522
|
}
|
|
10544
10523
|
const state = {
|
|
@@ -10561,9 +10540,9 @@ async function initializeInstanceState(configDir) {
|
|
|
10561
10540
|
await writeFile3(stateFile, JSON.stringify(state, null, 2), "utf-8");
|
|
10562
10541
|
}
|
|
10563
10542
|
async function mergeProviderEnv(configDir, template, apiKey) {
|
|
10564
|
-
const settingsFile =
|
|
10543
|
+
const settingsFile = join4(configDir, "settings.json");
|
|
10565
10544
|
let existing = {};
|
|
10566
|
-
if (
|
|
10545
|
+
if (existsSync4(settingsFile)) {
|
|
10567
10546
|
const raw = await readFile2(settingsFile, "utf-8");
|
|
10568
10547
|
existing = JSON.parse(raw);
|
|
10569
10548
|
}
|
|
@@ -10573,22 +10552,81 @@ async function mergeProviderEnv(configDir, template, apiKey) {
|
|
|
10573
10552
|
existing.includeCoAuthoredBy = template.settings.includeCoAuthoredBy;
|
|
10574
10553
|
await writeFile3(settingsFile, JSON.stringify(existing, null, 2), "utf-8");
|
|
10575
10554
|
}
|
|
10555
|
+
async function syncProviderTemplateForInstance(instance) {
|
|
10556
|
+
const providerName = instance.providerTemplate ?? detectProvider(instance.configDir);
|
|
10557
|
+
if (!providerName) {
|
|
10558
|
+
throw new ClaudeMultiError(ErrorCode.INSTANCE_NOT_FOUND, `Could not detect provider for '${instance.name}'`);
|
|
10559
|
+
}
|
|
10560
|
+
let template = getProviderTemplate(providerName);
|
|
10561
|
+
if (!template) {
|
|
10562
|
+
throw new ClaudeMultiError(ErrorCode.INSTANCE_NOT_FOUND, `Unknown provider template '${providerName}'`);
|
|
10563
|
+
}
|
|
10564
|
+
const settingsFile = join4(instance.configDir, "settings.json");
|
|
10565
|
+
if (!existsSync4(settingsFile)) {
|
|
10566
|
+
throw new ClaudeMultiError(ErrorCode.INSTANCE_DIR_NOT_FOUND, `No settings.json found for '${instance.name}'`);
|
|
10567
|
+
}
|
|
10568
|
+
const raw = JSON.parse(readFileSync4(settingsFile, "utf-8"));
|
|
10569
|
+
const existingEnv = raw.env ?? {};
|
|
10570
|
+
const apiKey = existingEnv.ANTHROPIC_AUTH_TOKEN ?? "";
|
|
10571
|
+
const existingBaseUrl = existingEnv.ANTHROPIC_BASE_URL;
|
|
10572
|
+
let resolvedRegion = null;
|
|
10573
|
+
if (providerHasRegions(providerName)) {
|
|
10574
|
+
const detectedRegion = existingBaseUrl ? detectRegionFromBaseUrl(existingBaseUrl) ?? instance.providerRegion : instance.providerRegion;
|
|
10575
|
+
if (detectedRegion) {
|
|
10576
|
+
const providerRegions = getProviderRegions(providerName);
|
|
10577
|
+
if (providerRegions && detectedRegion in providerRegions) {
|
|
10578
|
+
template = resolveRegionTemplate(template, detectedRegion);
|
|
10579
|
+
resolvedRegion = detectedRegion;
|
|
10580
|
+
}
|
|
10581
|
+
}
|
|
10582
|
+
}
|
|
10583
|
+
const templateSettings = structuredClone(template.settings);
|
|
10584
|
+
const newEnv = { ...templateSettings.env, ANTHROPIC_AUTH_TOKEN: apiKey };
|
|
10585
|
+
if (providerHasRegions(providerName) && !resolvedRegion && existingBaseUrl) {
|
|
10586
|
+
newEnv.ANTHROPIC_BASE_URL = existingBaseUrl;
|
|
10587
|
+
}
|
|
10588
|
+
for (const key of TUNABLE_ENV_VARS) {
|
|
10589
|
+
if (key in existingEnv && existingEnv[key] !== templateSettings.env[key]) {
|
|
10590
|
+
newEnv[key] = existingEnv[key];
|
|
10591
|
+
}
|
|
10592
|
+
}
|
|
10593
|
+
raw.env = { ...existingEnv, ...newEnv };
|
|
10594
|
+
raw.includeCoAuthoredBy = template.settings.includeCoAuthoredBy;
|
|
10595
|
+
raw.alwaysThinkingEnabled = template.settings.alwaysThinkingEnabled;
|
|
10596
|
+
writeFileSync2(settingsFile, JSON.stringify(raw, null, 2), "utf-8");
|
|
10597
|
+
let needsSave = false;
|
|
10598
|
+
const config = await loadConfig();
|
|
10599
|
+
const inst = config.instances.find((i) => i.name === instance.name);
|
|
10600
|
+
if (inst) {
|
|
10601
|
+
if (!inst.providerTemplate) {
|
|
10602
|
+
inst.providerTemplate = providerName;
|
|
10603
|
+
needsSave = true;
|
|
10604
|
+
}
|
|
10605
|
+
if (providerHasRegions(providerName) && resolvedRegion && !inst.providerRegion) {
|
|
10606
|
+
inst.providerRegion = resolvedRegion;
|
|
10607
|
+
needsSave = true;
|
|
10608
|
+
}
|
|
10609
|
+
if (needsSave) {
|
|
10610
|
+
await saveConfigAtomic(config);
|
|
10611
|
+
}
|
|
10612
|
+
}
|
|
10613
|
+
}
|
|
10576
10614
|
async function syncPluginsAndSkills(configDir) {
|
|
10577
10615
|
const defaultDir = getDefaultClaudeDir();
|
|
10578
|
-
if (!
|
|
10616
|
+
if (!existsSync4(configDir)) {
|
|
10579
10617
|
throw new ClaudeMultiError(ErrorCode.INSTANCE_DIR_NOT_FOUND, "Instance config directory does not exist");
|
|
10580
10618
|
}
|
|
10581
10619
|
await Promise.all(SYNC_DIRS.map(async (dir) => {
|
|
10582
|
-
const targetPath =
|
|
10583
|
-
const sourcePath =
|
|
10584
|
-
if (!
|
|
10620
|
+
const targetPath = join4(configDir, dir);
|
|
10621
|
+
const sourcePath = join4(defaultDir, dir);
|
|
10622
|
+
if (!existsSync4(sourcePath)) {
|
|
10585
10623
|
console.log(source_default.yellow(` ⚠ Source ${dir} not found in ${defaultDir}, skipping`));
|
|
10586
10624
|
return;
|
|
10587
10625
|
}
|
|
10588
|
-
if (
|
|
10626
|
+
if (existsSync4(targetPath)) {
|
|
10589
10627
|
try {
|
|
10590
10628
|
const linkTarget = readlinkSync(targetPath);
|
|
10591
|
-
if (linkTarget === sourcePath || linkTarget ===
|
|
10629
|
+
if (linkTarget === sourcePath || linkTarget === join4("..", "..", ".claude", dir)) {
|
|
10592
10630
|
console.log(source_default.gray(` ✓ ${dir} already synced`));
|
|
10593
10631
|
return;
|
|
10594
10632
|
}
|
|
@@ -10605,8 +10643,8 @@ async function syncPluginsAndSkills(configDir) {
|
|
|
10605
10643
|
async function copyFilesRecursive(source, target) {
|
|
10606
10644
|
const entries = readdirSync2(source);
|
|
10607
10645
|
await Promise.all(entries.map(async (entry) => {
|
|
10608
|
-
const sourceEntry =
|
|
10609
|
-
const targetEntry =
|
|
10646
|
+
const sourceEntry = join4(source, entry);
|
|
10647
|
+
const targetEntry = join4(target, entry);
|
|
10610
10648
|
const stat = statSync(sourceEntry);
|
|
10611
10649
|
if (stat.isDirectory()) {
|
|
10612
10650
|
await mkdir(targetEntry, { recursive: true });
|
|
@@ -10618,13 +10656,13 @@ async function copyFilesRecursive(source, target) {
|
|
|
10618
10656
|
}
|
|
10619
10657
|
async function unsyncPluginsAndSkills(configDir) {
|
|
10620
10658
|
const defaultDir = getDefaultClaudeDir();
|
|
10621
|
-
if (!
|
|
10659
|
+
if (!existsSync4(configDir)) {
|
|
10622
10660
|
throw new ClaudeMultiError(ErrorCode.INSTANCE_DIR_NOT_FOUND, "Instance config directory does not exist");
|
|
10623
10661
|
}
|
|
10624
10662
|
await Promise.all(SYNC_DIRS.map(async (dir) => {
|
|
10625
|
-
const targetPath =
|
|
10626
|
-
const sourcePath =
|
|
10627
|
-
if (!
|
|
10663
|
+
const targetPath = join4(configDir, dir);
|
|
10664
|
+
const sourcePath = join4(defaultDir, dir);
|
|
10665
|
+
if (!existsSync4(sourcePath)) {
|
|
10628
10666
|
console.log(source_default.yellow(` ⚠ Source ${dir} not found in ${defaultDir}, skipping`));
|
|
10629
10667
|
return;
|
|
10630
10668
|
}
|
|
@@ -10636,7 +10674,7 @@ async function unsyncPluginsAndSkills(configDir) {
|
|
|
10636
10674
|
if (isSymlink) {
|
|
10637
10675
|
rmSync2(targetPath, { force: true });
|
|
10638
10676
|
console.log(source_default.gray(` ✓ Removed symlink for ${dir}`));
|
|
10639
|
-
} else if (!
|
|
10677
|
+
} else if (!existsSync4(targetPath)) {} else {
|
|
10640
10678
|
console.log(source_default.yellow(` ⚠ ${dir} is already a regular directory, skipping`));
|
|
10641
10679
|
return;
|
|
10642
10680
|
}
|
|
@@ -10646,8 +10684,8 @@ async function unsyncPluginsAndSkills(configDir) {
|
|
|
10646
10684
|
}));
|
|
10647
10685
|
}
|
|
10648
10686
|
async function readClaudeSettings(configDir) {
|
|
10649
|
-
const settingsFile =
|
|
10650
|
-
if (!
|
|
10687
|
+
const settingsFile = join4(configDir, "settings.json");
|
|
10688
|
+
if (!existsSync4(settingsFile)) {
|
|
10651
10689
|
return null;
|
|
10652
10690
|
}
|
|
10653
10691
|
try {
|
|
@@ -10659,10 +10697,10 @@ async function readClaudeSettings(configDir) {
|
|
|
10659
10697
|
}
|
|
10660
10698
|
}
|
|
10661
10699
|
async function writeClaudeSettings(configDir, settings) {
|
|
10662
|
-
if (!
|
|
10700
|
+
if (!existsSync4(configDir)) {
|
|
10663
10701
|
await mkdir(configDir, { recursive: true });
|
|
10664
10702
|
}
|
|
10665
|
-
await writeJsonFileAtomic(
|
|
10703
|
+
await writeJsonFileAtomic(join4(configDir, "settings.json"), settings);
|
|
10666
10704
|
}
|
|
10667
10705
|
async function getEnabledPlugins(configDir) {
|
|
10668
10706
|
const settings = await readClaudeSettings(configDir);
|
|
@@ -10712,18 +10750,18 @@ function readMcpJsonFile(mcpPath) {
|
|
|
10712
10750
|
}
|
|
10713
10751
|
function scanPluginDir(baseDir, category, enabledPlugins) {
|
|
10714
10752
|
const subDir = category === PluginCategory.Internal ? "plugins" : "external_plugins";
|
|
10715
|
-
const dir =
|
|
10716
|
-
if (!
|
|
10753
|
+
const dir = join4(baseDir, MARKETPLACE_REL, subDir);
|
|
10754
|
+
if (!existsSync4(dir))
|
|
10717
10755
|
return [];
|
|
10718
10756
|
const results = [];
|
|
10719
10757
|
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
10720
10758
|
if (!entry.isDirectory())
|
|
10721
10759
|
continue;
|
|
10722
|
-
const pluginPath =
|
|
10760
|
+
const pluginPath = join4(dir, entry.name);
|
|
10723
10761
|
let name = entry.name;
|
|
10724
10762
|
let description = "";
|
|
10725
|
-
const metaFile =
|
|
10726
|
-
if (
|
|
10763
|
+
const metaFile = join4(pluginPath, ".claude-plugin", "plugin.json");
|
|
10764
|
+
if (existsSync4(metaFile)) {
|
|
10727
10765
|
try {
|
|
10728
10766
|
const meta = JSON.parse(readFileSync4(metaFile, "utf-8"));
|
|
10729
10767
|
if (meta.name)
|
|
@@ -10734,8 +10772,8 @@ function scanPluginDir(baseDir, category, enabledPlugins) {
|
|
|
10734
10772
|
console.error(source_default.yellow(`Warning: Could not parse plugin metadata for ${entry.name}`));
|
|
10735
10773
|
}
|
|
10736
10774
|
}
|
|
10737
|
-
const mcpFile =
|
|
10738
|
-
const hasMcp =
|
|
10775
|
+
const mcpFile = join4(pluginPath, ".mcp.json");
|
|
10776
|
+
const hasMcp = existsSync4(mcpFile);
|
|
10739
10777
|
let mcpServerNames;
|
|
10740
10778
|
if (hasMcp) {
|
|
10741
10779
|
const servers = readMcpJsonFile(mcpFile);
|
|
@@ -10758,8 +10796,8 @@ function scanPluginDir(baseDir, category, enabledPlugins) {
|
|
|
10758
10796
|
}
|
|
10759
10797
|
function scanPluginsFromDir(baseDir) {
|
|
10760
10798
|
let enabledPlugins = {};
|
|
10761
|
-
const settingsFile =
|
|
10762
|
-
if (
|
|
10799
|
+
const settingsFile = join4(baseDir, "settings.json");
|
|
10800
|
+
if (existsSync4(settingsFile)) {
|
|
10763
10801
|
try {
|
|
10764
10802
|
const s = JSON.parse(readFileSync4(settingsFile, "utf-8"));
|
|
10765
10803
|
if (s.enabledPlugins)
|
|
@@ -10779,7 +10817,7 @@ function listInstancePlugins(configDir) {
|
|
|
10779
10817
|
return scanPluginsFromDir(configDir);
|
|
10780
10818
|
}
|
|
10781
10819
|
function isPluginsSymlinked(configDir) {
|
|
10782
|
-
const pluginsPath =
|
|
10820
|
+
const pluginsPath = join4(configDir, "plugins");
|
|
10783
10821
|
const st = lstatSafe(pluginsPath);
|
|
10784
10822
|
return st?.isSymbolicLink() ?? false;
|
|
10785
10823
|
}
|
|
@@ -10795,8 +10833,8 @@ function isClaudeCodeRunning(configDir) {
|
|
|
10795
10833
|
}
|
|
10796
10834
|
}
|
|
10797
10835
|
function readInstalledPlugins(pluginsDir) {
|
|
10798
|
-
const filePath =
|
|
10799
|
-
if (!
|
|
10836
|
+
const filePath = join4(pluginsDir, "installed_plugins.json");
|
|
10837
|
+
if (!existsSync4(filePath)) {
|
|
10800
10838
|
return { version: 2, plugins: {} };
|
|
10801
10839
|
}
|
|
10802
10840
|
try {
|
|
@@ -10806,16 +10844,16 @@ function readInstalledPlugins(pluginsDir) {
|
|
|
10806
10844
|
}
|
|
10807
10845
|
}
|
|
10808
10846
|
async function writeInstalledPlugins(pluginsDir, data) {
|
|
10809
|
-
await writeJsonFileAtomic(
|
|
10847
|
+
await writeJsonFileAtomic(join4(pluginsDir, "installed_plugins.json"), data);
|
|
10810
10848
|
}
|
|
10811
10849
|
async function addPluginToInstalledPlugins(configDir, pluginId) {
|
|
10812
|
-
const pluginsDir =
|
|
10850
|
+
const pluginsDir = join4(configDir, "plugins");
|
|
10813
10851
|
const data = readInstalledPlugins(pluginsDir);
|
|
10814
10852
|
const key = `${pluginId}@claude-plugins-official`;
|
|
10815
10853
|
if (!data.plugins[key]) {
|
|
10816
10854
|
data.plugins[key] = [];
|
|
10817
10855
|
}
|
|
10818
|
-
const cachePath =
|
|
10856
|
+
const cachePath = join4(configDir, MARKETPLACE_REL);
|
|
10819
10857
|
const entry = {
|
|
10820
10858
|
scope: "user",
|
|
10821
10859
|
installPath: cachePath,
|
|
@@ -10827,7 +10865,7 @@ async function addPluginToInstalledPlugins(configDir, pluginId) {
|
|
|
10827
10865
|
await writeInstalledPlugins(pluginsDir, data);
|
|
10828
10866
|
}
|
|
10829
10867
|
async function removePluginFromInstalledPlugins(configDir, pluginId) {
|
|
10830
|
-
const pluginsDir =
|
|
10868
|
+
const pluginsDir = join4(configDir, "plugins");
|
|
10831
10869
|
const data = readInstalledPlugins(pluginsDir);
|
|
10832
10870
|
const key = `${pluginId}@claude-plugins-official`;
|
|
10833
10871
|
delete data.plugins[key];
|
|
@@ -10837,7 +10875,7 @@ function estimatePluginSize(pluginPath) {
|
|
|
10837
10875
|
let total = 0;
|
|
10838
10876
|
try {
|
|
10839
10877
|
for (const entry of readdirSync2(pluginPath, { withFileTypes: true })) {
|
|
10840
|
-
const fullPath =
|
|
10878
|
+
const fullPath = join4(pluginPath, entry.name);
|
|
10841
10879
|
if (entry.isDirectory()) {
|
|
10842
10880
|
total += estimatePluginSize(fullPath);
|
|
10843
10881
|
} else {
|
|
@@ -10855,8 +10893,8 @@ function detectMcpCollisions(configDir, newPluginIds) {
|
|
|
10855
10893
|
const defaultDir = getDefaultClaudeDir();
|
|
10856
10894
|
for (const pluginId of newPluginIds) {
|
|
10857
10895
|
for (const subDir of ["plugins", "external_plugins"]) {
|
|
10858
|
-
const mcpFile =
|
|
10859
|
-
if (!
|
|
10896
|
+
const mcpFile = join4(defaultDir, MARKETPLACE_REL, subDir, pluginId, ".mcp.json");
|
|
10897
|
+
if (!existsSync4(mcpFile))
|
|
10860
10898
|
continue;
|
|
10861
10899
|
const newServers = readMcpJsonFile(mcpFile);
|
|
10862
10900
|
for (const name of Object.keys(newServers)) {
|
|
@@ -10875,10 +10913,10 @@ function detectMcpCollisions(configDir, newPluginIds) {
|
|
|
10875
10913
|
function validatePluginOperation(configDir, operation, pluginId) {
|
|
10876
10914
|
const errors = [];
|
|
10877
10915
|
const warnings = [];
|
|
10878
|
-
if (!
|
|
10916
|
+
if (!existsSync4(configDir)) {
|
|
10879
10917
|
errors.push("Instance config directory does not exist");
|
|
10880
10918
|
}
|
|
10881
|
-
if (
|
|
10919
|
+
if (existsSync4(configDir) && isPluginsSymlinked(configDir)) {
|
|
10882
10920
|
errors.push("Plugins directory is symlinked (auto-sync). Disable auto-sync first.");
|
|
10883
10921
|
}
|
|
10884
10922
|
if (operation === PluginAction.Install && pluginId) {
|
|
@@ -10893,7 +10931,7 @@ function validatePluginOperation(configDir, operation, pluginId) {
|
|
|
10893
10931
|
errors.push(`Plugin '${pluginId}' not installed in this instance`);
|
|
10894
10932
|
}
|
|
10895
10933
|
}
|
|
10896
|
-
if (operation === PluginAction.Install && pluginId &&
|
|
10934
|
+
if (operation === PluginAction.Install && pluginId && existsSync4(configDir)) {
|
|
10897
10935
|
const collisions = detectMcpCollisions(configDir, [pluginId]);
|
|
10898
10936
|
for (const c of collisions) {
|
|
10899
10937
|
warnings.push(`MCP server name collision: '${c.serverName}'`);
|
|
@@ -10904,27 +10942,27 @@ function validatePluginOperation(configDir, operation, pluginId) {
|
|
|
10904
10942
|
async function copySinglePlugin(targetConfigDir, pluginId, category) {
|
|
10905
10943
|
const defaultDir = getDefaultClaudeDir();
|
|
10906
10944
|
const subDir = category === PluginCategory.Internal ? "plugins" : "external_plugins";
|
|
10907
|
-
const sourcePlugin =
|
|
10908
|
-
const targetPlugin =
|
|
10909
|
-
if (!
|
|
10945
|
+
const sourcePlugin = join4(defaultDir, MARKETPLACE_REL, subDir, pluginId);
|
|
10946
|
+
const targetPlugin = join4(targetConfigDir, MARKETPLACE_REL, subDir, pluginId);
|
|
10947
|
+
if (!existsSync4(sourcePlugin)) {
|
|
10910
10948
|
throw new ClaudeMultiError(ErrorCode.PLUGIN_NOT_FOUND, `Plugin '${pluginId}' not found in default Claude`);
|
|
10911
10949
|
}
|
|
10912
|
-
const scaffoldDir =
|
|
10913
|
-
if (!
|
|
10950
|
+
const scaffoldDir = join4(targetConfigDir, MARKETPLACE_REL, subDir);
|
|
10951
|
+
if (!existsSync4(scaffoldDir)) {
|
|
10914
10952
|
await mkdir(scaffoldDir, { recursive: true });
|
|
10915
10953
|
}
|
|
10916
|
-
const marketplaceDir =
|
|
10917
|
-
if (!
|
|
10954
|
+
const marketplaceDir = join4(targetConfigDir, MARKETPLACE_REL);
|
|
10955
|
+
if (!existsSync4(marketplaceDir)) {
|
|
10918
10956
|
await mkdir(marketplaceDir, { recursive: true });
|
|
10919
10957
|
}
|
|
10920
10958
|
for (const metaFile of ["known_marketplaces.json", "blocklist.json"]) {
|
|
10921
|
-
const src =
|
|
10922
|
-
const tgt =
|
|
10923
|
-
if (
|
|
10959
|
+
const src = join4(defaultDir, MARKETPLACE_REL, metaFile);
|
|
10960
|
+
const tgt = join4(marketplaceDir, metaFile);
|
|
10961
|
+
if (existsSync4(src) && !existsSync4(tgt)) {
|
|
10924
10962
|
await copyFile(src, tgt);
|
|
10925
10963
|
}
|
|
10926
10964
|
}
|
|
10927
|
-
if (
|
|
10965
|
+
if (existsSync4(targetPlugin)) {
|
|
10928
10966
|
rmSync2(targetPlugin, { force: true, recursive: true });
|
|
10929
10967
|
}
|
|
10930
10968
|
await copyDirRecursive(sourcePlugin, targetPlugin);
|
|
@@ -10943,15 +10981,15 @@ async function copySelectedPlugins(targetConfigDir, selections) {
|
|
|
10943
10981
|
const defaultDir = getDefaultClaudeDir();
|
|
10944
10982
|
for (const sel of selections) {
|
|
10945
10983
|
const subDir = sel.category === PluginCategory.Internal ? "plugins" : "external_plugins";
|
|
10946
|
-
const source =
|
|
10947
|
-
if (!
|
|
10984
|
+
const source = join4(defaultDir, MARKETPLACE_REL, subDir, sel.id);
|
|
10985
|
+
if (!existsSync4(source)) {
|
|
10948
10986
|
throw new ClaudeMultiError(ErrorCode.PLUGIN_NOT_FOUND, `Plugin '${sel.id}' not found in default Claude`);
|
|
10949
10987
|
}
|
|
10950
10988
|
}
|
|
10951
10989
|
let totalSize = 0;
|
|
10952
10990
|
for (const sel of selections) {
|
|
10953
10991
|
const subDir = sel.category === PluginCategory.Internal ? "plugins" : "external_plugins";
|
|
10954
|
-
totalSize += estimatePluginSize(
|
|
10992
|
+
totalSize += estimatePluginSize(join4(defaultDir, MARKETPLACE_REL, subDir, sel.id));
|
|
10955
10993
|
}
|
|
10956
10994
|
if (totalSize > 104857600) {
|
|
10957
10995
|
throw new ClaudeMultiError(ErrorCode.PLUGIN_TOO_LARGE, `Selected plugins total ${(totalSize / 1024 / 1024).toFixed(1)}MB. Ensure sufficient disk space.`);
|
|
@@ -10966,8 +11004,8 @@ async function copySelectedPlugins(targetConfigDir, selections) {
|
|
|
10966
11004
|
for (const done of completed) {
|
|
10967
11005
|
try {
|
|
10968
11006
|
const subDir = done.category === PluginCategory.Internal ? "plugins" : "external_plugins";
|
|
10969
|
-
const targetPath =
|
|
10970
|
-
if (
|
|
11007
|
+
const targetPath = join4(targetConfigDir, MARKETPLACE_REL, subDir, done.id);
|
|
11008
|
+
if (existsSync4(targetPath)) {
|
|
10971
11009
|
rmSync2(targetPath, { force: true, recursive: true });
|
|
10972
11010
|
}
|
|
10973
11011
|
await removePluginFromInstalledPlugins(targetConfigDir, done.id);
|
|
@@ -10983,8 +11021,8 @@ async function removeSinglePlugin(configDir, pluginId, category) {
|
|
|
10983
11021
|
throw new ClaudeMultiError(ErrorCode.SYMLINK_CONFLICT, "Cannot remove plugins from a symlinked instance. Disable auto-sync first.");
|
|
10984
11022
|
}
|
|
10985
11023
|
const subDir = category === PluginCategory.Internal ? "plugins" : "external_plugins";
|
|
10986
|
-
const pluginPath =
|
|
10987
|
-
if (!
|
|
11024
|
+
const pluginPath = join4(configDir, MARKETPLACE_REL, subDir, pluginId);
|
|
11025
|
+
if (!existsSync4(pluginPath)) {
|
|
10988
11026
|
throw new ClaudeMultiError(ErrorCode.PLUGIN_NOT_FOUND, `Plugin '${pluginId}' not found in this instance`);
|
|
10989
11027
|
}
|
|
10990
11028
|
const backupPath = pluginPath + ".removing";
|
|
@@ -11007,16 +11045,16 @@ async function removeSinglePlugin(configDir, pluginId, category) {
|
|
|
11007
11045
|
}
|
|
11008
11046
|
function getMcpServersFromPlugins(configDir) {
|
|
11009
11047
|
const result = {};
|
|
11010
|
-
const basePlugins =
|
|
11048
|
+
const basePlugins = join4(configDir, MARKETPLACE_REL);
|
|
11011
11049
|
for (const subDir of ["plugins", "external_plugins"]) {
|
|
11012
|
-
const dir =
|
|
11013
|
-
if (!
|
|
11050
|
+
const dir = join4(basePlugins, subDir);
|
|
11051
|
+
if (!existsSync4(dir))
|
|
11014
11052
|
continue;
|
|
11015
11053
|
for (const entry of readdirSync2(dir, { withFileTypes: true })) {
|
|
11016
11054
|
if (!entry.isDirectory())
|
|
11017
11055
|
continue;
|
|
11018
|
-
const mcpFile =
|
|
11019
|
-
if (!
|
|
11056
|
+
const mcpFile = join4(dir, entry.name, ".mcp.json");
|
|
11057
|
+
if (!existsSync4(mcpFile))
|
|
11020
11058
|
continue;
|
|
11021
11059
|
const servers = readMcpJsonFile(mcpFile);
|
|
11022
11060
|
Object.assign(result, servers);
|
|
@@ -11051,6 +11089,7 @@ var init_config = __esm(() => {
|
|
|
11051
11089
|
init_json_file();
|
|
11052
11090
|
init_errors();
|
|
11053
11091
|
init_constants();
|
|
11092
|
+
init_env();
|
|
11054
11093
|
init_source();
|
|
11055
11094
|
SYNC_DIRS = ["plugins", "skills"];
|
|
11056
11095
|
});
|
|
@@ -33330,7 +33369,7 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
|
|
|
33330
33369
|
return 0;
|
|
33331
33370
|
};
|
|
33332
33371
|
var validate2 = function validate3(version) {
|
|
33333
|
-
return typeof version === "string" && /^[v\d]/.test(version) &&
|
|
33372
|
+
return typeof version === "string" && /^[v\d]/.test(version) && semver2.test(version);
|
|
33334
33373
|
};
|
|
33335
33374
|
var compare = function compare2(v1, v2, operator) {
|
|
33336
33375
|
assertValidOperator(operator);
|
|
@@ -33364,12 +33403,12 @@ In order to be iterable, non-array objects must have a [Symbol.iterator]() metho
|
|
|
33364
33403
|
return false;
|
|
33365
33404
|
return true;
|
|
33366
33405
|
};
|
|
33367
|
-
var
|
|
33406
|
+
var semver2 = /^[v^~<>=]*?(\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+)(?:\.([x*]|\d+))?(?:-([\da-z\-]+(?:\.[\da-z\-]+)*))?(?:\+[\da-z\-]+(?:\.[\da-z\-]+)*)?)?)?$/i;
|
|
33368
33407
|
var validateAndParse = function validateAndParse2(version) {
|
|
33369
33408
|
if (typeof version !== "string") {
|
|
33370
33409
|
throw new TypeError("Invalid argument expected string");
|
|
33371
33410
|
}
|
|
33372
|
-
var match = version.match(
|
|
33411
|
+
var match = version.match(semver2);
|
|
33373
33412
|
if (!match) {
|
|
33374
33413
|
throw new Error("Invalid argument not valid semver ('".concat(version, "' received)"));
|
|
33375
33414
|
}
|
|
@@ -56046,6 +56085,18 @@ function useConfig() {
|
|
|
56046
56085
|
}
|
|
56047
56086
|
await reload();
|
|
56048
56087
|
}, [reload]);
|
|
56088
|
+
const syncTemplateEnv = import_react66.useCallback(async (instance) => {
|
|
56089
|
+
await syncProviderTemplateForInstance(instance);
|
|
56090
|
+
await reload();
|
|
56091
|
+
}, [reload]);
|
|
56092
|
+
const regenerateWrapper = import_react66.useCallback(async (instance) => {
|
|
56093
|
+
await createWrapper({
|
|
56094
|
+
name: instance.name,
|
|
56095
|
+
configDir: instance.configDir,
|
|
56096
|
+
binaryPath: instance.binaryPath
|
|
56097
|
+
});
|
|
56098
|
+
await reload();
|
|
56099
|
+
}, [reload]);
|
|
56049
56100
|
const migrationStatus = config ? getMigrationStatus(config) : null;
|
|
56050
56101
|
return {
|
|
56051
56102
|
config,
|
|
@@ -56056,6 +56107,8 @@ function useConfig() {
|
|
|
56056
56107
|
addInstance: addInstance2,
|
|
56057
56108
|
removeInstance: removeInstance2,
|
|
56058
56109
|
toggleAutoSync,
|
|
56110
|
+
syncTemplateEnv,
|
|
56111
|
+
regenerateWrapper,
|
|
56059
56112
|
migrationStatus,
|
|
56060
56113
|
instanceMigrationVersion: config?.instanceMigrationVersion,
|
|
56061
56114
|
getInstance,
|
|
@@ -56125,7 +56178,7 @@ var exports_AddInstance = {};
|
|
|
56125
56178
|
__export(exports_AddInstance, {
|
|
56126
56179
|
AddInstance: () => AddInstance
|
|
56127
56180
|
});
|
|
56128
|
-
import { join as
|
|
56181
|
+
import { join as join6 } from "node:path";
|
|
56129
56182
|
import { homedir as homedir3 } from "node:os";
|
|
56130
56183
|
function stepNumber(step) {
|
|
56131
56184
|
return STEP_FLOW.indexOf(step) + 1;
|
|
@@ -56169,6 +56222,9 @@ function reducer5(state, action) {
|
|
|
56169
56222
|
case "SET_ERROR":
|
|
56170
56223
|
return { ...state, error: action.error };
|
|
56171
56224
|
case "SELECT_PROVIDER":
|
|
56225
|
+
if (!action.provider || !providerHasRegions(action.provider)) {
|
|
56226
|
+
return { ...state, selectedProvider: action.provider, useProvider: action.useProvider, selectedRegion: null };
|
|
56227
|
+
}
|
|
56172
56228
|
return { ...state, selectedProvider: action.provider, useProvider: action.useProvider };
|
|
56173
56229
|
case "SET_REGION":
|
|
56174
56230
|
return { ...state, selectedRegion: action.region };
|
|
@@ -56291,34 +56347,37 @@ var import_react67, jsx_dev_runtime4, AddResult = ({
|
|
|
56291
56347
|
onChange: onSelect
|
|
56292
56348
|
}, undefined, false, undefined, this)
|
|
56293
56349
|
]
|
|
56294
|
-
}, undefined, true, undefined, this), ProviderRegionStep = ({ state, onSelect }) =>
|
|
56295
|
-
|
|
56296
|
-
|
|
56297
|
-
|
|
56298
|
-
|
|
56299
|
-
|
|
56300
|
-
|
|
56301
|
-
|
|
56302
|
-
|
|
56303
|
-
|
|
56304
|
-
|
|
56305
|
-
|
|
56306
|
-
|
|
56307
|
-
|
|
56308
|
-
|
|
56350
|
+
}, undefined, true, undefined, this), ProviderRegionStep = ({ state, onSelect }) => {
|
|
56351
|
+
const regions = state.selectedProvider ? getProviderRegions(state.selectedProvider) : undefined;
|
|
56352
|
+
return /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
56353
|
+
flexDirection: "column",
|
|
56354
|
+
gap: 1,
|
|
56355
|
+
children: [
|
|
56356
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
56357
|
+
children: "Select your subscription region:"
|
|
56358
|
+
}, undefined, false, undefined, this),
|
|
56359
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
56360
|
+
borderStyle: "round",
|
|
56361
|
+
borderColor: "yellow",
|
|
56362
|
+
paddingX: 1,
|
|
56363
|
+
children: /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
56364
|
+
bold: true,
|
|
56365
|
+
color: "yellow",
|
|
56366
|
+
children: "Check your account console to confirm the correct region for your subscription."
|
|
56367
|
+
}, undefined, false, undefined, this)
|
|
56368
|
+
}, undefined, false, undefined, this),
|
|
56369
|
+
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Select, {
|
|
56370
|
+
options: regions ? Object.entries(regions).map(([key, val]) => ({
|
|
56371
|
+
label: `${val.label} — ${val.baseUrl}`,
|
|
56372
|
+
value: key
|
|
56373
|
+
})) : [],
|
|
56374
|
+
visibleOptionCount: 3,
|
|
56375
|
+
defaultValue: state.selectedRegion ?? undefined,
|
|
56376
|
+
onChange: onSelect
|
|
56309
56377
|
}, undefined, false, undefined, this)
|
|
56310
|
-
|
|
56311
|
-
|
|
56312
|
-
|
|
56313
|
-
label: `${val.label} — ${val.baseUrl}`,
|
|
56314
|
-
value: key
|
|
56315
|
-
})),
|
|
56316
|
-
visibleOptionCount: 3,
|
|
56317
|
-
defaultValue: state.selectedRegion ?? undefined,
|
|
56318
|
-
onChange: onSelect
|
|
56319
|
-
}, undefined, false, undefined, this)
|
|
56320
|
-
]
|
|
56321
|
-
}, undefined, true, undefined, this), ProviderApiKeyStep = ({ state, onSubmit }) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
56378
|
+
]
|
|
56379
|
+
}, undefined, true, undefined, this);
|
|
56380
|
+
}, ProviderApiKeyStep = ({ state, onSubmit }) => /* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Box_default, {
|
|
56322
56381
|
flexDirection: "column",
|
|
56323
56382
|
gap: 1,
|
|
56324
56383
|
children: [
|
|
@@ -56345,7 +56404,7 @@ var import_react67, jsx_dev_runtime4, AddResult = ({
|
|
|
56345
56404
|
dimColor: true,
|
|
56346
56405
|
children: [
|
|
56347
56406
|
"Config: ",
|
|
56348
|
-
|
|
56407
|
+
join6(homedir3(), `.claude-${state.name}`)
|
|
56349
56408
|
]
|
|
56350
56409
|
}, undefined, true, undefined, this),
|
|
56351
56410
|
/* @__PURE__ */ jsx_dev_runtime4.jsxDEV(Text, {
|
|
@@ -56475,7 +56534,7 @@ var import_react67, jsx_dev_runtime4, AddResult = ({
|
|
|
56475
56534
|
dispatch({ type: "SET_STEP", step: "creating" /* Creating */ });
|
|
56476
56535
|
dispatch({ type: "SET_ERROR", error: "" });
|
|
56477
56536
|
try {
|
|
56478
|
-
const cDir =
|
|
56537
|
+
const cDir = join6(homedir3(), `.claude-${state.name}`);
|
|
56479
56538
|
const bPath = cfg.getDefaultBinaryPath(state.name);
|
|
56480
56539
|
const instance = {
|
|
56481
56540
|
name: state.name,
|
|
@@ -56483,7 +56542,9 @@ var import_react67, jsx_dev_runtime4, AddResult = ({
|
|
|
56483
56542
|
binaryPath: bPath,
|
|
56484
56543
|
createdAt: new Date().toISOString(),
|
|
56485
56544
|
autoSync: sync,
|
|
56486
|
-
createdWithVersion: getClaudeMultiVersion()
|
|
56545
|
+
createdWithVersion: getClaudeMultiVersion(),
|
|
56546
|
+
...state.useProvider && state.selectedProvider ? { providerTemplate: state.selectedProvider } : {},
|
|
56547
|
+
...state.selectedRegion && state.useProvider && state.selectedProvider && providerHasRegions(state.selectedProvider) ? { providerRegion: state.selectedRegion } : {}
|
|
56487
56548
|
};
|
|
56488
56549
|
await cfg.addInstance(instance);
|
|
56489
56550
|
await Promise.all([
|
|
@@ -56717,10 +56778,11 @@ __export(exports_health, {
|
|
|
56717
56778
|
dismissIssue: () => dismissIssue,
|
|
56718
56779
|
dismissAllIssues: () => dismissAllIssues
|
|
56719
56780
|
});
|
|
56720
|
-
import { existsSync as
|
|
56721
|
-
import {
|
|
56781
|
+
import { existsSync as existsSync6, readFileSync as readFileSync6, writeFileSync as writeFileSync3, mkdirSync as mkdirSync4, renameSync as renameSync2, unlinkSync as unlinkSync2 } from "node:fs";
|
|
56782
|
+
import { randomBytes as randomBytes3 } from "node:crypto";
|
|
56783
|
+
import { join as join7 } from "node:path";
|
|
56722
56784
|
function getHealthFile() {
|
|
56723
|
-
return
|
|
56785
|
+
return join7(getBaseDir(), ".claude-multi", "health-status.json");
|
|
56724
56786
|
}
|
|
56725
56787
|
function runHealthChecks(instances2, migrationStatus, instanceMigrationVersion) {
|
|
56726
56788
|
const now2 = new Date().toISOString();
|
|
@@ -56757,7 +56819,7 @@ function runHealthChecks(instances2, migrationStatus, instanceMigrationVersion)
|
|
|
56757
56819
|
});
|
|
56758
56820
|
}
|
|
56759
56821
|
for (const inst of instances2) {
|
|
56760
|
-
if (!
|
|
56822
|
+
if (!existsSync6(inst.configDir)) {
|
|
56761
56823
|
issues.push({
|
|
56762
56824
|
id: `configdir-missing-${inst.name}`,
|
|
56763
56825
|
severity: "error",
|
|
@@ -56773,7 +56835,7 @@ function runHealthChecks(instances2, migrationStatus, instanceMigrationVersion)
|
|
|
56773
56835
|
});
|
|
56774
56836
|
continue;
|
|
56775
56837
|
}
|
|
56776
|
-
if (!
|
|
56838
|
+
if (!existsSync6(inst.binaryPath)) {
|
|
56777
56839
|
issues.push({
|
|
56778
56840
|
id: `binary-missing-${inst.name}`,
|
|
56779
56841
|
severity: "warning",
|
|
@@ -56788,10 +56850,11 @@ function runHealthChecks(instances2, migrationStatus, instanceMigrationVersion)
|
|
|
56788
56850
|
resolutionHint: "Re-create the instance or run 'claude-multi sync'"
|
|
56789
56851
|
});
|
|
56790
56852
|
}
|
|
56791
|
-
const settingsFile =
|
|
56792
|
-
if (
|
|
56853
|
+
const settingsFile = join7(inst.configDir, "settings.json");
|
|
56854
|
+
if (existsSync6(settingsFile)) {
|
|
56855
|
+
let parsed = null;
|
|
56793
56856
|
try {
|
|
56794
|
-
JSON.parse(readFileSync6(settingsFile, "utf-8"));
|
|
56857
|
+
parsed = JSON.parse(readFileSync6(settingsFile, "utf-8"));
|
|
56795
56858
|
} catch {
|
|
56796
56859
|
issues.push({
|
|
56797
56860
|
id: `settings-corrupt-${inst.name}`,
|
|
@@ -56807,6 +56870,29 @@ function runHealthChecks(instances2, migrationStatus, instanceMigrationVersion)
|
|
|
56807
56870
|
resolutionHint: "Fix or delete the corrupted settings.json"
|
|
56808
56871
|
});
|
|
56809
56872
|
}
|
|
56873
|
+
if (parsed && inst.providerTemplate && providerHasRegions(inst.providerTemplate)) {
|
|
56874
|
+
const env3 = parsed.env;
|
|
56875
|
+
const actualUrl = env3?.ANTHROPIC_BASE_URL;
|
|
56876
|
+
const actualRegion = actualUrl ? detectRegionFromBaseUrl(actualUrl) : null;
|
|
56877
|
+
if (inst.providerRegion && actualRegion && inst.providerRegion !== actualRegion) {
|
|
56878
|
+
const providerRegions = getProviderRegions(inst.providerTemplate);
|
|
56879
|
+
const expectedUrl = providerRegions?.[inst.providerRegion]?.baseUrl;
|
|
56880
|
+
issues.push({
|
|
56881
|
+
id: `region-mismatch-${inst.name}`,
|
|
56882
|
+
severity: "warning",
|
|
56883
|
+
category: "settings",
|
|
56884
|
+
title: "Region URL mismatch",
|
|
56885
|
+
message: `Instance '${inst.name}' stored region is ${inst.providerRegion} but base URL points to ${actualRegion}`,
|
|
56886
|
+
detail: `Stored region: ${inst.providerRegion} (${expectedUrl})
|
|
56887
|
+
Actual URL: ${actualUrl}`,
|
|
56888
|
+
instanceName: inst.name,
|
|
56889
|
+
timestamp: now2,
|
|
56890
|
+
dismissed: false,
|
|
56891
|
+
resolved: false,
|
|
56892
|
+
resolutionHint: `Edit settings.json to set ANTHROPIC_BASE_URL to ${expectedUrl}, or run 'claude-multi doctor fix'`
|
|
56893
|
+
});
|
|
56894
|
+
}
|
|
56895
|
+
}
|
|
56810
56896
|
}
|
|
56811
56897
|
const symlinks = detectBrokenSymlinks(inst.configDir);
|
|
56812
56898
|
if (symlinks.broken.length > 0) {
|
|
@@ -56824,13 +56910,15 @@ function runHealthChecks(instances2, migrationStatus, instanceMigrationVersion)
|
|
|
56824
56910
|
resolutionHint: "Re-sync symlinks from the home screen"
|
|
56825
56911
|
});
|
|
56826
56912
|
}
|
|
56827
|
-
|
|
56913
|
+
const expectedClaudePath = tryGetClaudePath();
|
|
56914
|
+
if (existsSync6(inst.binaryPath) && expectedClaudePath) {
|
|
56828
56915
|
try {
|
|
56829
56916
|
const wrapperContent = readFileSync6(inst.binaryPath, "utf-8");
|
|
56830
56917
|
const shellMatch = wrapperContent.match(/exec\s+"([^"]+)"/);
|
|
56918
|
+
const cmdMatch = wrapperContent.match(/"([^"]+)"\s+%\*/);
|
|
56831
56919
|
const nodeMatch = wrapperContent.match(/spawn\("([^"]+)"/);
|
|
56832
|
-
const currentBin = shellMatch?.[1] ?? nodeMatch?.[1];
|
|
56833
|
-
if (currentBin && currentBin !==
|
|
56920
|
+
const currentBin = shellMatch?.[1] ?? cmdMatch?.[1] ?? nodeMatch?.[1];
|
|
56921
|
+
if (currentBin && currentBin !== expectedClaudePath) {
|
|
56834
56922
|
issues.push({
|
|
56835
56923
|
id: `wrong-claude-version-${inst.name}`,
|
|
56836
56924
|
severity: "error",
|
|
@@ -56838,7 +56926,7 @@ function runHealthChecks(instances2, migrationStatus, instanceMigrationVersion)
|
|
|
56838
56926
|
title: "Wrong Claude binary",
|
|
56839
56927
|
message: `Instance '${inst.name}' uses a Claude version that may break 3rd-party providers`,
|
|
56840
56928
|
detail: `Current: ${currentBin}
|
|
56841
|
-
Expected: ${
|
|
56929
|
+
Expected: ${expectedClaudePath}`,
|
|
56842
56930
|
instanceName: inst.name,
|
|
56843
56931
|
timestamp: now2,
|
|
56844
56932
|
dismissed: false,
|
|
@@ -56868,7 +56956,7 @@ Expected: ${PINNED_CLAUDE_BIN}`,
|
|
|
56868
56956
|
}
|
|
56869
56957
|
function loadHealthStatus() {
|
|
56870
56958
|
const healthFile = getHealthFile();
|
|
56871
|
-
if (!
|
|
56959
|
+
if (!existsSync6(healthFile)) {
|
|
56872
56960
|
return { lastChecked: "", issues: [] };
|
|
56873
56961
|
}
|
|
56874
56962
|
try {
|
|
@@ -56878,10 +56966,21 @@ function loadHealthStatus() {
|
|
|
56878
56966
|
}
|
|
56879
56967
|
}
|
|
56880
56968
|
function saveHealthStatus(status) {
|
|
56881
|
-
const dir =
|
|
56882
|
-
if (!
|
|
56883
|
-
|
|
56884
|
-
|
|
56969
|
+
const dir = join7(getBaseDir(), ".claude-multi");
|
|
56970
|
+
if (!existsSync6(dir))
|
|
56971
|
+
mkdirSync4(dir, { recursive: true });
|
|
56972
|
+
const healthFile = getHealthFile();
|
|
56973
|
+
const tmpPath = `${healthFile}.tmp.${randomBytes3(4).toString("hex")}`;
|
|
56974
|
+
try {
|
|
56975
|
+
writeFileSync3(tmpPath, JSON.stringify(status, null, 2), "utf-8");
|
|
56976
|
+
JSON.parse(readFileSync6(tmpPath, "utf-8"));
|
|
56977
|
+
renameSync2(tmpPath, healthFile);
|
|
56978
|
+
} catch (err) {
|
|
56979
|
+
try {
|
|
56980
|
+
unlinkSync2(tmpPath);
|
|
56981
|
+
} catch {}
|
|
56982
|
+
throw err;
|
|
56983
|
+
}
|
|
56885
56984
|
}
|
|
56886
56985
|
function dismissIssue(id) {
|
|
56887
56986
|
const status = loadHealthStatus();
|
|
@@ -56899,20 +56998,22 @@ function dismissAllIssues() {
|
|
|
56899
56998
|
saveHealthStatus(status);
|
|
56900
56999
|
}
|
|
56901
57000
|
function fixWrapperVersions(instances2) {
|
|
56902
|
-
|
|
57001
|
+
const expectedClaudePath = tryGetClaudePath();
|
|
57002
|
+
if (!expectedClaudePath)
|
|
56903
57003
|
return [];
|
|
56904
57004
|
const fixed = [];
|
|
56905
57005
|
for (const inst of instances2) {
|
|
56906
|
-
if (!
|
|
57006
|
+
if (!existsSync6(inst.binaryPath))
|
|
56907
57007
|
continue;
|
|
56908
57008
|
try {
|
|
56909
57009
|
const content = readFileSync6(inst.binaryPath, "utf-8");
|
|
56910
57010
|
const shellMatch = content.match(/exec\s+"([^"]+)"/);
|
|
57011
|
+
const cmdMatch = content.match(/"([^"]+)"\s+%\*/);
|
|
56911
57012
|
const nodeMatch = content.match(/spawn\("([^"]+)"/);
|
|
56912
|
-
const currentBin = shellMatch?.[1] ?? nodeMatch?.[1];
|
|
56913
|
-
if (!currentBin || currentBin ===
|
|
57013
|
+
const currentBin = shellMatch?.[1] ?? cmdMatch?.[1] ?? nodeMatch?.[1];
|
|
57014
|
+
if (!currentBin || currentBin === expectedClaudePath)
|
|
56914
57015
|
continue;
|
|
56915
|
-
const newContent = buildWrapperScript(inst,
|
|
57016
|
+
const newContent = buildWrapperScript(inst, expectedClaudePath);
|
|
56916
57017
|
if (content !== newContent) {
|
|
56917
57018
|
writeFileSync3(inst.binaryPath, newContent, { mode: 493 });
|
|
56918
57019
|
}
|
|
@@ -56928,6 +57029,7 @@ var init_health = __esm(() => {
|
|
|
56928
57029
|
init_version();
|
|
56929
57030
|
init_migration();
|
|
56930
57031
|
init_wrapper();
|
|
57032
|
+
init_templates();
|
|
56931
57033
|
});
|
|
56932
57034
|
|
|
56933
57035
|
// src/ink/components/Footer.tsx
|
|
@@ -57071,12 +57173,12 @@ var jsx_dev_runtime6, WarningBanner = ({
|
|
|
57071
57173
|
children: [
|
|
57072
57174
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
57073
57175
|
color: "red",
|
|
57074
|
-
children: " ⚠ Some instances
|
|
57176
|
+
children: " ⚠ Some instances have version issues. "
|
|
57075
57177
|
}, undefined, false, undefined, this),
|
|
57076
57178
|
/* @__PURE__ */ jsx_dev_runtime6.jsxDEV(Text, {
|
|
57077
57179
|
color: "red",
|
|
57078
57180
|
bold: true,
|
|
57079
|
-
children: "Press ! to
|
|
57181
|
+
children: "Press ! to review and fix."
|
|
57080
57182
|
}, undefined, false, undefined, this)
|
|
57081
57183
|
]
|
|
57082
57184
|
}, undefined, true, undefined, this)
|
|
@@ -57348,7 +57450,110 @@ var init_InstanceSelectMenu = __esm(async () => {
|
|
|
57348
57450
|
jsx_dev_runtime9 = __toESM(require_jsx_dev_runtime(), 1);
|
|
57349
57451
|
});
|
|
57350
57452
|
|
|
57453
|
+
// src/ink/util/instance-diagnostics.ts
|
|
57454
|
+
import { existsSync as existsSync7, readFileSync as readFileSync7 } from "node:fs";
|
|
57455
|
+
import { join as join8 } from "node:path";
|
|
57456
|
+
function tryResolveRegionalTemplate(template2, region) {
|
|
57457
|
+
if (!template2)
|
|
57458
|
+
return;
|
|
57459
|
+
try {
|
|
57460
|
+
const providerRegions = getProviderRegions(template2.name);
|
|
57461
|
+
if (providerRegions && region in providerRegions) {
|
|
57462
|
+
return resolveRegionTemplate(template2, region);
|
|
57463
|
+
}
|
|
57464
|
+
} catch {}
|
|
57465
|
+
return;
|
|
57466
|
+
}
|
|
57467
|
+
function detectTemplateMismatch(instance) {
|
|
57468
|
+
const providerName = instance.providerTemplate ?? detectProvider(instance.configDir);
|
|
57469
|
+
if (!providerName) {
|
|
57470
|
+
return { status: "unknown", providerName: null };
|
|
57471
|
+
}
|
|
57472
|
+
let template2 = getProviderTemplate(providerName);
|
|
57473
|
+
if (!template2) {
|
|
57474
|
+
return { status: "unknown", providerName };
|
|
57475
|
+
}
|
|
57476
|
+
const settingsFile = join8(instance.configDir, "settings.json");
|
|
57477
|
+
if (!existsSync7(settingsFile)) {
|
|
57478
|
+
return { status: "unknown", providerName };
|
|
57479
|
+
}
|
|
57480
|
+
let existingEnv = {};
|
|
57481
|
+
try {
|
|
57482
|
+
const raw = JSON.parse(readFileSync7(settingsFile, "utf-8"));
|
|
57483
|
+
existingEnv = raw.env ?? {};
|
|
57484
|
+
} catch {
|
|
57485
|
+
return { status: "unknown", providerName };
|
|
57486
|
+
}
|
|
57487
|
+
if (providerHasRegions(providerName)) {
|
|
57488
|
+
const existingUrl = existingEnv.ANTHROPIC_BASE_URL;
|
|
57489
|
+
const detectedRegion = existingUrl ? detectRegionFromBaseUrl(existingUrl) ?? instance.providerRegion : instance.providerRegion;
|
|
57490
|
+
if (detectedRegion) {
|
|
57491
|
+
const resolved = tryResolveRegionalTemplate(template2, detectedRegion);
|
|
57492
|
+
if (resolved) {
|
|
57493
|
+
template2 = resolved;
|
|
57494
|
+
}
|
|
57495
|
+
}
|
|
57496
|
+
}
|
|
57497
|
+
const templateEnv = template2.settings.env;
|
|
57498
|
+
for (const [key, expectedValue] of Object.entries(templateEnv)) {
|
|
57499
|
+
if (key === "ANTHROPIC_AUTH_TOKEN")
|
|
57500
|
+
continue;
|
|
57501
|
+
if (TUNABLE_ENV_VARS.has(key))
|
|
57502
|
+
continue;
|
|
57503
|
+
if (existingEnv[key] !== expectedValue) {
|
|
57504
|
+
return { status: "mismatch", providerName };
|
|
57505
|
+
}
|
|
57506
|
+
}
|
|
57507
|
+
return { status: "match", providerName };
|
|
57508
|
+
}
|
|
57509
|
+
function detectWrapperMismatch(instance) {
|
|
57510
|
+
if (!existsSync7(instance.binaryPath)) {
|
|
57511
|
+
return { status: "missing" };
|
|
57512
|
+
}
|
|
57513
|
+
const expected = generateWrapperScriptSafe({
|
|
57514
|
+
name: instance.name,
|
|
57515
|
+
configDir: instance.configDir,
|
|
57516
|
+
binaryPath: instance.binaryPath
|
|
57517
|
+
});
|
|
57518
|
+
if (expected === null) {
|
|
57519
|
+
return { status: "unknown" };
|
|
57520
|
+
}
|
|
57521
|
+
try {
|
|
57522
|
+
const current = readFileSync7(instance.binaryPath, "utf-8");
|
|
57523
|
+
return current === expected ? { status: "match" } : { status: "mismatch" };
|
|
57524
|
+
} catch {
|
|
57525
|
+
return { status: "unknown" };
|
|
57526
|
+
}
|
|
57527
|
+
}
|
|
57528
|
+
var init_instance_diagnostics = __esm(() => {
|
|
57529
|
+
init_templates();
|
|
57530
|
+
init_wrapper();
|
|
57531
|
+
init_env();
|
|
57532
|
+
});
|
|
57533
|
+
|
|
57351
57534
|
// src/ink/screens/ShowInstanceInfo.tsx
|
|
57535
|
+
function templateStatusLabel(status) {
|
|
57536
|
+
switch (status) {
|
|
57537
|
+
case "match":
|
|
57538
|
+
return "✓ up to date";
|
|
57539
|
+
case "mismatch":
|
|
57540
|
+
return "⚠ mismatch detected";
|
|
57541
|
+
case "unknown":
|
|
57542
|
+
return "? unknown";
|
|
57543
|
+
}
|
|
57544
|
+
}
|
|
57545
|
+
function wrapperStatusLabel(status) {
|
|
57546
|
+
switch (status) {
|
|
57547
|
+
case "match":
|
|
57548
|
+
return "✓ up to date";
|
|
57549
|
+
case "mismatch":
|
|
57550
|
+
return "⚠ mismatch detected";
|
|
57551
|
+
case "missing":
|
|
57552
|
+
return "✗ wrapper missing";
|
|
57553
|
+
case "unknown":
|
|
57554
|
+
return "? unknown";
|
|
57555
|
+
}
|
|
57556
|
+
}
|
|
57352
57557
|
var import_react69, jsx_dev_runtime10, DetailRow = ({
|
|
57353
57558
|
label,
|
|
57354
57559
|
value,
|
|
@@ -57382,19 +57587,74 @@ var import_react69, jsx_dev_runtime10, DetailRow = ({
|
|
|
57382
57587
|
}, undefined, false, undefined, this)
|
|
57383
57588
|
]
|
|
57384
57589
|
}, undefined, true, undefined, this);
|
|
57385
|
-
}, EMPTY_INFO, ShowInstanceInfo = ({ onBack }) => {
|
|
57386
|
-
const {
|
|
57590
|
+
}, EMPTY_INFO, ACTION_VALUES, ShowInstanceInfo = ({ onBack }) => {
|
|
57591
|
+
const { exit } = use_app_default();
|
|
57592
|
+
const { instances: instances2, listInstancePlugins: listInstancePlugins2, getInstanceMcpServers: getInstanceMcpServers2, syncTemplateEnv, regenerateWrapper } = useConfig();
|
|
57387
57593
|
const [step, setStep] = import_react69.useState("select");
|
|
57388
57594
|
const [selected, setSelected] = import_react69.useState(null);
|
|
57389
57595
|
const [infoData, setInfoData] = import_react69.useState(EMPTY_INFO);
|
|
57390
|
-
|
|
57391
|
-
|
|
57392
|
-
|
|
57393
|
-
|
|
57394
|
-
|
|
57395
|
-
|
|
57596
|
+
const [templateStatus, setTemplateStatus] = import_react69.useState("unknown");
|
|
57597
|
+
const [wrapperStatus, setWrapperStatus] = import_react69.useState("unknown");
|
|
57598
|
+
const [providerName, setProviderName] = import_react69.useState(null);
|
|
57599
|
+
const [actionResult, setActionResult] = import_react69.useState(null);
|
|
57600
|
+
const [executing, setExecuting] = import_react69.useState(false);
|
|
57601
|
+
const liveSelected = selected ? instances2.find((i) => i.name === selected.name) ?? selected : null;
|
|
57602
|
+
const runDiagnostics = import_react69.useCallback((inst) => {
|
|
57603
|
+
const tmpl = detectTemplateMismatch(inst);
|
|
57604
|
+
const wrap2 = detectWrapperMismatch(inst);
|
|
57605
|
+
setTemplateStatus(tmpl.status);
|
|
57606
|
+
setWrapperStatus(wrap2.status);
|
|
57607
|
+
setProviderName(tmpl.providerName);
|
|
57608
|
+
}, []);
|
|
57609
|
+
const loadInstanceInfo = import_react69.useCallback(async (inst) => {
|
|
57610
|
+
try {
|
|
57611
|
+
const plugins = listInstancePlugins2(inst.configDir);
|
|
57612
|
+
const mcpData = await getInstanceMcpServers2(inst.configDir);
|
|
57613
|
+
setInfoData({
|
|
57614
|
+
pluginCount: plugins.length,
|
|
57615
|
+
enabledCount: plugins.filter((p) => p.enabled).length,
|
|
57616
|
+
mcpPluginCount: Object.keys(mcpData.fromPlugins).length,
|
|
57617
|
+
mcpCustomCount: Object.keys(mcpData.fromSettings).length,
|
|
57618
|
+
mcpCount: Object.keys(mcpData.all).length
|
|
57619
|
+
});
|
|
57620
|
+
} catch {
|
|
57621
|
+
setInfoData(EMPTY_INFO);
|
|
57622
|
+
}
|
|
57623
|
+
}, [listInstancePlugins2, getInstanceMcpServers2]);
|
|
57624
|
+
use_input_default((input, key) => {
|
|
57625
|
+
if (executing)
|
|
57626
|
+
return;
|
|
57627
|
+
if (input === "q") {
|
|
57628
|
+
exit();
|
|
57629
|
+
return;
|
|
57630
|
+
}
|
|
57631
|
+
if (key.escape) {
|
|
57632
|
+
if (step === "info") {
|
|
57633
|
+
setStep("select");
|
|
57634
|
+
setSelected(null);
|
|
57635
|
+
} else if (step === "actions") {
|
|
57636
|
+
setStep("info");
|
|
57637
|
+
} else if (step === "result") {
|
|
57638
|
+
goToInfo();
|
|
57639
|
+
} else {
|
|
57640
|
+
onBack();
|
|
57641
|
+
}
|
|
57642
|
+
} else if (key.return) {
|
|
57643
|
+
if (step === "info") {
|
|
57644
|
+
setStep("actions");
|
|
57645
|
+
} else if (step === "result") {
|
|
57646
|
+
goToInfo();
|
|
57647
|
+
}
|
|
57396
57648
|
}
|
|
57397
57649
|
});
|
|
57650
|
+
const goToInfo = () => {
|
|
57651
|
+
const inst = liveSelected;
|
|
57652
|
+
if (inst) {
|
|
57653
|
+
runDiagnostics(inst);
|
|
57654
|
+
loadInstanceInfo(inst);
|
|
57655
|
+
}
|
|
57656
|
+
setStep("info");
|
|
57657
|
+
};
|
|
57398
57658
|
if (instances2.length === 0) {
|
|
57399
57659
|
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57400
57660
|
flexDirection: "column",
|
|
@@ -57425,20 +57685,62 @@ var import_react69, jsx_dev_runtime10, DetailRow = ({
|
|
|
57425
57685
|
return;
|
|
57426
57686
|
setSelected(inst);
|
|
57427
57687
|
setStep("info");
|
|
57688
|
+
runDiagnostics(inst);
|
|
57689
|
+
await loadInstanceInfo(inst);
|
|
57690
|
+
};
|
|
57691
|
+
const handleAction = async (value) => {
|
|
57692
|
+
if (executing)
|
|
57693
|
+
return;
|
|
57694
|
+
if (value === ACTION_VALUES.Back || !selected) {
|
|
57695
|
+
setStep("info");
|
|
57696
|
+
return;
|
|
57697
|
+
}
|
|
57698
|
+
setActionResult(null);
|
|
57699
|
+
setExecuting(true);
|
|
57700
|
+
setStep("executing");
|
|
57428
57701
|
try {
|
|
57429
|
-
|
|
57430
|
-
|
|
57431
|
-
|
|
57432
|
-
|
|
57433
|
-
|
|
57434
|
-
|
|
57435
|
-
|
|
57436
|
-
|
|
57702
|
+
if (value === ACTION_VALUES.SyncTemplate) {
|
|
57703
|
+
await syncTemplateEnv(liveSelected ?? selected);
|
|
57704
|
+
setActionResult({ message: `Settings template updated for '${selected.name}'`, type: "success" });
|
|
57705
|
+
} else if (value === ACTION_VALUES.UpdateWrapper || value === ACTION_VALUES.OverrideWrapper) {
|
|
57706
|
+
await regenerateWrapper(liveSelected ?? selected);
|
|
57707
|
+
setActionResult({ message: `Alias wrapper regenerated for '${selected.name}'`, type: "success" });
|
|
57708
|
+
}
|
|
57709
|
+
} catch (err) {
|
|
57710
|
+
setActionResult({
|
|
57711
|
+
message: err instanceof Error ? err.message : String(err),
|
|
57712
|
+
type: "error"
|
|
57713
|
+
});
|
|
57714
|
+
}
|
|
57715
|
+
setExecuting(false);
|
|
57716
|
+
setStep("result");
|
|
57717
|
+
};
|
|
57718
|
+
const buildActionOptions = () => {
|
|
57719
|
+
const options = [];
|
|
57720
|
+
if (providerName) {
|
|
57721
|
+
options.push({
|
|
57722
|
+
label: `\uD83D\uDD04 Update settings template [${templateStatusLabel(templateStatus)}]`,
|
|
57723
|
+
value: ACTION_VALUES.SyncTemplate
|
|
57724
|
+
});
|
|
57725
|
+
}
|
|
57726
|
+
options.push({
|
|
57727
|
+
label: `\uD83D\uDD27 Update alias wrapper [${wrapperStatusLabel(wrapperStatus)}]`,
|
|
57728
|
+
value: ACTION_VALUES.UpdateWrapper
|
|
57729
|
+
});
|
|
57730
|
+
if (wrapperStatus === "mismatch" || wrapperStatus === "missing") {
|
|
57731
|
+
options.push({
|
|
57732
|
+
label: `\uD83D\uDD28 Override alias to standard`,
|
|
57733
|
+
value: ACTION_VALUES.OverrideWrapper
|
|
57437
57734
|
});
|
|
57438
|
-
} catch {
|
|
57439
|
-
setInfoData(EMPTY_INFO);
|
|
57440
57735
|
}
|
|
57736
|
+
options.push({ label: "← Back", value: ACTION_VALUES.Back });
|
|
57737
|
+
return options;
|
|
57441
57738
|
};
|
|
57739
|
+
const hasPlugins = infoData.pluginCount !== null;
|
|
57740
|
+
const hasMcp = infoData.mcpCount !== null;
|
|
57741
|
+
const hasProvider = providerName !== null;
|
|
57742
|
+
const lastRow = hasMcp ? "mcp" : hasPlugins ? "plugins" : hasProvider ? "provider" : "version";
|
|
57743
|
+
const displayInstance = liveSelected ?? selected;
|
|
57442
57744
|
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57443
57745
|
flexDirection: "column",
|
|
57444
57746
|
width: "100",
|
|
@@ -57452,7 +57754,7 @@ var import_react69, jsx_dev_runtime10, DetailRow = ({
|
|
|
57452
57754
|
instances: instances2,
|
|
57453
57755
|
onSelect: handleInstanceSelect
|
|
57454
57756
|
}, undefined, false, undefined, this),
|
|
57455
|
-
step === "info" &&
|
|
57757
|
+
step === "info" && displayInstance && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57456
57758
|
flexDirection: "column",
|
|
57457
57759
|
gap: 0,
|
|
57458
57760
|
children: [
|
|
@@ -57466,7 +57768,7 @@ var import_react69, jsx_dev_runtime10, DetailRow = ({
|
|
|
57466
57768
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57467
57769
|
bold: true,
|
|
57468
57770
|
color: "cyan",
|
|
57469
|
-
children:
|
|
57771
|
+
children: displayInstance.name
|
|
57470
57772
|
}, undefined, false, undefined, this)
|
|
57471
57773
|
]
|
|
57472
57774
|
}, undefined, true, undefined, this),
|
|
@@ -57476,53 +57778,186 @@ var import_react69, jsx_dev_runtime10, DetailRow = ({
|
|
|
57476
57778
|
children: [
|
|
57477
57779
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(DetailRow, {
|
|
57478
57780
|
label: "Binary",
|
|
57479
|
-
value:
|
|
57781
|
+
value: displayInstance.binaryPath,
|
|
57480
57782
|
delay: 50
|
|
57481
57783
|
}, undefined, false, undefined, this),
|
|
57482
57784
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(DetailRow, {
|
|
57483
57785
|
label: "Config",
|
|
57484
|
-
value:
|
|
57786
|
+
value: displayInstance.configDir,
|
|
57485
57787
|
delay: 100
|
|
57486
57788
|
}, undefined, false, undefined, this),
|
|
57487
57789
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(DetailRow, {
|
|
57488
57790
|
label: "Created",
|
|
57489
|
-
value: new Date(
|
|
57791
|
+
value: new Date(displayInstance.createdAt).toLocaleString(),
|
|
57490
57792
|
delay: 150
|
|
57491
57793
|
}, undefined, false, undefined, this),
|
|
57492
57794
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(DetailRow, {
|
|
57493
57795
|
label: "Auto-sync",
|
|
57494
|
-
value:
|
|
57495
|
-
color:
|
|
57796
|
+
value: displayInstance.autoSync !== false ? "✓ Enabled" : "✗ Disabled",
|
|
57797
|
+
color: displayInstance.autoSync !== false ? "green" : "red",
|
|
57496
57798
|
delay: 200
|
|
57497
57799
|
}, undefined, false, undefined, this),
|
|
57498
57800
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(DetailRow, {
|
|
57499
57801
|
label: "Version",
|
|
57500
|
-
value:
|
|
57501
|
-
color:
|
|
57802
|
+
value: displayInstance.createdWithVersion === LEGACY_INSTANCE_VERSION ? "before version tracking" : displayInstance.createdWithVersion,
|
|
57803
|
+
color: displayInstance.createdWithVersion === LEGACY_INSTANCE_VERSION ? "yellow" : undefined,
|
|
57804
|
+
last: lastRow === "version",
|
|
57502
57805
|
delay: 250
|
|
57503
57806
|
}, undefined, false, undefined, this),
|
|
57504
|
-
|
|
57807
|
+
hasProvider && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(DetailRow, {
|
|
57808
|
+
label: "Provider",
|
|
57809
|
+
value: providerName,
|
|
57810
|
+
color: templateStatus === "match" ? undefined : templateStatus === "mismatch" ? "yellow" : undefined,
|
|
57811
|
+
last: lastRow === "provider",
|
|
57812
|
+
delay: 275
|
|
57813
|
+
}, undefined, false, undefined, this),
|
|
57814
|
+
hasPlugins && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(DetailRow, {
|
|
57505
57815
|
label: "Plugins",
|
|
57506
57816
|
value: `${infoData.pluginCount} installed, ${infoData.enabledCount} enabled`,
|
|
57817
|
+
last: lastRow === "plugins",
|
|
57507
57818
|
delay: 300
|
|
57508
57819
|
}, undefined, false, undefined, this),
|
|
57509
|
-
|
|
57820
|
+
hasMcp && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(DetailRow, {
|
|
57510
57821
|
label: "MCP Servers",
|
|
57511
57822
|
value: `${infoData.mcpCount} total (${infoData.mcpPluginCount} from plugins, ${infoData.mcpCustomCount} custom)`,
|
|
57512
|
-
last:
|
|
57823
|
+
last: lastRow === "mcp",
|
|
57513
57824
|
delay: 350
|
|
57514
57825
|
}, undefined, false, undefined, this)
|
|
57515
57826
|
]
|
|
57516
57827
|
}, undefined, true, undefined, this)
|
|
57517
57828
|
]
|
|
57518
57829
|
}, undefined, true, undefined, this),
|
|
57830
|
+
step === "actions" && displayInstance && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57831
|
+
flexDirection: "column",
|
|
57832
|
+
gap: 1,
|
|
57833
|
+
children: [
|
|
57834
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57835
|
+
gap: 1,
|
|
57836
|
+
children: [
|
|
57837
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57838
|
+
color: "cyan",
|
|
57839
|
+
children: "●"
|
|
57840
|
+
}, undefined, false, undefined, this),
|
|
57841
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57842
|
+
bold: true,
|
|
57843
|
+
color: "cyan",
|
|
57844
|
+
children: displayInstance.name
|
|
57845
|
+
}, undefined, false, undefined, this)
|
|
57846
|
+
]
|
|
57847
|
+
}, undefined, true, undefined, this),
|
|
57848
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57849
|
+
marginTop: 1,
|
|
57850
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57851
|
+
bold: true,
|
|
57852
|
+
children: "Actions:"
|
|
57853
|
+
}, undefined, false, undefined, this)
|
|
57854
|
+
}, undefined, false, undefined, this),
|
|
57855
|
+
(() => {
|
|
57856
|
+
const actionOptions = buildActionOptions();
|
|
57857
|
+
return /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Select, {
|
|
57858
|
+
options: actionOptions,
|
|
57859
|
+
visibleOptionCount: actionOptions.length,
|
|
57860
|
+
onChange: handleAction
|
|
57861
|
+
}, undefined, false, undefined, this);
|
|
57862
|
+
})()
|
|
57863
|
+
]
|
|
57864
|
+
}, undefined, true, undefined, this),
|
|
57865
|
+
step === "executing" && displayInstance && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57866
|
+
flexDirection: "column",
|
|
57867
|
+
gap: 1,
|
|
57868
|
+
children: [
|
|
57869
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57870
|
+
gap: 1,
|
|
57871
|
+
children: [
|
|
57872
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57873
|
+
color: "cyan",
|
|
57874
|
+
children: "●"
|
|
57875
|
+
}, undefined, false, undefined, this),
|
|
57876
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57877
|
+
bold: true,
|
|
57878
|
+
color: "cyan",
|
|
57879
|
+
children: displayInstance.name
|
|
57880
|
+
}, undefined, false, undefined, this)
|
|
57881
|
+
]
|
|
57882
|
+
}, undefined, true, undefined, this),
|
|
57883
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57884
|
+
marginTop: 1,
|
|
57885
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Spinner, {
|
|
57886
|
+
label: "Updating..."
|
|
57887
|
+
}, undefined, false, undefined, this)
|
|
57888
|
+
}, undefined, false, undefined, this)
|
|
57889
|
+
]
|
|
57890
|
+
}, undefined, true, undefined, this),
|
|
57891
|
+
step === "result" && displayInstance && actionResult && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57892
|
+
flexDirection: "column",
|
|
57893
|
+
gap: 1,
|
|
57894
|
+
children: [
|
|
57895
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57896
|
+
gap: 1,
|
|
57897
|
+
children: [
|
|
57898
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57899
|
+
color: "cyan",
|
|
57900
|
+
children: "●"
|
|
57901
|
+
}, undefined, false, undefined, this),
|
|
57902
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57903
|
+
bold: true,
|
|
57904
|
+
color: "cyan",
|
|
57905
|
+
children: displayInstance.name
|
|
57906
|
+
}, undefined, false, undefined, this)
|
|
57907
|
+
]
|
|
57908
|
+
}, undefined, true, undefined, this),
|
|
57909
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57910
|
+
marginTop: 1,
|
|
57911
|
+
children: /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(StatusBar, {
|
|
57912
|
+
message: actionResult.message,
|
|
57913
|
+
type: actionResult.type
|
|
57914
|
+
}, undefined, false, undefined, this)
|
|
57915
|
+
}, undefined, false, undefined, this)
|
|
57916
|
+
]
|
|
57917
|
+
}, undefined, true, undefined, this),
|
|
57519
57918
|
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57520
57919
|
marginTop: 1,
|
|
57521
|
-
children:
|
|
57522
|
-
|
|
57523
|
-
|
|
57524
|
-
|
|
57525
|
-
|
|
57920
|
+
children: [
|
|
57921
|
+
step === "info" && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57922
|
+
gap: 2,
|
|
57923
|
+
children: [
|
|
57924
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57925
|
+
dimColor: true,
|
|
57926
|
+
children: "Enter for actions"
|
|
57927
|
+
}, undefined, false, undefined, this),
|
|
57928
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57929
|
+
dimColor: true,
|
|
57930
|
+
children: "ESC to go back"
|
|
57931
|
+
}, undefined, false, undefined, this),
|
|
57932
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57933
|
+
dimColor: true,
|
|
57934
|
+
children: "q quit"
|
|
57935
|
+
}, undefined, false, undefined, this)
|
|
57936
|
+
]
|
|
57937
|
+
}, undefined, true, undefined, this),
|
|
57938
|
+
step === "actions" && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57939
|
+
dimColor: true,
|
|
57940
|
+
children: "↑↓ navigate │ Enter select │ ESC back │ q quit"
|
|
57941
|
+
}, undefined, false, undefined, this),
|
|
57942
|
+
step === "result" && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Box_default, {
|
|
57943
|
+
gap: 2,
|
|
57944
|
+
children: [
|
|
57945
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57946
|
+
dimColor: true,
|
|
57947
|
+
children: "Enter/ESC to return"
|
|
57948
|
+
}, undefined, false, undefined, this),
|
|
57949
|
+
/* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57950
|
+
dimColor: true,
|
|
57951
|
+
children: "q quit"
|
|
57952
|
+
}, undefined, false, undefined, this)
|
|
57953
|
+
]
|
|
57954
|
+
}, undefined, true, undefined, this),
|
|
57955
|
+
step === "select" && /* @__PURE__ */ jsx_dev_runtime10.jsxDEV(Text, {
|
|
57956
|
+
dimColor: true,
|
|
57957
|
+
children: "ESC to go back │ q quit"
|
|
57958
|
+
}, undefined, false, undefined, this)
|
|
57959
|
+
]
|
|
57960
|
+
}, undefined, true, undefined, this)
|
|
57526
57961
|
]
|
|
57527
57962
|
}, undefined, true, undefined, this);
|
|
57528
57963
|
};
|
|
@@ -57530,10 +57965,12 @@ var init_ShowInstanceInfo = __esm(async () => {
|
|
|
57530
57965
|
init_useConfig();
|
|
57531
57966
|
init_useAnimations();
|
|
57532
57967
|
init_migration();
|
|
57968
|
+
init_instance_diagnostics();
|
|
57533
57969
|
await __promiseAll([
|
|
57534
57970
|
init_build2(),
|
|
57971
|
+
init_build3(),
|
|
57535
57972
|
init_Header(),
|
|
57536
|
-
|
|
57973
|
+
init_StatusBar(),
|
|
57537
57974
|
init_InstanceSelectMenu()
|
|
57538
57975
|
]);
|
|
57539
57976
|
import_react69 = __toESM(require_react(), 1);
|
|
@@ -57545,6 +57982,12 @@ var init_ShowInstanceInfo = __esm(async () => {
|
|
|
57545
57982
|
mcpPluginCount: null,
|
|
57546
57983
|
mcpCustomCount: null
|
|
57547
57984
|
};
|
|
57985
|
+
ACTION_VALUES = {
|
|
57986
|
+
SyncTemplate: "sync-template",
|
|
57987
|
+
UpdateWrapper: "update-wrapper",
|
|
57988
|
+
OverrideWrapper: "override-wrapper",
|
|
57989
|
+
Back: "back"
|
|
57990
|
+
};
|
|
57548
57991
|
});
|
|
57549
57992
|
|
|
57550
57993
|
// src/ink/screens/RemoveInstance.tsx
|
|
@@ -58965,61 +59408,8 @@ var init_ManageMcp = __esm(async () => {
|
|
|
58965
59408
|
};
|
|
58966
59409
|
});
|
|
58967
59410
|
|
|
58968
|
-
// src/ink/components/IssueCard.tsx
|
|
58969
|
-
var jsx_dev_runtime16, SEVERITY_ICONS, SEVERITY_COLORS, IssueCard = ({
|
|
58970
|
-
issue,
|
|
58971
|
-
index
|
|
58972
|
-
}) => {
|
|
58973
|
-
const visible = useFadeIn(index * 60 + 50);
|
|
58974
|
-
if (!visible)
|
|
58975
|
-
return null;
|
|
58976
|
-
const icon = SEVERITY_ICONS[issue.severity] ?? "•";
|
|
58977
|
-
const color = SEVERITY_COLORS[issue.severity] ?? "white";
|
|
58978
|
-
return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
58979
|
-
flexDirection: "column",
|
|
58980
|
-
marginLeft: 2,
|
|
58981
|
-
children: [
|
|
58982
|
-
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
58983
|
-
gap: 1,
|
|
58984
|
-
children: [
|
|
58985
|
-
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
58986
|
-
children: icon
|
|
58987
|
-
}, undefined, false, undefined, this),
|
|
58988
|
-
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
58989
|
-
bold: true,
|
|
58990
|
-
color,
|
|
58991
|
-
children: issue.title
|
|
58992
|
-
}, undefined, false, undefined, this)
|
|
58993
|
-
]
|
|
58994
|
-
}, undefined, true, undefined, this),
|
|
58995
|
-
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
58996
|
-
marginLeft: 2,
|
|
58997
|
-
children: /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
58998
|
-
dimColor: true,
|
|
58999
|
-
children: issue.message
|
|
59000
|
-
}, undefined, false, undefined, this)
|
|
59001
|
-
}, undefined, false, undefined, this)
|
|
59002
|
-
]
|
|
59003
|
-
}, undefined, true, undefined, this);
|
|
59004
|
-
};
|
|
59005
|
-
var init_IssueCard = __esm(async () => {
|
|
59006
|
-
init_useAnimations();
|
|
59007
|
-
await init_build2();
|
|
59008
|
-
jsx_dev_runtime16 = __toESM(require_jsx_dev_runtime(), 1);
|
|
59009
|
-
SEVERITY_ICONS = {
|
|
59010
|
-
error: "❌",
|
|
59011
|
-
warning: "⚠",
|
|
59012
|
-
info: "ℹ️"
|
|
59013
|
-
};
|
|
59014
|
-
SEVERITY_COLORS = {
|
|
59015
|
-
error: "red",
|
|
59016
|
-
warning: "yellow",
|
|
59017
|
-
info: "gray"
|
|
59018
|
-
};
|
|
59019
|
-
});
|
|
59020
|
-
|
|
59021
59411
|
// src/ink/screens/HealthScreen.tsx
|
|
59022
|
-
var import_react76,
|
|
59412
|
+
var import_react76, jsx_dev_runtime16, SEVERITY_ICONS, HealthScreen = ({
|
|
59023
59413
|
issues,
|
|
59024
59414
|
onDismiss,
|
|
59025
59415
|
onDismissAll,
|
|
@@ -59029,7 +59419,6 @@ var import_react76, jsx_dev_runtime17, HealthScreen = ({
|
|
|
59029
59419
|
}) => {
|
|
59030
59420
|
const [step, setStep] = import_react76.useState("list");
|
|
59031
59421
|
const [selectedIssue, setSelectedIssue] = import_react76.useState(null);
|
|
59032
|
-
const showActions = useFadeIn(100);
|
|
59033
59422
|
useNavigation(() => {
|
|
59034
59423
|
if (step === "detail") {
|
|
59035
59424
|
setStep("list");
|
|
@@ -59039,38 +59428,39 @@ var import_react76, jsx_dev_runtime17, HealthScreen = ({
|
|
|
59039
59428
|
}
|
|
59040
59429
|
});
|
|
59041
59430
|
use_input_default((input) => {
|
|
59042
|
-
if (step
|
|
59043
|
-
|
|
59044
|
-
|
|
59045
|
-
|
|
59046
|
-
|
|
59047
|
-
|
|
59048
|
-
|
|
59049
|
-
|
|
59050
|
-
|
|
59051
|
-
|
|
59052
|
-
|
|
59053
|
-
|
|
59054
|
-
|
|
59431
|
+
if (step === "list") {
|
|
59432
|
+
if (input === "D") {
|
|
59433
|
+
onDismissAll();
|
|
59434
|
+
} else if (input === "r") {
|
|
59435
|
+
onRetry();
|
|
59436
|
+
} else if (input === "f") {
|
|
59437
|
+
onFix();
|
|
59438
|
+
}
|
|
59439
|
+
} else if (step === "detail" && selectedIssue) {
|
|
59440
|
+
if (input === "d") {
|
|
59441
|
+
onDismiss(selectedIssue.id);
|
|
59442
|
+
setSelectedIssue(null);
|
|
59443
|
+
setStep("list");
|
|
59444
|
+
}
|
|
59055
59445
|
}
|
|
59056
59446
|
});
|
|
59057
59447
|
if (issues.length === 0) {
|
|
59058
|
-
return /* @__PURE__ */
|
|
59448
|
+
return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59059
59449
|
flexDirection: "column",
|
|
59060
59450
|
width: "100",
|
|
59061
59451
|
paddingX: 2,
|
|
59062
59452
|
paddingY: 1,
|
|
59063
59453
|
children: [
|
|
59064
|
-
/* @__PURE__ */
|
|
59454
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Header, {
|
|
59065
59455
|
title: "\uD83D\uDC9A System Health"
|
|
59066
59456
|
}, undefined, false, undefined, this),
|
|
59067
|
-
/* @__PURE__ */
|
|
59457
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(StatusBar, {
|
|
59068
59458
|
message: "All systems healthy!",
|
|
59069
59459
|
type: "success"
|
|
59070
59460
|
}, undefined, false, undefined, this),
|
|
59071
|
-
/* @__PURE__ */
|
|
59461
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59072
59462
|
marginTop: 1,
|
|
59073
|
-
children: /* @__PURE__ */
|
|
59463
|
+
children: /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59074
59464
|
dimColor: true,
|
|
59075
59465
|
children: "ESC to go back"
|
|
59076
59466
|
}, undefined, false, undefined, this)
|
|
@@ -59079,137 +59469,167 @@ var import_react76, jsx_dev_runtime17, HealthScreen = ({
|
|
|
59079
59469
|
}, undefined, true, undefined, this);
|
|
59080
59470
|
}
|
|
59081
59471
|
const hasVersionIssues = issues.some((i) => i.category === "version");
|
|
59082
|
-
|
|
59472
|
+
const handleIssueSelect = (value) => {
|
|
59473
|
+
const issue = issues.find((i) => i.id === value);
|
|
59474
|
+
if (issue) {
|
|
59475
|
+
setSelectedIssue(issue);
|
|
59476
|
+
setStep("detail");
|
|
59477
|
+
}
|
|
59478
|
+
};
|
|
59479
|
+
const issueOptions = issues.map((issue) => ({
|
|
59480
|
+
label: `${SEVERITY_ICONS[issue.severity] ?? "•"} ${issue.title}`,
|
|
59481
|
+
value: issue.id
|
|
59482
|
+
}));
|
|
59483
|
+
return /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59083
59484
|
flexDirection: "column",
|
|
59084
59485
|
width: "100",
|
|
59085
59486
|
paddingX: 2,
|
|
59086
59487
|
paddingY: 1,
|
|
59087
59488
|
children: [
|
|
59088
|
-
/* @__PURE__ */
|
|
59489
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Header, {
|
|
59089
59490
|
title: "⚠ System Health"
|
|
59090
59491
|
}, undefined, false, undefined, this),
|
|
59091
|
-
step === "list" && /* @__PURE__ */
|
|
59492
|
+
step === "list" && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59092
59493
|
flexDirection: "column",
|
|
59093
59494
|
gap: 1,
|
|
59094
59495
|
children: [
|
|
59095
|
-
/* @__PURE__ */
|
|
59496
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59096
59497
|
bold: true,
|
|
59097
59498
|
children: [
|
|
59098
59499
|
issues.length,
|
|
59099
|
-
" issue(s) found:"
|
|
59500
|
+
" issue(s) found — select one to view:"
|
|
59100
59501
|
]
|
|
59101
59502
|
}, undefined, true, undefined, this),
|
|
59102
|
-
|
|
59103
|
-
|
|
59104
|
-
|
|
59105
|
-
|
|
59106
|
-
|
|
59503
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Select, {
|
|
59504
|
+
options: issueOptions,
|
|
59505
|
+
visibleOptionCount: issueOptions.length,
|
|
59506
|
+
onChange: handleIssueSelect
|
|
59507
|
+
}, undefined, false, undefined, this),
|
|
59508
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59107
59509
|
marginTop: 1,
|
|
59108
59510
|
flexDirection: "column",
|
|
59109
59511
|
children: [
|
|
59110
|
-
hasVersionIssues && /* @__PURE__ */
|
|
59512
|
+
hasVersionIssues && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59111
59513
|
marginBottom: 1,
|
|
59112
59514
|
children: [
|
|
59113
|
-
/* @__PURE__ */
|
|
59515
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59114
59516
|
color: "cyan",
|
|
59115
59517
|
bold: true,
|
|
59116
59518
|
children: "f"
|
|
59117
59519
|
}, undefined, false, undefined, this),
|
|
59118
|
-
/* @__PURE__ */
|
|
59520
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59119
59521
|
color: "cyan",
|
|
59120
59522
|
children: " fix wrappers "
|
|
59121
59523
|
}, undefined, false, undefined, this),
|
|
59122
|
-
/* @__PURE__ */
|
|
59524
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59123
59525
|
dimColor: true,
|
|
59124
59526
|
children: "│"
|
|
59125
59527
|
}, undefined, false, undefined, this)
|
|
59126
59528
|
]
|
|
59127
59529
|
}, undefined, true, undefined, this),
|
|
59128
|
-
/* @__PURE__ */
|
|
59530
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59129
59531
|
dimColor: true,
|
|
59130
|
-
children: "
|
|
59532
|
+
children: "D dismiss all │ r retry │ ESC back"
|
|
59131
59533
|
}, undefined, false, undefined, this)
|
|
59132
59534
|
]
|
|
59133
59535
|
}, undefined, true, undefined, this)
|
|
59134
59536
|
]
|
|
59135
59537
|
}, undefined, true, undefined, this),
|
|
59136
|
-
step === "detail" && selectedIssue && /* @__PURE__ */
|
|
59538
|
+
step === "detail" && selectedIssue && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59137
59539
|
flexDirection: "column",
|
|
59138
59540
|
gap: 1,
|
|
59139
59541
|
children: [
|
|
59140
|
-
/* @__PURE__ */
|
|
59542
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59141
59543
|
bold: true,
|
|
59142
59544
|
children: selectedIssue.title
|
|
59143
59545
|
}, undefined, false, undefined, this),
|
|
59144
|
-
/* @__PURE__ */
|
|
59546
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59145
59547
|
marginLeft: 2,
|
|
59146
59548
|
flexDirection: "column",
|
|
59147
59549
|
children: [
|
|
59148
|
-
/* @__PURE__ */
|
|
59550
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59149
59551
|
gap: 1,
|
|
59150
59552
|
children: [
|
|
59151
|
-
/* @__PURE__ */
|
|
59553
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59152
59554
|
dimColor: true,
|
|
59153
59555
|
children: "├─"
|
|
59154
59556
|
}, undefined, false, undefined, this),
|
|
59155
|
-
/* @__PURE__ */
|
|
59557
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59156
59558
|
dimColor: true,
|
|
59157
59559
|
bold: true,
|
|
59158
59560
|
children: "Severity:"
|
|
59159
59561
|
}, undefined, false, undefined, this),
|
|
59160
|
-
/* @__PURE__ */
|
|
59562
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59161
59563
|
color: selectedIssue.severity === "error" ? "red" : "yellow",
|
|
59162
59564
|
children: selectedIssue.severity
|
|
59163
59565
|
}, undefined, false, undefined, this)
|
|
59164
59566
|
]
|
|
59165
59567
|
}, undefined, true, undefined, this),
|
|
59166
|
-
selectedIssue.instanceName && /* @__PURE__ */
|
|
59568
|
+
selectedIssue.instanceName && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59167
59569
|
gap: 1,
|
|
59168
59570
|
children: [
|
|
59169
|
-
/* @__PURE__ */
|
|
59571
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59170
59572
|
dimColor: true,
|
|
59171
59573
|
children: "├─"
|
|
59172
59574
|
}, undefined, false, undefined, this),
|
|
59173
|
-
/* @__PURE__ */
|
|
59575
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59174
59576
|
dimColor: true,
|
|
59175
59577
|
bold: true,
|
|
59176
59578
|
children: "Instance:"
|
|
59177
59579
|
}, undefined, false, undefined, this),
|
|
59178
|
-
/* @__PURE__ */
|
|
59580
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59179
59581
|
children: selectedIssue.instanceName
|
|
59180
59582
|
}, undefined, false, undefined, this)
|
|
59181
59583
|
]
|
|
59182
59584
|
}, undefined, true, undefined, this),
|
|
59183
|
-
/* @__PURE__ */
|
|
59585
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59184
59586
|
gap: 1,
|
|
59185
59587
|
children: [
|
|
59186
|
-
/* @__PURE__ */
|
|
59588
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59187
59589
|
dimColor: true,
|
|
59188
59590
|
children: "├─"
|
|
59189
59591
|
}, undefined, false, undefined, this),
|
|
59190
|
-
/* @__PURE__ */
|
|
59592
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59191
59593
|
dimColor: true,
|
|
59192
59594
|
bold: true,
|
|
59193
59595
|
children: "Detail:"
|
|
59194
59596
|
}, undefined, false, undefined, this),
|
|
59195
|
-
/* @__PURE__ */
|
|
59597
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59196
59598
|
children: selectedIssue.message
|
|
59197
59599
|
}, undefined, false, undefined, this)
|
|
59198
59600
|
]
|
|
59199
59601
|
}, undefined, true, undefined, this),
|
|
59200
|
-
selectedIssue.
|
|
59602
|
+
selectedIssue.detail && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59201
59603
|
gap: 1,
|
|
59202
59604
|
children: [
|
|
59203
|
-
/* @__PURE__ */
|
|
59605
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59606
|
+
dimColor: true,
|
|
59607
|
+
children: "├─"
|
|
59608
|
+
}, undefined, false, undefined, this),
|
|
59609
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59610
|
+
dimColor: true,
|
|
59611
|
+
bold: true,
|
|
59612
|
+
children: "Info:"
|
|
59613
|
+
}, undefined, false, undefined, this),
|
|
59614
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59615
|
+
dimColor: true,
|
|
59616
|
+
children: selectedIssue.detail
|
|
59617
|
+
}, undefined, false, undefined, this)
|
|
59618
|
+
]
|
|
59619
|
+
}, undefined, true, undefined, this),
|
|
59620
|
+
selectedIssue.resolutionHint && /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59621
|
+
gap: 1,
|
|
59622
|
+
children: [
|
|
59623
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59204
59624
|
dimColor: true,
|
|
59205
59625
|
children: "└─"
|
|
59206
59626
|
}, undefined, false, undefined, this),
|
|
59207
|
-
/* @__PURE__ */
|
|
59627
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59208
59628
|
dimColor: true,
|
|
59209
59629
|
bold: true,
|
|
59210
59630
|
children: "Fix:"
|
|
59211
59631
|
}, undefined, false, undefined, this),
|
|
59212
|
-
/* @__PURE__ */
|
|
59632
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59213
59633
|
dimColor: true,
|
|
59214
59634
|
children: selectedIssue.resolutionHint
|
|
59215
59635
|
}, undefined, false, undefined, this)
|
|
@@ -59217,18 +59637,18 @@ var import_react76, jsx_dev_runtime17, HealthScreen = ({
|
|
|
59217
59637
|
}, undefined, true, undefined, this)
|
|
59218
59638
|
]
|
|
59219
59639
|
}, undefined, true, undefined, this),
|
|
59220
|
-
/* @__PURE__ */
|
|
59640
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59221
59641
|
marginTop: 1,
|
|
59222
|
-
children: /* @__PURE__ */
|
|
59642
|
+
children: /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59223
59643
|
dimColor: true,
|
|
59224
59644
|
children: "d dismiss │ ESC back"
|
|
59225
59645
|
}, undefined, false, undefined, this)
|
|
59226
59646
|
}, undefined, false, undefined, this)
|
|
59227
59647
|
]
|
|
59228
59648
|
}, undefined, true, undefined, this),
|
|
59229
|
-
/* @__PURE__ */
|
|
59649
|
+
/* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Box_default, {
|
|
59230
59650
|
marginTop: 1,
|
|
59231
|
-
children: /* @__PURE__ */
|
|
59651
|
+
children: /* @__PURE__ */ jsx_dev_runtime16.jsxDEV(Text, {
|
|
59232
59652
|
dimColor: true,
|
|
59233
59653
|
children: "ESC to go back"
|
|
59234
59654
|
}, undefined, false, undefined, this)
|
|
@@ -59237,16 +59657,20 @@ var import_react76, jsx_dev_runtime17, HealthScreen = ({
|
|
|
59237
59657
|
}, undefined, true, undefined, this);
|
|
59238
59658
|
};
|
|
59239
59659
|
var init_HealthScreen = __esm(async () => {
|
|
59240
|
-
init_useAnimations();
|
|
59241
59660
|
await __promiseAll([
|
|
59242
59661
|
init_build2(),
|
|
59662
|
+
init_build3(),
|
|
59243
59663
|
init_Header(),
|
|
59244
59664
|
init_StatusBar(),
|
|
59245
|
-
init_IssueCard(),
|
|
59246
59665
|
init_useNavigation()
|
|
59247
59666
|
]);
|
|
59248
59667
|
import_react76 = __toESM(require_react(), 1);
|
|
59249
|
-
|
|
59668
|
+
jsx_dev_runtime16 = __toESM(require_jsx_dev_runtime(), 1);
|
|
59669
|
+
SEVERITY_ICONS = {
|
|
59670
|
+
error: "❌",
|
|
59671
|
+
warning: "⚠",
|
|
59672
|
+
info: "ℹ️"
|
|
59673
|
+
};
|
|
59250
59674
|
});
|
|
59251
59675
|
|
|
59252
59676
|
// src/ink/screens/UpdateScreen.tsx
|
|
@@ -59257,59 +59681,59 @@ function VersionCard({
|
|
|
59257
59681
|
hasUpdate,
|
|
59258
59682
|
failed
|
|
59259
59683
|
}) {
|
|
59260
|
-
return /* @__PURE__ */
|
|
59684
|
+
return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59261
59685
|
flexDirection: "column",
|
|
59262
59686
|
marginTop: 1,
|
|
59263
59687
|
children: [
|
|
59264
|
-
/* @__PURE__ */
|
|
59265
|
-
children: /* @__PURE__ */
|
|
59688
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59689
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
59266
59690
|
bold: true,
|
|
59267
59691
|
children: label
|
|
59268
59692
|
}, undefined, false, undefined, this)
|
|
59269
59693
|
}, undefined, false, undefined, this),
|
|
59270
|
-
/* @__PURE__ */
|
|
59694
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59271
59695
|
marginLeft: 2,
|
|
59272
59696
|
children: [
|
|
59273
|
-
/* @__PURE__ */
|
|
59697
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
59274
59698
|
dimColor: true,
|
|
59275
59699
|
children: "Current: "
|
|
59276
59700
|
}, undefined, false, undefined, this),
|
|
59277
|
-
/* @__PURE__ */
|
|
59701
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
59278
59702
|
color: failed ? "red" : hasUpdate ? "yellow" : "green",
|
|
59279
59703
|
children: current || (failed ? "check failed" : "not installed")
|
|
59280
59704
|
}, undefined, false, undefined, this)
|
|
59281
59705
|
]
|
|
59282
59706
|
}, undefined, true, undefined, this),
|
|
59283
|
-
/* @__PURE__ */
|
|
59707
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59284
59708
|
marginLeft: 2,
|
|
59285
59709
|
children: [
|
|
59286
|
-
/* @__PURE__ */
|
|
59710
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
59287
59711
|
dimColor: true,
|
|
59288
59712
|
children: "Latest: "
|
|
59289
59713
|
}, undefined, false, undefined, this),
|
|
59290
|
-
/* @__PURE__ */
|
|
59714
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
59291
59715
|
bold: true,
|
|
59292
59716
|
children: latest || (failed ? "unreachable" : "unknown")
|
|
59293
59717
|
}, undefined, false, undefined, this)
|
|
59294
59718
|
]
|
|
59295
59719
|
}, undefined, true, undefined, this),
|
|
59296
|
-
failed && /* @__PURE__ */
|
|
59720
|
+
failed && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59297
59721
|
marginLeft: 2,
|
|
59298
|
-
children: /* @__PURE__ */
|
|
59722
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
59299
59723
|
color: "red",
|
|
59300
59724
|
children: "✗ Could not reach npm registry"
|
|
59301
59725
|
}, undefined, false, undefined, this)
|
|
59302
59726
|
}, undefined, false, undefined, this),
|
|
59303
|
-
!failed && hasUpdate && /* @__PURE__ */
|
|
59727
|
+
!failed && hasUpdate && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59304
59728
|
marginLeft: 2,
|
|
59305
|
-
children: /* @__PURE__ */
|
|
59729
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
59306
59730
|
color: "yellow",
|
|
59307
59731
|
children: "▲ Update available"
|
|
59308
59732
|
}, undefined, false, undefined, this)
|
|
59309
59733
|
}, undefined, false, undefined, this),
|
|
59310
|
-
!failed && !hasUpdate && current && /* @__PURE__ */
|
|
59734
|
+
!failed && !hasUpdate && current && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59311
59735
|
marginLeft: 2,
|
|
59312
|
-
children: /* @__PURE__ */
|
|
59736
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
59313
59737
|
color: "green",
|
|
59314
59738
|
children: "✓ Up to date"
|
|
59315
59739
|
}, undefined, false, undefined, this)
|
|
@@ -59317,7 +59741,7 @@ function VersionCard({
|
|
|
59317
59741
|
]
|
|
59318
59742
|
}, undefined, true, undefined, this);
|
|
59319
59743
|
}
|
|
59320
|
-
var import_react77,
|
|
59744
|
+
var import_react77, jsx_dev_runtime17, UpdateScreen = ({ onBack }) => {
|
|
59321
59745
|
const { exit } = use_app_default();
|
|
59322
59746
|
const fadeIn = useFadeIn();
|
|
59323
59747
|
const { error, success, setError, setSuccess, clear } = useMessage();
|
|
@@ -59390,41 +59814,41 @@ var import_react77, jsx_dev_runtime18, UpdateScreen = ({ onBack }) => {
|
|
|
59390
59814
|
return null;
|
|
59391
59815
|
if (step === "loading" || step === "check-failed") {
|
|
59392
59816
|
const isFailed = step === "check-failed";
|
|
59393
|
-
return /* @__PURE__ */
|
|
59817
|
+
return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59394
59818
|
flexDirection: "column",
|
|
59395
59819
|
width: "100",
|
|
59396
59820
|
paddingX: 2,
|
|
59397
59821
|
paddingY: 1,
|
|
59398
59822
|
children: [
|
|
59399
|
-
/* @__PURE__ */
|
|
59823
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Header, {
|
|
59400
59824
|
title: "\uD83D\uDCE6 Updates"
|
|
59401
59825
|
}, undefined, false, undefined, this),
|
|
59402
|
-
isFailed ? /* @__PURE__ */
|
|
59826
|
+
isFailed ? /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(jsx_dev_runtime17.Fragment, {
|
|
59403
59827
|
children: [
|
|
59404
|
-
multiInfo && /* @__PURE__ */
|
|
59828
|
+
multiInfo && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(VersionCard, {
|
|
59405
59829
|
label: "claude-multi",
|
|
59406
59830
|
current: multiInfo.current || null,
|
|
59407
59831
|
latest: multiInfo.latest,
|
|
59408
59832
|
hasUpdate: multiInfo.updateAvailable,
|
|
59409
59833
|
failed: !multiInfo.current && !multiInfo.latest
|
|
59410
59834
|
}, undefined, false, undefined, this),
|
|
59411
|
-
claudeInfo && /* @__PURE__ */
|
|
59835
|
+
claudeInfo && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(VersionCard, {
|
|
59412
59836
|
label: "@anthropic-ai/claude-code",
|
|
59413
59837
|
current: claudeInfo.current,
|
|
59414
59838
|
latest: claudeInfo.latest,
|
|
59415
59839
|
hasUpdate: claudeInfo.updateAvailable,
|
|
59416
59840
|
failed: !claudeInfo.current && !claudeInfo.latest
|
|
59417
59841
|
}, undefined, false, undefined, this),
|
|
59418
|
-
error && /* @__PURE__ */
|
|
59842
|
+
error && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59419
59843
|
marginTop: 1,
|
|
59420
|
-
children: /* @__PURE__ */
|
|
59844
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(StatusBar, {
|
|
59421
59845
|
message: error,
|
|
59422
59846
|
type: "error"
|
|
59423
59847
|
}, undefined, false, undefined, this)
|
|
59424
59848
|
}, undefined, false, undefined, this),
|
|
59425
|
-
/* @__PURE__ */
|
|
59849
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59426
59850
|
marginTop: 1,
|
|
59427
|
-
children: /* @__PURE__ */
|
|
59851
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Select, {
|
|
59428
59852
|
options: [
|
|
59429
59853
|
{ label: "\uD83D\uDD04 Retry", value: "recheck" },
|
|
59430
59854
|
{ label: "↩️ Back to menu", value: "back" }
|
|
@@ -59442,9 +59866,9 @@ var import_react77, jsx_dev_runtime18, UpdateScreen = ({ onBack }) => {
|
|
|
59442
59866
|
}, undefined, false, undefined, this)
|
|
59443
59867
|
}, undefined, false, undefined, this)
|
|
59444
59868
|
]
|
|
59445
|
-
}, undefined, true, undefined, this) : /* @__PURE__ */
|
|
59869
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59446
59870
|
marginTop: 1,
|
|
59447
|
-
children: /* @__PURE__ */
|
|
59871
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Spinner, {
|
|
59448
59872
|
label: "Checking for updates..."
|
|
59449
59873
|
}, undefined, false, undefined, this)
|
|
59450
59874
|
}, undefined, false, undefined, this)
|
|
@@ -59452,24 +59876,24 @@ var import_react77, jsx_dev_runtime18, UpdateScreen = ({ onBack }) => {
|
|
|
59452
59876
|
}, undefined, true, undefined, this);
|
|
59453
59877
|
}
|
|
59454
59878
|
if (step === "updating") {
|
|
59455
|
-
return /* @__PURE__ */
|
|
59879
|
+
return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59456
59880
|
flexDirection: "column",
|
|
59457
59881
|
width: "100",
|
|
59458
59882
|
paddingX: 2,
|
|
59459
59883
|
paddingY: 1,
|
|
59460
59884
|
children: [
|
|
59461
|
-
/* @__PURE__ */
|
|
59885
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Header, {
|
|
59462
59886
|
title: "\uD83D\uDCE6 Updates"
|
|
59463
59887
|
}, undefined, false, undefined, this),
|
|
59464
|
-
/* @__PURE__ */
|
|
59888
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59465
59889
|
marginTop: 1,
|
|
59466
|
-
children: /* @__PURE__ */
|
|
59890
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Spinner, {
|
|
59467
59891
|
label: `Updating ${updatingTarget === "multi" ? "claude-multi" : "@anthropic-ai/claude-code"}...`
|
|
59468
59892
|
}, undefined, false, undefined, this)
|
|
59469
59893
|
}, undefined, false, undefined, this),
|
|
59470
|
-
/* @__PURE__ */
|
|
59894
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59471
59895
|
marginTop: 1,
|
|
59472
|
-
children: /* @__PURE__ */
|
|
59896
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Text, {
|
|
59473
59897
|
dimColor: true,
|
|
59474
59898
|
children: "Do not press ESC: update in progress"
|
|
59475
59899
|
}, undefined, false, undefined, this)
|
|
@@ -59488,44 +59912,44 @@ var import_react77, jsx_dev_runtime18, UpdateScreen = ({ onBack }) => {
|
|
|
59488
59912
|
}
|
|
59489
59913
|
actionOptions.push({ label: "\uD83D\uDD04 Re-check versions", value: "recheck" });
|
|
59490
59914
|
actionOptions.push({ label: "↩️ Back to menu", value: "back" });
|
|
59491
|
-
return /* @__PURE__ */
|
|
59915
|
+
return /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59492
59916
|
flexDirection: "column",
|
|
59493
59917
|
width: "100",
|
|
59494
59918
|
paddingX: 2,
|
|
59495
59919
|
paddingY: 1,
|
|
59496
59920
|
children: [
|
|
59497
|
-
/* @__PURE__ */
|
|
59921
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Header, {
|
|
59498
59922
|
title: "\uD83D\uDCE6 Updates"
|
|
59499
59923
|
}, undefined, false, undefined, this),
|
|
59500
|
-
/* @__PURE__ */
|
|
59924
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(VersionCard, {
|
|
59501
59925
|
label: "claude-multi",
|
|
59502
59926
|
current: multiInfo?.current ?? null,
|
|
59503
59927
|
latest: multiInfo?.latest ?? "",
|
|
59504
59928
|
hasUpdate: multiUpdate
|
|
59505
59929
|
}, undefined, false, undefined, this),
|
|
59506
|
-
/* @__PURE__ */
|
|
59930
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(VersionCard, {
|
|
59507
59931
|
label: "@anthropic-ai/claude-code",
|
|
59508
59932
|
current: claudeInfo?.current ?? null,
|
|
59509
59933
|
latest: claudeInfo?.latest ?? "",
|
|
59510
59934
|
hasUpdate: claudeUpdate
|
|
59511
59935
|
}, undefined, false, undefined, this),
|
|
59512
|
-
error && /* @__PURE__ */
|
|
59936
|
+
error && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59513
59937
|
marginTop: 1,
|
|
59514
|
-
children: /* @__PURE__ */
|
|
59938
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(StatusBar, {
|
|
59515
59939
|
message: error,
|
|
59516
59940
|
type: "error"
|
|
59517
59941
|
}, undefined, false, undefined, this)
|
|
59518
59942
|
}, undefined, false, undefined, this),
|
|
59519
|
-
success && /* @__PURE__ */
|
|
59943
|
+
success && /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59520
59944
|
marginTop: 1,
|
|
59521
|
-
children: /* @__PURE__ */
|
|
59945
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(StatusBar, {
|
|
59522
59946
|
message: success,
|
|
59523
59947
|
type: "success"
|
|
59524
59948
|
}, undefined, false, undefined, this)
|
|
59525
59949
|
}, undefined, false, undefined, this),
|
|
59526
|
-
/* @__PURE__ */
|
|
59950
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Box_default, {
|
|
59527
59951
|
marginTop: 1,
|
|
59528
|
-
children: /* @__PURE__ */
|
|
59952
|
+
children: /* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Select, {
|
|
59529
59953
|
options: actionOptions,
|
|
59530
59954
|
onChange: (value) => {
|
|
59531
59955
|
if (value === "back") {
|
|
@@ -59543,7 +59967,7 @@ var import_react77, jsx_dev_runtime18, UpdateScreen = ({ onBack }) => {
|
|
|
59543
59967
|
}
|
|
59544
59968
|
}, undefined, false, undefined, this)
|
|
59545
59969
|
}, undefined, false, undefined, this),
|
|
59546
|
-
/* @__PURE__ */
|
|
59970
|
+
/* @__PURE__ */ jsx_dev_runtime17.jsxDEV(Footer, {}, undefined, false, undefined, this)
|
|
59547
59971
|
]
|
|
59548
59972
|
}, undefined, true, undefined, this);
|
|
59549
59973
|
};
|
|
@@ -59559,7 +59983,7 @@ var init_UpdateScreen = __esm(async () => {
|
|
|
59559
59983
|
init_Footer()
|
|
59560
59984
|
]);
|
|
59561
59985
|
import_react77 = __toESM(require_react(), 1);
|
|
59562
|
-
|
|
59986
|
+
jsx_dev_runtime17 = __toESM(require_jsx_dev_runtime(), 1);
|
|
59563
59987
|
});
|
|
59564
59988
|
|
|
59565
59989
|
// src/ink/App.tsx
|
|
@@ -59567,75 +59991,59 @@ var exports_App = {};
|
|
|
59567
59991
|
__export(exports_App, {
|
|
59568
59992
|
App: () => App2
|
|
59569
59993
|
});
|
|
59570
|
-
|
|
59571
|
-
import { existsSync as existsSync8 } from "node:fs";
|
|
59572
|
-
var import_react78, jsx_dev_runtime19, GoodbyeScreen = () => {
|
|
59994
|
+
var import_react78, jsx_dev_runtime18, GoodbyeScreen = () => {
|
|
59573
59995
|
const msg = useTypewriter("\uD83D\uDC4B Goodbye!", 40);
|
|
59574
|
-
return /* @__PURE__ */
|
|
59996
|
+
return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
|
|
59575
59997
|
paddingX: 2,
|
|
59576
59998
|
paddingY: 1,
|
|
59577
|
-
children: /* @__PURE__ */
|
|
59999
|
+
children: /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
|
|
59578
60000
|
dimColor: true,
|
|
59579
60001
|
children: msg
|
|
59580
60002
|
}, undefined, false, undefined, this)
|
|
59581
60003
|
}, undefined, false, undefined, this);
|
|
59582
|
-
}, DoctorResultScreen = ({ fixedCount, migratedCount,
|
|
60004
|
+
}, DoctorResultScreen = ({ fixedCount, migratedCount, onBack }) => {
|
|
59583
60005
|
useNavigation(onBack);
|
|
59584
|
-
return /* @__PURE__ */
|
|
60006
|
+
return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
|
|
59585
60007
|
flexDirection: "column",
|
|
59586
60008
|
width: "100",
|
|
59587
60009
|
paddingX: 2,
|
|
59588
60010
|
paddingY: 1,
|
|
59589
60011
|
children: [
|
|
59590
|
-
/* @__PURE__ */
|
|
59591
|
-
title: "
|
|
60012
|
+
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Header, {
|
|
60013
|
+
title: "Doctor Fix"
|
|
59592
60014
|
}, undefined, false, undefined, this),
|
|
59593
|
-
|
|
59594
|
-
children: [
|
|
59595
|
-
/* @__PURE__ */ jsx_dev_runtime19.jsxDEV(StatusBar, {
|
|
59596
|
-
message: "Failed to install pinned Claude binary",
|
|
59597
|
-
type: "error"
|
|
59598
|
-
}, undefined, false, undefined, this),
|
|
59599
|
-
/* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Box_default, {
|
|
59600
|
-
marginTop: 1,
|
|
59601
|
-
children: /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
|
|
59602
|
-
dimColor: true,
|
|
59603
|
-
children: "Check your network connection and try again."
|
|
59604
|
-
}, undefined, false, undefined, this)
|
|
59605
|
-
}, undefined, false, undefined, this)
|
|
59606
|
-
]
|
|
59607
|
-
}, undefined, true, undefined, this) : fixedCount > 0 || migratedCount > 0 ? /* @__PURE__ */ jsx_dev_runtime19.jsxDEV(jsx_dev_runtime19.Fragment, {
|
|
60015
|
+
fixedCount > 0 || migratedCount > 0 ? /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(jsx_dev_runtime18.Fragment, {
|
|
59608
60016
|
children: [
|
|
59609
|
-
fixedCount > 0 && /* @__PURE__ */
|
|
60017
|
+
fixedCount > 0 && /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(jsx_dev_runtime18.Fragment, {
|
|
59610
60018
|
children: [
|
|
59611
|
-
/* @__PURE__ */
|
|
59612
|
-
message: `Fixed ${fixedCount} wrapper(s) to use
|
|
60019
|
+
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(StatusBar, {
|
|
60020
|
+
message: `Fixed ${fixedCount} wrapper(s) to use global Claude binary`,
|
|
59613
60021
|
type: "success"
|
|
59614
60022
|
}, undefined, false, undefined, this),
|
|
59615
|
-
/* @__PURE__ */
|
|
60023
|
+
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
|
|
59616
60024
|
marginTop: 1,
|
|
59617
|
-
children: /* @__PURE__ */
|
|
60025
|
+
children: /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
|
|
59618
60026
|
dimColor: true,
|
|
59619
|
-
children: "All
|
|
60027
|
+
children: "All instances now use the globally installed Claude binary."
|
|
59620
60028
|
}, undefined, false, undefined, this)
|
|
59621
60029
|
}, undefined, false, undefined, this)
|
|
59622
60030
|
]
|
|
59623
60031
|
}, undefined, true, undefined, this),
|
|
59624
|
-
migratedCount > 0 && /* @__PURE__ */
|
|
60032
|
+
migratedCount > 0 && /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
|
|
59625
60033
|
marginTop: fixedCount > 0 ? 1 : 0,
|
|
59626
|
-
children: /* @__PURE__ */
|
|
60034
|
+
children: /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(StatusBar, {
|
|
59627
60035
|
message: `Migrated ${migratedCount} instance(s) to v${getClaudeMultiVersion()}`,
|
|
59628
60036
|
type: "success"
|
|
59629
60037
|
}, undefined, false, undefined, this)
|
|
59630
60038
|
}, undefined, false, undefined, this)
|
|
59631
60039
|
]
|
|
59632
|
-
}, undefined, true, undefined, this) : /* @__PURE__ */
|
|
60040
|
+
}, undefined, true, undefined, this) : /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(StatusBar, {
|
|
59633
60041
|
message: "All wrappers already use the correct Claude version",
|
|
59634
60042
|
type: "info"
|
|
59635
60043
|
}, undefined, false, undefined, this),
|
|
59636
|
-
/* @__PURE__ */
|
|
60044
|
+
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
|
|
59637
60045
|
marginTop: 1,
|
|
59638
|
-
children: /* @__PURE__ */
|
|
60046
|
+
children: /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
|
|
59639
60047
|
dimColor: true,
|
|
59640
60048
|
children: "ESC to go back"
|
|
59641
60049
|
}, undefined, false, undefined, this)
|
|
@@ -59646,9 +60054,9 @@ var import_react78, jsx_dev_runtime19, GoodbyeScreen = () => {
|
|
|
59646
60054
|
const visible = useFadeIn(100);
|
|
59647
60055
|
if (!visible || instances2.length === 0)
|
|
59648
60056
|
return null;
|
|
59649
|
-
return /* @__PURE__ */
|
|
60057
|
+
return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
|
|
59650
60058
|
marginBottom: 1,
|
|
59651
|
-
children: /* @__PURE__ */
|
|
60059
|
+
children: /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Text, {
|
|
59652
60060
|
dimColor: true,
|
|
59653
60061
|
children: [
|
|
59654
60062
|
instances2.length,
|
|
@@ -59660,23 +60068,15 @@ var import_react78, jsx_dev_runtime19, GoodbyeScreen = () => {
|
|
|
59660
60068
|
}, undefined, false, undefined, this);
|
|
59661
60069
|
}, App2 = () => {
|
|
59662
60070
|
const { exit } = use_app_default();
|
|
59663
|
-
const { instances: instances2, loading, migrationStatus, instanceMigrationVersion } = useConfig();
|
|
60071
|
+
const { instances: instances2, loading, migrationStatus, instanceMigrationVersion, reload } = useConfig();
|
|
59664
60072
|
const { issues, dismiss, dismissAll, retry } = useHealthCheck(instances2, migrationStatus, instanceMigrationVersion);
|
|
59665
60073
|
const [screen, setScreen] = import_react78.useState("menu");
|
|
59666
60074
|
const [menuKey, setMenuKey] = import_react78.useState(0);
|
|
59667
|
-
const [ccVersion] = import_react78.useState(() => {
|
|
59668
|
-
try {
|
|
59669
|
-
const output = execSync3("claude --version 2>/dev/null", { encoding: "utf-8", timeout: 5000 }).trim();
|
|
59670
|
-
return output.split(" ")[0] || null;
|
|
59671
|
-
} catch {
|
|
59672
|
-
return null;
|
|
59673
|
-
}
|
|
59674
|
-
});
|
|
59675
60075
|
const [doctorResult, setDoctorResult] = import_react78.useState({
|
|
59676
60076
|
fixedCount: 0,
|
|
59677
|
-
migratedCount: 0
|
|
59678
|
-
installFailed: false
|
|
60077
|
+
migratedCount: 0
|
|
59679
60078
|
});
|
|
60079
|
+
const [doctorRunning, setDoctorRunning] = import_react78.useState(false);
|
|
59680
60080
|
use_input_default((input, key) => {
|
|
59681
60081
|
if (screen !== "menu")
|
|
59682
60082
|
return;
|
|
@@ -59688,10 +60088,10 @@ var import_react78, jsx_dev_runtime19, GoodbyeScreen = () => {
|
|
|
59688
60088
|
}
|
|
59689
60089
|
});
|
|
59690
60090
|
if (loading) {
|
|
59691
|
-
return /* @__PURE__ */
|
|
60091
|
+
return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
|
|
59692
60092
|
paddingX: 2,
|
|
59693
60093
|
paddingY: 1,
|
|
59694
|
-
children: /* @__PURE__ */
|
|
60094
|
+
children: /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Spinner, {
|
|
59695
60095
|
label: "Loading..."
|
|
59696
60096
|
}, undefined, false, undefined, this)
|
|
59697
60097
|
}, undefined, false, undefined, this);
|
|
@@ -59701,45 +60101,35 @@ var import_react78, jsx_dev_runtime19, GoodbyeScreen = () => {
|
|
|
59701
60101
|
setMenuKey((k) => k + 1);
|
|
59702
60102
|
};
|
|
59703
60103
|
const handleDoctorFix = async () => {
|
|
59704
|
-
|
|
59705
|
-
|
|
60104
|
+
if (doctorRunning)
|
|
60105
|
+
return;
|
|
60106
|
+
setDoctorRunning(true);
|
|
60107
|
+
try {
|
|
60108
|
+
const fixed = fixWrapperVersions(instances2);
|
|
60109
|
+
let migrated = 0;
|
|
59706
60110
|
try {
|
|
59707
|
-
|
|
59708
|
-
|
|
59709
|
-
|
|
59710
|
-
|
|
59711
|
-
|
|
59712
|
-
|
|
59713
|
-
|
|
59714
|
-
|
|
59715
|
-
installPinnedClaude();
|
|
59716
|
-
} catch {
|
|
59717
|
-
installFailed = true;
|
|
60111
|
+
const fullConfig = await loadConfig();
|
|
60112
|
+
if (needsInstanceMigration(fullConfig)) {
|
|
60113
|
+
const before2 = fullConfig.instanceMigrationVersion;
|
|
60114
|
+
const migratedConfig = await runInstanceMigrations(fullConfig);
|
|
60115
|
+
if (migratedConfig.instanceMigrationVersion !== before2) {
|
|
60116
|
+
await saveConfigAtomic(migratedConfig);
|
|
60117
|
+
migrated = fullConfig.instances.length;
|
|
60118
|
+
}
|
|
59718
60119
|
}
|
|
59719
|
-
}
|
|
60120
|
+
} catch {}
|
|
60121
|
+
setDoctorResult({ fixedCount: fixed.length, migratedCount: migrated });
|
|
60122
|
+
await reload();
|
|
60123
|
+
setScreen("doctor-result");
|
|
60124
|
+
} finally {
|
|
60125
|
+
setDoctorRunning(false);
|
|
59720
60126
|
}
|
|
59721
|
-
const fixed = installFailed ? [] : fixWrapperVersions(instances2);
|
|
59722
|
-
let migrated = 0;
|
|
59723
|
-
try {
|
|
59724
|
-
const fullConfig = await loadConfig();
|
|
59725
|
-
if (needsInstanceMigration(fullConfig)) {
|
|
59726
|
-
const before2 = fullConfig.instanceMigrationVersion;
|
|
59727
|
-
const migratedConfig = await runInstanceMigrations(fullConfig);
|
|
59728
|
-
if (migratedConfig.instanceMigrationVersion !== before2) {
|
|
59729
|
-
await saveConfigAtomic(migratedConfig);
|
|
59730
|
-
migrated = fullConfig.instances.length;
|
|
59731
|
-
}
|
|
59732
|
-
}
|
|
59733
|
-
} catch {}
|
|
59734
|
-
setDoctorResult({ fixedCount: fixed.length, migratedCount: migrated, installFailed });
|
|
59735
|
-
retry();
|
|
59736
|
-
setScreen("doctor-result");
|
|
59737
60127
|
};
|
|
59738
60128
|
if (screen === "goodbye") {
|
|
59739
|
-
return /* @__PURE__ */
|
|
60129
|
+
return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(GoodbyeScreen, {}, undefined, false, undefined, this);
|
|
59740
60130
|
}
|
|
59741
60131
|
if (screen === "health") {
|
|
59742
|
-
return /* @__PURE__ */
|
|
60132
|
+
return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(HealthScreen, {
|
|
59743
60133
|
issues,
|
|
59744
60134
|
onDismiss: dismiss,
|
|
59745
60135
|
onDismissAll: dismissAll,
|
|
@@ -59749,17 +60139,16 @@ var import_react78, jsx_dev_runtime19, GoodbyeScreen = () => {
|
|
|
59749
60139
|
}, undefined, false, undefined, this);
|
|
59750
60140
|
}
|
|
59751
60141
|
if (screen === "doctor-result") {
|
|
59752
|
-
return /* @__PURE__ */
|
|
60142
|
+
return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(DoctorResultScreen, {
|
|
59753
60143
|
fixedCount: doctorResult.fixedCount,
|
|
59754
60144
|
migratedCount: doctorResult.migratedCount,
|
|
59755
|
-
installFailed: doctorResult.installFailed,
|
|
59756
60145
|
onBack: goToMenu
|
|
59757
60146
|
}, undefined, false, undefined, this);
|
|
59758
60147
|
}
|
|
59759
60148
|
if (screen !== "menu") {
|
|
59760
60149
|
const ScreenComponent = SCREEN_MAP[screen];
|
|
59761
60150
|
if (ScreenComponent) {
|
|
59762
|
-
return /* @__PURE__ */
|
|
60151
|
+
return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(ScreenComponent, {
|
|
59763
60152
|
onBack: goToMenu
|
|
59764
60153
|
}, undefined, false, undefined, this);
|
|
59765
60154
|
}
|
|
@@ -59790,44 +60179,26 @@ var import_react78, jsx_dev_runtime19, GoodbyeScreen = () => {
|
|
|
59790
60179
|
{ label: "\uD83D\uDCE6 Check for updates", value: "update" },
|
|
59791
60180
|
{ label: "\uD83D\uDEAA Exit", value: "exit" }
|
|
59792
60181
|
];
|
|
59793
|
-
return /* @__PURE__ */
|
|
60182
|
+
return /* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Box_default, {
|
|
59794
60183
|
flexDirection: "column",
|
|
59795
60184
|
width: "100",
|
|
59796
60185
|
paddingX: 2,
|
|
59797
60186
|
paddingY: 1,
|
|
59798
60187
|
children: [
|
|
59799
|
-
/* @__PURE__ */
|
|
60188
|
+
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Header, {
|
|
59800
60189
|
title: "\uD83E\uDD16 Claude Multi",
|
|
59801
60190
|
subtitle: "Interactive Mode"
|
|
59802
60191
|
}, undefined, false, undefined, this),
|
|
59803
|
-
/* @__PURE__ */
|
|
60192
|
+
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(WarningBanner, {
|
|
59804
60193
|
issueCount: issues.length,
|
|
59805
60194
|
errorCount,
|
|
59806
60195
|
warningCount,
|
|
59807
60196
|
hasVersionIssues
|
|
59808
60197
|
}, undefined, false, undefined, this),
|
|
59809
|
-
|
|
59810
|
-
marginBottom: 1,
|
|
59811
|
-
children: [
|
|
59812
|
-
/* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
|
|
59813
|
-
color: "red",
|
|
59814
|
-
bold: true,
|
|
59815
|
-
children: [
|
|
59816
|
-
"⚠ Claude Code v",
|
|
59817
|
-
ccVersion,
|
|
59818
|
-
" does not work with 3rd-party APIs. "
|
|
59819
|
-
]
|
|
59820
|
-
}, undefined, true, undefined, this),
|
|
59821
|
-
/* @__PURE__ */ jsx_dev_runtime19.jsxDEV(Text, {
|
|
59822
|
-
color: "red",
|
|
59823
|
-
children: "Run 'claude-multi doctor fix' to install a compatible version."
|
|
59824
|
-
}, undefined, false, undefined, this)
|
|
59825
|
-
]
|
|
59826
|
-
}, undefined, true, undefined, this),
|
|
59827
|
-
/* @__PURE__ */ jsx_dev_runtime19.jsxDEV(InstanceLine, {
|
|
60198
|
+
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(InstanceLine, {
|
|
59828
60199
|
instances: instances2
|
|
59829
60200
|
}, undefined, false, undefined, this),
|
|
59830
|
-
/* @__PURE__ */
|
|
60201
|
+
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Select, {
|
|
59831
60202
|
options: menuOptions,
|
|
59832
60203
|
visibleOptionCount: menuOptions.length,
|
|
59833
60204
|
onChange: async (value) => {
|
|
@@ -59843,7 +60214,7 @@ var import_react78, jsx_dev_runtime19, GoodbyeScreen = () => {
|
|
|
59843
60214
|
}
|
|
59844
60215
|
}
|
|
59845
60216
|
}, menuKey, false, undefined, this),
|
|
59846
|
-
/* @__PURE__ */
|
|
60217
|
+
/* @__PURE__ */ jsx_dev_runtime18.jsxDEV(Footer, {
|
|
59847
60218
|
showHealthHint: issues.length > 0
|
|
59848
60219
|
}, undefined, false, undefined, this)
|
|
59849
60220
|
]
|
|
@@ -59851,7 +60222,6 @@ var import_react78, jsx_dev_runtime19, GoodbyeScreen = () => {
|
|
|
59851
60222
|
}, SCREEN_MAP;
|
|
59852
60223
|
var init_App2 = __esm(async () => {
|
|
59853
60224
|
init_version();
|
|
59854
|
-
init_paths();
|
|
59855
60225
|
init_useConfig();
|
|
59856
60226
|
init_useHealthCheck();
|
|
59857
60227
|
init_useAnimations();
|
|
@@ -59878,7 +60248,7 @@ var init_App2 = __esm(async () => {
|
|
|
59878
60248
|
init_UpdateScreen()
|
|
59879
60249
|
]);
|
|
59880
60250
|
import_react78 = __toESM(require_react(), 1);
|
|
59881
|
-
|
|
60251
|
+
jsx_dev_runtime18 = __toESM(require_jsx_dev_runtime(), 1);
|
|
59882
60252
|
SCREEN_MAP = {
|
|
59883
60253
|
add: AddInstance,
|
|
59884
60254
|
list: ListInstances,
|
|
@@ -59919,7 +60289,7 @@ init_errors();
|
|
|
59919
60289
|
init_constants();
|
|
59920
60290
|
var import_prompts = __toESM(require_prompts3(), 1);
|
|
59921
60291
|
import { homedir as homedir4 } from "node:os";
|
|
59922
|
-
import { join as join9 } from "node:path";
|
|
60292
|
+
import { join as join9, dirname as dirname5, delimiter } from "node:path";
|
|
59923
60293
|
function exitWithCode(code) {
|
|
59924
60294
|
process.exit(code);
|
|
59925
60295
|
}
|
|
@@ -59956,6 +60326,7 @@ program2.command("add <name>").description("Add a new Claude Code instance").opt
|
|
|
59956
60326
|
let providerTemplate = null;
|
|
59957
60327
|
let apiKey = "";
|
|
59958
60328
|
let autoSync = !options.manual;
|
|
60329
|
+
let providerRegion;
|
|
59959
60330
|
if (options.provider) {
|
|
59960
60331
|
providerTemplate = getProviderTemplate(options.provider);
|
|
59961
60332
|
if (!providerTemplate) {
|
|
@@ -59970,12 +60341,19 @@ program2.command("add <name>").description("Add a new Claude Code instance").opt
|
|
|
59970
60341
|
useProviderTemplate = true;
|
|
59971
60342
|
if (providerHasRegions(providerTemplate.name)) {
|
|
59972
60343
|
const region = options.region || "cn";
|
|
60344
|
+
if (!options.region) {
|
|
60345
|
+
const regions = getProviderRegions(providerTemplate.name);
|
|
60346
|
+
console.log(source_default.yellow(`⚠ No --region specified, defaulting to cn. Available: ${regions ? Object.keys(regions).join(", ") : "cn"}`));
|
|
60347
|
+
}
|
|
60348
|
+
providerRegion = region;
|
|
59973
60349
|
try {
|
|
59974
60350
|
providerTemplate = resolveRegionTemplate(providerTemplate, region);
|
|
59975
60351
|
} catch (err) {
|
|
59976
60352
|
console.error(source_default.red(`✗ ${toMessage(err)}`));
|
|
59977
60353
|
exitWithCode(1);
|
|
59978
60354
|
}
|
|
60355
|
+
} else if (options.region) {
|
|
60356
|
+
console.log(source_default.yellow(`⚠ --region is ignored for non-regional provider '${providerTemplate.name}'`));
|
|
59979
60357
|
}
|
|
59980
60358
|
}
|
|
59981
60359
|
if (options.copySettings || options.copyAll || options.copyMcp || options.skipPrompts || options.provider) {
|
|
@@ -60040,7 +60418,9 @@ Found existing Claude Code configuration at ~/.claude`));
|
|
|
60040
60418
|
binaryPath,
|
|
60041
60419
|
createdAt: new Date().toISOString(),
|
|
60042
60420
|
autoSync,
|
|
60043
|
-
createdWithVersion: getClaudeMultiVersion()
|
|
60421
|
+
createdWithVersion: getClaudeMultiVersion(),
|
|
60422
|
+
...useProviderTemplate && providerTemplate ? { providerTemplate: providerTemplate.name } : {},
|
|
60423
|
+
...providerRegion ? { providerRegion } : {}
|
|
60044
60424
|
};
|
|
60045
60425
|
await addInstance(instance);
|
|
60046
60426
|
try {
|
|
@@ -60080,9 +60460,9 @@ Found existing Claude Code configuration at ~/.claude`));
|
|
|
60080
60460
|
console.log(source_default.gray(` Binary: ${binaryPath}`));
|
|
60081
60461
|
console.log(source_default.gray(` Config: ${configDir}`));
|
|
60082
60462
|
console.log();
|
|
60083
|
-
const binDir =
|
|
60463
|
+
const binDir = dirname5(binaryPath);
|
|
60084
60464
|
const pathEnv = process.env.PATH || "";
|
|
60085
|
-
const isInPath = pathEnv.split(
|
|
60465
|
+
const isInPath = pathEnv.split(delimiter).some((p) => p === binDir);
|
|
60086
60466
|
if (!isInPath) {
|
|
60087
60467
|
console.log(source_default.yellow(`⚠ Warning: ${binDir} is not in your PATH`));
|
|
60088
60468
|
console.log(source_default.gray(`Add to PATH by running:`));
|
|
@@ -60136,6 +60516,10 @@ program2.command("list").alias("ls").description("List all Claude Code instances
|
|
|
60136
60516
|
console.log(source_default.gray(` Binary: ${instance.binaryPath}`));
|
|
60137
60517
|
console.log(source_default.gray(` Config: ${instance.configDir}`));
|
|
60138
60518
|
console.log(source_default.gray(` Created: ${new Date(instance.createdAt).toLocaleString()}`));
|
|
60519
|
+
if (instance.providerTemplate) {
|
|
60520
|
+
const region = instance.providerRegion ? ` (${instance.providerRegion})` : "";
|
|
60521
|
+
console.log(source_default.gray(` Provider: ${instance.providerTemplate}${region}`));
|
|
60522
|
+
}
|
|
60139
60523
|
const autoSyncStatus = instance.autoSync !== false ? source_default.green("on") : source_default.yellow("off");
|
|
60140
60524
|
console.log(source_default.gray(` Auto-sync: ${autoSyncStatus}`));
|
|
60141
60525
|
console.log(source_default.gray(` Version: ${formatVersionLabel(instance.createdWithVersion)}`));
|
|
@@ -60157,6 +60541,10 @@ program2.command("info <name>").description("Show details about a specific insta
|
|
|
60157
60541
|
const autoSyncStatus = instance.autoSync !== false ? source_default.green("✓ Enabled") : source_default.yellow("✗ Disabled");
|
|
60158
60542
|
console.log(`${source_default.gray("Auto-sync:")} ${autoSyncStatus}`);
|
|
60159
60543
|
console.log(`${source_default.gray("Version:")} ${formatVersionLabel(instance.createdWithVersion)}`);
|
|
60544
|
+
if (instance.providerTemplate) {
|
|
60545
|
+
const region = instance.providerRegion ? ` (${instance.providerRegion})` : "";
|
|
60546
|
+
console.log(`${source_default.gray("Provider:")} ${instance.providerTemplate}${region}`);
|
|
60547
|
+
}
|
|
60160
60548
|
} catch (error) {
|
|
60161
60549
|
console.error(source_default.red(`✗ Error: ${toMessage(error)}`));
|
|
60162
60550
|
exitWithCode(1);
|
|
@@ -60232,17 +60620,13 @@ program2.command("doctor").description("Diagnose and fix common issues").argumen
|
|
|
60232
60620
|
const [
|
|
60233
60621
|
instances2,
|
|
60234
60622
|
{ runHealthChecks: runHealthChecks2, fixWrapperVersions: fixWrapperVersions2 },
|
|
60235
|
-
{
|
|
60236
|
-
{ PINNED_CLAUDE_BIN: PINNED_CLAUDE_BIN2 },
|
|
60237
|
-
{ installPinnedClaude: installPinnedClaude2, getPinnedBinaryVersion: getPinnedBinaryVersion2, isThirdPartyApiBroken: isThirdPartyApiBroken2, COMPATIBLE_CLAUDE_VERSION: COMPATIBLE_CLAUDE_VERSION2 },
|
|
60623
|
+
{ tryGetClaudePath: tryGetClaudePath2 },
|
|
60238
60624
|
{ needsInstanceMigration: needsInstanceMigration2, runInstanceMigrations: runInstanceMigrations2 },
|
|
60239
60625
|
{ loadConfig: loadConfig2, saveConfigAtomic: saveConfigAtomic2 }
|
|
60240
60626
|
] = await Promise.all([
|
|
60241
60627
|
listInstances(),
|
|
60242
60628
|
Promise.resolve().then(() => (init_health(), exports_health)),
|
|
60243
|
-
|
|
60244
|
-
Promise.resolve().then(() => (init_paths(), exports_paths)),
|
|
60245
|
-
Promise.resolve().then(() => (init_version(), exports_version)),
|
|
60629
|
+
Promise.resolve().then(() => (init_wrapper(), exports_wrapper)),
|
|
60246
60630
|
Promise.resolve().then(() => (init_migration(), exports_migration)),
|
|
60247
60631
|
Promise.resolve().then(() => (init_config(), exports_config))
|
|
60248
60632
|
]);
|
|
@@ -60250,23 +60634,15 @@ program2.command("doctor").description("Diagnose and fix common issues").argumen
|
|
|
60250
60634
|
console.log(source_default.bold(`
|
|
60251
60635
|
\uD83D\uDD27 Doctor Fix
|
|
60252
60636
|
`));
|
|
60253
|
-
|
|
60254
|
-
|
|
60255
|
-
|
|
60256
|
-
|
|
60257
|
-
} else {
|
|
60258
|
-
const pinnedVer = getPinnedBinaryVersion2();
|
|
60259
|
-
const needsReinstall = !pinnedVer || isThirdPartyApiBroken2(pinnedVer) || pinnedVer !== COMPATIBLE_CLAUDE_VERSION2;
|
|
60260
|
-
if (needsReinstall) {
|
|
60261
|
-
const reason = !pinnedVer ? "version unknown" : isThirdPartyApiBroken2(pinnedVer) ? "incompatible" : "outdated";
|
|
60262
|
-
console.log(source_default.yellow(`Pinned binary is ${pinnedVer ? `v${pinnedVer}` : reason}. Reinstalling v${COMPATIBLE_CLAUDE_VERSION2}...`));
|
|
60263
|
-
installPinnedClaude2();
|
|
60264
|
-
console.log(source_default.green(`✓ Reinstalled pinned Claude v${COMPATIBLE_CLAUDE_VERSION2}`));
|
|
60265
|
-
}
|
|
60637
|
+
const claudePath = tryGetClaudePath2();
|
|
60638
|
+
if (!claudePath) {
|
|
60639
|
+
console.error(source_default.red("Claude Code not found in PATH. Please install it first."));
|
|
60640
|
+
process.exit(1);
|
|
60266
60641
|
}
|
|
60642
|
+
console.log(source_default.gray(`Using claude at: ${claudePath}`));
|
|
60267
60643
|
const fixed = fixWrapperVersions2(instances2);
|
|
60268
60644
|
if (fixed.length > 0) {
|
|
60269
|
-
console.log(source_default.green(`✓ Fixed ${fixed.length} wrapper(s) to use
|
|
60645
|
+
console.log(source_default.green(`✓ Fixed ${fixed.length} wrapper(s) to use resolved Claude version:`));
|
|
60270
60646
|
for (const name of fixed) {
|
|
60271
60647
|
console.log(source_default.gray(` • ${name}`));
|
|
60272
60648
|
}
|