@mnemom/mnemom 0.17.0-next.6 → 0.17.0-next.8
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 +26 -0
- package/dist/commands/agent-config.d.ts +29 -0
- package/dist/commands/agent-config.js +193 -0
- package/dist/commands/{code-doctor.d.ts → agent-doctor.d.ts} +2 -2
- package/dist/commands/{code-doctor.js → agent-doctor.js} +27 -22
- package/dist/commands/{code-invite.d.ts → agent-invite.d.ts} +18 -18
- package/dist/commands/{code-invite.js → agent-invite.js} +30 -30
- package/dist/commands/agent-session.d.ts +68 -0
- package/dist/commands/agent-session.js +114 -0
- package/dist/commands/{code-setup.d.ts → agent-setup.d.ts} +13 -13
- package/dist/commands/{code-setup.js → agent-setup.js} +46 -42
- package/dist/commands/{code.d.ts → agent.d.ts} +50 -14
- package/dist/commands/{code.js → agent.js} +144 -86
- package/dist/commands/agents.d.ts +2 -2
- package/dist/commands/agents.js +5 -5
- package/dist/commands/onboard.js +1 -1
- package/dist/commands/wrap.js +1 -1
- package/dist/index.js +59 -51
- package/dist/lib/{code.d.ts → agent.d.ts} +52 -10
- package/dist/lib/{code.js → agent.js} +94 -15
- package/dist/lib/api.d.ts +4 -4
- package/dist/lib/api.js +9 -9
- package/dist/lib/auth.js +21 -1
- package/dist/lib/{code-config.d.ts → launcher-config.d.ts} +25 -23
- package/dist/lib/{code-config.js → launcher-config.js} +50 -31
- package/dist/lib/oauth.d.ts +26 -4
- package/dist/lib/oauth.js +98 -29
- package/dist/lib/version-gate.js +1 -1
- package/dist/rc-proxy.mjs +309 -136
- package/package.json +7 -3
- package/dist/commands/code-config.d.ts +0 -17
- package/dist/commands/code-config.js +0 -147
- package/dist/commands/code-session.d.ts +0 -52
- package/dist/commands/code-session.js +0 -78
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mnemom agent` with no session name — the interactive first-run setup.
|
|
3
|
+
*
|
|
4
|
+
* The daily command is just `mnemom agent` (the Claude Code pattern: install
|
|
5
|
+
* once, then the bare command). When the positional session name is omitted in
|
|
6
|
+
* a terminal we ask two things, explaining each in a sentence:
|
|
7
|
+
*
|
|
8
|
+
* 1. a SESSION NAME — labels the session in traces and the claude.ai session
|
|
9
|
+
* list (defaults to the current folder's name);
|
|
10
|
+
* 2. GOAL ALIGNMENT — one of three:
|
|
11
|
+
* - INFER it from your messages (implicit mode): nothing to type; the
|
|
12
|
+
* gateway reads your own messages, revises the goal as you steer, and the
|
|
13
|
+
* judge nudges the agent back when it drifts (a little µ per new message
|
|
14
|
+
* and per judged turn). Sends `x-mnemom-goal-mode: implicit`, no contract.
|
|
15
|
+
* - TYPE a one-line goal: sealed as a contract for the session; the judge
|
|
16
|
+
* nudges against it (a little µ per turn). Sends `x-mnemom-contract`.
|
|
17
|
+
* - OFF: the session runs governed with goal alignment off — neither header
|
|
18
|
+
* is sent, so the gateway's goal hooks are simply not engaged.
|
|
19
|
+
*
|
|
20
|
+
* Non-interactive runs (pipes, CI) never prompt — they get a clear error asking
|
|
21
|
+
* for a name. `--goal` on the command line always wins over the prompt, and a
|
|
22
|
+
* resolved implicit launch (`--implicit`, or launcher.toml `goal_mode =
|
|
23
|
+
* "implicit"` with no `--no-implicit`) skips it too. Pure apart from the
|
|
24
|
+
* injected `ask` functions, so every arm is unit-tested.
|
|
25
|
+
*/
|
|
26
|
+
export interface SessionAsk {
|
|
27
|
+
askInput(question: string): Promise<string>;
|
|
28
|
+
askYesNo(question: string, defaultYes: boolean): Promise<boolean>;
|
|
29
|
+
/** Numbered single-select; resolves the chosen label, or null on no/invalid choice. */
|
|
30
|
+
askSelect(question: string, options: string[]): Promise<string | null>;
|
|
31
|
+
}
|
|
32
|
+
export interface SessionSetupInput {
|
|
33
|
+
/** The positional `[scenario]` (session name), if given. */
|
|
34
|
+
scenario?: string;
|
|
35
|
+
/** `--goal <statement>`, if given — skips the goal prompt. */
|
|
36
|
+
goal?: string;
|
|
37
|
+
/** Resolved implicit mode (flag or config default) — skips the goal prompt; alignment on without a contract. */
|
|
38
|
+
implicit?: boolean;
|
|
39
|
+
interactive: boolean;
|
|
40
|
+
/** For the default session name (tests inject one). */
|
|
41
|
+
cwd?: string;
|
|
42
|
+
/** Narration sink (stderr by default; tests capture). */
|
|
43
|
+
say?: (line?: string) => void;
|
|
44
|
+
}
|
|
45
|
+
export interface SessionSetup {
|
|
46
|
+
scenario: string;
|
|
47
|
+
/** The goal statement to seal, or undefined = no sealed contract (implicit or off). */
|
|
48
|
+
goal?: string;
|
|
49
|
+
goalAlignment: "on" | "implicit" | "off";
|
|
50
|
+
/** True when the terminal prompts ran. */
|
|
51
|
+
prompted: boolean;
|
|
52
|
+
}
|
|
53
|
+
export declare const NO_SESSION_NAME_MESSAGE: string;
|
|
54
|
+
/** The three goal-alignment choices offered by the interactive prompt (labels are the select options). */
|
|
55
|
+
export declare const GOAL_CHOICE_IMPLICIT = "Infer my goal from my messages \u2014 nothing to type; revised as I steer (implicit mode)";
|
|
56
|
+
export declare const GOAL_CHOICE_TYPED = "Type a one-line goal \u2014 sealed as a contract for this session";
|
|
57
|
+
export declare const GOAL_CHOICE_OFF = "Off \u2014 run governed with goal alignment off (Enter)";
|
|
58
|
+
export declare const GOAL_CHOICES: readonly string[];
|
|
59
|
+
export declare const GOAL_CHOICE_QUESTION = "Goal alignment for this session?";
|
|
60
|
+
/** Current folder name, sanitised like an agent slug; "session" when that is empty. */
|
|
61
|
+
export declare function defaultSessionName(cwd?: string): string;
|
|
62
|
+
/** The one-line status printed at launch so the customer always knows the mode. */
|
|
63
|
+
export declare function goalAlignmentLine(mode: boolean | "on" | "implicit" | "off"): string;
|
|
64
|
+
/**
|
|
65
|
+
* Resolve the session name + goal for this launch. See the module doc for the
|
|
66
|
+
* rules. Throws NO_SESSION_NAME_MESSAGE when no name was given and we cannot ask.
|
|
67
|
+
*/
|
|
68
|
+
export declare function resolveSessionSetup(input: SessionSetupInput, ask: SessionAsk): Promise<SessionSetup>;
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mnemom agent` with no session name — the interactive first-run setup.
|
|
3
|
+
*
|
|
4
|
+
* The daily command is just `mnemom agent` (the Claude Code pattern: install
|
|
5
|
+
* once, then the bare command). When the positional session name is omitted in
|
|
6
|
+
* a terminal we ask two things, explaining each in a sentence:
|
|
7
|
+
*
|
|
8
|
+
* 1. a SESSION NAME — labels the session in traces and the claude.ai session
|
|
9
|
+
* list (defaults to the current folder's name);
|
|
10
|
+
* 2. GOAL ALIGNMENT — one of three:
|
|
11
|
+
* - INFER it from your messages (implicit mode): nothing to type; the
|
|
12
|
+
* gateway reads your own messages, revises the goal as you steer, and the
|
|
13
|
+
* judge nudges the agent back when it drifts (a little µ per new message
|
|
14
|
+
* and per judged turn). Sends `x-mnemom-goal-mode: implicit`, no contract.
|
|
15
|
+
* - TYPE a one-line goal: sealed as a contract for the session; the judge
|
|
16
|
+
* nudges against it (a little µ per turn). Sends `x-mnemom-contract`.
|
|
17
|
+
* - OFF: the session runs governed with goal alignment off — neither header
|
|
18
|
+
* is sent, so the gateway's goal hooks are simply not engaged.
|
|
19
|
+
*
|
|
20
|
+
* Non-interactive runs (pipes, CI) never prompt — they get a clear error asking
|
|
21
|
+
* for a name. `--goal` on the command line always wins over the prompt, and a
|
|
22
|
+
* resolved implicit launch (`--implicit`, or launcher.toml `goal_mode =
|
|
23
|
+
* "implicit"` with no `--no-implicit`) skips it too. Pure apart from the
|
|
24
|
+
* injected `ask` functions, so every arm is unit-tested.
|
|
25
|
+
*/
|
|
26
|
+
import { basename } from "node:path";
|
|
27
|
+
import { sanitizeAgentName } from "../lib/agent.js";
|
|
28
|
+
export const NO_SESSION_NAME_MESSAGE = "mnemom agent: a session name is required here (e.g. `mnemom agent onboarding`). " +
|
|
29
|
+
"In a terminal, plain `mnemom agent` asks for one.";
|
|
30
|
+
/** The three goal-alignment choices offered by the interactive prompt (labels are the select options). */
|
|
31
|
+
export const GOAL_CHOICE_IMPLICIT = "Infer my goal from my messages — nothing to type; revised as I steer (implicit mode)";
|
|
32
|
+
export const GOAL_CHOICE_TYPED = "Type a one-line goal — sealed as a contract for this session";
|
|
33
|
+
export const GOAL_CHOICE_OFF = "Off — run governed with goal alignment off (Enter)";
|
|
34
|
+
export const GOAL_CHOICES = [
|
|
35
|
+
GOAL_CHOICE_IMPLICIT,
|
|
36
|
+
GOAL_CHOICE_TYPED,
|
|
37
|
+
GOAL_CHOICE_OFF,
|
|
38
|
+
];
|
|
39
|
+
export const GOAL_CHOICE_QUESTION = "Goal alignment for this session?";
|
|
40
|
+
/** Current folder name, sanitised like an agent slug; "session" when that is empty. */
|
|
41
|
+
export function defaultSessionName(cwd = process.cwd()) {
|
|
42
|
+
return sanitizeAgentName(basename(cwd)) || "session";
|
|
43
|
+
}
|
|
44
|
+
/** The one-line status printed at launch so the customer always knows the mode. */
|
|
45
|
+
export function goalAlignmentLine(mode) {
|
|
46
|
+
const m = mode === true ? "on" : mode === false ? "off" : mode;
|
|
47
|
+
if (m === "implicit") {
|
|
48
|
+
return ("mnemom agent: goal alignment: on, implicit (no sealed contract — the gateway infers your goal " +
|
|
49
|
+
"from your own messages, revises it as you steer, and the judge nudges the agent back when it drifts)");
|
|
50
|
+
}
|
|
51
|
+
return m === "on"
|
|
52
|
+
? "mnemom agent: goal alignment: on (the judge nudges the agent back when it drifts from your goal)"
|
|
53
|
+
: "mnemom agent: goal alignment: off (no goal set — pass --goal or --implicit, or set one when prompted)";
|
|
54
|
+
}
|
|
55
|
+
const defaultSay = (line = "") => console.error(line);
|
|
56
|
+
/**
|
|
57
|
+
* Resolve the session name + goal for this launch. See the module doc for the
|
|
58
|
+
* rules. Throws NO_SESSION_NAME_MESSAGE when no name was given and we cannot ask.
|
|
59
|
+
*/
|
|
60
|
+
export async function resolveSessionSetup(input, ask) {
|
|
61
|
+
const say = input.say ?? defaultSay;
|
|
62
|
+
const flagGoal = (input.goal ?? "").trim();
|
|
63
|
+
const implicit = input.implicit === true;
|
|
64
|
+
const given = (input.scenario ?? "").trim();
|
|
65
|
+
if (given) {
|
|
66
|
+
return {
|
|
67
|
+
scenario: given,
|
|
68
|
+
goal: flagGoal || undefined,
|
|
69
|
+
goalAlignment: flagGoal ? "on" : implicit ? "implicit" : "off",
|
|
70
|
+
prompted: false,
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
if (!input.interactive)
|
|
74
|
+
throw new Error(NO_SESSION_NAME_MESSAGE);
|
|
75
|
+
// ── 1. session name ──
|
|
76
|
+
const fallback = defaultSessionName(input.cwd);
|
|
77
|
+
say();
|
|
78
|
+
say("Session name — labels this session in your traces and the claude.ai session list.");
|
|
79
|
+
say(` (Next time you can pass it directly: mnemom agent <name>.)`);
|
|
80
|
+
const typed = await ask.askInput(`Session name [${fallback}]:`);
|
|
81
|
+
const scenario = sanitizeAgentName(typed.trim()) || fallback;
|
|
82
|
+
// ── 2. goal alignment (skipped when --goal or implicit mode was resolved) ──
|
|
83
|
+
if (flagGoal) {
|
|
84
|
+
return { scenario, goal: flagGoal, goalAlignment: "on", prompted: true };
|
|
85
|
+
}
|
|
86
|
+
if (implicit) {
|
|
87
|
+
return { scenario, goalAlignment: "implicit", prompted: true };
|
|
88
|
+
}
|
|
89
|
+
say();
|
|
90
|
+
say("Goal alignment — how Mnemom keeps this session on track. Three choices:");
|
|
91
|
+
say(" Infer: nothing to type — the gateway reads your own messages, revises the goal as you");
|
|
92
|
+
say(" steer, and the judge nudges the agent back when it drifts (a little µ per message + turn).");
|
|
93
|
+
say(" Type a goal: one line, sealed as a contract; the judge nudges against it (a little µ per turn).");
|
|
94
|
+
say(" Off: the session runs governed with goal alignment off (the default — just press Enter).");
|
|
95
|
+
say(" (Make one the default: mnemom agent config set goal_mode implicit|off.)");
|
|
96
|
+
const choice = await ask.askSelect(GOAL_CHOICE_QUESTION, [...GOAL_CHOICES]);
|
|
97
|
+
if (choice === GOAL_CHOICE_IMPLICIT) {
|
|
98
|
+
return { scenario, goalAlignment: "implicit", prompted: true };
|
|
99
|
+
}
|
|
100
|
+
if (choice === GOAL_CHOICE_TYPED) {
|
|
101
|
+
const goal = (await ask.askInput("Goal (one line):")).trim();
|
|
102
|
+
if (!goal) {
|
|
103
|
+
say(" No goal entered — continuing with goal alignment off.");
|
|
104
|
+
return { scenario, goalAlignment: "off", prompted: true };
|
|
105
|
+
}
|
|
106
|
+
return { scenario, goal, goalAlignment: "on", prompted: true };
|
|
107
|
+
}
|
|
108
|
+
// Enter (no pick) and any invalid pick both resolve to null → off. Off is the
|
|
109
|
+
// deliberate default for now: a µ-costing mode is never picked by a bare Enter.
|
|
110
|
+
if (choice !== GOAL_CHOICE_OFF) {
|
|
111
|
+
say(" Goal alignment off (press 1 or 2 next time to turn it on).");
|
|
112
|
+
}
|
|
113
|
+
return { scenario, goalAlignment: "off", prompted: true };
|
|
114
|
+
}
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `mnemom
|
|
3
|
-
* `mnemom
|
|
2
|
+
* `mnemom agent setup` + the zero-friction provisioning behind a bare
|
|
3
|
+
* `mnemom agent <scenario>`.
|
|
4
4
|
*
|
|
5
|
-
* If a customer names no agent, `mnemom
|
|
6
|
-
* governed identity `
|
|
5
|
+
* If a customer names no agent, `mnemom agent` launches under a per-customer
|
|
6
|
+
* governed identity `agent-<handle>`. This module makes that identity REAL in
|
|
7
7
|
* their Mnemom org: it births the agent through the gateway, claims it (so the
|
|
8
8
|
* customer owns it), and publishes a sane default coding posture. The CARDS are
|
|
9
9
|
* observe-only (visibility, no active intervention); the goal contract is what
|
|
@@ -24,15 +24,15 @@
|
|
|
24
24
|
* putAlignmentCard/putProtectionCard (lib/api.ts) — rather than reinventing it.
|
|
25
25
|
*/
|
|
26
26
|
/**
|
|
27
|
-
* The default governed-agent slug for the current customer: `
|
|
27
|
+
* The default governed-agent slug for the current customer: `agent-<handle>`,
|
|
28
28
|
* where <handle> is the local-part of their mnemom login email (sanitised), or
|
|
29
29
|
* "user" when no email is available (API-key auth / opaque OAuth token).
|
|
30
30
|
*/
|
|
31
31
|
export declare function defaultAgentSlug(): string;
|
|
32
32
|
/**
|
|
33
|
-
* The default slug resolved from the authenticated IDENTITY: `
|
|
33
|
+
* The default slug resolved from the authenticated IDENTITY: `agent-<handle>` from
|
|
34
34
|
* the login email fetched via `/v1/auth/me`. The CLI's stored OAuth token carries
|
|
35
|
-
* no email, so the sync `defaultAgentSlug()` alone falls back to "
|
|
35
|
+
* no email, so the sync `defaultAgentSlug()` alone falls back to "agent-user";
|
|
36
36
|
* this fetches the real email once a session exists. Falls back to
|
|
37
37
|
* `defaultAgentSlug()` on any failure. Call it AFTER the session is ensured.
|
|
38
38
|
*/
|
|
@@ -60,12 +60,12 @@ export interface EnsureAgentResult {
|
|
|
60
60
|
* allowed here (non-interactive without --setup, or not logged in), or when the
|
|
61
61
|
* customer declines the confirm — in all those cases the launch continues under
|
|
62
62
|
* the given slug. THROWS only on an actual provisioning failure (birth/claim/
|
|
63
|
-
* card write) so the caller can decide whether that is fatal (`mnemom
|
|
63
|
+
* card write) so the caller can decide whether that is fatal (`mnemom agent
|
|
64
64
|
* setup`) or a warn-and-continue (a bare launch).
|
|
65
65
|
*/
|
|
66
66
|
export declare function ensureGovernedAgent(opts: EnsureAgentOptions): Promise<EnsureAgentResult>;
|
|
67
|
-
/** `mnemom
|
|
68
|
-
export declare function
|
|
67
|
+
/** `mnemom agent setup [--agent <slug>]` — the explicit provisioning entry point. */
|
|
68
|
+
export declare function agentSetupCommand(opts?: {
|
|
69
69
|
agent?: string;
|
|
70
70
|
}): Promise<void>;
|
|
71
71
|
/** Thrown when the agent's org has no spendable MU balance. The user-facing
|
|
@@ -77,7 +77,7 @@ export declare class MuInsufficientError extends Error {
|
|
|
77
77
|
/**
|
|
78
78
|
* The preamble errors whose guidance is ALREADY printed when thrown — callers
|
|
79
79
|
* exit 1 quietly instead of re-printing them as "Error: …". One predicate so the
|
|
80
|
-
* two catch sites (`mnemom
|
|
80
|
+
* two catch sites (`mnemom agent` and `mnemom agent setup`) cannot drift.
|
|
81
81
|
*/
|
|
82
82
|
export declare function isQuietPreambleExit(err: unknown): boolean;
|
|
83
83
|
/**
|
|
@@ -93,7 +93,7 @@ export declare function ensureMnemomSession(opts?: {
|
|
|
93
93
|
}): Promise<boolean>;
|
|
94
94
|
/**
|
|
95
95
|
* Enforce a positive Mnemom Units balance on the org the agent lives in.
|
|
96
|
-
* `mnemom
|
|
96
|
+
* `mnemom agent` has NO free tier — a determined zero/negative balance (or an org
|
|
97
97
|
* with no billing account) is BLOCKED with a portal-style top-up message.
|
|
98
98
|
* Fails OPEN on an inconclusive error (transient 5xx / network / 403), since the
|
|
99
99
|
* gateway is the real enforcement and this is a friendly pre-check; hard-blocks
|
|
@@ -101,7 +101,7 @@ export declare function ensureMnemomSession(opts?: {
|
|
|
101
101
|
*/
|
|
102
102
|
export declare function assertMuBalance(orgId: string, orgLabel: string): Promise<void>;
|
|
103
103
|
/**
|
|
104
|
-
* The shared pre-launch preamble for `mnemom
|
|
104
|
+
* The shared pre-launch preamble for `mnemom agent` (and `mnemom agent setup`):
|
|
105
105
|
* ensure a Mnemom session (login/sign-up), then enforce the MU balance on the
|
|
106
106
|
* org the agent lives in (default: the user's personal org). Returns the
|
|
107
107
|
* resolved org so the caller can reuse it. Throws with clear guidance when there
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `mnemom
|
|
3
|
-
* `mnemom
|
|
2
|
+
* `mnemom agent setup` + the zero-friction provisioning behind a bare
|
|
3
|
+
* `mnemom agent <scenario>`.
|
|
4
4
|
*
|
|
5
|
-
* If a customer names no agent, `mnemom
|
|
6
|
-
* governed identity `
|
|
5
|
+
* If a customer names no agent, `mnemom agent` launches under a per-customer
|
|
6
|
+
* governed identity `agent-<handle>`. This module makes that identity REAL in
|
|
7
7
|
* their Mnemom org: it births the agent through the gateway, claims it (so the
|
|
8
8
|
* customer owns it), and publishes a sane default coding posture. The CARDS are
|
|
9
9
|
* observe-only (visibility, no active intervention); the goal contract is what
|
|
@@ -29,15 +29,15 @@ import { getActiveOrg } from "../lib/cli-config.js";
|
|
|
29
29
|
import { getWebsiteUrl } from "../lib/config.js";
|
|
30
30
|
import { fmt } from "../lib/format.js";
|
|
31
31
|
import { askYesNo, isInteractive } from "../lib/prompt.js";
|
|
32
|
-
import { resolveGatewayHost, sanitizeAgentName } from "../lib/
|
|
33
|
-
import { configKeySpec,
|
|
32
|
+
import { resolveGatewayHost, sanitizeAgentName } from "../lib/agent.js";
|
|
33
|
+
import { configKeySpec, loadLauncherConfig, writeLauncherConfig } from "../lib/launcher-config.js";
|
|
34
34
|
import { deriveHashProof } from "./agents.js";
|
|
35
35
|
import { birthThroughGateway } from "./wrap.js";
|
|
36
|
-
import { resolveAnthropicKey } from "./
|
|
37
|
-
import { assertCodeEnabled, CodeNotEnabledError } from "./
|
|
36
|
+
import { resolveAnthropicKey } from "./agent.js";
|
|
37
|
+
import { assertCodeEnabled, CodeNotEnabledError } from "./agent-invite.js";
|
|
38
38
|
const say = (line = "") => console.error(line);
|
|
39
39
|
/**
|
|
40
|
-
* The default governed-agent slug for the current customer: `
|
|
40
|
+
* The default governed-agent slug for the current customer: `agent-<handle>`,
|
|
41
41
|
* where <handle> is the local-part of their mnemom login email (sanitised), or
|
|
42
42
|
* "user" when no email is available (API-key auth / opaque OAuth token).
|
|
43
43
|
*/
|
|
@@ -45,12 +45,12 @@ export function defaultAgentSlug() {
|
|
|
45
45
|
const email = getAuthInfo()?.email ?? "";
|
|
46
46
|
const local = email.split("@")[0] ?? "";
|
|
47
47
|
const handle = sanitizeAgentName(local) || "user";
|
|
48
|
-
return `
|
|
48
|
+
return `agent-${handle}`;
|
|
49
49
|
}
|
|
50
50
|
/**
|
|
51
|
-
* The default slug resolved from the authenticated IDENTITY: `
|
|
51
|
+
* The default slug resolved from the authenticated IDENTITY: `agent-<handle>` from
|
|
52
52
|
* the login email fetched via `/v1/auth/me`. The CLI's stored OAuth token carries
|
|
53
|
-
* no email, so the sync `defaultAgentSlug()` alone falls back to "
|
|
53
|
+
* no email, so the sync `defaultAgentSlug()` alone falls back to "agent-user";
|
|
54
54
|
* this fetches the real email once a session exists. Falls back to
|
|
55
55
|
* `defaultAgentSlug()` on any failure. Call it AFTER the session is ensured.
|
|
56
56
|
*/
|
|
@@ -59,7 +59,7 @@ export async function resolveDefaultSlug() {
|
|
|
59
59
|
const email = (await getMe()).email ?? "";
|
|
60
60
|
const handle = sanitizeAgentName(email.split("@")[0] ?? "");
|
|
61
61
|
if (handle)
|
|
62
|
-
return `
|
|
62
|
+
return `agent-${handle}`;
|
|
63
63
|
}
|
|
64
64
|
catch {
|
|
65
65
|
// fall through to the token-based best-effort
|
|
@@ -72,7 +72,7 @@ export async function resolveDefaultSlug() {
|
|
|
72
72
|
* allowed here (non-interactive without --setup, or not logged in), or when the
|
|
73
73
|
* customer declines the confirm — in all those cases the launch continues under
|
|
74
74
|
* the given slug. THROWS only on an actual provisioning failure (birth/claim/
|
|
75
|
-
* card write) so the caller can decide whether that is fatal (`mnemom
|
|
75
|
+
* card write) so the caller can decide whether that is fatal (`mnemom agent
|
|
76
76
|
* setup`) or a warn-and-continue (a bare launch).
|
|
77
77
|
*/
|
|
78
78
|
export async function ensureGovernedAgent(opts) {
|
|
@@ -83,11 +83,11 @@ export async function ensureGovernedAgent(opts) {
|
|
|
83
83
|
if (loggedIn) {
|
|
84
84
|
const existing = await getAgentByName(slug).catch(() => null);
|
|
85
85
|
if (existing) {
|
|
86
|
-
// On an EXPLICIT `mnemom
|
|
86
|
+
// On an EXPLICIT `mnemom agent setup`, repair/complete the cards on the
|
|
87
87
|
// already-claimed agent (e.g. a protection card that failed on a prior run
|
|
88
88
|
// before we minted its one-time grant). A bare launch leaves it alone.
|
|
89
89
|
if (opts.setup === true) {
|
|
90
|
-
say(fmt.dim(`mnemom
|
|
90
|
+
say(fmt.dim(`mnemom agent: '${slug}' is already claimed — refreshing its cards.`));
|
|
91
91
|
await publishDefaultCards(existing.id);
|
|
92
92
|
persistAgentSlug(slug);
|
|
93
93
|
return { slug, provisioned: true };
|
|
@@ -106,8 +106,8 @@ export async function ensureGovernedAgent(opts) {
|
|
|
106
106
|
if (opts.setup === true && !interactive) {
|
|
107
107
|
throw new Error("not authenticated — run `mnemom login` (or set MNEMOM_API_KEY) first.");
|
|
108
108
|
}
|
|
109
|
-
say(fmt.warn(`mnemom
|
|
110
|
-
say(fmt.dim(" Run `mnemom login`, then `mnemom
|
|
109
|
+
say(fmt.warn(`mnemom agent: not logged in — can't provision '${slug}'.`));
|
|
110
|
+
say(fmt.dim(" Run `mnemom login`, then `mnemom agent setup`. Launching with the unclaimed identity for now."));
|
|
111
111
|
return { slug, provisioned: false };
|
|
112
112
|
}
|
|
113
113
|
// 4. Confirm the plan (interactive runs; --setup non-interactive proceeds).
|
|
@@ -120,7 +120,7 @@ export async function ensureGovernedAgent(opts) {
|
|
|
120
120
|
say(fmt.label(" Posture:", "observe (alignment + protection observe-only, all surfaces screened); goal contracts nudge"));
|
|
121
121
|
say(fmt.dim(" Births the agent through the gateway, claims it to your org, and publishes its cards."));
|
|
122
122
|
if (!(await askYesNo("Provision and claim this agent now?", true))) {
|
|
123
|
-
say(fmt.dim(" Skipped — launching under the unclaimed identity. Run `mnemom
|
|
123
|
+
say(fmt.dim(" Skipped — launching under the unclaimed identity. Run `mnemom agent setup` anytime."));
|
|
124
124
|
return { slug, provisioned: false };
|
|
125
125
|
}
|
|
126
126
|
}
|
|
@@ -129,7 +129,7 @@ export async function ensureGovernedAgent(opts) {
|
|
|
129
129
|
const agentId = await birthThroughGateway(gatewayUrl, "anthropic", slug, opts.anthropicKey);
|
|
130
130
|
const hashProof = deriveHashProof(opts.anthropicKey, slug);
|
|
131
131
|
await claimAgent(agentId, { hashProof, orgId: org?.org_id });
|
|
132
|
-
say(fmt.success(`mnemom
|
|
132
|
+
say(fmt.success(`mnemom agent: claimed '${slug}' (${agentId}) in ${orgLabel}.`));
|
|
133
133
|
// Publish the observe-only cards. A card write that can't complete (propagation
|
|
134
134
|
// right after the claim, or a missing cards:write scope) does NOT abort the
|
|
135
135
|
// provision — the agent is claimed and governed on whatever landed; we warn how
|
|
@@ -181,23 +181,23 @@ async function publishDefaultCards(agentId) {
|
|
|
181
181
|
}
|
|
182
182
|
const prot = await tryPublishCard("protection", () => putProtectionCard(agentId, JSON.stringify(buildCodeProtectionCard(agentId)), "application/json"));
|
|
183
183
|
if (align.ok && prot.ok) {
|
|
184
|
-
say(fmt.success("mnemom
|
|
184
|
+
say(fmt.success("mnemom agent: observe posture published (alignment + protection observe; goal contracts nudge)."));
|
|
185
185
|
return;
|
|
186
186
|
}
|
|
187
187
|
if (align.ok)
|
|
188
|
-
say(fmt.success("mnemom
|
|
188
|
+
say(fmt.success("mnemom agent: alignment card published (observe)."));
|
|
189
189
|
for (const c of [align, prot]) {
|
|
190
190
|
if (c.ok)
|
|
191
191
|
continue;
|
|
192
192
|
// Alignment rides a standing cap, so `mnemom card publish` finishes it; the
|
|
193
193
|
// protection grant is one-time, so re-running setup (which re-mints) is the fix.
|
|
194
|
-
const publishCmd = c.name === "alignment" ? "mnemom card publish" : "mnemom
|
|
195
|
-
say(fmt.warn(`mnemom
|
|
194
|
+
const publishCmd = c.name === "alignment" ? "mnemom card publish" : "mnemom agent setup";
|
|
195
|
+
say(fmt.warn(`mnemom agent: couldn't publish the ${c.name} card — ${c.error}`));
|
|
196
196
|
say(fmt.dim(` The agent is claimed and running; finish it later with \`${publishCmd}\`.`));
|
|
197
197
|
}
|
|
198
198
|
}
|
|
199
|
-
/** `mnemom
|
|
200
|
-
export async function
|
|
199
|
+
/** `mnemom agent setup [--agent <slug>]` — the explicit provisioning entry point. */
|
|
200
|
+
export async function agentSetupCommand(opts = {}) {
|
|
201
201
|
const gatewayHost = resolveGatewayHost(process.env);
|
|
202
202
|
// Sign in (offer sign-up) and enforce the MU balance before any account write.
|
|
203
203
|
try {
|
|
@@ -209,25 +209,27 @@ export async function codeSetupCommand(opts = {}) {
|
|
|
209
209
|
throw err;
|
|
210
210
|
}
|
|
211
211
|
const anthropicKey = await resolveAnthropicKey(process.env, { allowPrompt: true });
|
|
212
|
-
// Session exists now, so derive the real handle from /v1/auth/me (not "
|
|
213
|
-
const slug = opts.agent?.trim()
|
|
212
|
+
// Session exists now, so derive the real handle from /v1/auth/me (not "agent-user").
|
|
213
|
+
const slug = opts.agent?.trim()
|
|
214
|
+
? sanitizeAgentName(opts.agent.trim())
|
|
215
|
+
: await resolveDefaultSlug();
|
|
214
216
|
if (!slug)
|
|
215
|
-
throw new Error("mnemom
|
|
217
|
+
throw new Error("mnemom agent setup: agent slug sanitised to empty — pass --agent <slug>.");
|
|
216
218
|
const result = await ensureGovernedAgent({ slug, anthropicKey, setup: true, gatewayHost });
|
|
217
219
|
if (!result.provisioned) {
|
|
218
220
|
say(fmt.dim(` '${slug}' is ready (already claimed) or setup was skipped.`));
|
|
219
221
|
}
|
|
220
222
|
}
|
|
221
223
|
function warnUnclaimed(slug) {
|
|
222
|
-
say(fmt.warn(`mnemom
|
|
223
|
-
say(fmt.dim(" Provision it (creates + claims the agent, publishes observe cards): mnemom
|
|
224
|
+
say(fmt.warn(`mnemom agent: agent '${slug}' is not set up in your org — launching with an UNCLAIMED identity (governance is advisory/fail-open).`));
|
|
225
|
+
say(fmt.dim(" Provision it (creates + claims the agent, publishes observe cards): mnemom agent setup"));
|
|
224
226
|
}
|
|
225
227
|
function persistAgentSlug(slug) {
|
|
226
228
|
try {
|
|
227
|
-
const cfg =
|
|
229
|
+
const cfg = loadLauncherConfig();
|
|
228
230
|
if (!cfg.agent) {
|
|
229
231
|
configKeySpec("agent").set(cfg, slug);
|
|
230
|
-
|
|
232
|
+
writeLauncherConfig(cfg);
|
|
231
233
|
}
|
|
232
234
|
}
|
|
233
235
|
catch {
|
|
@@ -248,7 +250,7 @@ export class MuInsufficientError extends Error {
|
|
|
248
250
|
/**
|
|
249
251
|
* The preamble errors whose guidance is ALREADY printed when thrown — callers
|
|
250
252
|
* exit 1 quietly instead of re-printing them as "Error: …". One predicate so the
|
|
251
|
-
* two catch sites (`mnemom
|
|
253
|
+
* two catch sites (`mnemom agent` and `mnemom agent setup`) cannot drift.
|
|
252
254
|
*/
|
|
253
255
|
export function isQuietPreambleExit(err) {
|
|
254
256
|
return err instanceof MuInsufficientError || err instanceof CodeNotEnabledError;
|
|
@@ -278,7 +280,7 @@ export async function ensureMnemomSession(opts = {}) {
|
|
|
278
280
|
if (!interactive)
|
|
279
281
|
return false;
|
|
280
282
|
say(fmt.section("Sign in to Mnemom"));
|
|
281
|
-
say(fmt.dim(" mnemom
|
|
283
|
+
say(fmt.dim(" mnemom agent runs your coding session governed and under your Mnemom account,"));
|
|
282
284
|
say(fmt.dim(" so it shows up in your traces and draws on your org's µ balance."));
|
|
283
285
|
say(fmt.dim(` New to Mnemom? You can create a free account in the same flow (or at ${getWebsiteUrl()}/signup).`));
|
|
284
286
|
if (!(await askYesNo("Sign in or create your account now?", true)))
|
|
@@ -304,7 +306,7 @@ export async function ensureMnemomSession(opts = {}) {
|
|
|
304
306
|
}
|
|
305
307
|
/**
|
|
306
308
|
* Enforce a positive Mnemom Units balance on the org the agent lives in.
|
|
307
|
-
* `mnemom
|
|
309
|
+
* `mnemom agent` has NO free tier — a determined zero/negative balance (or an org
|
|
308
310
|
* with no billing account) is BLOCKED with a portal-style top-up message.
|
|
309
311
|
* Fails OPEN on an inconclusive error (transient 5xx / network / 403), since the
|
|
310
312
|
* gateway is the real enforcement and this is a friendly pre-check; hard-blocks
|
|
@@ -333,7 +335,9 @@ export async function assertMuBalance(orgId, orgLabel) {
|
|
|
333
335
|
}
|
|
334
336
|
function safeBigInt(v) {
|
|
335
337
|
try {
|
|
336
|
-
return BigInt(String(v ?? "0")
|
|
338
|
+
return BigInt(String(v ?? "0")
|
|
339
|
+
.trim()
|
|
340
|
+
.split(".")[0] || "0");
|
|
337
341
|
}
|
|
338
342
|
catch {
|
|
339
343
|
return 0n;
|
|
@@ -347,16 +351,16 @@ function safeBigInt(v) {
|
|
|
347
351
|
function printTopUp(orgLabel, balanceMu) {
|
|
348
352
|
say();
|
|
349
353
|
say(fmt.warn(`No µ balance — ${orgLabel} is at ${balanceMu} µ.`));
|
|
350
|
-
say(fmt.dim(" mnemom
|
|
354
|
+
say(fmt.dim(" mnemom agent runs on µ, and there's no free tier. Without µ, Mnemom's safety"));
|
|
351
355
|
say(fmt.dim(" features can't run, so the launch is blocked. Top up to launch a governed session:"));
|
|
352
356
|
say();
|
|
353
357
|
say(` Top up µ: ${getWebsiteUrl()}/settings/billing`);
|
|
354
358
|
say(fmt.dim(" If you don't manage billing for this org, ask an admin to top up."));
|
|
355
359
|
say();
|
|
356
|
-
say(fmt.dim(" Your µ balance updates the moment a top-up completes — then re-run `mnemom
|
|
360
|
+
say(fmt.dim(" Your µ balance updates the moment a top-up completes — then re-run `mnemom agent`."));
|
|
357
361
|
}
|
|
358
362
|
/**
|
|
359
|
-
* The shared pre-launch preamble for `mnemom
|
|
363
|
+
* The shared pre-launch preamble for `mnemom agent` (and `mnemom agent setup`):
|
|
360
364
|
* ensure a Mnemom session (login/sign-up), then enforce the MU balance on the
|
|
361
365
|
* org the agent lives in (default: the user's personal org). Returns the
|
|
362
366
|
* resolved org so the caller can reuse it. Throws with clear guidance when there
|
|
@@ -366,14 +370,14 @@ export async function ensureSessionAndBalance(opts) {
|
|
|
366
370
|
const interactive = opts.interactive ?? isInteractive();
|
|
367
371
|
const haveSession = await ensureMnemomSession({ interactive });
|
|
368
372
|
if (!haveSession) {
|
|
369
|
-
throw new Error("mnemom
|
|
373
|
+
throw new Error("mnemom agent needs a Mnemom account — it runs your coding session governed and on your org's µ balance.\n" +
|
|
370
374
|
" Sign in: mnemom login (or set MNEMOM_API_KEY)\n" +
|
|
371
375
|
` New here? create a free account, then top up µ: ${getWebsiteUrl()}/settings/billing`);
|
|
372
376
|
}
|
|
373
377
|
const active = getActiveOrg();
|
|
374
378
|
const orgId = active?.org_id ?? (await getMyPersonalOrg()).org_id;
|
|
375
379
|
const orgLabel = active ? `${active.name} (${active.slug})` : "your personal org";
|
|
376
|
-
// Invited-cohort gate FIRST: an org that is not enabled for Mnemom
|
|
380
|
+
// Invited-cohort gate FIRST: an org that is not enabled for Mnemom Agent gets
|
|
377
381
|
// the invite guidance, not a top-up message (the µ check would be moot).
|
|
378
382
|
await assertCodeEnabled(orgId, orgLabel);
|
|
379
383
|
await assertMuBalance(orgId, orgLabel);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* `mnemom
|
|
2
|
+
* `mnemom agent <scenario>` — the CLI's first-class governed-coding-agent launcher.
|
|
3
3
|
*
|
|
4
4
|
* Launches your coding-agent CLI (Claude Code in v1) with its dev-time model
|
|
5
5
|
* traffic routed through the Mnemom gateway's /anthropic door for observability +
|
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
* no router door / Mnemom key). `--cli` selects the executable to run (name or
|
|
12
12
|
* full path) so codex/cursor/github adapters can be added later.
|
|
13
13
|
* - The us-2/PROD gateway is the DEFAULT door (https://gateway.mnemom.ai); an
|
|
14
|
-
* explicit
|
|
14
|
+
* explicit MNEMOM_AGENT_GATEWAY / --gateway still wins, never silently prod.
|
|
15
15
|
* - Three launch shapes: `terminal` (DEFAULT), `remote-control` (interactive RC
|
|
16
16
|
* in this terminal), `server` (headless RC dispatcher). RC runs the CLI
|
|
17
17
|
* UNTOUCHED behind a bundled local TLS proxy (rc-proxy.mjs) — Claude Code
|
|
@@ -20,12 +20,13 @@
|
|
|
20
20
|
* - yolo (`--dangerously-skip-permissions`) is ON by default; `--no-yolo` opts out.
|
|
21
21
|
*
|
|
22
22
|
* The Anthropic key is resolved from a credential source with ZERO 1Password
|
|
23
|
-
* dependency (env → the CLI's own ~/.mnemom/
|
|
23
|
+
* dependency (env → the CLI's own ~/.mnemom/launcher.json store → interactive
|
|
24
24
|
* prompt) and placed ONLY in the launched process (an `ANTHROPIC_CUSTOM_HEADERS`
|
|
25
25
|
* line, or the proxy's stdin under RC). It is never logged, printed, or passed as
|
|
26
26
|
* an argv value.
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
import { type LaunchShape, type SealedContractEnvelope } from "../lib/agent.js";
|
|
29
|
+
export interface AgentOptions {
|
|
29
30
|
goal?: string;
|
|
30
31
|
requirement?: string[];
|
|
31
32
|
allow?: string[];
|
|
@@ -34,6 +35,12 @@ export interface CodeOptions {
|
|
|
34
35
|
budget?: string;
|
|
35
36
|
maxTurns?: string;
|
|
36
37
|
stall?: string;
|
|
38
|
+
/**
|
|
39
|
+
* `--implicit`: goal alignment with no sealed contract — the gateway infers the
|
|
40
|
+
* goal from the user's messages and revises it as they steer; the ceilings above
|
|
41
|
+
* ride on the `x-mnemom-goal-mode` header. Exclusive with the contract flags.
|
|
42
|
+
*/
|
|
43
|
+
implicit?: boolean;
|
|
37
44
|
/** x-mnemom-agent value (defaults to "code-agent"). */
|
|
38
45
|
agent?: string;
|
|
39
46
|
conversationId?: string;
|
|
@@ -54,7 +61,7 @@ export interface CodeOptions {
|
|
|
54
61
|
*/
|
|
55
62
|
setup?: boolean;
|
|
56
63
|
/**
|
|
57
|
-
* Where to source the Anthropic key (from ~/.mnemom/
|
|
64
|
+
* Where to source the Anthropic key (from ~/.mnemom/launcher.toml `key_source`).
|
|
58
65
|
* Restricts the default env → store → prompt search: "env" uses env only,
|
|
59
66
|
* "store" uses env → store (no prompt), "prompt" forces the interactive prompt.
|
|
60
67
|
* Undefined = the full default order.
|
|
@@ -64,13 +71,13 @@ export interface CodeOptions {
|
|
|
64
71
|
/** Print the resolved launch plan and exit — no key read, no spawn. */
|
|
65
72
|
dryRun?: boolean;
|
|
66
73
|
}
|
|
67
|
-
/** Entry point for `mnemom
|
|
68
|
-
export declare function
|
|
74
|
+
/** Entry point for `mnemom agent [scenario]`. Throws on fatal misconfig. */
|
|
75
|
+
export declare function agentCommand(scenarioArg: string | undefined, options?: AgentOptions): Promise<void>;
|
|
69
76
|
/**
|
|
70
77
|
* Resolve the Anthropic key with NO 1Password dependency (built for external
|
|
71
78
|
* customer adoption), in order:
|
|
72
|
-
* 1. env:
|
|
73
|
-
* 2. the CLI's own store: ~/.mnemom/
|
|
79
|
+
* 1. env: MNEMOM_AGENT_ANTHROPIC_KEY, else ANTHROPIC_API_KEY
|
|
80
|
+
* 2. the CLI's own store: ~/.mnemom/launcher.json (`anthropic_key`)
|
|
74
81
|
* 3. interactive prompt (masked), offering to save it to the store
|
|
75
82
|
* Never logged / printed. Throws with guidance when nothing resolves — we refuse
|
|
76
83
|
* to launch un-routed.
|
|
@@ -81,8 +88,8 @@ export declare function resolveAnthropicKey(env: NodeJS.ProcessEnv, opts: {
|
|
|
81
88
|
}): Promise<string>;
|
|
82
89
|
/**
|
|
83
90
|
* Where an Anthropic key would resolve from RIGHT NOW, without reading its value:
|
|
84
|
-
* "env" (
|
|
85
|
-
* or null (would fall to the interactive prompt). For `mnemom
|
|
91
|
+
* "env" (MNEMOM_AGENT_ANTHROPIC_KEY / ANTHROPIC_API_KEY), "store" (~/.mnemom/launcher.json),
|
|
92
|
+
* or null (would fall to the interactive prompt). For `mnemom agent doctor`.
|
|
86
93
|
*/
|
|
87
94
|
export declare function anthropicKeySource(env?: NodeJS.ProcessEnv): "env" | "store" | null;
|
|
88
95
|
export interface ResolvedCli {
|
|
@@ -92,7 +99,7 @@ export interface ResolvedCli {
|
|
|
92
99
|
name: string;
|
|
93
100
|
}
|
|
94
101
|
/**
|
|
95
|
-
* Resolve which coding-agent CLI to launch. `--cli` (or
|
|
102
|
+
* Resolve which coding-agent CLI to launch. `--cli` (or MNEMOM_AGENT_CLI) is a
|
|
96
103
|
* name or a full path; default "claude". A value with a path separator is used
|
|
97
104
|
* verbatim (must exist); a bare name is resolved on PATH, then — for claude — the
|
|
98
105
|
* fnm/nvm/asdf install dirs (a version-manager shim / shell function is absent in
|
|
@@ -116,7 +123,7 @@ export interface RcCapability {
|
|
|
116
123
|
/**
|
|
117
124
|
* Can we launch the DEFAULT Remote-Control-in-terminal shape on this machine?
|
|
118
125
|
* Needs node + openssl (the local proxy mints an ephemeral CA) and a claude
|
|
119
|
-
* adapter that advertises `--remote-control`. Used both by `mnemom
|
|
126
|
+
* adapter that advertises `--remote-control`. Used both by `mnemom agent doctor`
|
|
120
127
|
* and by the auto-default selection (a bare launch prefers RC when capable).
|
|
121
128
|
*/
|
|
122
129
|
export declare function checkRcCapability(cli: ResolvedCli): RcCapability;
|
|
@@ -127,7 +134,36 @@ export declare function checkRcCapability(cli: ResolvedCli): RcCapability;
|
|
|
127
134
|
* appends `--strict-mcp-config --mcp-config {}` LAST so it wins over any
|
|
128
135
|
* caller-supplied --mcp-config.
|
|
129
136
|
*/
|
|
130
|
-
export declare function buildCliArgs(options:
|
|
137
|
+
export declare function buildCliArgs(options: AgentOptions, ctx: {
|
|
131
138
|
yolo: boolean;
|
|
132
139
|
allowCliFlags: boolean;
|
|
133
140
|
}): string[];
|
|
141
|
+
/**
|
|
142
|
+
* Which goal-alignment mode the launch status line names: a sealed contract →
|
|
143
|
+
* "on"; `--implicit` (mode header, no contract) → "implicit"; neither → "off".
|
|
144
|
+
* A sealed contract and a mode header never coexist (`assembleContract` refuses
|
|
145
|
+
* the combination), so the first arm winning is not a precedence choice.
|
|
146
|
+
*/
|
|
147
|
+
export declare function goalAlignmentMode(envelope: SealedContractEnvelope | null, goalMode: string | null): "on" | "implicit" | "off";
|
|
148
|
+
export declare function logLaunch(ctx: {
|
|
149
|
+
shape: LaunchShape;
|
|
150
|
+
door: string;
|
|
151
|
+
agent: string;
|
|
152
|
+
conversationId: string;
|
|
153
|
+
cellNote: string;
|
|
154
|
+
envelope: SealedContractEnvelope | null;
|
|
155
|
+
goalMode: string | null;
|
|
156
|
+
cli: ResolvedCli;
|
|
157
|
+
}): void;
|
|
158
|
+
export declare function printPlan(ctx: {
|
|
159
|
+
scenario: string;
|
|
160
|
+
shape: LaunchShape;
|
|
161
|
+
agent: string;
|
|
162
|
+
conversationId: string;
|
|
163
|
+
door: string;
|
|
164
|
+
cellNote: string;
|
|
165
|
+
envelope: SealedContractEnvelope | null;
|
|
166
|
+
goalMode: string | null;
|
|
167
|
+
yolo: boolean;
|
|
168
|
+
cli: ResolvedCli;
|
|
169
|
+
}): void;
|