@mnemom/mnemom 0.17.7-next.2 → 0.17.8-next.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/commands/agent-doctor.d.ts +4 -21
- package/dist/commands/agent-doctor.js +5 -51
- package/dist/commands/agent-goal.d.ts +1 -1
- package/dist/commands/agent-goal.js +3 -6
- package/dist/commands/agent-setup.d.ts +5 -16
- package/dist/commands/agent-setup.js +12 -29
- package/dist/commands/agent.d.ts +3 -25
- package/dist/commands/agent.js +31 -83
- package/dist/commands/wrap.d.ts +0 -8
- package/dist/commands/wrap.js +3 -36
- package/dist/lib/agent.d.ts +3 -29
- package/dist/lib/agent.js +2 -20
- package/dist/lib/api.d.ts +2 -27
- package/dist/lib/api.js +2 -64
- package/dist/lib/subscription-login.d.ts +20 -152
- package/dist/lib/subscription-login.js +28 -215
- package/dist/mcp/handoff-server.mjs +13 -35
- package/dist/rc-proxy.mjs +3 -6
- package/package.json +1 -1
package/dist/lib/agent.d.ts
CHANGED
|
@@ -491,10 +491,8 @@ export declare function launchPreferenceExplicit(opts: {
|
|
|
491
491
|
* Has an orchestrator already run the session + µ-balance preflight for this
|
|
492
492
|
* launch? `MNEMOM_AGENT_PREFLIGHTED=1` is for orchestrators (the ADW fleet) that
|
|
493
493
|
* checked sign-in and balance themselves before spawning many launches; it skips
|
|
494
|
-
* the per-launch session
|
|
495
|
-
*
|
|
496
|
-
* Mnemom key is minted for it), and the Mnemom Agent entitlement (which also
|
|
497
|
-
* gates Remote Control, fail-closed) is still fetched for it.
|
|
494
|
+
* the per-launch session/personal-org/balance round trips. The Mnemom Agent
|
|
495
|
+
* entitlement (which also gates Remote Control, fail-closed) is still fetched.
|
|
498
496
|
* Only the exact value `1` counts — anything else, including `true` or ` 1`, is
|
|
499
497
|
* a normal launch.
|
|
500
498
|
*/
|
|
@@ -543,11 +541,7 @@ export declare function resolveRemoteControlShape(args: {
|
|
|
543
541
|
export declare function buildCustomHeaders(opts: {
|
|
544
542
|
/** Absent on a subscription-login launch: Claude Code then sends its own claude.ai login. */
|
|
545
543
|
anthropicKey?: string;
|
|
546
|
-
/**
|
|
547
|
-
* The Mnemom key every `mnemom agent` launch sends (lib/subscription-login.ts
|
|
548
|
-
* resolveLaunchMnemomKey) — the gateway refuses the session without it, and on a subscription
|
|
549
|
-
* login it is also the governed-identity anchor.
|
|
550
|
-
*/
|
|
544
|
+
/** The governed-identity anchor on a subscription-login launch (lib/subscription-login.ts). */
|
|
551
545
|
mnemomKey?: string;
|
|
552
546
|
agent: string;
|
|
553
547
|
conversationId: string;
|
|
@@ -662,14 +656,6 @@ export declare function buildSessionConfigB64(opts: {
|
|
|
662
656
|
compactAt?: number | null;
|
|
663
657
|
experimental?: readonly string[];
|
|
664
658
|
}): string | undefined;
|
|
665
|
-
/**
|
|
666
|
-
* A no-op `x-mnemom-session-config` value: `{ v: 1, config: {} }` overrides nothing (the gateway
|
|
667
|
-
* applies an empty set, exactly its own defaults). buildSessionConfigB64 returns `undefined` for
|
|
668
|
-
* the defaults — no header at all; this is for a call that must be Mnemom agent traffic (the
|
|
669
|
-
* gateway's agent-traffic gate keys on the header's presence) without changing any setting: the
|
|
670
|
-
* launcher's birth probe (commands/wrap.ts birthThroughGateway).
|
|
671
|
-
*/
|
|
672
|
-
export declare const NOOP_SESSION_CONFIG_B64: string;
|
|
673
659
|
/**
|
|
674
660
|
* Is the `handoff` MCP tool + `CONTEXT_HANDOFF_ENABLED` session-config header ON for
|
|
675
661
|
* this launch? OFF by default (operator directive, curation 2026-09-25): an absent flag
|
|
@@ -705,12 +691,6 @@ export declare const HANDOFF_MCP_SERVER_NAME = "mnemom-handoff";
|
|
|
705
691
|
* it the same way it inherits `ANTHROPIC_CUSTOM_HEADERS` under the terminal shape.
|
|
706
692
|
*/
|
|
707
693
|
export declare const HANDOFF_RC_KEY_ENV_NAME = "MNEMOM_HANDOFF_KEY";
|
|
708
|
-
/**
|
|
709
|
-
* Beside `HANDOFF_RC_KEY_ENV_NAME`: the non-`ANTHROPIC_*` var `spawnRcCli` sets to the launch's
|
|
710
|
-
* Mnemom key when context handoff is on, so the handoff call carries the `x-mnemom-api-key` the
|
|
711
|
-
* gateway requires on every `mnemom agent` request.
|
|
712
|
-
*/
|
|
713
|
-
export declare const HANDOFF_RC_MNEMOM_KEY_ENV_NAME = "MNEMOM_HANDOFF_MNEMOM_KEY";
|
|
714
694
|
/**
|
|
715
695
|
* How the `handoff` MCP server (cli/src/mcp/handoff-server.mjs) recovers the Anthropic key
|
|
716
696
|
* WITHOUT it ever being written into the `--mcp-config` file on disk: `envName` is the NAME of a
|
|
@@ -742,12 +722,6 @@ export interface HandoffMcpParams {
|
|
|
742
722
|
/** The gateway ORIGIN (e.g. https://gateway.mnemom.ai) — see `resolveHandoffGatewayHost`. */
|
|
743
723
|
gatewayHost: string;
|
|
744
724
|
anthropicKeySource: HandoffAnthropicKeySource;
|
|
745
|
-
/**
|
|
746
|
-
* Where the server reads the Mnemom key (`x-mnemom-api-key`) from — same contract as
|
|
747
|
-
* `anthropicKeySource`: `ANTHROPIC_CUSTOM_HEADERS` (its `x-mnemom-api-key:` line) on a terminal
|
|
748
|
-
* launch, `HANDOFF_RC_MNEMOM_KEY_ENV_NAME` under Remote Control. Absent ⇒ no Mnemom key header.
|
|
749
|
-
*/
|
|
750
|
-
mnemomKeySource?: HandoffAnthropicKeySource;
|
|
751
725
|
agent: string;
|
|
752
726
|
conversationId: string;
|
|
753
727
|
/** `buildSessionConfigB64` output — forwarded so the route resolves the SAME per-session flag. */
|
package/dist/lib/agent.js
CHANGED
|
@@ -842,10 +842,8 @@ export function launchPreferenceExplicit(opts, env = process.env) {
|
|
|
842
842
|
* Has an orchestrator already run the session + µ-balance preflight for this
|
|
843
843
|
* launch? `MNEMOM_AGENT_PREFLIGHTED=1` is for orchestrators (the ADW fleet) that
|
|
844
844
|
* checked sign-in and balance themselves before spawning many launches; it skips
|
|
845
|
-
* the per-launch session
|
|
846
|
-
*
|
|
847
|
-
* Mnemom key is minted for it), and the Mnemom Agent entitlement (which also
|
|
848
|
-
* gates Remote Control, fail-closed) is still fetched for it.
|
|
845
|
+
* the per-launch session/personal-org/balance round trips. The Mnemom Agent
|
|
846
|
+
* entitlement (which also gates Remote Control, fail-closed) is still fetched.
|
|
849
847
|
* Only the exact value `1` counts — anything else, including `true` or ` 1`, is
|
|
850
848
|
* a normal launch.
|
|
851
849
|
*/
|
|
@@ -1056,14 +1054,6 @@ export function buildSessionConfigB64(opts) {
|
|
|
1056
1054
|
return undefined;
|
|
1057
1055
|
return Buffer.from(JSON.stringify(payload), "utf8").toString("base64url");
|
|
1058
1056
|
}
|
|
1059
|
-
/**
|
|
1060
|
-
* A no-op `x-mnemom-session-config` value: `{ v: 1, config: {} }` overrides nothing (the gateway
|
|
1061
|
-
* applies an empty set, exactly its own defaults). buildSessionConfigB64 returns `undefined` for
|
|
1062
|
-
* the defaults — no header at all; this is for a call that must be Mnemom agent traffic (the
|
|
1063
|
-
* gateway's agent-traffic gate keys on the header's presence) without changing any setting: the
|
|
1064
|
-
* launcher's birth probe (commands/wrap.ts birthThroughGateway).
|
|
1065
|
-
*/
|
|
1066
|
-
export const NOOP_SESSION_CONFIG_B64 = Buffer.from(JSON.stringify({ v: 1, config: {} }), "utf8").toString("base64url");
|
|
1067
1057
|
/**
|
|
1068
1058
|
* Is the `handoff` MCP tool + `CONTEXT_HANDOFF_ENABLED` session-config header ON for
|
|
1069
1059
|
* this launch? OFF by default (operator directive, curation 2026-09-25): an absent flag
|
|
@@ -1107,12 +1097,6 @@ export const HANDOFF_MCP_SERVER_NAME = "mnemom-handoff";
|
|
|
1107
1097
|
* it the same way it inherits `ANTHROPIC_CUSTOM_HEADERS` under the terminal shape.
|
|
1108
1098
|
*/
|
|
1109
1099
|
export const HANDOFF_RC_KEY_ENV_NAME = "MNEMOM_HANDOFF_KEY";
|
|
1110
|
-
/**
|
|
1111
|
-
* Beside `HANDOFF_RC_KEY_ENV_NAME`: the non-`ANTHROPIC_*` var `spawnRcCli` sets to the launch's
|
|
1112
|
-
* Mnemom key when context handoff is on, so the handoff call carries the `x-mnemom-api-key` the
|
|
1113
|
-
* gateway requires on every `mnemom agent` request.
|
|
1114
|
-
*/
|
|
1115
|
-
export const HANDOFF_RC_MNEMOM_KEY_ENV_NAME = "MNEMOM_HANDOFF_MNEMOM_KEY";
|
|
1116
1100
|
/** The `--mcp-config` document registering exactly the `handoff` tool. Pure — no I/O. */
|
|
1117
1101
|
export function buildHandoffMcpConfig(p) {
|
|
1118
1102
|
const env = {
|
|
@@ -1121,8 +1105,6 @@ export function buildHandoffMcpConfig(p) {
|
|
|
1121
1105
|
MNEMOM_HANDOFF_AGENT: p.agent,
|
|
1122
1106
|
MNEMOM_HANDOFF_CONVERSATION_ID: p.conversationId,
|
|
1123
1107
|
};
|
|
1124
|
-
if (p.mnemomKeySource)
|
|
1125
|
-
env.MNEMOM_HANDOFF_MNEMOM_KEY_ENV_NAME = p.mnemomKeySource.envName;
|
|
1126
1108
|
if (p.sessionConfigB64)
|
|
1127
1109
|
env.MNEMOM_HANDOFF_SESSION_CONFIG = p.sessionConfigB64;
|
|
1128
1110
|
return {
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -1069,27 +1069,6 @@ export declare function listApiKeys(): Promise<ApiKeyListItem[]>;
|
|
|
1069
1069
|
* for non-staff, admin:org for users not in any org-admin role).
|
|
1070
1070
|
*/
|
|
1071
1071
|
export declare function createApiKey(name: string, scopes: ApiKeyScope[]): Promise<ApiKeyCreated>;
|
|
1072
|
-
/**
|
|
1073
|
-
* POST /v1/orgs/{org_id}/api-keys — mint an ORG-owned key (its `org_id` is that org, so the
|
|
1074
|
-
* gateway births a new agent there). Owners and admins may mint any scopes; a member may mint a
|
|
1075
|
-
* key whose scopes are exactly ["gateway"]. A refusal (viewer/auditor, a non-member, or an API
|
|
1076
|
-
* that predates member org keys) is thrown as MnemomApiError with its status (403/404).
|
|
1077
|
-
*/
|
|
1078
|
-
export declare function createOrgApiKey(orgId: string, name: string, scopes: ApiKeyScope[]): Promise<ApiKeyCreated>;
|
|
1079
|
-
/**
|
|
1080
|
-
* GET /v1/api-keys/whoami authenticated by `key` ALONE (`X-Mnemom-Api-Key`, no session): does
|
|
1081
|
-
* the API accept this key? true = 200. false = 401/403 — revoked, rotated or unknown, OR a valid
|
|
1082
|
-
* `gateway`-only key: the API refuses every key without an `api:*` scope (ADR-049), so false
|
|
1083
|
-
* alone never proves a key dead. Throws on anything else (network, timeout, 429, 5xx): the
|
|
1084
|
-
* caller reads that as "could not check".
|
|
1085
|
-
*/
|
|
1086
|
-
export declare function apiAcceptsMnemomKey(key: string, timeoutMs: number): Promise<boolean>;
|
|
1087
|
-
/**
|
|
1088
|
-
* GET /v1/api-keys with a timeout, for checking a key: the signed-in caller's ACTIVE keys (a
|
|
1089
|
-
* revoked or rotated key is absent). null when there is no usable session (no credential, or
|
|
1090
|
-
* 401/403 after the refresh retry). Throws on anything else (network, timeout, 5xx).
|
|
1091
|
-
*/
|
|
1092
|
-
export declare function listOwnApiKeysForCheck(timeoutMs: number): Promise<ApiKeyListItem[] | null>;
|
|
1093
1072
|
/**
|
|
1094
1073
|
* POST /v1/api-keys/{key_id}/rotate — atomic mint-new + revoke-old.
|
|
1095
1074
|
* Returns the full new secret only on this call. The new key inherits
|
|
@@ -1099,13 +1078,9 @@ export declare function listOwnApiKeysForCheck(timeoutMs: number): Promise<ApiKe
|
|
|
1099
1078
|
export declare function rotateApiKey(keyId: string): Promise<ApiKeyCreated>;
|
|
1100
1079
|
/**
|
|
1101
1080
|
* DELETE /v1/api-keys/{key_id} — soft-revoke. The key row stays for
|
|
1102
|
-
* audit; `is_active` flips to false and `revoked_at` is timestamped.
|
|
1103
|
-
* a key the signed-in user created (an org key they minted included) is
|
|
1104
|
-
* found; anything else is a 404. `timeoutMs` bounds the call.
|
|
1081
|
+
* audit; `is_active` flips to false and `revoked_at` is timestamped.
|
|
1105
1082
|
*/
|
|
1106
|
-
export declare function revokeApiKey(keyId: string
|
|
1107
|
-
timeoutMs?: number;
|
|
1108
|
-
}): Promise<void>;
|
|
1083
|
+
export declare function revokeApiKey(keyId: string): Promise<void>;
|
|
1109
1084
|
export interface LicenseValidationResult {
|
|
1110
1085
|
valid: boolean;
|
|
1111
1086
|
license_id?: string;
|
package/dist/lib/api.js
CHANGED
|
@@ -1385,65 +1385,6 @@ export async function createApiKey(name, scopes) {
|
|
|
1385
1385
|
}
|
|
1386
1386
|
return (await response.json());
|
|
1387
1387
|
}
|
|
1388
|
-
/**
|
|
1389
|
-
* POST /v1/orgs/{org_id}/api-keys — mint an ORG-owned key (its `org_id` is that org, so the
|
|
1390
|
-
* gateway births a new agent there). Owners and admins may mint any scopes; a member may mint a
|
|
1391
|
-
* key whose scopes are exactly ["gateway"]. A refusal (viewer/auditor, a non-member, or an API
|
|
1392
|
-
* that predates member org keys) is thrown as MnemomApiError with its status (403/404).
|
|
1393
|
-
*/
|
|
1394
|
-
export async function createOrgApiKey(orgId, name, scopes) {
|
|
1395
|
-
const url = validateUrl(`${API_BASE}/v1/orgs/${encodeURIComponent(sanitizeForHttp(orgId))}/api-keys`);
|
|
1396
|
-
const response = await fetchWithAuthRetry(url, async () => ({
|
|
1397
|
-
method: "POST",
|
|
1398
|
-
headers: { ...(await authHeaders()), "Content-Type": "application/json" },
|
|
1399
|
-
body: JSON.stringify({ name, scopes }),
|
|
1400
|
-
}));
|
|
1401
|
-
if (!response.ok) {
|
|
1402
|
-
if (response.status === 401)
|
|
1403
|
-
throw new MnemomApiError(401, NOT_AUTHENTICATED_MSG);
|
|
1404
|
-
throw await readApiError(response, "Failed to create org api key");
|
|
1405
|
-
}
|
|
1406
|
-
return (await response.json());
|
|
1407
|
-
}
|
|
1408
|
-
/**
|
|
1409
|
-
* GET /v1/api-keys/whoami authenticated by `key` ALONE (`X-Mnemom-Api-Key`, no session): does
|
|
1410
|
-
* the API accept this key? true = 200. false = 401/403 — revoked, rotated or unknown, OR a valid
|
|
1411
|
-
* `gateway`-only key: the API refuses every key without an `api:*` scope (ADR-049), so false
|
|
1412
|
-
* alone never proves a key dead. Throws on anything else (network, timeout, 429, 5xx): the
|
|
1413
|
-
* caller reads that as "could not check".
|
|
1414
|
-
*/
|
|
1415
|
-
export async function apiAcceptsMnemomKey(key, timeoutMs) {
|
|
1416
|
-
const url = validateUrl(`${API_BASE}/v1/api-keys/whoami`);
|
|
1417
|
-
const response = await mnemomFetch(url, {
|
|
1418
|
-
headers: { "X-Mnemom-Api-Key": sanitizeForHttp(key), Accept: "application/json" },
|
|
1419
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
1420
|
-
});
|
|
1421
|
-
if (response.ok)
|
|
1422
|
-
return true;
|
|
1423
|
-
if (response.status === 401 || response.status === 403)
|
|
1424
|
-
return false;
|
|
1425
|
-
throw new MnemomApiError(response.status, `api-key whoami: HTTP ${response.status}`);
|
|
1426
|
-
}
|
|
1427
|
-
/**
|
|
1428
|
-
* GET /v1/api-keys with a timeout, for checking a key: the signed-in caller's ACTIVE keys (a
|
|
1429
|
-
* revoked or rotated key is absent). null when there is no usable session (no credential, or
|
|
1430
|
-
* 401/403 after the refresh retry). Throws on anything else (network, timeout, 5xx).
|
|
1431
|
-
*/
|
|
1432
|
-
export async function listOwnApiKeysForCheck(timeoutMs) {
|
|
1433
|
-
if ((await resolveAuth()).type === "none")
|
|
1434
|
-
return null;
|
|
1435
|
-
const url = validateUrl(`${API_BASE}/v1/api-keys`);
|
|
1436
|
-
const response = await fetchWithAuthRetry(url, async () => ({
|
|
1437
|
-
headers: { ...(await authHeaders()), Accept: "application/json" },
|
|
1438
|
-
signal: AbortSignal.timeout(timeoutMs),
|
|
1439
|
-
}));
|
|
1440
|
-
if (response.status === 401 || response.status === 403)
|
|
1441
|
-
return null;
|
|
1442
|
-
if (!response.ok) {
|
|
1443
|
-
throw new MnemomApiError(response.status, `list api keys: HTTP ${response.status}`);
|
|
1444
|
-
}
|
|
1445
|
-
return (await response.json()).keys ?? [];
|
|
1446
|
-
}
|
|
1447
1388
|
/**
|
|
1448
1389
|
* POST /v1/api-keys/{key_id}/rotate — atomic mint-new + revoke-old.
|
|
1449
1390
|
* Returns the full new secret only on this call. The new key inherits
|
|
@@ -1469,16 +1410,13 @@ export async function rotateApiKey(keyId) {
|
|
|
1469
1410
|
}
|
|
1470
1411
|
/**
|
|
1471
1412
|
* DELETE /v1/api-keys/{key_id} — soft-revoke. The key row stays for
|
|
1472
|
-
* audit; `is_active` flips to false and `revoked_at` is timestamped.
|
|
1473
|
-
* a key the signed-in user created (an org key they minted included) is
|
|
1474
|
-
* found; anything else is a 404. `timeoutMs` bounds the call.
|
|
1413
|
+
* audit; `is_active` flips to false and `revoked_at` is timestamped.
|
|
1475
1414
|
*/
|
|
1476
|
-
export async function revokeApiKey(keyId
|
|
1415
|
+
export async function revokeApiKey(keyId) {
|
|
1477
1416
|
const url = validateUrl(`${API_BASE}/v1/api-keys/${encodeURIComponent(keyId)}`);
|
|
1478
1417
|
const response = await fetchWithAuthRetry(url, async () => ({
|
|
1479
1418
|
method: "DELETE",
|
|
1480
1419
|
headers: await authHeaders(),
|
|
1481
|
-
signal: opts.timeoutMs ? AbortSignal.timeout(opts.timeoutMs) : undefined,
|
|
1482
1420
|
}));
|
|
1483
1421
|
if (!response.ok) {
|
|
1484
1422
|
if (response.status === 401) {
|
|
@@ -1,40 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `mnemom agent`
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* with scopes exactly ["gateway"] (POST /v1/orgs/:id/api-keys; any owner/admin/member may mint
|
|
14
|
-
* one), so the gateway's agent-traffic org check (#2289: the agent's org must be the key's org)
|
|
15
|
-
* passes. There is no personal-key fallback: a personal key has no org, so the gateway would
|
|
16
|
-
* refuse every governed turn with it. When the mint is refused (an API that predates member org
|
|
17
|
-
* keys, or a viewer/auditor role) the launch stops with guidance — ask an org owner/admin for a
|
|
18
|
-
* gateway-scoped org key, or set MNEMOM_AGENT_MNEMOM_KEY to one. Each saved key records the org
|
|
19
|
-
* it was minted for; a launch in another org mints and saves a key for that org.
|
|
20
|
-
*
|
|
21
|
-
* When the launcher replaces a key it minted and saved (proven dead, minted for another org, or
|
|
22
|
-
* the legacy single-field key), it revokes the old one best-effort. An env-provided key is never
|
|
23
|
-
* replaced and never revoked.
|
|
24
|
-
*
|
|
25
|
-
* Birth org: the launcher's gateway probe/birth call carries the key AND a no-op
|
|
26
|
-
* `x-mnemom-session-config`, which makes it Mnemom agent traffic: the gateway verifies the key
|
|
27
|
-
* and births a new agent in the key's org. The launcher's claim step then records the claim in
|
|
28
|
-
* that same org.
|
|
29
|
-
*
|
|
30
|
-
* With a Claude subscription login (`auth = subscription`) — Team and Enterprise plans only;
|
|
31
|
-
* the gateway checks the plan with Anthropic and refuses anything else
|
|
32
|
-
* (gateway/src/subscription-auth.ts) — Claude Code authenticates to the gateway with its own
|
|
33
|
-
* claude.ai OAuth login: the launch sets ANTHROPIC_BASE_URL and leaves ANTHROPIC_API_KEY /
|
|
34
|
-
* ANTHROPIC_AUTH_TOKEN unset, so Claude Code sends `Authorization: Bearer <its login>`. No
|
|
35
|
-
* Anthropic key is involved; the gateway anchors the governed identity on the Mnemom key and
|
|
36
|
-
* creates the agent in that key's org on the first turn, so there is no CLI-side birth or
|
|
37
|
-
* claim.
|
|
2
|
+
* `mnemom agent` with a Claude subscription login (`auth = subscription`) — Team and
|
|
3
|
+
* Enterprise plans only; the gateway checks the plan with Anthropic and refuses anything
|
|
4
|
+
* else (gateway/src/subscription-auth.ts).
|
|
5
|
+
*
|
|
6
|
+
* Claude Code then authenticates to the gateway with its own claude.ai OAuth login: the
|
|
7
|
+
* launch sets ANTHROPIC_BASE_URL and leaves ANTHROPIC_API_KEY / ANTHROPIC_AUTH_TOKEN unset,
|
|
8
|
+
* so Claude Code sends `Authorization: Bearer <its login>`. No Anthropic key is involved.
|
|
9
|
+
* The gateway anchors the governed identity on a Mnemom API key instead
|
|
10
|
+
* (`x-mnemom-api-key`), which this module resolves — env, then the 0600 store, then a
|
|
11
|
+
* freshly minted gateway-only key — and the agent is created in that key's org on the
|
|
12
|
+
* first turn, so there is no CLI-side birth or claim.
|
|
38
13
|
*
|
|
39
14
|
* Remote Control is internal-only (see subscriptionShape); the context-handoff tool
|
|
40
15
|
* authenticates with an Anthropic key, so it is off on a subscription launch.
|
|
@@ -47,133 +22,26 @@ export type AgentAuth = "api-key" | "subscription" | "console";
|
|
|
47
22
|
export declare const AGENT_AUTHS: readonly AgentAuth[];
|
|
48
23
|
/** Env override for the setting (the launcher.toml `auth` key folds into it). */
|
|
49
24
|
export declare const AGENT_AUTH_ENV = "MNEMOM_AGENT_AUTH";
|
|
50
|
-
/** Env override for the Mnemom key
|
|
25
|
+
/** Env override for the Mnemom key a subscription launch sends. */
|
|
51
26
|
export declare const MNEMOM_KEY_ENV = "MNEMOM_AGENT_MNEMOM_KEY";
|
|
52
|
-
/**
|
|
53
|
-
* Legacy field in ~/.mnemom/launcher.json (0600): the single minted key, from before keys were
|
|
54
|
-
* stored per org. Read as the no-org slot; retired when that slot is written.
|
|
55
|
-
*/
|
|
27
|
+
/** Field in ~/.mnemom/launcher.json (0600) holding the minted key. */
|
|
56
28
|
export declare const MNEMOM_KEY_STORE_FIELD = "mnemom_api_key";
|
|
57
|
-
/**
|
|
58
|
-
* Field in ~/.mnemom/launcher.json (0600): `{ <active org id | "_none">: { key, key_id, org_id } }`
|
|
59
|
-
* — one slot per `mnemom org use` setting; `org_id` is the org the key was minted for.
|
|
60
|
-
*/
|
|
61
|
-
export declare const MNEMOM_KEYS_BY_ORG_FIELD = "mnemom_api_keys";
|
|
62
29
|
export declare function coerceAgentAuth(raw: string): AgentAuth;
|
|
63
30
|
/** `--auth` flag > MNEMOM_AGENT_AUTH (launcher.toml folds in here) > api-key. */
|
|
64
31
|
export declare function resolveAgentAuth(flag: string | undefined, env: Record<string, string | undefined>): AgentAuth;
|
|
65
|
-
/** A key in the 0600 store: the secret, and its API key_id when this CLI minted it. */
|
|
66
|
-
export interface StoredMnemomKey {
|
|
67
|
-
key: string;
|
|
68
|
-
/** Absent on a key saved before key ids were stored. */
|
|
69
|
-
keyId?: string;
|
|
70
|
-
/** The launch org this key was minted for. Absent on a key saved before orgs were stored. */
|
|
71
|
-
orgId?: string;
|
|
72
|
-
}
|
|
73
|
-
/**
|
|
74
|
-
* Is a Mnemom key live? `invalid` only when it is PROVEN dead (checkMnemomKey); anything unproven
|
|
75
|
-
* (offline, slow, no session, a gateway-only key the API cannot introspect) is `unknown` — a
|
|
76
|
-
* launch then proceeds with the key, and the gateway refuses a dead one with a clear message.
|
|
77
|
-
*/
|
|
78
|
-
export type MnemomKeyCheck = "valid" | "invalid" | "unknown";
|
|
79
32
|
export interface MnemomKeyDeps {
|
|
80
33
|
env: Record<string, string | undefined>;
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
activeOrgId: string | null;
|
|
86
|
-
/**
|
|
87
|
-
* The org this launch runs in — the active org, else the caller's personal org (the org the
|
|
88
|
-
* launcher claims the agent into) — or null when unknown. Keys are minted for it; with none
|
|
89
|
-
* known, a launch that needs a new key refuses (it has no org to mint one for).
|
|
90
|
-
*/
|
|
91
|
-
launchOrgId: string | null;
|
|
92
|
-
readStored(orgId: string | null): StoredMnemomKey | undefined;
|
|
93
|
-
/**
|
|
94
|
-
* Mint an org-owned key with scopes ["gateway"] for `orgId`. Throws when the API refuses (a
|
|
95
|
-
* refusal carries `status`/`effectiveStatus` 403). Any `orgId` on the result is ignored: the
|
|
96
|
-
* store records the org the key was minted FOR.
|
|
97
|
-
*/
|
|
98
|
-
mint(orgId: string): Promise<StoredMnemomKey>;
|
|
99
|
-
store(orgId: string | null, key: StoredMnemomKey): void;
|
|
100
|
-
/** checkMnemomKey over the real API, with short timeouts. Never throws. */
|
|
101
|
-
check(key: string, keyId: string | undefined): Promise<MnemomKeyCheck>;
|
|
102
|
-
/** Revoke a key this CLI minted, by key_id (needs a session). May throw; callers ignore it. */
|
|
103
|
-
revoke(keyId: string): Promise<void>;
|
|
34
|
+
readStored(): string | undefined;
|
|
35
|
+
/** Mint a gateway-only personal key for this machine; returns the secret. */
|
|
36
|
+
mint(): Promise<string>;
|
|
37
|
+
store(key: string): void;
|
|
104
38
|
say(line: string): void;
|
|
105
39
|
}
|
|
106
|
-
/** A Mnemom key that is already on this machine, and where it came from. */
|
|
107
|
-
export interface LocalMnemomKey {
|
|
108
|
-
key: string;
|
|
109
|
-
source: "env" | "store";
|
|
110
|
-
/** The stored key's API key_id, when known. */
|
|
111
|
-
keyId?: string;
|
|
112
|
-
/** The org the stored key was minted for, when known. */
|
|
113
|
-
orgId?: string;
|
|
114
|
-
}
|
|
115
|
-
/**
|
|
116
|
-
* The Mnemom key already on this machine — MNEMOM_AGENT_MNEMOM_KEY, else the key stored for the
|
|
117
|
-
* active org — or null. Never mints. Shared by the launch (which mints on null), `mnemom agent
|
|
118
|
-
* doctor` (which reports the source) and the goal commands (which send the key the launch sent).
|
|
119
|
-
*/
|
|
120
|
-
export declare function readLocalMnemomKey(deps: Pick<MnemomKeyDeps, "env" | "readStored" | "activeOrgId">): LocalMnemomKey | null;
|
|
121
|
-
/** The I/O behind checkMnemomKey (lib/api.ts apiAcceptsMnemomKey / listOwnApiKeysForCheck). */
|
|
122
|
-
export interface MnemomKeyCheckIo {
|
|
123
|
-
/** true = the API accepted the key on its own (whoami 200); false = it refused it (401/403). */
|
|
124
|
-
apiAccepts(key: string): Promise<boolean>;
|
|
125
|
-
/** The signed-in account's active keys (incl. org keys it minted), or null with no session. */
|
|
126
|
-
listOwnKeys(): Promise<Array<{
|
|
127
|
-
key_id: string;
|
|
128
|
-
}> | null>;
|
|
129
|
-
}
|
|
130
|
-
/**
|
|
131
|
-
* Is `key` a live Mnemom key? A key counts as dead (`invalid`) only when that is PROVEN;
|
|
132
|
-
* anything unproven proceeds, and the gateway refuses a dead key with a clear message.
|
|
133
|
-
*
|
|
134
|
-
* - A key whose key_id we know (this CLI minted and saved it): the signed-in account's active
|
|
135
|
-
* keys — which include the org keys it minted — either list that key_id (`valid`) or do not:
|
|
136
|
-
* the key was revoked or rotated (`invalid`). No usable session ⇒ `unknown`.
|
|
137
|
-
* - Any other key (MNEMOM_AGENT_MNEMOM_KEY, a legacy saved key): whoami with the key itself.
|
|
138
|
-
* 200 ⇒ `valid`. A refusal proves nothing — the API refuses every key without an `api:*`
|
|
139
|
-
* scope (ADR-049), so a live gateway-only key is refused exactly like a dead one ⇒ `unknown`.
|
|
140
|
-
* Key prefixes are never matched: an 8-character prefix collides across keys.
|
|
141
|
-
*
|
|
142
|
-
* Any error or timeout ⇒ `unknown`.
|
|
143
|
-
*/
|
|
144
|
-
export declare function checkMnemomKey(key: string, keyId: string | undefined, io: MnemomKeyCheckIo): Promise<MnemomKeyCheck>;
|
|
145
|
-
/**
|
|
146
|
-
* The Mnemom key every launch sends — api-key, console and subscription alike: the local key
|
|
147
|
-
* (readLocalMnemomKey); else mint one (scopes ["gateway"], org-owned, for the launch's org) and
|
|
148
|
-
* store it. The key is never printed.
|
|
149
|
-
*
|
|
150
|
-
* - MNEMOM_AGENT_MNEMOM_KEY is used as given: not checked here (nothing could prove it dead —
|
|
151
|
-
* see checkMnemomKey), never replaced, never revoked. The gateway refuses a dead one.
|
|
152
|
-
* - A saved key minted for another org than the launch's (or saved before orgs were recorded,
|
|
153
|
-
* e.g. the legacy single-field key) is replaced by one for the launch's org, unchecked.
|
|
154
|
-
* - A saved key checked once (`deps.check`) and proven dead is replaced by a fresh one.
|
|
155
|
-
* - Replacing a saved key this CLI minted revokes the old one, best-effort.
|
|
156
|
-
*
|
|
157
|
-
* THROWS when no key can be had (no launch org, or the mint is refused or fails): the gateway
|
|
158
|
-
* would refuse the session, so the launch must not start.
|
|
159
|
-
*/
|
|
160
|
-
export declare function resolveLaunchMnemomKey(deps: MnemomKeyDeps): Promise<string>;
|
|
161
|
-
/** Did the API refuse the mint (403: an API that predates member org keys, or a viewer/auditor)? */
|
|
162
|
-
export declare function isMintRefusal(err: unknown): boolean;
|
|
163
|
-
/** Store slot for a key minted with no active org (for the caller's personal org). */
|
|
164
|
-
export declare const NO_ORG_SLOT = "_none";
|
|
165
|
-
/**
|
|
166
|
-
* The key stored for `orgId` in the store document: `mnemom_api_keys[<org id | _none>]`. The
|
|
167
|
-
* pre-per-org field `mnemom_api_key` (a bare string, minted personal) still serves the no-org
|
|
168
|
-
* slot until that slot is written. CR/LF stripped; anything malformed reads as no key.
|
|
169
|
-
*/
|
|
170
|
-
export declare function readStoredMnemomKey(data: Record<string, unknown>, orgId: string | null): StoredMnemomKey | undefined;
|
|
171
40
|
/**
|
|
172
|
-
* The
|
|
173
|
-
*
|
|
174
|
-
* removes it), so a stale legacy key can never shadow the new one.
|
|
41
|
+
* The Mnemom key a subscription launch sends: MNEMOM_AGENT_MNEMOM_KEY, else the stored
|
|
42
|
+
* key, else mint one (gateway scope only) and store it. The key is never printed.
|
|
175
43
|
*/
|
|
176
|
-
export declare function
|
|
44
|
+
export declare function resolveSubscriptionMnemomKey(deps: MnemomKeyDeps): Promise<string>;
|
|
177
45
|
/**
|
|
178
46
|
* Remote Control on a subscription login is open to accounts entitled to Remote Control
|
|
179
47
|
* (internal Mnemom accounts): the RC proxy then forwards the user's own OAuth bearer to the
|