@rynfar/meridian 1.71.1 → 1.73.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 +115 -162
- package/assets/desktop-dashboard.jpg +0 -0
- package/assets/trayTemplate.png +0 -0
- package/assets/trayTemplate@2x.png +0 -0
- package/assets/trayTemplate@3x.png +0 -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-grfp0s1j.js +330 -0
- package/dist/{cli-ryt69ryf.js → cli-p5zbk952.js} +2185 -358
- package/dist/{cli-8yp89fan.js → cli-p9ca4p13.js} +17 -2
- package/dist/cli-qpfky8wy.js +133 -0
- package/dist/cli.js +47 -12
- 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-n3gdtbmj.js → pluginPage-3kxsrdpj.js} +1 -1
- package/dist/{profileCli-1eecbmgk.js → profileCli-1bfgc05h.js} +13 -3
- package/dist/{profilePage-vfj2dbhn.js → profilePage-etxqg3vn.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/authDiscovery.d.ts +52 -0
- package/dist/proxy/authDiscovery.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/errors.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 +4 -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/session/processIncarnation.d.ts +7 -0
- package/dist/proxy/session/processIncarnation.d.ts.map +1 -1
- package/dist/proxy/sessionLifecycle.d.ts +8 -1
- package/dist/proxy/sessionLifecycle.d.ts.map +1 -1
- package/dist/proxy/sessionStore.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/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 +10 -2
- 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/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 +2 -1
- 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
|
@@ -118,7 +118,9 @@ var themeCss = `
|
|
|
118
118
|
background: rgba(188,140,255,0.12);
|
|
119
119
|
border: 1px solid rgba(188,140,255,0.35);
|
|
120
120
|
cursor: default;
|
|
121
|
-
|
|
121
|
+
.meridian-header .mh-profile.following { border-color: var(--accent2, #bc8cff); }
|
|
122
|
+
.meridian-header .mh-profile .mh-profile-follow {
|
|
123
|
+
color: var(--accent2, #bc8cff); font-size: 10px; }
|
|
122
124
|
.meridian-header .mh-status {
|
|
123
125
|
display: inline-flex; align-items: center; gap: 6px;
|
|
124
126
|
font-size: 11px; color: var(--muted, #8b949e); white-space: nowrap;
|
|
@@ -193,7 +195,20 @@ var themeCss = `
|
|
|
193
195
|
fetch('/profiles/list').then(function(r) { return r.json(); }).then(function(data) {
|
|
194
196
|
var current = (data.profiles || []).find(function(p) { return p.isActive; });
|
|
195
197
|
if (!current) { profileChip.classList.remove('visible'); return; }
|
|
196
|
-
|
|
198
|
+
// Follow mode: say so on every page. An instance quietly taking its
|
|
199
|
+
// active profile from another one, with a picker that won't stick, is
|
|
200
|
+
// otherwise an hour of confusion.
|
|
201
|
+
var follow = data.follow;
|
|
202
|
+
var followLabel = follow ? (follow.activeProfile ? 'following' : 'follow: local') : '';
|
|
203
|
+
if (follow && follow.stale) followLabel += ' (stale)';
|
|
204
|
+
profileChip.innerHTML = esc(current.id) + ' <span class="mh-profile-type">' + esc(current.type || '') + '</span>'
|
|
205
|
+
+ (follow ? ' <span class="mh-profile-follow">' + esc(followLabel) + '</span>' : '');
|
|
206
|
+
profileChip.classList.toggle('following', !!follow);
|
|
207
|
+
profileChip.title = follow
|
|
208
|
+
? 'Active profile follows ' + follow.url + ' (MERIDIAN_FOLLOW_ACTIVE)'
|
|
209
|
+
+ (follow.activeProfile ? '' : ' — no usable value from it, using the local profile')
|
|
210
|
+
+ '. Switching here is refused; switch on the followed instance.'
|
|
211
|
+
: 'Active profile — switch from the home page';
|
|
197
212
|
profileChip.classList.add('visible');
|
|
198
213
|
}).catch(function() {});
|
|
199
214
|
}
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
import {
|
|
2
|
+
configPath,
|
|
3
|
+
getSetting,
|
|
4
|
+
init_configDir,
|
|
5
|
+
setSetting
|
|
6
|
+
} from "./cli-eehk3052.js";
|
|
7
|
+
|
|
8
|
+
// src/proxy/profileRename.ts
|
|
9
|
+
init_configDir();
|
|
10
|
+
import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from "node:fs";
|
|
11
|
+
import { dirname, join } from "node:path";
|
|
12
|
+
var INVALID_PROFILE_ID = /[^a-zA-Z0-9_-]/;
|
|
13
|
+
function isValidProfileId(id) {
|
|
14
|
+
return id.length > 0 && !INVALID_PROFILE_ID.test(id);
|
|
15
|
+
}
|
|
16
|
+
function defaultProfilesDir() {
|
|
17
|
+
return configPath("profiles");
|
|
18
|
+
}
|
|
19
|
+
function defaultProfilesConfigFile() {
|
|
20
|
+
return configPath("profiles.json");
|
|
21
|
+
}
|
|
22
|
+
function loadProfileConfigFrom(file) {
|
|
23
|
+
if (!existsSync(file))
|
|
24
|
+
return [];
|
|
25
|
+
try {
|
|
26
|
+
const parsed = JSON.parse(readFileSync(file, "utf-8"));
|
|
27
|
+
return Array.isArray(parsed) ? parsed : [];
|
|
28
|
+
} catch (err) {
|
|
29
|
+
console.warn(`[meridian] Failed to read ${file}: ${err instanceof Error ? err.message : err}`);
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
function saveProfileConfigTo(file, profiles) {
|
|
34
|
+
mkdirSync(dirname(file), { recursive: true });
|
|
35
|
+
writeFileSync(file, `${JSON.stringify(profiles, null, 2)}
|
|
36
|
+
`, { mode: 384 });
|
|
37
|
+
}
|
|
38
|
+
function reclaimAlias(profiles, name) {
|
|
39
|
+
return profiles.map((p) => {
|
|
40
|
+
if (!p.aliases?.includes(name))
|
|
41
|
+
return p;
|
|
42
|
+
const remaining = p.aliases.filter((a) => a !== name);
|
|
43
|
+
const next = { ...p };
|
|
44
|
+
if (remaining.length > 0)
|
|
45
|
+
next.aliases = remaining;
|
|
46
|
+
else
|
|
47
|
+
delete next.aliases;
|
|
48
|
+
return next;
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
function planProfileRename(profiles, from, to, profilesDir) {
|
|
52
|
+
if (!isValidProfileId(to)) {
|
|
53
|
+
return {
|
|
54
|
+
ok: false,
|
|
55
|
+
error: `Invalid profile name "${to}".`,
|
|
56
|
+
hint: "Use only letters, numbers, hyphens, underscores."
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
const target = profiles.find((p) => p.id === from);
|
|
60
|
+
if (!target) {
|
|
61
|
+
return { ok: false, error: `Profile "${from}" not found.`, hint: "Run: meridian profile list" };
|
|
62
|
+
}
|
|
63
|
+
if (from === to) {
|
|
64
|
+
return { ok: false, error: `Profile "${from}" is already called that.` };
|
|
65
|
+
}
|
|
66
|
+
if (profiles.some((p) => p.id === to)) {
|
|
67
|
+
return { ok: false, error: `Profile "${to}" already exists.`, hint: "Run: meridian profile list" };
|
|
68
|
+
}
|
|
69
|
+
const oldDir = join(profilesDir, from);
|
|
70
|
+
const newDir = join(profilesDir, to);
|
|
71
|
+
const ownsDir = target.claudeConfigDir === oldDir;
|
|
72
|
+
const isOauthToken = Boolean(target.oauthToken) || target.type === "oauth-token";
|
|
73
|
+
const aliases = [...new Set([...target.aliases ?? [], from])].filter((a) => a !== to);
|
|
74
|
+
const renamed = { ...target, id: to, aliases };
|
|
75
|
+
if (ownsDir)
|
|
76
|
+
renamed.claudeConfigDir = newDir;
|
|
77
|
+
const next = reclaimAlias(profiles, to).map((p) => p.id === from ? renamed : p);
|
|
78
|
+
const plan = { profiles: next, aliases };
|
|
79
|
+
if (ownsDir || isOauthToken)
|
|
80
|
+
plan.dirMove = { from: oldDir, to: newDir };
|
|
81
|
+
return { ok: true, plan };
|
|
82
|
+
}
|
|
83
|
+
function applyProfileRename(from, to, options = {}) {
|
|
84
|
+
const profilesDir = options.profilesDir ?? defaultProfilesDir();
|
|
85
|
+
const configFile = options.configFile ?? defaultProfilesConfigFile();
|
|
86
|
+
const profiles = loadProfileConfigFrom(configFile);
|
|
87
|
+
const planned = planProfileRename(profiles, from, to, profilesDir);
|
|
88
|
+
if (!planned.ok)
|
|
89
|
+
return planned;
|
|
90
|
+
const { plan } = planned;
|
|
91
|
+
let movedDir;
|
|
92
|
+
if (plan.dirMove && existsSync(plan.dirMove.from)) {
|
|
93
|
+
if (existsSync(plan.dirMove.to)) {
|
|
94
|
+
return {
|
|
95
|
+
ok: false,
|
|
96
|
+
error: `Cannot rename to "${to}": ${plan.dirMove.to} already exists.`,
|
|
97
|
+
hint: "Remove or move that directory, then retry."
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
try {
|
|
101
|
+
renameSync(plan.dirMove.from, plan.dirMove.to);
|
|
102
|
+
movedDir = plan.dirMove;
|
|
103
|
+
} catch (err) {
|
|
104
|
+
return {
|
|
105
|
+
ok: false,
|
|
106
|
+
error: `Could not move credentials for "${from}": ${err instanceof Error ? err.message : err}`
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
try {
|
|
111
|
+
saveProfileConfigTo(configFile, plan.profiles);
|
|
112
|
+
} catch (err) {
|
|
113
|
+
const reason = err instanceof Error ? err.message : String(err);
|
|
114
|
+
if (movedDir) {
|
|
115
|
+
try {
|
|
116
|
+
renameSync(movedDir.to, movedDir.from);
|
|
117
|
+
} catch (undoErr) {
|
|
118
|
+
const undoReason = undoErr instanceof Error ? undoErr.message : String(undoErr);
|
|
119
|
+
return {
|
|
120
|
+
ok: false,
|
|
121
|
+
error: `Could not write ${configFile} (${reason}), and could not move credentials back (${undoReason}).`,
|
|
122
|
+
hint: `Profile "${from}" still expects its credentials at ${movedDir.from} — move ${movedDir.to} back by hand.`
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
return { ok: false, error: `Could not write ${configFile}: ${reason}` };
|
|
127
|
+
}
|
|
128
|
+
if (getSetting("activeProfile") === from)
|
|
129
|
+
setSetting("activeProfile", to);
|
|
130
|
+
return { ok: true, from, to, aliases: plan.aliases, profiles: plan.profiles };
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export { isValidProfileId, defaultProfilesDir, defaultProfilesConfigFile, loadProfileConfigFrom, saveProfileConfigTo, reclaimAlias, planProfileRename, applyProfileRename };
|
package/dist/cli.js
CHANGED
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import {
|
|
3
3
|
startProxyServer
|
|
4
|
-
} from "./cli-
|
|
5
|
-
import"./cli-
|
|
4
|
+
} from "./cli-p5zbk952.js";
|
|
5
|
+
import"./cli-82e2m44k.js";
|
|
6
|
+
import"./cli-dh0a1bw4.js";
|
|
7
|
+
import"./cli-8sw5wr9j.js";
|
|
8
|
+
import"./cli-grfp0s1j.js";
|
|
6
9
|
import"./cli-sry5aqdj.js";
|
|
7
|
-
import"./cli-
|
|
10
|
+
import"./cli-p9ca4p13.js";
|
|
8
11
|
import {
|
|
9
12
|
resolveClaudeExecutableAsync
|
|
10
|
-
} from "./cli-
|
|
11
|
-
import"./cli-
|
|
12
|
-
import"./cli-
|
|
13
|
-
import"./cli-
|
|
13
|
+
} from "./cli-2h3w5n6g.js";
|
|
14
|
+
import"./cli-chsp880k.js";
|
|
15
|
+
import"./cli-1jstkdj9.js";
|
|
16
|
+
import"./cli-qpfky8wy.js";
|
|
17
|
+
import"./cli-eehk3052.js";
|
|
14
18
|
import {
|
|
15
19
|
__require
|
|
16
20
|
} from "./cli-p9swy5t3.js";
|
|
@@ -35,6 +39,7 @@ Usage: meridian [command] [options]
|
|
|
35
39
|
|
|
36
40
|
Commands:
|
|
37
41
|
(default) Start the proxy server
|
|
42
|
+
status Show what a running instance is doing (the / page, in the terminal)
|
|
38
43
|
setup Configure the OpenCode plugin (run once after install)
|
|
39
44
|
profile Manage Claude account profiles (add, list, switch, remove)
|
|
40
45
|
refresh-token Refresh the Claude Code OAuth token
|
|
@@ -60,7 +65,7 @@ See https://github.com/rynfar/meridian for full documentation.`);
|
|
|
60
65
|
process.exit(0);
|
|
61
66
|
}
|
|
62
67
|
if (args[0] === "profile") {
|
|
63
|
-
const { profileAdd, profileAddOauthToken, profileList, profileRemove, profileSwitch, profileLogin, profileHelp } = await import("./profileCli-
|
|
68
|
+
const { profileAdd, profileAddOauthToken, profileList, profileRemove, profileRename, profileSwitch, profileLogin, profileHelp } = await import("./profileCli-1bfgc05h.js");
|
|
64
69
|
const subcommand = args[1];
|
|
65
70
|
const profileId = args[2];
|
|
66
71
|
const headless = args.includes("--headless");
|
|
@@ -76,6 +81,8 @@ if (args[0] === "profile") {
|
|
|
76
81
|
profileList();
|
|
77
82
|
else if (subcommand === "remove" && profileId)
|
|
78
83
|
profileRemove(profileId);
|
|
84
|
+
else if (subcommand === "rename" && profileId && args[3])
|
|
85
|
+
profileRename(profileId, args[3]);
|
|
79
86
|
else if (subcommand === "switch" && profileId)
|
|
80
87
|
await profileSwitch(profileId);
|
|
81
88
|
else if (subcommand === "login" && profileId)
|
|
@@ -93,7 +100,7 @@ if (args[0] === "setup") {
|
|
|
93
100
|
runSetup,
|
|
94
101
|
SUPPORTED_OPENCODE_V2_VERSIONS,
|
|
95
102
|
UnparseableConfigError
|
|
96
|
-
} = await import("./setup-
|
|
103
|
+
} = await import("./setup-7fr49z92.js");
|
|
97
104
|
const forceV1 = args.includes("--v1");
|
|
98
105
|
const forceV2 = args.includes("--v2");
|
|
99
106
|
if (forceV1 && forceV2) {
|
|
@@ -172,7 +179,7 @@ Restart OpenCode for the plugin to take effect.`);
|
|
|
172
179
|
process.exit(0);
|
|
173
180
|
}
|
|
174
181
|
if (args[0] === "refresh-token") {
|
|
175
|
-
const { refreshOAuthToken } = await import("./tokenRefresh-
|
|
182
|
+
const { refreshOAuthToken } = await import("./tokenRefresh-eg9h83wd.js");
|
|
176
183
|
const success = await refreshOAuthToken();
|
|
177
184
|
if (success) {
|
|
178
185
|
console.log("Token refreshed successfully");
|
|
@@ -189,6 +196,23 @@ var host = process.env.MERIDIAN_HOST ?? process.env.CLAUDE_PROXY_HOST ?? "127.0.
|
|
|
189
196
|
var idleTimeoutSeconds = parseInt(process.env.MERIDIAN_IDLE_TIMEOUT_SECONDS ?? process.env.CLAUDE_PROXY_IDLE_TIMEOUT_SECONDS ?? "120", 10);
|
|
190
197
|
var pluginDir = process.env.MERIDIAN_PLUGIN_DIR;
|
|
191
198
|
var pluginConfigPath = process.env.MERIDIAN_PLUGIN_CONFIG;
|
|
199
|
+
async function printRunningInstance() {
|
|
200
|
+
const { probeMeridian } = await import("./statusProbe-9x9q261e.js");
|
|
201
|
+
const result = await probeMeridian(host, port, { apiKey: process.env.MERIDIAN_API_KEY });
|
|
202
|
+
if (result.kind === "meridian") {
|
|
203
|
+
const { renderCliDashboard } = await import("./cliDashboard-c0dvkj4y.js");
|
|
204
|
+
process.stdout.write(renderCliDashboard({ host, port, ...result.snapshot }, { color: process.stdout.isTTY === true }));
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
if (args[0] === "status") {
|
|
209
|
+
const result = await printRunningInstance();
|
|
210
|
+
if (result.kind === "meridian")
|
|
211
|
+
process.exit(0);
|
|
212
|
+
const { formatStatusMessage } = await import("./statusProbe-9x9q261e.js");
|
|
213
|
+
console.error(formatStatusMessage(result, host, port));
|
|
214
|
+
process.exit(1);
|
|
215
|
+
}
|
|
192
216
|
var profiles;
|
|
193
217
|
var defaultProfile;
|
|
194
218
|
try {
|
|
@@ -205,7 +229,7 @@ async function runCli(start = startProxyServer, runAuthCheck = async () => {
|
|
|
205
229
|
return execFile(claudePath, ["auth", "status"], { timeout: 5000 });
|
|
206
230
|
}) {
|
|
207
231
|
try {
|
|
208
|
-
const { findOpencodeConfigPath, checkPluginConfigured, findPluginPath } = await import("./setup-
|
|
232
|
+
const { findOpencodeConfigPath, checkPluginConfigured, findPluginPath } = await import("./setup-7fr49z92.js");
|
|
209
233
|
const configPath = findOpencodeConfigPath();
|
|
210
234
|
const { existsSync } = await import("fs");
|
|
211
235
|
if (existsSync(configPath) && !checkPluginConfigured(configPath)) {
|
|
@@ -230,9 +254,11 @@ async function runCli(start = startProxyServer, runAuthCheck = async () => {
|
|
|
230
254
|
console.error("\x1B[33m⚠ Could not verify Claude auth status. If requests fail, run: claude login\x1B[0m");
|
|
231
255
|
}
|
|
232
256
|
if (!profiles) {
|
|
233
|
-
const { enableDiskProfileDiscovery } = await import("./profiles-
|
|
257
|
+
const { enableDiskProfileDiscovery } = await import("./profiles-0mp32ek9.js");
|
|
234
258
|
enableDiskProfileDiscovery();
|
|
235
259
|
}
|
|
260
|
+
const { enableOrganizationLookup } = await import("./organizationName-90f0atkn.js");
|
|
261
|
+
enableOrganizationLookup();
|
|
236
262
|
const proxy = await start({ port, host, idleTimeoutSeconds, pluginDir, pluginConfigPath, profiles, defaultProfile, version, installProcessErrorHandlers: true });
|
|
237
263
|
proxy.server.on("error", (error) => {
|
|
238
264
|
if (error.code === "EADDRINUSE") {
|
|
@@ -258,6 +284,15 @@ async function runCli(start = startProxyServer, runAuthCheck = async () => {
|
|
|
258
284
|
process.on("SIGINT", handleShutdownSignal);
|
|
259
285
|
}
|
|
260
286
|
if (__require.main == __require.module) {
|
|
287
|
+
const { isPortAvailable } = await import("./statusProbe-9x9q261e.js");
|
|
288
|
+
if (!await isPortAvailable(host, port)) {
|
|
289
|
+
const result = await printRunningInstance();
|
|
290
|
+
if (result.kind === "meridian")
|
|
291
|
+
process.exit(0);
|
|
292
|
+
const { formatConflictMessage } = await import("./statusProbe-9x9q261e.js");
|
|
293
|
+
console.error(formatConflictMessage(result, host, port));
|
|
294
|
+
process.exit(1);
|
|
295
|
+
}
|
|
261
296
|
await runCli();
|
|
262
297
|
}
|
|
263
298
|
export {
|
|
@@ -0,0 +1,325 @@
|
|
|
1
|
+
import {
|
|
2
|
+
WINDOW_LABELS,
|
|
3
|
+
classifyUtilization,
|
|
4
|
+
computeWeeklyPace,
|
|
5
|
+
formatResetCountdown
|
|
6
|
+
} from "./cli-3zwfvexc.js";
|
|
7
|
+
import"./cli-p9swy5t3.js";
|
|
8
|
+
|
|
9
|
+
// src/telemetry/cliDashboard.ts
|
|
10
|
+
var PALETTE = {
|
|
11
|
+
green: 71,
|
|
12
|
+
yellow: 178,
|
|
13
|
+
red: 203,
|
|
14
|
+
muted: 246,
|
|
15
|
+
accent: 75
|
|
16
|
+
};
|
|
17
|
+
var colorPaint = (text, color) => `\x1B[38;5;${PALETTE[color]}m${text}\x1B[0m`;
|
|
18
|
+
var plainPaint = (text) => text;
|
|
19
|
+
var UNKNOWN = "—";
|
|
20
|
+
function isNum(v) {
|
|
21
|
+
return typeof v === "number" && Number.isFinite(v);
|
|
22
|
+
}
|
|
23
|
+
function usd(v) {
|
|
24
|
+
if (!isNum(v))
|
|
25
|
+
return UNKNOWN;
|
|
26
|
+
if (v > 0 && v < 0.01)
|
|
27
|
+
return `$${v.toFixed(4)}`;
|
|
28
|
+
if (v < 100)
|
|
29
|
+
return `$${v.toFixed(2)}`;
|
|
30
|
+
return `$${Math.round(v).toLocaleString("en-US")}`;
|
|
31
|
+
}
|
|
32
|
+
function tokens(v) {
|
|
33
|
+
if (!isNum(v))
|
|
34
|
+
return UNKNOWN;
|
|
35
|
+
if (v >= 1e6)
|
|
36
|
+
return `${(v / 1e6).toFixed(1)}M`;
|
|
37
|
+
if (v >= 1000)
|
|
38
|
+
return `${(v / 1000).toFixed(1)}k`;
|
|
39
|
+
return String(v);
|
|
40
|
+
}
|
|
41
|
+
function millis(v) {
|
|
42
|
+
if (!isNum(v) || v === 0)
|
|
43
|
+
return UNKNOWN;
|
|
44
|
+
return v < 1000 ? `${v}ms` : `${(v / 1000).toFixed(1)}s`;
|
|
45
|
+
}
|
|
46
|
+
function windowLabel(type) {
|
|
47
|
+
const known = WINDOW_LABELS[type];
|
|
48
|
+
if (known)
|
|
49
|
+
return known;
|
|
50
|
+
return type.replace(/^seven_day_/, "7d ").replace(/_/g, " ").replace(/\b\w/g, (c) => c.toUpperCase());
|
|
51
|
+
}
|
|
52
|
+
function utilizationColor(utilization) {
|
|
53
|
+
const status = classifyUtilization(utilization);
|
|
54
|
+
return status === "high" ? "red" : status === "warn" ? "yellow" : "green";
|
|
55
|
+
}
|
|
56
|
+
function paceStatus(pace) {
|
|
57
|
+
return pace.projectedPct != null && pace.projectedPct >= 100 ? "over" : pace.status;
|
|
58
|
+
}
|
|
59
|
+
function paceColor(status) {
|
|
60
|
+
return status === "over" ? "red" : status === "ahead" ? "yellow" : "green";
|
|
61
|
+
}
|
|
62
|
+
var BAR_WIDTH = 28;
|
|
63
|
+
var BAR_FILL = "█";
|
|
64
|
+
var BAR_TRACK = "░";
|
|
65
|
+
var BAR_MARKER = "┃";
|
|
66
|
+
function clampPct(pct) {
|
|
67
|
+
return Math.max(0, Math.min(100, pct));
|
|
68
|
+
}
|
|
69
|
+
function renderBar(pct, color, paint, markerPct) {
|
|
70
|
+
const filled = Math.round(clampPct(pct) / 100 * BAR_WIDTH);
|
|
71
|
+
const marker = markerPct == null ? -1 : Math.min(Math.round(clampPct(markerPct) / 100 * BAR_WIDTH), BAR_WIDTH - 1);
|
|
72
|
+
const cells = [];
|
|
73
|
+
for (let i2 = 0;i2 < BAR_WIDTH; i2++) {
|
|
74
|
+
if (i2 === marker)
|
|
75
|
+
cells.push({ ch: BAR_MARKER, role: "marker" });
|
|
76
|
+
else if (i2 < filled)
|
|
77
|
+
cells.push({ ch: BAR_FILL, role: "fill" });
|
|
78
|
+
else
|
|
79
|
+
cells.push({ ch: BAR_TRACK, role: "track" });
|
|
80
|
+
}
|
|
81
|
+
let out = "";
|
|
82
|
+
let i = 0;
|
|
83
|
+
while (i < cells.length) {
|
|
84
|
+
const role = cells[i].role;
|
|
85
|
+
let run = "";
|
|
86
|
+
while (i < cells.length && cells[i].role === role) {
|
|
87
|
+
run += cells[i].ch;
|
|
88
|
+
i++;
|
|
89
|
+
}
|
|
90
|
+
out += role === "fill" ? paint(run, color) : role === "track" ? paint(run, "muted") : run;
|
|
91
|
+
}
|
|
92
|
+
return out;
|
|
93
|
+
}
|
|
94
|
+
function buildAccounts(input, now) {
|
|
95
|
+
const byProfile = input.summary?.costEstimate?.byProfile ?? {};
|
|
96
|
+
const quotaByProfile = {};
|
|
97
|
+
for (const entry of input.quota?.profiles ?? []) {
|
|
98
|
+
quotaByProfile[entry.id || entry.profile || "default"] = entry.windows ?? [];
|
|
99
|
+
}
|
|
100
|
+
const configured = input.profileList?.profiles ?? [];
|
|
101
|
+
const candidates = [];
|
|
102
|
+
if (configured.length > 0) {
|
|
103
|
+
for (const p of configured) {
|
|
104
|
+
const id = p.id ?? "default";
|
|
105
|
+
candidates.push({ id, label: id, isActive: p.isActive === true, configured: true });
|
|
106
|
+
}
|
|
107
|
+
} else {
|
|
108
|
+
const auth = input.health?.auth;
|
|
109
|
+
const email = auth?.loggedIn && auth.email || "";
|
|
110
|
+
const seen = new Set;
|
|
111
|
+
for (const key of [...Object.keys(quotaByProfile), ...Object.keys(byProfile)]) {
|
|
112
|
+
if (seen.has(key))
|
|
113
|
+
continue;
|
|
114
|
+
seen.add(key);
|
|
115
|
+
candidates.push({
|
|
116
|
+
id: key,
|
|
117
|
+
label: key === "default" ? email || "account" : key,
|
|
118
|
+
isActive: false,
|
|
119
|
+
configured: false
|
|
120
|
+
});
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const isPriority = input.profileList?.routing === "priority";
|
|
124
|
+
const blocks = [];
|
|
125
|
+
for (const candidate of candidates) {
|
|
126
|
+
const cost = byProfile[candidate.id];
|
|
127
|
+
const windows = (quotaByProfile[candidate.id] ?? []).filter((w) => w.utilization != null);
|
|
128
|
+
if (!candidate.configured && windows.length === 0 && !cost)
|
|
129
|
+
continue;
|
|
130
|
+
const rows = [];
|
|
131
|
+
for (const w of windows) {
|
|
132
|
+
const utilization = w.utilization;
|
|
133
|
+
if (!isNum(utilization))
|
|
134
|
+
continue;
|
|
135
|
+
rows.push({
|
|
136
|
+
label: windowLabel(w.type ?? ""),
|
|
137
|
+
pct: Math.round(utilization * 100),
|
|
138
|
+
figure: `${Math.round(utilization * 100)}%`,
|
|
139
|
+
color: utilizationColor(utilization),
|
|
140
|
+
note: formatResetCountdown(w.resetsAt, now)
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
let weekly;
|
|
144
|
+
for (const w of windows)
|
|
145
|
+
if (w.type === "seven_day")
|
|
146
|
+
weekly = w;
|
|
147
|
+
const pace = weekly ? computeWeeklyPace(weekly.utilization, weekly.resetsAt, now) : null;
|
|
148
|
+
if (pace) {
|
|
149
|
+
const status = paceStatus(pace);
|
|
150
|
+
const projected = pace.projectedPct;
|
|
151
|
+
const figure = status === "over" ? projected != null ? `${projected}%` : "100%" : `${pace.deltaPct >= 0 ? "+" : "-"}${Math.abs(pace.deltaPct)}%`;
|
|
152
|
+
rows.push({
|
|
153
|
+
label: "pace",
|
|
154
|
+
pct: pace.actualPct,
|
|
155
|
+
markerPct: pace.expectedPct,
|
|
156
|
+
figure,
|
|
157
|
+
color: paceColor(status),
|
|
158
|
+
note: status === "over" ? "runs out before reset" : projected != null ? `~${projected}% by reset` : ""
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
const badges = [];
|
|
162
|
+
if (isPriority) {
|
|
163
|
+
const order = input.profileList?.profileOrder ?? [];
|
|
164
|
+
const idx = order.indexOf(candidate.id);
|
|
165
|
+
if (idx >= 0)
|
|
166
|
+
badges.push({ text: `#${idx + 1} in pool`, color: "muted" });
|
|
167
|
+
const exhausted = (input.profileList?.exhausted ?? []).find((e) => e.id === candidate.id);
|
|
168
|
+
if (exhausted) {
|
|
169
|
+
badges.push({
|
|
170
|
+
text: `exhausted · resets ${formatResetCountdown(exhausted.until, now)}`,
|
|
171
|
+
color: "red"
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
} else if (candidate.isActive) {
|
|
175
|
+
badges.push({ text: "ACTIVE", color: "accent" });
|
|
176
|
+
}
|
|
177
|
+
const requests = cost?.requests;
|
|
178
|
+
blocks.push({
|
|
179
|
+
label: candidate.label,
|
|
180
|
+
isActive: candidate.isActive,
|
|
181
|
+
badges,
|
|
182
|
+
cost: usd(cost ? cost.estimatedUsd : 0),
|
|
183
|
+
sub: isNum(requests) ? `${requests} request${requests === 1 ? "" : "s"} · est. API value · 24h` : "no traffic · 24h",
|
|
184
|
+
rows
|
|
185
|
+
});
|
|
186
|
+
}
|
|
187
|
+
return blocks;
|
|
188
|
+
}
|
|
189
|
+
function buildStrip(summary) {
|
|
190
|
+
const tu = summary.tokenUsage ?? {};
|
|
191
|
+
const hitRate = tu.avgCacheHitRate;
|
|
192
|
+
const errors = summary.errorCount;
|
|
193
|
+
const items = [
|
|
194
|
+
{
|
|
195
|
+
label: "Requests",
|
|
196
|
+
value: isNum(summary.totalRequests) ? String(summary.totalRequests) : UNKNOWN,
|
|
197
|
+
detail: !isNum(errors) ? UNKNOWN : errors > 0 ? `${errors} error${errors === 1 ? "" : "s"}` : "no errors",
|
|
198
|
+
detailColor: isNum(errors) && errors > 0 ? "red" : undefined
|
|
199
|
+
},
|
|
200
|
+
{
|
|
201
|
+
label: "Tokens Out",
|
|
202
|
+
value: tokens(tu.totalOutputTokens),
|
|
203
|
+
detail: `${tokens(tu.totalInputTokens)} in`
|
|
204
|
+
},
|
|
205
|
+
{
|
|
206
|
+
label: "Cache Hit",
|
|
207
|
+
value: isNum(hitRate) ? `${Math.round(hitRate * 100)}%` : UNKNOWN,
|
|
208
|
+
valueColor: isNum(hitRate) && hitRate >= 0.5 ? "green" : undefined,
|
|
209
|
+
detail: "prompt cache"
|
|
210
|
+
},
|
|
211
|
+
{
|
|
212
|
+
label: "Est. API Value",
|
|
213
|
+
value: usd(summary.costEstimate?.totalUsd),
|
|
214
|
+
detail: "list prices"
|
|
215
|
+
},
|
|
216
|
+
{
|
|
217
|
+
label: "Median Response",
|
|
218
|
+
value: millis(summary.totalDuration?.p50),
|
|
219
|
+
detail: `p95 ${millis(summary.totalDuration?.p95)}`
|
|
220
|
+
}
|
|
221
|
+
];
|
|
222
|
+
const violations = summary.envelopeViolationCount;
|
|
223
|
+
if (isNum(violations) && violations > 0) {
|
|
224
|
+
items.push({
|
|
225
|
+
label: "Envelope",
|
|
226
|
+
value: String(violations),
|
|
227
|
+
valueColor: "red",
|
|
228
|
+
detail: "wire-contract violations",
|
|
229
|
+
detailColor: "red"
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
return items;
|
|
233
|
+
}
|
|
234
|
+
function healthPill(health) {
|
|
235
|
+
const status = health?.status;
|
|
236
|
+
if (status === "healthy")
|
|
237
|
+
return { label: "Operational", color: "green" };
|
|
238
|
+
if (status === "degraded")
|
|
239
|
+
return { label: "Degraded", color: "yellow" };
|
|
240
|
+
return { label: "Offline", color: "red" };
|
|
241
|
+
}
|
|
242
|
+
function activeProfileChip(profileList) {
|
|
243
|
+
const active = (profileList?.profiles ?? []).find((p) => p.isActive === true);
|
|
244
|
+
if (!active?.id)
|
|
245
|
+
return null;
|
|
246
|
+
return active.type ? `${active.id} ${active.type}` : active.id;
|
|
247
|
+
}
|
|
248
|
+
var INDENT = " ";
|
|
249
|
+
function renderCliDashboard(input, options = {}) {
|
|
250
|
+
const paint = options.color ? colorPaint : plainPaint;
|
|
251
|
+
const bold = options.color ? (t) => `\x1B[1m${t}\x1B[22m` : (t) => t;
|
|
252
|
+
const now = input.now ?? Date.now();
|
|
253
|
+
const out = [];
|
|
254
|
+
const pill = healthPill(input.health);
|
|
255
|
+
const chip = activeProfileChip(input.profileList);
|
|
256
|
+
out.push(`${bold("MERIDIAN")} ${paint("●", pill.color)} ${pill.label}` + (chip ? ` ${paint("·", "muted")} ${chip}` : ""));
|
|
257
|
+
out.push("");
|
|
258
|
+
out.push(`${INDENT}ANTHROPIC_BASE_URL=http://${input.host}:${input.port}`);
|
|
259
|
+
const meta = [];
|
|
260
|
+
const auth = input.health?.auth;
|
|
261
|
+
if (auth?.loggedIn) {
|
|
262
|
+
meta.push(`${auth.email ?? ""}${auth.subscriptionType ? ` (${auth.subscriptionType})` : ""}`);
|
|
263
|
+
}
|
|
264
|
+
meta.push(input.health?.mode ?? "internal");
|
|
265
|
+
meta.push(`port ${input.port}`);
|
|
266
|
+
out.push(`${INDENT}${paint(meta.join(" · "), "muted")}`);
|
|
267
|
+
out.push("");
|
|
268
|
+
const accounts = buildAccounts(input, now);
|
|
269
|
+
const accountsNote = input.unavailable?.accounts;
|
|
270
|
+
if (accounts.length > 0 || accountsNote) {
|
|
271
|
+
out.push(paint(accounts.length === 1 ? "ACCOUNT" : "ACCOUNTS", "muted"));
|
|
272
|
+
out.push("");
|
|
273
|
+
if (accountsNote) {
|
|
274
|
+
out.push(`${INDENT}${paint(accountsNote, "yellow")}`);
|
|
275
|
+
out.push("");
|
|
276
|
+
}
|
|
277
|
+
const allRows = accounts.flatMap((a) => a.rows);
|
|
278
|
+
const labelWidth = Math.max(0, ...allRows.map((r) => r.label.length));
|
|
279
|
+
const figureWidth = Math.max(0, ...allRows.map((r) => r.figure.length));
|
|
280
|
+
const costColumn = INDENT.length + 2 + labelWidth + 2 + BAR_WIDTH + 2 + figureWidth;
|
|
281
|
+
for (const account of accounts) {
|
|
282
|
+
const dot = paint("●", account.isActive ? "accent" : "muted");
|
|
283
|
+
const badges = account.badges.map((b) => b.color ? paint(b.text, b.color) : b.text).join(" ");
|
|
284
|
+
const headLeft = `${account.label}${badges ? ` ${badges}` : ""}`;
|
|
285
|
+
const headLeftPlain = account.label + (account.badges.length > 0 ? ` ${account.badges.map((b) => b.text).join(" ")}` : "");
|
|
286
|
+
const gap = Math.max(1, costColumn - INDENT.length - 2 - headLeftPlain.length - account.cost.length);
|
|
287
|
+
out.push(`${INDENT}${dot} ${headLeft}${" ".repeat(gap)}${bold(account.cost)}`);
|
|
288
|
+
out.push(`${INDENT} ${paint(account.sub, "muted")}`);
|
|
289
|
+
if (account.rows.length === 0) {
|
|
290
|
+
out.push(`${INDENT} ${paint("no usage data yet", "muted")}`);
|
|
291
|
+
}
|
|
292
|
+
for (const row of account.rows) {
|
|
293
|
+
const label = row.label.padEnd(labelWidth);
|
|
294
|
+
const bar = renderBar(row.pct, row.color, paint, row.markerPct);
|
|
295
|
+
const figure = row.figure.padStart(figureWidth);
|
|
296
|
+
const note = row.note ? ` ${paint(row.note, "muted")}` : "";
|
|
297
|
+
out.push(`${INDENT} ${paint(label, "muted")} ${bar} ${paint(figure, row.color)}${note}`);
|
|
298
|
+
}
|
|
299
|
+
out.push("");
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
const trafficNote = input.unavailable?.traffic;
|
|
303
|
+
out.push(paint("LAST 24 HOURS", "muted"));
|
|
304
|
+
out.push("");
|
|
305
|
+
if (trafficNote) {
|
|
306
|
+
out.push(`${INDENT}${paint(trafficNote, "yellow")}`);
|
|
307
|
+
} else {
|
|
308
|
+
const items = buildStrip(input.summary ?? {});
|
|
309
|
+
const labelWidth = Math.max(...items.map((i) => i.label.length));
|
|
310
|
+
const valueWidth = Math.max(...items.map((i) => i.value.length));
|
|
311
|
+
for (const item of items) {
|
|
312
|
+
const label = paint(item.label.padEnd(labelWidth), "muted");
|
|
313
|
+
const valuePlain = item.value.padStart(valueWidth);
|
|
314
|
+
const value = item.valueColor ? paint(valuePlain, item.valueColor) : valuePlain;
|
|
315
|
+
const detail = item.detailColor ? paint(item.detail, item.detailColor) : paint(item.detail, "muted");
|
|
316
|
+
out.push(`${INDENT}${label} ${value} ${detail}`);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
return `${out.join(`
|
|
320
|
+
`)}
|
|
321
|
+
`;
|
|
322
|
+
}
|
|
323
|
+
export {
|
|
324
|
+
renderCliDashboard
|
|
325
|
+
};
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where Meridian keeps its own configuration.
|
|
3
|
+
*
|
|
4
|
+
* One directory holds everything Meridian persists for itself — settings.json,
|
|
5
|
+
* profiles.json, the per-profile CLAUDE_CONFIG_DIRs under profiles/,
|
|
6
|
+
* adapter-instances.json, sdk-features.json, model-pricing.json, telemetry.db.
|
|
7
|
+
* `MERIDIAN_CONFIG_DIR` moves that directory, so a second instance pointed at
|
|
8
|
+
* an empty one gets its own everything rather than inheriting the first
|
|
9
|
+
* instance's accounts.
|
|
10
|
+
*
|
|
11
|
+
* Resolved per call, never frozen at import time. A module-level constant is
|
|
12
|
+
* computed before the CLI has parsed argv or a test has set the variable, and
|
|
13
|
+
* can then be changed by neither.
|
|
14
|
+
*
|
|
15
|
+
* NOTE: deliberately does NOT honour XDG_CONFIG_HOME — anyone who has that set
|
|
16
|
+
* would silently relocate to a different config directory and appear to lose
|
|
17
|
+
* everything in it.
|
|
18
|
+
*
|
|
19
|
+
* NOTE: read straight from process.env rather than through env.ts, which would
|
|
20
|
+
* also accept a CLAUDE_PROXY_CONFIG_DIR alias. This variable postdates that
|
|
21
|
+
* prefix, so there is no legacy deployment to stay compatible with and no
|
|
22
|
+
* reason to start accepting a second name for it.
|
|
23
|
+
*/
|
|
24
|
+
/** The directory used when MERIDIAN_CONFIG_DIR is unset. */
|
|
25
|
+
export declare function defaultConfigDir(): string;
|
|
26
|
+
/** The directory Meridian's configuration lives in. */
|
|
27
|
+
export declare function configDir(): string;
|
|
28
|
+
/** A path inside the config directory, e.g. `configPath("profiles.json")`. */
|
|
29
|
+
export declare function configPath(...segments: string[]): string;
|
|
30
|
+
//# sourceMappingURL=configDir.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"configDir.d.ts","sourceRoot":"","sources":["../src/configDir.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAKH,4DAA4D;AAC5D,wBAAgB,gBAAgB,IAAI,MAAM,CAEzC;AAED,uDAAuD;AACvD,wBAAgB,SAAS,IAAI,MAAM,CAElC;AAED,8EAA8E;AAC9E,wBAAgB,UAAU,CAAC,GAAG,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,CAExD"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import {
|
|
2
|
+
ORGANIZATION_REFRESH_AFTER_MS,
|
|
3
|
+
ORGANIZATION_RETRY_AFTER_MS,
|
|
4
|
+
enableOrganizationLookup,
|
|
5
|
+
extractOrganizationName,
|
|
6
|
+
fetchOrganizationName,
|
|
7
|
+
organizationNames,
|
|
8
|
+
organizationNeedsRefresh,
|
|
9
|
+
readOrganizations,
|
|
10
|
+
refreshOrganizationNameSoon,
|
|
11
|
+
rememberOrganizationName,
|
|
12
|
+
resetOrganizationLookupForTesting
|
|
13
|
+
} from "./cli-8sw5wr9j.js";
|
|
14
|
+
import"./cli-chsp880k.js";
|
|
15
|
+
import"./cli-1jstkdj9.js";
|
|
16
|
+
import"./cli-p9swy5t3.js";
|
|
17
|
+
export {
|
|
18
|
+
resetOrganizationLookupForTesting,
|
|
19
|
+
rememberOrganizationName,
|
|
20
|
+
refreshOrganizationNameSoon,
|
|
21
|
+
readOrganizations,
|
|
22
|
+
organizationNeedsRefresh,
|
|
23
|
+
organizationNames,
|
|
24
|
+
fetchOrganizationName,
|
|
25
|
+
extractOrganizationName,
|
|
26
|
+
enableOrganizationLookup,
|
|
27
|
+
ORGANIZATION_RETRY_AFTER_MS,
|
|
28
|
+
ORGANIZATION_REFRESH_AFTER_MS
|
|
29
|
+
};
|