@rynfar/meridian 1.41.0 → 1.42.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/README.md +43 -4
- package/dist/{cli-0eky480v.js → cli-7k1fcprd.js} +69 -3
- package/dist/{cli-vdp9s10c.js → cli-cx463q74.js} +8 -0
- package/dist/{cli-swjr844z.js → cli-kvwnarfk.js} +247 -93
- package/dist/cli.js +15 -9
- package/dist/{profileCli-5f15dx7k.js → profileCli-wpb4qbjn.js} +105 -13
- package/dist/{profiles-edzz1ffd.js → profiles-rdd84b45.js} +1 -1
- package/dist/proxy/adapters/droid.d.ts.map +1 -1
- package/dist/proxy/cwd.d.ts +42 -0
- package/dist/proxy/cwd.d.ts.map +1 -0
- package/dist/proxy/errors.d.ts +14 -4
- package/dist/proxy/errors.d.ts.map +1 -1
- package/dist/proxy/models.d.ts +61 -1
- package/dist/proxy/models.d.ts.map +1 -1
- package/dist/proxy/oauthUsage.d.ts +17 -7
- package/dist/proxy/oauthUsage.d.ts.map +1 -1
- package/dist/proxy/plugins/loader.d.ts.map +1 -1
- package/dist/proxy/profiles.d.ts +12 -4
- package/dist/proxy/profiles.d.ts.map +1 -1
- package/dist/proxy/query.d.ts.map +1 -1
- package/dist/proxy/sdkFeatures.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/tokenRefresh.d.ts +52 -0
- package/dist/proxy/tokenRefresh.d.ts.map +1 -1
- package/dist/proxy/transforms/droid.d.ts.map +1 -1
- package/dist/server.js +3 -3
- package/dist/{tokenRefresh-3kh1e8q8.js → tokenRefresh-swetnf89.js} +12 -2
- package/package.json +2 -2
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
resolveProfile,
|
|
6
6
|
restoreActiveProfile,
|
|
7
7
|
setActiveProfile
|
|
8
|
-
} from "./cli-
|
|
8
|
+
} from "./cli-cx463q74.js";
|
|
9
9
|
import {
|
|
10
10
|
isTrackedPlugin,
|
|
11
11
|
recordError,
|
|
@@ -26,9 +26,12 @@ import {
|
|
|
26
26
|
import {
|
|
27
27
|
claudeLog,
|
|
28
28
|
createPlatformCredentialStore,
|
|
29
|
+
ensureFreshToken,
|
|
29
30
|
refreshOAuthToken,
|
|
31
|
+
startBackgroundRefresh,
|
|
32
|
+
stopBackgroundRefresh,
|
|
30
33
|
withClaudeLogContext
|
|
31
|
-
} from "./cli-
|
|
34
|
+
} from "./cli-7k1fcprd.js";
|
|
32
35
|
import {
|
|
33
36
|
__commonJS,
|
|
34
37
|
__esm,
|
|
@@ -1178,14 +1181,14 @@ __export(exports_sdkFeatures, {
|
|
|
1178
1181
|
getFeaturesForAdapter: () => getFeaturesForAdapter,
|
|
1179
1182
|
getAllFeatureConfigs: () => getAllFeatureConfigs
|
|
1180
1183
|
});
|
|
1181
|
-
import { existsSync as
|
|
1182
|
-
import { join as
|
|
1183
|
-
import { homedir as
|
|
1184
|
+
import { existsSync as existsSync6, mkdirSync as mkdirSync2, readFileSync as readFileSync4, writeFileSync as writeFileSync2, renameSync as renameSync2 } from "node:fs";
|
|
1185
|
+
import { join as join5 } from "node:path";
|
|
1186
|
+
import { homedir as homedir3 } from "node:os";
|
|
1184
1187
|
function getConfigPath() {
|
|
1185
|
-
const dir =
|
|
1186
|
-
if (!
|
|
1188
|
+
const dir = join5(homedir3(), ".config", "meridian");
|
|
1189
|
+
if (!existsSync6(dir))
|
|
1187
1190
|
mkdirSync2(dir, { recursive: true });
|
|
1188
|
-
return
|
|
1191
|
+
return join5(dir, "sdk-features.json");
|
|
1189
1192
|
}
|
|
1190
1193
|
function readConfig() {
|
|
1191
1194
|
const now = Date.now();
|
|
@@ -1193,7 +1196,7 @@ function readConfig() {
|
|
|
1193
1196
|
return cachedConfig;
|
|
1194
1197
|
const path3 = getConfigPath();
|
|
1195
1198
|
try {
|
|
1196
|
-
if (
|
|
1199
|
+
if (existsSync6(path3)) {
|
|
1197
1200
|
cachedConfig = JSON.parse(readFileSync4(path3, "utf-8"));
|
|
1198
1201
|
} else {
|
|
1199
1202
|
cachedConfig = {};
|
|
@@ -1283,7 +1286,7 @@ function resetAdapterFeatures(adapterName) {
|
|
|
1283
1286
|
var DEFAULT_FEATURES, ADAPTER_DEFAULTS, cachedConfig = null, lastReadTime = 0, CACHE_TTL_MS = 5000, VALID_CLAUDE_MD_VALUES, VALID_THINKING_VALUES;
|
|
1284
1287
|
var init_sdkFeatures = __esm(() => {
|
|
1285
1288
|
DEFAULT_FEATURES = {
|
|
1286
|
-
codeSystemPrompt:
|
|
1289
|
+
codeSystemPrompt: true,
|
|
1287
1290
|
clientSystemPrompt: true,
|
|
1288
1291
|
claudeMd: "off",
|
|
1289
1292
|
memory: false,
|
|
@@ -1296,7 +1299,11 @@ var init_sdkFeatures = __esm(() => {
|
|
|
1296
1299
|
sdkDebug: false,
|
|
1297
1300
|
additionalDirectories: ""
|
|
1298
1301
|
};
|
|
1299
|
-
ADAPTER_DEFAULTS = {
|
|
1302
|
+
ADAPTER_DEFAULTS = {
|
|
1303
|
+
passthrough: {
|
|
1304
|
+
codeSystemPrompt: false
|
|
1305
|
+
}
|
|
1306
|
+
};
|
|
1300
1307
|
VALID_CLAUDE_MD_VALUES = new Set(["off", "project", "full"]);
|
|
1301
1308
|
VALID_THINKING_VALUES = new Set(["adaptive", "enabled", "disabled"]);
|
|
1302
1309
|
});
|
|
@@ -3703,8 +3710,8 @@ var serve = (options, listeningListener) => {
|
|
|
3703
3710
|
};
|
|
3704
3711
|
|
|
3705
3712
|
// src/proxy/server.ts
|
|
3706
|
-
import { homedir as
|
|
3707
|
-
import { join as
|
|
3713
|
+
import { homedir as homedir4 } from "node:os";
|
|
3714
|
+
import { join as join6 } from "node:path";
|
|
3708
3715
|
import { query } from "@anthropic-ai/claude-agent-sdk";
|
|
3709
3716
|
|
|
3710
3717
|
// src/proxy/rateLimitStore.ts
|
|
@@ -3784,8 +3791,8 @@ async function readAccessToken(store) {
|
|
|
3784
3791
|
const creds = await store.read();
|
|
3785
3792
|
return creds?.claudeAiOauth?.accessToken ?? null;
|
|
3786
3793
|
}
|
|
3787
|
-
async function callAnthropic(token, signal) {
|
|
3788
|
-
const res = await
|
|
3794
|
+
async function callAnthropic(token, fetchImpl, signal) {
|
|
3795
|
+
const res = await fetchImpl(OAUTH_USAGE_URL, {
|
|
3789
3796
|
headers: {
|
|
3790
3797
|
Authorization: `Bearer ${token}`,
|
|
3791
3798
|
"anthropic-beta": OAUTH_BETA_HEADER,
|
|
@@ -3797,9 +3804,17 @@ async function callAnthropic(token, signal) {
|
|
|
3797
3804
|
return { __status: res.status };
|
|
3798
3805
|
return await res.json();
|
|
3799
3806
|
}
|
|
3807
|
+
var _testOverride = null;
|
|
3800
3808
|
async function fetchOAuthUsage(opts) {
|
|
3809
|
+
if (_testOverride && !opts?.fetchImpl && !opts?.store) {
|
|
3810
|
+
return _testOverride(opts);
|
|
3811
|
+
}
|
|
3812
|
+
return fetchOAuthUsageImpl(opts);
|
|
3813
|
+
}
|
|
3814
|
+
async function fetchOAuthUsageImpl(opts) {
|
|
3801
3815
|
const ttl = opts?.ttlMs ?? CACHE_TTL_MS_DEFAULT;
|
|
3802
3816
|
const cacheKey2 = opts?.profileId ?? DEFAULT_KEY;
|
|
3817
|
+
const fetchImpl = opts?.fetchImpl ?? globalThis.fetch;
|
|
3803
3818
|
if (!opts?.force) {
|
|
3804
3819
|
const cached = cacheByProfile.get(cacheKey2);
|
|
3805
3820
|
if (cached && Date.now() - cached.fetchedAt < ttl)
|
|
@@ -3814,7 +3829,7 @@ async function fetchOAuthUsage(opts) {
|
|
|
3814
3829
|
const token = await readAccessToken(store);
|
|
3815
3830
|
if (!token)
|
|
3816
3831
|
return null;
|
|
3817
|
-
let result = await callAnthropic(token);
|
|
3832
|
+
let result = await callAnthropic(token, fetchImpl);
|
|
3818
3833
|
if ("__status" in result && result.__status === 401) {
|
|
3819
3834
|
claudeLog("oauth_usage.token_refresh_attempt", { profile: cacheKey2 });
|
|
3820
3835
|
const refreshed = await refreshOAuthToken(store);
|
|
@@ -3825,7 +3840,7 @@ async function fetchOAuthUsage(opts) {
|
|
|
3825
3840
|
const newToken = await readAccessToken(store);
|
|
3826
3841
|
if (!newToken)
|
|
3827
3842
|
return null;
|
|
3828
|
-
result = await callAnthropic(newToken);
|
|
3843
|
+
result = await callAnthropic(newToken, fetchImpl);
|
|
3829
3844
|
}
|
|
3830
3845
|
if ("__status" in result) {
|
|
3831
3846
|
claudeLog("oauth_usage.upstream_error", { profile: cacheKey2, status: result.__status });
|
|
@@ -3845,6 +3860,17 @@ async function fetchOAuthUsage(opts) {
|
|
|
3845
3860
|
return promise;
|
|
3846
3861
|
}
|
|
3847
3862
|
|
|
3863
|
+
// src/proxy/cwd.ts
|
|
3864
|
+
import { existsSync } from "node:fs";
|
|
3865
|
+
function resolveSdkWorkingDirectory(opts) {
|
|
3866
|
+
const exists = opts.exists ?? existsSync;
|
|
3867
|
+
const claimed = opts.envOverride || opts.adapterCwd || opts.fallback;
|
|
3868
|
+
if (exists(claimed)) {
|
|
3869
|
+
return { workingDirectory: claimed, claimedWorkingDirectory: claimed, fellBack: false };
|
|
3870
|
+
}
|
|
3871
|
+
return { workingDirectory: opts.fallback, claimedWorkingDirectory: claimed, fellBack: true };
|
|
3872
|
+
}
|
|
3873
|
+
|
|
3848
3874
|
// src/proxy/types.ts
|
|
3849
3875
|
var DEFAULT_PROXY_CONFIG = {
|
|
3850
3876
|
port: 3456,
|
|
@@ -8443,7 +8469,7 @@ class MemoryDiagnosticLogStore {
|
|
|
8443
8469
|
}
|
|
8444
8470
|
var diagnosticLog = new MemoryDiagnosticLogStore;
|
|
8445
8471
|
// src/telemetry/routes.ts
|
|
8446
|
-
import { existsSync, readFileSync } from "node:fs";
|
|
8472
|
+
import { existsSync as existsSync2, readFileSync } from "node:fs";
|
|
8447
8473
|
import { resolve, dirname } from "node:path";
|
|
8448
8474
|
import { fileURLToPath } from "node:url";
|
|
8449
8475
|
|
|
@@ -8797,7 +8823,7 @@ timer = setInterval(refresh, 5000);
|
|
|
8797
8823
|
|
|
8798
8824
|
// src/telemetry/routes.ts
|
|
8799
8825
|
var _iconPath = resolve(dirname(fileURLToPath(import.meta.url)), "..", "..", "assets", "icon.svg");
|
|
8800
|
-
var _iconSvg =
|
|
8826
|
+
var _iconSvg = existsSync2(_iconPath) ? readFileSync(_iconPath, "utf-8") : null;
|
|
8801
8827
|
function createTelemetryRoutes() {
|
|
8802
8828
|
const routes = new Hono2;
|
|
8803
8829
|
routes.get("/", (c) => {
|
|
@@ -9135,7 +9161,13 @@ function classifyError(errMsg) {
|
|
|
9135
9161
|
}
|
|
9136
9162
|
function isExpiredTokenError(errMsg) {
|
|
9137
9163
|
const lower = errMsg.toLowerCase();
|
|
9138
|
-
|
|
9164
|
+
if (lower.includes("oauth token has expired") || lower.includes("not logged in"))
|
|
9165
|
+
return true;
|
|
9166
|
+
if (lower.includes("invalid_token") || lower.includes("token_expired"))
|
|
9167
|
+
return true;
|
|
9168
|
+
if (lower.includes("401") && (lower.includes("authentication") || lower.includes("unauthorized") || lower.includes("invalid")))
|
|
9169
|
+
return true;
|
|
9170
|
+
return false;
|
|
9139
9171
|
}
|
|
9140
9172
|
function isStaleSessionError(error) {
|
|
9141
9173
|
if (!(error instanceof Error))
|
|
@@ -9230,19 +9262,20 @@ function formatSdkTermination(t, ctx) {
|
|
|
9230
9262
|
|
|
9231
9263
|
// src/proxy/models.ts
|
|
9232
9264
|
import { exec as execCallback } from "child_process";
|
|
9233
|
-
import { existsSync as
|
|
9265
|
+
import { existsSync as existsSync3, statSync } from "fs";
|
|
9234
9266
|
import { fileURLToPath as fileURLToPath2 } from "url";
|
|
9235
9267
|
import { join as join2, dirname as dirname2 } from "path";
|
|
9236
9268
|
import { promisify } from "util";
|
|
9237
9269
|
var exec = promisify(execCallback);
|
|
9270
|
+
var STUB_SIZE_THRESHOLD = 4096;
|
|
9238
9271
|
var CANONICAL_OPUS_MODEL = "claude-opus-4-7";
|
|
9239
9272
|
var CANONICAL_SONNET_MODEL = "claude-sonnet-4-6";
|
|
9240
9273
|
var CANONICAL_HAIKU_MODEL = "claude-haiku-4-5";
|
|
9241
|
-
function resolveSdkModelDefaults() {
|
|
9274
|
+
function resolveSdkModelDefaults(env2 = process.env) {
|
|
9242
9275
|
return {
|
|
9243
|
-
ANTHROPIC_DEFAULT_OPUS_MODEL:
|
|
9244
|
-
ANTHROPIC_DEFAULT_SONNET_MODEL:
|
|
9245
|
-
ANTHROPIC_DEFAULT_HAIKU_MODEL:
|
|
9276
|
+
ANTHROPIC_DEFAULT_OPUS_MODEL: env2.MERIDIAN_DEFAULT_OPUS_MODEL ?? CANONICAL_OPUS_MODEL,
|
|
9277
|
+
ANTHROPIC_DEFAULT_SONNET_MODEL: env2.MERIDIAN_DEFAULT_SONNET_MODEL ?? CANONICAL_SONNET_MODEL,
|
|
9278
|
+
ANTHROPIC_DEFAULT_HAIKU_MODEL: env2.MERIDIAN_DEFAULT_HAIKU_MODEL ?? CANONICAL_HAIKU_MODEL
|
|
9246
9279
|
};
|
|
9247
9280
|
}
|
|
9248
9281
|
var AUTH_STATUS_CACHE_TTL_MS = 60000;
|
|
@@ -9372,42 +9405,112 @@ async function getClaudeAuthStatusAsync(profileId, envOverrides) {
|
|
|
9372
9405
|
cachedAuthStatusPromise = null;
|
|
9373
9406
|
}
|
|
9374
9407
|
}
|
|
9375
|
-
var
|
|
9408
|
+
var cachedClaudeInfo = null;
|
|
9376
9409
|
var cachedClaudePathPromise = null;
|
|
9410
|
+
var DEFAULT_DEPS = {
|
|
9411
|
+
existsSync: existsSync3,
|
|
9412
|
+
statSync: (p) => statSync(p),
|
|
9413
|
+
exec,
|
|
9414
|
+
resolvePackage: (specifier) => fileURLToPath2(import.meta.resolve(specifier)),
|
|
9415
|
+
envGet: (name) => process.env[name],
|
|
9416
|
+
platform: process.platform,
|
|
9417
|
+
arch: process.arch,
|
|
9418
|
+
isBun: typeof process.versions.bun !== "undefined"
|
|
9419
|
+
};
|
|
9420
|
+
function tryEnvOverride(deps) {
|
|
9421
|
+
const explicit = deps.envGet("MERIDIAN_CLAUDE_PATH");
|
|
9422
|
+
if (!explicit)
|
|
9423
|
+
return null;
|
|
9424
|
+
return deps.existsSync(explicit) ? explicit : null;
|
|
9425
|
+
}
|
|
9426
|
+
function tryBundledBinary(deps) {
|
|
9427
|
+
try {
|
|
9428
|
+
const pkgPath = deps.resolvePackage("@anthropic-ai/claude-code/package.json");
|
|
9429
|
+
const bundled = join2(dirname2(pkgPath), "bin", "claude.exe");
|
|
9430
|
+
if (!deps.existsSync(bundled))
|
|
9431
|
+
return null;
|
|
9432
|
+
const size = deps.statSync(bundled).size;
|
|
9433
|
+
if (size <= STUB_SIZE_THRESHOLD)
|
|
9434
|
+
return null;
|
|
9435
|
+
return bundled;
|
|
9436
|
+
} catch {
|
|
9437
|
+
return null;
|
|
9438
|
+
}
|
|
9439
|
+
}
|
|
9440
|
+
function tryPlatformPackage(deps) {
|
|
9441
|
+
const binName = deps.platform === "win32" ? "claude.exe" : "claude";
|
|
9442
|
+
const candidates = [`@anthropic-ai/claude-code-${deps.platform}-${deps.arch}`];
|
|
9443
|
+
if (deps.platform === "linux") {
|
|
9444
|
+
candidates.push(`@anthropic-ai/claude-code-${deps.platform}-${deps.arch}-musl`);
|
|
9445
|
+
}
|
|
9446
|
+
for (const pkg of candidates) {
|
|
9447
|
+
try {
|
|
9448
|
+
const pkgJson = deps.resolvePackage(`${pkg}/package.json`);
|
|
9449
|
+
const candidate = join2(dirname2(pkgJson), binName);
|
|
9450
|
+
if (deps.existsSync(candidate))
|
|
9451
|
+
return candidate;
|
|
9452
|
+
} catch {}
|
|
9453
|
+
}
|
|
9454
|
+
return null;
|
|
9455
|
+
}
|
|
9456
|
+
async function tryPathLookup(deps) {
|
|
9457
|
+
const cmd = deps.platform === "win32" ? "where claude" : "which claude";
|
|
9458
|
+
try {
|
|
9459
|
+
const { stdout } = await deps.exec(cmd);
|
|
9460
|
+
const candidates = stdout.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
|
|
9461
|
+
for (const candidate of candidates) {
|
|
9462
|
+
if (deps.platform === "win32" && candidate.startsWith("/"))
|
|
9463
|
+
continue;
|
|
9464
|
+
if (deps.existsSync(candidate))
|
|
9465
|
+
return candidate;
|
|
9466
|
+
}
|
|
9467
|
+
} catch {}
|
|
9468
|
+
return null;
|
|
9469
|
+
}
|
|
9470
|
+
function tryLegacySdkCliJs(deps) {
|
|
9471
|
+
if (!deps.isBun)
|
|
9472
|
+
return null;
|
|
9473
|
+
try {
|
|
9474
|
+
const sdkPath = deps.resolvePackage("@anthropic-ai/claude-agent-sdk");
|
|
9475
|
+
const cliJs = join2(dirname2(sdkPath), "cli.js");
|
|
9476
|
+
return deps.existsSync(cliJs) ? cliJs : null;
|
|
9477
|
+
} catch {
|
|
9478
|
+
return null;
|
|
9479
|
+
}
|
|
9480
|
+
}
|
|
9481
|
+
async function resolveClaudeExecutableWithSource(deps = DEFAULT_DEPS) {
|
|
9482
|
+
const env2 = tryEnvOverride(deps);
|
|
9483
|
+
if (env2)
|
|
9484
|
+
return { path: env2, source: "env" };
|
|
9485
|
+
const bundled = tryBundledBinary(deps);
|
|
9486
|
+
if (bundled)
|
|
9487
|
+
return { path: bundled, source: "bundled" };
|
|
9488
|
+
const platformPkg = tryPlatformPackage(deps);
|
|
9489
|
+
if (platformPkg)
|
|
9490
|
+
return { path: platformPkg, source: "platform-package" };
|
|
9491
|
+
const pathLookup = await tryPathLookup(deps);
|
|
9492
|
+
if (pathLookup)
|
|
9493
|
+
return { path: pathLookup, source: "path-lookup" };
|
|
9494
|
+
const legacy = tryLegacySdkCliJs(deps);
|
|
9495
|
+
if (legacy)
|
|
9496
|
+
return { path: legacy, source: "legacy-cli-js" };
|
|
9497
|
+
return null;
|
|
9498
|
+
}
|
|
9499
|
+
function getResolvedClaudeExecutableInfo() {
|
|
9500
|
+
return cachedClaudeInfo;
|
|
9501
|
+
}
|
|
9377
9502
|
async function resolveClaudeExecutableAsync() {
|
|
9378
|
-
if (
|
|
9379
|
-
return
|
|
9503
|
+
if (cachedClaudeInfo)
|
|
9504
|
+
return cachedClaudeInfo.path;
|
|
9380
9505
|
if (cachedClaudePathPromise)
|
|
9381
9506
|
return cachedClaudePathPromise;
|
|
9382
9507
|
cachedClaudePathPromise = (async () => {
|
|
9383
|
-
const
|
|
9384
|
-
|
|
9385
|
-
|
|
9386
|
-
|
|
9387
|
-
if (existsSync2(bundledBinary)) {
|
|
9388
|
-
cachedClaudePath = bundledBinary;
|
|
9389
|
-
return bundledBinary;
|
|
9390
|
-
}
|
|
9391
|
-
} catch {}
|
|
9392
|
-
try {
|
|
9393
|
-
const { stdout } = await exec("which claude");
|
|
9394
|
-
const claudePath = stdout.trim();
|
|
9395
|
-
if (claudePath && existsSync2(claudePath)) {
|
|
9396
|
-
cachedClaudePath = claudePath;
|
|
9397
|
-
return claudePath;
|
|
9398
|
-
}
|
|
9399
|
-
} catch {}
|
|
9400
|
-
if (runningUnderBun) {
|
|
9401
|
-
try {
|
|
9402
|
-
const sdkPath = fileURLToPath2(import.meta.resolve("@anthropic-ai/claude-agent-sdk"));
|
|
9403
|
-
const sdkCliJs = join2(dirname2(sdkPath), "cli.js");
|
|
9404
|
-
if (existsSync2(sdkCliJs)) {
|
|
9405
|
-
cachedClaudePath = sdkCliJs;
|
|
9406
|
-
return sdkCliJs;
|
|
9407
|
-
}
|
|
9408
|
-
} catch {}
|
|
9508
|
+
const resolved = await resolveClaudeExecutableWithSource();
|
|
9509
|
+
if (resolved) {
|
|
9510
|
+
cachedClaudeInfo = resolved;
|
|
9511
|
+
return resolved.path;
|
|
9409
9512
|
}
|
|
9410
|
-
throw new Error("Could not find Claude Code executable. Install via: npm install -g @anthropic-ai/claude-code");
|
|
9513
|
+
throw new Error("Could not find Claude Code executable. Install via: npm install -g @anthropic-ai/claude-code, " + "or set MERIDIAN_CLAUDE_PATH=/path/to/claude to point at an existing binary.");
|
|
9411
9514
|
})();
|
|
9412
9515
|
try {
|
|
9413
9516
|
return await cachedClaudePathPromise;
|
|
@@ -10285,6 +10388,10 @@ var DROID_ALLOWED_MCP_TOOLS = [
|
|
|
10285
10388
|
`mcp__${DROID_MCP_SERVER_NAME}__glob`,
|
|
10286
10389
|
`mcp__${DROID_MCP_SERVER_NAME}__grep`
|
|
10287
10390
|
];
|
|
10391
|
+
function resolveDroidPassthrough() {
|
|
10392
|
+
const envVal = process.env.MERIDIAN_PASSTHROUGH ?? process.env.CLAUDE_PROXY_PASSTHROUGH;
|
|
10393
|
+
return envVal === "1" || envVal === "true" || envVal === "yes";
|
|
10394
|
+
}
|
|
10288
10395
|
var droidTransforms = [
|
|
10289
10396
|
{
|
|
10290
10397
|
name: "droid-core",
|
|
@@ -10296,7 +10403,7 @@ var droidTransforms = [
|
|
|
10296
10403
|
incompatibleTools: CLAUDE_CODE_ONLY_TOOLS,
|
|
10297
10404
|
allowedMcpTools: DROID_ALLOWED_MCP_TOOLS,
|
|
10298
10405
|
sdkAgents: {},
|
|
10299
|
-
passthrough:
|
|
10406
|
+
passthrough: resolveDroidPassthrough(),
|
|
10300
10407
|
leaksCwdViaSystemReminder: true
|
|
10301
10408
|
};
|
|
10302
10409
|
}
|
|
@@ -10367,7 +10474,8 @@ var droidAdapter = {
|
|
|
10367
10474
|
return "";
|
|
10368
10475
|
},
|
|
10369
10476
|
usesPassthrough() {
|
|
10370
|
-
|
|
10477
|
+
const envVal = process.env.MERIDIAN_PASSTHROUGH ?? process.env.CLAUDE_PROXY_PASSTHROUGH;
|
|
10478
|
+
return envVal === "1" || envVal === "true" || envVal === "yes";
|
|
10371
10479
|
}
|
|
10372
10480
|
};
|
|
10373
10481
|
|
|
@@ -10929,10 +11037,6 @@ function detectAdapter(c) {
|
|
|
10929
11037
|
return defaultAdapter;
|
|
10930
11038
|
}
|
|
10931
11039
|
|
|
10932
|
-
// src/proxy/query.ts
|
|
10933
|
-
import { join as join3 } from "node:path";
|
|
10934
|
-
import { homedir as homedir2 } from "node:os";
|
|
10935
|
-
|
|
10936
11040
|
// src/mcpTools.ts
|
|
10937
11041
|
import { createSdkMcpServer as createSdkMcpServer2, tool } from "@anthropic-ai/claude-agent-sdk";
|
|
10938
11042
|
import * as fs from "node:fs/promises";
|
|
@@ -16625,6 +16729,15 @@ function createOpencodeMcpServer() {
|
|
|
16625
16729
|
}
|
|
16626
16730
|
|
|
16627
16731
|
// src/proxy/query.ts
|
|
16732
|
+
function stripConfigDir(env2) {
|
|
16733
|
+
if (!("CLAUDE_CONFIG_DIR" in env2))
|
|
16734
|
+
return env2;
|
|
16735
|
+
if (env2.CLAUDE_CODE_OAUTH_TOKEN)
|
|
16736
|
+
return env2;
|
|
16737
|
+
const out = { ...env2 };
|
|
16738
|
+
delete out.CLAUDE_CONFIG_DIR;
|
|
16739
|
+
return out;
|
|
16740
|
+
}
|
|
16628
16741
|
function computePassthroughMaxTurns(resumeSessionId, hasDeferredTools, advisorModel) {
|
|
16629
16742
|
const hasResume = !!resumeSessionId;
|
|
16630
16743
|
const base = hasResume && hasDeferredTools ? 4 : 3;
|
|
@@ -16729,10 +16842,9 @@ function buildQueryOptions(ctx) {
|
|
|
16729
16842
|
} : {},
|
|
16730
16843
|
...onStderr ? { stderr: onStderr } : {},
|
|
16731
16844
|
env: {
|
|
16732
|
-
...cleanEnv,
|
|
16845
|
+
...sharedMemory ? stripConfigDir(cleanEnv) : cleanEnv,
|
|
16733
16846
|
ENABLE_TOOL_SEARCH: hasDeferredTools ? "true" : "false",
|
|
16734
16847
|
...passthrough ? { ENABLE_CLAUDEAI_MCP_SERVERS: "false" } : {},
|
|
16735
|
-
...sharedMemory ? { CLAUDE_CONFIG_DIR: join3(homedir2(), ".claude") } : {},
|
|
16736
16848
|
...process.getuid?.() === 0 ? { IS_SANDBOX: "1" } : {}
|
|
16737
16849
|
},
|
|
16738
16850
|
...Object.keys(sdkAgents).length > 0 ? { agents: sdkAgents } : {},
|
|
@@ -16766,8 +16878,9 @@ function getAdapterTransforms(adapterName) {
|
|
|
16766
16878
|
}
|
|
16767
16879
|
|
|
16768
16880
|
// src/proxy/plugins/loader.ts
|
|
16769
|
-
import { readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as
|
|
16770
|
-
import { join as
|
|
16881
|
+
import { readdirSync as readdirSync2, readFileSync as readFileSync2, existsSync as existsSync4 } from "fs";
|
|
16882
|
+
import { join as join3, isAbsolute as isAbsolute2, extname } from "path";
|
|
16883
|
+
import { pathToFileURL } from "url";
|
|
16771
16884
|
|
|
16772
16885
|
// src/proxy/plugins/validation.ts
|
|
16773
16886
|
var KNOWN_ADAPTERS = ["opencode", "crush", "droid", "pi", "forgecode", "passthrough"];
|
|
@@ -16807,7 +16920,7 @@ function validateTransform(exported) {
|
|
|
16807
16920
|
// src/proxy/plugins/loader.ts
|
|
16808
16921
|
var loadCounter = 0;
|
|
16809
16922
|
function parsePluginConfig(configPath) {
|
|
16810
|
-
if (!
|
|
16923
|
+
if (!existsSync4(configPath))
|
|
16811
16924
|
return [];
|
|
16812
16925
|
try {
|
|
16813
16926
|
const raw2 = readFileSync2(configPath, "utf-8");
|
|
@@ -16820,7 +16933,7 @@ function parsePluginConfig(configPath) {
|
|
|
16820
16933
|
async function loadPlugins(pluginDir, configPath) {
|
|
16821
16934
|
resetAllPluginStats();
|
|
16822
16935
|
const config = configPath ? parsePluginConfig(configPath) : [];
|
|
16823
|
-
const pluginDirExists =
|
|
16936
|
+
const pluginDirExists = existsSync4(pluginDir);
|
|
16824
16937
|
let filenames = [];
|
|
16825
16938
|
if (pluginDirExists) {
|
|
16826
16939
|
try {
|
|
@@ -16851,7 +16964,7 @@ async function loadPlugins(pluginDir, configPath) {
|
|
|
16851
16964
|
const loaded = [];
|
|
16852
16965
|
const seenNames = new Set;
|
|
16853
16966
|
for (const { filename, entry } of ordered) {
|
|
16854
|
-
const filePath = isAbsolute2(filename) ? filename :
|
|
16967
|
+
const filePath = isAbsolute2(filename) ? filename : join3(pluginDir, filename);
|
|
16855
16968
|
if (entry && !entry.enabled) {
|
|
16856
16969
|
loaded.push({
|
|
16857
16970
|
name: filename,
|
|
@@ -16864,7 +16977,8 @@ async function loadPlugins(pluginDir, configPath) {
|
|
|
16864
16977
|
}
|
|
16865
16978
|
try {
|
|
16866
16979
|
const cacheBuster = `?t=${Date.now()}-${++loadCounter}`;
|
|
16867
|
-
const
|
|
16980
|
+
const specifier = process.platform === "win32" ? pathToFileURL(filePath).href + cacheBuster : filePath + cacheBuster;
|
|
16981
|
+
const mod = await import(specifier);
|
|
16868
16982
|
const exported = mod.default ?? mod;
|
|
16869
16983
|
const transforms = Array.isArray(exported) ? exported : [exported];
|
|
16870
16984
|
for (const item of transforms) {
|
|
@@ -17222,17 +17336,17 @@ function verifyLineage(cached, messages, cacheKey2, cache) {
|
|
|
17222
17336
|
// src/proxy/sessionStore.ts
|
|
17223
17337
|
import {
|
|
17224
17338
|
closeSync,
|
|
17225
|
-
existsSync as
|
|
17339
|
+
existsSync as existsSync5,
|
|
17226
17340
|
mkdirSync,
|
|
17227
17341
|
openSync,
|
|
17228
17342
|
readFileSync as readFileSync3,
|
|
17229
17343
|
renameSync,
|
|
17230
|
-
statSync,
|
|
17344
|
+
statSync as statSync2,
|
|
17231
17345
|
unlinkSync,
|
|
17232
17346
|
writeFileSync
|
|
17233
17347
|
} from "node:fs";
|
|
17234
|
-
import { homedir as
|
|
17235
|
-
import { join as
|
|
17348
|
+
import { homedir as homedir2 } from "node:os";
|
|
17349
|
+
import { join as join4 } from "node:path";
|
|
17236
17350
|
var DEFAULT_MAX_STORED_SESSIONS = 1e4;
|
|
17237
17351
|
var STALE_LOCK_THRESHOLD_MS = 30000;
|
|
17238
17352
|
function getMaxStoredSessions() {
|
|
@@ -17256,7 +17370,7 @@ function acquireLock(lockPath) {
|
|
|
17256
17370
|
return false;
|
|
17257
17371
|
}
|
|
17258
17372
|
try {
|
|
17259
|
-
const stat =
|
|
17373
|
+
const stat = statSync2(lockPath);
|
|
17260
17374
|
if (Date.now() - stat.mtimeMs > STALE_LOCK_THRESHOLD_MS) {
|
|
17261
17375
|
unlinkSync(lockPath);
|
|
17262
17376
|
const fd = openSync(lockPath, "wx");
|
|
@@ -17280,17 +17394,17 @@ var sessionDirOverride = null;
|
|
|
17280
17394
|
var skipLocking = false;
|
|
17281
17395
|
function getStorePath() {
|
|
17282
17396
|
const dir = sessionDirOverride || process.env.MERIDIAN_SESSION_DIR || process.env.CLAUDE_PROXY_SESSION_DIR || getDefaultCacheDir();
|
|
17283
|
-
if (!
|
|
17397
|
+
if (!existsSync5(dir)) {
|
|
17284
17398
|
mkdirSync(dir, { recursive: true });
|
|
17285
17399
|
}
|
|
17286
|
-
return
|
|
17400
|
+
return join4(dir, "sessions.json");
|
|
17287
17401
|
}
|
|
17288
17402
|
function getDefaultCacheDir() {
|
|
17289
|
-
const newDir =
|
|
17290
|
-
const oldDir =
|
|
17291
|
-
if (
|
|
17403
|
+
const newDir = join4(homedir2(), ".cache", "meridian");
|
|
17404
|
+
const oldDir = join4(homedir2(), ".cache", "opencode-claude-max-proxy");
|
|
17405
|
+
if (existsSync5(newDir))
|
|
17292
17406
|
return newDir;
|
|
17293
|
-
if (
|
|
17407
|
+
if (existsSync5(oldDir)) {
|
|
17294
17408
|
try {
|
|
17295
17409
|
const { symlinkSync } = __require("fs");
|
|
17296
17410
|
symlinkSync(oldDir, newDir);
|
|
@@ -17303,7 +17417,7 @@ function getDefaultCacheDir() {
|
|
|
17303
17417
|
}
|
|
17304
17418
|
function readStore() {
|
|
17305
17419
|
const path3 = getStorePath();
|
|
17306
|
-
if (!
|
|
17420
|
+
if (!existsSync5(path3))
|
|
17307
17421
|
return {};
|
|
17308
17422
|
try {
|
|
17309
17423
|
const data = readFileSync3(path3, "utf-8");
|
|
@@ -17805,8 +17919,8 @@ function createProxyServer(config = {}) {
|
|
|
17805
17919
|
const sessionDiscoveredTools = new Map;
|
|
17806
17920
|
const sessionToolCache = new Map;
|
|
17807
17921
|
const sessionMcpCache = new LRUMap(getMaxSessionsLimit());
|
|
17808
|
-
const pluginDir = finalConfig.pluginDir ??
|
|
17809
|
-
const pluginConfigPath = finalConfig.pluginConfigPath ??
|
|
17922
|
+
const pluginDir = finalConfig.pluginDir ?? join6(homedir4(), ".config", "meridian", "plugins");
|
|
17923
|
+
const pluginConfigPath = finalConfig.pluginConfigPath ?? join6(homedir4(), ".config", "meridian", "plugins.json");
|
|
17810
17924
|
let loadedPlugins = [];
|
|
17811
17925
|
let pluginTransforms = [];
|
|
17812
17926
|
const app = new Hono2;
|
|
@@ -17820,6 +17934,8 @@ function createProxyServer(config = {}) {
|
|
|
17820
17934
|
app.use("/profiles", requireAuth);
|
|
17821
17935
|
app.use("/plugins/*", requireAuth);
|
|
17822
17936
|
app.use("/plugins", requireAuth);
|
|
17937
|
+
app.use("/settings/*", requireAuth);
|
|
17938
|
+
app.use("/settings", requireAuth);
|
|
17823
17939
|
app.use("/auth/*", requireAuth);
|
|
17824
17940
|
app.get("/", (c) => {
|
|
17825
17941
|
const accept = c.req.header("accept") || "";
|
|
@@ -17872,18 +17988,33 @@ function createProxyServer(config = {}) {
|
|
|
17872
17988
|
if (!Array.isArray(body.messages)) {
|
|
17873
17989
|
return c.json({ type: "error", error: { type: "invalid_request_error", message: "messages: Field required" } }, 400);
|
|
17874
17990
|
}
|
|
17991
|
+
if (body.messages.length === 0) {
|
|
17992
|
+
return c.json({ type: "error", error: { type: "invalid_request_error", message: "messages: Cannot be empty — at least one message is required" } }, 400);
|
|
17993
|
+
}
|
|
17875
17994
|
const profile = resolveProfile(finalConfig.profiles, finalConfig.defaultProfile, c.req.header("x-meridian-profile") || undefined);
|
|
17876
17995
|
const authStatus = await getClaudeAuthStatusAsync(profile.id !== "default" ? profile.id : undefined, Object.keys(profile.env).length > 0 ? profile.env : undefined);
|
|
17877
17996
|
const agentMode = c.req.header("x-opencode-agent-mode") ?? null;
|
|
17878
17997
|
const requestSource = c.req.header("x-meridian-source")?.slice(0, 64) || undefined;
|
|
17879
17998
|
let model = mapModelToClaudeModel(body.model || "sonnet", authStatus?.subscriptionType, agentMode);
|
|
17880
|
-
const
|
|
17881
|
-
|
|
17999
|
+
const cwdResolution = resolveSdkWorkingDirectory({
|
|
18000
|
+
envOverride: process.env.MERIDIAN_WORKDIR ?? process.env.CLAUDE_PROXY_WORKDIR,
|
|
18001
|
+
adapterCwd: adapter.extractWorkingDirectory(body),
|
|
18002
|
+
fallback: process.cwd()
|
|
18003
|
+
});
|
|
18004
|
+
const workingDirectory = cwdResolution.workingDirectory;
|
|
18005
|
+
if (cwdResolution.fellBack) {
|
|
18006
|
+
claudeLog("cwd_fallback", {
|
|
18007
|
+
claimed: cwdResolution.claimedWorkingDirectory,
|
|
18008
|
+
usedInstead: workingDirectory
|
|
18009
|
+
});
|
|
18010
|
+
}
|
|
18011
|
+
const clientWorkingDirectory = adapter.extractClientWorkingDirectory?.(body) || cwdResolution.claimedWorkingDirectory;
|
|
17882
18012
|
const {
|
|
17883
|
-
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS,
|
|
17884
18013
|
ANTHROPIC_API_KEY: _dropApiKey,
|
|
17885
18014
|
ANTHROPIC_BASE_URL: _dropBaseUrl,
|
|
17886
18015
|
ANTHROPIC_AUTH_TOKEN: _dropAuthToken,
|
|
18016
|
+
CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS,
|
|
18017
|
+
CLAUDE_CODE_USE_POWERSHELL_TOOL: _dropUsePowershell,
|
|
17887
18018
|
...cleanEnv
|
|
17888
18019
|
} = process.env;
|
|
17889
18020
|
const sdkModelDefaults = resolveSdkModelDefaults();
|
|
@@ -18142,7 +18273,7 @@ function createProxyServer(config = {}) {
|
|
|
18142
18273
|
const upstreamStartAt = Date.now();
|
|
18143
18274
|
let firstChunkAt;
|
|
18144
18275
|
let currentSessionId;
|
|
18145
|
-
const sdkUuidMap = cachedSession?.sdkMessageUuids ? [...cachedSession.sdkMessageUuids] :
|
|
18276
|
+
const sdkUuidMap = cachedSession?.sdkMessageUuids ? [...cachedSession.sdkMessageUuids] : [];
|
|
18146
18277
|
while (sdkUuidMap.length < allMessages.length)
|
|
18147
18278
|
sdkUuidMap.push(null);
|
|
18148
18279
|
claudeLog("upstream.start", { mode: "non_stream", model });
|
|
@@ -18156,6 +18287,7 @@ function createProxyServer(config = {}) {
|
|
|
18156
18287
|
const RATE_LIMIT_BASE_DELAY_MS = 1000;
|
|
18157
18288
|
const response = async function* () {
|
|
18158
18289
|
let rateLimitRetries = 0;
|
|
18290
|
+
await ensureFreshToken().catch(() => {});
|
|
18159
18291
|
let tokenRefreshed = false;
|
|
18160
18292
|
while (true) {
|
|
18161
18293
|
let didYieldContent = false;
|
|
@@ -18187,7 +18319,7 @@ function createProxyServer(config = {}) {
|
|
|
18187
18319
|
taskBudget,
|
|
18188
18320
|
betas,
|
|
18189
18321
|
settingSources,
|
|
18190
|
-
codeSystemPrompt: sdkFeatures.codeSystemPrompt
|
|
18322
|
+
codeSystemPrompt: sdkFeatures.codeSystemPrompt,
|
|
18191
18323
|
clientSystemPrompt: sdkFeatures.clientSystemPrompt === false ? false : undefined,
|
|
18192
18324
|
memory: sdkFeatures.memory,
|
|
18193
18325
|
dreaming: sdkFeatures.dreaming,
|
|
@@ -18249,7 +18381,7 @@ function createProxyServer(config = {}) {
|
|
|
18249
18381
|
taskBudget,
|
|
18250
18382
|
betas,
|
|
18251
18383
|
settingSources,
|
|
18252
|
-
codeSystemPrompt: sdkFeatures.codeSystemPrompt
|
|
18384
|
+
codeSystemPrompt: sdkFeatures.codeSystemPrompt,
|
|
18253
18385
|
clientSystemPrompt: sdkFeatures.clientSystemPrompt === false ? false : undefined,
|
|
18254
18386
|
memory: sdkFeatures.memory,
|
|
18255
18387
|
dreaming: sdkFeatures.dreaming,
|
|
@@ -18360,6 +18492,12 @@ function createProxyServer(config = {}) {
|
|
|
18360
18492
|
lastStopReason = message.message.stop_reason;
|
|
18361
18493
|
}
|
|
18362
18494
|
}
|
|
18495
|
+
if (message.type === "result") {
|
|
18496
|
+
const resultUsage = message.usage;
|
|
18497
|
+
if (resultUsage) {
|
|
18498
|
+
lastUsage = { ...lastUsage, ...resultUsage };
|
|
18499
|
+
}
|
|
18500
|
+
}
|
|
18363
18501
|
}
|
|
18364
18502
|
claudeLog("upstream.completed", {
|
|
18365
18503
|
mode: "non_stream",
|
|
@@ -18539,7 +18677,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
18539
18677
|
throw error;
|
|
18540
18678
|
}
|
|
18541
18679
|
};
|
|
18542
|
-
const sdkUuidMap = cachedSession?.sdkMessageUuids ? [...cachedSession.sdkMessageUuids] :
|
|
18680
|
+
const sdkUuidMap = cachedSession?.sdkMessageUuids ? [...cachedSession.sdkMessageUuids] : [];
|
|
18543
18681
|
while (sdkUuidMap.length < allMessages.length)
|
|
18544
18682
|
sdkUuidMap.push(null);
|
|
18545
18683
|
let messageStartEmitted = false;
|
|
@@ -18551,6 +18689,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
18551
18689
|
const RATE_LIMIT_BASE_DELAY_MS = 1000;
|
|
18552
18690
|
const response = async function* () {
|
|
18553
18691
|
let rateLimitRetries = 0;
|
|
18692
|
+
await ensureFreshToken().catch(() => {});
|
|
18554
18693
|
let tokenRefreshed = false;
|
|
18555
18694
|
while (true) {
|
|
18556
18695
|
let didYieldClientEvent = false;
|
|
@@ -18582,7 +18721,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
18582
18721
|
taskBudget,
|
|
18583
18722
|
betas,
|
|
18584
18723
|
settingSources,
|
|
18585
|
-
codeSystemPrompt: sdkFeatures.codeSystemPrompt
|
|
18724
|
+
codeSystemPrompt: sdkFeatures.codeSystemPrompt,
|
|
18586
18725
|
clientSystemPrompt: sdkFeatures.clientSystemPrompt === false ? false : undefined,
|
|
18587
18726
|
memory: sdkFeatures.memory,
|
|
18588
18727
|
dreaming: sdkFeatures.dreaming,
|
|
@@ -18644,7 +18783,7 @@ Subprocess stderr: ${stderrOutput}`;
|
|
|
18644
18783
|
taskBudget,
|
|
18645
18784
|
betas,
|
|
18646
18785
|
settingSources,
|
|
18647
|
-
codeSystemPrompt: sdkFeatures.codeSystemPrompt
|
|
18786
|
+
codeSystemPrompt: sdkFeatures.codeSystemPrompt,
|
|
18648
18787
|
clientSystemPrompt: sdkFeatures.clientSystemPrompt === false ? false : undefined,
|
|
18649
18788
|
memory: sdkFeatures.memory,
|
|
18650
18789
|
dreaming: sdkFeatures.dreaming,
|
|
@@ -19368,6 +19507,7 @@ data: ${JSON.stringify({
|
|
|
19368
19507
|
auth: { loggedIn: false }
|
|
19369
19508
|
}, 503);
|
|
19370
19509
|
}
|
|
19510
|
+
const claudeExecutableInfo = getResolvedClaudeExecutableInfo();
|
|
19371
19511
|
return c.json({
|
|
19372
19512
|
status: "healthy",
|
|
19373
19513
|
version: serverVersion,
|
|
@@ -19377,6 +19517,7 @@ data: ${JSON.stringify({
|
|
|
19377
19517
|
subscriptionType: auth.subscriptionType
|
|
19378
19518
|
},
|
|
19379
19519
|
mode: envBool("PASSTHROUGH") ? "passthrough" : "internal",
|
|
19520
|
+
...claudeExecutableInfo ? { claudeExecutable: claudeExecutableInfo } : {},
|
|
19380
19521
|
plugin: { opencode: checkPluginConfigured() ? "configured" : "not-configured" }
|
|
19381
19522
|
});
|
|
19382
19523
|
} catch {
|
|
@@ -19489,9 +19630,16 @@ data: ${JSON.stringify({
|
|
|
19489
19630
|
if (!anthropicBody) {
|
|
19490
19631
|
return c.json({ type: "error", error: { type: "invalid_request_error", message: "messages: Field required" } }, 400);
|
|
19491
19632
|
}
|
|
19633
|
+
const internalHeaders = { "Content-Type": "application/json" };
|
|
19634
|
+
const xApiKey = c.req.header("x-api-key");
|
|
19635
|
+
if (xApiKey)
|
|
19636
|
+
internalHeaders["x-api-key"] = xApiKey;
|
|
19637
|
+
const authz = c.req.header("authorization");
|
|
19638
|
+
if (authz)
|
|
19639
|
+
internalHeaders["authorization"] = authz;
|
|
19492
19640
|
const internalReq = new Request("http://internal/v1/messages", {
|
|
19493
19641
|
method: "POST",
|
|
19494
|
-
headers:
|
|
19642
|
+
headers: internalHeaders,
|
|
19495
19643
|
body: JSON.stringify(anthropicBody)
|
|
19496
19644
|
});
|
|
19497
19645
|
const internalRes = await app.fetch(internalReq);
|
|
@@ -19770,6 +19918,10 @@ async function startProxyServer(config = {}) {
|
|
|
19770
19918
|
console.log(`Telemetry dashboard: http://${finalConfig.host}:${info.port}/telemetry`);
|
|
19771
19919
|
const pins = resolveSdkModelDefaults();
|
|
19772
19920
|
console.log(`Model pins: opus=${pins.ANTHROPIC_DEFAULT_OPUS_MODEL} sonnet=${pins.ANTHROPIC_DEFAULT_SONNET_MODEL} haiku=${pins.ANTHROPIC_DEFAULT_HAIKU_MODEL}`);
|
|
19921
|
+
const claudeInfo = getResolvedClaudeExecutableInfo();
|
|
19922
|
+
if (claudeInfo) {
|
|
19923
|
+
console.log(`Claude executable: ${claudeInfo.path} (resolved via ${claudeInfo.source})`);
|
|
19924
|
+
}
|
|
19773
19925
|
console.log(`
|
|
19774
19926
|
Point any Anthropic-compatible tool at this endpoint:`);
|
|
19775
19927
|
console.log(` ANTHROPIC_API_KEY=x ANTHROPIC_BASE_URL=http://${finalConfig.host}:${info.port}`);
|
|
@@ -19791,6 +19943,7 @@ Or use a different port:`);
|
|
|
19791
19943
|
console.error(` MERIDIAN_PORT=4567 meridian`);
|
|
19792
19944
|
}
|
|
19793
19945
|
});
|
|
19946
|
+
startBackgroundRefresh();
|
|
19794
19947
|
let authKeepaliveInterval;
|
|
19795
19948
|
const effectiveProfiles = getEffectiveProfiles(finalConfig.profiles);
|
|
19796
19949
|
if (effectiveProfiles.length > 0) {
|
|
@@ -19814,6 +19967,7 @@ Or use a different port:`);
|
|
|
19814
19967
|
async close() {
|
|
19815
19968
|
if (authKeepaliveInterval)
|
|
19816
19969
|
clearInterval(authKeepaliveInterval);
|
|
19970
|
+
stopBackgroundRefresh();
|
|
19817
19971
|
await new Promise((resolve3, reject) => {
|
|
19818
19972
|
server.close((err) => err ? reject(err) : resolve3());
|
|
19819
19973
|
});
|