@rynfar/meridian 1.53.0 → 1.54.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 CHANGED
@@ -667,6 +667,47 @@ Run several configurations of the same adapter side by side — e.g. a passthrou
667
667
 
668
668
  Built-in adapter names are reserved and can't be shadowed. With no instances configured, detection is exactly the built-in chain. Config file changes apply within ~5s, no restart needed.
669
669
 
670
+ ### Claude Design MCP
671
+
672
+ Meridian proxies the Claude Design MCP API (`api.anthropic.com/v1/design/*`), so MCP clients can use Claude Design tools through your local endpoint.
673
+
674
+ **1. Add the MCP server.** For Claude Code:
675
+
676
+ ```bash
677
+ claude mcp add -s user --transport http claude-design http://127.0.0.1:3456/v1/design/mcp
678
+ ```
679
+
680
+ Any other MCP client: point it at `http://127.0.0.1:3456/v1/design/mcp` (streamable HTTP).
681
+
682
+ **2. Grant Claude Design consent (one time, per Anthropic account).** Tool calls return a `needs_consent` error until you enable it: open [claude.ai/design/settings](https://claude.ai/design/settings), find **"Claude product access"** ("Let other Claude products, like Claude Code, read and edit your Design projects"), and switch it **On**. This is a setting on the Anthropic account itself — with multiple Meridian profiles, the account behind the *profile handling the request* is the one that needs the toggle.
683
+
684
+ That's it — your existing Claude Max login covers auth (`initialize`, `tools/list`, and tool calls are all verified working with a plain Max token). Verify with a quick handshake:
685
+
686
+ ```bash
687
+ curl -s -X POST http://127.0.0.1:3456/v1/design/mcp -H 'content-type: application/json' \
688
+ -d '{"jsonrpc":"2.0","method":"tools/list","id":1}'
689
+ ```
690
+
691
+ **Multiple profiles:** design requests use the active profile by default. To pin design traffic to a specific profile regardless of which is active, register the server with a profile header:
692
+
693
+ ```bash
694
+ claude mcp add -s user --transport http --header "x-meridian-profile: personal" \
695
+ claude-design http://127.0.0.1:3456/v1/design/mcp
696
+ ```
697
+
698
+ **Fallback OAuth flow:** if the upstream ever rejects your token with an `auth_error` (scope enforcement has varied over time), `/design-login` obtains a dedicated token with the `user:design:read`/`user:design:write` scopes:
699
+
700
+ ```bash
701
+ curl http://127.0.0.1:3456/design-login # returns an authorize URL — open it in your browser
702
+ curl -X POST http://127.0.0.1:3456/design-login \
703
+ -H 'content-type: application/json' \
704
+ -d '{"code": "<code-from-browser>"}' # paste the code you were shown
705
+ ```
706
+
707
+ The design token is stored at `~/.config/meridian/design-token.json` (mode `0600`, global across profiles) and refreshed automatically when it expires.
708
+
709
+ > Contributed by [@sittitep](https://github.com/sittitep) (#543).
710
+
670
711
  ### Any Anthropic-compatible tool
671
712
 
672
713
  ```bash
@@ -834,6 +875,8 @@ ANTHROPIC_API_KEY=your-secret-key ANTHROPIC_BASE_URL=http://meridian-host:3456 o
834
875
  | `POST /v1/chat/completions` | OpenAI-compatible chat completions |
835
876
  | `POST /v1/responses` | OpenAI Responses API (Codex CLI ≥ 0.96) |
836
877
  | `GET /v1/models` | OpenAI-compatible model list |
878
+ | `GET/POST /v1/design/*` | Claude Design MCP proxy (see [Claude Design MCP](#claude-design-mcp)) |
879
+ | `GET/POST /design-login` | OAuth flow for the design scopes |
837
880
  | `GET /health` | Auth status, mode, plugin status |
838
881
  | `POST /auth/refresh` | Manually refresh the OAuth token |
839
882
  | `GET /telemetry` | Performance dashboard |
@@ -1,22 +1,347 @@
1
- import {
2
- resolveClaudeExecutableSync
3
- } from "./cli-vjeftz4z.js";
4
1
  import {
5
2
  setSetting
6
3
  } from "./cli-340h1chz.js";
7
4
  import {
8
5
  createPlatformCredentialStore
9
6
  } from "./cli-aq5zz92m.js";
10
- import"./cli-p9swy5t3.js";
7
+ import {
8
+ __esm
9
+ } from "./cli-p9swy5t3.js";
10
+
11
+ // src/env.ts
12
+ function env(suffix) {
13
+ return process.env[`MERIDIAN_${suffix}`] ?? process.env[`CLAUDE_PROXY_${suffix}`];
14
+ }
15
+ function envBool(suffix) {
16
+ const val = env(suffix);
17
+ return val === "1" || val === "true" || val === "yes";
18
+ }
19
+ function resolvePassthrough(defaultValue) {
20
+ const val = env("PASSTHROUGH");
21
+ if (val === "1" || val === "true" || val === "yes")
22
+ return true;
23
+ if (val === "0" || val === "false" || val === "no")
24
+ return false;
25
+ return defaultValue;
26
+ }
27
+ function envInt(suffix, defaultValue) {
28
+ const val = env(suffix);
29
+ if (!val)
30
+ return defaultValue;
31
+ const parsed = parseInt(val, 10);
32
+ return Number.isFinite(parsed) ? parsed : defaultValue;
33
+ }
34
+ var init_env = () => {};
11
35
 
12
36
  // src/proxy/profileCli.ts
13
37
  import { execFileSync, spawnSync } from "node:child_process";
14
38
  import { createHash, randomBytes } from "node:crypto";
15
- import { mkdirSync, readFileSync, rmSync, writeFileSync, existsSync } from "node:fs";
39
+ import { mkdirSync, readFileSync, rmSync, writeFileSync, existsSync as existsSync2 } from "node:fs";
16
40
  import { homedir } from "node:os";
17
- import { join } from "node:path";
18
- var PROFILES_DIR = join(homedir(), ".config", "meridian", "profiles");
19
- var CONFIG_FILE = join(homedir(), ".config", "meridian", "profiles.json");
41
+ import { join as join2 } from "node:path";
42
+
43
+ // src/proxy/models.ts
44
+ init_env();
45
+ import { exec as execCallback, execFile as execFileCallback } from "child_process";
46
+ import { existsSync, statSync } from "fs";
47
+ import { fileURLToPath } from "url";
48
+ import { join, dirname } from "path";
49
+ import { promisify } from "util";
50
+ var exec = promisify(execCallback);
51
+ var execFile = promisify(execFileCallback);
52
+ var STUB_SIZE_THRESHOLD = 4096;
53
+ var CANONICAL_FABLE_MODEL = "claude-fable-5";
54
+ var CANONICAL_OPUS_MODEL = "claude-opus-4-8";
55
+ var CANONICAL_SONNET_MODEL = "claude-sonnet-5";
56
+ var CANONICAL_HAIKU_MODEL = "claude-haiku-4-5";
57
+ function resolveSdkModelDefaults(env2 = process.env) {
58
+ return {
59
+ ANTHROPIC_DEFAULT_FABLE_MODEL: env2.MERIDIAN_DEFAULT_FABLE_MODEL ?? CANONICAL_FABLE_MODEL,
60
+ ANTHROPIC_DEFAULT_OPUS_MODEL: env2.MERIDIAN_DEFAULT_OPUS_MODEL ?? CANONICAL_OPUS_MODEL,
61
+ ANTHROPIC_DEFAULT_SONNET_MODEL: env2.MERIDIAN_DEFAULT_SONNET_MODEL ?? CANONICAL_SONNET_MODEL,
62
+ ANTHROPIC_DEFAULT_HAIKU_MODEL: env2.MERIDIAN_DEFAULT_HAIKU_MODEL ?? CANONICAL_HAIKU_MODEL
63
+ };
64
+ }
65
+ function explicitModelPin(requestedModel) {
66
+ const base = requestedModel.trim().toLowerCase().replace(/\[1m\]$/, "");
67
+ const match = /^claude-(sonnet|opus|haiku|fable|mythos)-\d[\w.-]*$/.exec(base);
68
+ if (!match)
69
+ return;
70
+ const tier = match[1] === "mythos" ? "FABLE" : match[1].toUpperCase();
71
+ return { [`ANTHROPIC_DEFAULT_${tier}_MODEL`]: base };
72
+ }
73
+ var AUTH_STATUS_CACHE_TTL_MS = 60000;
74
+ var AUTH_STATUS_FAILURE_TTL_MS = 5000;
75
+ var cachedAuthStatus = null;
76
+ var lastKnownGoodAuthStatus = null;
77
+ var cachedAuthStatusAt = 0;
78
+ var cachedAuthStatusIsFailure = false;
79
+ var cachedAuthStatusPromise = null;
80
+ function supports1mContext(model) {
81
+ const override = env("1M_CONTEXT_SUPPORT");
82
+ if (override === "0" || override === "false" || override === "no")
83
+ return false;
84
+ if (model.includes("4-5") || model.includes("4.5"))
85
+ return false;
86
+ return true;
87
+ }
88
+ function mapModelToClaudeModel(model, subscriptionType, agentMode) {
89
+ if (model.includes("haiku"))
90
+ return "haiku";
91
+ const use1m = supports1mContext(model);
92
+ const isSubagent = agentMode === "subagent";
93
+ if (model.includes("fable") || model.includes("mythos")) {
94
+ if (use1m && !isSubagent && !isExtendedContextKnownUnavailable())
95
+ return "fable[1m]";
96
+ return "fable";
97
+ }
98
+ if (model.includes("opus")) {
99
+ if (use1m && !isSubagent && !isExtendedContextKnownUnavailable())
100
+ return "opus[1m]";
101
+ return "opus";
102
+ }
103
+ const sonnetOverride = process.env.MERIDIAN_SONNET_MODEL ?? process.env.CLAUDE_PROXY_SONNET_MODEL;
104
+ if (sonnetOverride === "sonnet[1m]") {
105
+ if (!use1m || isSubagent || isExtendedContextKnownUnavailable())
106
+ return "sonnet";
107
+ return "sonnet[1m]";
108
+ }
109
+ return "sonnet";
110
+ }
111
+ var EXTRA_USAGE_RETRY_MS = 60 * 60 * 1000;
112
+ var extraUsageUnavailableAt = 0;
113
+ function recordExtendedContextUnavailable() {
114
+ extraUsageUnavailableAt = Date.now();
115
+ }
116
+ function isExtendedContextKnownUnavailable() {
117
+ return extraUsageUnavailableAt > 0 && Date.now() - extraUsageUnavailableAt < EXTRA_USAGE_RETRY_MS;
118
+ }
119
+ function stripExtendedContext(model) {
120
+ if (model === "opus[1m]")
121
+ return "opus";
122
+ if (model === "sonnet[1m]")
123
+ return "sonnet";
124
+ if (model === "fable[1m]")
125
+ return "fable";
126
+ return model;
127
+ }
128
+ function hasExtendedContext(model) {
129
+ return model.endsWith("[1m]");
130
+ }
131
+ var profileAuthCaches = new Map;
132
+ function getAuthCacheInfo(profileId) {
133
+ if (!profileId) {
134
+ return { lastCheckedAt: cachedAuthStatusAt, lastSuccessAt: cachedAuthStatusIsFailure ? 0 : cachedAuthStatusAt, isFailure: cachedAuthStatusIsFailure };
135
+ }
136
+ const cache = profileAuthCaches.get(profileId);
137
+ if (!cache)
138
+ return { lastCheckedAt: 0, lastSuccessAt: 0, isFailure: false };
139
+ return { lastCheckedAt: cache.at, lastSuccessAt: cache.lastSuccessAt, isFailure: cache.isFailure };
140
+ }
141
+ function getAuthCache(key) {
142
+ let cache = profileAuthCaches.get(key);
143
+ if (!cache) {
144
+ cache = { status: null, lastKnownGood: null, at: 0, isFailure: false, promise: null, lastSuccessAt: 0 };
145
+ profileAuthCaches.set(key, cache);
146
+ }
147
+ return cache;
148
+ }
149
+ async function getClaudeAuthStatusAsync(profileId, envOverrides) {
150
+ const isDefault = !profileId;
151
+ const cache = isDefault ? null : getAuthCache(profileId);
152
+ const c_status = cache ? cache.status : cachedAuthStatus;
153
+ const c_lastKnownGood = cache ? cache.lastKnownGood : lastKnownGoodAuthStatus;
154
+ const c_at = cache ? cache.at : cachedAuthStatusAt;
155
+ const c_isFailure = cache ? cache.isFailure : cachedAuthStatusIsFailure;
156
+ let c_promise = cache ? cache.promise : cachedAuthStatusPromise;
157
+ const ttl = c_isFailure ? AUTH_STATUS_FAILURE_TTL_MS : AUTH_STATUS_CACHE_TTL_MS;
158
+ if (c_at > 0 && Date.now() - c_at < ttl) {
159
+ return c_status ?? c_lastKnownGood;
160
+ }
161
+ if (c_promise)
162
+ return c_promise;
163
+ c_promise = (async () => {
164
+ try {
165
+ const claudePath = await resolveClaudeExecutableAsync();
166
+ const { stdout } = await execFile(claudePath, ["auth", "status"], {
167
+ timeout: 5000,
168
+ ...envOverrides ? { env: { ...process.env, ...envOverrides } } : {}
169
+ });
170
+ const parsed = JSON.parse(stdout);
171
+ if (cache) {
172
+ cache.status = parsed;
173
+ cache.lastKnownGood = parsed;
174
+ cache.at = Date.now();
175
+ cache.isFailure = false;
176
+ cache.lastSuccessAt = Date.now();
177
+ } else {
178
+ cachedAuthStatus = parsed;
179
+ lastKnownGoodAuthStatus = parsed;
180
+ cachedAuthStatusAt = Date.now();
181
+ cachedAuthStatusIsFailure = false;
182
+ }
183
+ return parsed;
184
+ } catch {
185
+ if (cache) {
186
+ cache.isFailure = true;
187
+ cache.at = Date.now();
188
+ cache.status = null;
189
+ return cache.lastKnownGood;
190
+ } else {
191
+ cachedAuthStatusIsFailure = true;
192
+ cachedAuthStatusAt = Date.now();
193
+ cachedAuthStatus = null;
194
+ return lastKnownGoodAuthStatus;
195
+ }
196
+ }
197
+ })();
198
+ if (cache)
199
+ cache.promise = c_promise;
200
+ else
201
+ cachedAuthStatusPromise = c_promise;
202
+ try {
203
+ return await c_promise;
204
+ } finally {
205
+ if (cache)
206
+ cache.promise = null;
207
+ else
208
+ cachedAuthStatusPromise = null;
209
+ }
210
+ }
211
+ var cachedClaudeInfo = null;
212
+ var cachedClaudePathPromise = null;
213
+ var DEFAULT_DEPS = {
214
+ existsSync,
215
+ statSync: (p) => statSync(p),
216
+ exec,
217
+ resolvePackage: (specifier) => fileURLToPath(import.meta.resolve(specifier)),
218
+ envGet: (name) => process.env[name],
219
+ platform: process.platform,
220
+ arch: process.arch,
221
+ isBun: typeof process.versions.bun !== "undefined"
222
+ };
223
+ function tryEnvOverride(deps) {
224
+ const explicit = deps.envGet("MERIDIAN_CLAUDE_PATH");
225
+ if (!explicit)
226
+ return null;
227
+ return deps.existsSync(explicit) ? explicit : null;
228
+ }
229
+ function tryBundledBinary(deps) {
230
+ try {
231
+ const pkgPath = deps.resolvePackage("@anthropic-ai/claude-code/package.json");
232
+ const bundled = join(dirname(pkgPath), "bin", "claude.exe");
233
+ if (!deps.existsSync(bundled))
234
+ return null;
235
+ const size = deps.statSync(bundled).size;
236
+ if (size <= STUB_SIZE_THRESHOLD)
237
+ return null;
238
+ return bundled;
239
+ } catch {
240
+ return null;
241
+ }
242
+ }
243
+ function tryPlatformPackage(deps) {
244
+ const binName = deps.platform === "win32" ? "claude.exe" : "claude";
245
+ const candidates = [`@anthropic-ai/claude-code-${deps.platform}-${deps.arch}`];
246
+ if (deps.platform === "linux") {
247
+ candidates.push(`@anthropic-ai/claude-code-${deps.platform}-${deps.arch}-musl`);
248
+ }
249
+ for (const pkg of candidates) {
250
+ try {
251
+ const pkgJson = deps.resolvePackage(`${pkg}/package.json`);
252
+ const candidate = join(dirname(pkgJson), binName);
253
+ if (deps.existsSync(candidate))
254
+ return candidate;
255
+ } catch {}
256
+ }
257
+ return null;
258
+ }
259
+ async function tryPathLookup(deps) {
260
+ const cmd = deps.platform === "win32" ? "where claude" : "which claude";
261
+ try {
262
+ const { stdout } = await deps.exec(cmd);
263
+ const candidates = stdout.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
264
+ for (const candidate of candidates) {
265
+ if (deps.platform === "win32" && candidate.startsWith("/"))
266
+ continue;
267
+ if (deps.existsSync(candidate))
268
+ return candidate;
269
+ }
270
+ } catch {}
271
+ return null;
272
+ }
273
+ function tryLegacySdkCliJs(deps) {
274
+ if (!deps.isBun)
275
+ return null;
276
+ try {
277
+ const sdkPath = deps.resolvePackage("@anthropic-ai/claude-agent-sdk");
278
+ const cliJs = join(dirname(sdkPath), "cli.js");
279
+ return deps.existsSync(cliJs) ? cliJs : null;
280
+ } catch {
281
+ return null;
282
+ }
283
+ }
284
+ async function resolveClaudeExecutableWithSource(deps = DEFAULT_DEPS) {
285
+ const env2 = tryEnvOverride(deps);
286
+ if (env2)
287
+ return { path: env2, source: "env" };
288
+ const bundled = tryBundledBinary(deps);
289
+ if (bundled)
290
+ return { path: bundled, source: "bundled" };
291
+ const platformPkg = tryPlatformPackage(deps);
292
+ if (platformPkg)
293
+ return { path: platformPkg, source: "platform-package" };
294
+ const pathLookup = await tryPathLookup(deps);
295
+ if (pathLookup)
296
+ return { path: pathLookup, source: "path-lookup" };
297
+ const legacy = tryLegacySdkCliJs(deps);
298
+ if (legacy)
299
+ return { path: legacy, source: "legacy-cli-js" };
300
+ return null;
301
+ }
302
+ function resolveClaudeExecutableSync(deps = DEFAULT_DEPS) {
303
+ const env2 = tryEnvOverride(deps);
304
+ if (env2)
305
+ return { path: env2, source: "env" };
306
+ const bundled = tryBundledBinary(deps);
307
+ if (bundled)
308
+ return { path: bundled, source: "bundled" };
309
+ const platformPkg = tryPlatformPackage(deps);
310
+ if (platformPkg)
311
+ return { path: platformPkg, source: "platform-package" };
312
+ return null;
313
+ }
314
+ function getResolvedClaudeExecutableInfo() {
315
+ return cachedClaudeInfo;
316
+ }
317
+ async function resolveClaudeExecutableAsync() {
318
+ if (cachedClaudeInfo)
319
+ return cachedClaudeInfo.path;
320
+ if (cachedClaudePathPromise)
321
+ return cachedClaudePathPromise;
322
+ cachedClaudePathPromise = (async () => {
323
+ const resolved = await resolveClaudeExecutableWithSource();
324
+ if (resolved) {
325
+ cachedClaudeInfo = resolved;
326
+ return resolved.path;
327
+ }
328
+ 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.");
329
+ })();
330
+ try {
331
+ return await cachedClaudePathPromise;
332
+ } finally {
333
+ cachedClaudePathPromise = null;
334
+ }
335
+ }
336
+ function isClosedControllerError(error) {
337
+ if (!(error instanceof Error))
338
+ return false;
339
+ return error.message.includes("Controller is already closed");
340
+ }
341
+
342
+ // src/proxy/profileCli.ts
343
+ var PROFILES_DIR = join2(homedir(), ".config", "meridian", "profiles");
344
+ var CONFIG_FILE = join2(homedir(), ".config", "meridian", "profiles.json");
20
345
  var OAUTH_AUTHORIZE_URL = "https://claude.com/cai/oauth/authorize";
21
346
  var OAUTH_TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
22
347
  var OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
@@ -33,18 +358,19 @@ function ensureProfilesDir() {
33
358
  mkdirSync(PROFILES_DIR, { recursive: true });
34
359
  }
35
360
  function getProfileDir(id) {
36
- return join(PROFILES_DIR, id);
361
+ return join2(PROFILES_DIR, id);
37
362
  }
38
363
  function buildAuthLoginEnv(configDir, _options = {}, baseEnv = process.env) {
39
- const env = { ...baseEnv };
364
+ const env2 = { ...baseEnv };
40
365
  if (configDir)
41
- env.CLAUDE_CONFIG_DIR = configDir;
42
- return env;
366
+ env2.CLAUDE_CONFIG_DIR = configDir;
367
+ return env2;
43
368
  }
44
369
  function base64Url(bytes) {
45
370
  return bytes.toString("base64url");
46
371
  }
47
- function createManualOAuthSession() {
372
+ function createManualOAuthSession(scopes) {
373
+ const scopeList = scopes ?? OAUTH_SCOPES;
48
374
  const codeVerifier = base64Url(randomBytes(32));
49
375
  const state = base64Url(randomBytes(32));
50
376
  const codeChallenge = createHash("sha256").update(codeVerifier).digest("base64url");
@@ -53,7 +379,7 @@ function createManualOAuthSession() {
53
379
  url.searchParams.set("client_id", OAUTH_CLIENT_ID);
54
380
  url.searchParams.set("response_type", "code");
55
381
  url.searchParams.set("redirect_uri", OAUTH_REDIRECT_URI);
56
- url.searchParams.set("scope", OAUTH_SCOPES.join(" "));
382
+ url.searchParams.set("scope", scopeList.join(" "));
57
383
  url.searchParams.set("code_challenge", codeChallenge);
58
384
  url.searchParams.set("code_challenge_method", "S256");
59
385
  url.searchParams.set("state", state);
@@ -78,7 +404,7 @@ function parseAuthorizationCodeInput(input) {
78
404
  return code ? { code, state } : null;
79
405
  }
80
406
  function loadProfileConfig() {
81
- if (!existsSync(CONFIG_FILE))
407
+ if (!existsSync2(CONFIG_FILE))
82
408
  return [];
83
409
  try {
84
410
  return JSON.parse(readFileSync(CONFIG_FILE, "utf-8"));
@@ -186,7 +512,7 @@ async function profileAdd(id, options = {}) {
186
512
  console.error(` Run: meridian profile list`);
187
513
  process.exit(1);
188
514
  }
189
- const defaultClaudeDir = join(homedir(), ".claude");
515
+ const defaultClaudeDir = join2(homedir(), ".claude");
190
516
  const alreadyImported = profiles.some((p) => p.claudeConfigDir === defaultClaudeDir);
191
517
  if (!alreadyImported) {
192
518
  const defaultAuth = getAuthStatus(defaultClaudeDir);
@@ -317,7 +643,7 @@ function dirsToRemoveOnProfileRemove(profile, profilesDir) {
317
643
  dirs.push(profile.claudeConfigDir);
318
644
  }
319
645
  if (profile.oauthToken || profile.type === "oauth-token") {
320
- const isolationDir = join(profilesDir, profile.id);
646
+ const isolationDir = join2(profilesDir, profile.id);
321
647
  if (!dirs.includes(isolationDir))
322
648
  dirs.push(isolationDir);
323
649
  }
@@ -339,7 +665,7 @@ function profileRemove(id) {
339
665
  profiles.splice(idx, 1);
340
666
  saveProfileConfig(profiles);
341
667
  for (const dir of dirsToRemove) {
342
- if (existsSync(dir))
668
+ if (existsSync2(dir))
343
669
  rmSync(dir, { recursive: true, force: true });
344
670
  }
345
671
  console.log(`\x1B[32m✓ Profile "${id}" removed.\x1B[0m`);
@@ -498,16 +824,5 @@ Examples:
498
824
  meridian profile switch work # Switch to work account
499
825
  meridian profile list # Show all profiles`);
500
826
  }
501
- export {
502
- profileSwitch,
503
- profileRemove,
504
- profileLogin,
505
- profileList,
506
- profileHelp,
507
- profileAddOauthToken,
508
- profileAdd,
509
- parseAuthorizationCodeInput,
510
- dirsToRemoveOnProfileRemove,
511
- createManualOAuthSession,
512
- buildAuthLoginEnv
513
- };
827
+
828
+ export { env, envBool, resolvePassthrough, envInt, init_env, CANONICAL_SONNET_MODEL, resolveSdkModelDefaults, explicitModelPin, mapModelToClaudeModel, recordExtendedContextUnavailable, stripExtendedContext, hasExtendedContext, getAuthCacheInfo, getClaudeAuthStatusAsync, getResolvedClaudeExecutableInfo, resolveClaudeExecutableAsync, isClosedControllerError, OAUTH_TOKEN_URL, OAUTH_CLIENT_ID, OAUTH_REDIRECT_URI, buildAuthLoginEnv, createManualOAuthSession, parseAuthorizationCodeInput, profileAdd, profileAddOauthToken, profileList, dirsToRemoveOnProfileRemove, profileRemove, profileSwitch, profileLogin, profileHelp };