@rynfar/meridian 1.72.0 → 1.74.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 +119 -107
- package/assets/banner.svg +18 -43
- package/assets/how-it-works.svg +40 -86
- package/assets/providers/README.md +10 -0
- package/assets/providers/antigravity.png +0 -0
- package/assets/providers/claude.png +0 -0
- package/dist/antigravity-clients/opencode.js +173 -0
- package/dist/antigravity-clients/pi.js +21 -0
- package/dist/antigravitySetup-35pd5xqn.js +191 -0
- package/dist/cli-1jstkdj9.js +30 -0
- package/dist/{cli-9e5cxp89.js → cli-2h3w5n6g.js} +163 -65
- package/dist/cli-3zwfvexc.js +56 -0
- package/dist/{cli-hxxy0m1z.js → cli-82e2m44k.js} +2 -1
- package/dist/cli-8sw5wr9j.js +136 -0
- package/dist/{cli-khhjyk04.js → cli-chsp880k.js} +214 -21
- package/dist/cli-dh0a1bw4.js +619 -0
- package/dist/cli-eehk3052.js +57 -0
- package/dist/{cli-ab7zkp1a.js → cli-fveyj34s.js} +32261 -18952
- package/dist/cli-grfp0s1j.js +330 -0
- package/dist/cli-qpfky8wy.js +133 -0
- package/dist/{cli-hj61zpt7.js → cli-wbsmhxcx.js} +26 -2
- package/dist/cli.js +111 -38
- package/dist/cliDashboard-c0dvkj4y.js +325 -0
- package/dist/configDir.d.ts +30 -0
- package/dist/configDir.d.ts.map +1 -0
- package/dist/organizationName-90f0atkn.js +29 -0
- package/dist/{pluginPage-f5gdmbxc.js → pluginPage-pp72d2j8.js} +1 -1
- package/dist/{profileCli-1eecbmgk.js → profileCli-1bfgc05h.js} +13 -3
- package/dist/{profilePage-mamej7kp.js → profilePage-vs319rvf.js} +252 -60
- package/dist/profileRename-4a4km6g8.js +22 -0
- package/dist/{profiles-wch9h234.js → profiles-0mp32ek9.js} +16 -3
- package/dist/proxy/adapterInstances.d.ts +1 -1
- package/dist/proxy/adapterInstances.d.ts.map +1 -1
- package/dist/proxy/adapters/claudecode.d.ts.map +1 -1
- package/dist/proxy/adapters/droid.d.ts.map +1 -1
- package/dist/proxy/auth.d.ts +2 -0
- package/dist/proxy/auth.d.ts.map +1 -1
- package/dist/proxy/authDiscovery.d.ts +52 -0
- package/dist/proxy/authDiscovery.d.ts.map +1 -0
- package/dist/proxy/backends/antigravity.d.ts +8 -0
- package/dist/proxy/backends/antigravity.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityAttachments.d.ts +16 -0
- package/dist/proxy/backends/antigravityAttachments.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityGrammar.d.ts +12 -0
- package/dist/proxy/backends/antigravityGrammar.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityJobs.d.ts +19 -0
- package/dist/proxy/backends/antigravityJobs.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityMedia.d.ts +9 -0
- package/dist/proxy/backends/antigravityMedia.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityNative.d.ts +8 -0
- package/dist/proxy/backends/antigravityNative.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityOpenai.d.ts +9 -0
- package/dist/proxy/backends/antigravityOpenai.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityOpenaiMedia.d.ts +9 -0
- package/dist/proxy/backends/antigravityOpenaiMedia.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityPlugins.d.ts +41 -0
- package/dist/proxy/backends/antigravityPlugins.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityProbe.d.ts +16 -0
- package/dist/proxy/backends/antigravityProbe.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityProcess.d.ts +4 -0
- package/dist/proxy/backends/antigravityProcess.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityProtocol.d.ts +582 -0
- package/dist/proxy/backends/antigravityProtocol.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityReplay.d.ts +41 -0
- package/dist/proxy/backends/antigravityReplay.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityResponses.d.ts +35 -0
- package/dist/proxy/backends/antigravityResponses.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityRuntime.d.ts +189 -0
- package/dist/proxy/backends/antigravityRuntime.d.ts.map +1 -0
- package/dist/proxy/backends/antigravitySchema.d.ts +10 -0
- package/dist/proxy/backends/antigravitySchema.d.ts.map +1 -0
- package/dist/proxy/backends/antigravitySessions.d.ts +28 -0
- package/dist/proxy/backends/antigravitySessions.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityState.d.ts +22 -0
- package/dist/proxy/backends/antigravityState.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityStops.d.ts +10 -0
- package/dist/proxy/backends/antigravityStops.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityTokens.d.ts +14 -0
- package/dist/proxy/backends/antigravityTokens.d.ts.map +1 -0
- package/dist/proxy/backends/antigravityUrl.d.ts +7 -0
- package/dist/proxy/backends/antigravityUrl.d.ts.map +1 -0
- package/dist/proxy/backends/providerStatus.d.ts +15 -0
- package/dist/proxy/backends/providerStatus.d.ts.map +1 -0
- package/dist/proxy/credentialsMode.d.ts +77 -0
- package/dist/proxy/credentialsMode.d.ts.map +1 -0
- package/dist/proxy/design.d.ts.map +1 -1
- package/dist/proxy/followActive.d.ts +262 -0
- package/dist/proxy/followActive.d.ts.map +1 -0
- package/dist/proxy/limitDetection.d.ts +110 -0
- package/dist/proxy/limitDetection.d.ts.map +1 -0
- package/dist/proxy/models.d.ts.map +1 -1
- package/dist/proxy/oauthPlan.d.ts +63 -0
- package/dist/proxy/oauthPlan.d.ts.map +1 -0
- package/dist/proxy/oauthUsage.d.ts +65 -2
- package/dist/proxy/oauthUsage.d.ts.map +1 -1
- package/dist/proxy/openai.d.ts +6 -2
- package/dist/proxy/openai.d.ts.map +1 -1
- package/dist/proxy/organizationName.d.ts +71 -0
- package/dist/proxy/organizationName.d.ts.map +1 -0
- package/dist/proxy/passthroughEarlyStop.d.ts +10 -0
- package/dist/proxy/passthroughEarlyStop.d.ts.map +1 -1
- package/dist/proxy/planAllowance.d.ts +75 -0
- package/dist/proxy/planAllowance.d.ts.map +1 -0
- package/dist/proxy/probes.d.ts +85 -0
- package/dist/proxy/probes.d.ts.map +1 -0
- package/dist/proxy/profileCli.d.ts +53 -1
- package/dist/proxy/profileCli.d.ts.map +1 -1
- package/dist/proxy/profileHealth.d.ts +127 -0
- package/dist/proxy/profileHealth.d.ts.map +1 -0
- package/dist/proxy/profileRename.d.ts +83 -0
- package/dist/proxy/profileRename.d.ts.map +1 -0
- package/dist/proxy/profiles.d.ts +72 -6
- package/dist/proxy/profiles.d.ts.map +1 -1
- package/dist/proxy/query.d.ts +7 -0
- package/dist/proxy/query.d.ts.map +1 -1
- package/dist/proxy/routing.d.ts +59 -1
- package/dist/proxy/routing.d.ts.map +1 -1
- package/dist/proxy/sdkFeatures.d.ts +1 -1
- package/dist/proxy/sdkFeatures.d.ts.map +1 -1
- package/dist/proxy/server.d.ts.map +1 -1
- package/dist/proxy/session/fingerprint.d.ts +5 -0
- package/dist/proxy/session/fingerprint.d.ts.map +1 -1
- package/dist/proxy/session/lineage.d.ts.map +1 -1
- package/dist/proxy/setup.d.ts.map +1 -1
- package/dist/proxy/supervision.d.ts +41 -0
- package/dist/proxy/supervision.d.ts.map +1 -0
- package/dist/proxy/tokenRefresh.d.ts +38 -4
- package/dist/proxy/tokenRefresh.d.ts.map +1 -1
- package/dist/proxy/types.d.ts +32 -0
- package/dist/proxy/types.d.ts.map +1 -1
- package/dist/server.js +11 -7
- package/dist/settings.d.ts +83 -0
- package/dist/settings.d.ts.map +1 -0
- package/dist/{setup-ndmjpy23.js → setup-7fr49z92.js} +1 -1
- package/dist/statusProbe-9x9q261e.js +151 -0
- package/dist/telemetry/dashboard.d.ts.map +1 -1
- package/dist/telemetry/index.d.ts +20 -2
- package/dist/telemetry/index.d.ts.map +1 -1
- package/dist/telemetry/landing.d.ts +1 -1
- package/dist/telemetry/landing.d.ts.map +1 -1
- package/dist/telemetry/logStore.d.ts +11 -0
- package/dist/telemetry/logStore.d.ts.map +1 -1
- package/dist/telemetry/pricingStore.d.ts +2 -2
- package/dist/telemetry/pricingStore.d.ts.map +1 -1
- package/dist/telemetry/profileBar.d.ts +3 -3
- package/dist/telemetry/profileBar.d.ts.map +1 -1
- package/dist/telemetry/profileFacts.d.ts +17 -0
- package/dist/telemetry/profileFacts.d.ts.map +1 -0
- package/dist/telemetry/profileOrder.d.ts +68 -0
- package/dist/telemetry/profileOrder.d.ts.map +1 -0
- package/dist/telemetry/profilePage.d.ts.map +1 -1
- package/dist/telemetry/profileSort.d.ts +35 -0
- package/dist/telemetry/profileSort.d.ts.map +1 -0
- package/dist/telemetry/profileSpent.d.ts +68 -0
- package/dist/telemetry/profileSpent.d.ts.map +1 -0
- package/dist/telemetry/providerPage.d.ts +2 -0
- package/dist/telemetry/providerPage.d.ts.map +1 -0
- package/dist/telemetry/providerSetup.d.ts +5 -0
- package/dist/telemetry/providerSetup.d.ts.map +1 -0
- package/dist/telemetry/providerView.d.ts +45 -0
- package/dist/telemetry/providerView.d.ts.map +1 -0
- package/dist/telemetry/routeChain.d.ts +32 -0
- package/dist/telemetry/routeChain.d.ts.map +1 -0
- package/dist/telemetry/routes.d.ts.map +1 -1
- package/dist/telemetry/settingsPage.d.ts +1 -1
- package/dist/telemetry/settingsPage.d.ts.map +1 -1
- package/dist/telemetry/sqlite.d.ts.map +1 -1
- package/dist/telemetry/store.d.ts +6 -1
- package/dist/telemetry/store.d.ts.map +1 -1
- package/dist/telemetry/types.d.ts +132 -2
- package/dist/telemetry/types.d.ts.map +1 -1
- package/dist/{tokenRefresh-kzz08kea.js → tokenRefresh-eg9h83wd.js} +6 -1
- package/package.json +11 -4
- package/dist/cli-5jxyma6z.js +0 -277
- package/dist/cli-vj9cv18n.js +0 -38
- package/dist/proxy/settings.d.ts +0 -30
- package/dist/proxy/settings.d.ts.map +0 -1
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The organization an account belongs to, as Anthropic names it.
|
|
3
|
+
*
|
|
4
|
+
* `GET /api/oauth/profile` answers `organization.name` — the human label for
|
|
5
|
+
* the account behind a profile. A fleet whose profiles are called `work2` and
|
|
6
|
+
* `corp3` is told apart by that label and by nothing else on the card.
|
|
7
|
+
*
|
|
8
|
+
* WHERE IT IS KEPT. `.credentials.json` already holds `subscriptionType` and
|
|
9
|
+
* `rateLimitTier`, so it looks like the natural home — but those are Claude
|
|
10
|
+
* Code's OWN keys. Meridian writes that file to be indistinguishable from one
|
|
11
|
+
* `claude login` wrote, and a Meridian-invented key breaks that deliberately;
|
|
12
|
+
* worse, Claude Code rewrites the file on its next refresh and would drop the
|
|
13
|
+
* key, so it would not even survive. This is Meridian's own file, beside
|
|
14
|
+
* settings.json, and neither objection applies to it.
|
|
15
|
+
*
|
|
16
|
+
* WHY IT IS CACHED. The render path must not make an authenticated round trip
|
|
17
|
+
* per profile: two pages poll `/profiles/list` every 10s and a fleet is a dozen
|
|
18
|
+
* accounts, which is a dozen requests to Anthropic every ten seconds for a
|
|
19
|
+
* string that changes approximately never. So reads are synchronous and
|
|
20
|
+
* cache-only, and a stale entry is refreshed in the background — the response
|
|
21
|
+
* never waits on the network.
|
|
22
|
+
*
|
|
23
|
+
* Leaf module — no imports from server.ts or session/.
|
|
24
|
+
*/
|
|
25
|
+
import { type CredentialStore } from "./tokenRefresh";
|
|
26
|
+
/** How old an entry may get before a background refresh is worth making. */
|
|
27
|
+
export declare const ORGANIZATION_REFRESH_AFTER_MS: number;
|
|
28
|
+
/** Floor between two lookups for one profile, successful or not, so an
|
|
29
|
+
* unreachable Anthropic cannot be retried once per 10s poll forever. */
|
|
30
|
+
export declare const ORGANIZATION_RETRY_AFTER_MS: number;
|
|
31
|
+
export interface OrganizationRecord {
|
|
32
|
+
name: string;
|
|
33
|
+
fetchedAt: number;
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Read a record map out of whatever the file actually holds. Hand-editable and
|
|
37
|
+
* written by other versions, so an entry that is not a usable name is dropped
|
|
38
|
+
* rather than served.
|
|
39
|
+
*/
|
|
40
|
+
export declare function readOrganizations(raw: unknown): Record<string, OrganizationRecord>;
|
|
41
|
+
/**
|
|
42
|
+
* Pull the name out of an `/api/oauth/profile` body.
|
|
43
|
+
*
|
|
44
|
+
* Nullable in principle even though every account measured has one, so an
|
|
45
|
+
* absent name yields null and the caller renders nothing rather than "unknown".
|
|
46
|
+
*/
|
|
47
|
+
export declare function extractOrganizationName(body: unknown): string | null;
|
|
48
|
+
export declare function organizationNeedsRefresh(record: OrganizationRecord | undefined, now: number, refreshAfterMs?: number): boolean;
|
|
49
|
+
/** Every organization on record, keyed by profile id. */
|
|
50
|
+
export declare function organizationNames(): Record<string, OrganizationRecord>;
|
|
51
|
+
export declare function rememberOrganizationName(profileId: string, name: string): void;
|
|
52
|
+
type FetchLike = (input: string, init?: RequestInit) => Promise<Response>;
|
|
53
|
+
/**
|
|
54
|
+
* Best-effort lookup for one account. Never throws and never fails its caller:
|
|
55
|
+
* a profile whose organization is unknown is strictly better than a page that
|
|
56
|
+
* will not render.
|
|
57
|
+
*/
|
|
58
|
+
export declare function fetchOrganizationName(store: CredentialStore, fetchImpl?: FetchLike): Promise<string | null>;
|
|
59
|
+
export declare function enableOrganizationLookup(): void;
|
|
60
|
+
export interface RefreshOrganizationOpts {
|
|
61
|
+
claudeConfigDir?: string;
|
|
62
|
+
store?: CredentialStore;
|
|
63
|
+
fetchImpl?: FetchLike;
|
|
64
|
+
retryAfterMs?: number;
|
|
65
|
+
}
|
|
66
|
+
/** Learn one profile's organization in the background. Returns immediately. */
|
|
67
|
+
export declare function refreshOrganizationNameSoon(profileId: string, opts?: RefreshOrganizationOpts): void;
|
|
68
|
+
/** Reset module state — for testing only. */
|
|
69
|
+
export declare function resetOrganizationLookupForTesting(): void;
|
|
70
|
+
export {};
|
|
71
|
+
//# sourceMappingURL=organizationName.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"organizationName.d.ts","sourceRoot":"","sources":["../../src/proxy/organizationName.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAMH,OAAO,EAAiC,KAAK,eAAe,EAAE,MAAM,gBAAgB,CAAA;AAIpF,4EAA4E;AAC5E,eAAO,MAAM,6BAA6B,QAAsB,CAAA;AAEhE;yEACyE;AACzE,eAAO,MAAM,2BAA2B,QAAgB,CAAA;AAcxD,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAA;IACZ,SAAS,EAAE,MAAM,CAAA;CAClB;AAID;;;;GAIG;AACH,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAalF;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CASpE;AAED,wBAAgB,wBAAwB,CACtC,MAAM,EAAE,kBAAkB,GAAG,SAAS,EACtC,GAAG,EAAE,MAAM,EACX,cAAc,GAAE,MAAsC,GACrD,OAAO,CAGT;AAID,yDAAyD;AACzD,wBAAgB,iBAAiB,IAAI,MAAM,CAAC,MAAM,EAAE,kBAAkB,CAAC,CAQtE;AAED,wBAAgB,wBAAwB,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,IAAI,CAS9E;AAID,KAAK,SAAS,GAAG,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,WAAW,KAAK,OAAO,CAAC,QAAQ,CAAC,CAAA;AAEzE;;;;GAIG;AACH,wBAAsB,qBAAqB,CACzC,KAAK,EAAE,eAAe,EACtB,SAAS,GAAE,SAA4B,GACtC,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAsBxB;AAWD,wBAAgB,wBAAwB,IAAI,IAAI,CAE/C;AAKD,MAAM,WAAW,uBAAuB;IACtC,eAAe,CAAC,EAAE,MAAM,CAAA;IACxB,KAAK,CAAC,EAAE,eAAe,CAAA;IACvB,SAAS,CAAC,EAAE,SAAS,CAAA;IACrB,YAAY,CAAC,EAAE,MAAM,CAAA;CACtB;AAED,+EAA+E;AAC/E,wBAAgB,2BAA2B,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,GAAE,uBAA4B,GAAG,IAAI,CAsBvG;AAED,6CAA6C;AAC7C,wBAAgB,iCAAiC,IAAI,IAAI,CAIxD"}
|
|
@@ -113,6 +113,16 @@ export interface CompleteToolResultContinuationOptions {
|
|
|
113
113
|
*/
|
|
114
114
|
allowTrailingSystemReminder?: boolean;
|
|
115
115
|
}
|
|
116
|
+
/**
|
|
117
|
+
* Detect mid-conversation effort metadata system messages (e.g. pi >= 0.85.0
|
|
118
|
+
* Persistent Claude thinking effort). These carry effort metadata in
|
|
119
|
+
* `output_config` with empty content and no tool ids or text instructions.
|
|
120
|
+
*/
|
|
121
|
+
export declare function isMidConvoEffortSystemMessage(message: {
|
|
122
|
+
role?: unknown;
|
|
123
|
+
content?: unknown;
|
|
124
|
+
output_config?: unknown;
|
|
125
|
+
} | null | undefined): boolean;
|
|
116
126
|
/**
|
|
117
127
|
* Verify that a resumed tool-result delta settles exactly the tool calls at the
|
|
118
128
|
* stored assistant checkpoint, then coalesce queued user turns into one SDK
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"passthroughEarlyStop.d.ts","sourceRoot":"","sources":["../../src/proxy/passthroughEarlyStop.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AAYH,MAAM,WAAW,gBAAgB;IAC/B,gFAAgF;IAChF,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB,6EAA6E;IAC7E,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;IACrB;yEACqE;IACrE,qBAAqB,CAAC,EAAE,MAAM,CAAA;IAC9B,0EAA0E;IAC1E,KAAK,EAAE,OAAO,CAAA;CACf;AAED,wBAAgB,sBAAsB,IAAI,gBAAgB,CAEzD;AAED;;;;;;;GAOG;AACH,MAAM,WAAW,sBAAsB;IACrC,IAAI,EAAE,UAAU,CAAA;IAChB,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,MAAM,CAAA;CACb;AAED,wBAAgB,wBAAwB,CACtC,KAAK,EAAE,OAAO,EACd,gBAAgB,GAAE,MAA2B,GAC5C,KAAK,IAAI,sBAAsB,CAQjC;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,OAAO,EAChB,gBAAgB,GAAE,MAA2B,GAC5C,IAAI,CAON;AAED;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,gBAAgB,EACzB,OAAO,EAAE,OAAO,EAChB,gBAAgB,GAAE,MAA2B,GAC5C,IAAI,CAoBN;AAED;;;;;;;;;GASG;AACH,wBAAgB,eAAe,CAAC,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,OAAO,GAAG,IAAI,CAQjF;AAED;;;;;GAKG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,gBAAgB,GAAG,OAAO,CAM5E;AAED;;GAEG;AACH,MAAM,WAAW,qCAAqC;IACpD;;;;;;;;OAQG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAA;CACtC;AAED;;;;;GAKG;AACH,wBAAgB,sCAAsC,CACpD,QAAQ,EAAE,KAAK,CAAC;IAAE,IAAI,CAAC,EAAE,OAAO,CAAC;IAAC,OAAO,CAAC,EAAE,OAAO,CAAA;CAAE,CAAC,EACtD,WAAW,EAAE,SAAS,MAAM,EAAE,EAC9B,OAAO,CAAC,EAAE,qCAAqC,GAC9C,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,EAAE,CAAA;CAAE,CAAC,GAAG,SAAS,
|
|
1
|
+
{"version":3,"file":"passthroughEarlyStop.d.ts","sourceRoot":"","sources":["../../src/proxy/passthroughEarlyStop.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Plan → coding-allotment multiplier.
|
|
3
|
+
*
|
|
4
|
+
* Anthropic sizes a plan's Claude Code allotment as a multiple of the Pro
|
|
5
|
+
* baseline — 5x, 20x, 6.25x — and that number, not the plan name, is what says
|
|
6
|
+
* how much work an account can actually do. Two accounts both reporting
|
|
7
|
+
* `Plan: max` can differ by 4x in capacity, so a page that shows only the plan
|
|
8
|
+
* cannot tell the user which account has room left.
|
|
9
|
+
*
|
|
10
|
+
* The multiplier is derived from the raw strings the profile endpoint returns
|
|
11
|
+
* — `seatTier` for a Team account, `rateLimitTier` otherwise — rather than
|
|
12
|
+
* from `subscriptionType`, because that field is too coarse: it collapses Max
|
|
13
|
+
* 5x and Max 20x into the single word `max`, and Team Standard and Team
|
|
14
|
+
* Premium into `team`. `subscriptionType` names the family and is used for the
|
|
15
|
+
* size only as a fallback for the one tier it pins unambiguously.
|
|
16
|
+
*
|
|
17
|
+
* An unrecognized tier yields null rather than a default, which is the whole
|
|
18
|
+
* point of the field: rendering `1x` for an account that is really 20x is
|
|
19
|
+
* worse than rendering nothing, because a reader acts on it.
|
|
20
|
+
*
|
|
21
|
+
* This is a leaf module — pure, no I/O, no imports.
|
|
22
|
+
*/
|
|
23
|
+
export interface PlanAllowance {
|
|
24
|
+
/** Multiplier as displayed, e.g. `"20x"`. Null when the tier is unknown. */
|
|
25
|
+
multiplier: string | null;
|
|
26
|
+
/**
|
|
27
|
+
* The same value as a number, so callers can weight or rank accounts without
|
|
28
|
+
* re-parsing the label. Null whenever `multiplier` is.
|
|
29
|
+
*/
|
|
30
|
+
weight: number | null;
|
|
31
|
+
/** Tier label, e.g. `"Personal Max"`. Null when the tier is unknown. */
|
|
32
|
+
label: string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Which side of Anthropic's pricing the account sits on — `"Personal"`,
|
|
35
|
+
* `"Team"` or `"Enterprise"`. Separate from `planName` because the two are
|
|
36
|
+
* answered by different fields and either can be known without the other: an
|
|
37
|
+
* account whose family is declared but whose tier is unrecognized still has
|
|
38
|
+
* a trustworthy family.
|
|
39
|
+
*/
|
|
40
|
+
accountType: string | null;
|
|
41
|
+
/**
|
|
42
|
+
* The plan WITHIN that family, in the vocabulary of Anthropic's own pricing
|
|
43
|
+
* page: `"Max 20x"`, `"Max 5x"`, `"Pro"`, `"Free"` for personal accounts and
|
|
44
|
+
* `"Premium seat"` / `"Standard seat"` for Team ones.
|
|
45
|
+
*
|
|
46
|
+
* Null when the family is known but the plan is not — which is the common
|
|
47
|
+
* case for a Team seat with no `seat_tier`, since its `rate_limit_tier`
|
|
48
|
+
* reports the underlying bucket rather than the seat.
|
|
49
|
+
*/
|
|
50
|
+
planName: string | null;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Reduce a raw tier string to the form the table below is keyed by.
|
|
54
|
+
*
|
|
55
|
+
* Anthropic prefixes the wire value (`default_claude_max_20x`) and separates
|
|
56
|
+
* words with underscores; the same tier also appears bare (`max_20x`) in
|
|
57
|
+
* places, and `team_tier_1` is the wire spelling of what the pricing page
|
|
58
|
+
* calls Team Premium. Normalizing first means one entry per tier instead of
|
|
59
|
+
* one per spelling.
|
|
60
|
+
*/
|
|
61
|
+
export declare function normalizeRateLimitTier(raw: string | null | undefined): string | null;
|
|
62
|
+
/**
|
|
63
|
+
* Derive the allowance from whatever plan fields a credential file carries.
|
|
64
|
+
*
|
|
65
|
+
* Both arguments are optional because both are optional on disk: a profile
|
|
66
|
+
* written before the plan was persisted has neither, and one written by an
|
|
67
|
+
* older Meridian has only `subscriptionType`. Every unknown case returns the
|
|
68
|
+
* same all-null shape, so callers can render conditionally on one field.
|
|
69
|
+
*/
|
|
70
|
+
export declare function planAllowance(fields: {
|
|
71
|
+
rateLimitTier?: string | null;
|
|
72
|
+
seatTier?: string | null;
|
|
73
|
+
subscriptionType?: string | null;
|
|
74
|
+
} | null | undefined): PlanAllowance;
|
|
75
|
+
//# sourceMappingURL=planAllowance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"planAllowance.d.ts","sourceRoot":"","sources":["../../src/proxy/planAllowance.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,WAAW,aAAa;IAC5B,4EAA4E;IAC5E,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;;;OAGG;IACH,MAAM,EAAE,MAAM,GAAG,IAAI,CAAA;IACrB,wEAAwE;IACxE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,GAAG,IAAI,CAAA;IAC1B;;;;;;;;OAQG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;CACxB;AA4BD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CASpF;AAwED;;;;;;;GAOG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE;IACpC,aAAa,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IAC7B,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAA;CACjC,GAAG,IAAI,GAAG,SAAS,GAAG,aAAa,CAkBnC"}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Liveness and readiness as two DIFFERENT questions, because the existing
|
|
3
|
+
* `/health` answers a third one and is wrong when used as either.
|
|
4
|
+
*
|
|
5
|
+
* `/health` verifies the ACTIVE profile's auth: it spawns `claude auth status`
|
|
6
|
+
* and returns 503 when that profile is logged out. As a liveness probe that is
|
|
7
|
+
* a restart loop waiting to happen - a logged-out account is not fixed by
|
|
8
|
+
* killing the process, and a supervisor pointed at it will keep killing a
|
|
9
|
+
* perfectly healthy proxy until somebody re-authenticates. As a readiness probe
|
|
10
|
+
* it is wrong in the other direction: it inspects one profile out of however
|
|
11
|
+
* many are configured, and its own catch-all answers `degraded` with status
|
|
12
|
+
* **200**, so an instance that cannot verify auth at all reads as ready.
|
|
13
|
+
*
|
|
14
|
+
* So:
|
|
15
|
+
*
|
|
16
|
+
* /livez is this PROCESS still turning - would a restart help?
|
|
17
|
+
* /readyz should traffic be sent to THIS instance rather than another?
|
|
18
|
+
*
|
|
19
|
+
* Named after kube-apiserver's own endpoints, and shaped like them - plain
|
|
20
|
+
* text `ok`, with `?verbose` listing every check - so a Kubernetes probe, a
|
|
21
|
+
* Caddy `health_uri` and a person with curl all read the same thing.
|
|
22
|
+
*/
|
|
23
|
+
export type ProbeKind = "livez" | "readyz";
|
|
24
|
+
export interface ProbeCheck {
|
|
25
|
+
readonly name: string;
|
|
26
|
+
readonly ok: boolean;
|
|
27
|
+
/** Why it failed. Absent when it passed. */
|
|
28
|
+
readonly detail?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface ProbeReport {
|
|
31
|
+
readonly ok: boolean;
|
|
32
|
+
readonly checks: readonly ProbeCheck[];
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Liveness passes unconditionally, and that is the design rather than a stub.
|
|
36
|
+
*
|
|
37
|
+
* Reaching this function at all means the event loop is turning and the HTTP
|
|
38
|
+
* server is answering, which is the entire question. Every dependency added
|
|
39
|
+
* here - a subprocess, a credential file, a reachable upstream - is another
|
|
40
|
+
* way for this process to be killed over somebody else's outage, and a
|
|
41
|
+
* liveness probe that restarts a working process is strictly worse than no
|
|
42
|
+
* liveness probe at all.
|
|
43
|
+
*/
|
|
44
|
+
export declare function livenessReport(): ProbeReport;
|
|
45
|
+
export interface ReadinessInput {
|
|
46
|
+
/** Profiles this instance would actually serve from. */
|
|
47
|
+
readonly profileCount: number;
|
|
48
|
+
/** Whether a Claude executable resolves for this instance. */
|
|
49
|
+
readonly claudeExecutableResolved: boolean;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Readiness admits only checks that are PER-INSTANCE.
|
|
53
|
+
*
|
|
54
|
+
* The point of readiness is to move traffic somewhere better, so a check that
|
|
55
|
+
* two instances fail together cannot move it anywhere - it can only take every
|
|
56
|
+
* instance out at once and turn a clear error into a 502. That is why the
|
|
57
|
+
* credentials are deliberately not checked here even though a proxy with no
|
|
58
|
+
* usable token serves nothing: instances share those files, so an outage of
|
|
59
|
+
* them is not a reason to prefer one instance over another, and the honest
|
|
60
|
+
* answer to the caller is the provider's own 401 rather than a gateway error.
|
|
61
|
+
*
|
|
62
|
+
* What remains is genuinely local to one process:
|
|
63
|
+
*
|
|
64
|
+
* profiles an instance whose configuration and whose
|
|
65
|
+
* `profiles.json` are both empty has no account to serve
|
|
66
|
+
* from, while a neighbour reading a populated one is
|
|
67
|
+
* fine. In a container that is entirely per-instance: the
|
|
68
|
+
* file lives under that container's own HOME, so a
|
|
69
|
+
* missing mount takes exactly one replica out.
|
|
70
|
+
* claude-executable resolved from `MERIDIAN_CLAUDE_PATH`, this install's
|
|
71
|
+
* own `node_modules`, or its platform package - all
|
|
72
|
+
* per-instance, and without one no request can be served
|
|
73
|
+
* (#478).
|
|
74
|
+
*/
|
|
75
|
+
export declare function readinessReport(input: ReadinessInput): ProbeReport;
|
|
76
|
+
/**
|
|
77
|
+
* kube-apiserver's own output shape: `[+]name ok` per check, a verdict line,
|
|
78
|
+
* and a bare `ok` when everything passed and nobody asked for detail.
|
|
79
|
+
*
|
|
80
|
+
* The terse form is the one a load balancer polls every few seconds, so it
|
|
81
|
+
* stays two bytes; the failing form names the checks that failed even without
|
|
82
|
+
* `?verbose`, because a 503 nobody can explain is a 503 somebody disables.
|
|
83
|
+
*/
|
|
84
|
+
export declare function renderProbe(kind: ProbeKind, report: ProbeReport, verbose: boolean): string;
|
|
85
|
+
//# sourceMappingURL=probes.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"probes.d.ts","sourceRoot":"","sources":["../../src/proxy/probes.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH,MAAM,MAAM,SAAS,GAAG,OAAO,GAAG,QAAQ,CAAA;AAE1C,MAAM,WAAW,UAAU;IACzB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;IACrB,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,4CAA4C;IAC5C,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CACzB;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,OAAO,CAAA;IACpB,QAAQ,CAAC,MAAM,EAAE,SAAS,UAAU,EAAE,CAAA;CACvC;AAED;;;;;;;;;GASG;AACH,wBAAgB,cAAc,IAAI,WAAW,CAE5C;AAED,MAAM,WAAW,cAAc;IAC7B,wDAAwD;IACxD,QAAQ,CAAC,YAAY,EAAE,MAAM,CAAA;IAC7B,8DAA8D;IAC9D,QAAQ,CAAC,wBAAwB,EAAE,OAAO,CAAA;CAC3C;AAED;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,cAAc,GAAG,WAAW,CAgBlE;AAED;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,GAAG,MAAM,CAS1F"}
|
|
@@ -1,17 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* CLI commands for profile management.
|
|
3
3
|
*
|
|
4
|
-
* Browser-login profiles are stored under
|
|
4
|
+
* Browser-login profiles are stored under <config dir>/profiles/{id}/
|
|
5
5
|
* — each directory is a standalone CLAUDE_CONFIG_DIR with its own OAuth
|
|
6
6
|
* tokens. OAuth-token profiles (added via `--oauth-token`) live entirely in
|
|
7
7
|
* profiles.json — no per-profile config dir.
|
|
8
8
|
*
|
|
9
9
|
* This is a leaf module — no imports from server.ts or session/.
|
|
10
10
|
*/
|
|
11
|
+
import { type OAuthPlanFields } from "./oauthPlan";
|
|
11
12
|
import type { ProfileConfig } from "./profiles";
|
|
13
|
+
import { type CredentialsFile } from "./tokenRefresh";
|
|
12
14
|
export declare const OAUTH_TOKEN_URL = "https://platform.claude.com/v1/oauth/token";
|
|
13
15
|
export declare const OAUTH_CLIENT_ID = "9d1c250a-e61b-44d9-88ed-5944d1962f5e";
|
|
14
16
|
export declare const OAUTH_REDIRECT_URI = "https://platform.claude.com/oauth/code/callback";
|
|
17
|
+
/**
|
|
18
|
+
* Pure: is this ID safe to use as a profile name?
|
|
19
|
+
*
|
|
20
|
+
* A profile ID becomes a directory name under PROFILES_DIR, so anything
|
|
21
|
+
* carrying a path separator or a `..` segment would escape that directory.
|
|
22
|
+
* Restricting to plain identifiers keeps IDs both safe and shell-friendly.
|
|
23
|
+
*/
|
|
24
|
+
export declare function isValidProfileId(id: string): boolean;
|
|
15
25
|
interface AuthLoginOptions {
|
|
16
26
|
headless?: boolean;
|
|
17
27
|
}
|
|
@@ -24,9 +34,29 @@ interface ParsedAuthorizationCode {
|
|
|
24
34
|
code: string;
|
|
25
35
|
state?: string;
|
|
26
36
|
}
|
|
37
|
+
interface OAuthTokenResponse {
|
|
38
|
+
access_token: string;
|
|
39
|
+
refresh_token?: string;
|
|
40
|
+
expires_in?: number;
|
|
41
|
+
expires_at?: number;
|
|
42
|
+
scope?: string;
|
|
43
|
+
}
|
|
27
44
|
export declare function buildAuthLoginEnv(configDir: string | undefined, _options?: AuthLoginOptions, baseEnv?: NodeJS.ProcessEnv): NodeJS.ProcessEnv;
|
|
28
45
|
export declare function createManualOAuthSession(scopes?: string[]): ManualOAuthSession;
|
|
29
46
|
export declare function parseAuthorizationCodeInput(input: string): ParsedAuthorizationCode | null;
|
|
47
|
+
type CompleteOAuthTokenResponse = OAuthTokenResponse & {
|
|
48
|
+
refresh_token: string;
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Build the record a login writes to disk.
|
|
52
|
+
*
|
|
53
|
+
* Split out so the on-disk shape is directly assertable: the defect this closes
|
|
54
|
+
* was a field missing from this object literal, which no test of the
|
|
55
|
+
* surrounding prompt/fetch I/O would have caught. Plan fields spread in only
|
|
56
|
+
* when known — `subscriptionType: undefined` would write a null-ish key into a
|
|
57
|
+
* file the real CLI also parses.
|
|
58
|
+
*/
|
|
59
|
+
export declare function buildLoginCredentials(tokenData: CompleteOAuthTokenResponse, plan: OAuthPlanFields, now?: number): CredentialsFile;
|
|
30
60
|
export declare function profileAdd(id: string, options?: AuthLoginOptions): Promise<void>;
|
|
31
61
|
export declare function profileAddOauthToken(id: string, tokenArg: string | undefined): Promise<void>;
|
|
32
62
|
export declare function profileList(): void;
|
|
@@ -41,7 +71,29 @@ export declare function profileList(): void;
|
|
|
41
71
|
*/
|
|
42
72
|
export declare function dirsToRemoveOnProfileRemove(profile: ProfileConfig, profilesDir: string): string[];
|
|
43
73
|
export declare function profileRemove(id: string): void;
|
|
74
|
+
export declare function profileRename(from: string, to: string): void;
|
|
44
75
|
export declare function profileSwitch(id: string): Promise<void>;
|
|
76
|
+
export type ProfileLoginPlan = {
|
|
77
|
+
action: "create";
|
|
78
|
+
} | {
|
|
79
|
+
action: "reject-invalid-id";
|
|
80
|
+
} | {
|
|
81
|
+
action: "reject-oauth-token";
|
|
82
|
+
} | {
|
|
83
|
+
action: "login";
|
|
84
|
+
profile: ProfileConfig;
|
|
85
|
+
};
|
|
86
|
+
/**
|
|
87
|
+
* Pure: decide what `meridian profile login <id>` should do.
|
|
88
|
+
*
|
|
89
|
+
* An unknown ID is a request to create that profile, not an error — the ID is
|
|
90
|
+
* validated first because only this branch turns it into a directory. A profile
|
|
91
|
+
* that already exists is never re-validated: it was written by an earlier `add`
|
|
92
|
+
* (or by hand), and login must keep working on it either way.
|
|
93
|
+
*
|
|
94
|
+
* Caller performs the login itself — this returns the decision only.
|
|
95
|
+
*/
|
|
96
|
+
export declare function planProfileLogin(id: string, profiles: ProfileConfig[]): ProfileLoginPlan;
|
|
45
97
|
export declare function profileLogin(id: string, options?: AuthLoginOptions): Promise<void>;
|
|
46
98
|
export declare function profileHelp(): void;
|
|
47
99
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"profileCli.d.ts","sourceRoot":"","sources":["../../src/proxy/profileCli.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;
|
|
1
|
+
{"version":3,"file":"profileCli.d.ts","sourceRoot":"","sources":["../../src/proxy/profileCli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What we know, right now, about accounts that have just been refused.
|
|
3
|
+
*
|
|
4
|
+
* Two stores, both in-memory and both deliberately not persisted - this is
|
|
5
|
+
* observability and routing hygiene, not durable truth. After a restart the
|
|
6
|
+
* next refusal re-establishes everything.
|
|
7
|
+
*
|
|
8
|
+
* `SpentStore` holds the latest refusal per profile, so a UI can say "this
|
|
9
|
+
* account is refusing" alongside the cached percentages instead of replacing
|
|
10
|
+
* them. Measured on the live fleet: an account rendered `5h 67% / 7d 7%` while
|
|
11
|
+
* every request through it was being refused, because those percentages are a
|
|
12
|
+
* snapshot of the last successful read and a refusal never touched them.
|
|
13
|
+
*
|
|
14
|
+
* `FailoverEventLog` is a bounded, monotonically numbered event ring so an
|
|
15
|
+
* external supervisor (vibeterm's account switcher) can poll for refusals and
|
|
16
|
+
* failovers. It exists because `claudeLog("profile.failover", …)` went to the
|
|
17
|
+
* log and nowhere else, and because `/telemetry/requests` - the obvious place
|
|
18
|
+
* to look - is a 500-row ring with no cursor, so a poller cannot tell "nothing
|
|
19
|
+
* happened" from "it scrolled past between polls". The `since` cursor here is
|
|
20
|
+
* the fix for exactly that.
|
|
21
|
+
*
|
|
22
|
+
* Leaf module: no I/O, no imports from server.ts. Clocks are injectable so the
|
|
23
|
+
* tests do not depend on wall time.
|
|
24
|
+
*/
|
|
25
|
+
import type { LimitDiagnosis } from "./limitDetection";
|
|
26
|
+
export interface SpentRecord {
|
|
27
|
+
profileId: string;
|
|
28
|
+
/** When the refusal was observed (epoch ms). */
|
|
29
|
+
at: number;
|
|
30
|
+
diagnosis: LimitDiagnosis;
|
|
31
|
+
/** When this account is expected to serve again, when known. */
|
|
32
|
+
until: number | null;
|
|
33
|
+
/** Truncated raw SDK message - the operator's evidence for the verdict. */
|
|
34
|
+
message: string;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Latest refusal per profile, dropped on read once it expires (the same
|
|
38
|
+
* read-time expiry `ProfileExhaustion` uses, so the two never disagree about
|
|
39
|
+
* whether an account is currently in trouble).
|
|
40
|
+
*/
|
|
41
|
+
export declare class SpentStore {
|
|
42
|
+
private readonly now;
|
|
43
|
+
private readonly records;
|
|
44
|
+
constructor(now?: () => number);
|
|
45
|
+
/**
|
|
46
|
+
* Record a refusal. A later record always replaces an earlier one: unlike an
|
|
47
|
+
* exhaustion mark (where a longer cooldown must win), the newest refusal is
|
|
48
|
+
* by definition the best description of the account's current state.
|
|
49
|
+
*/
|
|
50
|
+
record(profileId: string, diagnosis: LimitDiagnosis, message: string): SpentRecord;
|
|
51
|
+
get(profileId: string): SpentRecord | undefined;
|
|
52
|
+
/** Live records only - expired ones are dropped on read. */
|
|
53
|
+
snapshot(): SpentRecord[];
|
|
54
|
+
clear(): void;
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* `refused` - an account said no. Emitted in every routing mode, so an
|
|
58
|
+
* exhausted account is visible even when nothing failed over.
|
|
59
|
+
* `failover` - a request was re-issued on another account and succeeded,
|
|
60
|
+
* so the client never saw the refusal.
|
|
61
|
+
* `pool_exhausted` - every candidate refused; the client got the error.
|
|
62
|
+
*/
|
|
63
|
+
export type FailoverEventKind = "refused" | "failover" | "pool_exhausted";
|
|
64
|
+
export interface FailoverEvent {
|
|
65
|
+
/** Monotonic, starts at 1, never reused. The `since` cursor. */
|
|
66
|
+
seq: number;
|
|
67
|
+
at: number;
|
|
68
|
+
kind: FailoverEventKind;
|
|
69
|
+
/** The account that refused. */
|
|
70
|
+
profile: string;
|
|
71
|
+
/** The account that served the request instead, for `failover`. */
|
|
72
|
+
servedBy: string | null;
|
|
73
|
+
reason: string;
|
|
74
|
+
/** Routing mode in effect when this happened. */
|
|
75
|
+
routing: string;
|
|
76
|
+
sessionKey: string | null;
|
|
77
|
+
/**
|
|
78
|
+
* True when this refusal happened on an internal re-proxy hop, meaning the
|
|
79
|
+
* client did not see it. A `refused` event with `internalHop: false` is one
|
|
80
|
+
* the connected agent actually received.
|
|
81
|
+
*/
|
|
82
|
+
internalHop: boolean;
|
|
83
|
+
until: number | null;
|
|
84
|
+
limit: LimitDiagnosis | null;
|
|
85
|
+
}
|
|
86
|
+
export interface FailoverEventPage {
|
|
87
|
+
events: FailoverEvent[];
|
|
88
|
+
/**
|
|
89
|
+
* Cursor for the next poll. The seq of the LAST RETURNED event, or the
|
|
90
|
+
* requested `since` when nothing was returned - never the ring's newest seq,
|
|
91
|
+
* because a page truncated by `limit` would then skip the remainder.
|
|
92
|
+
*/
|
|
93
|
+
nextSince: number;
|
|
94
|
+
oldestSeq: number;
|
|
95
|
+
latestSeq: number;
|
|
96
|
+
/**
|
|
97
|
+
* True when events between the requested `since` and the oldest retained one
|
|
98
|
+
* were evicted, so the caller knows it missed some rather than believing it
|
|
99
|
+
* has seen everything.
|
|
100
|
+
*/
|
|
101
|
+
dropped: boolean;
|
|
102
|
+
capacity: number;
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Bounded ring of refusal/failover events, oldest-first on read.
|
|
106
|
+
*
|
|
107
|
+
* Capacity is generous relative to the event rate (one per refusal, not one per
|
|
108
|
+
* request), so a consumer polling every few seconds cannot outrun it; `dropped`
|
|
109
|
+
* exists for the case where a consumer was away long enough that it did.
|
|
110
|
+
*/
|
|
111
|
+
export declare class FailoverEventLog {
|
|
112
|
+
private readonly capacity;
|
|
113
|
+
private readonly now;
|
|
114
|
+
private readonly events;
|
|
115
|
+
private seq;
|
|
116
|
+
constructor(capacity?: number, now?: () => number);
|
|
117
|
+
append(event: Omit<FailoverEvent, "seq" | "at"> & {
|
|
118
|
+
at?: number;
|
|
119
|
+
}): FailoverEvent;
|
|
120
|
+
/**
|
|
121
|
+
* Events strictly after `since`, oldest-first. `since = 0` returns everything
|
|
122
|
+
* retained, which is what a consumer starting cold wants.
|
|
123
|
+
*/
|
|
124
|
+
since(since: number, limit?: number): FailoverEventPage;
|
|
125
|
+
clear(): void;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=profileHealth.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profileHealth.d.ts","sourceRoot":"","sources":["../../src/proxy/profileHealth.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AAEH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAA;AAEtD,MAAM,WAAW,WAAW;IAC1B,SAAS,EAAE,MAAM,CAAA;IACjB,gDAAgD;IAChD,EAAE,EAAE,MAAM,CAAA;IACV,SAAS,EAAE,cAAc,CAAA;IACzB,gEAAgE;IAChE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,2EAA2E;IAC3E,OAAO,EAAE,MAAM,CAAA;CAChB;AAWD;;;;GAIG;AACH,qBAAa,UAAU;IAGT,OAAO,CAAC,QAAQ,CAAC,GAAG;IAFhC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAiC;gBAE5B,GAAG,GAAE,MAAM,MAAiB;IAEzD;;;;OAIG;IACH,MAAM,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,cAAc,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW;IAiBlF,GAAG,CAAC,SAAS,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS;IAU/C,4DAA4D;IAC5D,QAAQ,IAAI,WAAW,EAAE;IASzB,KAAK,IAAI,IAAI;CAGd;AAED;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,GAAG,SAAS,GAAG,UAAU,GAAG,gBAAgB,CAAA;AAEzE,MAAM,WAAW,aAAa;IAC5B,gEAAgE;IAChE,GAAG,EAAE,MAAM,CAAA;IACX,EAAE,EAAE,MAAM,CAAA;IACV,IAAI,EAAE,iBAAiB,CAAA;IACvB,gCAAgC;IAChC,OAAO,EAAE,MAAM,CAAA;IACf,mEAAmE;IACnE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,MAAM,EAAE,MAAM,CAAA;IACd,iDAAiD;IACjD,OAAO,EAAE,MAAM,CAAA;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAA;IACzB;;;;OAIG;IACH,WAAW,EAAE,OAAO,CAAA;IACpB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAA;IACpB,KAAK,EAAE,cAAc,GAAG,IAAI,CAAA;CAC7B;AAED,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,aAAa,EAAE,CAAA;IACvB;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB,SAAS,EAAE,MAAM,CAAA;IACjB;;;;OAIG;IACH,OAAO,EAAE,OAAO,CAAA;IAChB,QAAQ,EAAE,MAAM,CAAA;CACjB;AAKD;;;;;;GAMG;AACH,qBAAa,gBAAgB;IAKzB,OAAO,CAAC,QAAQ,CAAC,QAAQ;IACzB,OAAO,CAAC,QAAQ,CAAC,GAAG;IALtB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,GAAG,CAAI;gBAGI,QAAQ,GAAE,MAA+B,EACzC,GAAG,GAAE,MAAM,MAAiB;IAG/C,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,aAAa,EAAE,KAAK,GAAG,IAAI,CAAC,GAAG;QAAE,EAAE,CAAC,EAAE,MAAM,CAAA;KAAE,GAAG,aAAa;IAOjF;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,GAAE,MAA2B,GAAG,iBAAiB;IAkB3E,KAAK,IAAI,IAAI;CAId"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Profile renaming.
|
|
3
|
+
*
|
|
4
|
+
* A rename has to move everything that names a profile: its entry in
|
|
5
|
+
* profiles.json and, when its credentials live under
|
|
6
|
+
* ~/.config/meridian/profiles/<id>, the credential directory itself. Renaming
|
|
7
|
+
* the entry alone would leave the profile pointing at a directory that is no
|
|
8
|
+
* longer its own — an account logged out by a cosmetic change — so both are
|
|
9
|
+
* planned together and applied as one step that either happens or does not.
|
|
10
|
+
*
|
|
11
|
+
* The old name survives as an ALIAS on the renamed profile. It is a redirect,
|
|
12
|
+
* not a second name: after `x` is renamed to `y`, `x-meridian-profile: x` is
|
|
13
|
+
* served by `y`, and the moment `x` is claimed again — by `profile add x`, or
|
|
14
|
+
* by renaming something else to `x` — the redirect is dropped.
|
|
15
|
+
*
|
|
16
|
+
* Chains are collapsed on write. Renaming x→y and later y→z leaves z holding
|
|
17
|
+
* both "x" and "y", so resolution is a single lookup and no alias can dangle
|
|
18
|
+
* at an intermediate name that no longer exists.
|
|
19
|
+
*
|
|
20
|
+
* This is a leaf module — no imports from server.ts or session/.
|
|
21
|
+
*/
|
|
22
|
+
import type { ProfileConfig } from "./profiles";
|
|
23
|
+
export declare function isValidProfileId(id: string): boolean;
|
|
24
|
+
export declare function defaultProfilesDir(): string;
|
|
25
|
+
export declare function defaultProfilesConfigFile(): string;
|
|
26
|
+
export declare function loadProfileConfigFrom(file: string): ProfileConfig[];
|
|
27
|
+
export declare function saveProfileConfigTo(file: string, profiles: ProfileConfig[]): void;
|
|
28
|
+
/**
|
|
29
|
+
* Drop `name` from every profile's alias list — a real profile is claiming the
|
|
30
|
+
* name, so the redirect has to stop. Profiles with nothing to drop are
|
|
31
|
+
* returned as-is.
|
|
32
|
+
*/
|
|
33
|
+
export declare function reclaimAlias(profiles: ProfileConfig[], name: string): ProfileConfig[];
|
|
34
|
+
export interface ProfileRenamePlan {
|
|
35
|
+
/** The complete profile list as it should be written to disk. */
|
|
36
|
+
profiles: ProfileConfig[];
|
|
37
|
+
/** Credential directory to move, when this profile keeps one under profilesDir. */
|
|
38
|
+
dirMove?: {
|
|
39
|
+
from: string;
|
|
40
|
+
to: string;
|
|
41
|
+
};
|
|
42
|
+
/** Aliases the renamed profile ends up carrying, chains already collapsed. */
|
|
43
|
+
aliases: string[];
|
|
44
|
+
}
|
|
45
|
+
export type ProfileRenameResult = {
|
|
46
|
+
ok: true;
|
|
47
|
+
plan: ProfileRenamePlan;
|
|
48
|
+
} | {
|
|
49
|
+
ok: false;
|
|
50
|
+
error: string;
|
|
51
|
+
hint?: string;
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Pure: decide what a rename would change. Refuses rather than corrupting —
|
|
55
|
+
* an unknown source, an occupied target, or a name the charset rejects each
|
|
56
|
+
* come back as an error with nothing planned.
|
|
57
|
+
*/
|
|
58
|
+
export declare function planProfileRename(profiles: ProfileConfig[], from: string, to: string, profilesDir: string): ProfileRenameResult;
|
|
59
|
+
export interface ApplyProfileRenameOptions {
|
|
60
|
+
/** Directory holding per-profile credential dirs. Defaults to the real one. */
|
|
61
|
+
profilesDir?: string;
|
|
62
|
+
/** profiles.json path. Defaults to the real one. */
|
|
63
|
+
configFile?: string;
|
|
64
|
+
}
|
|
65
|
+
export type ApplyProfileRenameResult = {
|
|
66
|
+
ok: true;
|
|
67
|
+
from: string;
|
|
68
|
+
to: string;
|
|
69
|
+
aliases: string[];
|
|
70
|
+
profiles: ProfileConfig[];
|
|
71
|
+
} | {
|
|
72
|
+
ok: false;
|
|
73
|
+
error: string;
|
|
74
|
+
hint?: string;
|
|
75
|
+
};
|
|
76
|
+
/**
|
|
77
|
+
* Apply a rename to disk: credentials first, then the profile list, then the
|
|
78
|
+
* active pointer. If the profile list cannot be written the credential move is
|
|
79
|
+
* undone, so the profile is never left naming a directory that moved out from
|
|
80
|
+
* under it.
|
|
81
|
+
*/
|
|
82
|
+
export declare function applyProfileRename(from: string, to: string, options?: ApplyProfileRenameOptions): ApplyProfileRenameResult;
|
|
83
|
+
//# sourceMappingURL=profileRename.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profileRename.d.ts","sourceRoot":"","sources":["../../src/proxy/profileRename.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAA;AAK/C,wBAAgB,gBAAgB,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAEpD;AAED,wBAAgB,kBAAkB,IAAI,MAAM,CAE3C;AAED,wBAAgB,yBAAyB,IAAI,MAAM,CAElD;AAED,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CASnE;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI,CAGjF;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,aAAa,EAAE,EAAE,IAAI,EAAE,MAAM,GAAG,aAAa,EAAE,CASrF;AAED,MAAM,WAAW,iBAAiB;IAChC,iEAAiE;IACjE,QAAQ,EAAE,aAAa,EAAE,CAAA;IACzB,mFAAmF;IACnF,OAAO,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,CAAA;IACtC,8EAA8E;IAC9E,OAAO,EAAE,MAAM,EAAE,CAAA;CAClB;AAED,MAAM,MAAM,mBAAmB,GAC3B;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,iBAAiB,CAAA;CAAE,GACrC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/C;;;;GAIG;AACH,wBAAgB,iBAAiB,CAC/B,QAAQ,EAAE,aAAa,EAAE,EACzB,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,WAAW,EAAE,MAAM,GAClB,mBAAmB,CA2CrB;AAED,MAAM,WAAW,yBAAyB;IACxC,+EAA+E;IAC/E,WAAW,CAAC,EAAE,MAAM,CAAA;IACpB,oDAAoD;IACpD,UAAU,CAAC,EAAE,MAAM,CAAA;CACpB;AAED,MAAM,MAAM,wBAAwB,GAChC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,EAAE,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,EAAE,CAAC;IAAC,QAAQ,EAAE,aAAa,EAAE,CAAA;CAAE,GACpF;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAE,CAAA;AAE/C;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,EACZ,EAAE,EAAE,MAAM,EACV,OAAO,GAAE,yBAA8B,GACtC,wBAAwB,CAwD1B"}
|