@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/dist/cli.js CHANGED
@@ -1,13 +1,13 @@
1
1
  #!/usr/bin/env node
2
2
  import {
3
3
  startProxyServer
4
- } from "./cli-027as0fx.js";
4
+ } from "./cli-mqht6rs9.js";
5
5
  import"./cli-f0yqy2d2.js";
6
6
  import"./cli-sry5aqdj.js";
7
7
  import"./cli-xmweegb1.js";
8
8
  import {
9
9
  resolveClaudeExecutableAsync
10
- } from "./cli-vjeftz4z.js";
10
+ } from "./cli-jhm27q0x.js";
11
11
  import"./cli-340h1chz.js";
12
12
  import"./cli-je60fevk.js";
13
13
  import"./cli-aq5zz92m.js";
@@ -55,7 +55,7 @@ See https://github.com/rynfar/meridian for full documentation.`);
55
55
  process.exit(0);
56
56
  }
57
57
  if (args[0] === "profile") {
58
- const { profileAdd, profileAddOauthToken, profileList, profileRemove, profileSwitch, profileLogin, profileHelp } = await import("./profileCli-s1h4vh8w.js");
58
+ const { profileAdd, profileAddOauthToken, profileList, profileRemove, profileSwitch, profileLogin, profileHelp } = await import("./profileCli-d9tcp916.js");
59
59
  const subcommand = args[1];
60
60
  const profileId = args[2];
61
61
  const headless = args.includes("--headless");
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The MCP grep tool handler (registered in mcpTools.ts; lives here so it can
3
+ * be unit-tested directly). Uses execFile (no shell) so pattern/include/path
4
+ * can never be interpreted as shell syntax. From #543 by @sittitep.
5
+ */
6
+ export declare function runGrepTool(args: {
7
+ pattern: string;
8
+ path?: string;
9
+ include?: string;
10
+ }): Promise<{
11
+ content: {
12
+ type: "text";
13
+ text: string;
14
+ }[];
15
+ isError?: undefined;
16
+ } | {
17
+ content: {
18
+ type: "text";
19
+ text: string;
20
+ }[];
21
+ isError: boolean;
22
+ }>;
23
+ //# sourceMappingURL=grepTool.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"grepTool.d.ts","sourceRoot":"","sources":["../src/grepTool.ts"],"names":[],"mappings":"AAOA;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,OAAO,CAAC,EAAE,MAAM,CAAA;CAAE;;;;;;;;;;;;GAoB3F"}
@@ -1 +1 @@
1
- {"version":3,"file":"mcpTools.d.ts","sourceRoot":"","sources":["../src/mcpTools.ts"],"names":[],"mappings":"AAYA;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,4EA8KtC"}
1
+ {"version":3,"file":"mcpTools.d.ts","sourceRoot":"","sources":["../src/mcpTools.ts"],"names":[],"mappings":"AAaA;;;;;;;;;;;;GAYG;AACH,wBAAgB,uBAAuB,4EA6JtC"}
@@ -0,0 +1,35 @@
1
+ import {
2
+ OAUTH_CLIENT_ID,
3
+ OAUTH_REDIRECT_URI,
4
+ OAUTH_TOKEN_URL,
5
+ buildAuthLoginEnv,
6
+ createManualOAuthSession,
7
+ dirsToRemoveOnProfileRemove,
8
+ parseAuthorizationCodeInput,
9
+ profileAdd,
10
+ profileAddOauthToken,
11
+ profileHelp,
12
+ profileList,
13
+ profileLogin,
14
+ profileRemove,
15
+ profileSwitch
16
+ } from "./cli-jhm27q0x.js";
17
+ import"./cli-340h1chz.js";
18
+ import"./cli-aq5zz92m.js";
19
+ import"./cli-p9swy5t3.js";
20
+ export {
21
+ profileSwitch,
22
+ profileRemove,
23
+ profileLogin,
24
+ profileList,
25
+ profileHelp,
26
+ profileAddOauthToken,
27
+ profileAdd,
28
+ parseAuthorizationCodeInput,
29
+ dirsToRemoveOnProfileRemove,
30
+ createManualOAuthSession,
31
+ buildAuthLoginEnv,
32
+ OAUTH_TOKEN_URL,
33
+ OAUTH_REDIRECT_URI,
34
+ OAUTH_CLIENT_ID
35
+ };
@@ -0,0 +1,82 @@
1
+ import type { CredentialStore } from "./tokenRefresh";
2
+ export type FetchLike = (input: string | URL | Request, init?: RequestInit) => Promise<Response>;
3
+ export declare const DESIGN_SCOPES: string[];
4
+ export declare const DESIGN_UPSTREAM_ORIGIN = "https://api.anthropic.com";
5
+ export interface DesignTokenData {
6
+ accessToken: string;
7
+ refreshToken?: string;
8
+ expiresAt: number;
9
+ scopes?: string[];
10
+ }
11
+ export interface DesignTokenStore {
12
+ read(): Promise<DesignTokenData | null>;
13
+ write(data: DesignTokenData): Promise<void>;
14
+ }
15
+ export declare function defaultDesignTokenPath(): string;
16
+ export declare function createFileDesignTokenStore(path?: string): DesignTokenStore;
17
+ export declare function isDesignTokenFresh(data: DesignTokenData, now?: number): boolean;
18
+ /**
19
+ * Returns a usable design access token: the stored one if fresh, otherwise
20
+ * the result of a refresh_token grant (persisted back to the store). Null
21
+ * when there is no token or the refresh fails — callers fall back to
22
+ * profile credentials and the upstream tells the user to /design-login.
23
+ */
24
+ export declare function getDesignAccessToken(opts: {
25
+ store: DesignTokenStore;
26
+ fetchFn?: FetchLike;
27
+ now?: number;
28
+ }): Promise<string | null>;
29
+ /**
30
+ * Auth precedence for upstream Design API requests:
31
+ * design token → profile API key → profile OAuth token → Max credential
32
+ * store. The design token comes first because it is the only credential
33
+ * guaranteed to carry the design scopes.
34
+ */
35
+ export declare function resolveDesignAuthHeaders(opts: {
36
+ designToken: string | null;
37
+ profile: {
38
+ type: string;
39
+ env: Record<string, string | undefined>;
40
+ };
41
+ credentialStore?: CredentialStore;
42
+ ensureFresh?: (store: CredentialStore) => Promise<unknown>;
43
+ }): Promise<Record<string, string>>;
44
+ /**
45
+ * Headers forwarded upstream. accept-encoding is pinned to identity:
46
+ * Node's fetch auto-decompresses gzip but keeps the content-encoding
47
+ * header, so MCP SDK clients receiving the re-served body would try to
48
+ * decompress it a second time and fail to parse.
49
+ */
50
+ export declare function buildDesignForwardHeaders(getHeader: (name: string) => string | undefined, authHeaders: Record<string, string>): Record<string, string>;
51
+ /** Forward all upstream headers (including mcp-session-id) minus hop-by-hop. */
52
+ export declare function filterUpstreamResponseHeaders(headers: Iterable<[string, string]>): Record<string, string>;
53
+ export declare function isDesignAuthFailure(status: number): boolean;
54
+ export interface DesignLoginResult {
55
+ status: number;
56
+ body: unknown;
57
+ }
58
+ export interface DesignLogin {
59
+ /** Start a login session; returns the JSON body for GET /design-login. */
60
+ start(): {
61
+ authorizeUrl: string;
62
+ instructions: string;
63
+ };
64
+ /** Like start() but also exposes the state, for tests. */
65
+ startRaw(): {
66
+ authorizeUrl: string;
67
+ state: string;
68
+ };
69
+ /** Handle POST /design-login: exchange the pasted code for a token. */
70
+ exchange(body: unknown): Promise<DesignLoginResult>;
71
+ }
72
+ export declare function createDesignLogin(deps: {
73
+ store: DesignTokenStore;
74
+ createSession?: (scopes: string[]) => {
75
+ authorizeUrl: string;
76
+ codeVerifier: string;
77
+ state: string;
78
+ };
79
+ fetchFn?: FetchLike;
80
+ now?: () => number;
81
+ }): DesignLogin;
82
+ //# sourceMappingURL=design.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"design.d.ts","sourceRoot":"","sources":["../../src/proxy/design.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,48 @@
1
+ /**
2
+ * CLI commands for profile management.
3
+ *
4
+ * Browser-login profiles are stored under ~/.config/meridian/profiles/{id}/
5
+ * — each directory is a standalone CLAUDE_CONFIG_DIR with its own OAuth
6
+ * tokens. OAuth-token profiles (added via `--oauth-token`) live entirely in
7
+ * profiles.json — no per-profile config dir.
8
+ *
9
+ * This is a leaf module — no imports from server.ts or session/.
10
+ */
11
+ import type { ProfileConfig } from "./profiles";
12
+ export declare const OAUTH_TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
13
+ export declare const OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
14
+ export declare const OAUTH_REDIRECT_URI = "https://platform.claude.com/oauth/code/callback";
15
+ interface AuthLoginOptions {
16
+ headless?: boolean;
17
+ }
18
+ interface ManualOAuthSession {
19
+ authorizeUrl: string;
20
+ codeVerifier: string;
21
+ state: string;
22
+ }
23
+ interface ParsedAuthorizationCode {
24
+ code: string;
25
+ state?: string;
26
+ }
27
+ export declare function buildAuthLoginEnv(configDir: string | undefined, _options?: AuthLoginOptions, baseEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
28
+ export declare function createManualOAuthSession(scopes?: string[]): ManualOAuthSession;
29
+ export declare function parseAuthorizationCodeInput(input: string): ParsedAuthorizationCode | null;
30
+ export declare function profileAdd(id: string, options?: AuthLoginOptions): Promise<void>;
31
+ export declare function profileAddOauthToken(id: string, tokenArg: string | undefined): Promise<void>;
32
+ export declare function profileList(): void;
33
+ /**
34
+ * Pure: resolve which on-disk directories should be removed when this profile
35
+ * is deleted. Browser-login profiles drop their explicit `claudeConfigDir`
36
+ * (provided it lives under `profilesDir`); oauth-token profiles drop the
37
+ * pinned isolation dir at `profilesDir/<id>` (created by the SDK during use,
38
+ * not stored on the profile itself).
39
+ *
40
+ * Caller is responsible for the actual `rmSync` — this returns paths only.
41
+ */
42
+ export declare function dirsToRemoveOnProfileRemove(profile: ProfileConfig, profilesDir: string): string[];
43
+ export declare function profileRemove(id: string): void;
44
+ export declare function profileSwitch(id: string): Promise<void>;
45
+ export declare function profileLogin(id: string, options?: AuthLoginOptions): Promise<void>;
46
+ export declare function profileHelp(): void;
47
+ export {};
48
+ //# sourceMappingURL=profileCli.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profileCli.d.ts","sourceRoot":"","sources":["../../src/proxy/profileCli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAQH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAO/C,eAAO,MAAM,eAAe,+CAA+C,CAAA;AAC3E,eAAO,MAAM,eAAe,yCAAyC,CAAA;AACrE,eAAO,MAAM,kBAAkB,oDAAoD,CAAA;AAkBnF,UAAU,gBAAgB;IACxB,QAAQ,CAAC,EAAE,OAAO,CAAA;CACnB;AAED,UAAU,kBAAkB;IAC1B,YAAY,EAAE,MAAM,CAAA;IACpB,YAAY,EAAE,MAAM,CAAA;IACpB,KAAK,EAAE,MAAM,CAAA;CACd;AAED,UAAU,uBAAuB;IAC/B,IAAI,EAAE,MAAM,CAAA;IACZ,KAAK,CAAC,EAAE,MAAM,CAAA;CACf;AAUD,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,GAAG,SAAS,EAC7B,QAAQ,GAAE,gBAAqB,EAC/B,OAAO,GAAE,MAAM,CAAC,UAAwB,GACvC,MAAM,CAAC,UAAU,CAInB;AAMD,wBAAgB,wBAAwB,CAAC,MAAM,CAAC,EAAE,MAAM,EAAE,GAAG,kBAAkB,CAe9E;AAED,wBAAgB,2BAA2B,CAAC,KAAK,EAAE,MAAM,GAAG,uBAAuB,GAAG,IAAI,CAiBzF;AAiHD,wBAAsB,UAAU,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAwG1F;AAED,wBAAsB,oBAAoB,CAAC,EAAE,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CA8BlG;AAED,wBAAgB,WAAW,IAAI,IAAI,CAsBlC;AAED;;;;;;;;GAQG;AACH,wBAAgB,2BAA2B,CAAC,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM,EAAE,CAUjG;AAED,wBAAgB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,IAAI,CAyB9C;AAED,wBAAsB,aAAa,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAwB7D;AAED,wBAAsB,YAAY,CAAC,EAAE,EAAE,MAAM,EAAE,OAAO,GAAE,gBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAkD5F;AAoED,wBAAgB,WAAW,IAAI,IAAI,CAsBlC"}
@@ -1 +1 @@
1
- {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAGvD,YAAY,EACV,SAAS,EACT,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAA;AAKpB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAwCnG,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EAEpB,KAAK,aAAa,EAGnB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAA+B,iBAAiB,EAAE,mBAAmB,EAAsC,MAAM,iBAAiB,CAAA;AAGzI,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,CAAA;AAgR7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAkmHhF;AAWD,wBAAgB,gCAAgC,IAAI,IAAI,CAavD;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAmGhG"}
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/proxy/server.ts"],"names":[],"mappings":"AAgBA,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,SAAS,CAAA;AACtE,YAAY,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,CAAA;AAGvD,YAAY,EACV,SAAS,EACT,cAAc,EACd,eAAe,EACf,gBAAgB,EAChB,cAAc,EACd,cAAc,EACd,iBAAiB,EACjB,YAAY,EACZ,aAAa,EACb,WAAW,GACZ,MAAM,aAAa,CAAA;AAKpB,OAAO,EAAE,gBAAgB,EAAE,cAAc,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAA;AAkDnG,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,oBAAoB,EAEpB,KAAK,aAAa,EAGnB,MAAM,mBAAmB,CAAA;AAG1B,OAAO,EAA+B,iBAAiB,EAAE,mBAAmB,EAAsC,MAAM,iBAAiB,CAAA;AAGzI,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,oBAAoB,EAAE,CAAA;AAChE,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,CAAA;AACjD,YAAY,EAAE,aAAa,EAAE,CAAA;AAgR7B,wBAAgB,iBAAiB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,WAAW,CAwrHhF;AAWD,wBAAgB,gCAAgC,IAAI,IAAI,CAavD;AAED,wBAAsB,gBAAgB,CAAC,MAAM,GAAE,OAAO,CAAC,WAAW,CAAM,GAAG,OAAO,CAAC,aAAa,CAAC,CAmGhG"}
package/dist/server.js CHANGED
@@ -11,11 +11,11 @@ import {
11
11
  runObserveHook,
12
12
  runTransformHook,
13
13
  startProxyServer
14
- } from "./cli-027as0fx.js";
14
+ } from "./cli-mqht6rs9.js";
15
15
  import"./cli-f0yqy2d2.js";
16
16
  import"./cli-sry5aqdj.js";
17
17
  import"./cli-xmweegb1.js";
18
- import"./cli-vjeftz4z.js";
18
+ import"./cli-jhm27q0x.js";
19
19
  import"./cli-340h1chz.js";
20
20
  import"./cli-je60fevk.js";
21
21
  import"./cli-aq5zz92m.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rynfar/meridian",
3
- "version": "1.53.0",
3
+ "version": "1.54.0",
4
4
  "description": "Local Anthropic API powered by your Claude Max subscription. One subscription, every agent.",
5
5
  "type": "module",
6
6
  "main": "./dist/server.js",
@@ -1,329 +0,0 @@
1
- import {
2
- __esm
3
- } from "./cli-p9swy5t3.js";
4
-
5
- // src/env.ts
6
- function env(suffix) {
7
- return process.env[`MERIDIAN_${suffix}`] ?? process.env[`CLAUDE_PROXY_${suffix}`];
8
- }
9
- function envBool(suffix) {
10
- const val = env(suffix);
11
- return val === "1" || val === "true" || val === "yes";
12
- }
13
- function resolvePassthrough(defaultValue) {
14
- const val = env("PASSTHROUGH");
15
- if (val === "1" || val === "true" || val === "yes")
16
- return true;
17
- if (val === "0" || val === "false" || val === "no")
18
- return false;
19
- return defaultValue;
20
- }
21
- function envInt(suffix, defaultValue) {
22
- const val = env(suffix);
23
- if (!val)
24
- return defaultValue;
25
- const parsed = parseInt(val, 10);
26
- return Number.isFinite(parsed) ? parsed : defaultValue;
27
- }
28
- var init_env = () => {};
29
-
30
- // src/proxy/models.ts
31
- init_env();
32
- import { exec as execCallback, execFile as execFileCallback } from "child_process";
33
- import { existsSync, statSync } from "fs";
34
- import { fileURLToPath } from "url";
35
- import { join, dirname } from "path";
36
- import { promisify } from "util";
37
- var exec = promisify(execCallback);
38
- var execFile = promisify(execFileCallback);
39
- var STUB_SIZE_THRESHOLD = 4096;
40
- var CANONICAL_FABLE_MODEL = "claude-fable-5";
41
- var CANONICAL_OPUS_MODEL = "claude-opus-4-8";
42
- var CANONICAL_SONNET_MODEL = "claude-sonnet-5";
43
- var CANONICAL_HAIKU_MODEL = "claude-haiku-4-5";
44
- function resolveSdkModelDefaults(env2 = process.env) {
45
- return {
46
- ANTHROPIC_DEFAULT_FABLE_MODEL: env2.MERIDIAN_DEFAULT_FABLE_MODEL ?? CANONICAL_FABLE_MODEL,
47
- ANTHROPIC_DEFAULT_OPUS_MODEL: env2.MERIDIAN_DEFAULT_OPUS_MODEL ?? CANONICAL_OPUS_MODEL,
48
- ANTHROPIC_DEFAULT_SONNET_MODEL: env2.MERIDIAN_DEFAULT_SONNET_MODEL ?? CANONICAL_SONNET_MODEL,
49
- ANTHROPIC_DEFAULT_HAIKU_MODEL: env2.MERIDIAN_DEFAULT_HAIKU_MODEL ?? CANONICAL_HAIKU_MODEL
50
- };
51
- }
52
- function explicitModelPin(requestedModel) {
53
- const base = requestedModel.trim().toLowerCase().replace(/\[1m\]$/, "");
54
- const match = /^claude-(sonnet|opus|haiku|fable|mythos)-\d[\w.-]*$/.exec(base);
55
- if (!match)
56
- return;
57
- const tier = match[1] === "mythos" ? "FABLE" : match[1].toUpperCase();
58
- return { [`ANTHROPIC_DEFAULT_${tier}_MODEL`]: base };
59
- }
60
- var AUTH_STATUS_CACHE_TTL_MS = 60000;
61
- var AUTH_STATUS_FAILURE_TTL_MS = 5000;
62
- var cachedAuthStatus = null;
63
- var lastKnownGoodAuthStatus = null;
64
- var cachedAuthStatusAt = 0;
65
- var cachedAuthStatusIsFailure = false;
66
- var cachedAuthStatusPromise = null;
67
- function supports1mContext(model) {
68
- const override = env("1M_CONTEXT_SUPPORT");
69
- if (override === "0" || override === "false" || override === "no")
70
- return false;
71
- if (model.includes("4-5") || model.includes("4.5"))
72
- return false;
73
- return true;
74
- }
75
- function mapModelToClaudeModel(model, subscriptionType, agentMode) {
76
- if (model.includes("haiku"))
77
- return "haiku";
78
- const use1m = supports1mContext(model);
79
- const isSubagent = agentMode === "subagent";
80
- if (model.includes("fable") || model.includes("mythos")) {
81
- if (use1m && !isSubagent && !isExtendedContextKnownUnavailable())
82
- return "fable[1m]";
83
- return "fable";
84
- }
85
- if (model.includes("opus")) {
86
- if (use1m && !isSubagent && !isExtendedContextKnownUnavailable())
87
- return "opus[1m]";
88
- return "opus";
89
- }
90
- const sonnetOverride = process.env.MERIDIAN_SONNET_MODEL ?? process.env.CLAUDE_PROXY_SONNET_MODEL;
91
- if (sonnetOverride === "sonnet[1m]") {
92
- if (!use1m || isSubagent || isExtendedContextKnownUnavailable())
93
- return "sonnet";
94
- return "sonnet[1m]";
95
- }
96
- return "sonnet";
97
- }
98
- var EXTRA_USAGE_RETRY_MS = 60 * 60 * 1000;
99
- var extraUsageUnavailableAt = 0;
100
- function recordExtendedContextUnavailable() {
101
- extraUsageUnavailableAt = Date.now();
102
- }
103
- function isExtendedContextKnownUnavailable() {
104
- return extraUsageUnavailableAt > 0 && Date.now() - extraUsageUnavailableAt < EXTRA_USAGE_RETRY_MS;
105
- }
106
- function stripExtendedContext(model) {
107
- if (model === "opus[1m]")
108
- return "opus";
109
- if (model === "sonnet[1m]")
110
- return "sonnet";
111
- if (model === "fable[1m]")
112
- return "fable";
113
- return model;
114
- }
115
- function hasExtendedContext(model) {
116
- return model.endsWith("[1m]");
117
- }
118
- var profileAuthCaches = new Map;
119
- function getAuthCacheInfo(profileId) {
120
- if (!profileId) {
121
- return { lastCheckedAt: cachedAuthStatusAt, lastSuccessAt: cachedAuthStatusIsFailure ? 0 : cachedAuthStatusAt, isFailure: cachedAuthStatusIsFailure };
122
- }
123
- const cache = profileAuthCaches.get(profileId);
124
- if (!cache)
125
- return { lastCheckedAt: 0, lastSuccessAt: 0, isFailure: false };
126
- return { lastCheckedAt: cache.at, lastSuccessAt: cache.lastSuccessAt, isFailure: cache.isFailure };
127
- }
128
- function getAuthCache(key) {
129
- let cache = profileAuthCaches.get(key);
130
- if (!cache) {
131
- cache = { status: null, lastKnownGood: null, at: 0, isFailure: false, promise: null, lastSuccessAt: 0 };
132
- profileAuthCaches.set(key, cache);
133
- }
134
- return cache;
135
- }
136
- async function getClaudeAuthStatusAsync(profileId, envOverrides) {
137
- const isDefault = !profileId;
138
- const cache = isDefault ? null : getAuthCache(profileId);
139
- const c_status = cache ? cache.status : cachedAuthStatus;
140
- const c_lastKnownGood = cache ? cache.lastKnownGood : lastKnownGoodAuthStatus;
141
- const c_at = cache ? cache.at : cachedAuthStatusAt;
142
- const c_isFailure = cache ? cache.isFailure : cachedAuthStatusIsFailure;
143
- let c_promise = cache ? cache.promise : cachedAuthStatusPromise;
144
- const ttl = c_isFailure ? AUTH_STATUS_FAILURE_TTL_MS : AUTH_STATUS_CACHE_TTL_MS;
145
- if (c_at > 0 && Date.now() - c_at < ttl) {
146
- return c_status ?? c_lastKnownGood;
147
- }
148
- if (c_promise)
149
- return c_promise;
150
- c_promise = (async () => {
151
- try {
152
- const claudePath = await resolveClaudeExecutableAsync();
153
- const { stdout } = await execFile(claudePath, ["auth", "status"], {
154
- timeout: 5000,
155
- ...envOverrides ? { env: { ...process.env, ...envOverrides } } : {}
156
- });
157
- const parsed = JSON.parse(stdout);
158
- if (cache) {
159
- cache.status = parsed;
160
- cache.lastKnownGood = parsed;
161
- cache.at = Date.now();
162
- cache.isFailure = false;
163
- cache.lastSuccessAt = Date.now();
164
- } else {
165
- cachedAuthStatus = parsed;
166
- lastKnownGoodAuthStatus = parsed;
167
- cachedAuthStatusAt = Date.now();
168
- cachedAuthStatusIsFailure = false;
169
- }
170
- return parsed;
171
- } catch {
172
- if (cache) {
173
- cache.isFailure = true;
174
- cache.at = Date.now();
175
- cache.status = null;
176
- return cache.lastKnownGood;
177
- } else {
178
- cachedAuthStatusIsFailure = true;
179
- cachedAuthStatusAt = Date.now();
180
- cachedAuthStatus = null;
181
- return lastKnownGoodAuthStatus;
182
- }
183
- }
184
- })();
185
- if (cache)
186
- cache.promise = c_promise;
187
- else
188
- cachedAuthStatusPromise = c_promise;
189
- try {
190
- return await c_promise;
191
- } finally {
192
- if (cache)
193
- cache.promise = null;
194
- else
195
- cachedAuthStatusPromise = null;
196
- }
197
- }
198
- var cachedClaudeInfo = null;
199
- var cachedClaudePathPromise = null;
200
- var DEFAULT_DEPS = {
201
- existsSync,
202
- statSync: (p) => statSync(p),
203
- exec,
204
- resolvePackage: (specifier) => fileURLToPath(import.meta.resolve(specifier)),
205
- envGet: (name) => process.env[name],
206
- platform: process.platform,
207
- arch: process.arch,
208
- isBun: typeof process.versions.bun !== "undefined"
209
- };
210
- function tryEnvOverride(deps) {
211
- const explicit = deps.envGet("MERIDIAN_CLAUDE_PATH");
212
- if (!explicit)
213
- return null;
214
- return deps.existsSync(explicit) ? explicit : null;
215
- }
216
- function tryBundledBinary(deps) {
217
- try {
218
- const pkgPath = deps.resolvePackage("@anthropic-ai/claude-code/package.json");
219
- const bundled = join(dirname(pkgPath), "bin", "claude.exe");
220
- if (!deps.existsSync(bundled))
221
- return null;
222
- const size = deps.statSync(bundled).size;
223
- if (size <= STUB_SIZE_THRESHOLD)
224
- return null;
225
- return bundled;
226
- } catch {
227
- return null;
228
- }
229
- }
230
- function tryPlatformPackage(deps) {
231
- const binName = deps.platform === "win32" ? "claude.exe" : "claude";
232
- const candidates = [`@anthropic-ai/claude-code-${deps.platform}-${deps.arch}`];
233
- if (deps.platform === "linux") {
234
- candidates.push(`@anthropic-ai/claude-code-${deps.platform}-${deps.arch}-musl`);
235
- }
236
- for (const pkg of candidates) {
237
- try {
238
- const pkgJson = deps.resolvePackage(`${pkg}/package.json`);
239
- const candidate = join(dirname(pkgJson), binName);
240
- if (deps.existsSync(candidate))
241
- return candidate;
242
- } catch {}
243
- }
244
- return null;
245
- }
246
- async function tryPathLookup(deps) {
247
- const cmd = deps.platform === "win32" ? "where claude" : "which claude";
248
- try {
249
- const { stdout } = await deps.exec(cmd);
250
- const candidates = stdout.split(/\r?\n/).map((s) => s.trim()).filter(Boolean);
251
- for (const candidate of candidates) {
252
- if (deps.platform === "win32" && candidate.startsWith("/"))
253
- continue;
254
- if (deps.existsSync(candidate))
255
- return candidate;
256
- }
257
- } catch {}
258
- return null;
259
- }
260
- function tryLegacySdkCliJs(deps) {
261
- if (!deps.isBun)
262
- return null;
263
- try {
264
- const sdkPath = deps.resolvePackage("@anthropic-ai/claude-agent-sdk");
265
- const cliJs = join(dirname(sdkPath), "cli.js");
266
- return deps.existsSync(cliJs) ? cliJs : null;
267
- } catch {
268
- return null;
269
- }
270
- }
271
- async function resolveClaudeExecutableWithSource(deps = DEFAULT_DEPS) {
272
- const env2 = tryEnvOverride(deps);
273
- if (env2)
274
- return { path: env2, source: "env" };
275
- const bundled = tryBundledBinary(deps);
276
- if (bundled)
277
- return { path: bundled, source: "bundled" };
278
- const platformPkg = tryPlatformPackage(deps);
279
- if (platformPkg)
280
- return { path: platformPkg, source: "platform-package" };
281
- const pathLookup = await tryPathLookup(deps);
282
- if (pathLookup)
283
- return { path: pathLookup, source: "path-lookup" };
284
- const legacy = tryLegacySdkCliJs(deps);
285
- if (legacy)
286
- return { path: legacy, source: "legacy-cli-js" };
287
- return null;
288
- }
289
- function resolveClaudeExecutableSync(deps = DEFAULT_DEPS) {
290
- const env2 = tryEnvOverride(deps);
291
- if (env2)
292
- return { path: env2, source: "env" };
293
- const bundled = tryBundledBinary(deps);
294
- if (bundled)
295
- return { path: bundled, source: "bundled" };
296
- const platformPkg = tryPlatformPackage(deps);
297
- if (platformPkg)
298
- return { path: platformPkg, source: "platform-package" };
299
- return null;
300
- }
301
- function getResolvedClaudeExecutableInfo() {
302
- return cachedClaudeInfo;
303
- }
304
- async function resolveClaudeExecutableAsync() {
305
- if (cachedClaudeInfo)
306
- return cachedClaudeInfo.path;
307
- if (cachedClaudePathPromise)
308
- return cachedClaudePathPromise;
309
- cachedClaudePathPromise = (async () => {
310
- const resolved = await resolveClaudeExecutableWithSource();
311
- if (resolved) {
312
- cachedClaudeInfo = resolved;
313
- return resolved.path;
314
- }
315
- 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.");
316
- })();
317
- try {
318
- return await cachedClaudePathPromise;
319
- } finally {
320
- cachedClaudePathPromise = null;
321
- }
322
- }
323
- function isClosedControllerError(error) {
324
- if (!(error instanceof Error))
325
- return false;
326
- return error.message.includes("Controller is already closed");
327
- }
328
-
329
- export { env, envBool, resolvePassthrough, envInt, init_env, CANONICAL_SONNET_MODEL, resolveSdkModelDefaults, explicitModelPin, mapModelToClaudeModel, recordExtendedContextUnavailable, stripExtendedContext, hasExtendedContext, getAuthCacheInfo, getClaudeAuthStatusAsync, resolveClaudeExecutableSync, getResolvedClaudeExecutableInfo, resolveClaudeExecutableAsync, isClosedControllerError };