@moxxy/plugin-provider-admin 0.26.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/index.js ADDED
@@ -0,0 +1,520 @@
1
+ import { createMutex, defineTool, definePlugin, MoxxyError, z, } from '@moxxy/sdk';
2
+ import { buildProviderDef, validateOpenAICompatKey } from './factory.js';
3
+ import { providerApiKeyName } from './key-name.js';
4
+ import { providersConfigPath, readProvidersConfig, removeStoredProvider, upsertStoredProvider, } from './store.js';
5
+ /**
6
+ * `AppContext` doesn't declare a `logger` (warnings are best-effort), but some
7
+ * hosts attach one. Narrow with a runtime guard rather than asserting its shape
8
+ * via a blanket cast, so a non-conforming `logger` is simply ignored.
9
+ */
10
+ function getWarnLogger(ctx) {
11
+ if (typeof ctx !== 'object' || ctx === null)
12
+ return undefined;
13
+ const candidate = ctx.logger;
14
+ if (typeof candidate === 'object' && candidate !== null && typeof candidate.warn === 'function') {
15
+ return candidate;
16
+ }
17
+ return undefined;
18
+ }
19
+ export { providersConfigPath, readProvidersConfig, upsertStoredProvider, removeStoredProvider };
20
+ export { buildProviderDef, validateOpenAICompatKey } from './factory.js';
21
+ export { providerApiKeyName, storedProviderApiKeyName } from './key-name.js';
22
+ const PROVIDER_NAME_RE = /^[a-z][a-z0-9-]*$/;
23
+ const providerNameSchema = z
24
+ .string()
25
+ .min(1)
26
+ .max(60)
27
+ .regex(PROVIDER_NAME_RE, 'name must be slug-like (lowercase letters, digits, hyphens; must start with a letter)');
28
+ const ENV_VAR_RE = /^[A-Z][A-Z0-9_]*$/;
29
+ /**
30
+ * Defense-in-depth check on a vendor base URL before the OpenAI SDK probes it
31
+ * with a Bearer key. The permission prompt is the primary gate, but a base URL
32
+ * a user might not scrutinize should not be able to point a stored credential
33
+ * at an arbitrary host. We require https (allowing http only for explicit
34
+ * localhost) and reject link-local / cloud-metadata addresses (SSRF + key
35
+ * egress). The threat model treats baseURL as operator-controlled; this is a
36
+ * backstop, not the trust boundary.
37
+ */
38
+ function isSafeBaseURL(value) {
39
+ let url;
40
+ try {
41
+ url = new URL(value);
42
+ }
43
+ catch {
44
+ return false;
45
+ }
46
+ const host = url.hostname.toLowerCase();
47
+ const isLocalhost = host === 'localhost' || host === '127.0.0.1' || host === '::1' || host === '[::1]';
48
+ if (url.protocol === 'http:')
49
+ return isLocalhost;
50
+ if (url.protocol !== 'https:')
51
+ return false;
52
+ // `localhost` over https is the only allowed loopback name; everything below
53
+ // operates on the WHATWG-canonicalized host (decimal/hex/octal IPv4 forms are
54
+ // already folded to dotted-decimal, so a `169.254.x` / private prefix can't be
55
+ // smuggled as `https://2852039166/v1`).
56
+ // Block loopback, link-local / metadata, unspecified, AND RFC1918 private
57
+ // ranges even over https — a stored Bearer credential must not be egressable
58
+ // to an internal/metadata host via a base URL the user might not scrutinize.
59
+ if (host === 'localhost' ||
60
+ host.startsWith('127.') || // IPv4 loopback 127.0.0.0/8
61
+ host.startsWith('169.254.') || // IPv4 link-local incl. cloud metadata 169.254.169.254
62
+ host.startsWith('0.') || // "this" network 0.0.0.0/8
63
+ host === '0.0.0.0' ||
64
+ host.startsWith('10.') || // RFC1918 10.0.0.0/8
65
+ host.startsWith('192.168.') || // RFC1918 192.168.0.0/16
66
+ isPrivate172(host) || // RFC1918 172.16.0.0/12
67
+ host === '::1' ||
68
+ host === '[::1]' || // IPv6 loopback
69
+ host.startsWith('[fe80:') || // IPv6 link-local
70
+ host.startsWith('[fc') || // IPv6 unique-local fc00::/7
71
+ host.startsWith('[fd')) {
72
+ return false;
73
+ }
74
+ return true;
75
+ }
76
+ /** True for a dotted-decimal IPv4 host in the RFC1918 172.16.0.0/12 range. */
77
+ function isPrivate172(host) {
78
+ const m = /^172\.(\d{1,3})\./.exec(host);
79
+ if (!m)
80
+ return false;
81
+ const octet = Number(m[1]);
82
+ return octet >= 16 && octet <= 31;
83
+ }
84
+ const safeBaseURLSchema = z
85
+ .string()
86
+ .url()
87
+ .refine(isSafeBaseURL, {
88
+ message: 'baseURL must be an https URL (or http://localhost). file://, ftp://, link-local and ' +
89
+ 'cloud-metadata addresses are rejected to prevent credential egress / SSRF.',
90
+ });
91
+ const modelDescriptorSchema = z.object({
92
+ id: z.string().min(1),
93
+ contextWindow: z.number().int().positive(),
94
+ maxOutputTokens: z.number().int().positive().optional(),
95
+ supportsTools: z.boolean().default(true),
96
+ supportsStreaming: z.boolean().default(true),
97
+ supportsImages: z.boolean().optional(),
98
+ /**
99
+ * Whether the model ingests `document` blocks (native PDF etc.). Without
100
+ * this flag the desktop degrades attachments to extracted text for every
101
+ * runtime-registered provider — declare it for models that take files.
102
+ */
103
+ supportsDocuments: z.boolean().optional(),
104
+ supportsAudio: z.boolean().optional(),
105
+ }).passthrough();
106
+ const addProviderInput = z.object({
107
+ kind: z
108
+ .enum(['openai-compat'])
109
+ .default('openai-compat')
110
+ .describe('Wire-protocol family the vendor speaks. "openai-compat" reuses the moxxy ' +
111
+ 'OpenAI client against a vendor baseURL (z.ai, deepseek, groq, openrouter, …). ' +
112
+ 'Native-SDK vendors must ship as a dedicated plugin instead.'),
113
+ name: providerNameSchema.describe('Provider slug. Becomes the registry key + canonical vault entry (<NAME>_API_KEY).'),
114
+ baseURL: safeBaseURLSchema.describe('Vendor API base URL, e.g. https://api.z.ai/api/coding/paas/v4.'),
115
+ defaultModel: z.string().min(1).describe('Model id used when a request does not pin one explicitly.'),
116
+ models: z
117
+ .array(modelDescriptorSchema)
118
+ .min(1)
119
+ .describe('Models the vendor exposes. Powers /model autocomplete and the setup wizard.'),
120
+ envVar: z
121
+ .string()
122
+ .regex(ENV_VAR_RE)
123
+ .optional()
124
+ .describe('Override the API-key env-var name (defaults to <NAME>_API_KEY).'),
125
+ });
126
+ const removeProviderInput = z.object({
127
+ name: providerNameSchema,
128
+ });
129
+ /**
130
+ * Validation for the `configure()` patch. `configure` is part of the exported
131
+ * ProviderAdminView contract — ANY in-process consumer (a future channel, a
132
+ * test, a plugin) can call it, not just the runner handler. The invariant must
133
+ * live where the data is persisted, so a malformed baseURL/envVar can't reach
134
+ * buildProviderDef + the vault key-name derivation through an alternate caller.
135
+ * Mirrors the runner's providerConfigureParamsSchema.patch.
136
+ */
137
+ const configurePatchSchema = z.object({
138
+ baseURL: safeBaseURLSchema.optional(),
139
+ defaultModel: z.string().min(1).optional(),
140
+ envVar: z.string().regex(ENV_VAR_RE).optional(),
141
+ models: z.array(modelDescriptorSchema).min(1).optional(),
142
+ });
143
+ const testProviderInput = z.object({
144
+ baseURL: safeBaseURLSchema.describe('Vendor API base URL to probe, e.g. https://api.deepseek.com.'),
145
+ keyName: z
146
+ .string()
147
+ .regex(ENV_VAR_RE)
148
+ .describe('NAME of the vault secret holding the API key (e.g. DEEPSEEK_API_KEY). The key is ' +
149
+ 'resolved from the vault inside the tool — never ask the user for the plaintext key ' +
150
+ 'and never pass one as a tool argument. Have them store it first: /vault set <NAME> <key>.'),
151
+ });
152
+ function createProviderAdminEngine(opts) {
153
+ const { providerRegistry, configPath, resolveActiveConfig } = opts;
154
+ const ownNames = new Set();
155
+ // Per-name mutexes, ref-counted so the map is bounded by the number of
156
+ // CONCURRENTLY-active names, not the cumulative count of every slug ever seen.
157
+ // Without the counter a model issuing many distinct provider_add/remove calls
158
+ // would grow this map without bound for the life of the runner. We can't probe
159
+ // a Mutex's queue (the interface only exposes `run`), so we track holders
160
+ // ourselves and drop the entry when the last in-flight call for a name settles.
161
+ const locks = new Map();
162
+ return {
163
+ providerRegistry,
164
+ configPath,
165
+ ownNames,
166
+ isBuiltin(name) {
167
+ return providerRegistry.list().some((p) => p.name === name) && !ownNames.has(name);
168
+ },
169
+ async withLock(name, fn) {
170
+ let slot = locks.get(name);
171
+ if (!slot) {
172
+ slot = { mutex: createMutex(), holders: 0 };
173
+ locks.set(name, slot);
174
+ }
175
+ slot.holders += 1;
176
+ try {
177
+ return await slot.mutex.run(fn);
178
+ }
179
+ finally {
180
+ slot.holders -= 1;
181
+ // Last holder out removes the entry. A name acquired again later just
182
+ // creates a fresh mutex — serialization is only ever needed between
183
+ // OVERLAPPING calls, which by definition still share this live slot.
184
+ if (slot.holders === 0 && locks.get(name) === slot)
185
+ locks.delete(name);
186
+ }
187
+ },
188
+ async rebuildActiveIfNeeded(name) {
189
+ if (!resolveActiveConfig)
190
+ return;
191
+ const activeName = providerRegistry.getActiveName?.();
192
+ if (activeName !== name)
193
+ return;
194
+ try {
195
+ const cfg = await resolveActiveConfig(name);
196
+ providerRegistry.setActive?.(name, cfg);
197
+ }
198
+ catch {
199
+ // Best-effort: a failed rebuild leaves `getActive()` throwing exactly as
200
+ // it did before this fix — never worse — and the user can re-select.
201
+ }
202
+ },
203
+ };
204
+ }
205
+ /**
206
+ * Re-register a stored provider against the live registry + persist it. The
207
+ * whole capture→mutate→persist→rollback sequence runs under the per-name lock so
208
+ * concurrent admin calls (parallel tool calls / a configure racing an add) can't
209
+ * interleave with stale prevDef snapshots. On a write failure the prior def is
210
+ * restored (or the phantom dropped) so the registry never drifts from disk.
211
+ */
212
+ async function applyStoredProvider(engine, entry) {
213
+ const { providerRegistry, configPath } = engine;
214
+ return engine.withLock(entry.name, async () => {
215
+ const def = buildProviderDef(entry);
216
+ const prevDef = providerRegistry.list().find((p) => p.name === entry.name);
217
+ const wasRegistered = prevDef !== undefined;
218
+ if (wasRegistered)
219
+ providerRegistry.replace(def);
220
+ else
221
+ providerRegistry.register(def);
222
+ engine.ownNames.add(entry.name);
223
+ try {
224
+ await upsertStoredProvider(entry, configPath);
225
+ }
226
+ catch (err) {
227
+ // Roll back the runtime registration. If a def existed before this call,
228
+ // restore it; otherwise drop the phantom + our ownership claim so the next
229
+ // boot doesn't see something that isn't on disk.
230
+ if (wasRegistered && prevDef)
231
+ providerRegistry.replace(prevDef);
232
+ else {
233
+ providerRegistry.unregister(entry.name);
234
+ engine.ownNames.delete(entry.name);
235
+ }
236
+ throw err;
237
+ }
238
+ // Replacing the active provider's def dropped its cached instance — rebuild.
239
+ if (wasRegistered)
240
+ await engine.rebuildActiveIfNeeded(entry.name);
241
+ return { replaced: wasRegistered };
242
+ });
243
+ }
244
+ /**
245
+ * Like {@link buildProviderAdminPlugin} but also returns a
246
+ * {@link ProviderAdminView} api the host can stash on the session
247
+ * (`session.providerAdmin`) so channels — and the runner's
248
+ * `provider.configure` method — can edit a stored provider without going
249
+ * through the model. Mirrors `buildMcpAdminPluginWithApi`.
250
+ */
251
+ export function buildProviderAdminPluginWithApi(opts) {
252
+ const engine = createProviderAdminEngine(opts);
253
+ const api = {
254
+ configure: async (name, patch) => {
255
+ if (engine.isBuiltin(name)) {
256
+ throw new MoxxyError({
257
+ code: 'CONFIG_INVALID',
258
+ message: `provider-admin: "${name}" is a built-in provider and cannot be reconfigured here — ` +
259
+ `built-ins are code. Only runtime-registered (providers.json) providers are editable.`,
260
+ });
261
+ }
262
+ // Defense-in-depth: validate the patch HERE (where it is persisted), not
263
+ // only at the runner boundary, so any in-process caller is covered.
264
+ const validated = configurePatchSchema.parse(patch);
265
+ const cfg = await readProvidersConfig(engine.configPath);
266
+ const entry = cfg.providers.find((p) => p.name === name);
267
+ if (!entry) {
268
+ throw new MoxxyError({
269
+ code: 'CONFIG_INVALID',
270
+ message: `provider-admin: no stored provider named "${name}" — only runtime-registered ` +
271
+ `(providers.json) providers are configurable; built-ins are code.`,
272
+ });
273
+ }
274
+ const next = {
275
+ ...entry,
276
+ ...(validated.baseURL ? { baseURL: validated.baseURL } : {}),
277
+ ...(validated.defaultModel ? { defaultModel: validated.defaultModel } : {}),
278
+ ...(validated.envVar ? { envVar: validated.envVar } : {}),
279
+ ...(validated.models && validated.models.length > 0 ? { models: validated.models } : {}),
280
+ };
281
+ if (!next.models.some((m) => m.id === next.defaultModel)) {
282
+ throw new MoxxyError({
283
+ code: 'CONFIG_INVALID',
284
+ message: `provider-admin: defaultModel "${next.defaultModel}" is not in the models list ` +
285
+ `(${next.models.map((m) => m.id).join(', ')}).`,
286
+ });
287
+ }
288
+ // Same order as provider_add: live registry first, then disk, so a failed
289
+ // write rolls back; the whole section is locked per name.
290
+ await applyStoredProvider(engine, next);
291
+ },
292
+ };
293
+ return { plugin: buildProviderAdminPlugin(opts, engine), api };
294
+ }
295
+ export function buildProviderAdminPlugin(opts, sharedEngine) {
296
+ const engine = sharedEngine ?? createProviderAdminEngine(opts);
297
+ const { providerRegistry, configPath } = engine;
298
+ return definePlugin({
299
+ name: '@moxxy/plugin-provider-admin',
300
+ version: '0.0.0',
301
+ tools: [
302
+ defineTool({
303
+ name: 'provider_add',
304
+ description: 'Register an OpenAI-compatible LLM provider (z.ai, deepseek, groq, openrouter, fireworks, ' +
305
+ 'together, mistral, …) with moxxy. Wraps the in-process OpenAI client with the vendor baseURL + ' +
306
+ 'a user-supplied models list. Persists to ~/.moxxy/providers.json so the provider survives ' +
307
+ 'restarts. The new provider is registered in the LIVE session — switch to it with /provider ' +
308
+ 'or set it as the default in moxxy.config.ts.',
309
+ inputSchema: addProviderInput,
310
+ permission: { action: 'prompt' },
311
+ handler: async (input) => {
312
+ if (engine.isBuiltin(input.name)) {
313
+ throw new MoxxyError({
314
+ code: 'CONFIG_INVALID',
315
+ message: `provider_add: "${input.name}" is a built-in provider and cannot be shadowed ` +
316
+ `or redirected. Pick a different slug for your OpenAI-compatible vendor ` +
317
+ `(e.g. "${input.name}-compat").`,
318
+ });
319
+ }
320
+ const entry = {
321
+ kind: 'openai-compat',
322
+ name: input.name,
323
+ baseURL: input.baseURL,
324
+ defaultModel: input.defaultModel,
325
+ models: input.models,
326
+ ...(input.envVar ? { envVar: input.envVar } : {}),
327
+ createdAt: new Date().toISOString(),
328
+ };
329
+ if (!entry.models.some((m) => m.id === entry.defaultModel)) {
330
+ throw new MoxxyError({
331
+ code: 'CONFIG_INVALID',
332
+ message: `provider_add: defaultModel "${entry.defaultModel}" is not in the models list. ` +
333
+ `Add it to the array or pick one of: ${entry.models.map((m) => m.id).join(', ')}.`,
334
+ });
335
+ }
336
+ const { replaced: wasRegistered } = await applyStoredProvider(engine, entry);
337
+ const vaultKeyName = providerApiKeyName(entry);
338
+ return {
339
+ ok: true,
340
+ name: entry.name,
341
+ kind: entry.kind,
342
+ baseURL: entry.baseURL,
343
+ defaultModel: entry.defaultModel,
344
+ models: entry.models.map((m) => m.id),
345
+ path: configPath ?? providersConfigPath(),
346
+ replaced: wasRegistered,
347
+ note: `Provider "${entry.name}" is live in this session. ` +
348
+ `Have the USER store the API key by running: /vault set ${vaultKeyName} <key> ` +
349
+ `— never ask them to paste the key to you. ` +
350
+ `Once stored, you can verify it with provider_test (baseURL + keyName "${vaultKeyName}") — it resolves the key from the vault itself. ` +
351
+ `Switch with the /provider command or set provider.name in moxxy.config.ts.`,
352
+ };
353
+ },
354
+ }),
355
+ defineTool({
356
+ name: 'provider_list',
357
+ description: 'List user-registered providers (persisted in ~/.moxxy/providers.json) plus their default model and base URL. ' +
358
+ 'Built-in providers (anthropic, openai, openai-codex) are NOT included — query session.providers for those.',
359
+ inputSchema: z.object({}),
360
+ handler: async () => {
361
+ const cfg = await readProvidersConfig(configPath);
362
+ return {
363
+ path: configPath ?? providersConfigPath(),
364
+ providers: cfg.providers.map((p) => ({
365
+ name: p.name,
366
+ kind: p.kind,
367
+ baseURL: p.baseURL,
368
+ defaultModel: p.defaultModel,
369
+ models: p.models.map((m) => m.id),
370
+ envVar: providerApiKeyName(p),
371
+ })),
372
+ };
373
+ },
374
+ }),
375
+ defineTool({
376
+ name: 'provider_remove',
377
+ description: 'Remove a previously-added provider from ~/.moxxy/providers.json and detach it from the live session. ' +
378
+ 'Does NOT delete the stored API key — call vault_delete name=<NAME>_API_KEY separately if you also want to drop the credential.',
379
+ inputSchema: removeProviderInput,
380
+ permission: { action: 'prompt' },
381
+ handler: async ({ name }) => {
382
+ // Removing the ACTIVE provider leaves the registry with active=null, so
383
+ // the next turn fails with a "no active provider" error. Mirror the
384
+ // setEnabled guard's intent: surface the consequence prominently
385
+ // instead of returning a cheerful ok with no warning.
386
+ const removingActive = providerRegistry.getActiveName?.() === name;
387
+ return engine.withLock(name, async () => {
388
+ const removed = await removeStoredProvider(name, configPath);
389
+ if (!removed) {
390
+ return { ok: false, name, note: `No stored provider named "${name}".` };
391
+ }
392
+ try {
393
+ providerRegistry.unregister(name);
394
+ }
395
+ catch {
396
+ // Already gone in the live registry — best effort.
397
+ }
398
+ engine.ownNames.delete(name);
399
+ const note = removingActive
400
+ ? `Removed "${name}" from providers.json and detached from session. ` +
401
+ `WARNING: "${name}" was the ACTIVE provider — the session now has NO active provider ` +
402
+ `and the next turn will fail until you switch with the /provider command.`
403
+ : `Removed "${name}" from providers.json and detached from session.`;
404
+ return { ok: true, name, removedActive: removingActive, note };
405
+ });
406
+ },
407
+ }),
408
+ defineTool({
409
+ name: 'provider_test',
410
+ description: 'Probe an OpenAI-compatible endpoint by calling /v1/models. Takes the NAME of a vault ' +
411
+ 'secret (e.g. ZAI_API_KEY) and resolves the API key via the vault inside the handler — ' +
412
+ 'the plaintext key never enters the conversation or logs. Have the USER store the key ' +
413
+ 'first with /vault set <NAME> <key>, then call this to confirm the baseURL + key are ' +
414
+ 'valid (typically before provider_add). Returns { ok: true } on success or ' +
415
+ '{ ok: false, message } with the vendor error verbatim.',
416
+ inputSchema: testProviderInput,
417
+ permission: { action: 'prompt' },
418
+ // The plaintext key is resolved HERE, at call time, via ctx.getSecret —
419
+ // it never appears as tool input/output, so it stays out of the model
420
+ // context, the runner session log, and the desktop NDJSON log.
421
+ handler: async ({ baseURL, keyName }, ctx) => {
422
+ if (!ctx.getSecret) {
423
+ return {
424
+ ok: false,
425
+ message: 'provider_test: this session has no secret vault wired in (ctx.getSecret is ' +
426
+ 'unavailable), so the key cannot be resolved. Register the provider with ' +
427
+ 'provider_add and have the user verify the key with `moxxy doctor` instead.',
428
+ };
429
+ }
430
+ const apiKey = await ctx.getSecret(keyName);
431
+ if (!apiKey) {
432
+ return {
433
+ ok: false,
434
+ message: `provider_test: no vault secret named "${keyName}". Ask the USER to store it ` +
435
+ `by running: /vault set ${keyName} <key> — then call provider_test again with ` +
436
+ `keyName "${keyName}". Never ask them to paste the key into the conversation.`,
437
+ };
438
+ }
439
+ return validateOpenAICompatKey(apiKey, { baseURL });
440
+ },
441
+ }),
442
+ ],
443
+ hooks: {
444
+ onInit: async (ctx) => {
445
+ const log = getWarnLogger(ctx);
446
+ let cfg;
447
+ try {
448
+ cfg = await readProvidersConfig(configPath);
449
+ }
450
+ catch (err) {
451
+ log?.warn('provider-admin: failed to read providers.json', {
452
+ err: err instanceof Error ? err.message : String(err),
453
+ });
454
+ return;
455
+ }
456
+ for (const entry of cfg.providers) {
457
+ try {
458
+ // Evaluate built-in collision against the live registry MINUS our
459
+ // own names BEFORE claiming ownership. A name present in the registry
460
+ // that we didn't put there is a built-in (code provider) and must
461
+ // never be overwritten by a poisoned/legacy store entry.
462
+ if (engine.isBuiltin(entry.name)) {
463
+ log?.warn(`provider-admin: skipping stored provider "${entry.name}" — it collides with a built-in`);
464
+ continue;
465
+ }
466
+ const def = buildProviderDef(entry);
467
+ const already = providerRegistry.list().some((p) => p.name === entry.name);
468
+ if (already)
469
+ providerRegistry.replace(def);
470
+ else
471
+ providerRegistry.register(def);
472
+ engine.ownNames.add(entry.name);
473
+ }
474
+ catch (err) {
475
+ log?.warn(`provider-admin: failed to register "${entry.name}"`, {
476
+ err: err instanceof Error ? err.message : String(err),
477
+ });
478
+ }
479
+ }
480
+ },
481
+ },
482
+ });
483
+ }
484
+ export const providerAdminPlugin = (() => {
485
+ let resolvedRegistry = null;
486
+ let resolveCreds = null;
487
+ const lazyRegistry = new Proxy({}, {
488
+ get(_target, prop) {
489
+ if (!resolvedRegistry) {
490
+ throw new Error('@moxxy/plugin-provider-admin: the "providers" service is unavailable — the host must publish it');
491
+ }
492
+ const value = resolvedRegistry[prop];
493
+ return typeof value === 'function'
494
+ ? value.bind(resolvedRegistry)
495
+ : value;
496
+ },
497
+ });
498
+ const { plugin, api } = buildProviderAdminPluginWithApi({
499
+ providerRegistry: lazyRegistry,
500
+ resolveActiveConfig: (name) => (resolveCreds ? resolveCreds(name) : {}),
501
+ });
502
+ const innerOnInit = plugin.hooks?.onInit;
503
+ return definePlugin({
504
+ ...plugin,
505
+ hooks: {
506
+ ...plugin.hooks,
507
+ onInit: async (ctx) => {
508
+ resolvedRegistry = ctx.services.get('providers') ?? null;
509
+ resolveCreds = ctx.services.get('resolveCredentials') ?? null;
510
+ ctx.services.register('providerAdmin', api);
511
+ // Now that the registry is resolved, run the stored-provider
512
+ // re-registration (it drives the lazy registry).
513
+ await innerOnInit?.(ctx);
514
+ },
515
+ },
516
+ });
517
+ })();
518
+ // Discovery entry: `createPluginLoader` requires a default Plugin export.
519
+ export default providerAdminPlugin;
520
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ /**
2
+ * THE canonical derivation of the vault/env key name that holds a
3
+ * provider's API key. Every consumer (provider-admin tools, the CLI's
4
+ * credential resolution, the desktop's provider discovery) must agree on
5
+ * this name or keys stored by one surface become invisible to another —
6
+ * previously the CLI, the admin tools and the desktop each derived it
7
+ * slightly differently (the CLI didn't map `-` → `_` and ignored the
8
+ * stored `envVar` override).
9
+ *
10
+ * Rules:
11
+ * - a stored `envVar` override always wins;
12
+ * - otherwise the provider slug is upper-snaked and suffixed with
13
+ * `_API_KEY` (`z-ai` → `Z_AI_API_KEY`) — hyphens become underscores
14
+ * so the result is a valid POSIX env-var name.
15
+ */
16
+ export declare function providerApiKeyName(provider: string | {
17
+ readonly name: string;
18
+ readonly envVar?: string;
19
+ }): string;
20
+ /**
21
+ * Key name for a provider honoring any `envVar` override persisted in
22
+ * ~/.moxxy/providers.json. Returns `null` when the provider isn't a
23
+ * stored (runtime-registered) one — callers fall back to
24
+ * `providerApiKeyName(name)` for built-ins.
25
+ */
26
+ export declare function storedProviderApiKeyName(providerName: string, configPath?: string): Promise<string | null>;
27
+ //# sourceMappingURL=key-name.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-name.d.ts","sourceRoot":"","sources":["../src/key-name.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,kBAAkB,CAChC,QAAQ,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GACrE,MAAM,CAIR;AAED;;;;;GAKG;AACH,wBAAsB,wBAAwB,CAC5C,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAIxB"}
@@ -0,0 +1,34 @@
1
+ import { readProvidersConfig } from './store.js';
2
+ /**
3
+ * THE canonical derivation of the vault/env key name that holds a
4
+ * provider's API key. Every consumer (provider-admin tools, the CLI's
5
+ * credential resolution, the desktop's provider discovery) must agree on
6
+ * this name or keys stored by one surface become invisible to another —
7
+ * previously the CLI, the admin tools and the desktop each derived it
8
+ * slightly differently (the CLI didn't map `-` → `_` and ignored the
9
+ * stored `envVar` override).
10
+ *
11
+ * Rules:
12
+ * - a stored `envVar` override always wins;
13
+ * - otherwise the provider slug is upper-snaked and suffixed with
14
+ * `_API_KEY` (`z-ai` → `Z_AI_API_KEY`) — hyphens become underscores
15
+ * so the result is a valid POSIX env-var name.
16
+ */
17
+ export function providerApiKeyName(provider) {
18
+ if (typeof provider !== 'string' && provider.envVar)
19
+ return provider.envVar;
20
+ const name = typeof provider === 'string' ? provider : provider.name;
21
+ return `${name.toUpperCase().replace(/-/g, '_')}_API_KEY`;
22
+ }
23
+ /**
24
+ * Key name for a provider honoring any `envVar` override persisted in
25
+ * ~/.moxxy/providers.json. Returns `null` when the provider isn't a
26
+ * stored (runtime-registered) one — callers fall back to
27
+ * `providerApiKeyName(name)` for built-ins.
28
+ */
29
+ export async function storedProviderApiKeyName(providerName, configPath) {
30
+ const cfg = await readProvidersConfig(configPath);
31
+ const entry = cfg.providers.find((p) => p.name === providerName);
32
+ return entry ? providerApiKeyName(entry) : null;
33
+ }
34
+ //# sourceMappingURL=key-name.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"key-name.js","sourceRoot":"","sources":["../src/key-name.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEjD;;;;;;;;;;;;;;GAcG;AACH,MAAM,UAAU,kBAAkB,CAChC,QAAsE;IAEtE,IAAI,OAAO,QAAQ,KAAK,QAAQ,IAAI,QAAQ,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC,MAAM,CAAC;IAC5E,MAAM,IAAI,GAAG,OAAO,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC;IACrE,OAAO,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC;AAC5D,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,wBAAwB,CAC5C,YAAoB,EACpB,UAAmB;IAEnB,MAAM,GAAG,GAAG,MAAM,mBAAmB,CAAC,UAAU,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,GAAG,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,YAAY,CAAC,CAAC;IACjE,OAAO,KAAK,CAAC,CAAC,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC"}
@@ -0,0 +1,12 @@
1
+ import type { StoredProvider, StoredProvidersConfig } from './types.js';
2
+ /**
3
+ * User-level provider catalog. Mirrors the MCP admin storage pattern:
4
+ * a JSON file in ~/.moxxy/ that the admin tools mutate and the plugin's
5
+ * onInit hook reads back on every boot to repopulate the registry.
6
+ */
7
+ export declare function providersConfigPath(): string;
8
+ export declare function readProvidersConfig(filePath?: string): Promise<StoredProvidersConfig>;
9
+ export declare function writeProvidersConfig(cfg: StoredProvidersConfig, filePath?: string): Promise<void>;
10
+ export declare function upsertStoredProvider(entry: StoredProvider, filePath?: string): Promise<StoredProvidersConfig>;
11
+ export declare function removeStoredProvider(name: string, filePath?: string): Promise<boolean>;
12
+ //# sourceMappingURL=store.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../src/store.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,qBAAqB,EAAE,MAAM,YAAY,CAAC;AAExE;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,MAAM,CAE5C;AAqCD,wBAAsB,mBAAmB,CAAC,QAAQ,GAAE,MAA8B,GAAG,OAAO,CAAC,qBAAqB,CAAC,CAwBlH;AAUD,wBAAsB,oBAAoB,CACxC,GAAG,EAAE,qBAAqB,EAC1B,QAAQ,GAAE,MAA8B,GACvC,OAAO,CAAC,IAAI,CAAC,CAEf;AASD,wBAAsB,oBAAoB,CACxC,KAAK,EAAE,cAAc,EACrB,QAAQ,GAAE,MAA8B,GACvC,OAAO,CAAC,qBAAqB,CAAC,CAShC;AAED,wBAAsB,oBAAoB,CACxC,IAAI,EAAE,MAAM,EACZ,QAAQ,GAAE,MAA8B,GACvC,OAAO,CAAC,OAAO,CAAC,CAQlB"}