@mnemom/mnemom 0.17.6-next.1 → 0.17.6-next.3
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 +8 -2
- package/dist/commands/agent-doctor.d.ts +21 -4
- package/dist/commands/agent-doctor.js +51 -5
- package/dist/commands/agent-goal.d.ts +1 -1
- package/dist/commands/agent-goal.js +6 -3
- package/dist/commands/agent-setup.d.ts +16 -5
- package/dist/commands/agent-setup.js +29 -12
- package/dist/commands/agent.d.ts +28 -6
- package/dist/commands/agent.js +86 -31
- package/dist/commands/wrap.d.ts +8 -0
- package/dist/commands/wrap.js +36 -3
- package/dist/index.js +1 -1
- package/dist/lib/agent.d.ts +44 -8
- package/dist/lib/agent.js +36 -7
- package/dist/lib/api.d.ts +27 -2
- package/dist/lib/api.js +64 -2
- package/dist/lib/first-run/backtest.d.ts +16 -33
- package/dist/lib/first-run/backtest.js +19 -54
- package/dist/lib/first-run/index.js +1 -1
- package/dist/lib/first-run/screen.d.ts +9 -9
- package/dist/lib/first-run/screen.js +31 -20
- package/dist/lib/launcher-config.d.ts +2 -1
- package/dist/lib/subscription-login.d.ts +152 -20
- package/dist/lib/subscription-login.js +215 -28
- package/dist/mcp/handoff-server.mjs +35 -13
- package/dist/rc-proxy.mjs +6 -3
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The first-run screen: one plain terminal screen (at most
|
|
2
|
+
* The first-run screen: one plain terminal screen (at most 22 lines of at most 78
|
|
3
3
|
* columns, ASCII) built from the backtest numbers. Pure — no I/O — so every layout is
|
|
4
4
|
* unit-tested. Every number on it is recorded in the audit with its raw value and
|
|
5
5
|
* method.
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
* - No live counter is promised: `mnemom agent` has no status bar today.
|
|
26
26
|
*/
|
|
27
27
|
export declare const WIDTH = 78;
|
|
28
|
-
export declare const MAX_LINES =
|
|
28
|
+
export declare const MAX_LINES = 22;
|
|
29
29
|
/** Less history than this (API prices, in the window) is too little to backtest. */
|
|
30
30
|
export declare const MIN_HISTORY_USD = 5;
|
|
31
31
|
/** Variation A iff the shown saving is at least this many dollars and this many percent. */
|
|
@@ -33,12 +33,12 @@ export declare const STRONG_MIN_USD = 5;
|
|
|
33
33
|
export declare const STRONG_MIN_PCT = 5;
|
|
34
34
|
export declare const DAYS = 30;
|
|
35
35
|
/**
|
|
36
|
-
* The forward line:
|
|
37
|
-
*
|
|
38
|
-
*
|
|
39
|
-
* undercounts output).
|
|
36
|
+
* The forward line: chain45 S46 C2n (context runtime, aggressive profile) total bill vs
|
|
37
|
+
* stock, -20.9% [-25.6, -15.9], Opus 5.5, n=13 (r15 readout; operator 2026-10-02: quote
|
|
38
|
+
* S46, not S43), 95% CI rounded to fives, 15-25. The d240p1 ~45% figure is NOT used
|
|
39
|
+
* (its re-bill undercounts output).
|
|
40
40
|
*/
|
|
41
|
-
export declare const FORWARD_LINE = "Long sessions are where Mnemom saves the most: about 15 to 25% in our
|
|
41
|
+
export declare const FORWARD_LINE = "Long sessions are where Mnemom saves the most: about 15 to 25% in our datasets.";
|
|
42
42
|
/** Prices, promotions and plan allocations move; the saving is in usage (operator 2026-10-01). */
|
|
43
43
|
export declare const PRICE_LINE = "Prices and plan limits change. Mnemom cuts what you use, so you stay ahead.";
|
|
44
44
|
/** What `mnemom agent` does today: routes through the gateway, records, keeps context lean. */
|
|
@@ -52,8 +52,8 @@ export declare function sig3(x: number): number;
|
|
|
52
52
|
* screen. The implied saving is the shown saving, which never exceeds the raw saving.
|
|
53
53
|
*/
|
|
54
54
|
export declare function pair(total: number, saved: number): [number, number, number];
|
|
55
|
-
/** part / whole as a percentage rounded DOWN
|
|
56
|
-
export declare function
|
|
55
|
+
/** part / whole as a whole-number percentage, decimals dropped (rounded DOWN). */
|
|
56
|
+
export declare function pctDown(part: number, whole: number): number;
|
|
57
57
|
export declare function day(t: number): string;
|
|
58
58
|
export declare function usd(n: number): string;
|
|
59
59
|
export declare function clean(s: string): string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* The first-run screen: one plain terminal screen (at most
|
|
2
|
+
* The first-run screen: one plain terminal screen (at most 22 lines of at most 78
|
|
3
3
|
* columns, ASCII) built from the backtest numbers. Pure — no I/O — so every layout is
|
|
4
4
|
* unit-tested. Every number on it is recorded in the audit with its raw value and
|
|
5
5
|
* method.
|
|
@@ -26,7 +26,7 @@
|
|
|
26
26
|
*/
|
|
27
27
|
import { ESTIMATOR_METHOD } from "./backtest.js";
|
|
28
28
|
export const WIDTH = 78;
|
|
29
|
-
export const MAX_LINES =
|
|
29
|
+
export const MAX_LINES = 22;
|
|
30
30
|
/** Less history than this (API prices, in the window) is too little to backtest. */
|
|
31
31
|
export const MIN_HISTORY_USD = 5;
|
|
32
32
|
/** Variation A iff the shown saving is at least this many dollars and this many percent. */
|
|
@@ -34,14 +34,14 @@ export const STRONG_MIN_USD = 5;
|
|
|
34
34
|
export const STRONG_MIN_PCT = 5;
|
|
35
35
|
export const DAYS = 30;
|
|
36
36
|
/**
|
|
37
|
-
* The forward line:
|
|
38
|
-
*
|
|
39
|
-
*
|
|
40
|
-
* undercounts output).
|
|
37
|
+
* The forward line: chain45 S46 C2n (context runtime, aggressive profile) total bill vs
|
|
38
|
+
* stock, -20.9% [-25.6, -15.9], Opus 5.5, n=13 (r15 readout; operator 2026-10-02: quote
|
|
39
|
+
* S46, not S43), 95% CI rounded to fives, 15-25. The d240p1 ~45% figure is NOT used
|
|
40
|
+
* (its re-bill undercounts output).
|
|
41
41
|
*/
|
|
42
|
-
export const FORWARD_LINE = "Long sessions are where Mnemom saves the most: about 15 to 25% in our
|
|
43
|
-
const FORWARD_SOURCE = "operator 2026-10-
|
|
44
|
-
"rounded to 15 to 25; measured vs stock
|
|
42
|
+
export const FORWARD_LINE = "Long sessions are where Mnemom saves the most: about 15 to 25% in our datasets.";
|
|
43
|
+
const FORWARD_SOURCE = "operator 2026-10-02: S46 C2n total bill -20.9% [-25.6, -15.9] (Opus 5.5, n=13), 95% CI " +
|
|
44
|
+
"rounded to fives, 15 to 25; measured vs stock";
|
|
45
45
|
/** Prices, promotions and plan allocations move; the saving is in usage (operator 2026-10-01). */
|
|
46
46
|
export const PRICE_LINE = "Prices and plan limits change. Mnemom cuts what you use, so you stay ahead.";
|
|
47
47
|
/** What `mnemom agent` does today: routes through the gateway, records, keeps context lean. */
|
|
@@ -73,11 +73,11 @@ export function pair(total, saved) {
|
|
|
73
73
|
const tot = sig3(total);
|
|
74
74
|
return [tot, Math.min(sv, tot), Math.max(tot - sv, 0)];
|
|
75
75
|
}
|
|
76
|
-
/** part / whole as a percentage rounded DOWN
|
|
77
|
-
export function
|
|
76
|
+
/** part / whole as a whole-number percentage, decimals dropped (rounded DOWN). */
|
|
77
|
+
export function pctDown(part, whole) {
|
|
78
78
|
if (whole <= 0 || part <= 0)
|
|
79
79
|
return 0;
|
|
80
|
-
return Math.floor((100 * part) / whole
|
|
80
|
+
return Math.floor((100 * part) / whole + 1e-9);
|
|
81
81
|
}
|
|
82
82
|
const MONTHS = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
|
|
83
83
|
export function day(t) {
|
|
@@ -126,17 +126,17 @@ const SAVED_METHOD = `backtest.estimate(): ${ESTIMATOR_METHOD}; 2 sig figs DOWN`
|
|
|
126
126
|
function subLines(sub, A) {
|
|
127
127
|
if (!sub)
|
|
128
128
|
return [];
|
|
129
|
-
const p =
|
|
129
|
+
const p = pctDown(sub.saved, sub.actual);
|
|
130
130
|
const raw = sub.actual > 0 ? (100 * sub.saved) / sub.actual : 0;
|
|
131
131
|
if (p < 5) {
|
|
132
|
-
A("sub_line_omitted", { shown: true, raw, method: "usage cut
|
|
132
|
+
A("sub_line_omitted", { shown: true, raw, method: "usage cut below 5% (decimals dropped)" });
|
|
133
133
|
return [];
|
|
134
134
|
}
|
|
135
135
|
A("sub_usage_pct", {
|
|
136
136
|
shown: p,
|
|
137
137
|
raw,
|
|
138
138
|
method: "saving / API-price cost over the subscription sessions in the window (all sessions if " +
|
|
139
|
-
"none is tagged); cost-weighted,
|
|
139
|
+
"none is tagged); cost-weighted, decimals dropped",
|
|
140
140
|
});
|
|
141
141
|
return wrap(`On your subscription that is about ${p}% less usage: fewer limit hits, and less ` +
|
|
142
142
|
"overage if you use extra usage.");
|
|
@@ -151,7 +151,7 @@ export function buildScreen(inp) {
|
|
|
151
151
|
const actual = ses.reduce((t, r) => t + r.actual, 0);
|
|
152
152
|
const saved = ses.reduce((t, r) => t + r.saved, 0);
|
|
153
153
|
const [a, s, e] = pair(actual, saved);
|
|
154
|
-
const p =
|
|
154
|
+
const p = pctDown(saved, actual);
|
|
155
155
|
const enough = actual >= MIN_HISTORY_USD;
|
|
156
156
|
const variation = enough && s >= STRONG_MIN_USD && p >= STRONG_MIN_PCT ? "A" : enough ? "B" : "C";
|
|
157
157
|
A("variation", { shown: variation, raw: { actual, saved }, method: "see screen.ts header" });
|
|
@@ -162,7 +162,11 @@ export function buildScreen(inp) {
|
|
|
162
162
|
L.push("");
|
|
163
163
|
if (variation === "A") {
|
|
164
164
|
A("spent_usd", { shown: a, raw: actual, method: SPENT_METHOD });
|
|
165
|
-
A("saved_pct", {
|
|
165
|
+
A("saved_pct", {
|
|
166
|
+
shown: p,
|
|
167
|
+
raw: (100 * saved) / actual,
|
|
168
|
+
method: "decimals dropped (rounded DOWN)",
|
|
169
|
+
});
|
|
166
170
|
const viaRaw = ses.reduce((t, r) => t + (r.viaMnemom ? r.saved : 0), 0);
|
|
167
171
|
const via = sig2(viaRaw);
|
|
168
172
|
const rest = sig2(saved - viaRaw);
|
|
@@ -170,12 +174,14 @@ export function buildScreen(inp) {
|
|
|
170
174
|
A("saved_usd", { shown: s, raw: saved, method: SAVED_METHOD });
|
|
171
175
|
A("with_mnemom_usd", { shown: e, raw: actual - saved, method: "spent shown - saved shown" });
|
|
172
176
|
L.push(...wrap(`At API prices that usage cost about ${usd(a)}. With Mnemom: about ${usd(e)}.`));
|
|
177
|
+
L.push("");
|
|
173
178
|
L.push(...wrap(`That's about ${usd(s)} less (${p}%), and you don't change how you work.`));
|
|
174
179
|
}
|
|
175
180
|
else {
|
|
176
181
|
const m = `${SAVED_METHOD}; sessions the launch ledger shows ran through Mnemom`;
|
|
177
182
|
A("saved_via_mnemom_usd", { shown: via, raw: viaRaw, method: m });
|
|
178
183
|
L.push(...wrap(`At API prices that usage comes to about ${usd(a)} without Mnemom.`));
|
|
184
|
+
L.push("");
|
|
179
185
|
if (rest < 1) {
|
|
180
186
|
L.push(...wrap(`Mnemom saved you about ${usd(via)} of it (${p}%), and you didn't change how you work.`));
|
|
181
187
|
}
|
|
@@ -202,11 +208,14 @@ export function buildScreen(inp) {
|
|
|
202
208
|
raw: big.actual - big.saved,
|
|
203
209
|
method: "its cost shown - its saving (2 sig figs DOWN)",
|
|
204
210
|
});
|
|
211
|
+
L.push("");
|
|
205
212
|
const where = big.label ? `${big.label} on ${day(big.end)}` : `on ${day(big.end)}`;
|
|
206
213
|
L.push(...wrap(big.viaMnemom
|
|
207
214
|
? `Your biggest session, ${where}: ${usd(ba)} without Mnemom, about ${usd(be)} with it.`
|
|
208
215
|
: `Your biggest session, ${where}: ${usd(ba)}, with Mnemom about ${usd(be)}.`));
|
|
209
|
-
|
|
216
|
+
const subL = subLines(inp.sub, A);
|
|
217
|
+
if (subL.length)
|
|
218
|
+
L.push("", ...subL);
|
|
210
219
|
}
|
|
211
220
|
else {
|
|
212
221
|
if (variation === "B") {
|
|
@@ -219,10 +228,12 @@ export function buildScreen(inp) {
|
|
|
219
228
|
L.push(...wrap(`Your sessions used about ${usd(a)} at API prices. They stayed small, so Mnemom ` +
|
|
220
229
|
"wouldn't have changed that much."));
|
|
221
230
|
}
|
|
222
|
-
|
|
231
|
+
if (variation === "B")
|
|
232
|
+
L.push("");
|
|
233
|
+
L.push(...wrap(FORWARD_LINE));
|
|
223
234
|
A("forward_range_pct", {
|
|
224
235
|
shown: "15 to 25",
|
|
225
|
-
raw: [-
|
|
236
|
+
raw: [-25.6, -20.9, -15.9],
|
|
226
237
|
method: FORWARD_SOURCE,
|
|
227
238
|
});
|
|
228
239
|
}
|
|
@@ -58,7 +58,8 @@ export interface LauncherConfig {
|
|
|
58
58
|
/**
|
|
59
59
|
* How the gateway folds each session's context (`balanced` when unset): `off` leaves
|
|
60
60
|
* compaction to the coding agent, `balanced` keeps more earlier work verbatim, `aggressive`
|
|
61
|
-
* folds earlier with a tighter working set
|
|
61
|
+
* folds earlier with a tighter working set, `adaptive` sizes the fold to the conversation
|
|
62
|
+
* (none below 200k tokens, aggressive up to 1M, balanced above). `--context-profile` overrides it per launch.
|
|
62
63
|
*/
|
|
63
64
|
contextProfile?: ContextProfile;
|
|
64
65
|
/**
|
|
@@ -1,15 +1,40 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `mnemom agent`
|
|
3
|
-
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
2
|
+
* `mnemom agent` launch auth: the `auth` setting (api-key | console | subscription) and the
|
|
3
|
+
* Mnemom API key EVERY launch sends.
|
|
4
|
+
*
|
|
5
|
+
* The Mnemom key (`x-mnemom-api-key`) rides on every governed request a launch makes, for every
|
|
6
|
+
* auth mode and launch shape: the gateway refuses `mnemom agent` traffic that carries no
|
|
7
|
+
* verified Mnemom key. This module resolves it — env, then the key stored for the active org in
|
|
8
|
+
* the 0600 store, then a freshly minted gateway-only key — checks it once (a revoked or rotated
|
|
9
|
+
* stored key is replaced), and a launch that cannot resolve one refuses to start.
|
|
10
|
+
*
|
|
11
|
+
* Which org a key belongs to: the key is minted FOR the launch's org — the active org, else the
|
|
12
|
+
* caller's personal org, i.e. the org the launcher claims the agent into — as an org-owned key
|
|
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.
|
|
13
38
|
*
|
|
14
39
|
* Remote Control is internal-only (see subscriptionShape); the context-handoff tool
|
|
15
40
|
* authenticates with an Anthropic key, so it is off on a subscription launch.
|
|
@@ -22,26 +47,133 @@ export type AgentAuth = "api-key" | "subscription" | "console";
|
|
|
22
47
|
export declare const AGENT_AUTHS: readonly AgentAuth[];
|
|
23
48
|
/** Env override for the setting (the launcher.toml `auth` key folds into it). */
|
|
24
49
|
export declare const AGENT_AUTH_ENV = "MNEMOM_AGENT_AUTH";
|
|
25
|
-
/** Env override for the Mnemom key
|
|
50
|
+
/** Env override for the Mnemom key every launch sends. */
|
|
26
51
|
export declare const MNEMOM_KEY_ENV = "MNEMOM_AGENT_MNEMOM_KEY";
|
|
27
|
-
/**
|
|
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
|
+
*/
|
|
28
56
|
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";
|
|
29
62
|
export declare function coerceAgentAuth(raw: string): AgentAuth;
|
|
30
63
|
/** `--auth` flag > MNEMOM_AGENT_AUTH (launcher.toml folds in here) > api-key. */
|
|
31
64
|
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";
|
|
32
79
|
export interface MnemomKeyDeps {
|
|
33
80
|
env: Record<string, string | undefined>;
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
81
|
+
/**
|
|
82
|
+
* The active org (`mnemom org use`), or null when none is set. The store holds one key per
|
|
83
|
+
* org: a minted key belongs to the org that was active when it was minted.
|
|
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>;
|
|
38
104
|
say(line: string): void;
|
|
39
105
|
}
|
|
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;
|
|
40
171
|
/**
|
|
41
|
-
* The
|
|
42
|
-
*
|
|
172
|
+
* The mergeStore patch that saves `key` for `orgId` — replacing that org's key, keeping every
|
|
173
|
+
* other org's. Writing the no-org slot retires the legacy `mnemom_api_key` field (a null value
|
|
174
|
+
* removes it), so a stale legacy key can never shadow the new one.
|
|
43
175
|
*/
|
|
44
|
-
export declare function
|
|
176
|
+
export declare function storePatchForMnemomKey(data: Record<string, unknown>, orgId: string | null, key: StoredMnemomKey): Record<string, unknown>;
|
|
45
177
|
/**
|
|
46
178
|
* Remote Control on a subscription login is open to accounts entitled to Remote Control
|
|
47
179
|
* (internal Mnemom accounts): the RC proxy then forwards the user's own OAuth bearer to the
|