@mnemom/mnemom 0.17.25 → 0.17.26
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-config.js +9 -0
- package/dist/commands/agent-doctor.d.ts +3 -2
- package/dist/commands/agent-doctor.js +22 -7
- package/dist/commands/agent-goal.js +7 -2
- package/dist/commands/agent-sessions.js +2 -1
- package/dist/commands/agent-setup.d.ts +104 -4
- package/dist/commands/agent-setup.js +414 -18
- package/dist/commands/agent-slack.d.ts +4 -0
- package/dist/commands/agent-slack.js +67 -21
- package/dist/commands/agent.d.ts +29 -1
- package/dist/commands/agent.js +89 -12
- package/dist/commands/wrap.d.ts +2 -0
- package/dist/commands/wrap.js +13 -1
- package/dist/index.js +19 -5
- package/dist/lib/agent-identity-route.d.ts +21 -3
- package/dist/lib/agent-identity-route.js +42 -15
- package/dist/lib/agent-ledger.d.ts +5 -0
- package/dist/lib/agent.d.ts +62 -1
- package/dist/lib/agent.js +55 -0
- package/dist/lib/api.d.ts +33 -1
- package/dist/lib/api.js +10 -0
- package/dist/lib/experimental.js +14 -2
- package/dist/lib/goal-api.d.ts +3 -3
- package/dist/lib/goal-api.js +5 -2
- package/dist/lib/launcher-config.d.ts +18 -0
- package/dist/lib/launcher-config.js +47 -1
- package/dist/lib/oauth.d.ts +7 -0
- package/dist/lib/oauth.js +92 -17
- package/dist/lib/served-agent-cache.d.ts +8 -1
- package/dist/lib/served-agent-cache.js +11 -2
- package/dist/lib/slack-channel.d.ts +1 -0
- package/dist/lib/slack-channel.js +30 -12
- package/dist/lib/slack-route.d.ts +72 -9
- package/dist/lib/slack-route.js +113 -24
- package/dist/lib/slack-router.d.ts +37 -2
- package/dist/lib/slack-router.js +98 -13
- package/dist/lib/slack-state.d.ts +105 -4
- package/dist/lib/slack-state.js +230 -11
- package/dist/lib/subscription-login.d.ts +12 -3
- package/dist/lib/subscription-login.js +19 -7
- package/dist/mcp/handoff-server.mjs +31 -3
- package/dist/rc-proxy.mjs +14 -0
- package/package.json +1 -1
|
@@ -72,30 +72,42 @@ export function resolveAgentAuth(flag, env) {
|
|
|
72
72
|
return fromEnv ? coerceAgentAuth(fromEnv) : "api-key";
|
|
73
73
|
}
|
|
74
74
|
/**
|
|
75
|
-
* The Mnemom key
|
|
76
|
-
*
|
|
75
|
+
* The Mnemom key this machine already has — MNEMOM_AGENT_MNEMOM_KEY, else the stored key — or
|
|
76
|
+
* undefined. NEVER mints. An unpinned api-key launch sends it (`x-mnemom-api-key`) alongside its
|
|
77
|
+
* Anthropic key when there is one, so the gateway can serve the key owner's claimed agent of that
|
|
78
|
+
* name instead of a fresh one per rotated Anthropic key; with none it launches exactly as before.
|
|
77
79
|
*/
|
|
78
|
-
export
|
|
80
|
+
export function readMnemomKey(deps) {
|
|
79
81
|
const fromEnv = headerSafe(deps.env[MNEMOM_KEY_ENV] ?? "");
|
|
80
82
|
if (fromEnv)
|
|
81
83
|
return fromEnv;
|
|
82
84
|
const stored = headerSafe(deps.readStored() ?? "");
|
|
83
|
-
|
|
84
|
-
|
|
85
|
+
return stored || undefined;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* The Mnemom key a subscription launch (or a pinned launch, which the gateway honours only with
|
|
89
|
+
* a verified Mnemom key) sends: MNEMOM_AGENT_MNEMOM_KEY, else the stored key, else mint one
|
|
90
|
+
* (gateway scope only) and store it. The key is never printed. `purpose` names why in the
|
|
91
|
+
* one-line notes ("subscription login" by default).
|
|
92
|
+
*/
|
|
93
|
+
export async function resolveSubscriptionMnemomKey(deps, purpose = "subscription login") {
|
|
94
|
+
const existing = readMnemomKey(deps);
|
|
95
|
+
if (existing)
|
|
96
|
+
return existing;
|
|
85
97
|
let minted;
|
|
86
98
|
try {
|
|
87
99
|
minted = headerSafe(await deps.mint());
|
|
88
100
|
}
|
|
89
101
|
catch (err) {
|
|
90
102
|
const msg = err instanceof Error ? err.message : String(err);
|
|
91
|
-
throw new Error(`mnemom agent:
|
|
103
|
+
throw new Error(`mnemom agent: ${purpose} needs a Mnemom API key and minting one failed (${msg}).\n` +
|
|
92
104
|
` Create one with \`mnemom api-key create --name mnemom-agent --scopes gateway\` and set ${MNEMOM_KEY_ENV}.`, { cause: err });
|
|
93
105
|
}
|
|
94
106
|
if (!minted)
|
|
95
107
|
throw new Error("mnemom agent: the API returned an empty Mnemom key.");
|
|
96
108
|
try {
|
|
97
109
|
deps.store(minted);
|
|
98
|
-
deps.say(
|
|
110
|
+
deps.say(`mnemom agent: minted a gateway-only Mnemom API key for ${purpose} (saved to ~/.mnemom/launcher.json, 0600).`);
|
|
99
111
|
}
|
|
100
112
|
catch {
|
|
101
113
|
deps.say("mnemom agent: minted a gateway-only Mnemom API key for this launch but could not save it — the next launch mints another.");
|
|
@@ -85,11 +85,31 @@ function resolveKeyFromEnvName(name, env) {
|
|
|
85
85
|
return value.trim();
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
/** A full Mnemom agent id (mirrors AGENT_ID_RE in cli/src/lib/agent.ts). */
|
|
89
|
+
const AGENT_ID_RE = /^mnm-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/;
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The Mnemom key the launch's own requests carry, when it has one: the `x-mnemom-api-key:` line
|
|
93
|
+
* of the inherited `ANTHROPIC_CUSTOM_HEADERS` (terminal), else the dedicated
|
|
94
|
+
* `MNEMOM_HANDOFF_MNEMOM_KEY` the Remote Control launcher sets. "" when there is none. A pinned
|
|
95
|
+
* call needs it: the gateway honours `x-mnemom-agent-id` only with a verified Mnemom key.
|
|
96
|
+
* @param {string} keyEnvName
|
|
97
|
+
* @param {NodeJS.ProcessEnv} env
|
|
98
|
+
* @returns {string}
|
|
99
|
+
*/
|
|
100
|
+
function resolveMnemomKey(keyEnvName, env) {
|
|
101
|
+
if (keyEnvName === "ANTHROPIC_CUSTOM_HEADERS") {
|
|
102
|
+
const m = (env.ANTHROPIC_CUSTOM_HEADERS ?? "").match(/^x-mnemom-api-key:\s*(.+)$/im);
|
|
103
|
+
return m ? m[1].trim() : "";
|
|
104
|
+
}
|
|
105
|
+
return (env.MNEMOM_HANDOFF_MNEMOM_KEY ?? "").trim();
|
|
106
|
+
}
|
|
107
|
+
|
|
88
108
|
/**
|
|
89
109
|
* Read the tool's config from env. Throws (message never contains the key value) when a
|
|
90
110
|
* required var is missing, or when the named key-source var resolves to no usable key.
|
|
91
111
|
* @param {NodeJS.ProcessEnv} env
|
|
92
|
-
* @returns {{gatewayHost: string, anthropicKey: string, agent: string, conversationId: string, sessionConfigB64?: string}}
|
|
112
|
+
* @returns {{gatewayHost: string, anthropicKey: string, mnemomKey?: string, agent: string, agentId?: string, conversationId: string, sessionConfigB64?: string}}
|
|
93
113
|
*/
|
|
94
114
|
export function configFromEnv(env) {
|
|
95
115
|
const missing = REQUIRED_ENV.filter((k) => !(env[k] ?? "").trim());
|
|
@@ -104,10 +124,16 @@ export function configFromEnv(env) {
|
|
|
104
124
|
"process's own inherited environment has no usable value for it.",
|
|
105
125
|
);
|
|
106
126
|
}
|
|
127
|
+
const agentId = (env.MNEMOM_HANDOFF_AGENT_ID ?? "").trim().toLowerCase();
|
|
128
|
+
if (agentId && !AGENT_ID_RE.test(agentId)) {
|
|
129
|
+
throw new Error("mnemom-handoff: MNEMOM_HANDOFF_AGENT_ID is not a full mnm-<uuid> agent id.");
|
|
130
|
+
}
|
|
107
131
|
return {
|
|
108
132
|
gatewayHost: env.MNEMOM_HANDOFF_GATEWAY_HOST.trim(),
|
|
109
133
|
anthropicKey,
|
|
134
|
+
mnemomKey: resolveMnemomKey(keyEnvName, env) || undefined,
|
|
110
135
|
agent: env.MNEMOM_HANDOFF_AGENT.trim(),
|
|
136
|
+
agentId: agentId || undefined,
|
|
111
137
|
conversationId: env.MNEMOM_HANDOFF_CONVERSATION_ID.trim(),
|
|
112
138
|
sessionConfigB64: env.MNEMOM_HANDOFF_SESSION_CONFIG?.trim() || undefined,
|
|
113
139
|
};
|
|
@@ -115,7 +141,7 @@ export function configFromEnv(env) {
|
|
|
115
141
|
|
|
116
142
|
/**
|
|
117
143
|
* Build the fetch call. Exported so a test can assert the wire shape without mocking fetch.
|
|
118
|
-
* @param {{gatewayHost: string, anthropicKey: string, agent: string, conversationId: string, sessionConfigB64?: string}} cfg
|
|
144
|
+
* @param {{gatewayHost: string, anthropicKey: string, mnemomKey?: string, agent: string, agentId?: string, conversationId: string, sessionConfigB64?: string}} cfg
|
|
119
145
|
* @param {string} note
|
|
120
146
|
*/
|
|
121
147
|
export function buildHandoffRequest(cfg, note) {
|
|
@@ -124,6 +150,8 @@ export function buildHandoffRequest(cfg, note) {
|
|
|
124
150
|
"x-api-key": cfg.anthropicKey,
|
|
125
151
|
"x-mnemom-agent": cfg.agent,
|
|
126
152
|
};
|
|
153
|
+
if (cfg.mnemomKey) headers["x-mnemom-api-key"] = cfg.mnemomKey;
|
|
154
|
+
if (cfg.agentId) headers["x-mnemom-agent-id"] = cfg.agentId;
|
|
127
155
|
if (cfg.sessionConfigB64) headers["x-mnemom-session-config"] = cfg.sessionConfigB64;
|
|
128
156
|
return {
|
|
129
157
|
url: `${cfg.gatewayHost.replace(/\/+$/, "")}${HANDOFF_PATH}`,
|
|
@@ -150,7 +178,7 @@ function extractGatewayError(body) {
|
|
|
150
178
|
* Call the route and render the result. NEVER throws: a network failure, a non-2xx status, or
|
|
151
179
|
* an unparseable body all come back as `{ok:false, message}` for the caller to surface as an
|
|
152
180
|
* MCP tool error — the tool must never crash the server or the session over a bad response.
|
|
153
|
-
* @param {{gatewayHost: string, anthropicKey: string, agent: string, conversationId: string, sessionConfigB64?: string}} cfg
|
|
181
|
+
* @param {{gatewayHost: string, anthropicKey: string, mnemomKey?: string, agent: string, agentId?: string, conversationId: string, sessionConfigB64?: string}} cfg
|
|
154
182
|
* @param {string} note
|
|
155
183
|
* @param {typeof fetch} fetchImpl
|
|
156
184
|
*/
|
package/dist/rc-proxy.mjs
CHANGED
|
@@ -62,6 +62,9 @@
|
|
|
62
62
|
// CONFIG (env, none secret)
|
|
63
63
|
// MNEMOM_AGENT_RC_DOOR gateway door URL (required), e.g. https://gateway.mnemom.ai/anthropic
|
|
64
64
|
// MNEMOM_AGENT_RC_AGENT x-mnemom-agent value (required)
|
|
65
|
+
// MNEMOM_AGENT_RC_AGENT_ID x-mnemom-agent-id value (optional; a full mnm-<uuid> pin — the
|
|
66
|
+
// gateway then serves exactly that agent or refuses; needs the
|
|
67
|
+
// Mnemom key on stdin line 2)
|
|
65
68
|
// MNEMOM_AGENT_RC_CONVERSATION_ID x-mnemom-conversation-id value (required)
|
|
66
69
|
// MNEMOM_AGENT_RC_CONTRACT_B64 base64 contract for x-mnemom-contract (optional)
|
|
67
70
|
// MNEMOM_AGENT_RC_GOAL_MODE x-mnemom-goal-mode value (optional; `--implicit` — no contract,
|
|
@@ -111,6 +114,12 @@ try {
|
|
|
111
114
|
}
|
|
112
115
|
if (GATEWAY.protocol !== "https:") die("MNEMOM_AGENT_RC_DOOR must be https");
|
|
113
116
|
const AGENT = env.MNEMOM_AGENT_RC_AGENT || die("MNEMOM_AGENT_RC_AGENT is required");
|
|
117
|
+
const AGENT_ID = (env.MNEMOM_AGENT_RC_AGENT_ID || "").trim().toLowerCase();
|
|
118
|
+
if (
|
|
119
|
+
AGENT_ID &&
|
|
120
|
+
!/^mnm-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(AGENT_ID)
|
|
121
|
+
)
|
|
122
|
+
die("MNEMOM_AGENT_RC_AGENT_ID must be a full mnm-<uuid> agent id");
|
|
114
123
|
const CONV =
|
|
115
124
|
env.MNEMOM_AGENT_RC_CONVERSATION_ID || die("MNEMOM_AGENT_RC_CONVERSATION_ID is required");
|
|
116
125
|
const CONTRACT_B64 = env.MNEMOM_AGENT_RC_CONTRACT_B64 || "";
|
|
@@ -168,6 +177,8 @@ try {
|
|
|
168
177
|
} catch {
|
|
169
178
|
die("expected three lines of secrets on stdin (anthropic, mnemom, openai)");
|
|
170
179
|
}
|
|
180
|
+
if (AGENT_ID && !secrets.mnemom)
|
|
181
|
+
die("a pinned agent (MNEMOM_AGENT_RC_AGENT_ID) needs the Mnemom key (stdin line 2)");
|
|
171
182
|
if (SUBSCRIPTION) {
|
|
172
183
|
if (!secrets.mnemom) die("subscription login needs the Mnemom key (stdin line 2)");
|
|
173
184
|
} else if (!secrets.anthropic) die("the Anthropic key (stdin line 1) is empty");
|
|
@@ -519,6 +530,9 @@ function handle(req, res, viaPlain) {
|
|
|
519
530
|
headers["x-api-key"] = secrets.anthropic;
|
|
520
531
|
}
|
|
521
532
|
headers["x-mnemom-agent"] = AGENT;
|
|
533
|
+
// The pin is this proxy's to state: a client-supplied one is dropped, like x-mnemom-turn.
|
|
534
|
+
delete headers["x-mnemom-agent-id"];
|
|
535
|
+
if (AGENT_ID) headers["x-mnemom-agent-id"] = AGENT_ID;
|
|
522
536
|
headers["x-mnemom-conversation-id"] = CONV;
|
|
523
537
|
if (secrets.mnemom) headers["x-mnemom-api-key"] = secrets.mnemom;
|
|
524
538
|
if (PROVIDER) headers["x-mnemom-provider"] = PROVIDER;
|