@mnemom/mnemom 0.17.0-next.3 → 0.17.0-next.5
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/code-doctor.js +1 -1
- package/dist/commands/code-invite.d.ts +3 -3
- package/dist/commands/code-invite.js +2 -6
- package/dist/commands/code-session.d.ts +52 -0
- package/dist/commands/code-session.js +78 -0
- package/dist/commands/code-setup.js +27 -3
- package/dist/commands/code.d.ts +2 -2
- package/dist/commands/code.js +20 -7
- package/dist/index.js +3 -3
- package/dist/lib/api.d.ts +10 -0
- package/dist/lib/api.js +12 -0
- package/package.json +1 -1
|
@@ -98,7 +98,7 @@ export async function codeDoctorCommand(options = {}) {
|
|
|
98
98
|
out("");
|
|
99
99
|
const launchReady = !lines.some((l) => l.mark === "miss");
|
|
100
100
|
if (launchReady) {
|
|
101
|
-
out(" Ready to launch: mnemom code
|
|
101
|
+
out(" Ready to launch: mnemom code");
|
|
102
102
|
}
|
|
103
103
|
else {
|
|
104
104
|
out(" Not launch-ready — resolve the [MISS] items above.");
|
|
@@ -59,7 +59,6 @@ export declare function codeInviteCommand(token: string | undefined, opts?: {
|
|
|
59
59
|
interactive?: boolean;
|
|
60
60
|
ensureSession?: EnsureSession;
|
|
61
61
|
}): Promise<AcceptProductInviteResult>;
|
|
62
|
-
export declare const NO_SCENARIO_MESSAGE = "mnemom code: a <scenario> slug is required (e.g. `mnemom code onboarding`) \u2014 or redeem an invitation with `mnemom code --invite <token>`.";
|
|
63
62
|
export interface CodeInvocation {
|
|
64
63
|
/** The positional `[scenario]` (may be a reserved sub-verb such as "invite"). */
|
|
65
64
|
scenario?: string;
|
|
@@ -70,7 +69,8 @@ export interface CodeInvocation {
|
|
|
70
69
|
}
|
|
71
70
|
export interface CodeInvocationDeps {
|
|
72
71
|
redeem: (token: string | undefined) => Promise<unknown>;
|
|
73
|
-
launch
|
|
72
|
+
/** The launch half; `undefined` = no session name given (the launcher prompts in a terminal). */
|
|
73
|
+
launch: (scenario: string | undefined) => Promise<void>;
|
|
74
74
|
}
|
|
75
75
|
/**
|
|
76
76
|
* How the `code` command's positional + `--invite` compose — kept OUT of
|
|
@@ -79,6 +79,6 @@ export interface CodeInvocationDeps {
|
|
|
79
79
|
* - `mnemom code --invite <token>` → redeem, done
|
|
80
80
|
* - `mnemom code --invite <token> <scen>` → redeem, then launch
|
|
81
81
|
* - `mnemom code <scen>` → launch
|
|
82
|
-
* - `mnemom code` →
|
|
82
|
+
* - `mnemom code` → launch (the launcher asks for a name + goal)
|
|
83
83
|
*/
|
|
84
84
|
export declare function runCodeInvocation(input: CodeInvocation, deps: CodeInvocationDeps): Promise<void>;
|
|
@@ -132,7 +132,7 @@ export function printAccepted(res) {
|
|
|
132
132
|
else if (res.grant === "deferred") {
|
|
133
133
|
say(fmt.dim(" Your starter µ credit is pending — you can start now; if it hasn't landed shortly, contact support@mnemom.ai."));
|
|
134
134
|
}
|
|
135
|
-
say(fmt.dim(" Start a governed session: mnemom code
|
|
135
|
+
say(fmt.dim(" Start a governed session: mnemom code"));
|
|
136
136
|
}
|
|
137
137
|
/**
|
|
138
138
|
* `mnemom code --invite <token>` / `mnemom code invite <token>`: sign in, redeem,
|
|
@@ -166,8 +166,6 @@ export async function codeInviteCommand(token, opts = {}) {
|
|
|
166
166
|
printAccepted(result);
|
|
167
167
|
return result;
|
|
168
168
|
}
|
|
169
|
-
// ── `mnemom code` entry dispatch ─────────────────────────────────────────────
|
|
170
|
-
export const NO_SCENARIO_MESSAGE = "mnemom code: a <scenario> slug is required (e.g. `mnemom code onboarding`) — or redeem an invitation with `mnemom code --invite <token>`.";
|
|
171
169
|
/**
|
|
172
170
|
* How the `code` command's positional + `--invite` compose — kept OUT of
|
|
173
171
|
* index.ts so it is unit-testable:
|
|
@@ -175,7 +173,7 @@ export const NO_SCENARIO_MESSAGE = "mnemom code: a <scenario> slug is required (
|
|
|
175
173
|
* - `mnemom code --invite <token>` → redeem, done
|
|
176
174
|
* - `mnemom code --invite <token> <scen>` → redeem, then launch
|
|
177
175
|
* - `mnemom code <scen>` → launch
|
|
178
|
-
* - `mnemom code` →
|
|
176
|
+
* - `mnemom code` → launch (the launcher asks for a name + goal)
|
|
179
177
|
*/
|
|
180
178
|
export async function runCodeInvocation(input, deps) {
|
|
181
179
|
if (input.scenario === "invite") {
|
|
@@ -187,7 +185,5 @@ export async function runCodeInvocation(input, deps) {
|
|
|
187
185
|
if (!input.scenario)
|
|
188
186
|
return;
|
|
189
187
|
}
|
|
190
|
-
if (!input.scenario)
|
|
191
|
-
throw new Error(NO_SCENARIO_MESSAGE);
|
|
192
188
|
await deps.launch(input.scenario);
|
|
193
189
|
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mnemom code` with no session name — the interactive first-run setup.
|
|
3
|
+
*
|
|
4
|
+
* The daily command is just `mnemom code` (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. an optional GOAL — one line. With a goal, Mnemom seals a goal contract
|
|
11
|
+
* for the session and the judge nudges the agent back when it drifts (a
|
|
12
|
+
* little µ per turn). Without one, the session runs governed but with goal
|
|
13
|
+
* alignment OFF: no contract header is sent, so the gateway's goal hook is
|
|
14
|
+
* simply not engaged for the conversation.
|
|
15
|
+
*
|
|
16
|
+
* Non-interactive runs (pipes, CI) never prompt — they get a clear error asking
|
|
17
|
+
* for a name. `--goal` on the command line always wins over the prompt. Pure
|
|
18
|
+
* apart from the injected `ask` functions, so every arm is unit-tested.
|
|
19
|
+
*/
|
|
20
|
+
export interface SessionAsk {
|
|
21
|
+
askInput(question: string): Promise<string>;
|
|
22
|
+
askYesNo(question: string, defaultYes: boolean): Promise<boolean>;
|
|
23
|
+
}
|
|
24
|
+
export interface SessionSetupInput {
|
|
25
|
+
/** The positional `[scenario]` (session name), if given. */
|
|
26
|
+
scenario?: string;
|
|
27
|
+
/** `--goal <statement>`, if given — skips the goal prompt. */
|
|
28
|
+
goal?: string;
|
|
29
|
+
interactive: boolean;
|
|
30
|
+
/** For the default session name (tests inject one). */
|
|
31
|
+
cwd?: string;
|
|
32
|
+
/** Narration sink (stderr by default; tests capture). */
|
|
33
|
+
say?: (line?: string) => void;
|
|
34
|
+
}
|
|
35
|
+
export interface SessionSetup {
|
|
36
|
+
scenario: string;
|
|
37
|
+
/** The goal statement to seal, or undefined = goal alignment off. */
|
|
38
|
+
goal?: string;
|
|
39
|
+
goalAlignment: "on" | "off";
|
|
40
|
+
/** True when the terminal prompts ran. */
|
|
41
|
+
prompted: boolean;
|
|
42
|
+
}
|
|
43
|
+
export declare const NO_SESSION_NAME_MESSAGE: string;
|
|
44
|
+
/** Current folder name, sanitised like an agent slug; "session" when that is empty. */
|
|
45
|
+
export declare function defaultSessionName(cwd?: string): string;
|
|
46
|
+
/** The one-line status printed at launch so the customer always knows the mode. */
|
|
47
|
+
export declare function goalAlignmentLine(on: boolean): string;
|
|
48
|
+
/**
|
|
49
|
+
* Resolve the session name + goal for this launch. See the module doc for the
|
|
50
|
+
* rules. Throws NO_SESSION_NAME_MESSAGE when no name was given and we cannot ask.
|
|
51
|
+
*/
|
|
52
|
+
export declare function resolveSessionSetup(input: SessionSetupInput, ask: SessionAsk): Promise<SessionSetup>;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `mnemom code` with no session name — the interactive first-run setup.
|
|
3
|
+
*
|
|
4
|
+
* The daily command is just `mnemom code` (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. an optional GOAL — one line. With a goal, Mnemom seals a goal contract
|
|
11
|
+
* for the session and the judge nudges the agent back when it drifts (a
|
|
12
|
+
* little µ per turn). Without one, the session runs governed but with goal
|
|
13
|
+
* alignment OFF: no contract header is sent, so the gateway's goal hook is
|
|
14
|
+
* simply not engaged for the conversation.
|
|
15
|
+
*
|
|
16
|
+
* Non-interactive runs (pipes, CI) never prompt — they get a clear error asking
|
|
17
|
+
* for a name. `--goal` on the command line always wins over the prompt. Pure
|
|
18
|
+
* apart from the injected `ask` functions, so every arm is unit-tested.
|
|
19
|
+
*/
|
|
20
|
+
import { basename } from "node:path";
|
|
21
|
+
import { sanitizeAgentName } from "../lib/code.js";
|
|
22
|
+
export const NO_SESSION_NAME_MESSAGE = "mnemom code: a session name is required here (e.g. `mnemom code onboarding`). " +
|
|
23
|
+
"In a terminal, plain `mnemom code` asks for one.";
|
|
24
|
+
/** Current folder name, sanitised like an agent slug; "session" when that is empty. */
|
|
25
|
+
export function defaultSessionName(cwd = process.cwd()) {
|
|
26
|
+
return sanitizeAgentName(basename(cwd)) || "session";
|
|
27
|
+
}
|
|
28
|
+
/** The one-line status printed at launch so the customer always knows the mode. */
|
|
29
|
+
export function goalAlignmentLine(on) {
|
|
30
|
+
return on
|
|
31
|
+
? "mnemom code: goal alignment: on (the judge nudges the agent back when it drifts from your goal)"
|
|
32
|
+
: "mnemom code: goal alignment: off (no goal set — pass --goal or set one when prompted)";
|
|
33
|
+
}
|
|
34
|
+
const defaultSay = (line = "") => console.error(line);
|
|
35
|
+
/**
|
|
36
|
+
* Resolve the session name + goal for this launch. See the module doc for the
|
|
37
|
+
* rules. Throws NO_SESSION_NAME_MESSAGE when no name was given and we cannot ask.
|
|
38
|
+
*/
|
|
39
|
+
export async function resolveSessionSetup(input, ask) {
|
|
40
|
+
const say = input.say ?? defaultSay;
|
|
41
|
+
const flagGoal = (input.goal ?? "").trim();
|
|
42
|
+
const given = (input.scenario ?? "").trim();
|
|
43
|
+
if (given) {
|
|
44
|
+
return {
|
|
45
|
+
scenario: given,
|
|
46
|
+
goal: flagGoal || undefined,
|
|
47
|
+
goalAlignment: flagGoal ? "on" : "off",
|
|
48
|
+
prompted: false,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
if (!input.interactive)
|
|
52
|
+
throw new Error(NO_SESSION_NAME_MESSAGE);
|
|
53
|
+
// ── 1. session name ──
|
|
54
|
+
const fallback = defaultSessionName(input.cwd);
|
|
55
|
+
say();
|
|
56
|
+
say("Session name — labels this session in your traces and the claude.ai session list.");
|
|
57
|
+
say(` (Next time you can pass it directly: mnemom code <name>.)`);
|
|
58
|
+
const typed = await ask.askInput(`Session name [${fallback}]:`);
|
|
59
|
+
const scenario = sanitizeAgentName(typed.trim()) || fallback;
|
|
60
|
+
// ── 2. goal (skipped when --goal was given) ──
|
|
61
|
+
if (flagGoal) {
|
|
62
|
+
return { scenario, goal: flagGoal, goalAlignment: "on", prompted: true };
|
|
63
|
+
}
|
|
64
|
+
say();
|
|
65
|
+
say("Goal alignment — an optional one-line goal for this session.");
|
|
66
|
+
say(" With a goal, Mnemom's judge watches each turn and nudges the agent back when it drifts");
|
|
67
|
+
say(" (a little µ per turn). Without one, the session runs governed with goal alignment off.");
|
|
68
|
+
const wantsGoal = await ask.askYesNo("Set a goal for this session?", true);
|
|
69
|
+
if (!wantsGoal) {
|
|
70
|
+
return { scenario, goalAlignment: "off", prompted: true };
|
|
71
|
+
}
|
|
72
|
+
const goal = (await ask.askInput("Goal (one line):")).trim();
|
|
73
|
+
if (!goal) {
|
|
74
|
+
say(" No goal entered — continuing with goal alignment off.");
|
|
75
|
+
return { scenario, goalAlignment: "off", prompted: true };
|
|
76
|
+
}
|
|
77
|
+
return { scenario, goal, goalAlignment: "on", prompted: true };
|
|
78
|
+
}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
* birthThroughGateway (wrap.ts), deriveHashProof (agents.ts), claimAgent +
|
|
24
24
|
* putAlignmentCard/putProtectionCard (lib/api.ts) — rather than reinventing it.
|
|
25
25
|
*/
|
|
26
|
-
import { claimAgent, getAgentByName, getMuBalance, getMyPersonalOrg, MnemomApiError, putAlignmentCard, putProtectionCard, } from "../lib/api.js";
|
|
26
|
+
import { claimAgent, getAgentByName, getMuBalance, getMyPersonalOrg, MnemomApiError, mintProtectionCapability, putAlignmentCard, putProtectionCard, } from "../lib/api.js";
|
|
27
27
|
import { getAuthInfo, isLoggedIn, loginWithBrowser, loginWithDeviceFlow, resolveAuth, } from "../lib/auth.js";
|
|
28
28
|
import { getActiveOrg } from "../lib/cli-config.js";
|
|
29
29
|
import { getWebsiteUrl } from "../lib/config.js";
|
|
@@ -63,8 +63,18 @@ export async function ensureGovernedAgent(opts) {
|
|
|
63
63
|
const loggedIn = await isLoggedIn();
|
|
64
64
|
if (loggedIn) {
|
|
65
65
|
const existing = await getAgentByName(slug).catch(() => null);
|
|
66
|
-
if (existing)
|
|
66
|
+
if (existing) {
|
|
67
|
+
// On an EXPLICIT `mnemom code setup`, repair/complete the cards on the
|
|
68
|
+
// already-claimed agent (e.g. a protection card that failed on a prior run
|
|
69
|
+
// before we minted its one-time grant). A bare launch leaves it alone.
|
|
70
|
+
if (opts.setup === true) {
|
|
71
|
+
say(fmt.dim(`mnemom code: '${slug}' is already claimed — refreshing its cards.`));
|
|
72
|
+
await publishDefaultCards(existing.id);
|
|
73
|
+
persistAgentSlug(slug);
|
|
74
|
+
return { slug, provisioned: true };
|
|
75
|
+
}
|
|
67
76
|
return { slug, provisioned: false };
|
|
77
|
+
}
|
|
68
78
|
}
|
|
69
79
|
// 2. Are we allowed to provision here?
|
|
70
80
|
const canProvision = opts.setup === true || (opts.setup !== false && interactive);
|
|
@@ -138,6 +148,18 @@ async function tryPublishCard(name, write) {
|
|
|
138
148
|
/** Publish both default observe-only cards; never throws — warns on a card that can't be written. */
|
|
139
149
|
async function publishDefaultCards(agentId) {
|
|
140
150
|
const align = await tryPublishCard("alignment", () => putAlignmentCard(agentId, JSON.stringify(buildCodeAlignmentCard(agentId)), "application/json"));
|
|
151
|
+
// Protection is the "locked door": it needs a one-time cards:write:protection
|
|
152
|
+
// grant that the claim does NOT include (alignment rides a standing cap). Mint
|
|
153
|
+
// it with our human login JWT — the "Provision and claim?" confirm is the
|
|
154
|
+
// explicit human approval, and the mint endpoint accepts a human operator (only
|
|
155
|
+
// agent OAuth principals are rejected). The next write consumes the grant. A
|
|
156
|
+
// mint failure falls through to the write's retry + graceful degrade.
|
|
157
|
+
try {
|
|
158
|
+
await mintProtectionCapability(agentId);
|
|
159
|
+
}
|
|
160
|
+
catch {
|
|
161
|
+
// best effort — the protection write below surfaces the real, actionable error
|
|
162
|
+
}
|
|
141
163
|
const prot = await tryPublishCard("protection", () => putProtectionCard(agentId, JSON.stringify(buildCodeProtectionCard(agentId)), "application/json"));
|
|
142
164
|
if (align.ok && prot.ok) {
|
|
143
165
|
say(fmt.success("mnemom code: observe posture published (alignment + protection observe; goal contracts nudge)."));
|
|
@@ -148,7 +170,9 @@ async function publishDefaultCards(agentId) {
|
|
|
148
170
|
for (const c of [align, prot]) {
|
|
149
171
|
if (c.ok)
|
|
150
172
|
continue;
|
|
151
|
-
|
|
173
|
+
// Alignment rides a standing cap, so `mnemom card publish` finishes it; the
|
|
174
|
+
// protection grant is one-time, so re-running setup (which re-mints) is the fix.
|
|
175
|
+
const publishCmd = c.name === "alignment" ? "mnemom card publish" : "mnemom code setup";
|
|
152
176
|
say(fmt.warn(`mnemom code: couldn't publish the ${c.name} card — ${c.error}`));
|
|
153
177
|
say(fmt.dim(` The agent is claimed and running; finish it later with \`${publishCmd}\`.`));
|
|
154
178
|
}
|
package/dist/commands/code.d.ts
CHANGED
|
@@ -64,8 +64,8 @@ export interface CodeOptions {
|
|
|
64
64
|
/** Print the resolved launch plan and exit — no key read, no spawn. */
|
|
65
65
|
dryRun?: boolean;
|
|
66
66
|
}
|
|
67
|
-
/** Entry point for `mnemom code
|
|
68
|
-
export declare function codeCommand(
|
|
67
|
+
/** Entry point for `mnemom code [scenario]`. Throws on fatal misconfig. */
|
|
68
|
+
export declare function codeCommand(scenarioArg: string | undefined, options?: CodeOptions): Promise<void>;
|
|
69
69
|
/**
|
|
70
70
|
* Resolve the Anthropic key with NO 1Password dependency (built for external
|
|
71
71
|
* customer adoption), in order:
|
package/dist/commands/code.js
CHANGED
|
@@ -34,16 +34,18 @@ import { MNEMOM_DIR } from "../lib/config.js";
|
|
|
34
34
|
import { configKeySpec, loadCodeConfig, writeCodeConfig } from "../lib/code-config.js";
|
|
35
35
|
import { fmt } from "../lib/format.js";
|
|
36
36
|
import { askInput, askYesNo, isInteractive } from "../lib/prompt.js";
|
|
37
|
+
import { goalAlignmentLine, resolveSessionSetup } from "./code-session.js";
|
|
37
38
|
import { defaultAgentSlug, ensureGovernedAgent, ensureSessionAndBalance, isQuietPreambleExit, } from "./code-setup.js";
|
|
38
39
|
import { assembleContract, buildCustomHeaders, isProdGateway, launchPreferenceExplicit, resolveAnthropicDoor, resolveConversationId, resolveGatewayHost, resolveLaunchShape, sanitizeAgentName, } from "../lib/code.js";
|
|
39
40
|
/** The CLI's own provider-key store (zero 1Password): ~/.mnemom/code.json, 0600. */
|
|
40
41
|
const CODE_STORE = join(MNEMOM_DIR, "code.json");
|
|
41
42
|
const say = (line = "") => console.error(line);
|
|
42
|
-
/** Entry point for `mnemom code
|
|
43
|
-
export async function codeCommand(
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
43
|
+
/** Entry point for `mnemom code [scenario]`. Throws on fatal misconfig. */
|
|
44
|
+
export async function codeCommand(scenarioArg, options = {}) {
|
|
45
|
+
// ── session name + goal ── (a bare `mnemom code` in a terminal asks for both,
|
|
46
|
+
// explaining goal alignment; no goal ⇒ no contract header ⇒ goal alignment off)
|
|
47
|
+
const session = await resolveSessionSetup({ scenario: scenarioArg, goal: options.goal, interactive: isInteractive() }, { askInput: (q) => askInput(q), askYesNo: (q, d) => askYesNo(q, d) });
|
|
48
|
+
const scenario = session.scenario;
|
|
47
49
|
const env = process.env;
|
|
48
50
|
let shape = resolveLaunchShape({ remoteControl: options.remoteControl, server: options.server }, env);
|
|
49
51
|
const shapeExplicit = launchPreferenceExplicit({ remoteControl: options.remoteControl, server: options.server }, env);
|
|
@@ -58,7 +60,7 @@ export async function codeCommand(scenario, options = {}) {
|
|
|
58
60
|
const conversationId = resolveConversationId(options.conversationId);
|
|
59
61
|
// ── contract (built only if a contract flag was given; --goal then required) ──
|
|
60
62
|
const envelope = assembleContract({
|
|
61
|
-
goal:
|
|
63
|
+
goal: session.goal,
|
|
62
64
|
requirement: options.requirement,
|
|
63
65
|
allow: options.allow,
|
|
64
66
|
forbid: options.forbid,
|
|
@@ -107,7 +109,17 @@ export async function codeCommand(scenario, options = {}) {
|
|
|
107
109
|
bin: "(not found — pass --cli <path> or `mnemom code config set cli <path>`)",
|
|
108
110
|
name: basename((options.cli || env.MNEMOM_CODE_CLI || "claude").trim()),
|
|
109
111
|
};
|
|
110
|
-
printPlan({
|
|
112
|
+
printPlan({
|
|
113
|
+
scenario,
|
|
114
|
+
shape,
|
|
115
|
+
agent,
|
|
116
|
+
conversationId,
|
|
117
|
+
door,
|
|
118
|
+
cellNote,
|
|
119
|
+
envelope,
|
|
120
|
+
yolo,
|
|
121
|
+
cli: planCli,
|
|
122
|
+
});
|
|
111
123
|
return;
|
|
112
124
|
}
|
|
113
125
|
// Real launch: make sure we actually have a CLI to run. If we couldn't find it,
|
|
@@ -163,6 +175,7 @@ export async function codeCommand(scenario, options = {}) {
|
|
|
163
175
|
}
|
|
164
176
|
}
|
|
165
177
|
logLaunch({ shape, door, agent, conversationId, cellNote, envelope, cli });
|
|
178
|
+
say(goalAlignmentLine(envelope !== null));
|
|
166
179
|
if (shape === "terminal") {
|
|
167
180
|
launchTerminal({
|
|
168
181
|
cli,
|
package/dist/index.js
CHANGED
|
@@ -82,7 +82,7 @@ program
|
|
|
82
82
|
});
|
|
83
83
|
// ── code — first-class governed coding-agent launcher ────────────────────────
|
|
84
84
|
//
|
|
85
|
-
// `mnemom code
|
|
85
|
+
// `mnemom code [scenario]` launches your coding-agent CLI (Claude Code in v1) with
|
|
86
86
|
// its dev-time model traffic routed through the Mnemom gateway's /anthropic door
|
|
87
87
|
// for observability + governance, under a governed agent identity (the
|
|
88
88
|
// program-level `--agent`, default "code-agent") and an optional per-conversation
|
|
@@ -101,7 +101,7 @@ const collectRepeatable = (value, previous) => {
|
|
|
101
101
|
};
|
|
102
102
|
program
|
|
103
103
|
.command("code [scenario] [passthrough...]")
|
|
104
|
-
.description("Launch a governed coding agent through the Mnemom gateway (governed identity + optional sealed contract). " +
|
|
104
|
+
.description("Launch a governed coding agent through the Mnemom gateway (governed identity + optional sealed contract). Plain `mnemom code` asks for a session name and an optional goal. " +
|
|
105
105
|
"Sub-verbs: `mnemom code setup` provisions your governed agent; `mnemom code doctor` preflights prerequisites; `mnemom code config …` manages persistent settings (~/.mnemom/code.toml); `mnemom code invite <token>` redeems a Mnemom Code invitation.")
|
|
106
106
|
.option("--goal <statement>", "Contract goal statement (required if any contract flag is given)")
|
|
107
107
|
.option("--requirement <text>", "Contract requirement (repeatable)", collectRepeatable, [])
|
|
@@ -125,7 +125,7 @@ program
|
|
|
125
125
|
"max",
|
|
126
126
|
]))
|
|
127
127
|
.option("--trim-mcp", "Launch the CLI with no MCP servers (--strict-mcp-config + empty --mcp-config)")
|
|
128
|
-
.option("--invite <token>", "Redeem a Mnemom Code invitation (pinv_…): unlocks Mnemom Code for you + credits your starter µ; launches too when a
|
|
128
|
+
.option("--invite <token>", "Redeem a Mnemom Code invitation (pinv_…): unlocks Mnemom Code for you + credits your starter µ; launches too when a session name is given")
|
|
129
129
|
.option("--setup", "Provision + claim the governed agent before launch (non-interactive opt-in)")
|
|
130
130
|
.option("--no-setup", "Skip governed-agent provisioning entirely for this launch")
|
|
131
131
|
.option("--no-yolo", "Do NOT pass --dangerously-skip-permissions (yolo is on by default)")
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -394,6 +394,16 @@ export interface MuBalance {
|
|
|
394
394
|
enforcementPausedReason?: string | null;
|
|
395
395
|
}
|
|
396
396
|
export declare function getMuBalance(orgId?: string): Promise<MuBalance>;
|
|
397
|
+
/**
|
|
398
|
+
* Mint the one-time `cards:write:protection` capability for an agent — the
|
|
399
|
+
* "locked door" that a plain claim does NOT grant (alignment is a standing cap;
|
|
400
|
+
* protection is one-time, 15-min TTL, single-use). `POST
|
|
401
|
+
* /v1/agents/:id/protection-capability` (MNE-876) requires a HUMAN operator
|
|
402
|
+
* (rejects agent OAuth principals) with org co-manage of the agent, so the CLI's
|
|
403
|
+
* own login JWT can mint it — no browser grant needed. Consumed by the very next
|
|
404
|
+
* protection-card write.
|
|
405
|
+
*/
|
|
406
|
+
export declare function mintProtectionCapability(agentId: string): Promise<void>;
|
|
397
407
|
export interface TeamListItem {
|
|
398
408
|
team_id: string;
|
|
399
409
|
name: string;
|
package/dist/lib/api.js
CHANGED
|
@@ -379,6 +379,18 @@ export async function getMuBalance(orgId) {
|
|
|
379
379
|
const q = orgId ? `?org_id=${encodeURIComponent(orgId)}` : "";
|
|
380
380
|
return gFetch(`/v1/billing/mu${q}`, {}, { fallback: "Could not read MU balance" });
|
|
381
381
|
}
|
|
382
|
+
/**
|
|
383
|
+
* Mint the one-time `cards:write:protection` capability for an agent — the
|
|
384
|
+
* "locked door" that a plain claim does NOT grant (alignment is a standing cap;
|
|
385
|
+
* protection is one-time, 15-min TTL, single-use). `POST
|
|
386
|
+
* /v1/agents/:id/protection-capability` (MNE-876) requires a HUMAN operator
|
|
387
|
+
* (rejects agent OAuth principals) with org co-manage of the agent, so the CLI's
|
|
388
|
+
* own login JWT can mint it — no browser grant needed. Consumed by the very next
|
|
389
|
+
* protection-card write.
|
|
390
|
+
*/
|
|
391
|
+
export async function mintProtectionCapability(agentId) {
|
|
392
|
+
await gFetch(`/v1/agents/${encodeURIComponent(agentId)}/protection-capability`, { method: "POST" }, { fallback: "Could not mint the protection capability" });
|
|
393
|
+
}
|
|
382
394
|
/**
|
|
383
395
|
* GET /v1/orgs/:org_id/teams for every org the user is a member of,
|
|
384
396
|
* concatenated. The CLI consumer that just wants "every team I can see"
|